1
2
3
4
5
6 package vet
7
8 import (
9 "context"
10 "fmt"
11 "path/filepath"
12
13 "cmd/go/internal/base"
14 "cmd/go/internal/cfg"
15 "cmd/go/internal/load"
16 "cmd/go/internal/modload"
17 "cmd/go/internal/trace"
18 "cmd/go/internal/work"
19 )
20
21
22 func init() {
23 CmdVet.Run = runVet
24 }
25
26 var CmdVet = &base.Command{
27 CustomFlags: true,
28 UsageLine: "go vet [build flags] [-vettool prog] [vet flags] [packages]",
29 Short: "report likely mistakes in packages",
30 Long: `
31 Vet runs the Go vet command on the packages named by the import paths.
32
33 For more about vet and its flags, see 'go doc cmd/vet'.
34 For more about specifying packages, see 'go help packages'.
35 For a list of checkers and their flags, see 'go tool vet help'.
36 For details of a specific checker such as 'printf', see 'go tool vet help printf'.
37
38 The -vettool=prog flag selects a different analysis tool with alternative
39 or additional checks.
40 For example, the 'shadow' analyzer can be built and run using these commands:
41
42 go install golang.org/x/tools/go/analysis/passes/shadow/cmd/shadow@latest
43 go vet -vettool=$(which shadow)
44
45 The build flags supported by go vet are those that control package resolution
46 and execution, such as -C, -n, -x, -v, -tags, and -toolexec.
47 For more about these flags, see 'go help build'.
48
49 See also: go fmt, go fix.
50 `,
51 }
52
53 func runVet(ctx context.Context, cmd *base.Command, args []string) {
54 vetFlags, pkgArgs := vetFlags(args)
55 modload.InitWorkfile()
56
57 if cfg.DebugTrace != "" {
58 var close func() error
59 var err error
60 ctx, close, err = trace.Start(ctx, cfg.DebugTrace)
61 if err != nil {
62 base.Fatalf("failed to start trace: %v", err)
63 }
64 defer func() {
65 if err := close(); err != nil {
66 base.Fatalf("failed to stop trace: %v", err)
67 }
68 }()
69 }
70
71 ctx, span := trace.StartSpan(ctx, fmt.Sprint("Running ", cmd.Name(), " command"))
72 defer span.Done()
73
74 work.BuildInit()
75 work.VetFlags = vetFlags
76 if len(vetFlags) > 0 {
77 work.VetExplicit = true
78 }
79 if vetTool != "" {
80 var err error
81 work.VetTool, err = filepath.Abs(vetTool)
82 if err != nil {
83 base.Fatalf("%v", err)
84 }
85 }
86
87 pkgOpts := load.PackageOpts{ModResolveTests: true}
88 pkgs := load.PackagesAndErrors(ctx, pkgOpts, pkgArgs)
89 load.CheckPackageErrors(pkgs)
90 if len(pkgs) == 0 {
91 base.Fatalf("no packages to vet")
92 }
93
94 b := work.NewBuilder("")
95 defer func() {
96 if err := b.Close(); err != nil {
97 base.Fatal(err)
98 }
99 }()
100
101 root := &work.Action{Mode: "go vet"}
102 for _, p := range pkgs {
103 _, ptest, pxtest, err := load.TestPackagesFor(ctx, pkgOpts, p, nil)
104 if err != nil {
105 base.Errorf("%v", err)
106 continue
107 }
108 if len(ptest.GoFiles) == 0 && len(ptest.CgoFiles) == 0 && pxtest == nil {
109 base.Errorf("go: can't vet %s: no Go files in %s", p.ImportPath, p.Dir)
110 continue
111 }
112 if len(ptest.GoFiles) > 0 || len(ptest.CgoFiles) > 0 {
113 root.Deps = append(root.Deps, b.VetAction(work.ModeBuild, work.ModeBuild, ptest))
114 }
115 if pxtest != nil {
116 root.Deps = append(root.Deps, b.VetAction(work.ModeBuild, work.ModeBuild, pxtest))
117 }
118 }
119 b.Do(ctx, root)
120 }
121
View as plain text