| | |
| | |
| | |
| |
|
| | package syntax |
| |
|
| | import ( |
| | "fmt" |
| | "strings" |
| | "testing" |
| | ) |
| |
|
| | |
| | |
| | |
| | type test struct { |
| | nodetyp string |
| | snippet string |
| | } |
| |
|
| | var decls = []test{ |
| | |
| | |
| | |
| | {"ImportDecl", `import @"math"`}, |
| | {"ImportDecl", `import @mymath "math"`}, |
| | {"ImportDecl", `import @. "math"`}, |
| | {"ImportDecl", `import (@"math")`}, |
| | {"ImportDecl", `import (@mymath "math")`}, |
| | {"ImportDecl", `import (@. "math")`}, |
| |
|
| | {"ConstDecl", `const @x`}, |
| | {"ConstDecl", `const @x = 0`}, |
| | {"ConstDecl", `const @x, y, z = 0, 1, 2`}, |
| | {"ConstDecl", `const (@x)`}, |
| | {"ConstDecl", `const (@x = 0)`}, |
| | {"ConstDecl", `const (@x, y, z = 0, 1, 2)`}, |
| |
|
| | {"TypeDecl", `type @T int`}, |
| | {"TypeDecl", `type @T = int`}, |
| | {"TypeDecl", `type (@T int)`}, |
| | {"TypeDecl", `type (@T = int)`}, |
| |
|
| | {"VarDecl", `var @x int`}, |
| | {"VarDecl", `var @x, y, z int`}, |
| | {"VarDecl", `var @x int = 0`}, |
| | {"VarDecl", `var @x, y, z int = 1, 2, 3`}, |
| | {"VarDecl", `var @x = 0`}, |
| | {"VarDecl", `var @x, y, z = 1, 2, 3`}, |
| | {"VarDecl", `var (@x int)`}, |
| | {"VarDecl", `var (@x, y, z int)`}, |
| | {"VarDecl", `var (@x int = 0)`}, |
| | {"VarDecl", `var (@x, y, z int = 1, 2, 3)`}, |
| | {"VarDecl", `var (@x = 0)`}, |
| | {"VarDecl", `var (@x, y, z = 1, 2, 3)`}, |
| |
|
| | {"FuncDecl", `func @f() {}`}, |
| | {"FuncDecl", `func @(T) f() {}`}, |
| | {"FuncDecl", `func @(x T) f() {}`}, |
| | } |
| |
|
| | var exprs = []test{ |
| | |
| | |
| | |
| | {"Name", `@x`}, |
| |
|
| | {"BasicLit", `@0`}, |
| | {"BasicLit", `@0x123`}, |
| | {"BasicLit", `@3.1415`}, |
| | {"BasicLit", `@.2718`}, |
| | {"BasicLit", `@1i`}, |
| | {"BasicLit", `@'a'`}, |
| | {"BasicLit", `@"abc"`}, |
| | {"BasicLit", "@`abc`"}, |
| |
|
| | {"CompositeLit", `@{}`}, |
| | {"CompositeLit", `T@{}`}, |
| | {"CompositeLit", `struct{x, y int}@{}`}, |
| |
|
| | {"KeyValueExpr", `"foo"@: true`}, |
| | {"KeyValueExpr", `"a"@: b`}, |
| |
|
| | {"FuncLit", `@func (){}`}, |
| | {"ParenExpr", `@(x)`}, |
| | {"SelectorExpr", `a@.b`}, |
| | {"IndexExpr", `a@[i]`}, |
| |
|
| | {"SliceExpr", `a@[:]`}, |
| | {"SliceExpr", `a@[i:]`}, |
| | {"SliceExpr", `a@[:j]`}, |
| | {"SliceExpr", `a@[i:j]`}, |
| | {"SliceExpr", `a@[i:j:k]`}, |
| |
|
| | {"AssertExpr", `x@.(T)`}, |
| |
|
| | {"Operation", `@*b`}, |
| | {"Operation", `@+b`}, |
| | {"Operation", `@-b`}, |
| | {"Operation", `@!b`}, |
| | {"Operation", `@^b`}, |
| | {"Operation", `@&b`}, |
| | {"Operation", `@<-b`}, |
| |
|
| | {"Operation", `a @|| b`}, |
| | {"Operation", `a @&& b`}, |
| | {"Operation", `a @== b`}, |
| | {"Operation", `a @+ b`}, |
| | {"Operation", `a @* b`}, |
| |
|
| | {"CallExpr", `f@()`}, |
| | {"CallExpr", `f@(x, y, z)`}, |
| | {"CallExpr", `obj.f@(1, 2, 3)`}, |
| | {"CallExpr", `func(x int) int { return x + 1 }@(y)`}, |
| |
|
| | |
| | } |
| |
|
| | var types = []test{ |
| | {"Operation", `@*T`}, |
| | {"Operation", `@*struct{}`}, |
| |
|
| | {"ArrayType", `@[10]T`}, |
| | {"ArrayType", `@[...]T`}, |
| |
|
| | {"SliceType", `@[]T`}, |
| | {"DotsType", `@...T`}, |
| | {"StructType", `@struct{}`}, |
| | {"InterfaceType", `@interface{}`}, |
| | {"FuncType", `func@()`}, |
| | {"MapType", `@map[T]T`}, |
| |
|
| | {"ChanType", `@chan T`}, |
| | {"ChanType", `@chan<- T`}, |
| | {"ChanType", `@<-chan T`}, |
| | } |
| |
|
| | var fields = []test{ |
| | {"Field", `@T`}, |
| | {"Field", `@(T)`}, |
| | {"Field", `@x T`}, |
| | {"Field", `@x *(T)`}, |
| | {"Field", `@x, y, z T`}, |
| | {"Field", `@x, y, z (*T)`}, |
| | } |
| |
|
| | var stmts = []test{ |
| | {"EmptyStmt", `@`}, |
| |
|
| | {"LabeledStmt", `L@:`}, |
| | {"LabeledStmt", `L@: ;`}, |
| | {"LabeledStmt", `L@: f()`}, |
| |
|
| | {"BlockStmt", `@{}`}, |
| |
|
| | |
| | {"ExprStmt", `@<-ch`}, |
| | {"ExprStmt", `f@()`}, |
| | {"ExprStmt", `append@(s, 1, 2, 3)`}, |
| |
|
| | {"SendStmt", `ch @<- x`}, |
| |
|
| | {"DeclStmt", `@const x = 0`}, |
| | {"DeclStmt", `@const (x = 0)`}, |
| | {"DeclStmt", `@type T int`}, |
| | {"DeclStmt", `@type T = int`}, |
| | {"DeclStmt", `@type (T1 = int; T2 = float32)`}, |
| | {"DeclStmt", `@var x = 0`}, |
| | {"DeclStmt", `@var x, y, z int`}, |
| | {"DeclStmt", `@var (a, b = 1, 2)`}, |
| |
|
| | {"AssignStmt", `x @= y`}, |
| | {"AssignStmt", `a, b, x @= 1, 2, 3`}, |
| | {"AssignStmt", `x @+= y`}, |
| | {"AssignStmt", `x @:= y`}, |
| | {"AssignStmt", `x, ok @:= f()`}, |
| | {"AssignStmt", `x@++`}, |
| | {"AssignStmt", `a[i]@--`}, |
| |
|
| | {"BranchStmt", `@break`}, |
| | {"BranchStmt", `@break L`}, |
| | {"BranchStmt", `@continue`}, |
| | {"BranchStmt", `@continue L`}, |
| | {"BranchStmt", `@fallthrough`}, |
| | {"BranchStmt", `@goto L`}, |
| |
|
| | {"CallStmt", `@defer f()`}, |
| | {"CallStmt", `@go f()`}, |
| |
|
| | {"ReturnStmt", `@return`}, |
| | {"ReturnStmt", `@return x`}, |
| | {"ReturnStmt", `@return a, b, a + b*f(1, 2, 3)`}, |
| |
|
| | {"IfStmt", `@if cond {}`}, |
| | {"IfStmt", `@if cond { f() } else {}`}, |
| | {"IfStmt", `@if cond { f() } else { g(); h() }`}, |
| | {"ForStmt", `@for {}`}, |
| | {"ForStmt", `@for { f() }`}, |
| | {"SwitchStmt", `@switch {}`}, |
| | {"SwitchStmt", `@switch { default: }`}, |
| | {"SwitchStmt", `@switch { default: x++ }`}, |
| | {"SelectStmt", `@select {}`}, |
| | {"SelectStmt", `@select { default: }`}, |
| | {"SelectStmt", `@select { default: ch <- false }`}, |
| | } |
| |
|
| | var ranges = []test{ |
| | {"RangeClause", `@range s`}, |
| | {"RangeClause", `i = @range s`}, |
| | {"RangeClause", `i := @range s`}, |
| | {"RangeClause", `_, x = @range s`}, |
| | {"RangeClause", `i, x = @range s`}, |
| | {"RangeClause", `_, x := @range s.f`}, |
| | {"RangeClause", `i, x := @range f(i)`}, |
| | } |
| |
|
| | var guards = []test{ |
| | {"TypeSwitchGuard", `x@.(type)`}, |
| | {"TypeSwitchGuard", `x := x@.(type)`}, |
| | } |
| |
|
| | var cases = []test{ |
| | {"CaseClause", `@case x:`}, |
| | {"CaseClause", `@case x, y, z:`}, |
| | {"CaseClause", `@case x == 1, y == 2:`}, |
| | {"CaseClause", `@default:`}, |
| | } |
| |
|
| | var comms = []test{ |
| | {"CommClause", `@case <-ch:`}, |
| | {"CommClause", `@case x <- ch:`}, |
| | {"CommClause", `@case x = <-ch:`}, |
| | {"CommClause", `@case x := <-ch:`}, |
| | {"CommClause", `@case x, ok = <-ch: f(1, 2, 3)`}, |
| | {"CommClause", `@case x, ok := <-ch: x++`}, |
| | {"CommClause", `@default:`}, |
| | {"CommClause", `@default: ch <- true`}, |
| | } |
| |
|
| | func TestPos(t *testing.T) { |
| | |
| | |
| | |
| |
|
| | testPos(t, decls, "package p; ", "", |
| | func(f *File) Node { return f.DeclList[0] }, |
| | ) |
| |
|
| | |
| | testPos(t, exprs, "package p; var _ = T{ ", " }", |
| | func(f *File) Node { return f.DeclList[0].(*VarDecl).Values.(*CompositeLit).ElemList[0] }, |
| | ) |
| |
|
| | |
| | testPos(t, types, "package p; func f(", ")", |
| | func(f *File) Node { return f.DeclList[0].(*FuncDecl).Type.ParamList[0].Type }, |
| | ) |
| |
|
| | testPos(t, fields, "package p; func f(", ")", |
| | func(f *File) Node { return f.DeclList[0].(*FuncDecl).Type.ParamList[0] }, |
| | ) |
| |
|
| | testPos(t, stmts, "package p; func _() { ", "; }", |
| | func(f *File) Node { return f.DeclList[0].(*FuncDecl).Body.List[0] }, |
| | ) |
| |
|
| | testPos(t, ranges, "package p; func _() { for ", " {} }", |
| | func(f *File) Node { return f.DeclList[0].(*FuncDecl).Body.List[0].(*ForStmt).Init.(*RangeClause) }, |
| | ) |
| |
|
| | testPos(t, guards, "package p; func _() { switch ", " {} }", |
| | func(f *File) Node { return f.DeclList[0].(*FuncDecl).Body.List[0].(*SwitchStmt).Tag.(*TypeSwitchGuard) }, |
| | ) |
| |
|
| | testPos(t, cases, "package p; func _() { switch { ", " } }", |
| | func(f *File) Node { return f.DeclList[0].(*FuncDecl).Body.List[0].(*SwitchStmt).Body[0] }, |
| | ) |
| |
|
| | testPos(t, comms, "package p; func _() { select { ", " } }", |
| | func(f *File) Node { return f.DeclList[0].(*FuncDecl).Body.List[0].(*SelectStmt).Body[0] }, |
| | ) |
| | } |
| |
|
| | func testPos(t *testing.T, list []test, prefix, suffix string, extract func(*File) Node) { |
| | for _, test := range list { |
| | |
| | src, index := stripAt(prefix + test.snippet + suffix) |
| | if index < 0 { |
| | t.Errorf("missing @: %s (%s)", src, test.nodetyp) |
| | continue |
| | } |
| |
|
| | |
| | file, err := Parse(nil, strings.NewReader(src), nil, nil, 0) |
| | if err != nil { |
| | t.Errorf("parse error: %s: %v (%s)", src, err, test.nodetyp) |
| | continue |
| | } |
| |
|
| | |
| | node := extract(file) |
| | if typ := typeOf(node); typ != test.nodetyp { |
| | t.Errorf("type error: %s: type = %s, want %s", src, typ, test.nodetyp) |
| | continue |
| | } |
| |
|
| | |
| | if pos := int(node.Pos().Col()); pos != index+colbase { |
| | t.Errorf("pos error: %s: pos = %d, want %d (%s)", src, pos, index+colbase, test.nodetyp) |
| | continue |
| | } |
| | } |
| | } |
| |
|
| | func stripAt(s string) (string, int) { |
| | if i := strings.Index(s, "@"); i >= 0 { |
| | return s[:i] + s[i+1:], i |
| | } |
| | return s, -1 |
| | } |
| |
|
| | func typeOf(n Node) string { |
| | const prefix = "*syntax." |
| | k := fmt.Sprintf("%T", n) |
| | return strings.TrimPrefix(k, prefix) |
| | } |
| |
|