1 // Copyright 2009 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
17 var fset
= token
.NewFileSet()
19 var validFiles
= []string{
26 func TestParse(t
*testing
.T
) {
27 for _
, filename
:= range validFiles
{
28 _
, err
:= ParseFile(fset
, filename
, nil, DeclarationErrors
)
30 t
.Fatalf("ParseFile(%s): %v", filename
, err
)
35 func nameFilter(filename
string) bool {
37 case "parser.go", "interface.go", "parser_test.go":
39 case "parser.go.orig":
40 return true // permit but should be ignored by ParseDir
45 func dirFilter(f os
.FileInfo
) bool { return nameFilter(f
.Name()) }
47 func TestParseDir(t
*testing
.T
) {
49 pkgs
, err
:= ParseDir(fset
, path
, dirFilter
, 0)
51 t
.Fatalf("ParseDir(%s): %v", path
, err
)
53 if n
:= len(pkgs
); n
!= 1 {
54 t
.Errorf("got %d packages; want 1", n
)
58 t
.Errorf(`package "parser" not found`)
61 if n
:= len(pkg
.Files
); n
!= 3 {
62 t
.Errorf("got %d package files; want 3", n
)
64 for filename
:= range pkg
.Files
{
65 if !nameFilter(filename
) {
66 t
.Errorf("unexpected package file: %s", filename
)
71 func TestParseExpr(t
*testing
.T
) {
72 // just kicking the tires:
73 // a valid arithmetic expression
75 x
, err
:= ParseExpr(src
)
77 t
.Fatalf("ParseExpr(%s): %v", src
, err
)
80 if _
, ok
:= x
.(*ast
.BinaryExpr
); !ok
{
81 t
.Errorf("ParseExpr(%s): got %T, want *ast.BinaryExpr", src
, x
)
84 // a valid type expression
85 src
= "struct{x *int}"
86 x
, err
= ParseExpr(src
)
88 t
.Fatalf("ParseExpr(%s): %v", src
, err
)
91 if _
, ok
:= x
.(*ast
.StructType
); !ok
{
92 t
.Errorf("ParseExpr(%s): got %T, want *ast.StructType", src
, x
)
95 // an invalid expression
97 _
, err
= ParseExpr(src
)
99 t
.Fatalf("ParseExpr(%s): got no error", src
)
102 // a valid expression followed by extra tokens is invalid
104 _
, err
= ParseExpr(src
)
106 t
.Fatalf("ParseExpr(%s): got no error", src
)
109 // ParseExpr must not crash
110 for _
, src
:= range valids
{
115 func TestColonEqualsScope(t
*testing
.T
) {
116 f
, err
:= ParseFile(fset
, "", `package p; func f() { x, y, z := x, y, z }`, 0)
121 // RHS refers to undefined globals; LHS does not.
122 as
:= f
.Decls
[0].(*ast
.FuncDecl
).Body
.List
[0].(*ast
.AssignStmt
)
123 for _
, v
:= range as
.Rhs
{
126 t
.Errorf("rhs %s has Obj, should not", id
.Name
)
129 for _
, v
:= range as
.Lhs
{
132 t
.Errorf("lhs %s does not have Obj, should", id
.Name
)
137 func TestVarScope(t
*testing
.T
) {
138 f
, err
:= ParseFile(fset
, "", `package p; func f() { var x, y, z = x, y, z }`, 0)
143 // RHS refers to undefined globals; LHS does not.
144 as
:= f
.Decls
[0].(*ast
.FuncDecl
).Body
.List
[0].(*ast
.DeclStmt
).Decl
.(*ast
.GenDecl
).Specs
[0].(*ast
.ValueSpec
)
145 for _
, v
:= range as
.Values
{
148 t
.Errorf("rhs %s has Obj, should not", id
.Name
)
151 for _
, id
:= range as
.Names
{
153 t
.Errorf("lhs %s does not have Obj, should", id
.Name
)
158 func TestObjects(t
*testing
.T
) {
168 f
, err
:= ParseFile(fset
, "", src
, 0)
173 objects
:= map[string]ast
.ObjKind
{
174 "p": ast
.Bad
, // not in a scope
175 "fmt": ast
.Bad
, // not resolved yet
179 "int": ast
.Bad
, // not resolved yet
184 ast
.Inspect(f
, func(n ast
.Node
) bool {
185 if ident
, ok
:= n
.(*ast
.Ident
); ok
{
188 if objects
[ident
.Name
] != ast
.Bad
{
189 t
.Errorf("no object for %s", ident
.Name
)
193 if obj
.Name
!= ident
.Name
{
194 t
.Errorf("names don't match: obj.Name = %s, ident.Name = %s", obj
.Name
, ident
.Name
)
196 kind
:= objects
[ident
.Name
]
197 if obj
.Kind
!= kind
{
198 t
.Errorf("%s: obj.Kind = %s; want %s", ident
.Name
, obj
.Kind
, kind
)
205 func TestUnresolved(t
*testing
.T
) {
206 f
, err
:= ParseFile(fset
, "", `
210 func f2a(byte, int, float)
211 func f3a(a, b int, c float)
213 func f5a(a s1a, b ...complex)
216 func f2b([]byte, (int), *float)
217 func f3b(a, b *int, c []float)
218 func f4b(...*complex)
219 func f5b(a s1a, b ...[]complex)
221 type s1a struct { int }
222 type s2a struct { byte; int; s1a }
223 type s3a struct { a, b int; c float }
225 type s1b struct { *int }
226 type s2b struct { byte; int; *float }
227 type s3b struct { a, b *s3b; c []float }
233 want
:= "int " + // f1a
234 "byte int float " + // f2a
235 "int float " + // f3a
240 "byte int float " + // f2b
241 "int float " + // f3b
247 "int float " + // s3a
250 "byte int float " + // s2a
253 // collect unresolved identifiers
255 for _
, u
:= range f
.Unresolved
{
256 buf
.WriteString(u
.Name
)
262 t
.Errorf("\ngot: %s\nwant: %s", got
, want
)
266 var imports
= map[string]bool{
275 // Each of these pairs tests both `` vs "" strings
276 // and also use of invalid characters spelled out as
277 // escape sequences and written directly.
278 // For example `"\x00"` tests import "\x00"
279 // while "`\x00`" tests import `<actual-NUL-byte>`.
298 func TestImports(t
*testing
.T
) {
299 for path
, isValid
:= range imports
{
300 src
:= fmt
.Sprintf("package p; import %s", path
)
301 _
, err
:= ParseFile(fset
, "", src
, 0)
303 case err
!= nil && isValid
:
304 t
.Errorf("ParseFile(%s): got %v; expected no error", src
, err
)
305 case err
== nil && !isValid
:
306 t
.Errorf("ParseFile(%s): got no error; expected one", src
)
311 func TestCommentGroups(t
*testing
.T
) {
312 f
, err
:= ParseFile(fset
, "", `
313 package p /* 1a */ /* 1b */ /* 1c */ // 1d
319 /* 3c */ const e = 2.7182
321 // Example from issue 3139
322 func ExampleCount() {
323 fmt.Println(strings.Count("cheese", "e"))
324 fmt.Println(strings.Count("five", "")) // before & after each rune
333 expected
:= [][]string{
334 {"/* 1a */", "/* 1b */", "/* 1c */", "// 1d"},
335 {"/* 2a\n*/", "// 2b"},
336 {"/* 3a */", "// 3b", "/* 3c */"},
337 {"// Example from issue 3139"},
338 {"// before & after each rune"},
339 {"// Output:", "// 3", "// 5"},
341 if len(f
.Comments
) != len(expected
) {
342 t
.Fatalf("got %d comment groups; expected %d", len(f
.Comments
), len(expected
))
344 for i
, exp
:= range expected
{
345 got
:= f
.Comments
[i
].List
346 if len(got
) != len(exp
) {
347 t
.Errorf("got %d comments in group %d; expected %d", len(got
), i
, len(exp
))
350 for j
, exp
:= range exp
{
353 t
.Errorf("got %q in group %d; expected %q", got
, i
, exp
)
359 func getField(file
*ast
.File
, fieldname
string) *ast
.Field
{
360 parts
:= strings
.Split(fieldname
, ".")
361 for _
, d
:= range file
.Decls
{
362 if d
, ok
:= d
.(*ast
.GenDecl
); ok
&& d
.Tok
== token
.TYPE
{
363 for _
, s
:= range d
.Specs
{
364 if s
, ok
:= s
.(*ast
.TypeSpec
); ok
&& s
.Name
.Name
== parts
[0] {
365 if s
, ok
:= s
.Type
.(*ast
.StructType
); ok
{
366 for _
, f
:= range s
.Fields
.List
{
367 for _
, name
:= range f
.Names
{
368 if name
.Name
== parts
[1] {
381 // Don't use ast.CommentGroup.Text() - we want to see exact comment text.
382 func commentText(c
*ast
.CommentGroup
) string {
385 for _
, c
:= range c
.List
{
386 buf
.WriteString(c
.Text
)
392 func checkFieldComments(t
*testing
.T
, file
*ast
.File
, fieldname
, lead
, line
string) {
393 f
:= getField(file
, fieldname
)
395 t
.Fatalf("field not found: %s", fieldname
)
397 if got
:= commentText(f
.Doc
); got
!= lead
{
398 t
.Errorf("got lead comment %q; expected %q", got
, lead
)
400 if got
:= commentText(f
.Comment
); got
!= line
{
401 t
.Errorf("got line comment %q; expected %q", got
, line
)
405 func TestLeadAndLineComments(t
*testing
.T
) {
406 f
, err
:= ParseFile(fset
, "", `
409 /* F1 lead comment */
411 F1 int /* F1 */ // line comment
414 F2 int // F2 line comment
416 f3 int // f3 line comment
422 checkFieldComments(t
, f
, "T.F1", "/* F1 lead comment *///", "/* F1 */// line comment")
423 checkFieldComments(t
, f
, "T.F2", "// F2 lead// comment", "// F2 line comment")
424 checkFieldComments(t
, f
, "T.f3", "// f3 lead comment", "// f3 line comment")
426 checkFieldComments(t
, f
, "T.F1", "/* F1 lead comment *///", "/* F1 */// line comment")
427 checkFieldComments(t
, f
, "T.F2", "// F2 lead// comment", "// F2 line comment")
428 if getField(f
, "T.f3") != nil {
429 t
.Error("not expected to find T.f3")