Check that error strings aren't capitalized and don't end with punctuation.
diff --git a/lint.go b/lint.go
index f1986de..a6db5fa 100644
--- a/lint.go
+++ b/lint.go
@@ -15,8 +15,10 @@
"go/printer"
"go/token"
"regexp"
+ "strconv"
"strings"
"unicode"
+ "unicode/utf8"
)
// A Linter lints Go source code.
@@ -73,6 +75,7 @@
f.lintRanges()
f.lintErrorf()
f.lintErrors()
+ f.lintErrorStrings()
f.lintReceiverNames()
return f.problems
@@ -727,6 +730,47 @@
}
}
+// lintErrorStrings examines error strings. It complains if they are capitalized or end in punctuation.
+func (f *file) lintErrorStrings() {
+ f.walk(func(node ast.Node) bool {
+ ce, ok := node.(*ast.CallExpr)
+ if !ok {
+ return true
+ }
+ if !isPkgDot(ce.Fun, "errors", "New") && !isPkgDot(ce.Fun, "fmt", "Errorf") {
+ return true
+ }
+ if len(ce.Args) < 1 {
+ return true
+ }
+ str, ok := ce.Args[0].(*ast.BasicLit)
+ if !ok || str.Kind != token.STRING {
+ return true
+ }
+ s, _ := strconv.Unquote(str.Value) // can assume well-formed Go
+ if s == "" {
+ return true
+ }
+ first, _ := utf8.DecodeRuneInString(s)
+ last, _ := utf8.DecodeLastRuneInString(s)
+ isCap := unicode.IsUpper(first)
+ isPunct := last == '.' || last == ':' || last == '!'
+ var msg string
+ switch {
+ case isCap && isPunct:
+ msg = "error strings should not be capitalized and should not end with punctuation"
+ case isCap:
+ msg = "error strings should not be capitalized"
+ case isPunct:
+ msg = "error strings should not end with punctuation"
+ default:
+ return true
+ }
+ f.errorf(str, 0.8, msg)
+ return true
+ })
+}
+
var badReceiverNames = map[string]bool{
"me": true,
"this": true,
diff --git a/testdata/errors.go b/testdata/errors.go
index 54bd922..e6aabdd 100644
--- a/testdata/errors.go
+++ b/testdata/errors.go
@@ -20,5 +20,14 @@
)
func f() {
- var whatever = errors.New("...") // ok
+ var whatever = errors.New("ok") // ok
+}
+
+// Check for the error strings themselves.
+
+func g(x int) error {
+ if x < 1 {
+ return fmt.Errorf("This %d is too low", x) // MATCH /error strings.*not be capitalized/
+ }
+ return errors.New(`too much stuff.`) // MATCH /error strings.*not end with punctuation/
}