Flag error strings that end with a newline

Signed-off-by: Joe Tsai <joetsai@google.com>
diff --git a/lint.go b/lint.go
index 59fea7c..2a2e607 100644
--- a/lint.go
+++ b/lint.go
@@ -1155,21 +1155,30 @@
 	}
 }
 
-func lintCapAndPunct(s string) (isCap, isPunct bool) {
+func lintErrorString(s string) (isClean bool, conf float64) {
+	const basicConfidence = 0.8
+	const capConfidence = basicConfidence - 0.2
 	first, firstN := utf8.DecodeRuneInString(s)
 	last, _ := utf8.DecodeLastRuneInString(s)
-	isPunct = last == '.' || last == ':' || last == '!'
-	isCap = unicode.IsUpper(first)
-	if isCap && len(s) > firstN {
-		// Don't flag strings starting with something that looks like an initialism.
-		if second, _ := utf8.DecodeRuneInString(s[firstN:]); unicode.IsUpper(second) {
-			isCap = false
+	if last == '.' || last == ':' || last == '!' || last == '\n' {
+		return false, basicConfidence
+	}
+	if unicode.IsUpper(first) {
+		// People use proper nouns and exported Go identifiers in error strings,
+		// so decrease the confidence of warnings for capitalization.
+		if len(s) <= firstN {
+			return false, capConfidence
+		}
+		// Flag strings starting with something that doesn't look like an initialism.
+		if second, _ := utf8.DecodeRuneInString(s[firstN:]); !unicode.IsUpper(second) {
+			return false, capConfidence
 		}
 	}
-	return
+	return true, 0
 }
 
-// lintErrorStrings examines error strings. It complains if they are capitalized or end in punctuation.
+// lintErrorStrings examines error strings.
+// It complains if they are capitalized or end in punctuation or a newline.
 func (f *file) lintErrorStrings() {
 	f.walk(func(node ast.Node) bool {
 		ce, ok := node.(*ast.CallExpr)
@@ -1190,25 +1199,13 @@
 		if s == "" {
 			return true
 		}
-		isCap, isPunct := lintCapAndPunct(s)
-		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:
+		clean, conf := lintErrorString(s)
+		if clean {
 			return true
 		}
-		// People use proper nouns and exported Go identifiers in error strings,
-		// so decrease the confidence of warnings for capitalization.
-		conf := 0.8
-		if isCap {
-			conf = 0.6
-		}
-		f.errorf(str, conf, link(styleGuideBase+"#error-strings"), category("errors"), msg)
+
+		f.errorf(str, conf, link(styleGuideBase+"#error-strings"), category("errors"),
+			"error strings should not be capitalized or end with punctuation or a newline")
 		return true
 	})
 }
diff --git a/testdata/errors.go b/testdata/errors.go
index 396dcfc..3435bf8 100644
--- a/testdata/errors.go
+++ b/testdata/errors.go
@@ -27,10 +27,11 @@
 // 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/
-	} else if x == 0 {
-		return fmt.Errorf("XML time") // ok
-	}
-	return errors.New(`too much stuff.`) // MATCH /error strings.*not end with punctuation/
+	var err error
+	err = fmt.Errorf("This %d is too low", x)     // MATCH /error strings.*be capitalized/
+	err = fmt.Errorf("XML time")                  // ok
+	err = fmt.Errorf("newlines are fun\n")        // MATCH /error strings.*end with punctuation/
+	err = fmt.Errorf("Newlines are really fun\n") // MATCH /error strings.+not be capitalized/
+	err = errors.New(`too much stuff.`)           // MATCH /error strings.*end with punctuation/
+	return err
 }