|  | // Copyright 2017 The Go Authors. All rights reserved. | 
|  | // Use of this source code is governed by a BSD-style | 
|  | // license that can be found in the LICENSE file. | 
|  |  | 
|  | //go:build ignore | 
|  | // +build ignore | 
|  |  | 
|  | // The gcexportdata command is a diagnostic tool that displays the | 
|  | // contents of gc export data files. | 
|  | package main | 
|  |  | 
|  | import ( | 
|  | "flag" | 
|  | "fmt" | 
|  | "go/token" | 
|  | "go/types" | 
|  | "log" | 
|  | "os" | 
|  |  | 
|  | "golang.org/x/tools/go/gcexportdata" | 
|  | "golang.org/x/tools/go/types/typeutil" | 
|  | ) | 
|  |  | 
|  | var packageFlag = flag.String("package", "", "alternative package to print") | 
|  |  | 
|  | func main() { | 
|  | log.SetPrefix("gcexportdata: ") | 
|  | log.SetFlags(0) | 
|  | flag.Usage = func() { | 
|  | fmt.Fprintln(os.Stderr, "usage: gcexportdata [-package path] file.a") | 
|  | } | 
|  | flag.Parse() | 
|  | if flag.NArg() != 1 { | 
|  | flag.Usage() | 
|  | os.Exit(2) | 
|  | } | 
|  | filename := flag.Args()[0] | 
|  |  | 
|  | f, err := os.Open(filename) | 
|  | if err != nil { | 
|  | log.Fatal(err) | 
|  | } | 
|  |  | 
|  | r, err := gcexportdata.NewReader(f) | 
|  | if err != nil { | 
|  | log.Fatalf("%s: %s", filename, err) | 
|  | } | 
|  |  | 
|  | // Decode the package. | 
|  | const primary = "<primary>" | 
|  | imports := make(map[string]*types.Package) | 
|  | fset := token.NewFileSet() | 
|  | pkg, err := gcexportdata.Read(r, fset, imports, primary) | 
|  | if err != nil { | 
|  | log.Fatalf("%s: %s", filename, err) | 
|  | } | 
|  |  | 
|  | // Optionally select an indirectly mentioned package. | 
|  | if *packageFlag != "" { | 
|  | pkg = imports[*packageFlag] | 
|  | if pkg == nil { | 
|  | fmt.Fprintf(os.Stderr, "export data file %s does not mention %s; has:\n", | 
|  | filename, *packageFlag) | 
|  | for p := range imports { | 
|  | if p != primary { | 
|  | fmt.Fprintf(os.Stderr, "\t%s\n", p) | 
|  | } | 
|  | } | 
|  | os.Exit(1) | 
|  | } | 
|  | } | 
|  |  | 
|  | // Print all package-level declarations, including non-exported ones. | 
|  | fmt.Printf("package %s\n", pkg.Name()) | 
|  | for _, imp := range pkg.Imports() { | 
|  | fmt.Printf("import %q\n", imp.Path()) | 
|  | } | 
|  | qual := func(p *types.Package) string { | 
|  | if pkg == p { | 
|  | return "" | 
|  | } | 
|  | return p.Name() | 
|  | } | 
|  | scope := pkg.Scope() | 
|  | for _, name := range scope.Names() { | 
|  | obj := scope.Lookup(name) | 
|  | fmt.Printf("%s: %s\n", | 
|  | fset.Position(obj.Pos()), | 
|  | types.ObjectString(obj, qual)) | 
|  |  | 
|  | // For types, print each method. | 
|  | if _, ok := obj.(*types.TypeName); ok { | 
|  | for _, method := range typeutil.IntuitiveMethodSet(obj.Type(), nil) { | 
|  | fmt.Printf("%s: %s\n", | 
|  | fset.Position(method.Obj().Pos()), | 
|  | types.SelectionString(method, qual)) | 
|  | } | 
|  | } | 
|  | } | 
|  | } |