1// Copyright 2017 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// +build ignore
6
7// The gcexportdata command is a diagnostic tool that displays the
8// contents of gc export data files.
9package main
10
11import (
12 "flag"
13 "fmt"
14 "go/token"
15 "go/types"
16 "log"
17 "os"
18
19 "golang.org/x/tools/go/gcexportdata"
20 "golang.org/x/tools/go/types/typeutil"
21)
22
23var packageFlag = flag.String("package", "", "alternative package to print")
24
25func main() {
26 log.SetPrefix("gcexportdata: ")
27 log.SetFlags(0)
28 flag.Usage = func() {
29 fmt.Fprintln(os.Stderr, "usage: gcexportdata [-package path] file.a")
30 }
31 flag.Parse()
32 if flag.NArg() != 1 {
33 flag.Usage()
34 os.Exit(2)
35 }
36 filename := flag.Args()[0]
37
38 f, err := os.Open(filename)
39 if err != nil {
40 log.Fatal(err)
41 }
42
43 r, err := gcexportdata.NewReader(f)
44 if err != nil {
45 log.Fatalf("%s: %s", filename, err)
46 }
47
48 // Decode the package.
49 const primary = "<primary>"
50 imports := make(map[string]*types.Package)
51 fset := token.NewFileSet()
52 pkg, err := gcexportdata.Read(r, fset, imports, primary)
53 if err != nil {
54 log.Fatalf("%s: %s", filename, err)
55 }
56
57 // Optionally select an indirectly mentioned package.
58 if *packageFlag != "" {
59 pkg = imports[*packageFlag]
60 if pkg == nil {
61 fmt.Fprintf(os.Stderr, "export data file %s does not mention %s; has:\n",
62 filename, *packageFlag)
63 for p := range imports {
64 if p != primary {
65 fmt.Fprintf(os.Stderr, "\t%s\n", p)
66 }
67 }
68 os.Exit(1)
69 }
70 }
71
72 // Print all package-level declarations, including non-exported ones.
73 fmt.Printf("package %s\n", pkg.Name())
74 for _, imp := range pkg.Imports() {
75 fmt.Printf("import %q\n", imp.Path())
76 }
77 qual := func(p *types.Package) string {
78 if pkg == p {
79 return ""
80 }
81 return p.Name()
82 }
83 scope := pkg.Scope()
84 for _, name := range scope.Names() {
85 obj := scope.Lookup(name)
86 fmt.Printf("%s: %s\n",
87 fset.Position(obj.Pos()),
88 types.ObjectString(obj, qual))
89
90 // For types, print each method.
91 if _, ok := obj.(*types.TypeName); ok {
92 for _, method := range typeutil.IntuitiveMethodSet(obj.Type(), nil) {
93 fmt.Printf("%s: %s\n",
94 fset.Position(method.Obj().Pos()),
95 types.SelectionString(method, qual))
96 }
97 }
98 }
99}