1 // Copyright 2013 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
7 // This file defines tests of PathEnclosingInterval.
9 // TODO(adonovan): exhaustive tests that run over the whole input
10 // tree, not just handcrafted examples.
21 "golang.org/x/tools/go/ast/astutil"
24 // pathToString returns a string containing the concrete types of the
26 func pathToString(path []ast.Node) string {
29 for i, n := range path {
33 fmt.Fprint(&buf, strings.TrimPrefix(fmt.Sprintf("%T", n), "*ast."))
39 // findInterval parses input and returns the [start, end) positions of
40 // the first occurrence of substr in input. f==nil indicates failure;
41 // an error has already been reported in that case.
43 func findInterval(t *testing.T, fset *token.FileSet, input, substr string) (f *ast.File, start, end token.Pos) {
44 f, err := parser.ParseFile(fset, "<input>", input, 0)
46 t.Errorf("parse error: %s", err)
50 i := strings.Index(input, substr)
52 t.Errorf("%q is not a substring of input", substr)
57 filePos := fset.File(f.Package)
58 return f, filePos.Pos(i), filePos.Pos(i + len(substr))
61 // Common input for following tests.
68 z := (x + y) // add them
69 f() // NB: ExprStmt and its CallExpr have same Pos/End
73 func TestPathEnclosingInterval_Exact(t *testing.T) {
74 // For the exact tests, we check that a substring is mapped to
75 // the canonical string for the node it denotes.
77 substr string // first occurrence of this string indicates interval
78 node string // complete text of expected containing node
81 input[11 : len(input)-1]},
83 input[11 : len(input)-1]},
119 for _, test := range tests {
120 f, start, end := findInterval(t, new(token.FileSet), input, test.substr)
125 path, exact := astutil.PathEnclosingInterval(f, start, end)
127 t.Errorf("PathEnclosingInterval(%q) not exact", test.substr)
133 t.Errorf("PathEnclosingInterval(%q).path: got [], want %q",
134 test.substr, test.node)
139 if got := input[path[0].Pos():path[0].End()]; got != test.node {
140 t.Errorf("PathEnclosingInterval(%q): got %q, want %q (path was %s)",
141 test.substr, got, test.node, pathToString(path))
147 func TestPathEnclosingInterval_Paths(t *testing.T) {
148 // For these tests, we check only the path of the enclosing
149 // node, but not its complete text because it's often quite
150 // large when !exact.
152 substr string // first occurrence of this string indicates interval
153 path string // the pathToString(),exact of the expected path
156 "[BlockStmt FuncDecl File],false"},
158 "[ParenExpr AssignStmt BlockStmt FuncDecl File],false"},
160 "[BinaryExpr ParenExpr AssignStmt BlockStmt FuncDecl File],false"},
162 "[AssignStmt BlockStmt FuncDecl File],false"},
164 "[FuncDecl File],false"},
166 "[FuncDecl File],false"},
168 "[FuncDecl File],false"},
170 "[FuncDecl File],false"},
174 "[Ident FuncDecl File],true"},
176 "[FuncDecl File],true"},
178 "[Ident File],true"},
180 "[CallExpr ExprStmt BlockStmt FuncDecl File],true"},
182 for _, test := range tests {
183 f, start, end := findInterval(t, new(token.FileSet), input, test.substr)
188 path, exact := astutil.PathEnclosingInterval(f, start, end)
189 if got := fmt.Sprintf("%s,%v", pathToString(path), exact); got != test.path {
190 t.Errorf("PathEnclosingInterval(%q): got %q, want %q",
191 test.substr, got, test.path)