Source file
src/go/types/example_test.go
1
2
3
4
5
6
7
8
9
10 package types_test
11
12
13
14
15
16
17
18 import (
19 "fmt"
20 "go/ast"
21 "go/format"
22 "go/importer"
23 "go/parser"
24 "go/token"
25 "go/types"
26 "log"
27 "regexp"
28 "slices"
29 "strings"
30 )
31
32
33
34 func ExampleScope() {
35
36 fset := token.NewFileSet()
37 var files []*ast.File
38 for _, src := range []string{
39 `package main
40 import "fmt"
41 func main() {
42 freezing := FToC(-18)
43 fmt.Println(freezing, Boiling) }
44 `,
45 `package main
46 import "fmt"
47 type Celsius float64
48 func (c Celsius) String() string { return fmt.Sprintf("%g°C", c) }
49 func FToC(f float64) Celsius { return Celsius(f - 32 / 9 * 5) }
50 const Boiling Celsius = 100
51 func Unused() { {}; {{ var x int; _ = x }} } // make sure empty block scopes get printed
52 `,
53 } {
54 files = append(files, mustParse(fset, src))
55 }
56
57
58
59
60 conf := types.Config{Importer: importer.Default()}
61 pkg, err := conf.Check("temperature", fset, files, nil)
62 if err != nil {
63 log.Fatal(err)
64 }
65
66
67
68 var buf strings.Builder
69 pkg.Scope().WriteTo(&buf, 0, true)
70 rx := regexp.MustCompile(` 0x[a-fA-F\d]*`)
71 fmt.Println(rx.ReplaceAllString(buf.String(), ""))
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105 }
106
107
108 func ExampleMethodSet() {
109
110 const input = `
111 package temperature
112 import "fmt"
113 type Celsius float64
114 func (c Celsius) String() string { return fmt.Sprintf("%g°C", c) }
115 func (c *Celsius) SetF(f float64) { *c = Celsius(f - 32 / 9 * 5) }
116
117 type S struct { I; m int }
118 type I interface { m() byte }
119 `
120 fset := token.NewFileSet()
121 f, err := parser.ParseFile(fset, "celsius.go", input, 0)
122 if err != nil {
123 log.Fatal(err)
124 }
125
126
127
128
129 conf := types.Config{Importer: importer.Default()}
130 pkg, err := conf.Check("temperature", fset, []*ast.File{f}, nil)
131 if err != nil {
132 log.Fatal(err)
133 }
134
135
136 celsius := pkg.Scope().Lookup("Celsius").Type()
137 for _, t := range []types.Type{celsius, types.NewPointer(celsius)} {
138 fmt.Printf("Method set of %s:\n", t)
139 mset := types.NewMethodSet(t)
140 for i := 0; i < mset.Len(); i++ {
141 fmt.Println(mset.At(i))
142 }
143 fmt.Println()
144 }
145
146
147 styp := pkg.Scope().Lookup("S").Type()
148 fmt.Printf("Method set of %s:\n", styp)
149 fmt.Println(types.NewMethodSet(styp))
150
151
152
153
154
155
156
157
158
159
160
161 }
162
163
164
165
166 func ExampleInfo() {
167
168 const input = `
169 package fib
170
171 type S string
172
173 var a, b, c = len(b), S(c), "hello"
174
175 func fib(x int) int {
176 if x < 2 {
177 return x
178 }
179 return fib(x-1) - fib(x-2)
180 }`
181
182
183 fset := token.NewFileSet()
184 f := mustParse(fset, input)
185
186
187
188
189 info := types.Info{
190 Types: make(map[ast.Expr]types.TypeAndValue),
191 Defs: make(map[*ast.Ident]types.Object),
192 Uses: make(map[*ast.Ident]types.Object),
193 }
194 var conf types.Config
195 pkg, err := conf.Check("fib", fset, []*ast.File{f}, &info)
196 if err != nil {
197 log.Fatal(err)
198 }
199
200
201 fmt.Printf("InitOrder: %v\n\n", info.InitOrder)
202
203
204
205 fmt.Println("Defs and Uses of each named object:")
206 usesByObj := make(map[types.Object][]string)
207 for id, obj := range info.Uses {
208 posn := fset.Position(id.Pos())
209 lineCol := fmt.Sprintf("%d:%d", posn.Line, posn.Column)
210 usesByObj[obj] = append(usesByObj[obj], lineCol)
211 }
212 var items []string
213 for obj, uses := range usesByObj {
214 slices.Sort(uses)
215 item := fmt.Sprintf("%s:\n defined at %s\n used at %s",
216 types.ObjectString(obj, types.RelativeTo(pkg)),
217 fset.Position(obj.Pos()),
218 strings.Join(uses, ", "))
219 items = append(items, item)
220 }
221 slices.Sort(items)
222 fmt.Println(strings.Join(items, "\n"))
223 fmt.Println()
224
225 fmt.Println("Types and Values of each expression:")
226 items = nil
227 for expr, tv := range info.Types {
228 var buf strings.Builder
229 posn := fset.Position(expr.Pos())
230 tvstr := tv.Type.String()
231 if tv.Value != nil {
232 tvstr += " = " + tv.Value.String()
233 }
234
235 fmt.Fprintf(&buf, "%2d:%2d | %-19s | %-7s : %s",
236 posn.Line, posn.Column, exprString(fset, expr),
237 mode(tv), tvstr)
238 items = append(items, buf.String())
239 }
240 slices.Sort(items)
241 fmt.Println(strings.Join(items, "\n"))
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298 }
299
300 func mode(tv types.TypeAndValue) string {
301 switch {
302 case tv.IsVoid():
303 return "void"
304 case tv.IsType():
305 return "type"
306 case tv.IsBuiltin():
307 return "builtin"
308 case tv.IsNil():
309 return "nil"
310 case tv.Assignable():
311 if tv.Addressable() {
312 return "var"
313 }
314 return "mapindex"
315 case tv.IsValue():
316 return "value"
317 default:
318 return "unknown"
319 }
320 }
321
322 func exprString(fset *token.FileSet, expr ast.Expr) string {
323 var buf strings.Builder
324 format.Node(&buf, fset, expr)
325 return buf.String()
326 }
327
View as plain text