Commit 2ba6ecb3 authored by Robert Griesemer's avatar Robert Griesemer

go/parser: ParseExpr must accept type expressions

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
parent b39fb1da
...@@ -84,6 +84,7 @@ var tests = []struct { ...@@ -84,6 +84,7 @@ var tests = []struct {
{"testdata/rewrite5.input", "-r=x+x->2*x"}, {"testdata/rewrite5.input", "-r=x+x->2*x"},
{"testdata/rewrite6.input", "-r=fun(x)->Fun(x)"}, {"testdata/rewrite6.input", "-r=fun(x)->Fun(x)"},
{"testdata/rewrite7.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/stdin*.input", "-stdin"},
{"testdata/comments.input", ""}, {"testdata/comments.input", ""},
{"testdata/import.input", ""}, {"testdata/import.input", ""},
......
...@@ -35,10 +35,10 @@ func initRewrite() { ...@@ -35,10 +35,10 @@ func initRewrite() {
// It might make sense to expand this to allow statement patterns, // It might make sense to expand this to allow statement patterns,
// but there are problems with preserving formatting and also // but there are problems with preserving formatting and also
// with what a wildcard for a statement looks like. // 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) x, err := parser.ParseExpr(s)
if err != nil { 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) os.Exit(2)
} }
return x return x
......
// 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
// 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{}
...@@ -162,16 +162,27 @@ func ParseDir(fset *token.FileSet, path string, filter func(os.FileInfo) bool, m ...@@ -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. // 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) { func ParseExpr(x string) (ast.Expr, error) {
// parse x within the context of a complete package for correct scopes; var p parser
// use //line directive for correct positions in error messages and put p.init(token.NewFileSet(), "", []byte(x), 0)
// x alone on a separate line (handles line comments), followed by a ';'
// to force an error if the expression is incomplete // Set up pkg-level scopes to avoid nil-pointer errors.
file, err := ParseFile(token.NewFileSet(), "", "package p;func _(){_=\n//line :1\n"+x+"\n;}", 0) // This is not needed for a correct expression x as the
if err != nil { // parser will be ok with a nil topScope, but be cautious
return nil, err // 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
} }
...@@ -68,7 +68,7 @@ func TestParseDir(t *testing.T) { ...@@ -68,7 +68,7 @@ func TestParseDir(t *testing.T) {
func TestParseExpr(t *testing.T) { func TestParseExpr(t *testing.T) {
// just kicking the tires: // just kicking the tires:
// a valid expression // a valid arithmetic expression
src := "a + b" src := "a + b"
x, err := ParseExpr(src) x, err := ParseExpr(src)
if err != nil { if err != nil {
...@@ -79,6 +79,17 @@ func TestParseExpr(t *testing.T) { ...@@ -79,6 +79,17 @@ func TestParseExpr(t *testing.T) {
t.Errorf("ParseExpr(%s): got %T, expected *ast.BinaryExpr", src, x) 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 // an invalid expression
src = "a + *" src = "a + *"
_, err = ParseExpr(src) _, err = ParseExpr(src)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment