OSDN Git Service

libgo: Update to weekly.2011-12-22.
[pf3gnuchains/gcc-fork.git] / libgo / go / go / doc / exports.go
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.
4
5 // This file implements export filtering of an AST.
6
7 package doc
8
9 import "go/ast"
10
11 func filterIdentList(list []*ast.Ident) []*ast.Ident {
12         j := 0
13         for _, x := range list {
14                 if ast.IsExported(x.Name) {
15                         list[j] = x
16                         j++
17                 }
18         }
19         return list[0:j]
20 }
21
22 func baseName(x ast.Expr) *ast.Ident {
23         switch t := x.(type) {
24         case *ast.Ident:
25                 return t
26         case *ast.SelectorExpr:
27                 if _, ok := t.X.(*ast.Ident); ok {
28                         return t.Sel
29                 }
30         case *ast.StarExpr:
31                 return baseName(t.X)
32         }
33         return nil
34 }
35
36 func (doc *docReader) filterFieldList(fields *ast.FieldList) (removedFields bool) {
37         if fields == nil {
38                 return false
39         }
40         list := fields.List
41         j := 0
42         for _, f := range list {
43                 keepField := false
44                 if len(f.Names) == 0 {
45                         // anonymous field
46                         name := baseName(f.Type)
47                         keepField = name != nil && name.IsExported()
48                 } else {
49                         n := len(f.Names)
50                         f.Names = filterIdentList(f.Names)
51                         if len(f.Names) < n {
52                                 removedFields = true
53                         }
54                         keepField = len(f.Names) > 0
55                 }
56                 if keepField {
57                         doc.filterType(f.Type)
58                         list[j] = f
59                         j++
60                 }
61         }
62         if j < len(list) {
63                 removedFields = true
64         }
65         fields.List = list[0:j]
66         return
67 }
68
69 func (doc *docReader) filterParamList(fields *ast.FieldList) bool {
70         if fields == nil {
71                 return false
72         }
73         var b bool
74         for _, f := range fields.List {
75                 if doc.filterType(f.Type) {
76                         b = true
77                 }
78         }
79         return b
80 }
81
82 func (doc *docReader) filterType(typ ast.Expr) bool {
83         switch t := typ.(type) {
84         case *ast.Ident:
85                 return ast.IsExported(t.Name)
86         case *ast.ParenExpr:
87                 return doc.filterType(t.X)
88         case *ast.ArrayType:
89                 return doc.filterType(t.Elt)
90         case *ast.StructType:
91                 if doc.filterFieldList(t.Fields) {
92                         t.Incomplete = true
93                 }
94                 return len(t.Fields.List) > 0
95         case *ast.FuncType:
96                 b1 := doc.filterParamList(t.Params)
97                 b2 := doc.filterParamList(t.Results)
98                 return b1 || b2
99         case *ast.InterfaceType:
100                 if doc.filterFieldList(t.Methods) {
101                         t.Incomplete = true
102                 }
103                 return len(t.Methods.List) > 0
104         case *ast.MapType:
105                 b1 := doc.filterType(t.Key)
106                 b2 := doc.filterType(t.Value)
107                 return b1 || b2
108         case *ast.ChanType:
109                 return doc.filterType(t.Value)
110         }
111         return false
112 }
113
114 func (doc *docReader) filterSpec(spec ast.Spec) bool {
115         switch s := spec.(type) {
116         case *ast.ValueSpec:
117                 s.Names = filterIdentList(s.Names)
118                 if len(s.Names) > 0 {
119                         doc.filterType(s.Type)
120                         return true
121                 }
122         case *ast.TypeSpec:
123                 if ast.IsExported(s.Name.Name) {
124                         doc.filterType(s.Type)
125                         return true
126                 }
127         }
128         return false
129 }
130
131 func (doc *docReader) filterSpecList(list []ast.Spec) []ast.Spec {
132         j := 0
133         for _, s := range list {
134                 if doc.filterSpec(s) {
135                         list[j] = s
136                         j++
137                 }
138         }
139         return list[0:j]
140 }
141
142 func (doc *docReader) filterDecl(decl ast.Decl) bool {
143         switch d := decl.(type) {
144         case *ast.GenDecl:
145                 d.Specs = doc.filterSpecList(d.Specs)
146                 return len(d.Specs) > 0
147         case *ast.FuncDecl:
148                 return ast.IsExported(d.Name.Name)
149         }
150         return false
151 }
152
153 // fileExports trims the AST for a Go file in place such that
154 // only exported nodes remain. fileExports returns true if
155 // there are exported declarations; otherwise it returns false.
156 //
157 func (doc *docReader) fileExports(src *ast.File) bool {
158         j := 0
159         for _, d := range src.Decls {
160                 if doc.filterDecl(d) {
161                         src.Decls[j] = d
162                         j++
163                 }
164         }
165         src.Decls = src.Decls[0:j]
166         return j > 0
167 }