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/parser"
23 "go/token"
24 "go/types"
25 "log"
26 "regexp"
27 "slices"
28 "strings"
29 )
30
31
32
33 func ExampleScope() {
34
35 fset := token.NewFileSet()
36 var files []*ast.File
37 for _, src := range []string{
38 `package main
39 import "fmt"
40 func main() {
41 freezing := FToC(-18)
42 fmt.Println(freezing, Boiling) }
43 `,
44 `package main
45 import "fmt"
46 type Celsius float64
47 func (c Celsius) String() string { return fmt.Sprintf("%g°C", c) }
48 func FToC(f float64) Celsius { return Celsius(f - 32 / 9 * 5) }
49 const Boiling Celsius = 100
50 func Unused() { {}; {{ var x int; _ = x }} } // make sure empty block scopes get printed
51 `,
52 } {
53 files = append(files, mustParse(fset, src))
54 }
55
56
57
58
59 conf := types.Config{Importer: defaultImporter(fset)}
60 pkg, err := conf.Check("temperature", fset, files, nil)
61 if err != nil {
62 log.Fatal(err)
63 }
64
65
66
67 var buf strings.Builder
68 pkg.Scope().WriteTo(&buf, 0, true)
69 rx := regexp.MustCompile(` 0x[a-fA-F\d]*`)
70 fmt.Println(rx.ReplaceAllString(buf.String(), ""))
71
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 func ExampleMethodSet() {
108
109 const input = `
110 package temperature
111 import "fmt"
112 type Celsius float64
113 func (c Celsius) String() string { return fmt.Sprintf("%g°C", c) }
114 func (c *Celsius) SetF(f float64) { *c = Celsius(f - 32 / 9 * 5) }
115
116 type S struct { I; m int }
117 type I interface { m() byte }
118 `
119 fset := token.NewFileSet()
120 f, err := parser.ParseFile(fset, "celsius.go", input, 0)
121 if err != nil {
122 log.Fatal(err)
123 }
124
125
126
127
128 conf := types.Config{Importer: defaultImporter(fset)}
129 pkg, err := conf.Check("temperature", fset, []*ast.File{f}, nil)
130 if err != nil {
131 log.Fatal(err)
132 }
133
134
135 celsius := pkg.Scope().Lookup("Celsius").Type()
136 for _, t := range []types.Type{celsius, types.NewPointer(celsius)} {
137 fmt.Printf("Method set of %s:\n", t)
138 for m := range types.NewMethodSet(t).Methods() {
139 fmt.Println(m)
140 }
141 fmt.Println()
142 }
143
144
145 styp := pkg.Scope().Lookup("S").Type()
146 fmt.Printf("Method set of %s:\n", styp)
147 fmt.Println(types.NewMethodSet(styp))
148
149
150
151
152
153
154
155
156
157
158
159 }
160
161
162
163
164 func ExampleInfo() {
165
166 const input = `
167 package fib
168
169 type S string
170
171 var a, b, c = len(b), S(c), "hello"
172
173 func fib(x int) int {
174 if x < 2 {
175 return x
176 }
177 return fib(x-1) - fib(x-2)
178 }`
179
180
181 fset := token.NewFileSet()
182 f := mustParse(fset, input)
183
184
185
186
187 info := types.Info{
188 Types: make(map[ast.Expr]types.TypeAndValue),
189 Defs: make(map[*ast.Ident]types.Object),
190 Uses: make(map[*ast.Ident]types.Object),
191 }
192 var conf types.Config
193 pkg, err := conf.Check("fib", fset, []*ast.File{f}, &info)
194 if err != nil {
195 log.Fatal(err)
196 }
197
198
199 fmt.Printf("InitOrder: %v\n\n", info.InitOrder)
200
201
202
203 fmt.Println("Defs and Uses of each named object:")
204 usesByObj := make(map[types.Object][]string)
205 for id, obj := range info.Uses {
206 posn := fset.Position(id.Pos())
207 lineCol := fmt.Sprintf("%d:%d", posn.Line, posn.Column)
208 usesByObj[obj] = append(usesByObj[obj], lineCol)
209 }
210 var items []string
211 for obj, uses := range usesByObj {
212 slices.Sort(uses)
213 item := fmt.Sprintf("%s:\n defined at %s\n used at %s",
214 types.ObjectString(obj, types.RelativeTo(pkg)),
215 fset.Position(obj.Pos()),
216 strings.Join(uses, ", "))
217 items = append(items, item)
218 }
219 slices.Sort(items)
220 fmt.Println(strings.Join(items, "\n"))
221 fmt.Println()
222
223 fmt.Println("Types and Values of each expression:")
224 items = nil
225 for expr, tv := range info.Types {
226 var buf strings.Builder
227 posn := fset.Position(expr.Pos())
228 tvstr := tv.Type.String()
229 if tv.Value != nil {
230 tvstr += " = " + tv.Value.String()
231 }
232
233 fmt.Fprintf(&buf, "%2d:%2d | %-19s | %-7s : %s",
234 posn.Line, posn.Column, exprString(fset, expr),
235 mode(tv), tvstr)
236 items = append(items, buf.String())
237 }
238 slices.Sort(items)
239 fmt.Println(strings.Join(items, "\n"))
240
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 func mode(tv types.TypeAndValue) string {
299 switch {
300 case tv.IsVoid():
301 return "void"
302 case tv.IsType():
303 return "type"
304 case tv.IsBuiltin():
305 return "builtin"
306 case tv.IsNil():
307 return "nil"
308 case tv.Assignable():
309 if tv.Addressable() {
310 return "var"
311 }
312 return "mapindex"
313 case tv.IsValue():
314 return "value"
315 default:
316 return "unknown"
317 }
318 }
319
320 func exprString(fset *token.FileSet, expr ast.Expr) string {
321 var buf strings.Builder
322 format.Node(&buf, fset, expr)
323 return buf.String()
324 }
325
View as plain text