1
0
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:
Rob Pike 2012-07-16 14:03:11 -07:00
parent 8de5080f34
commit f49b7b0acf
6 changed files with 53 additions and 15 deletions

View File

@ -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

View File

@ -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 {

View File

@ -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[)]"
}

View File

@ -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")

View File

@ -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"
}

View File

@ -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`
}