mirror of
https://github.com/golang/go
synced 2024-11-24 21:00:09 -07:00
go/ast: consider anonymous fields and set Incomplete bit when filtering ASTs
Also: - fieldListExports: don't require internal pointer to StructType/InterfaceType node - filterFieldLists: make structure match fieldListExports R=rsc CC=golang-dev https://golang.org/cl/4527050
This commit is contained in:
parent
26bbb2b2f7
commit
d376935a18
@ -21,24 +21,26 @@ func identListExports(list []*Ident) []*Ident {
|
||||
}
|
||||
|
||||
|
||||
// isExportedType assumes that typ is a correct type.
|
||||
func isExportedType(typ Expr) bool {
|
||||
switch t := typ.(type) {
|
||||
// fieldName assumes that x is the type of an anonymous field and
|
||||
// returns the corresponding field name. If x is not an acceptable
|
||||
// anonymous field, the result is nil.
|
||||
//
|
||||
func fieldName(x Expr) *Ident {
|
||||
switch t := x.(type) {
|
||||
case *Ident:
|
||||
return t.IsExported()
|
||||
case *ParenExpr:
|
||||
return isExportedType(t.X)
|
||||
return t
|
||||
case *SelectorExpr:
|
||||
// assume t.X is a typename
|
||||
return t.Sel.IsExported()
|
||||
if _, ok := t.X.(*Ident); ok {
|
||||
return t.Sel
|
||||
}
|
||||
case *StarExpr:
|
||||
return isExportedType(t.X)
|
||||
return fieldName(t.X)
|
||||
}
|
||||
return false
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
func fieldListExports(fields *FieldList, incomplete *bool) {
|
||||
func fieldListExports(fields *FieldList) (removedFields bool) {
|
||||
if fields == nil {
|
||||
return
|
||||
}
|
||||
@ -53,12 +55,13 @@ func fieldListExports(fields *FieldList, incomplete *bool) {
|
||||
// fields, so this is not absolutely correct.
|
||||
// However, this cannot be done w/o complete
|
||||
// type information.)
|
||||
exported = isExportedType(f.Type)
|
||||
name := fieldName(f.Type)
|
||||
exported = name != nil && name.IsExported()
|
||||
} else {
|
||||
n := len(f.Names)
|
||||
f.Names = identListExports(f.Names)
|
||||
if len(f.Names) < n {
|
||||
*incomplete = true
|
||||
removedFields = true
|
||||
}
|
||||
exported = len(f.Names) > 0
|
||||
}
|
||||
@ -69,9 +72,10 @@ func fieldListExports(fields *FieldList, incomplete *bool) {
|
||||
}
|
||||
}
|
||||
if j < len(list) {
|
||||
*incomplete = true
|
||||
removedFields = true
|
||||
}
|
||||
fields.List = list[0:j]
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
@ -90,12 +94,16 @@ func typeExports(typ Expr) {
|
||||
case *ArrayType:
|
||||
typeExports(t.Elt)
|
||||
case *StructType:
|
||||
fieldListExports(t.Fields, &t.Incomplete)
|
||||
if fieldListExports(t.Fields) {
|
||||
t.Incomplete = true
|
||||
}
|
||||
case *FuncType:
|
||||
paramListExports(t.Params)
|
||||
paramListExports(t.Results)
|
||||
case *InterfaceType:
|
||||
fieldListExports(t.Methods, &t.Incomplete)
|
||||
if fieldListExports(t.Methods) {
|
||||
t.Incomplete = true
|
||||
}
|
||||
case *MapType:
|
||||
typeExports(t.Key)
|
||||
typeExports(t.Value)
|
||||
@ -206,25 +214,36 @@ func filterIdentList(list []*Ident, f Filter) []*Ident {
|
||||
}
|
||||
|
||||
|
||||
func filterFieldList(list []*Field, f Filter) []*Field {
|
||||
j := 0
|
||||
for _, field := range list {
|
||||
field.Names = filterIdentList(field.Names, f)
|
||||
if len(field.Names) > 0 {
|
||||
list[j] = field
|
||||
j++
|
||||
}
|
||||
}
|
||||
return list[0:j]
|
||||
}
|
||||
|
||||
|
||||
func filterFields(fields *FieldList, f Filter) bool {
|
||||
func filterFieldList(fields *FieldList, filter Filter) (removedFields bool) {
|
||||
if fields == nil {
|
||||
return false
|
||||
}
|
||||
fields.List = filterFieldList(fields.List, f)
|
||||
return len(fields.List) > 0
|
||||
list := fields.List
|
||||
j := 0
|
||||
for _, f := range list {
|
||||
keepField := false
|
||||
if len(f.Names) == 0 {
|
||||
// anonymous field
|
||||
name := fieldName(f.Type)
|
||||
keepField = name != nil && filter(name.Name)
|
||||
} else {
|
||||
n := len(f.Names)
|
||||
f.Names = filterIdentList(f.Names, filter)
|
||||
if len(f.Names) < n {
|
||||
removedFields = true
|
||||
}
|
||||
keepField = len(f.Names) > 0
|
||||
}
|
||||
if keepField {
|
||||
list[j] = f
|
||||
j++
|
||||
}
|
||||
}
|
||||
if j < len(list) {
|
||||
removedFields = true
|
||||
}
|
||||
fields.List = list[0:j]
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
@ -239,9 +258,15 @@ func filterSpec(spec Spec, f Filter) bool {
|
||||
}
|
||||
switch t := s.Type.(type) {
|
||||
case *StructType:
|
||||
return filterFields(t.Fields, f)
|
||||
if filterFieldList(t.Fields, f) {
|
||||
t.Incomplete = true
|
||||
}
|
||||
return len(t.Fields.List) > 0
|
||||
case *InterfaceType:
|
||||
return filterFields(t.Methods, f)
|
||||
if filterFieldList(t.Methods, f) {
|
||||
t.Incomplete = true
|
||||
}
|
||||
return len(t.Methods.List) > 0
|
||||
}
|
||||
}
|
||||
return false
|
||||
|
Loading…
Reference in New Issue
Block a user