1
2
3
4
5 package inspector
6
7
8
9
10
11
12 import (
13 "fmt"
14 "go/ast"
15
16 "golang.org/x/tools/go/ast/edge"
17 )
18
19 func walkList[N ast.Node](v *visitor, ek edge.Kind, list []N) {
20 for i, node := range list {
21 walk(v, ek, i, node)
22 }
23 }
24
25 func walk(v *visitor, ek edge.Kind, index int, node ast.Node) {
26 v.push(ek, index, node)
27
28
29
30
31 switch n := node.(type) {
32
33 case *ast.Comment:
34
35
36 case *ast.CommentGroup:
37 walkList(v, edge.CommentGroup_List, n.List)
38
39 case *ast.Field:
40 if n.Doc != nil {
41 walk(v, edge.Field_Doc, -1, n.Doc)
42 }
43 walkList(v, edge.Field_Names, n.Names)
44 if n.Type != nil {
45 walk(v, edge.Field_Type, -1, n.Type)
46 }
47 if n.Tag != nil {
48 walk(v, edge.Field_Tag, -1, n.Tag)
49 }
50 if n.Comment != nil {
51 walk(v, edge.Field_Comment, -1, n.Comment)
52 }
53
54 case *ast.FieldList:
55 walkList(v, edge.FieldList_List, n.List)
56
57
58 case *ast.BadExpr, *ast.Ident, *ast.BasicLit:
59
60
61 case *ast.Ellipsis:
62 if n.Elt != nil {
63 walk(v, edge.Ellipsis_Elt, -1, n.Elt)
64 }
65
66 case *ast.FuncLit:
67 walk(v, edge.FuncLit_Type, -1, n.Type)
68 walk(v, edge.FuncLit_Body, -1, n.Body)
69
70 case *ast.CompositeLit:
71 if n.Type != nil {
72 walk(v, edge.CompositeLit_Type, -1, n.Type)
73 }
74 walkList(v, edge.CompositeLit_Elts, n.Elts)
75
76 case *ast.ParenExpr:
77 walk(v, edge.ParenExpr_X, -1, n.X)
78
79 case *ast.SelectorExpr:
80 walk(v, edge.SelectorExpr_X, -1, n.X)
81 walk(v, edge.SelectorExpr_Sel, -1, n.Sel)
82
83 case *ast.IndexExpr:
84 walk(v, edge.IndexExpr_X, -1, n.X)
85 walk(v, edge.IndexExpr_Index, -1, n.Index)
86
87 case *ast.IndexListExpr:
88 walk(v, edge.IndexListExpr_X, -1, n.X)
89 walkList(v, edge.IndexListExpr_Indices, n.Indices)
90
91 case *ast.SliceExpr:
92 walk(v, edge.SliceExpr_X, -1, n.X)
93 if n.Low != nil {
94 walk(v, edge.SliceExpr_Low, -1, n.Low)
95 }
96 if n.High != nil {
97 walk(v, edge.SliceExpr_High, -1, n.High)
98 }
99 if n.Max != nil {
100 walk(v, edge.SliceExpr_Max, -1, n.Max)
101 }
102
103 case *ast.TypeAssertExpr:
104 walk(v, edge.TypeAssertExpr_X, -1, n.X)
105 if n.Type != nil {
106 walk(v, edge.TypeAssertExpr_Type, -1, n.Type)
107 }
108
109 case *ast.CallExpr:
110 walk(v, edge.CallExpr_Fun, -1, n.Fun)
111 walkList(v, edge.CallExpr_Args, n.Args)
112
113 case *ast.StarExpr:
114 walk(v, edge.StarExpr_X, -1, n.X)
115
116 case *ast.UnaryExpr:
117 walk(v, edge.UnaryExpr_X, -1, n.X)
118
119 case *ast.BinaryExpr:
120 walk(v, edge.BinaryExpr_X, -1, n.X)
121 walk(v, edge.BinaryExpr_Y, -1, n.Y)
122
123 case *ast.KeyValueExpr:
124 walk(v, edge.KeyValueExpr_Key, -1, n.Key)
125 walk(v, edge.KeyValueExpr_Value, -1, n.Value)
126
127
128 case *ast.ArrayType:
129 if n.Len != nil {
130 walk(v, edge.ArrayType_Len, -1, n.Len)
131 }
132 walk(v, edge.ArrayType_Elt, -1, n.Elt)
133
134 case *ast.StructType:
135 walk(v, edge.StructType_Fields, -1, n.Fields)
136
137 case *ast.FuncType:
138 if n.TypeParams != nil {
139 walk(v, edge.FuncType_TypeParams, -1, n.TypeParams)
140 }
141 if n.Params != nil {
142 walk(v, edge.FuncType_Params, -1, n.Params)
143 }
144 if n.Results != nil {
145 walk(v, edge.FuncType_Results, -1, n.Results)
146 }
147
148 case *ast.InterfaceType:
149 walk(v, edge.InterfaceType_Methods, -1, n.Methods)
150
151 case *ast.MapType:
152 walk(v, edge.MapType_Key, -1, n.Key)
153 walk(v, edge.MapType_Value, -1, n.Value)
154
155 case *ast.ChanType:
156 walk(v, edge.ChanType_Value, -1, n.Value)
157
158
159 case *ast.BadStmt:
160
161
162 case *ast.DeclStmt:
163 walk(v, edge.DeclStmt_Decl, -1, n.Decl)
164
165 case *ast.EmptyStmt:
166
167
168 case *ast.LabeledStmt:
169 walk(v, edge.LabeledStmt_Label, -1, n.Label)
170 walk(v, edge.LabeledStmt_Stmt, -1, n.Stmt)
171
172 case *ast.ExprStmt:
173 walk(v, edge.ExprStmt_X, -1, n.X)
174
175 case *ast.SendStmt:
176 walk(v, edge.SendStmt_Chan, -1, n.Chan)
177 walk(v, edge.SendStmt_Value, -1, n.Value)
178
179 case *ast.IncDecStmt:
180 walk(v, edge.IncDecStmt_X, -1, n.X)
181
182 case *ast.AssignStmt:
183 walkList(v, edge.AssignStmt_Lhs, n.Lhs)
184 walkList(v, edge.AssignStmt_Rhs, n.Rhs)
185
186 case *ast.GoStmt:
187 walk(v, edge.GoStmt_Call, -1, n.Call)
188
189 case *ast.DeferStmt:
190 walk(v, edge.DeferStmt_Call, -1, n.Call)
191
192 case *ast.ReturnStmt:
193 walkList(v, edge.ReturnStmt_Results, n.Results)
194
195 case *ast.BranchStmt:
196 if n.Label != nil {
197 walk(v, edge.BranchStmt_Label, -1, n.Label)
198 }
199
200 case *ast.BlockStmt:
201 walkList(v, edge.BlockStmt_List, n.List)
202
203 case *ast.IfStmt:
204 if n.Init != nil {
205 walk(v, edge.IfStmt_Init, -1, n.Init)
206 }
207 walk(v, edge.IfStmt_Cond, -1, n.Cond)
208 walk(v, edge.IfStmt_Body, -1, n.Body)
209 if n.Else != nil {
210 walk(v, edge.IfStmt_Else, -1, n.Else)
211 }
212
213 case *ast.CaseClause:
214 walkList(v, edge.CaseClause_List, n.List)
215 walkList(v, edge.CaseClause_Body, n.Body)
216
217 case *ast.SwitchStmt:
218 if n.Init != nil {
219 walk(v, edge.SwitchStmt_Init, -1, n.Init)
220 }
221 if n.Tag != nil {
222 walk(v, edge.SwitchStmt_Tag, -1, n.Tag)
223 }
224 walk(v, edge.SwitchStmt_Body, -1, n.Body)
225
226 case *ast.TypeSwitchStmt:
227 if n.Init != nil {
228 walk(v, edge.TypeSwitchStmt_Init, -1, n.Init)
229 }
230 walk(v, edge.TypeSwitchStmt_Assign, -1, n.Assign)
231 walk(v, edge.TypeSwitchStmt_Body, -1, n.Body)
232
233 case *ast.CommClause:
234 if n.Comm != nil {
235 walk(v, edge.CommClause_Comm, -1, n.Comm)
236 }
237 walkList(v, edge.CommClause_Body, n.Body)
238
239 case *ast.SelectStmt:
240 walk(v, edge.SelectStmt_Body, -1, n.Body)
241
242 case *ast.ForStmt:
243 if n.Init != nil {
244 walk(v, edge.ForStmt_Init, -1, n.Init)
245 }
246 if n.Cond != nil {
247 walk(v, edge.ForStmt_Cond, -1, n.Cond)
248 }
249 if n.Post != nil {
250 walk(v, edge.ForStmt_Post, -1, n.Post)
251 }
252 walk(v, edge.ForStmt_Body, -1, n.Body)
253
254 case *ast.RangeStmt:
255 if n.Key != nil {
256 walk(v, edge.RangeStmt_Key, -1, n.Key)
257 }
258 if n.Value != nil {
259 walk(v, edge.RangeStmt_Value, -1, n.Value)
260 }
261 walk(v, edge.RangeStmt_X, -1, n.X)
262 walk(v, edge.RangeStmt_Body, -1, n.Body)
263
264
265 case *ast.ImportSpec:
266 if n.Doc != nil {
267 walk(v, edge.ImportSpec_Doc, -1, n.Doc)
268 }
269 if n.Name != nil {
270 walk(v, edge.ImportSpec_Name, -1, n.Name)
271 }
272 walk(v, edge.ImportSpec_Path, -1, n.Path)
273 if n.Comment != nil {
274 walk(v, edge.ImportSpec_Comment, -1, n.Comment)
275 }
276
277 case *ast.ValueSpec:
278 if n.Doc != nil {
279 walk(v, edge.ValueSpec_Doc, -1, n.Doc)
280 }
281 walkList(v, edge.ValueSpec_Names, n.Names)
282 if n.Type != nil {
283 walk(v, edge.ValueSpec_Type, -1, n.Type)
284 }
285 walkList(v, edge.ValueSpec_Values, n.Values)
286 if n.Comment != nil {
287 walk(v, edge.ValueSpec_Comment, -1, n.Comment)
288 }
289
290 case *ast.TypeSpec:
291 if n.Doc != nil {
292 walk(v, edge.TypeSpec_Doc, -1, n.Doc)
293 }
294 walk(v, edge.TypeSpec_Name, -1, n.Name)
295 if n.TypeParams != nil {
296 walk(v, edge.TypeSpec_TypeParams, -1, n.TypeParams)
297 }
298 walk(v, edge.TypeSpec_Type, -1, n.Type)
299 if n.Comment != nil {
300 walk(v, edge.TypeSpec_Comment, -1, n.Comment)
301 }
302
303 case *ast.BadDecl:
304
305
306 case *ast.GenDecl:
307 if n.Doc != nil {
308 walk(v, edge.GenDecl_Doc, -1, n.Doc)
309 }
310 walkList(v, edge.GenDecl_Specs, n.Specs)
311
312 case *ast.FuncDecl:
313 if n.Doc != nil {
314 walk(v, edge.FuncDecl_Doc, -1, n.Doc)
315 }
316 if n.Recv != nil {
317 walk(v, edge.FuncDecl_Recv, -1, n.Recv)
318 }
319 walk(v, edge.FuncDecl_Name, -1, n.Name)
320 walk(v, edge.FuncDecl_Type, -1, n.Type)
321 if n.Body != nil {
322 walk(v, edge.FuncDecl_Body, -1, n.Body)
323 }
324
325 case *ast.File:
326 if n.Doc != nil {
327 walk(v, edge.File_Doc, -1, n.Doc)
328 }
329 walk(v, edge.File_Name, -1, n.Name)
330 walkList(v, edge.File_Decls, n.Decls)
331
332
333
334
335 default:
336
337 panic(fmt.Sprintf("Walk: unexpected node type %T", n))
338 }
339
340 v.pop(node)
341 }
342
View as plain text