...

Source file src/golang.org/x/tools/go/gcexportdata/example_test.go

Documentation: golang.org/x/tools/go/gcexportdata

     1  // 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  
     5  //go:build go1.7 && gc && !android && !ios && (unix || aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris || plan9 || windows)
     6  // +build go1.7
     7  // +build gc
     8  // +build !android
     9  // +build !ios
    10  // +build unix aix darwin dragonfly freebsd linux netbsd openbsd solaris plan9 windows
    11  
    12  package gcexportdata_test
    13  
    14  import (
    15  	"fmt"
    16  	"go/ast"
    17  	"go/parser"
    18  	"go/token"
    19  	"go/types"
    20  	"log"
    21  	"os"
    22  	"path/filepath"
    23  	"strings"
    24  
    25  	"golang.org/x/tools/go/gcexportdata"
    26  )
    27  
    28  // ExampleRead uses gcexportdata.Read to load type information for the
    29  // "fmt" package from the fmt.a file produced by the gc compiler.
    30  func ExampleRead() {
    31  	// Find the export data file.
    32  	filename, path := gcexportdata.Find("fmt", "")
    33  	if filename == "" {
    34  		log.Fatalf("can't find export data for fmt")
    35  	}
    36  	fmt.Printf("Package path:       %s\n", path)
    37  
    38  	// Open and read the file.
    39  	f, err := os.Open(filename)
    40  	if err != nil {
    41  		log.Fatal(err)
    42  	}
    43  	defer f.Close()
    44  	r, err := gcexportdata.NewReader(f)
    45  	if err != nil {
    46  		log.Fatalf("reading export data %s: %v", filename, err)
    47  	}
    48  
    49  	// Decode the export data.
    50  	fset := token.NewFileSet()
    51  	imports := make(map[string]*types.Package)
    52  	pkg, err := gcexportdata.Read(r, fset, imports, path)
    53  	if err != nil {
    54  		log.Fatal(err)
    55  	}
    56  
    57  	// We can see all the names in Names.
    58  	members := pkg.Scope().Names()
    59  	foundPrintln := false
    60  	for _, member := range members {
    61  		if member == "Println" {
    62  			foundPrintln = true
    63  			break
    64  		}
    65  	}
    66  	fmt.Print("Package members:    ")
    67  	if foundPrintln {
    68  		fmt.Println("Println found")
    69  	} else {
    70  		fmt.Println("Println not found")
    71  	}
    72  
    73  	// We can also look up a name directly using Lookup.
    74  	println := pkg.Scope().Lookup("Println")
    75  	// go 1.18+ uses the 'any' alias
    76  	typ := strings.ReplaceAll(println.Type().String(), "interface{}", "any")
    77  	fmt.Printf("Println type:       %s\n", typ)
    78  	posn := fset.Position(println.Pos())
    79  	// make example deterministic
    80  	posn.Line = 123
    81  	fmt.Printf("Println location:   %s\n", slashify(posn))
    82  
    83  	// Output:
    84  	//
    85  	// Package path:       fmt
    86  	// Package members:    Println found
    87  	// Println type:       func(a ...any) (n int, err error)
    88  	// Println location:   $GOROOT/src/fmt/print.go:123:1
    89  }
    90  
    91  // ExampleNewImporter demonstrates usage of NewImporter to provide type
    92  // information for dependencies when type-checking Go source code.
    93  func ExampleNewImporter() {
    94  	const src = `package myrpc
    95  
    96  // choosing a package that doesn't change across releases
    97  import "net/rpc"
    98  
    99  const serverError rpc.ServerError = ""
   100  `
   101  	fset := token.NewFileSet()
   102  	f, err := parser.ParseFile(fset, "myrpc.go", src, 0)
   103  	if err != nil {
   104  		log.Fatal(err)
   105  	}
   106  
   107  	packages := make(map[string]*types.Package)
   108  	imp := gcexportdata.NewImporter(fset, packages)
   109  	conf := types.Config{Importer: imp}
   110  	pkg, err := conf.Check("myrpc", fset, []*ast.File{f}, nil)
   111  	if err != nil {
   112  		log.Fatal(err)
   113  	}
   114  
   115  	// object from imported package
   116  	pi := packages["net/rpc"].Scope().Lookup("ServerError")
   117  	fmt.Printf("type %s.%s %s // %s\n",
   118  		pi.Pkg().Path(),
   119  		pi.Name(),
   120  		pi.Type().Underlying(),
   121  		slashify(fset.Position(pi.Pos())),
   122  	)
   123  
   124  	// object in source package
   125  	twopi := pkg.Scope().Lookup("serverError")
   126  	fmt.Printf("const %s %s = %s // %s\n",
   127  		twopi.Name(),
   128  		twopi.Type(),
   129  		twopi.(*types.Const).Val(),
   130  		slashify(fset.Position(twopi.Pos())),
   131  	)
   132  
   133  	// Output:
   134  	//
   135  	// type net/rpc.ServerError string // $GOROOT/src/net/rpc/client.go:20:1
   136  	// const serverError net/rpc.ServerError = "" // myrpc.go:6:7
   137  }
   138  
   139  func slashify(posn token.Position) token.Position {
   140  	posn.Filename = filepath.ToSlash(posn.Filename) // for MS Windows portability
   141  	return posn
   142  }
   143  

View as plain text