123 lines
3.2 KiB
Go
123 lines
3.2 KiB
Go
// 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.
|
|
fmt.Printf("Package members: %s...\n", pkg.Scope().Names()[: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 myscanner
|
|
|
|
// choosing a package that is unlikely to change across releases
|
|
import "text/scanner"
|
|
|
|
const eof = scanner.EOF
|
|
`
|
|
fset := token.NewFileSet()
|
|
f, err := parser.ParseFile(fset, "myscanner.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("myscanner", fset, []*ast.File{f}, nil)
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
|
|
// object from imported package
|
|
pi := packages["text/scanner"].Scope().Lookup("EOF")
|
|
fmt.Printf("const %s.%s %s = %s // %s\n",
|
|
pi.Pkg().Path(),
|
|
pi.Name(),
|
|
pi.Type(),
|
|
pi.(*types.Const).Val(),
|
|
slashify(fset.Position(pi.Pos())),
|
|
)
|
|
|
|
// object in source package
|
|
twopi := pkg.Scope().Lookup("eof")
|
|
fmt.Printf("const %s %s = %s // %s\n",
|
|
twopi.Name(),
|
|
twopi.Type(),
|
|
twopi.(*types.Const).Val(),
|
|
slashify(fset.Position(twopi.Pos())),
|
|
)
|
|
|
|
// Output:
|
|
//
|
|
// const text/scanner.EOF untyped int = -1 // $GOROOT/src/text/scanner/scanner.go:75:1
|
|
// const eof untyped int = -1 // myscanner.go:6:7
|
|
}
|
|
|
|
func slashify(posn token.Position) token.Position {
|
|
posn.Filename = filepath.ToSlash(posn.Filename) // for MS Windows portability
|
|
return posn
|
|
}
|