github.com/shogo82148/std@v1.22.1-0.20240327122250-4e474527810c/go/ast/example_test.go (about) 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 "github.com/shogo82148/std/fmt" 9 "github.com/shogo82148/std/go/ast" 10 "github.com/shogo82148/std/go/format" 11 "github.com/shogo82148/std/go/parser" 12 "github.com/shogo82148/std/go/token" 13 "github.com/shogo82148/std/strings" 14 ) 15 16 // この例は、GoプログラムのASTを検査する方法を示しています。 17 func ExampleInspect() { 18 // srcはASTを検査したい入力です。 19 src := ` 20 package p 21 const c = 1.0 22 var X = f(3.14)*2 + c 23 ` 24 25 // srcを解析してASTを作成する。 26 fset := token.NewFileSet() // ポジションはfsetに対して相対的です。 27 f, err := parser.ParseFile(fset, "src.go", src, 0) 28 if err != nil { 29 panic(err) 30 } 31 32 // AST を調査し、すべての識別子とリテラルを表示します。 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 // この例では、デバッグ用に出力されるASTの形状を示しています。 59 func ExamplePrint() { 60 // srcはASTを出力したい入力です。 61 src := ` 62 package main 63 func main() { 64 println("Hello, World!") 65 } 66 ` 67 68 // src を解析してASTを作成します。 69 fset := token.NewFileSet() // ポジションはfsetに対して相対的です。 70 f, err := parser.ParseFile(fset, "", src, 0) 71 if err != nil { 72 panic(err) 73 } 74 75 // 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 . GoVersion: "" 140 // 61 } 141 } 142 143 // この例は、ast.CommentMapを使用して、Goプログラムの変数宣言を削除しながら正しいコメントの関連を保持する方法を示しています。 144 func ExampleCommentMap() { 145 146 // src は、私たちが操作するためのASTを作成する入力です。 147 src := ` 148 // This is the package comment. 149 package main 150 151 // This comment is associated with the hello constant. 152 const hello = "Hello, World!" // line comment 1 153 154 // This comment is associated with the foo variable. 155 var foo = hello // line comment 2 156 157 // This comment is associated with the main function. 158 func main() { 159 fmt.Println(hello) // line comment 3 160 } 161 ` 162 163 // src をパースしてASTを作成する。 164 fset := token.NewFileSet() // positionsはfsetに対して相対的です。 165 f, err := parser.ParseFile(fset, "src.go", src, parser.ParseComments) 166 if err != nil { 167 panic(err) 168 } 169 170 // ast.File のコメントから ast.CommentMap を作成します。 171 // これにより、コメントと AST ノードの関連付けが保持されます。 172 cmap := ast.NewCommentMap(fset, f, f.Comments) 173 174 // 最初の変数宣言を宣言リストから削除します。 175 for i, decl := range f.Decls { 176 if gen, ok := decl.(*ast.GenDecl); ok && gen.Tok == token.VAR { 177 copy(f.Decls[i:], f.Decls[i+1:]) 178 f.Decls = f.Decls[:len(f.Decls)-1] 179 break 180 } 181 } 182 183 // コメントマップを使用して、もはや必要でないコメント(変数宣言に関連するコメント)をフィルタリングし、新しいコメントリストを作成します。 184 f.Comments = cmap.Filter(f).Comments() 185 186 // 変更されたASTを出力します。 187 var buf strings.Builder 188 if err := format.Node(&buf, fset, f); err != nil { 189 panic(err) 190 } 191 fmt.Printf("%s", buf.String()) 192 193 // Output: 194 // // This is the package comment. 195 // package main 196 // 197 // // This comment is associated with the hello constant. 198 // const hello = "Hello, World!" // line comment 1 199 // 200 // // This comment is associated with the main function. 201 // func main() { 202 // fmt.Println(hello) // line comment 3 203 // } 204 }