github.com/sirkon/goproxy@v1.4.8/internal/vet/vetflag.go (about)

     1  // Copyright 2017 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 vet
     6  
     7  import (
     8  	"flag"
     9  	"fmt"
    10  	"os"
    11  	"strings"
    12  
    13  	"github.com/sirkon/goproxy/internal/base"
    14  	"github.com/sirkon/goproxy/internal/cmdflag"
    15  	"github.com/sirkon/goproxy/internal/str"
    16  	"github.com/sirkon/goproxy/internal/work"
    17  )
    18  
    19  const cmd = "vet"
    20  
    21  // vetFlagDefn is the set of flags we process.
    22  var vetFlagDefn = []*cmdflag.Defn{
    23  	// Note: Some flags, in particular -tags and -v, are known to
    24  	// vet but also defined as build flags. This works fine, so we
    25  	// don't define them here but use AddBuildFlags to init them.
    26  	// However some, like -x, are known to the build but not
    27  	// to vet. We handle them in vetFlags.
    28  
    29  	// local.
    30  	{Name: "all", BoolVar: new(bool), PassToTest: true},
    31  	{Name: "asmdecl", BoolVar: new(bool), PassToTest: true},
    32  	{Name: "assign", BoolVar: new(bool), PassToTest: true},
    33  	{Name: "atomic", BoolVar: new(bool), PassToTest: true},
    34  	{Name: "bool", BoolVar: new(bool), PassToTest: true},
    35  	{Name: "buildtags", BoolVar: new(bool), PassToTest: true},
    36  	{Name: "cgocall", BoolVar: new(bool), PassToTest: true},
    37  	{Name: "composites", BoolVar: new(bool), PassToTest: true},
    38  	{Name: "copylocks", BoolVar: new(bool), PassToTest: true},
    39  	{Name: "httpresponse", BoolVar: new(bool), PassToTest: true},
    40  	{Name: "lostcancel", BoolVar: new(bool), PassToTest: true},
    41  	{Name: "methods", BoolVar: new(bool), PassToTest: true},
    42  	{Name: "nilfunc", BoolVar: new(bool), PassToTest: true},
    43  	{Name: "printf", BoolVar: new(bool), PassToTest: true},
    44  	{Name: "printfuncs", PassToTest: true},
    45  	{Name: "rangeloops", BoolVar: new(bool), PassToTest: true},
    46  	{Name: "shadow", BoolVar: new(bool), PassToTest: true},
    47  	{Name: "shadowstrict", BoolVar: new(bool), PassToTest: true},
    48  	{Name: "shift", BoolVar: new(bool), PassToTest: true},
    49  	{Name: "source", BoolVar: new(bool), PassToTest: true},
    50  	{Name: "structtags", BoolVar: new(bool), PassToTest: true},
    51  	{Name: "tests", BoolVar: new(bool), PassToTest: true},
    52  	{Name: "unreachable", BoolVar: new(bool), PassToTest: true},
    53  	{Name: "unsafeptr", BoolVar: new(bool), PassToTest: true},
    54  	{Name: "unusedfuncs", PassToTest: true},
    55  	{Name: "unusedresult", BoolVar: new(bool), PassToTest: true},
    56  	{Name: "unusedstringmethods", PassToTest: true},
    57  }
    58  
    59  var vetTool string
    60  
    61  // add build flags to vetFlagDefn.
    62  func init() {
    63  	cmdflag.AddKnownFlags("vet", vetFlagDefn)
    64  	var cmd base.Command
    65  	work.AddBuildFlags(&cmd)
    66  	cmd.Flag.StringVar(&vetTool, "vettool", "", "path to vet tool binary") // for cmd/vet tests; undocumented for now
    67  	cmd.Flag.VisitAll(func(f *flag.Flag) {
    68  		vetFlagDefn = append(vetFlagDefn, &cmdflag.Defn{
    69  			Name:  f.Name,
    70  			Value: f.Value,
    71  		})
    72  	})
    73  }
    74  
    75  // vetFlags processes the command line, splitting it at the first non-flag
    76  // into the list of flags and list of packages.
    77  func vetFlags(args []string) (passToVet, packageNames []string) {
    78  	args = str.StringList(cmdflag.FindGOFLAGS(vetFlagDefn), args)
    79  	for i := 0; i < len(args); i++ {
    80  		if !strings.HasPrefix(args[i], "-") {
    81  			return args[:i], args[i:]
    82  		}
    83  
    84  		f, value, extraWord := cmdflag.Parse(cmd, vetFlagDefn, args, i)
    85  		if f == nil {
    86  			fmt.Fprintf(os.Stderr, "vet: flag %q not defined\n", args[i])
    87  			fmt.Fprintf(os.Stderr, "Run \"go help vet\" for more information\n")
    88  			os.Exit(2)
    89  		}
    90  		if f.Value != nil {
    91  			if err := f.Value.Set(value); err != nil {
    92  				base.Fatalf("invalid flag argument for -%s: %v", f.Name, err)
    93  			}
    94  			keep := f.PassToTest
    95  			if !keep {
    96  				// A build flag, probably one we don't want to pass to vet.
    97  				// Can whitelist.
    98  				switch f.Name {
    99  				case "tags", "v":
   100  					keep = true
   101  				}
   102  			}
   103  			if !keep {
   104  				// Flags known to the build but not to vet, so must be dropped.
   105  				if extraWord {
   106  					args = append(args[:i], args[i+2:]...)
   107  					extraWord = false
   108  				} else {
   109  					args = append(args[:i], args[i+1:]...)
   110  				}
   111  				i--
   112  			}
   113  		}
   114  		if extraWord {
   115  			i++
   116  		}
   117  	}
   118  	return args, nil
   119  }