diff options
Diffstat (limited to 'libgo/go/go/parser/parser_test.go')
-rw-r--r-- | libgo/go/go/parser/parser_test.go | 106 |
1 files changed, 95 insertions, 11 deletions
diff --git a/libgo/go/go/parser/parser_test.go b/libgo/go/go/parser/parser_test.go index 85065fd..c7bb36d 100644 --- a/libgo/go/go/parser/parser_test.go +++ b/libgo/go/go/parser/parser_test.go @@ -14,8 +14,6 @@ import ( "testing" ) -var fset = token.NewFileSet() - var validFiles = []string{ "parser.go", "parser_test.go", @@ -25,7 +23,7 @@ var validFiles = []string{ func TestParse(t *testing.T) { for _, filename := range validFiles { - _, err := ParseFile(fset, filename, nil, DeclarationErrors) + _, err := ParseFile(token.NewFileSet(), filename, nil, DeclarationErrors) if err != nil { t.Fatalf("ParseFile(%s): %v", filename, err) } @@ -46,7 +44,7 @@ func dirFilter(f os.FileInfo) bool { return nameFilter(f.Name()) } func TestParseDir(t *testing.T) { path := "." - pkgs, err := ParseDir(fset, path, dirFilter, 0) + pkgs, err := ParseDir(token.NewFileSet(), path, dirFilter, 0) if err != nil { t.Fatalf("ParseDir(%s): %v", path, err) } @@ -131,7 +129,7 @@ func TestParseExpr(t *testing.T) { } func TestColonEqualsScope(t *testing.T) { - f, err := ParseFile(fset, "", `package p; func f() { x, y, z := x, y, z }`, 0) + f, err := ParseFile(token.NewFileSet(), "", `package p; func f() { x, y, z := x, y, z }`, 0) if err != nil { t.Fatal(err) } @@ -153,7 +151,7 @@ func TestColonEqualsScope(t *testing.T) { } func TestVarScope(t *testing.T) { - f, err := ParseFile(fset, "", `package p; func f() { var x, y, z = x, y, z }`, 0) + f, err := ParseFile(token.NewFileSet(), "", `package p; func f() { var x, y, z = x, y, z }`, 0) if err != nil { t.Fatal(err) } @@ -183,7 +181,7 @@ var x int func f() { L: } ` - f, err := ParseFile(fset, "", src, 0) + f, err := ParseFile(token.NewFileSet(), "", src, 0) if err != nil { t.Fatal(err) } @@ -221,7 +219,7 @@ func f() { L: } } func TestUnresolved(t *testing.T) { - f, err := ParseFile(fset, "", ` + f, err := ParseFile(token.NewFileSet(), "", ` package p // func f1a(int) @@ -316,7 +314,7 @@ var imports = map[string]bool{ func TestImports(t *testing.T) { for path, isValid := range imports { src := fmt.Sprintf("package p; import %s", path) - _, err := ParseFile(fset, "", src, 0) + _, err := ParseFile(token.NewFileSet(), "", src, 0) switch { case err != nil && isValid: t.Errorf("ParseFile(%s): got %v; expected no error", src, err) @@ -327,7 +325,7 @@ func TestImports(t *testing.T) { } func TestCommentGroups(t *testing.T) { - f, err := ParseFile(fset, "", ` + f, err := ParseFile(token.NewFileSet(), "", ` package p /* 1a */ /* 1b */ /* 1c */ // 1d /* 2a */ @@ -421,7 +419,7 @@ func checkFieldComments(t *testing.T, file *ast.File, fieldname, lead, line stri } func TestLeadAndLineComments(t *testing.T) { - f, err := ParseFile(fset, "", ` + f, err := ParseFile(token.NewFileSet(), "", ` package p type T struct { /* F1 lead comment */ @@ -447,3 +445,89 @@ type T struct { t.Error("not expected to find T.f3") } } + +// TestIssue9979 verifies that empty statements are contained within their enclosing blocks. +func TestIssue9979(t *testing.T) { + for _, src := range []string{ + "package p; func f() {;}", + "package p; func f() {L:}", + "package p; func f() {L:;}", + "package p; func f() {L:\n}", + "package p; func f() {L:\n;}", + "package p; func f() { ; }", + "package p; func f() { L: }", + "package p; func f() { L: ; }", + "package p; func f() { L: \n}", + "package p; func f() { L: \n; }", + } { + fset := token.NewFileSet() + f, err := ParseFile(fset, "", src, 0) + if err != nil { + t.Fatal(err) + } + + var pos, end token.Pos + ast.Inspect(f, func(x ast.Node) bool { + switch s := x.(type) { + case *ast.BlockStmt: + pos, end = s.Pos()+1, s.End()-1 // exclude "{", "}" + case *ast.LabeledStmt: + pos, end = s.Pos()+2, s.End() // exclude "L:" + case *ast.EmptyStmt: + // check containment + if s.Pos() < pos || s.End() > end { + t.Errorf("%s: %T[%d, %d] not inside [%d, %d]", src, s, s.Pos(), s.End(), pos, end) + } + // check semicolon + offs := fset.Position(s.Pos()).Offset + if ch := src[offs]; ch != ';' != s.Implicit { + want := "want ';'" + if s.Implicit { + want = "but ';' is implicit" + } + t.Errorf("%s: found %q at offset %d; %s", src, ch, offs, want) + } + } + return true + }) + } +} + +// TestIncompleteSelection ensures that an incomplete selector +// expression is parsed as a (blank) *ast.SelectorExpr, not a +// *ast.BadExpr. +func TestIncompleteSelection(t *testing.T) { + for _, src := range []string{ + "package p; var _ = fmt.", // at EOF + "package p; var _ = fmt.\ntype X int", // not at EOF + } { + fset := token.NewFileSet() + f, err := ParseFile(fset, "", src, 0) + if err == nil { + t.Errorf("ParseFile(%s) succeeded unexpectedly", src) + continue + } + + const wantErr = "expected selector or type assertion" + if !strings.Contains(err.Error(), wantErr) { + t.Errorf("ParseFile returned wrong error %q, want %q", err, wantErr) + } + + var sel *ast.SelectorExpr + ast.Inspect(f, func(n ast.Node) bool { + if n, ok := n.(*ast.SelectorExpr); ok { + sel = n + } + return true + }) + if sel == nil { + t.Error("found no *ast.SelectorExpr") + continue + } + const wantSel = "&{fmt _}" + if fmt.Sprint(sel) != wantSel { + t.Errorf("found selector %s, want %s", sel, wantSel) + continue + } + } +} |