Giant blob of minor changes
[dotfiles/.git] / .config / coc / extensions / coc-go-data / tools / pkg / mod / golang.org / x / tools@v0.0.0-20201105173854-bc9fc8d8c4bc / cmd / guru / main.go
1 // Copyright 2013 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 // guru: a tool for answering questions about Go source code.
6 //
7 //    http://golang.org/s/using-guru
8 //
9 // Run with -help flag or help subcommand for usage information.
10 //
11 package main // import "golang.org/x/tools/cmd/guru"
12
13 import (
14         "bufio"
15         "flag"
16         "fmt"
17         "go/build"
18         "go/token"
19         "io"
20         "log"
21         "os"
22         "path/filepath"
23         "runtime"
24         "runtime/pprof"
25         "strings"
26         "sync"
27
28         "golang.org/x/tools/go/buildutil"
29 )
30
31 // flags
32 var (
33         modifiedFlag   = flag.Bool("modified", false, "read archive of modified files from standard input")
34         scopeFlag      = flag.String("scope", "", "comma-separated list of `packages` the analysis should be limited to")
35         ptalogFlag     = flag.String("ptalog", "", "write points-to analysis log to `file`")
36         jsonFlag       = flag.Bool("json", false, "emit output in JSON format")
37         reflectFlag    = flag.Bool("reflect", false, "analyze reflection soundly (slow)")
38         cpuprofileFlag = flag.String("cpuprofile", "", "write CPU profile to `file`")
39 )
40
41 func init() {
42         flag.Var((*buildutil.TagsFlag)(&build.Default.BuildTags), "tags", buildutil.TagsFlagDoc)
43
44         // gccgo does not provide a GOROOT with standard library sources.
45         // If we have one in the environment, force gc mode.
46         if build.Default.Compiler == "gccgo" {
47                 if _, err := os.Stat(filepath.Join(runtime.GOROOT(), "src", "runtime", "runtime.go")); err == nil {
48                         build.Default.Compiler = "gc"
49                 }
50         }
51 }
52
53 const useHelp = "Run 'guru -help' for more information.\n"
54
55 const helpMessage = `Go source code guru.
56 Usage: guru [flags] <mode> <position>
57
58 The mode argument determines the query to perform:
59
60         callees         show possible targets of selected function call
61         callers         show possible callers of selected function
62         callstack       show path from callgraph root to selected function
63         definition      show declaration of selected identifier
64         describe        describe selected syntax: definition, methods, etc
65         freevars        show free variables of selection
66         implements      show 'implements' relation for selected type or method
67         peers           show send/receive corresponding to selected channel op
68         pointsto        show variables the selected pointer may point to
69         referrers       show all refs to entity denoted by selected identifier
70         what            show basic information about the selected syntax node
71         whicherrs       show possible values of the selected error variable
72
73 The position argument specifies the filename and byte offset (or range)
74 of the syntax element to query.  For example:
75
76         foo.go:#123,#128
77         bar.go:#123
78
79 The -json flag causes guru to emit output in JSON format;
80         golang.org/x/tools/cmd/guru/serial defines its schema.
81         Otherwise, the output is in an editor-friendly format in which
82         every line has the form "pos: text", where pos is "-" if unknown.
83
84 The -modified flag causes guru to read an archive from standard input.
85         Files in this archive will be used in preference to those in
86         the file system.  In this way, a text editor may supply guru
87         with the contents of its unsaved buffers.  Each archive entry
88         consists of the file name, a newline, the decimal file size,
89         another newline, and the contents of the file.
90
91 The -scope flag restricts analysis to the specified packages.
92         Its value is a comma-separated list of patterns of these forms:
93                 golang.org/x/tools/cmd/guru     # a single package
94                 golang.org/x/tools/...          # all packages beneath dir
95                 ...                             # the entire workspace.
96         A pattern preceded by '-' is negative, so the scope
97                 encoding/...,-encoding/xml
98         matches all encoding packages except encoding/xml.
99
100 User manual: http://golang.org/s/using-guru
101
102 Example: describe syntax at offset 530 in this file (an import spec):
103
104   $ guru describe src/golang.org/x/tools/cmd/guru/main.go:#530
105 `
106
107 func printHelp() {
108         fmt.Fprintln(os.Stderr, helpMessage)
109         fmt.Fprintln(os.Stderr, "Flags:")
110         flag.PrintDefaults()
111 }
112
113 func main() {
114         log.SetPrefix("guru: ")
115         log.SetFlags(0)
116
117         // Don't print full help unless -help was requested.
118         // Just gently remind users that it's there.
119         flag.Usage = func() { fmt.Fprint(os.Stderr, useHelp) }
120         flag.CommandLine.Init(os.Args[0], flag.ContinueOnError) // hack
121         if err := flag.CommandLine.Parse(os.Args[1:]); err != nil {
122                 // (err has already been printed)
123                 if err == flag.ErrHelp {
124                         printHelp()
125                 }
126                 os.Exit(2)
127         }
128
129         args := flag.Args()
130         if len(args) != 2 {
131                 flag.Usage()
132                 os.Exit(2)
133         }
134         mode, posn := args[0], args[1]
135
136         if mode == "help" {
137                 printHelp()
138                 os.Exit(2)
139         }
140
141         // Set up points-to analysis log file.
142         var ptalog io.Writer
143         if *ptalogFlag != "" {
144                 if f, err := os.Create(*ptalogFlag); err != nil {
145                         log.Fatalf("Failed to create PTA log file: %s", err)
146                 } else {
147                         buf := bufio.NewWriter(f)
148                         ptalog = buf
149                         defer func() {
150                                 if err := buf.Flush(); err != nil {
151                                         log.Printf("flush: %s", err)
152                                 }
153                                 if err := f.Close(); err != nil {
154                                         log.Printf("close: %s", err)
155                                 }
156                         }()
157                 }
158         }
159
160         // Profiling support.
161         if *cpuprofileFlag != "" {
162                 f, err := os.Create(*cpuprofileFlag)
163                 if err != nil {
164                         log.Fatal(err)
165                 }
166                 pprof.StartCPUProfile(f)
167                 defer pprof.StopCPUProfile()
168         }
169
170         ctxt := &build.Default
171
172         // If there were modified files,
173         // read them from the standard input and
174         // overlay them on the build context.
175         if *modifiedFlag {
176                 modified, err := buildutil.ParseOverlayArchive(os.Stdin)
177                 if err != nil {
178                         log.Fatal(err)
179                 }
180
181                 // All I/O done by guru needs to consult the modified map.
182                 // The ReadFile done by referrers does,
183                 // but the loader's cgo preprocessing currently does not.
184
185                 if len(modified) > 0 {
186                         ctxt = buildutil.OverlayContext(ctxt, modified)
187                 }
188         }
189
190         var outputMu sync.Mutex
191         output := func(fset *token.FileSet, qr QueryResult) {
192                 outputMu.Lock()
193                 defer outputMu.Unlock()
194                 if *jsonFlag {
195                         // JSON output
196                         fmt.Printf("%s\n", qr.JSON(fset))
197                 } else {
198                         // plain output
199                         printf := func(pos interface{}, format string, args ...interface{}) {
200                                 fprintf(os.Stdout, fset, pos, format, args...)
201                         }
202                         qr.PrintPlain(printf)
203                 }
204         }
205
206         // Avoid corner case of split("").
207         var scope []string
208         if *scopeFlag != "" {
209                 scope = strings.Split(*scopeFlag, ",")
210         }
211
212         // Ask the guru.
213         query := Query{
214                 Pos:        posn,
215                 Build:      ctxt,
216                 Scope:      scope,
217                 PTALog:     ptalog,
218                 Reflection: *reflectFlag,
219                 Output:     output,
220         }
221
222         if err := Run(mode, &query); err != nil {
223                 log.Fatal(err)
224         }
225 }