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 for m := range types.NewMethodSet(t).Methods() {
140 fmt.Println(m)
141 }
142 fmt.Println()
143 }
144
145
146 styp := pkg.Scope().Lookup("S").Type()
147 fmt.Printf("Method set of %s:\n", styp)
148 fmt.Println(types.NewMethodSet(styp))
149
150
151
152
153
154
155
156
157
158
159
160 }
161
162
163
164
165 func ExampleInfo() {
166
167 const input = `
168 package fib
169
170 type S string
171
172 var a, b, c = len(b), S(c), "hello"
173
174 func fib(x int) int {
175 if x < 2 {
176 return x
177 }
178 return fib(x-1) - fib(x-2)
179 }`
180
181
182 fset := token.NewFileSet()
183 f := mustParse(fset, input)
184
185
186
187
188 info := types.Info{
189 Types: make(map[ast.Expr]types.TypeAndValue),
190 Defs: make(map[*ast.Ident]types.Object),
191 Uses: make(map[*ast.Ident]types.Object),
192 }
193 var conf types.Config
194 pkg, err := conf.Check("fib", fset, []*ast.File{f}, &info)
195 if err != nil {
196 log.Fatal(err)
197 }
198
199
200 fmt.Printf("InitOrder: %v\n\n", info.InitOrder)
201
202
203
204 fmt.Println("Defs and Uses of each named object:")
205 usesByObj := make(map[types.Object][]string)
206 for id, obj := range info.Uses {
207 posn := fset.Position(id.Pos())
208 lineCol := fmt.Sprintf("%d:%d", posn.Line, posn.Column)
209 usesByObj[obj] = append(usesByObj[obj], lineCol)
210 }
211 var items []string
212 for obj, uses := range usesByObj {
213 slices.Sort(uses)
214 item := fmt.Sprintf("%s:\n defined at %s\n used at %s",
215 types.ObjectString(obj, types.RelativeTo(pkg)),
216 fset.Position(obj.Pos()),
217 strings.Join(uses, ", "))
218 items = append(items, item)
219 }
220 slices.Sort(items)
221 fmt.Println(strings.Join(items, "\n"))
222 fmt.Println()
223
224 fmt.Println("Types and Values of each expression:")
225 items = nil
226 for expr, tv := range info.Types {
227 var buf strings.Builder
228 posn := fset.Position(expr.Pos())
229 tvstr := tv.Type.String()
230 if tv.Value != nil {
231 tvstr += " = " + tv.Value.String()
232 }
233
234 fmt.Fprintf(&buf, "%2d:%2d | %-19s | %-7s : %s",
235 posn.Line, posn.Column, exprString(fset, expr),
236 mode(tv), tvstr)
237 items = append(items, buf.String())
238 }
239 slices.Sort(items)
240 fmt.Println(strings.Join(items, "\n"))
241
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 func mode(tv types.TypeAndValue) string {
300 switch {
301 case tv.IsVoid():
302 return "void"
303 case tv.IsType():
304 return "type"
305 case tv.IsBuiltin():
306 return "builtin"
307 case tv.IsNil():
308 return "nil"
309 case tv.Assignable():
310 if tv.Addressable() {
311 return "var"
312 }
313 return "mapindex"
314 case tv.IsValue():
315 return "value"
316 default:
317 return "unknown"
318 }
319 }
320
321 func exprString(fset *token.FileSet, expr ast.Expr) string {
322 var buf strings.Builder
323 format.Node(&buf, fset, expr)
324 return buf.String()
325 }
326
View as plain text