Source file src/pkg/cmd/go/internal/vet/vetflag.go
1
2
3
4
5 package vet
6
7 import (
8 "bytes"
9 "encoding/json"
10 "flag"
11 "fmt"
12 "log"
13 "os"
14 "os/exec"
15 "path/filepath"
16 "strings"
17
18 "cmd/go/internal/base"
19 "cmd/go/internal/cmdflag"
20 "cmd/go/internal/str"
21 "cmd/go/internal/work"
22 )
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39 var vetTool string
40
41 func init() {
42
43
44
45 for i, arg := range os.Args {
46 if arg == "-vettool" || arg == "--vettool" {
47 if i+1 >= len(os.Args) {
48 log.Fatalf("%s requires a filename", arg)
49 }
50 vetTool = os.Args[i+1]
51 break
52 } else if strings.HasPrefix(arg, "-vettool=") ||
53 strings.HasPrefix(arg, "--vettool=") {
54 vetTool = arg[strings.IndexByte(arg, '=')+1:]
55 break
56 }
57 }
58 }
59
60
61
62 func vetFlags(usage func(), args []string) (passToVet, packageNames []string) {
63
64 tool := vetTool
65 if tool != "" {
66 var err error
67 tool, err = filepath.Abs(tool)
68 if err != nil {
69 log.Fatal(err)
70 }
71 } else {
72 tool = base.Tool("vet")
73 }
74 out := new(bytes.Buffer)
75 vetcmd := exec.Command(tool, "-flags")
76 vetcmd.Stdout = out
77 if err := vetcmd.Run(); err != nil {
78 fmt.Fprintf(os.Stderr, "go vet: can't execute %s -flags: %v\n", tool, err)
79 base.SetExitStatus(2)
80 base.Exit()
81 }
82 var analysisFlags []struct {
83 Name string
84 Bool bool
85 Usage string
86 }
87 if err := json.Unmarshal(out.Bytes(), &analysisFlags); err != nil {
88 fmt.Fprintf(os.Stderr, "go vet: can't unmarshal JSON from %s -flags: %v", tool, err)
89 base.SetExitStatus(2)
90 base.Exit()
91 }
92
93
94
95
96
97
98
99 var vetFlagDefn []*cmdflag.Defn
100 for _, f := range analysisFlags {
101 switch f.Name {
102 case "tags", "v":
103 continue
104 }
105 defn := &cmdflag.Defn{
106 Name: f.Name,
107 PassToTest: true,
108 }
109 if f.Bool {
110 defn.BoolVar = new(bool)
111 }
112 vetFlagDefn = append(vetFlagDefn, defn)
113 }
114
115
116 var cmd base.Command
117 work.AddBuildFlags(&cmd)
118
119
120 cmd.Flag.StringVar(new(string), "vettool", "", "path to vet tool binary")
121 cmd.Flag.VisitAll(func(f *flag.Flag) {
122 vetFlagDefn = append(vetFlagDefn, &cmdflag.Defn{
123 Name: f.Name,
124 Value: f.Value,
125 })
126 })
127
128
129 args = str.StringList(cmdflag.FindGOFLAGS(vetFlagDefn), args)
130 for i := 0; i < len(args); i++ {
131 if !strings.HasPrefix(args[i], "-") {
132 return args[:i], args[i:]
133 }
134
135 f, value, extraWord := cmdflag.Parse("vet", usage, vetFlagDefn, args, i)
136 if f == nil {
137 fmt.Fprintf(os.Stderr, "vet: flag %q not defined\n", args[i])
138 fmt.Fprintf(os.Stderr, "Run \"go help vet\" for more information\n")
139 base.SetExitStatus(2)
140 base.Exit()
141 }
142 if f.Value != nil {
143 if err := f.Value.Set(value); err != nil {
144 base.Fatalf("invalid flag argument for -%s: %v", f.Name, err)
145 }
146 keep := f.PassToTest
147 if !keep {
148
149
150 switch f.Name {
151 case "tags", "v":
152 keep = true
153 }
154 }
155 if !keep {
156
157 if extraWord {
158 args = append(args[:i], args[i+2:]...)
159 extraWord = false
160 } else {
161 args = append(args[:i], args[i+1:]...)
162 }
163 i--
164 }
165 }
166 if extraWord {
167 i++
168 }
169 }
170 return args, nil
171 }
172
173 var vetUsage func()
174
175 func init() { vetUsage = usage }
176
177 func usage() {
178 fmt.Fprintf(os.Stderr, "usage: %s\n", CmdVet.UsageLine)
179 fmt.Fprintf(os.Stderr, "Run 'go help %s' for details.\n", CmdVet.LongName())
180
181
182 cmd := "go tool vet"
183 if vetTool != "" {
184 cmd = vetTool
185 }
186 fmt.Fprintf(os.Stderr, "Run '%s -help' for the vet tool's flags.\n", cmd)
187
188 base.SetExitStatus(2)
189 base.Exit()
190 }
191
View as plain text