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