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