mirror of
https://github.com/golang/go
synced 2024-11-20 09:04:44 -07:00
cmd/vet: provide flags to control which tests to run
By default, all are still run, but a particular test can be selected with the new flags. R=golang-dev, bradfitz CC=golang-dev https://golang.org/cl/6395053
This commit is contained in:
parent
8de5080f34
commit
f49b7b0acf
@ -9,9 +9,12 @@ calls whose arguments do not align with the format string. Vet uses heuristics
|
|||||||
that do not guarantee all reports are genuine problems, but it can find errors
|
that do not guarantee all reports are genuine problems, but it can find errors
|
||||||
not caught by the compilers.
|
not caught by the compilers.
|
||||||
|
|
||||||
|
By default all checks are performed, but if explicit flags are provided, only
|
||||||
|
those identified by the flags are performed.
|
||||||
|
|
||||||
Available checks:
|
Available checks:
|
||||||
|
|
||||||
1. Printf family
|
1. Printf family, flag -printf
|
||||||
|
|
||||||
Suspicious calls to functions in the Printf family, including any functions
|
Suspicious calls to functions in the Printf family, including any functions
|
||||||
with these names:
|
with these names:
|
||||||
@ -28,7 +31,7 @@ complains about arguments that look like format descriptor strings.
|
|||||||
It also checks for errors such as using a Writer as the first argument of
|
It also checks for errors such as using a Writer as the first argument of
|
||||||
Printf.
|
Printf.
|
||||||
|
|
||||||
2. Methods
|
2. Methods, flag -methods
|
||||||
|
|
||||||
Non-standard signatures for methods with familiar names, including:
|
Non-standard signatures for methods with familiar names, including:
|
||||||
Format GobEncode GobDecode MarshalJSON MarshalXML
|
Format GobEncode GobDecode MarshalJSON MarshalXML
|
||||||
@ -36,16 +39,21 @@ Non-standard signatures for methods with familiar names, including:
|
|||||||
UnmarshalJSON UnreadByte UnreadRune WriteByte
|
UnmarshalJSON UnreadByte UnreadRune WriteByte
|
||||||
WriteTo
|
WriteTo
|
||||||
|
|
||||||
3. Struct tags
|
3. Struct tags, flag -structtags
|
||||||
|
|
||||||
Struct tags that do not follow the format understood by reflect.StructTag.Get.
|
Struct tags that do not follow the format understood by reflect.StructTag.Get.
|
||||||
|
|
||||||
|
4. Untagged composite literals, flag -composites
|
||||||
|
|
||||||
|
Composite struct literals that do not used the type-tagged syntax.
|
||||||
|
|
||||||
|
|
||||||
Usage:
|
Usage:
|
||||||
|
|
||||||
go tool vet [flag] [file.go ...]
|
go tool vet [flag] [file.go ...]
|
||||||
go tool vet [flag] [directory ...] # Scan all .go files under directory, recursively
|
go tool vet [flag] [directory ...] # Scan all .go files under directory, recursively
|
||||||
|
|
||||||
The flags are:
|
The other flags are:
|
||||||
-v
|
-v
|
||||||
Verbose mode
|
Verbose mode
|
||||||
-printfuncs
|
-printfuncs
|
||||||
|
@ -23,6 +23,15 @@ import (
|
|||||||
var verbose = flag.Bool("v", false, "verbose")
|
var verbose = flag.Bool("v", false, "verbose")
|
||||||
var exitCode = 0
|
var exitCode = 0
|
||||||
|
|
||||||
|
// Flags to control which checks to perform
|
||||||
|
var (
|
||||||
|
vetAll = flag.Bool("all", true, "check everything; disabled if any explicit check is requested")
|
||||||
|
vetMethods = flag.Bool("methods", false, "check that canonically named methods are canonically defined")
|
||||||
|
vetPrintf = flag.Bool("printf", false, "check printf-like invocations")
|
||||||
|
vetStructTags = flag.Bool("structtags", false, "check that struct field tags have canonical format")
|
||||||
|
vetUntaggedLiteral = flag.Bool("composites", false, "check that composite literals used type-tagged elements")
|
||||||
|
)
|
||||||
|
|
||||||
// setExit sets the value for os.Exit when it is called, later. It
|
// setExit sets the value for os.Exit when it is called, later. It
|
||||||
// remembers the highest value.
|
// remembers the highest value.
|
||||||
func setExit(err int) {
|
func setExit(err int) {
|
||||||
@ -50,6 +59,11 @@ func main() {
|
|||||||
flag.Usage = Usage
|
flag.Usage = Usage
|
||||||
flag.Parse()
|
flag.Parse()
|
||||||
|
|
||||||
|
// If a check is named explicitly, turn off the 'all' flag.
|
||||||
|
if *vetMethods || *vetPrintf || *vetStructTags || *vetUntaggedLiteral {
|
||||||
|
*vetAll = false
|
||||||
|
}
|
||||||
|
|
||||||
if *printfuncs != "" {
|
if *printfuncs != "" {
|
||||||
for _, name := range strings.Split(*printfuncs, ",") {
|
for _, name := range strings.Split(*printfuncs, ",") {
|
||||||
if len(name) == 0 {
|
if len(name) == 0 {
|
||||||
|
@ -55,6 +55,9 @@ var canonicalMethods = map[string]MethodSig{
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (f *File) checkCanonicalMethod(id *ast.Ident, t *ast.FuncType) {
|
func (f *File) checkCanonicalMethod(id *ast.Ident, t *ast.FuncType) {
|
||||||
|
if !*vetMethods && !*vetAll {
|
||||||
|
return
|
||||||
|
}
|
||||||
// Expected input/output.
|
// Expected input/output.
|
||||||
expect, ok := canonicalMethods[id.Name]
|
expect, ok := canonicalMethods[id.Name]
|
||||||
if !ok {
|
if !ok {
|
||||||
@ -159,3 +162,10 @@ func (f *File) matchParamType(expect string, actual ast.Expr) bool {
|
|||||||
printer.Fprint(&f.b, f.fset, actual)
|
printer.Fprint(&f.b, f.fset, actual)
|
||||||
return f.b.String() == expect
|
return f.b.String() == expect
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (t *BadTypeUsedInTests) Scan(x fmt.ScanState, c byte) { // ERROR "method Scan[(]x fmt.ScanState, c byte[)] should have signature Scan[(]fmt.ScanState, rune[)] error"
|
||||||
|
}
|
||||||
|
|
||||||
|
type BadInterfaceUsedInTests interface {
|
||||||
|
ReadByte() byte // ERROR "method ReadByte[(][)] byte should have signature ReadByte[(][)] [(]byte, error[)]"
|
||||||
|
}
|
||||||
|
@ -43,6 +43,9 @@ var printList = map[string]int{
|
|||||||
|
|
||||||
// checkCall triggers the print-specific checks if the call invokes a print function.
|
// checkCall triggers the print-specific checks if the call invokes a print function.
|
||||||
func (f *File) checkFmtPrintfCall(call *ast.CallExpr, Name string) {
|
func (f *File) checkFmtPrintfCall(call *ast.CallExpr, Name string) {
|
||||||
|
if !*vetPrintf && !*vetAll {
|
||||||
|
return
|
||||||
|
}
|
||||||
name := strings.ToLower(Name)
|
name := strings.ToLower(Name)
|
||||||
if skip, ok := printfList[name]; ok {
|
if skip, ok := printfList[name]; ok {
|
||||||
f.checkPrintf(call, Name, skip)
|
f.checkPrintf(call, Name, skip)
|
||||||
@ -290,17 +293,6 @@ func BadFunctionUsedInTests() {
|
|||||||
f.Warnf(0, "%#s", "hello") // ERROR "unrecognized printf flag"
|
f.Warnf(0, "%#s", "hello") // ERROR "unrecognized printf flag"
|
||||||
}
|
}
|
||||||
|
|
||||||
type BadTypeUsedInTests struct {
|
|
||||||
X int "hello" // ERROR "struct field tag"
|
|
||||||
}
|
|
||||||
|
|
||||||
func (t *BadTypeUsedInTests) Scan(x fmt.ScanState, c byte) { // ERROR "method Scan[(]x fmt.ScanState, c byte[)] should have signature Scan[(]fmt.ScanState, rune[)] error"
|
|
||||||
}
|
|
||||||
|
|
||||||
type BadInterfaceUsedInTests interface {
|
|
||||||
ReadByte() byte // ERROR "method ReadByte[(][)] byte should have signature ReadByte[(][)] [(]byte, error[)]"
|
|
||||||
}
|
|
||||||
|
|
||||||
// printf is used by the test.
|
// printf is used by the test.
|
||||||
func printf(format string, args ...interface{}) {
|
func printf(format string, args ...interface{}) {
|
||||||
panic("don't call - testing only")
|
panic("don't call - testing only")
|
||||||
|
@ -14,6 +14,9 @@ import (
|
|||||||
|
|
||||||
// checkField checks a struct field tag.
|
// checkField checks a struct field tag.
|
||||||
func (f *File) checkCanonicalFieldTag(field *ast.Field) {
|
func (f *File) checkCanonicalFieldTag(field *ast.Field) {
|
||||||
|
if !*vetStructTags && !*vetAll {
|
||||||
|
return
|
||||||
|
}
|
||||||
if field.Tag == nil {
|
if field.Tag == nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -32,3 +35,7 @@ func (f *File) checkCanonicalFieldTag(field *ast.Field) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type BadTypeUsedInTests struct {
|
||||||
|
X int "hello" // ERROR "struct field tag"
|
||||||
|
}
|
||||||
|
@ -14,6 +14,9 @@ import (
|
|||||||
// checkUntaggedLiteral checks if a composite literal is an struct literal with
|
// checkUntaggedLiteral checks if a composite literal is an struct literal with
|
||||||
// untagged fields.
|
// untagged fields.
|
||||||
func (f *File) checkUntaggedLiteral(c *ast.CompositeLit) {
|
func (f *File) checkUntaggedLiteral(c *ast.CompositeLit) {
|
||||||
|
if !*vetUntaggedLiteral && !*vetAll {
|
||||||
|
return
|
||||||
|
}
|
||||||
// Check if the CompositeLit contains an untagged field.
|
// Check if the CompositeLit contains an untagged field.
|
||||||
allKeyValue := true
|
allKeyValue := true
|
||||||
for _, e := range c.Elts {
|
for _, e := range c.Elts {
|
||||||
@ -119,3 +122,7 @@ var untaggedLiteralWhitelist = map[string]bool{
|
|||||||
"image.Point": true,
|
"image.Point": true,
|
||||||
"image.Rectangle": true,
|
"image.Rectangle": true,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type BadTag struct {
|
||||||
|
S string `this is a bad tag`
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user