]> Cypherpunks repositories - gostls13.git/commitdiff
go/parser: ParseExpr must accept type expressions
authorRobert Griesemer <gri@golang.org>
Wed, 3 Apr 2013 14:41:26 +0000 (07:41 -0700)
committerRobert Griesemer <gri@golang.org>
Wed, 3 Apr 2013 14:41:26 +0000 (07:41 -0700)
My old code was trying to be too smart.
Also: Slightly better error message format
for gofmt -r pattern errors.

Fixes #4406.

R=golang-dev, adg
CC=golang-dev
https://golang.org/cl/8267045

src/cmd/gofmt/gofmt_test.go
src/cmd/gofmt/rewrite.go
src/cmd/gofmt/testdata/rewrite8.golden [new file with mode: 0644]
src/cmd/gofmt/testdata/rewrite8.input [new file with mode: 0644]
src/pkg/go/parser/interface.go
src/pkg/go/parser/parser_test.go

index 8ff00a253acb14040b478da9f2034ca72ff6c2ea..75a322a6c80ac5d3cf1407f4b0bfc73152359afe 100644 (file)
@@ -84,6 +84,7 @@ var tests = []struct {
        {"testdata/rewrite5.input", "-r=x+x->2*x"},
        {"testdata/rewrite6.input", "-r=fun(x)->Fun(x)"},
        {"testdata/rewrite7.input", "-r=fun(x...)->Fun(x)"},
+       {"testdata/rewrite8.input", "-r=interface{}->int"},
        {"testdata/stdin*.input", "-stdin"},
        {"testdata/comments.input", ""},
        {"testdata/import.input", ""},
index 1aa1f6ed001a2b3f25ba1d2fda5f29698feacb3b..66d2331a5ea595a1e7ef2068f4469f5f85c4a94a 100644 (file)
@@ -35,10 +35,10 @@ func initRewrite() {
 // It might make sense to expand this to allow statement patterns,
 // but there are problems with preserving formatting and also
 // with what a wildcard for a statement looks like.
-func parseExpr(s string, what string) ast.Expr {
+func parseExpr(s, what string) ast.Expr {
        x, err := parser.ParseExpr(s)
        if err != nil {
-               fmt.Fprintf(os.Stderr, "parsing %s %s: %s\n", what, s, err)
+               fmt.Fprintf(os.Stderr, "parsing %s %s at %s\n", what, s, err)
                os.Exit(2)
        }
        return x
diff --git a/src/cmd/gofmt/testdata/rewrite8.golden b/src/cmd/gofmt/testdata/rewrite8.golden
new file mode 100644 (file)
index 0000000..cfc452b
--- /dev/null
@@ -0,0 +1,10 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Check that literal type expression rewrites are accepted.
+// Was issue 4406.
+
+package p
+
+type T int
diff --git a/src/cmd/gofmt/testdata/rewrite8.input b/src/cmd/gofmt/testdata/rewrite8.input
new file mode 100644 (file)
index 0000000..235efa9
--- /dev/null
@@ -0,0 +1,10 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Check that literal type expression rewrites are accepted.
+// Was issue 4406.
+
+package p
+
+type T interface{}
index 39affdd6b988b07d1557eabf02e4a4a857b4d626..149257ca6b108711776139062fb861c5d5b5f58b 100644 (file)
@@ -162,16 +162,27 @@ func ParseDir(fset *token.FileSet, path string, filter func(os.FileInfo) bool, m
 }
 
 // ParseExpr is a convenience function for obtaining the AST of an expression x.
-// The position information recorded in the AST is undefined.
+// The position information recorded in the AST is undefined. The filename used
+// in error messages is the empty string.
 //
 func ParseExpr(x string) (ast.Expr, error) {
-       // parse x within the context of a complete package for correct scopes;
-       // use //line directive for correct positions in error messages and put
-       // x alone on a separate line (handles line comments), followed by a ';'
-       // to force an error if the expression is incomplete
-       file, err := ParseFile(token.NewFileSet(), "", "package p;func _(){_=\n//line :1\n"+x+"\n;}", 0)
-       if err != nil {
-               return nil, err
+       var p parser
+       p.init(token.NewFileSet(), "", []byte(x), 0)
+
+       // Set up pkg-level scopes to avoid nil-pointer errors.
+       // This is not needed for a correct expression x as the
+       // parser will be ok with a nil topScope, but be cautious
+       // in case of an erroneous x.
+       p.openScope()
+       p.pkgScope = p.topScope
+       e := p.parseRhsOrType()
+       p.closeScope()
+       assert(p.topScope == nil, "unbalanced scopes")
+
+       if p.errors.Len() > 0 {
+               p.errors.Sort()
+               return nil, p.errors.Err()
        }
-       return file.Decls[0].(*ast.FuncDecl).Body.List[0].(*ast.AssignStmt).Rhs[0], nil
+
+       return e, nil
 }
index 1960377b0a69287425a3ded030b813e9ef0a8dcd..48813d106127d782dff9878e72b7193ae6e4fd6b 100644 (file)
@@ -68,7 +68,7 @@ func TestParseDir(t *testing.T) {
 
 func TestParseExpr(t *testing.T) {
        // just kicking the tires:
-       // a valid expression
+       // a valid arithmetic expression
        src := "a + b"
        x, err := ParseExpr(src)
        if err != nil {
@@ -79,6 +79,17 @@ func TestParseExpr(t *testing.T) {
                t.Errorf("ParseExpr(%s): got %T, expected *ast.BinaryExpr", src, x)
        }
 
+       // a valid type expression
+       src = "struct{x *int}"
+       x, err = ParseExpr(src)
+       if err != nil {
+               t.Fatalf("ParseExpr(%s): %v", src, err)
+       }
+       // sanity check
+       if _, ok := x.(*ast.StructType); !ok {
+               t.Errorf("ParseExpr(%s): got %T, expected *ast.StructType", src, x)
+       }
+
        // an invalid expression
        src = "a + *"
        _, err = ParseExpr(src)