Source file
src/go/ast/walk.go
1
2
3
4
5 package ast
6
7 import "fmt"
8
9
10
11
12 type Visitor interface {
13 Visit(node Node) (w Visitor)
14 }
15
16
17
18 func walkIdentList(v Visitor, list []*Ident) {
19 for _, x := range list {
20 Walk(v, x)
21 }
22 }
23
24 func walkExprList(v Visitor, list []Expr) {
25 for _, x := range list {
26 Walk(v, x)
27 }
28 }
29
30 func walkStmtList(v Visitor, list []Stmt) {
31 for _, x := range list {
32 Walk(v, x)
33 }
34 }
35
36 func walkDeclList(v Visitor, list []Decl) {
37 for _, x := range list {
38 Walk(v, x)
39 }
40 }
41
42
43
44
45
46
47
48
49
50
51 func Walk(v Visitor, node Node) {
52 if v = v.Visit(node); v == nil {
53 return
54 }
55
56
57
58
59 switch n := node.(type) {
60
61 case *Comment:
62
63
64 case *CommentGroup:
65 for _, c := range n.List {
66 Walk(v, c)
67 }
68
69 case *Field:
70 if n.Doc != nil {
71 Walk(v, n.Doc)
72 }
73 walkIdentList(v, n.Names)
74 if n.Type != nil {
75 Walk(v, n.Type)
76 }
77 if n.Tag != nil {
78 Walk(v, n.Tag)
79 }
80 if n.Comment != nil {
81 Walk(v, n.Comment)
82 }
83
84 case *FieldList:
85 for _, f := range n.List {
86 Walk(v, f)
87 }
88
89
90 case *BadExpr, *Ident, *BasicLit:
91
92
93 case *Ellipsis:
94 if n.Elt != nil {
95 Walk(v, n.Elt)
96 }
97
98 case *FuncLit:
99 Walk(v, n.Type)
100 Walk(v, n.Body)
101
102 case *CompositeLit:
103 if n.Type != nil {
104 Walk(v, n.Type)
105 }
106 walkExprList(v, n.Elts)
107
108 case *ParenExpr:
109 Walk(v, n.X)
110
111 case *SelectorExpr:
112 Walk(v, n.X)
113 Walk(v, n.Sel)
114
115 case *IndexExpr:
116 Walk(v, n.X)
117 Walk(v, n.Index)
118
119 case *IndexListExpr:
120 Walk(v, n.X)
121 for _, index := range n.Indices {
122 Walk(v, index)
123 }
124
125 case *SliceExpr:
126 Walk(v, n.X)
127 if n.Low != nil {
128 Walk(v, n.Low)
129 }
130 if n.High != nil {
131 Walk(v, n.High)
132 }
133 if n.Max != nil {
134 Walk(v, n.Max)
135 }
136
137 case *TypeAssertExpr:
138 Walk(v, n.X)
139 if n.Type != nil {
140 Walk(v, n.Type)
141 }
142
143 case *CallExpr:
144 Walk(v, n.Fun)
145 walkExprList(v, n.Args)
146
147 case *StarExpr:
148 Walk(v, n.X)
149
150 case *UnaryExpr:
151 Walk(v, n.X)
152
153 case *BinaryExpr:
154 Walk(v, n.X)
155 Walk(v, n.Y)
156
157 case *KeyValueExpr:
158 Walk(v, n.Key)
159 Walk(v, n.Value)
160
161
162 case *ArrayType:
163 if n.Len != nil {
164 Walk(v, n.Len)
165 }
166 Walk(v, n.Elt)
167
168 case *StructType:
169 Walk(v, n.Fields)
170
171 case *FuncType:
172 if n.TypeParams != nil {
173 Walk(v, n.TypeParams)
174 }
175 if n.Params != nil {
176 Walk(v, n.Params)
177 }
178 if n.Results != nil {
179 Walk(v, n.Results)
180 }
181
182 case *InterfaceType:
183 Walk(v, n.Methods)
184
185 case *MapType:
186 Walk(v, n.Key)
187 Walk(v, n.Value)
188
189 case *ChanType:
190 Walk(v, n.Value)
191
192
193 case *BadStmt:
194
195
196 case *DeclStmt:
197 Walk(v, n.Decl)
198
199 case *EmptyStmt:
200
201
202 case *LabeledStmt:
203 Walk(v, n.Label)
204 Walk(v, n.Stmt)
205
206 case *ExprStmt:
207 Walk(v, n.X)
208
209 case *SendStmt:
210 Walk(v, n.Chan)
211 Walk(v, n.Value)
212
213 case *IncDecStmt:
214 Walk(v, n.X)
215
216 case *AssignStmt:
217 walkExprList(v, n.Lhs)
218 walkExprList(v, n.Rhs)
219
220 case *GoStmt:
221 Walk(v, n.Call)
222
223 case *DeferStmt:
224 Walk(v, n.Call)
225
226 case *ReturnStmt:
227 walkExprList(v, n.Results)
228
229 case *BranchStmt:
230 if n.Label != nil {
231 Walk(v, n.Label)
232 }
233
234 case *BlockStmt:
235 walkStmtList(v, n.List)
236
237 case *IfStmt:
238 if n.Init != nil {
239 Walk(v, n.Init)
240 }
241 Walk(v, n.Cond)
242 Walk(v, n.Body)
243 if n.Else != nil {
244 Walk(v, n.Else)
245 }
246
247 case *CaseClause:
248 walkExprList(v, n.List)
249 walkStmtList(v, n.Body)
250
251 case *SwitchStmt:
252 if n.Init != nil {
253 Walk(v, n.Init)
254 }
255 if n.Tag != nil {
256 Walk(v, n.Tag)
257 }
258 Walk(v, n.Body)
259
260 case *TypeSwitchStmt:
261 if n.Init != nil {
262 Walk(v, n.Init)
263 }
264 Walk(v, n.Assign)
265 Walk(v, n.Body)
266
267 case *CommClause:
268 if n.Comm != nil {
269 Walk(v, n.Comm)
270 }
271 walkStmtList(v, n.Body)
272
273 case *SelectStmt:
274 Walk(v, n.Body)
275
276 case *ForStmt:
277 if n.Init != nil {
278 Walk(v, n.Init)
279 }
280 if n.Cond != nil {
281 Walk(v, n.Cond)
282 }
283 if n.Post != nil {
284 Walk(v, n.Post)
285 }
286 Walk(v, n.Body)
287
288 case *RangeStmt:
289 if n.Key != nil {
290 Walk(v, n.Key)
291 }
292 if n.Value != nil {
293 Walk(v, n.Value)
294 }
295 Walk(v, n.X)
296 Walk(v, n.Body)
297
298
299 case *ImportSpec:
300 if n.Doc != nil {
301 Walk(v, n.Doc)
302 }
303 if n.Name != nil {
304 Walk(v, n.Name)
305 }
306 Walk(v, n.Path)
307 if n.Comment != nil {
308 Walk(v, n.Comment)
309 }
310
311 case *ValueSpec:
312 if n.Doc != nil {
313 Walk(v, n.Doc)
314 }
315 walkIdentList(v, n.Names)
316 if n.Type != nil {
317 Walk(v, n.Type)
318 }
319 walkExprList(v, n.Values)
320 if n.Comment != nil {
321 Walk(v, n.Comment)
322 }
323
324 case *TypeSpec:
325 if n.Doc != nil {
326 Walk(v, n.Doc)
327 }
328 Walk(v, n.Name)
329 if n.TypeParams != nil {
330 Walk(v, n.TypeParams)
331 }
332 Walk(v, n.Type)
333 if n.Comment != nil {
334 Walk(v, n.Comment)
335 }
336
337 case *BadDecl:
338
339
340 case *GenDecl:
341 if n.Doc != nil {
342 Walk(v, n.Doc)
343 }
344 for _, s := range n.Specs {
345 Walk(v, s)
346 }
347
348 case *FuncDecl:
349 if n.Doc != nil {
350 Walk(v, n.Doc)
351 }
352 if n.Recv != nil {
353 Walk(v, n.Recv)
354 }
355 Walk(v, n.Name)
356 Walk(v, n.Type)
357 if n.Body != nil {
358 Walk(v, n.Body)
359 }
360
361
362 case *File:
363 if n.Doc != nil {
364 Walk(v, n.Doc)
365 }
366 Walk(v, n.Name)
367 walkDeclList(v, n.Decls)
368
369
370
371
372 case *Package:
373 for _, f := range n.Files {
374 Walk(v, f)
375 }
376
377 default:
378 panic(fmt.Sprintf("ast.Walk: unexpected node type %T", n))
379 }
380
381 v.Visit(nil)
382 }
383
384 type inspector func(Node) bool
385
386 func (f inspector) Visit(node Node) Visitor {
387 if f(node) {
388 return f
389 }
390 return nil
391 }
392
393
394
395
396
397
398 func Inspect(node Node, f func(Node) bool) {
399 Walk(inspector(f), node)
400 }
401
View as plain text