1
1
package ast_test
2
2
3
3
import (
4
- "log"
5
4
"testing"
6
5
7
6
"github.com/robertkrimen/otto/ast"
8
7
"github.com/robertkrimen/otto/file"
9
8
"github.com/robertkrimen/otto/parser"
9
+ "github.com/stretchr/testify/require"
10
10
)
11
11
12
12
type walker struct {
13
- stack []ast.Node
14
- source string
15
- shift file.Idx
13
+ stack []ast.Node
14
+ source string
15
+ shift file.Idx
16
+ seen map [ast.Node ]struct {}
17
+ duplicate int
16
18
}
17
19
18
20
// push and pop below are to prove the symmetry of Enter/Exit calls
@@ -38,18 +40,25 @@ func (w *walker) pop(n ast.Node) {
38
40
39
41
func (w * walker ) Enter (n ast.Node ) ast.Visitor {
40
42
w .push (n )
43
+ if _ , ok := w .seen [n ]; ok {
44
+ // Skip items we've already seen which occurs due to declarations.
45
+ w .duplicate ++
46
+ return w
47
+ }
48
+
49
+ w .seen [n ] = struct {}{}
41
50
42
51
if id , ok := n .(* ast.Identifier ); ok && id != nil {
43
52
idx := n .Idx0 () + w .shift - 1
44
- s := w .source [:idx ] + "new_ " + w .source [idx :]
53
+ s := w .source [:idx ] + "IDENT_ " + w .source [idx :]
45
54
w .source = s
46
- w .shift += 4
55
+ w .shift += 6
47
56
}
48
57
if v , ok := n .(* ast.VariableExpression ); ok && v != nil {
49
58
idx := n .Idx0 () + w .shift - 1
50
- s := w .source [:idx ] + "varnew_ " + w .source [idx :]
59
+ s := w .source [:idx ] + "VAR_ " + w .source [idx :]
51
60
w .source = s
52
- w .shift += 7
61
+ w .shift += 4
53
62
}
54
63
55
64
return w
@@ -60,23 +69,27 @@ func (w *walker) Exit(n ast.Node) {
60
69
}
61
70
62
71
func TestVisitorRewrite (t * testing.T ) {
63
- source := `var b = function() {test(); try {} catch(e) {} var test = "test(); var test = 1"} // test`
72
+ source := `var b = function() {
73
+ test();
74
+ try {} catch(e) {}
75
+ var test = "test(); var test = 1"
76
+ } // test`
64
77
program , err := parser .ParseFile (nil , "" , source , 0 )
65
- if err != nil {
66
- log .Fatal (err )
67
- }
68
-
69
- w := & walker {source : source }
78
+ require .NoError (t , err )
70
79
80
+ w := & walker {
81
+ source : source ,
82
+ seen : make (map [ast.Node ]struct {}),
83
+ }
71
84
ast .Walk (w , program )
72
85
73
- xformed := `var varnew_b = function() {new_test(); try {} catch(new_e) {} var varnew_test = "test(); var test = 1"} // test`
86
+ xformed := `var VAR_b = function() {
87
+ IDENT_test();
88
+ try {} catch(IDENT_e) {}
89
+ var VAR_test = "test(); var test = 1"
90
+ } // test`
74
91
75
- if w .source != xformed {
76
- t .Errorf ("source is `%s` not `%s`" , w .source , xformed )
77
- }
78
-
79
- if len (w .stack ) != 0 {
80
- t .Errorf ("stack should be empty, but is length: %d" , len (w .stack ))
81
- }
92
+ require .Equal (t , xformed , w .source )
93
+ require .Len (t , w .stack , 0 )
94
+ require .Equal (t , w .duplicate , 0 )
82
95
}
0 commit comments