...
1
2
3
4
5
6
7
8
9
10
11 package main
12
13 import (
14 "bytes"
15 "flag"
16 "fmt"
17 "go/token"
18 "go/types"
19 "log"
20 "os"
21 "sort"
22
23 "golang.org/x/tools/go/gcexportdata"
24 "golang.org/x/tools/go/packages"
25 "golang.org/x/tools/go/types/typeutil"
26 "golang.org/x/tools/internal/gcimporter"
27 )
28
29 func main() {
30 flag.Parse()
31 cfg := &packages.Config{
32 Fset: token.NewFileSet(),
33
34
35 Mode: packages.NeedName | packages.NeedExportFile,
36 }
37 pkgs, err := packages.Load(cfg, flag.Args()...)
38 if err != nil {
39 log.Fatal(err)
40 }
41 if packages.PrintErrors(pkgs) > 0 {
42 os.Exit(1)
43 }
44
45 for _, pkg := range pkgs {
46
47
48
49 var tpkg1 *types.Package
50 {
51 export, err := os.ReadFile(pkg.ExportFile)
52 if err != nil {
53 log.Fatalf("can't read %q export data: %v", pkg.PkgPath, err)
54 }
55 r, err := gcexportdata.NewReader(bytes.NewReader(export))
56 if err != nil {
57 log.Fatalf("reading export data %s: %v", pkg.ExportFile, err)
58 }
59 tpkg1, err = gcexportdata.Read(r, cfg.Fset, make(map[string]*types.Package), pkg.PkgPath)
60 if err != nil {
61 log.Fatalf("decoding export data: %v", err)
62 }
63 }
64 fmt.Println("# Read from compiler's unified export data:")
65 printPackage(tpkg1)
66
67
68
69 var tpkg2 *types.Package
70 {
71 var out bytes.Buffer
72 if err := gcimporter.IExportData(&out, cfg.Fset, tpkg1); err != nil {
73 log.Fatal(err)
74 }
75 var err error
76 _, tpkg2, err = gcimporter.IImportData(cfg.Fset, make(map[string]*types.Package), out.Bytes(), tpkg1.Path())
77 if err != nil {
78 log.Fatal(err)
79 }
80 }
81 fmt.Println("# After round-tripping through indexed export data:")
82 printPackage(tpkg2)
83 }
84 }
85
86 func printPackage(pkg *types.Package) {
87 fmt.Printf("package %s %q\n", pkg.Name(), pkg.Path())
88
89 if !pkg.Complete() {
90 fmt.Printf("\thas incomplete exported type info\n")
91 }
92
93
94 var lines []string
95 for _, imp := range pkg.Imports() {
96 lines = append(lines, fmt.Sprintf("\timport %q", imp.Path()))
97 }
98 sort.Strings(lines)
99 for _, line := range lines {
100 fmt.Println(line)
101 }
102
103
104 qual := types.RelativeTo(pkg)
105 scope := pkg.Scope()
106 for _, name := range scope.Names() {
107 obj := scope.Lookup(name)
108 fmt.Printf("\t%s\n", types.ObjectString(obj, qual))
109 if _, ok := obj.(*types.TypeName); ok {
110 for _, meth := range typeutil.IntuitiveMethodSet(obj.Type(), nil) {
111 fmt.Printf("\t%s\n", types.SelectionString(meth, qual))
112 }
113 }
114 }
115
116 fmt.Println()
117 }
118
View as plain text