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
|
package ast_test
import (
"log"
"testing"
"github.com/robertkrimen/otto/ast"
"github.com/robertkrimen/otto/file"
"github.com/robertkrimen/otto/parser"
)
type walker struct {
stack []ast.Node
source string
shift file.Idx
}
// push and pop below are to prove the symmetry of Enter/Exit calls
func (w *walker) push(n ast.Node) {
w.stack = append(w.stack, n)
}
func (w *walker) pop(n ast.Node) {
size := len(w.stack)
if size <= 0 {
panic("pop of empty stack")
}
toPop := w.stack[size-1]
if toPop != n {
panic("pop: nodes do not equal")
}
w.stack[size-1] = nil
w.stack = w.stack[:size-1]
}
func (w *walker) Enter(n ast.Node) ast.Visitor {
w.push(n)
if id, ok := n.(*ast.Identifier); ok && id != nil {
idx := n.Idx0() + w.shift - 1
s := w.source[:idx] + "new_" + w.source[idx:]
w.source = s
w.shift += 4
}
if v, ok := n.(*ast.VariableExpression); ok && v != nil {
idx := n.Idx0() + w.shift - 1
s := w.source[:idx] + "varnew_" + w.source[idx:]
w.source = s
w.shift += 7
}
return w
}
func (w *walker) Exit(n ast.Node) {
w.pop(n)
}
func TestVisitorRewrite(t *testing.T) {
source := `var b = function() {test(); try {} catch(e) {} var test = "test(); var test = 1"} // test`
program, err := parser.ParseFile(nil, "", source, 0)
if err != nil {
log.Fatal(err)
}
w := &walker{source: source}
ast.Walk(w, program)
xformed := `var varnew_b = function() {new_test(); try {} catch(new_e) {} var varnew_test = "test(); var test = 1"} // test`
if w.source != xformed {
t.Errorf("source is `%s` not `%s`", w.source, xformed)
}
if len(w.stack) != 0 {
t.Errorf("stack should be empty, but is length: %d", len(w.stack))
}
}
|