1 // Copyright 2011 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
5 // This file implements export filtering of an AST.
11 func filterIdentList(list []*ast.Ident) []*ast.Ident {
13 for _, x := range list {
14 if ast.IsExported(x.Name) {
22 func baseName(x ast.Expr) *ast.Ident {
23 switch t := x.(type) {
26 case *ast.SelectorExpr:
27 if _, ok := t.X.(*ast.Ident); ok {
36 func (doc *docReader) filterFieldList(tinfo *typeInfo, fields *ast.FieldList) (removedFields bool) {
42 for _, f := range list {
44 if len(f.Names) == 0 {
46 name := baseName(f.Type)
47 if name != nil && name.IsExported() {
48 // we keep the field - in this case doc.addDecl
49 // will take care of adding the embedded type
51 } else if tinfo != nil {
52 // we don't keep the field - add it as an embedded
53 // type so we won't loose its methods, if any
54 if embedded := doc.lookupTypeInfo(name.Name); embedded != nil {
55 _, ptr := f.Type.(*ast.StarExpr)
56 tinfo.addEmbeddedType(embedded, ptr)
61 f.Names = filterIdentList(f.Names)
65 keepField = len(f.Names) > 0
68 doc.filterType(nil, f.Type)
76 fields.List = list[0:j]
80 func (doc *docReader) filterParamList(fields *ast.FieldList) bool {
85 for _, f := range fields.List {
86 if doc.filterType(nil, f.Type) {
93 func (doc *docReader) filterType(tinfo *typeInfo, typ ast.Expr) bool {
94 switch t := typ.(type) {
96 return ast.IsExported(t.Name)
98 return doc.filterType(nil, t.X)
100 return doc.filterType(nil, t.Elt)
101 case *ast.StructType:
102 if doc.filterFieldList(tinfo, t.Fields) {
105 return len(t.Fields.List) > 0
107 b1 := doc.filterParamList(t.Params)
108 b2 := doc.filterParamList(t.Results)
110 case *ast.InterfaceType:
111 if doc.filterFieldList(tinfo, t.Methods) {
114 return len(t.Methods.List) > 0
116 b1 := doc.filterType(nil, t.Key)
117 b2 := doc.filterType(nil, t.Value)
120 return doc.filterType(nil, t.Value)
125 func (doc *docReader) filterSpec(spec ast.Spec) bool {
126 switch s := spec.(type) {
128 s.Names = filterIdentList(s.Names)
129 if len(s.Names) > 0 {
130 doc.filterType(nil, s.Type)
134 if ast.IsExported(s.Name.Name) {
135 doc.filterType(doc.lookupTypeInfo(s.Name.Name), s.Type)
142 func (doc *docReader) filterSpecList(list []ast.Spec) []ast.Spec {
144 for _, s := range list {
145 if doc.filterSpec(s) {
153 func (doc *docReader) filterDecl(decl ast.Decl) bool {
154 switch d := decl.(type) {
156 d.Specs = doc.filterSpecList(d.Specs)
157 return len(d.Specs) > 0
159 return ast.IsExported(d.Name.Name)
164 // fileExports trims the AST for a Go file in place such that
165 // only exported nodes remain. fileExports returns true if
166 // there are exported declarations; otherwise it returns false.
168 func (doc *docReader) fileExports(src *ast.File) bool {
170 for _, d := range src.Decls {
171 if doc.filterDecl(d) {
176 src.Decls = src.Decls[0:j]