mirror of
https://github.com/golang/go
synced 2024-11-19 14:54:43 -07:00
go/ast, go/doc, godoc: consider struct fields and interface methods when filtering ASTs
So far, only top-level names where considered when trimming ASTs using a filter function. For instance, "godoc reflect Implements" didn't show the "Implements" method of the type Interface because the local method name was not considered (on the other hand, "top- level" declared methods associated with types were considered). With this CL, AST filter functions look also at struct fields and interface methods. R=rsc, r CC=golang-dev https://golang.org/cl/4518050
This commit is contained in:
parent
69a91663d2
commit
0389051aac
@ -206,13 +206,43 @@ 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 {
|
||||
if fields == nil {
|
||||
return false
|
||||
}
|
||||
fields.List = filterFieldList(fields.List, f)
|
||||
return len(fields.List) > 0
|
||||
}
|
||||
|
||||
|
||||
func filterSpec(spec Spec, f Filter) bool {
|
||||
switch s := spec.(type) {
|
||||
case *ValueSpec:
|
||||
s.Names = filterIdentList(s.Names, f)
|
||||
return len(s.Names) > 0
|
||||
case *TypeSpec:
|
||||
return f(s.Name.Name)
|
||||
if f(s.Name.Name) {
|
||||
return true
|
||||
}
|
||||
switch t := s.Type.(type) {
|
||||
case *StructType:
|
||||
return filterFields(t.Fields, f)
|
||||
case *InterfaceType:
|
||||
return filterFields(t.Methods, f)
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
@ -230,7 +260,14 @@ func filterSpecList(list []Spec, f Filter) []Spec {
|
||||
}
|
||||
|
||||
|
||||
func filterDecl(decl Decl, f Filter) bool {
|
||||
// FilterDecl trims the AST for a Go declaration in place by removing
|
||||
// all names (including struct field and interface method names, but
|
||||
// not from parameter lists) that don't pass through the filter f.
|
||||
//
|
||||
// FilterDecl returns true if there are any declared names left after
|
||||
// filtering; it returns false otherwise.
|
||||
//
|
||||
func FilterDecl(decl Decl, f Filter) bool {
|
||||
switch d := decl.(type) {
|
||||
case *GenDecl:
|
||||
d.Specs = filterSpecList(d.Specs, f)
|
||||
@ -243,10 +280,10 @@ func filterDecl(decl Decl, f Filter) bool {
|
||||
|
||||
|
||||
// FilterFile trims the AST for a Go file in place by removing all
|
||||
// names from top-level declarations (but not from parameter lists
|
||||
// or inside types) that don't pass through the filter f. If the
|
||||
// declaration is empty afterwards, the declaration is removed from
|
||||
// the AST.
|
||||
// names from top-level declarations (including struct field and
|
||||
// interface method names, but not from parameter lists) that don't
|
||||
// pass through the filter f. If the declaration is empty afterwards,
|
||||
// the declaration is removed from the AST.
|
||||
// The File.comments list is not changed.
|
||||
//
|
||||
// FilterFile returns true if there are any top-level declarations
|
||||
@ -255,7 +292,7 @@ func filterDecl(decl Decl, f Filter) bool {
|
||||
func FilterFile(src *File, f Filter) bool {
|
||||
j := 0
|
||||
for _, d := range src.Decls {
|
||||
if filterDecl(d, f) {
|
||||
if FilterDecl(d, f) {
|
||||
src.Decls[j] = d
|
||||
j++
|
||||
}
|
||||
@ -266,10 +303,10 @@ func FilterFile(src *File, f Filter) bool {
|
||||
|
||||
|
||||
// FilterPackage trims the AST for a Go package in place by removing all
|
||||
// names from top-level declarations (but not from parameter lists
|
||||
// or inside types) that don't pass through the filter f. If the
|
||||
// declaration is empty afterwards, the declaration is removed from
|
||||
// the AST.
|
||||
// names from top-level declarations (including struct field and
|
||||
// interface method names, but not from parameter lists) that don't
|
||||
// pass through the filter f. If the declaration is empty afterwards,
|
||||
// the declaration is removed from the AST.
|
||||
// The pkg.Files list is not changed, so that file names and top-level
|
||||
// package comments don't get lost.
|
||||
//
|
||||
|
@ -569,32 +569,10 @@ func (doc *docReader) newDoc(importpath string, filenames []string) *PackageDoc
|
||||
// ----------------------------------------------------------------------------
|
||||
// Filtering by name
|
||||
|
||||
type Filter func(string) bool
|
||||
|
||||
|
||||
func matchDecl(d *ast.GenDecl, f Filter) bool {
|
||||
for _, d := range d.Specs {
|
||||
switch v := d.(type) {
|
||||
case *ast.ValueSpec:
|
||||
for _, name := range v.Names {
|
||||
if f(name.Name) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
case *ast.TypeSpec:
|
||||
if f(v.Name.Name) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
|
||||
func filterValueDocs(a []*ValueDoc, f Filter) []*ValueDoc {
|
||||
func filterValueDocs(a []*ValueDoc, f ast.Filter) []*ValueDoc {
|
||||
w := 0
|
||||
for _, vd := range a {
|
||||
if matchDecl(vd.Decl, f) {
|
||||
if ast.FilterDecl(vd.Decl, f) {
|
||||
a[w] = vd
|
||||
w++
|
||||
}
|
||||
@ -603,7 +581,7 @@ func filterValueDocs(a []*ValueDoc, f Filter) []*ValueDoc {
|
||||
}
|
||||
|
||||
|
||||
func filterFuncDocs(a []*FuncDoc, f Filter) []*FuncDoc {
|
||||
func filterFuncDocs(a []*FuncDoc, f ast.Filter) []*FuncDoc {
|
||||
w := 0
|
||||
for _, fd := range a {
|
||||
if f(fd.Name) {
|
||||
@ -615,11 +593,11 @@ func filterFuncDocs(a []*FuncDoc, f Filter) []*FuncDoc {
|
||||
}
|
||||
|
||||
|
||||
func filterTypeDocs(a []*TypeDoc, f Filter) []*TypeDoc {
|
||||
func filterTypeDocs(a []*TypeDoc, f ast.Filter) []*TypeDoc {
|
||||
w := 0
|
||||
for _, td := range a {
|
||||
n := 0 // number of matches
|
||||
if matchDecl(td.Decl, f) {
|
||||
if ast.FilterDecl(td.Decl, f) {
|
||||
n = 1
|
||||
} else {
|
||||
// type name doesn't match, but we may have matching consts, vars, factories or methods
|
||||
@ -641,7 +619,7 @@ func filterTypeDocs(a []*TypeDoc, f Filter) []*TypeDoc {
|
||||
// Filter eliminates documentation for names that don't pass through the filter f.
|
||||
// TODO: Recognize "Type.Method" as a name.
|
||||
//
|
||||
func (p *PackageDoc) Filter(f Filter) {
|
||||
func (p *PackageDoc) Filter(f ast.Filter) {
|
||||
p.Consts = filterValueDocs(p.Consts, f)
|
||||
p.Vars = filterValueDocs(p.Vars, f)
|
||||
p.Types = filterTypeDocs(p.Types, f)
|
||||
|
Loading…
Reference in New Issue
Block a user