-
Notifications
You must be signed in to change notification settings - Fork 93
/
tonodes.go
74 lines (69 loc) · 1.54 KB
/
tonodes.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
/*
* gomacro - A Go interpreter with Lisp-like macros
*
* Copyright (C) 2018-2019 Massimiliano Ghilardi
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
*
* tonodes.go
*
* Created on Mar 05, 2018
* Author Massimiliano Ghilardi
*/
package ast2
import (
"go/ast"
"go/token"
)
// ToNode recursively traverses Ast and extracts all the contained ast.Node:s
func ToNodes(x Ast) []ast.Node {
return ToNodesAppend(nil, x)
}
func ToNodesAppend(dst []ast.Node, x Ast) []ast.Node {
switch x := x.(type) {
case nil:
return dst
case File:
dst = collectImports(dst, x.X.Imports)
// treat as AstWithSlice to traverse File contents
break
case AstWithNode:
if x != nil {
dst = append(dst, x.Node())
}
return dst
case NodeSlice:
// faster than generic AstWithSlice
return append(dst, x.X...)
case AstWithSlice:
break
default:
y := x.Interface()
errorf("cannot convert to []ast.Node: %v // %T", y, y)
return nil
}
form, ok := x.(AstWithSlice)
if ok && form != nil {
n := form.Size()
for i := 0; i < n; i++ {
dst = ToNodesAppend(dst, form.Get(i))
}
}
return dst
}
func collectImports(dst []ast.Node, imports []*ast.ImportSpec) []ast.Node {
if n := len(imports); n != 0 {
specs := make([]ast.Spec, n)
for i, imp := range imports {
specs[i] = imp
}
dst = append(dst, &ast.GenDecl{
Tok: token.IMPORT,
Specs: specs,
})
}
return dst
}