]> Cypherpunks repositories - gostls13.git/commitdiff
vet: improve flag handling
authorRob Pike <r@golang.org>
Mon, 11 Feb 2013 21:33:11 +0000 (13:33 -0800)
committerRob Pike <r@golang.org>
Mon, 11 Feb 2013 21:33:11 +0000 (13:33 -0800)
Simplify the internal logic for flags controlling what to vet,
by introducing a map of flags that gathers them all together.
This change should simplify the process of adding further flags.

Add a test for untagged struct literals.
Delete a redundant test that was also in the wrong file.
Clean up some ERROR patterns that weren't working.

"make test" passes again.

R=golang-dev, bradfitz
CC=golang-dev
https://golang.org/cl/7305075

src/cmd/vet/atomic.go
src/cmd/vet/buildtag.go
src/cmd/vet/main.go
src/cmd/vet/method.go
src/cmd/vet/print.go
src/cmd/vet/rangeloop.go
src/cmd/vet/structtag.go
src/cmd/vet/taglit.go

index 7a76e9b91587debe1d7d37506e6be2571d72d17c..9c7ae7dbfcb996738904f829278ac306e9604e1c 100644 (file)
@@ -13,7 +13,7 @@ import (
 // checkAtomicAssignment walks the assignment statement checking for comomon
 // mistaken usage of atomic package, such as: x = atomic.AddUint64(&x, 1)
 func (f *File) checkAtomicAssignment(n *ast.AssignStmt) {
-       if !*vetAtomic && !*vetAll {
+       if !vet("atomic") {
                return
        }
 
index 2fd6625de9f151fdc18672e9f4200634f271fe05..bd1dd2d378813d3158928928ae9bbbdeb62d22b7 100644 (file)
@@ -25,7 +25,7 @@ var (
 
 // checkBuildTag checks that build tags are in the correct location and well-formed.
 func checkBuildTag(name string, data []byte) {
-       if !*vetBuildTags && !*vetAll {
+       if !vet("buildtags") {
                return
        }
        lines := bytes.SplitAfter(data, nl)
index 22e3073869f8e8f7327bc35552c988bdcab8ceaf..c7676e22f104a13ee79bfbec4dd0447adb039a85 100644 (file)
@@ -25,18 +25,23 @@ import (
 var verbose = flag.Bool("v", false, "verbose")
 var exitCode = 0
 
-// Flags to control which checks to perform.
-// NOTE: Add new flags to the if statement at the top of func main too.
-var (
-       vetAll             = flag.Bool("all", true, "check everything; disabled if any explicit check is requested")
-       vetAtomic          = flag.Bool("atomic", false, "check for common mistaken usages of the sync/atomic package")
-       vetBuildTags       = flag.Bool("buildtags", false, "check that +build tags are valid")
-       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")
-       vetRangeLoops      = flag.Bool("rangeloops", false, "check that range loop variables are used correctly")
-       vetUntaggedLiteral = flag.Bool("composites", false, "check that composite literals used type-tagged elements")
-)
+// Flags to control which checks to perform. "all" is set to true here, and disabled later if
+// a flag is set explicitly.
+var report = map[string]*bool{
+       "all":        flag.Bool("all", true, "check everything; disabled if any explicit check is requested"),
+       "atomic":     flag.Bool("atomic", false, "check for common mistaken usages of the sync/atomic package"),
+       "buildtags":  flag.Bool("buildtags", false, "check that +build tags are valid"),
+       "composites": flag.Bool("composites", false, "check that composite literals used type-tagged elements"),
+       "methods":    flag.Bool("methods", false, "check that canonically named methods are canonically defined"),
+       "printf":     flag.Bool("printf", false, "check printf-like invocations"),
+       "structtags": flag.Bool("structtags", false, "check that struct field tags have canonical format"),
+       "rangeloops": flag.Bool("rangeloops", false, "check that range loop variables are used correctly"),
+}
+
+// vet tells whether to report errors for the named check, a flag name.
+func vet(name string) bool {
+       return *report["all"] || *report[name]
+}
 
 // setExit sets the value for os.Exit when it is called, later.  It
 // remembers the highest value.
@@ -66,8 +71,11 @@ func main() {
        flag.Parse()
 
        // If a check is named explicitly, turn off the 'all' flag.
-       if *vetAtomic || *vetBuildTags || *vetMethods || *vetPrintf || *vetStructTags || *vetRangeLoops || *vetUntaggedLiteral {
-               *vetAll = false
+       for name, ptr := range report {
+               if name != "all" && *ptr {
+                       *report["all"] = false
+                       break
+               }
        }
 
        if *printfuncs != "" {
index dcfa8a02f395df32b677845fb115219b28d091f3..a01873df1ca717c9da2765cf74a575bcb0d83df8 100644 (file)
@@ -55,7 +55,7 @@ var canonicalMethods = map[string]MethodSig{
 }
 
 func (f *File) checkCanonicalMethod(id *ast.Ident, t *ast.FuncType) {
-       if !*vetMethods && !*vetAll {
+       if !vet("methods") {
                return
        }
        // Expected input/output.
@@ -161,9 +161,9 @@ func (f *File) matchParamType(expect string, actual ast.Expr) bool {
        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"
+func (t *BadTypeUsedInTests) Scan(x fmt.ScanState, c byte) { // ERROR "should have signature Scan"
 }
 
 type BadInterfaceUsedInTests interface {
-       ReadByte() byte // ERROR "method ReadByte[(][)] byte should have signature ReadByte[(][)] [(]byte, error[)]"
+       ReadByte() byte // ERROR "should have signature ReadByte"
 }
index ea85edac1dead17126c5ddb607c01851f1bee122..1fe112b4822ca1b628bc82b829028923ce38dd15 100644 (file)
@@ -44,7 +44,7 @@ var printList = map[string]int{
 
 // checkCall triggers the print-specific checks if the call invokes a print function.
 func (f *File) checkFmtPrintfCall(call *ast.CallExpr, Name string) {
-       if !*vetPrintf && !*vetAll {
+       if !vet("printf") {
                return
        }
        name := strings.ToLower(Name)
index 71cbc115799beda1041a12a7b40fd70a932b175c..1687fcb8a2636e6c39282539ff5316356d22cbc8 100644 (file)
@@ -27,7 +27,7 @@ import "go/ast"
 // its index or value variables are used unsafely inside goroutines or deferred
 // function literals.
 func checkRangeLoop(f *File, n *ast.RangeStmt) {
-       if !*vetRangeLoops && !*vetAll {
+       if !vet("rangeloops") {
                return
        }
        key, _ := n.Key.(*ast.Ident)
index 4aab2d086ff8a629bcb80c9007f42a2add40a1f4..4a04bb5b6305c17d10a22ab67d4d541f9c05c885 100644 (file)
@@ -14,7 +14,7 @@ import (
 
 // checkField checks a struct field tag.
 func (f *File) checkCanonicalFieldTag(field *ast.Field) {
-       if !*vetStructTags && !*vetAll {
+       if !vet("structtags") {
                return
        }
        if field.Tag == nil {
@@ -37,5 +37,5 @@ func (f *File) checkCanonicalFieldTag(field *ast.Field) {
 }
 
 type BadTypeUsedInTests struct {
-       X int "hello" // ERROR "struct field tag"
+       X int "hello" // ERROR "not compatible with reflect.StructTag.Get"
 }
index ccc78cc353ccd930867477ce48b72f0cebf30a55..6171efea48d306f4129825fbaa5c6dbd422e3c95 100644 (file)
@@ -9,12 +9,14 @@ package main
 import (
        "go/ast"
        "strings"
+
+       "flag" // for test
 )
 
 // checkUntaggedLiteral checks if a composite literal is an struct literal with
 // untagged fields.
 func (f *File) checkUntaggedLiteral(c *ast.CompositeLit) {
-       if !*vetUntaggedLiteral && !*vetAll {
+       if !vet("composites") {
                return
        }
        // Check if the CompositeLit contains an untagged field.
@@ -123,6 +125,9 @@ var untaggedLiteralWhitelist = map[string]bool{
        "image.Rectangle":     true,
 }
 
-type BadTag struct {
-       S string `this is a bad tag` // ERROR "not compatible with reflect.StructTag.Get"
+var BadStructLiteralUsedInTests = flag.Flag{ // ERROR "untagged fields"
+       "Name",
+       "Usage",
+       nil, // Value
+       "DefValue",
 }