/
vet.go
121 lines (105 loc) · 3.33 KB
/
vet.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Package vet implements the ``go vet'' command.
package vet
import (
"cmd/go/internal/base"
"cmd/go/internal/load"
"cmd/go/internal/modload"
"cmd/go/internal/work"
"path/filepath"
)
var CmdVet = &base.Command{
Run: runVet,
CustomFlags: true,
UsageLine: "go vet [-n] [-x] [-vettool prog] [build flags] [vet flags] [packages]",
Short: "report likely mistakes in packages",
Long: `
Vet runs the Go vet command on the packages named by the import paths.
For more about vet and its flags, see 'go doc cmd/vet'.
For more about specifying packages, see 'go help packages'.
For a list of checkers and their flags, see 'go tool vet help'.
For details of a specific checker such as 'printf', see 'go tool vet help printf'.
The -n flag prints commands that would be executed.
The -x flag prints commands as they are executed.
The -vettool=prog flag selects a different analysis tool with alternative
or additional checks.
For example, the 'shadow' analyzer can be built and run using these commands:
go install golang.org/x/tools/go/analysis/passes/shadow/cmd/shadow
go vet -vettool=$(which shadow)
The build flags supported by go vet are those that control package resolution
and execution, such as -n, -x, -v, -tags, and -toolexec.
For more about these flags, see 'go help build'.
See also: go fmt, go fix.
`,
}
func runVet(cmd *base.Command, args []string) {
modload.LoadTests = true
vetFlags, pkgArgs := vetFlags(vetUsage, args)
work.BuildInit()
work.VetFlags = vetFlags
work.VetExplicit = true
if vetTool != "" {
var err error
work.VetTool, err = filepath.Abs(vetTool)
if err != nil {
base.Fatalf("%v", err)
}
}
pkgs := load.PackagesForBuild(pkgArgs)
if len(pkgs) == 0 {
base.Fatalf("no packages to vet")
}
var b work.Builder
b.Init()
root := &work.Action{Mode: "go vet"}
for _, p := range pkgs {
_, ptest, pxtest, err := testPackagesFor(p)
if err != nil {
base.Errorf("%v", err)
continue
}
if len(ptest.GoFiles) == 0 && len(ptest.CgoFiles) == 0 && pxtest == nil {
base.Errorf("go vet %s: no Go files in %s", p.ImportPath, p.Dir)
continue
}
if len(ptest.GoFiles) > 0 || len(ptest.CgoFiles) > 0 {
root.Deps = append(root.Deps, b.VetAction(work.ModeBuild, work.ModeBuild, ptest))
}
if pxtest != nil {
root.Deps = append(root.Deps, b.VetAction(work.ModeBuild, work.ModeBuild, pxtest))
}
}
b.Do(root)
}
// testPackagesFor is like load.TestPackagesAndErrors but it returns
// an error if the test packages or their dependencies have errors.
// Only test packages without errors are returned.
func testPackagesFor(p *load.Package) (pmain, ptest, pxtest *load.Package, err error) {
pmain, ptest, pxtest = load.TestPackagesAndErrors(p, nil)
for _, p1 := range []*load.Package{ptest, pxtest, pmain} {
if p1 == nil {
// pxtest may be nil
continue
}
if p1.Error != nil {
err = p1.Error
break
}
if len(p1.DepsErrors) > 0 {
err = p1.DepsErrors[0]
break
}
}
if pmain.Error != nil || len(pmain.DepsErrors) > 0 {
pmain = nil
}
if ptest.Error != nil || len(ptest.DepsErrors) > 0 {
ptest = nil
}
if pxtest != nil && (pxtest.Error != nil || len(pxtest.DepsErrors) > 0) {
pxtest = nil
}
return pmain, ptest, pxtest, err
}