--- /dev/null
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build go1.7
+// +build gc
+
+package gcexportdata_test
+
+import (
+ "fmt"
+ "go/ast"
+ "go/parser"
+ "go/token"
+ "go/types"
+ "log"
+ "os"
+ "path/filepath"
+
+ "golang.org/x/tools/go/gcexportdata"
+)
+
+// ExampleRead uses gcexportdata.Read to load type information for the
+// "fmt" package from the fmt.a file produced by the gc compiler.
+func ExampleRead() {
+ // Find the export data file.
+ filename, path := gcexportdata.Find("fmt", "")
+ if filename == "" {
+ log.Fatalf("can't find export data for fmt")
+ }
+ fmt.Printf("Package path: %s\n", path)
+ fmt.Printf("Export data: %s\n", filepath.Base(filename))
+
+ // Open and read the file.
+ f, err := os.Open(filename)
+ if err != nil {
+ log.Fatal(err)
+ }
+ defer f.Close()
+ r, err := gcexportdata.NewReader(f)
+ if err != nil {
+ log.Fatalf("reading export data %s: %v", filename, err)
+ }
+
+ // Decode the export data.
+ fset := token.NewFileSet()
+ imports := make(map[string]*types.Package)
+ pkg, err := gcexportdata.Read(r, fset, imports, path)
+ if err != nil {
+ log.Fatal(err)
+ }
+
+ // Print package information.
+ members := pkg.Scope().Names()
+ if members[0] == ".inittask" {
+ // An improvement to init handling in 1.13 added ".inittask". Remove so go >= 1.13 and go < 1.13 both pass.
+ members = members[1:]
+ }
+ fmt.Printf("Package members: %s...\n", members[:5])
+ println := pkg.Scope().Lookup("Println")
+ posn := fset.Position(println.Pos())
+ posn.Line = 123 // make example deterministic
+ fmt.Printf("Println type: %s\n", println.Type())
+ fmt.Printf("Println location: %s\n", slashify(posn))
+
+ // Output:
+ //
+ // Package path: fmt
+ // Export data: fmt.a
+ // Package members: [Errorf Formatter Fprint Fprintf Fprintln]...
+ // Println type: func(a ...interface{}) (n int, err error)
+ // Println location: $GOROOT/src/fmt/print.go:123:1
+}
+
+// ExampleNewImporter demonstrates usage of NewImporter to provide type
+// information for dependencies when type-checking Go source code.
+func ExampleNewImporter() {
+ const src = `package myrpc
+
+// choosing a package that doesn't change across releases
+import "net/rpc"
+
+const serverError rpc.ServerError = ""
+`
+ fset := token.NewFileSet()
+ f, err := parser.ParseFile(fset, "myrpc.go", src, 0)
+ if err != nil {
+ log.Fatal(err)
+ }
+
+ packages := make(map[string]*types.Package)
+ imp := gcexportdata.NewImporter(fset, packages)
+ conf := types.Config{Importer: imp}
+ pkg, err := conf.Check("myrpc", fset, []*ast.File{f}, nil)
+ if err != nil {
+ log.Fatal(err)
+ }
+
+ // object from imported package
+ pi := packages["net/rpc"].Scope().Lookup("ServerError")
+ fmt.Printf("type %s.%s %s // %s\n",
+ pi.Pkg().Path(),
+ pi.Name(),
+ pi.Type().Underlying(),
+ slashify(fset.Position(pi.Pos())),
+ )
+
+ // object in source package
+ twopi := pkg.Scope().Lookup("serverError")
+ fmt.Printf("const %s %s = %s // %s\n",
+ twopi.Name(),
+ twopi.Type(),
+ twopi.(*types.Const).Val(),
+ slashify(fset.Position(twopi.Pos())),
+ )
+
+ // Output:
+ //
+ // type net/rpc.ServerError string // $GOROOT/src/net/rpc/client.go:20:1
+ // const serverError net/rpc.ServerError = "" // myrpc.go:6:7
+}
+
+func slashify(posn token.Position) token.Position {
+ posn.Filename = filepath.ToSlash(posn.Filename) // for MS Windows portability
+ return posn
+}