main.go

 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}