diff options
Diffstat (limited to '')
-rw-r--r-- | src/go/ast/example_test.go | 208 |
1 files changed, 208 insertions, 0 deletions
diff --git a/src/go/ast/example_test.go b/src/go/ast/example_test.go new file mode 100644 index 0000000..c6904be --- /dev/null +++ b/src/go/ast/example_test.go @@ -0,0 +1,208 @@ +// 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. + +package ast_test + +import ( + "fmt" + "go/ast" + "go/format" + "go/parser" + "go/token" + "strings" +) + +// This example demonstrates how to inspect the AST of a Go program. +func ExampleInspect() { + // src is the input for which we want to inspect the AST. + src := ` +package p +const c = 1.0 +var X = f(3.14)*2 + c +` + + // Create the AST by parsing src. + fset := token.NewFileSet() // positions are relative to fset + f, err := parser.ParseFile(fset, "src.go", src, 0) + if err != nil { + panic(err) + } + + // Inspect the AST and print all identifiers and literals. + ast.Inspect(f, func(n ast.Node) bool { + var s string + switch x := n.(type) { + case *ast.BasicLit: + s = x.Value + case *ast.Ident: + s = x.Name + } + if s != "" { + fmt.Printf("%s:\t%s\n", fset.Position(n.Pos()), s) + } + return true + }) + + // Output: + // src.go:2:9: p + // src.go:3:7: c + // src.go:3:11: 1.0 + // src.go:4:5: X + // src.go:4:9: f + // src.go:4:11: 3.14 + // src.go:4:17: 2 + // src.go:4:21: c +} + +// This example shows what an AST looks like when printed for debugging. +func ExamplePrint() { + // src is the input for which we want to print the AST. + src := ` +package main +func main() { + println("Hello, World!") +} +` + + // Create the AST by parsing src. + fset := token.NewFileSet() // positions are relative to fset + f, err := parser.ParseFile(fset, "", src, 0) + if err != nil { + panic(err) + } + + // Print the AST. + ast.Print(fset, f) + + // Output: + // 0 *ast.File { + // 1 . Package: 2:1 + // 2 . Name: *ast.Ident { + // 3 . . NamePos: 2:9 + // 4 . . Name: "main" + // 5 . } + // 6 . Decls: []ast.Decl (len = 1) { + // 7 . . 0: *ast.FuncDecl { + // 8 . . . Name: *ast.Ident { + // 9 . . . . NamePos: 3:6 + // 10 . . . . Name: "main" + // 11 . . . . Obj: *ast.Object { + // 12 . . . . . Kind: func + // 13 . . . . . Name: "main" + // 14 . . . . . Decl: *(obj @ 7) + // 15 . . . . } + // 16 . . . } + // 17 . . . Type: *ast.FuncType { + // 18 . . . . Func: 3:1 + // 19 . . . . Params: *ast.FieldList { + // 20 . . . . . Opening: 3:10 + // 21 . . . . . Closing: 3:11 + // 22 . . . . } + // 23 . . . } + // 24 . . . Body: *ast.BlockStmt { + // 25 . . . . Lbrace: 3:13 + // 26 . . . . List: []ast.Stmt (len = 1) { + // 27 . . . . . 0: *ast.ExprStmt { + // 28 . . . . . . X: *ast.CallExpr { + // 29 . . . . . . . Fun: *ast.Ident { + // 30 . . . . . . . . NamePos: 4:2 + // 31 . . . . . . . . Name: "println" + // 32 . . . . . . . } + // 33 . . . . . . . Lparen: 4:9 + // 34 . . . . . . . Args: []ast.Expr (len = 1) { + // 35 . . . . . . . . 0: *ast.BasicLit { + // 36 . . . . . . . . . ValuePos: 4:10 + // 37 . . . . . . . . . Kind: STRING + // 38 . . . . . . . . . Value: "\"Hello, World!\"" + // 39 . . . . . . . . } + // 40 . . . . . . . } + // 41 . . . . . . . Ellipsis: - + // 42 . . . . . . . Rparen: 4:25 + // 43 . . . . . . } + // 44 . . . . . } + // 45 . . . . } + // 46 . . . . Rbrace: 5:1 + // 47 . . . } + // 48 . . } + // 49 . } + // 50 . FileStart: 1:1 + // 51 . FileEnd: 5:3 + // 52 . Scope: *ast.Scope { + // 53 . . Objects: map[string]*ast.Object (len = 1) { + // 54 . . . "main": *(obj @ 11) + // 55 . . } + // 56 . } + // 57 . Unresolved: []*ast.Ident (len = 1) { + // 58 . . 0: *(obj @ 29) + // 59 . } + // 60 } +} + +// This example illustrates how to remove a variable declaration +// in a Go program while maintaining correct comment association +// using an ast.CommentMap. +func ExampleCommentMap() { + // src is the input for which we create the AST that we + // are going to manipulate. + src := ` +// This is the package comment. +package main + +// This comment is associated with the hello constant. +const hello = "Hello, World!" // line comment 1 + +// This comment is associated with the foo variable. +var foo = hello // line comment 2 + +// This comment is associated with the main function. +func main() { + fmt.Println(hello) // line comment 3 +} +` + + // Create the AST by parsing src. + fset := token.NewFileSet() // positions are relative to fset + f, err := parser.ParseFile(fset, "src.go", src, parser.ParseComments) + if err != nil { + panic(err) + } + + // Create an ast.CommentMap from the ast.File's comments. + // This helps keeping the association between comments + // and AST nodes. + cmap := ast.NewCommentMap(fset, f, f.Comments) + + // Remove the first variable declaration from the list of declarations. + for i, decl := range f.Decls { + if gen, ok := decl.(*ast.GenDecl); ok && gen.Tok == token.VAR { + copy(f.Decls[i:], f.Decls[i+1:]) + f.Decls = f.Decls[:len(f.Decls)-1] + break + } + } + + // Use the comment map to filter comments that don't belong anymore + // (the comments associated with the variable declaration), and create + // the new comments list. + f.Comments = cmap.Filter(f).Comments() + + // Print the modified AST. + var buf strings.Builder + if err := format.Node(&buf, fset, f); err != nil { + panic(err) + } + fmt.Printf("%s", buf.String()) + + // Output: + // // This is the package comment. + // package main + // + // // This comment is associated with the hello constant. + // const hello = "Hello, World!" // line comment 1 + // + // // This comment is associated with the main function. + // func main() { + // fmt.Println(hello) // line comment 3 + // } +} |