Source file src/cmd/vendor/golang.org/x/tools/go/analysis/internal/analysisflags/help.go

     1  // Copyright 2018 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  package analysisflags
     6  
     7  import (
     8  	"flag"
     9  	"fmt"
    10  	"log"
    11  	"os"
    12  	"sort"
    13  	"strings"
    14  
    15  	"golang.org/x/tools/go/analysis"
    16  )
    17  
    18  const help = `PROGNAME is a tool for static analysis of Go programs.
    19  
    20  PROGNAME examines Go source code and reports diagnostics for
    21  suspicious constructs or opportunities for improvement.
    22  Diagnostics may include suggested fixes.
    23  
    24  An example of a suspicious construct is a Printf call whose arguments
    25  do not align with the format string. Analyzers may use heuristics that
    26  do not guarantee all reports are genuine problems, but can find
    27  mistakes not caught by the compiler.
    28  
    29  An example of an opportunity for improvement is a loop over
    30  strings.Split(doc, "\n"), which may be replaced by a loop over the
    31  strings.SplitSeq iterator, avoiding an array allocation.
    32  Diagnostics in such cases may report non-problems,
    33  but should carry fixes that may be safely applied.
    34  
    35  For analyzers of the first kind, use "go vet -vettool=PROGRAM"
    36  to run the tool and report diagnostics.
    37  
    38  For analyzers of the second kind, use "go fix -fixtool=PROGRAM"
    39  to run the tool and apply the fixes it suggests.
    40  `
    41  
    42  // Help implements the help subcommand for a multichecker or unitchecker
    43  // style command. The optional args specify the analyzers to describe.
    44  // Help calls log.Fatal if no such analyzer exists.
    45  func Help(progname string, analyzers []*analysis.Analyzer, args []string) {
    46  	// No args: show summary of all analyzers.
    47  	if len(args) == 0 {
    48  		fmt.Println(strings.ReplaceAll(help, "PROGNAME", progname))
    49  		fmt.Println("Registered analyzers:")
    50  		fmt.Println()
    51  		sort.Slice(analyzers, func(i, j int) bool {
    52  			return analyzers[i].Name < analyzers[j].Name
    53  		})
    54  		for _, a := range analyzers {
    55  			title := strings.Split(a.Doc, "\n\n")[0]
    56  			fmt.Printf("    %-12s %s\n", a.Name, title)
    57  		}
    58  		fmt.Println("\nBy default all analyzers are run.")
    59  		fmt.Println("To select specific analyzers, use the -NAME flag for each one,")
    60  		fmt.Println(" or -NAME=false to run all analyzers not explicitly disabled.")
    61  
    62  		// Show only the core command-line flags.
    63  		fmt.Println("\nCore flags:")
    64  		fmt.Println()
    65  		fs := flag.NewFlagSet("", flag.ExitOnError)
    66  		flag.VisitAll(func(f *flag.Flag) {
    67  			if !strings.Contains(f.Name, ".") {
    68  				fs.Var(f.Value, f.Name, f.Usage)
    69  			}
    70  		})
    71  		fs.SetOutput(os.Stdout)
    72  		fs.PrintDefaults()
    73  
    74  		fmt.Printf("\nTo see details and flags of a specific analyzer, run '%s help name'.\n", progname)
    75  
    76  		return
    77  	}
    78  
    79  	// Show help on specific analyzer(s).
    80  outer:
    81  	for _, arg := range args {
    82  		for _, a := range analyzers {
    83  			if a.Name == arg {
    84  				paras := strings.Split(a.Doc, "\n\n")
    85  				title := paras[0]
    86  				fmt.Printf("%s: %s\n", a.Name, title)
    87  
    88  				// Show only the flags relating to this analysis,
    89  				// properly prefixed.
    90  				first := true
    91  				fs := flag.NewFlagSet(a.Name, flag.ExitOnError)
    92  				a.Flags.VisitAll(func(f *flag.Flag) {
    93  					if first {
    94  						first = false
    95  						fmt.Println("\nAnalyzer flags:")
    96  						fmt.Println()
    97  					}
    98  					fs.Var(f.Value, a.Name+"."+f.Name, f.Usage)
    99  				})
   100  				fs.SetOutput(os.Stdout)
   101  				fs.PrintDefaults()
   102  
   103  				if len(paras) > 1 {
   104  					fmt.Printf("\n%s\n", strings.Join(paras[1:], "\n\n"))
   105  				}
   106  
   107  				continue outer
   108  			}
   109  		}
   110  		log.Fatalf("Analyzer %q not registered", arg)
   111  	}
   112  }
   113  

View as plain text