Home | History | Annotate | Download | only in ast
      1 // Copyright 2012 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.
      4 
      5 // To avoid a cyclic dependency with go/parser, this file is in a separate package.
      6 
      7 package ast_test
      8 
      9 import (
     10 	"bytes"
     11 	"fmt"
     12 	. "go/ast"
     13 	"go/parser"
     14 	"go/token"
     15 	"sort"
     16 	"testing"
     17 )
     18 
     19 const src = `
     20 // the very first comment
     21 
     22 // package p
     23 package p /* the name is p */
     24 
     25 // imports
     26 import (
     27 	"bytes"     // bytes
     28 	"fmt"       // fmt
     29 	"go/ast"
     30 	"go/parser"
     31 )
     32 
     33 // T
     34 type T struct {
     35 	a, b, c int // associated with a, b, c
     36 	// associated with x, y
     37 	x, y float64    // float values
     38 	z    complex128 // complex value
     39 }
     40 // also associated with T
     41 
     42 // x
     43 var x = 0 // x = 0
     44 // also associated with x
     45 
     46 // f1
     47 func f1() {
     48 	/* associated with s1 */
     49 	s1()
     50 	// also associated with s1
     51 	
     52 	// associated with s2
     53 	
     54 	// also associated with s2
     55 	s2() // line comment for s2
     56 }
     57 // associated with f1
     58 // also associated with f1
     59 
     60 // associated with f2
     61 
     62 // f2
     63 func f2() {
     64 }
     65 
     66 func f3() {
     67 	i := 1 /* 1 */ + 2 // addition
     68 	_ = i
     69 }
     70 
     71 // the very last comment
     72 `
     73 
     74 // res maps a key of the form "line number: node type"
     75 // to the associated comments' text.
     76 //
     77 var res = map[string]string{
     78 	" 5: *ast.File":       "the very first comment\npackage p\n",
     79 	" 5: *ast.Ident":      " the name is p\n",
     80 	" 8: *ast.GenDecl":    "imports\n",
     81 	" 9: *ast.ImportSpec": "bytes\n",
     82 	"10: *ast.ImportSpec": "fmt\n",
     83 	"16: *ast.GenDecl":    "T\nalso associated with T\n",
     84 	"17: *ast.Field":      "associated with a, b, c\n",
     85 	"19: *ast.Field":      "associated with x, y\nfloat values\n",
     86 	"20: *ast.Field":      "complex value\n",
     87 	"25: *ast.GenDecl":    "x\nx = 0\nalso associated with x\n",
     88 	"29: *ast.FuncDecl":   "f1\nassociated with f1\nalso associated with f1\n",
     89 	"31: *ast.ExprStmt":   " associated with s1\nalso associated with s1\n",
     90 	"37: *ast.ExprStmt":   "associated with s2\nalso associated with s2\nline comment for s2\n",
     91 	"45: *ast.FuncDecl":   "associated with f2\nf2\n",
     92 	"49: *ast.AssignStmt": "addition\n",
     93 	"49: *ast.BasicLit":   " 1\n",
     94 	"50: *ast.Ident":      "the very last comment\n",
     95 }
     96 
     97 func ctext(list []*CommentGroup) string {
     98 	var buf bytes.Buffer
     99 	for _, g := range list {
    100 		buf.WriteString(g.Text())
    101 	}
    102 	return buf.String()
    103 }
    104 
    105 func TestCommentMap(t *testing.T) {
    106 	fset := token.NewFileSet()
    107 	f, err := parser.ParseFile(fset, "", src, parser.ParseComments)
    108 	if err != nil {
    109 		t.Fatal(err)
    110 	}
    111 	cmap := NewCommentMap(fset, f, f.Comments)
    112 
    113 	// very correct association of comments
    114 	for n, list := range cmap {
    115 		key := fmt.Sprintf("%2d: %T", fset.Position(n.Pos()).Line, n)
    116 		got := ctext(list)
    117 		want := res[key]
    118 		if got != want {
    119 			t.Errorf("%s: got %q; want %q", key, got, want)
    120 		}
    121 	}
    122 
    123 	// verify that no comments got lost
    124 	if n := len(cmap.Comments()); n != len(f.Comments) {
    125 		t.Errorf("got %d comment groups in map; want %d", n, len(f.Comments))
    126 	}
    127 
    128 	// support code to update test:
    129 	// set genMap to true to generate res map
    130 	const genMap = false
    131 	if genMap {
    132 		out := make([]string, 0, len(cmap))
    133 		for n, list := range cmap {
    134 			out = append(out, fmt.Sprintf("\t\"%2d: %T\":\t%q,", fset.Position(n.Pos()).Line, n, ctext(list)))
    135 		}
    136 		sort.Strings(out)
    137 		for _, s := range out {
    138 			fmt.Println(s)
    139 		}
    140 	}
    141 }
    142 
    143 // TODO(gri): add tests for Filter.
    144