Source file src/pkg/cmd/vendor/golang.org/x/tools/go/ast/astutil/rewrite.go
1
2
3
4
5 package astutil
6
7 import (
8 "fmt"
9 "go/ast"
10 "reflect"
11 "sort"
12 )
13
14
15
16
17
18
19
20 type ApplyFunc func(*Cursor) bool
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43 func Apply(root ast.Node, pre, post ApplyFunc) (result ast.Node) {
44 parent := &struct{ ast.Node }{root}
45 defer func() {
46 if r := recover(); r != nil && r != abort {
47 panic(r)
48 }
49 result = parent.Node
50 }()
51 a := &application{pre: pre, post: post}
52 a.apply(parent, "Node", nil, root)
53 return
54 }
55
56 var abort = new(int)
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71 type Cursor struct {
72 parent ast.Node
73 name string
74 iter *iterator
75 node ast.Node
76 }
77
78
79 func (c *Cursor) Node() ast.Node { return c.node }
80
81
82 func (c *Cursor) Parent() ast.Node { return c.parent }
83
84
85
86
87 func (c *Cursor) Name() string { return c.name }
88
89
90
91
92
93 func (c *Cursor) Index() int {
94 if c.iter != nil {
95 return c.iter.index
96 }
97 return -1
98 }
99
100
101 func (c *Cursor) field() reflect.Value {
102 return reflect.Indirect(reflect.ValueOf(c.parent)).FieldByName(c.name)
103 }
104
105
106
107 func (c *Cursor) Replace(n ast.Node) {
108 if _, ok := c.node.(*ast.File); ok {
109 file, ok := n.(*ast.File)
110 if !ok {
111 panic("attempt to replace *ast.File with non-*ast.File")
112 }
113 c.parent.(*ast.Package).Files[c.name] = file
114 return
115 }
116
117 v := c.field()
118 if i := c.Index(); i >= 0 {
119 v = v.Index(i)
120 }
121 v.Set(reflect.ValueOf(n))
122 }
123
124
125
126
127
128 func (c *Cursor) Delete() {
129 if _, ok := c.node.(*ast.File); ok {
130 delete(c.parent.(*ast.Package).Files, c.name)
131 return
132 }
133
134 i := c.Index()
135 if i < 0 {
136 panic("Delete node not contained in slice")
137 }
138 v := c.field()
139 l := v.Len()
140 reflect.Copy(v.Slice(i, l), v.Slice(i+1, l))
141 v.Index(l - 1).Set(reflect.Zero(v.Type().Elem()))
142 v.SetLen(l - 1)
143 c.iter.step--
144 }
145
146
147
148
149 func (c *Cursor) InsertAfter(n ast.Node) {
150 i := c.Index()
151 if i < 0 {
152 panic("InsertAfter node not contained in slice")
153 }
154 v := c.field()
155 v.Set(reflect.Append(v, reflect.Zero(v.Type().Elem())))
156 l := v.Len()
157 reflect.Copy(v.Slice(i+2, l), v.Slice(i+1, l))
158 v.Index(i + 1).Set(reflect.ValueOf(n))
159 c.iter.step++
160 }
161
162
163
164
165 func (c *Cursor) InsertBefore(n ast.Node) {
166 i := c.Index()
167 if i < 0 {
168 panic("InsertBefore node not contained in slice")
169 }
170 v := c.field()
171 v.Set(reflect.Append(v, reflect.Zero(v.Type().Elem())))
172 l := v.Len()
173 reflect.Copy(v.Slice(i+1, l), v.Slice(i, l))
174 v.Index(i).Set(reflect.ValueOf(n))
175 c.iter.index++
176 }
177
178
179 type application struct {
180 pre, post ApplyFunc
181 cursor Cursor
182 iter iterator
183 }
184
185 func (a *application) apply(parent ast.Node, name string, iter *iterator, n ast.Node) {
186
187 if v := reflect.ValueOf(n); v.Kind() == reflect.Ptr && v.IsNil() {
188 n = nil
189 }
190
191
192 saved := a.cursor
193 a.cursor.parent = parent
194 a.cursor.name = name
195 a.cursor.iter = iter
196 a.cursor.node = n
197
198 if a.pre != nil && !a.pre(&a.cursor) {
199 a.cursor = saved
200 return
201 }
202
203
204
205 switch n := n.(type) {
206 case nil:
207
208
209
210 case *ast.Comment:
211
212
213 case *ast.CommentGroup:
214 if n != nil {
215 a.applyList(n, "List")
216 }
217
218 case *ast.Field:
219 a.apply(n, "Doc", nil, n.Doc)
220 a.applyList(n, "Names")
221 a.apply(n, "Type", nil, n.Type)
222 a.apply(n, "Tag", nil, n.Tag)
223 a.apply(n, "Comment", nil, n.Comment)
224
225 case *ast.FieldList:
226 a.applyList(n, "List")
227
228
229 case *ast.BadExpr, *ast.Ident, *ast.BasicLit:
230
231
232 case *ast.Ellipsis:
233 a.apply(n, "Elt", nil, n.Elt)
234
235 case *ast.FuncLit:
236 a.apply(n, "Type", nil, n.Type)
237 a.apply(n, "Body", nil, n.Body)
238
239 case *ast.CompositeLit:
240 a.apply(n, "Type", nil, n.Type)
241 a.applyList(n, "Elts")
242
243 case *ast.ParenExpr:
244 a.apply(n, "X", nil, n.X)
245
246 case *ast.SelectorExpr:
247 a.apply(n, "X", nil, n.X)
248 a.apply(n, "Sel", nil, n.Sel)
249
250 case *ast.IndexExpr:
251 a.apply(n, "X", nil, n.X)
252 a.apply(n, "Index", nil, n.Index)
253
254 case *ast.SliceExpr:
255 a.apply(n, "X", nil, n.X)
256 a.apply(n, "Low", nil, n.Low)
257 a.apply(n, "High", nil, n.High)
258 a.apply(n, "Max", nil, n.Max)
259
260 case *ast.TypeAssertExpr:
261 a.apply(n, "X", nil, n.X)
262 a.apply(n, "Type", nil, n.Type)
263
264 case *ast.CallExpr:
265 a.apply(n, "Fun", nil, n.Fun)
266 a.applyList(n, "Args")
267
268 case *ast.StarExpr:
269 a.apply(n, "X", nil, n.X)
270
271 case *ast.UnaryExpr:
272 a.apply(n, "X", nil, n.X)
273
274 case *ast.BinaryExpr:
275 a.apply(n, "X", nil, n.X)
276 a.apply(n, "Y", nil, n.Y)
277
278 case *ast.KeyValueExpr:
279 a.apply(n, "Key", nil, n.Key)
280 a.apply(n, "Value", nil, n.Value)
281
282
283 case *ast.ArrayType:
284 a.apply(n, "Len", nil, n.Len)
285 a.apply(n, "Elt", nil, n.Elt)
286
287 case *ast.StructType:
288 a.apply(n, "Fields", nil, n.Fields)
289
290 case *ast.FuncType:
291 a.apply(n, "Params", nil, n.Params)
292 a.apply(n, "Results", nil, n.Results)
293
294 case *ast.InterfaceType:
295 a.apply(n, "Methods", nil, n.Methods)
296
297 case *ast.MapType:
298 a.apply(n, "Key", nil, n.Key)
299 a.apply(n, "Value", nil, n.Value)
300
301 case *ast.ChanType:
302 a.apply(n, "Value", nil, n.Value)
303
304
305 case *ast.BadStmt:
306
307
308 case *ast.DeclStmt:
309 a.apply(n, "Decl", nil, n.Decl)
310
311 case *ast.EmptyStmt:
312
313
314 case *ast.LabeledStmt:
315 a.apply(n, "Label", nil, n.Label)
316 a.apply(n, "Stmt", nil, n.Stmt)
317
318 case *ast.ExprStmt:
319 a.apply(n, "X", nil, n.X)
320
321 case *ast.SendStmt:
322 a.apply(n, "Chan", nil, n.Chan)
323 a.apply(n, "Value", nil, n.Value)
324
325 case *ast.IncDecStmt:
326 a.apply(n, "X", nil, n.X)
327
328 case *ast.AssignStmt:
329 a.applyList(n, "Lhs")
330 a.applyList(n, "Rhs")
331
332 case *ast.GoStmt:
333 a.apply(n, "Call", nil, n.Call)
334
335 case *ast.DeferStmt:
336 a.apply(n, "Call", nil, n.Call)
337
338 case *ast.ReturnStmt:
339 a.applyList(n, "Results")
340
341 case *ast.BranchStmt:
342 a.apply(n, "Label", nil, n.Label)
343
344 case *ast.BlockStmt:
345 a.applyList(n, "List")
346
347 case *ast.IfStmt:
348 a.apply(n, "Init", nil, n.Init)
349 a.apply(n, "Cond", nil, n.Cond)
350 a.apply(n, "Body", nil, n.Body)
351 a.apply(n, "Else", nil, n.Else)
352
353 case *ast.CaseClause:
354 a.applyList(n, "List")
355 a.applyList(n, "Body")
356
357 case *ast.SwitchStmt:
358 a.apply(n, "Init", nil, n.Init)
359 a.apply(n, "Tag", nil, n.Tag)
360 a.apply(n, "Body", nil, n.Body)
361
362 case *ast.TypeSwitchStmt:
363 a.apply(n, "Init", nil, n.Init)
364 a.apply(n, "Assign", nil, n.Assign)
365 a.apply(n, "Body", nil, n.Body)
366
367 case *ast.CommClause:
368 a.apply(n, "Comm", nil, n.Comm)
369 a.applyList(n, "Body")
370
371 case *ast.SelectStmt:
372 a.apply(n, "Body", nil, n.Body)
373
374 case *ast.ForStmt:
375 a.apply(n, "Init", nil, n.Init)
376 a.apply(n, "Cond", nil, n.Cond)
377 a.apply(n, "Post", nil, n.Post)
378 a.apply(n, "Body", nil, n.Body)
379
380 case *ast.RangeStmt:
381 a.apply(n, "Key", nil, n.Key)
382 a.apply(n, "Value", nil, n.Value)
383 a.apply(n, "X", nil, n.X)
384 a.apply(n, "Body", nil, n.Body)
385
386
387 case *ast.ImportSpec:
388 a.apply(n, "Doc", nil, n.Doc)
389 a.apply(n, "Name", nil, n.Name)
390 a.apply(n, "Path", nil, n.Path)
391 a.apply(n, "Comment", nil, n.Comment)
392
393 case *ast.ValueSpec:
394 a.apply(n, "Doc", nil, n.Doc)
395 a.applyList(n, "Names")
396 a.apply(n, "Type", nil, n.Type)
397 a.applyList(n, "Values")
398 a.apply(n, "Comment", nil, n.Comment)
399
400 case *ast.TypeSpec:
401 a.apply(n, "Doc", nil, n.Doc)
402 a.apply(n, "Name", nil, n.Name)
403 a.apply(n, "Type", nil, n.Type)
404 a.apply(n, "Comment", nil, n.Comment)
405
406 case *ast.BadDecl:
407
408
409 case *ast.GenDecl:
410 a.apply(n, "Doc", nil, n.Doc)
411 a.applyList(n, "Specs")
412
413 case *ast.FuncDecl:
414 a.apply(n, "Doc", nil, n.Doc)
415 a.apply(n, "Recv", nil, n.Recv)
416 a.apply(n, "Name", nil, n.Name)
417 a.apply(n, "Type", nil, n.Type)
418 a.apply(n, "Body", nil, n.Body)
419
420
421 case *ast.File:
422 a.apply(n, "Doc", nil, n.Doc)
423 a.apply(n, "Name", nil, n.Name)
424 a.applyList(n, "Decls")
425
426
427
428 case *ast.Package:
429
430 var names []string
431 for name := range n.Files {
432 names = append(names, name)
433 }
434 sort.Strings(names)
435 for _, name := range names {
436 a.apply(n, name, nil, n.Files[name])
437 }
438
439 default:
440 panic(fmt.Sprintf("Apply: unexpected node type %T", n))
441 }
442
443 if a.post != nil && !a.post(&a.cursor) {
444 panic(abort)
445 }
446
447 a.cursor = saved
448 }
449
450
451 type iterator struct {
452 index, step int
453 }
454
455 func (a *application) applyList(parent ast.Node, name string) {
456
457 saved := a.iter
458 a.iter.index = 0
459 for {
460
461 v := reflect.Indirect(reflect.ValueOf(parent)).FieldByName(name)
462 if a.iter.index >= v.Len() {
463 break
464 }
465
466
467 var x ast.Node
468 if e := v.Index(a.iter.index); e.IsValid() {
469 x = e.Interface().(ast.Node)
470 }
471
472 a.iter.step = 1
473 a.apply(parent, name, &a.iter, x)
474 a.iter.index += a.iter.step
475 }
476 a.iter = saved
477 }
478
View as plain text