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