-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathnode.go
More file actions
108 lines (91 loc) · 2.25 KB
/
node.go
File metadata and controls
108 lines (91 loc) · 2.25 KB
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
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
package astpatt
import (
"github.com/tehsphinx/astrav"
)
// Node represents a pattern node.
type Node interface {
Match(Node) bool
Populate(astrav.Node)
Children() []Node
Walk(f func(node Node) bool)
isType(astrav.NodeType) bool
populateDefault(ast astrav.Node)
fillNode(nodes []Node, ast astrav.Node)
}
// DefaultNode implements the default node definition
type DefaultNode struct {
parentNode
}
type parentNode struct {
Nodes nodes `json:"children,omitempty"`
NodeType astrav.NodeType `json:"type"`
Code string `json:"-"`
}
func (s *parentNode) correctType(node Node) bool {
return node.isType(s.NodeType)
}
// Match checks if given node matches the criteria
func (s *parentNode) Match(node Node) bool {
if !s.correctType(node) {
return false
}
return s.Nodes.Match(node)
}
// Children returns the child nodes.
func (s *parentNode) Children() []Node {
return s.Nodes
}
// Populate populates the pattern node from a given ast node.
// This is the default Populator implementation. Overwrite for spefic pattern node behavior.
func (s *parentNode) Populate(ast astrav.Node) {
s.populateDefault(ast)
s.populateChildren(ast)
}
func (s *parentNode) populateDefault(ast astrav.Node) {
s.NodeType = ast.NodeType()
s.Code = ast.GetSourceString()
}
func (s *parentNode) fillNode(nodes []Node, ast astrav.Node) {
s.Nodes = nodes
s.populateDefault(ast)
}
func (s *parentNode) populateChildren(ast astrav.Node) {
for _, ast := range ast.Children() {
node := creator(ast)
if node.isType(NodeTypeOmit) {
continue
}
if node.isType(NodeTypeSkip) {
s.populateChildren(ast)
continue
}
s.Nodes = append(s.Nodes, node)
}
}
// Walk traverses the tree and its children.
// return false to skip children of the current element
func (s *parentNode) Walk(f func(node Node) bool) {
if !f(s) {
return
}
for _, child := range s.Children() {
child.Walk(f)
}
}
func (s *parentNode) isType(nodeType astrav.NodeType) bool {
return s.NodeType == nodeType
}
type nodes []Node
// Match checks if given node matches the criteria
func (s nodes) Match(parent Node) bool {
var nodes = parent.Children()
if len(s) != len(nodes) {
return false
}
for i, child := range s {
if !child.Match(nodes[i]) {
return false
}
}
return true
}