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