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  }