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