| // Copyright 2012 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. |
| |
| // To avoid a cyclic dependency with go/parser, this file is in a separate package. |
| |
| package ast_test |
| |
| import ( |
| "bytes" |
| "fmt" |
| . "go/ast" |
| "go/parser" |
| "go/token" |
| "sort" |
| "testing" |
| ) |
| |
| const src = ` |
| // the very first comment |
| |
| // package p |
| package p /* the name is p */ |
| |
| // imports |
| import ( |
| "bytes" // bytes |
| "fmt" // fmt |
| "go/ast" |
| "go/parser" |
| ) |
| |
| // T |
| type T struct { |
| a, b, c int // associated with a, b, c |
| // associated with x, y |
| x, y float64 // float values |
| z complex128 // complex value |
| } |
| // also associated with T |
| |
| // x |
| var x = 0 // x = 0 |
| // also associated with x |
| |
| // f1 |
| func f1() { |
| /* associated with s1 */ |
| s1() |
| // also associated with s1 |
| |
| // associated with s2 |
| |
| // also associated with s2 |
| s2() // line comment for s2 |
| } |
| // associated with f1 |
| // also associated with f1 |
| |
| // associated with f2 |
| |
| // f2 |
| func f2() { |
| } |
| |
| func f3() { |
| i := 1 /* 1 */ + 2 // addition |
| _ = i |
| } |
| |
| // the very last comment |
| ` |
| |
| // res maps a key of the form "line number: node type" |
| // to the associated comments' text. |
| // |
| var res = map[string]string{ |
| " 5: *ast.File": "the very first comment\npackage p\n", |
| " 5: *ast.Ident": " the name is p\n", |
| " 8: *ast.GenDecl": "imports\n", |
| " 9: *ast.ImportSpec": "bytes\n", |
| "10: *ast.ImportSpec": "fmt\n", |
| "16: *ast.GenDecl": "T\nalso associated with T\n", |
| "17: *ast.Field": "associated with a, b, c\n", |
| "19: *ast.Field": "associated with x, y\nfloat values\n", |
| "20: *ast.Field": "complex value\n", |
| "25: *ast.GenDecl": "x\nx = 0\nalso associated with x\n", |
| "29: *ast.FuncDecl": "f1\nassociated with f1\nalso associated with f1\n", |
| "31: *ast.ExprStmt": " associated with s1\nalso associated with s1\n", |
| "37: *ast.ExprStmt": "associated with s2\nalso associated with s2\nline comment for s2\n", |
| "45: *ast.FuncDecl": "associated with f2\nf2\n", |
| "49: *ast.AssignStmt": "addition\n", |
| "49: *ast.BasicLit": " 1\n", |
| "50: *ast.Ident": "the very last comment\n", |
| } |
| |
| func ctext(list []*CommentGroup) string { |
| var buf bytes.Buffer |
| for _, g := range list { |
| buf.WriteString(g.Text()) |
| } |
| return buf.String() |
| } |
| |
| func TestCommentMap(t *testing.T) { |
| fset := token.NewFileSet() |
| f, err := parser.ParseFile(fset, "", src, parser.ParseComments) |
| if err != nil { |
| t.Fatal(err) |
| } |
| cmap := NewCommentMap(fset, f, f.Comments) |
| |
| // very correct association of comments |
| for n, list := range cmap { |
| key := fmt.Sprintf("%2d: %T", fset.Position(n.Pos()).Line, n) |
| got := ctext(list) |
| want := res[key] |
| if got != want { |
| t.Errorf("%s: got %q; want %q", key, got, want) |
| } |
| } |
| |
| // verify that no comments got lost |
| if n := len(cmap.Comments()); n != len(f.Comments) { |
| t.Errorf("got %d comment groups in map; want %d", n, len(f.Comments)) |
| } |
| |
| // support code to update test: |
| // set genMap to true to generate res map |
| const genMap = false |
| if genMap { |
| out := make([]string, 0, len(cmap)) |
| for n, list := range cmap { |
| out = append(out, fmt.Sprintf("\t\"%2d: %T\":\t%q,", fset.Position(n.Pos()).Line, n, ctext(list))) |
| } |
| sort.Strings(out) |
| for _, s := range out { |
| fmt.Println(s) |
| } |
| } |
| } |
| |
| func TestFilter(t *testing.T) { |
| fset := token.NewFileSet() |
| f, err := parser.ParseFile(fset, "", src, parser.ParseComments) |
| if err != nil { |
| t.Fatal(err) |
| } |
| cmap := NewCommentMap(fset, f, f.Comments) |
| |
| // delete variable declaration |
| for i, decl := range f.Decls { |
| if gen, ok := decl.(*GenDecl); ok && gen.Tok == token.VAR { |
| copy(f.Decls[i:], f.Decls[i+1:]) |
| f.Decls = f.Decls[:len(f.Decls)-1] |
| break |
| } |
| } |
| |
| // check if comments are filtered correctly |
| cc := cmap.Filter(f) |
| for n, list := range cc { |
| key := fmt.Sprintf("%2d: %T", fset.Position(n.Pos()).Line, n) |
| got := ctext(list) |
| want := res[key] |
| if key == "25: *ast.GenDecl" || got != want { |
| t.Errorf("%s: got %q; want %q", key, got, want) |
| } |
| } |
| } |