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 {
{"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", ""},
......
......@@ -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
......
// 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
}
// 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
}
......@@ -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)
......
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