Expand suggestions to cope with sub-line replacements.

This changes the Errorf check to provide a suggestion.
diff --git a/lint.go b/lint.go
index eff0bbd..58b01d7 100644
--- a/lint.go
+++ b/lint.go
@@ -1042,12 +1042,7 @@
 
 		newRS := *rs // shallow copy
 		newRS.Value = nil
-		line := f.render(&newRS)
-		if i := strings.Index(line, "\n"); i >= 0 {
-			line = line[:i]
-		}
-		line = f.indentOf(rs) + line
-		p.ReplacementLine = line
+		p.ReplacementLine = f.firstLineOf(&newRS, rs)
 
 		return true
 	})
@@ -1080,7 +1075,13 @@
 		if isTestingError {
 			errorfPrefix = f.render(se.X)
 		}
-		f.errorf(node, 1, category("errors"), "should replace %s(fmt.Sprintf(...)) with %s.Errorf(...)", f.render(se), errorfPrefix)
+		p := f.errorf(node, 1, category("errors"), "should replace %s(fmt.Sprintf(...)) with %s.Errorf(...)", f.render(se), errorfPrefix)
+
+		m := f.srcLineWithMatch(ce, `^(.*)`+f.render(se)+`\(fmt\.Sprintf\((.*)\)\)(.*)$`)
+		if m != nil {
+			p.ReplacementLine = m[1] + errorfPrefix + ".Errorf(" + m[2] + ")" + m[3]
+		}
+
 		return true
 	})
 }
@@ -1488,6 +1489,16 @@
 	return "", false
 }
 
+// firstLineOf renders the given node and returns its first line.
+// It will also match the indentation of another node.
+func (f *file) firstLineOf(node, match ast.Node) string {
+	line := f.render(node)
+	if i := strings.Index(line, "\n"); i >= 0 {
+		line = line[:i]
+	}
+	return f.indentOf(match) + line
+}
+
 func (f *file) indentOf(node ast.Node) string {
 	line := srcLine(f.src, f.fset.Position(node.Pos()))
 	for i, r := range line {
@@ -1500,6 +1511,13 @@
 	return line // unusual or empty line
 }
 
+func (f *file) srcLineWithMatch(node ast.Node, pattern string) (m []string) {
+	line := srcLine(f.src, f.fset.Position(node.Pos()))
+	line = strings.TrimSuffix(line, "\n")
+	rx := regexp.MustCompile(pattern)
+	return rx.FindStringSubmatch(line)
+}
+
 // srcLine returns the complete line at p, including the terminating newline.
 func srcLine(src []byte, p token.Position) string {
 	// Run to end of line in both directions if not at line start/end.
diff --git a/lint_test.go b/lint_test.go
index e6b25de..d4539b2 100644
--- a/lint_test.go
+++ b/lint_test.go
@@ -71,8 +71,15 @@
 				}
 				if in.Match.MatchString(p.Text) {
 					// check replacement if we are expecting one
-					if in.Replacement != "" && p.ReplacementLine != in.Replacement {
-						t.Errorf("Lint failed at %s:%d; got replacement %q, want %q", fi.Name(), in.Line, p.ReplacementLine, in.Replacement)
+					if in.Replacement != "" {
+						// ignore any inline comments, since that would be recursive
+						r := p.ReplacementLine
+						if i := strings.Index(r, " //"); i >= 0 {
+							r = r[:i]
+						}
+						if r != in.Replacement {
+							t.Errorf("Lint failed at %s:%d; got replacement %q, want %q", fi.Name(), in.Line, r, in.Replacement)
+						}
 					}
 
 					// remove this problem from ps
diff --git a/testdata/errorf.go b/testdata/errorf.go
index 5a7efeb..72161f2 100644
--- a/testdata/errorf.go
+++ b/testdata/errorf.go
@@ -11,7 +11,7 @@
 
 func f(x int) error {
 	if x > 10 {
-		return errors.New(fmt.Sprintf("something %d", x)) // MATCH /should replace.*errors\.New\(fmt\.Sprintf\(\.\.\.\)\).*fmt\.Errorf\(\.\.\.\)/
+		return errors.New(fmt.Sprintf("something %d", x)) // MATCH /should replace.*errors\.New\(fmt\.Sprintf\(\.\.\.\)\).*fmt\.Errorf\(\.\.\.\)/ -> `		return fmt.Errorf("something %d", x)`
 	}
 	if x > 5 {
 		return errors.New(g("blah")) // ok