blob: a50bc40b9f44304cddbe6782e37a16477d2e8fb8 [file] [log] [blame]
Alan Donovan1a954d52016-10-06 17:39:25 -04001// Copyright 2016 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
Alan Donovanf24fea32016-10-28 13:52:00 -04005// +build go1.7
Ian Lance Taylorc65208e2018-06-07 21:33:18 -07006// +build gc
Alan Donovanf24fea32016-10-28 13:52:00 -04007
Alan Donovan1a954d52016-10-06 17:39:25 -04008package gcexportdata_test
9
10import (
11 "fmt"
12 "go/ast"
13 "go/parser"
14 "go/token"
15 "go/types"
16 "log"
17 "os"
18 "path/filepath"
19
20 "golang.org/x/tools/go/gcexportdata"
21)
22
23// ExampleRead uses gcexportdata.Read to load type information for the
24// "fmt" package from the fmt.a file produced by the gc compiler.
25func ExampleRead() {
26 // Find the export data file.
27 filename, path := gcexportdata.Find("fmt", "")
28 if filename == "" {
29 log.Fatalf("can't find export data for fmt")
30 }
31 fmt.Printf("Package path: %s\n", path)
32 fmt.Printf("Export data: %s\n", filepath.Base(filename))
33
34 // Open and read the file.
35 f, err := os.Open(filename)
36 if err != nil {
37 log.Fatal(err)
38 }
39 defer f.Close()
40 r, err := gcexportdata.NewReader(f)
41 if err != nil {
42 log.Fatalf("reading export data %s: %v", filename, err)
43 }
44
45 // Decode the export data.
46 fset := token.NewFileSet()
47 imports := make(map[string]*types.Package)
48 pkg, err := gcexportdata.Read(r, fset, imports, path)
49 if err != nil {
50 log.Fatal(err)
51 }
52
53 // Print package information.
David Chase3f1ed9e2019-03-19 16:54:43 -040054 members := pkg.Scope().Names()
55 if members[0] == ".inittask" {
56 // An improvement to init handling in 1.13 added ".inittask". Remove so go >= 1.13 and go < 1.13 both pass.
57 members = members[1:]
58 }
59 fmt.Printf("Package members: %s...\n", members[:5])
Alan Donovan1a954d52016-10-06 17:39:25 -040060 println := pkg.Scope().Lookup("Println")
61 posn := fset.Position(println.Pos())
Alan Donovan0db92ca2016-10-25 16:43:39 -040062 posn.Line = 123 // make example deterministic
Alan Donovan1a954d52016-10-06 17:39:25 -040063 fmt.Printf("Println type: %s\n", println.Type())
Alan Donovan0db92ca2016-10-25 16:43:39 -040064 fmt.Printf("Println location: %s\n", slashify(posn))
Alan Donovan1a954d52016-10-06 17:39:25 -040065
66 // Output:
67 //
68 // Package path: fmt
69 // Export data: fmt.a
70 // Package members: [Errorf Formatter Fprint Fprintf Fprintln]...
71 // Println type: func(a ...interface{}) (n int, err error)
72 // Println location: $GOROOT/src/fmt/print.go:123:1
73}
74
75// ExampleNewImporter demonstrates usage of NewImporter to provide type
76// information for dependencies when type-checking Go source code.
77func ExampleNewImporter() {
Rebecca Stambler83362c32019-02-21 12:51:16 -050078 const src = `package myrpc
Alan Donovan1a954d52016-10-06 17:39:25 -040079
Rebecca Stambler83362c32019-02-21 12:51:16 -050080// choosing a package that doesn't change across releases
81import "net/rpc"
Alan Donovan1a954d52016-10-06 17:39:25 -040082
Rebecca Stambler52f869c2019-04-16 13:39:56 -040083const serverError rpc.ServerError = ""
Alan Donovan1a954d52016-10-06 17:39:25 -040084`
85 fset := token.NewFileSet()
Rebecca Stambler83362c32019-02-21 12:51:16 -050086 f, err := parser.ParseFile(fset, "myrpc.go", src, 0)
Alan Donovan1a954d52016-10-06 17:39:25 -040087 if err != nil {
88 log.Fatal(err)
89 }
90
91 packages := make(map[string]*types.Package)
92 imp := gcexportdata.NewImporter(fset, packages)
93 conf := types.Config{Importer: imp}
Rebecca Stambler83362c32019-02-21 12:51:16 -050094 pkg, err := conf.Check("myrpc", fset, []*ast.File{f}, nil)
Alan Donovan1a954d52016-10-06 17:39:25 -040095 if err != nil {
96 log.Fatal(err)
97 }
98
99 // object from imported package
Rebecca Stambler52f869c2019-04-16 13:39:56 -0400100 pi := packages["net/rpc"].Scope().Lookup("ServerError")
101 fmt.Printf("type %s.%s %s // %s\n",
Alan Donovan1a954d52016-10-06 17:39:25 -0400102 pi.Pkg().Path(),
103 pi.Name(),
Rebecca Stambler52f869c2019-04-16 13:39:56 -0400104 pi.Type().Underlying(),
Robert Griesemerb9ad13c2017-06-08 14:03:24 -0700105 slashify(fset.Position(pi.Pos())),
106 )
Alan Donovan1a954d52016-10-06 17:39:25 -0400107
108 // object in source package
Rebecca Stambler52f869c2019-04-16 13:39:56 -0400109 twopi := pkg.Scope().Lookup("serverError")
Alan Donovan1a954d52016-10-06 17:39:25 -0400110 fmt.Printf("const %s %s = %s // %s\n",
111 twopi.Name(),
112 twopi.Type(),
113 twopi.(*types.Const).Val(),
Robert Griesemerb9ad13c2017-06-08 14:03:24 -0700114 slashify(fset.Position(twopi.Pos())),
115 )
Alan Donovan1a954d52016-10-06 17:39:25 -0400116
117 // Output:
118 //
Rebecca Stambler52f869c2019-04-16 13:39:56 -0400119 // type net/rpc.ServerError string // $GOROOT/src/net/rpc/client.go:20:1
120 // const serverError net/rpc.ServerError = "" // myrpc.go:6:7
Alan Donovan1a954d52016-10-06 17:39:25 -0400121}
Alan Donovan0db92ca2016-10-25 16:43:39 -0400122
123func slashify(posn token.Position) token.Position {
124 posn.Filename = filepath.ToSlash(posn.Filename) // for MS Windows portability
125 return posn
126}