]> Cypherpunks.ru repositories - gostls13.git/blob - src/go/ast/example_test.go
c6904be6e553e6f10be14646021484692c3d23f7
[gostls13.git] / src / go / ast / example_test.go
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 package ast_test
6
7 import (
8         "fmt"
9         "go/ast"
10         "go/format"
11         "go/parser"
12         "go/token"
13         "strings"
14 )
15
16 // This example demonstrates how to inspect the AST of a Go program.
17 func ExampleInspect() {
18         // src is the input for which we want to inspect the AST.
19         src := `
20 package p
21 const c = 1.0
22 var X = f(3.14)*2 + c
23 `
24
25         // Create the AST by parsing src.
26         fset := token.NewFileSet() // positions are relative to fset
27         f, err := parser.ParseFile(fset, "src.go", src, 0)
28         if err != nil {
29                 panic(err)
30         }
31
32         // Inspect the AST and print all identifiers and literals.
33         ast.Inspect(f, func(n ast.Node) bool {
34                 var s string
35                 switch x := n.(type) {
36                 case *ast.BasicLit:
37                         s = x.Value
38                 case *ast.Ident:
39                         s = x.Name
40                 }
41                 if s != "" {
42                         fmt.Printf("%s:\t%s\n", fset.Position(n.Pos()), s)
43                 }
44                 return true
45         })
46
47         // Output:
48         // src.go:2:9:  p
49         // src.go:3:7:  c
50         // src.go:3:11: 1.0
51         // src.go:4:5:  X
52         // src.go:4:9:  f
53         // src.go:4:11: 3.14
54         // src.go:4:17: 2
55         // src.go:4:21: c
56 }
57
58 // This example shows what an AST looks like when printed for debugging.
59 func ExamplePrint() {
60         // src is the input for which we want to print the AST.
61         src := `
62 package main
63 func main() {
64         println("Hello, World!")
65 }
66 `
67
68         // Create the AST by parsing src.
69         fset := token.NewFileSet() // positions are relative to fset
70         f, err := parser.ParseFile(fset, "", src, 0)
71         if err != nil {
72                 panic(err)
73         }
74
75         // Print the AST.
76         ast.Print(fset, f)
77
78         // Output:
79         //      0  *ast.File {
80         //      1  .  Package: 2:1
81         //      2  .  Name: *ast.Ident {
82         //      3  .  .  NamePos: 2:9
83         //      4  .  .  Name: "main"
84         //      5  .  }
85         //      6  .  Decls: []ast.Decl (len = 1) {
86         //      7  .  .  0: *ast.FuncDecl {
87         //      8  .  .  .  Name: *ast.Ident {
88         //      9  .  .  .  .  NamePos: 3:6
89         //     10  .  .  .  .  Name: "main"
90         //     11  .  .  .  .  Obj: *ast.Object {
91         //     12  .  .  .  .  .  Kind: func
92         //     13  .  .  .  .  .  Name: "main"
93         //     14  .  .  .  .  .  Decl: *(obj @ 7)
94         //     15  .  .  .  .  }
95         //     16  .  .  .  }
96         //     17  .  .  .  Type: *ast.FuncType {
97         //     18  .  .  .  .  Func: 3:1
98         //     19  .  .  .  .  Params: *ast.FieldList {
99         //     20  .  .  .  .  .  Opening: 3:10
100         //     21  .  .  .  .  .  Closing: 3:11
101         //     22  .  .  .  .  }
102         //     23  .  .  .  }
103         //     24  .  .  .  Body: *ast.BlockStmt {
104         //     25  .  .  .  .  Lbrace: 3:13
105         //     26  .  .  .  .  List: []ast.Stmt (len = 1) {
106         //     27  .  .  .  .  .  0: *ast.ExprStmt {
107         //     28  .  .  .  .  .  .  X: *ast.CallExpr {
108         //     29  .  .  .  .  .  .  .  Fun: *ast.Ident {
109         //     30  .  .  .  .  .  .  .  .  NamePos: 4:2
110         //     31  .  .  .  .  .  .  .  .  Name: "println"
111         //     32  .  .  .  .  .  .  .  }
112         //     33  .  .  .  .  .  .  .  Lparen: 4:9
113         //     34  .  .  .  .  .  .  .  Args: []ast.Expr (len = 1) {
114         //     35  .  .  .  .  .  .  .  .  0: *ast.BasicLit {
115         //     36  .  .  .  .  .  .  .  .  .  ValuePos: 4:10
116         //     37  .  .  .  .  .  .  .  .  .  Kind: STRING
117         //     38  .  .  .  .  .  .  .  .  .  Value: "\"Hello, World!\""
118         //     39  .  .  .  .  .  .  .  .  }
119         //     40  .  .  .  .  .  .  .  }
120         //     41  .  .  .  .  .  .  .  Ellipsis: -
121         //     42  .  .  .  .  .  .  .  Rparen: 4:25
122         //     43  .  .  .  .  .  .  }
123         //     44  .  .  .  .  .  }
124         //     45  .  .  .  .  }
125         //     46  .  .  .  .  Rbrace: 5:1
126         //     47  .  .  .  }
127         //     48  .  .  }
128         //     49  .  }
129         //     50  .  FileStart: 1:1
130         //     51  .  FileEnd: 5:3
131         //     52  .  Scope: *ast.Scope {
132         //     53  .  .  Objects: map[string]*ast.Object (len = 1) {
133         //     54  .  .  .  "main": *(obj @ 11)
134         //     55  .  .  }
135         //     56  .  }
136         //     57  .  Unresolved: []*ast.Ident (len = 1) {
137         //     58  .  .  0: *(obj @ 29)
138         //     59  .  }
139         //     60  }
140 }
141
142 // This example illustrates how to remove a variable declaration
143 // in a Go program while maintaining correct comment association
144 // using an ast.CommentMap.
145 func ExampleCommentMap() {
146         // src is the input for which we create the AST that we
147         // are going to manipulate.
148         src := `
149 // This is the package comment.
150 package main
151
152 // This comment is associated with the hello constant.
153 const hello = "Hello, World!" // line comment 1
154
155 // This comment is associated with the foo variable.
156 var foo = hello // line comment 2
157
158 // This comment is associated with the main function.
159 func main() {
160         fmt.Println(hello) // line comment 3
161 }
162 `
163
164         // Create the AST by parsing src.
165         fset := token.NewFileSet() // positions are relative to fset
166         f, err := parser.ParseFile(fset, "src.go", src, parser.ParseComments)
167         if err != nil {
168                 panic(err)
169         }
170
171         // Create an ast.CommentMap from the ast.File's comments.
172         // This helps keeping the association between comments
173         // and AST nodes.
174         cmap := ast.NewCommentMap(fset, f, f.Comments)
175
176         // Remove the first variable declaration from the list of declarations.
177         for i, decl := range f.Decls {
178                 if gen, ok := decl.(*ast.GenDecl); ok && gen.Tok == token.VAR {
179                         copy(f.Decls[i:], f.Decls[i+1:])
180                         f.Decls = f.Decls[:len(f.Decls)-1]
181                         break
182                 }
183         }
184
185         // Use the comment map to filter comments that don't belong anymore
186         // (the comments associated with the variable declaration), and create
187         // the new comments list.
188         f.Comments = cmap.Filter(f).Comments()
189
190         // Print the modified AST.
191         var buf strings.Builder
192         if err := format.Node(&buf, fset, f); err != nil {
193                 panic(err)
194         }
195         fmt.Printf("%s", buf.String())
196
197         // Output:
198         // // This is the package comment.
199         // package main
200         //
201         // // This comment is associated with the hello constant.
202         // const hello = "Hello, World!" // line comment 1
203         //
204         // // This comment is associated with the main function.
205         // func main() {
206         //      fmt.Println(hello) // line comment 3
207         // }
208 }