Commit 8b8625a3 authored by Ian Lance Taylor's avatar Ian Lance Taylor

cmd/cover: don't crash on non-gofmt'ed input

Without the change to cover.go, the new test fails with

panic: overlapping edits: [4946,4950)->"", [4947,4947)->"thisNameMustBeVeryLongToCauseOverflowOfCounterIncrementStatementOntoNextLineForTest.Count[112]++;"

The original code inserts "else{", deletes "else", and then positions
a new block just after the "}" that must come before the "else".
That works on gofmt'ed code, but fails if the code looks like "}else".
When there is no space between the "{" and the "else", the new block
is inserted into a location that we are deleting, leading to the
"overlapping edits" mentioned above.

This CL fixes this case by not deleting the "else" but just using the
one that is already there. That requires adjust the block offset to
come after the "{" that we insert.

Fixes #23927

Change-Id: I40ef592490878765bbce6550ddb439e43ac525b2
Reviewed-on: https://go-review.googlesource.com/98935
Run-TryBot: Ian Lance Taylor <iant@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: 's avatarRobert Griesemer <gri@golang.org>
parent 419c0645
......@@ -238,23 +238,28 @@ func (f *File) Visit(node ast.Node) ast.Visitor {
// if y {
// }
// }
f.edit.Insert(f.offset(n.Body.End()), "else{")
elseOffset := f.findText(n.Body.End(), "else")
if elseOffset < 0 {
panic("lost else")
}
f.edit.Delete(elseOffset, elseOffset+4)
f.edit.Insert(elseOffset+4, "{")
f.edit.Insert(f.offset(n.Else.End()), "}")
// We just created a block, now walk it.
// Adjust the position of the new block to start after
// the "else". That will cause it to follow the "{"
// we inserted above.
pos := f.fset.File(n.Body.End()).Pos(elseOffset + 4)
switch stmt := n.Else.(type) {
case *ast.IfStmt:
block := &ast.BlockStmt{
Lbrace: n.Body.End(), // Start at end of the "if" block so the covered part looks like it starts at the "else".
Lbrace: pos,
List: []ast.Stmt{stmt},
Rbrace: stmt.End(),
}
n.Else = block
case *ast.BlockStmt:
stmt.Lbrace = n.Body.End() // Start at end of the "if" block so the covered part looks like it starts at the "else".
stmt.Lbrace = pos
default:
panic("unexpected node type in if")
}
......
......@@ -59,6 +59,17 @@ func TestCover(t *testing.T) {
for i, line := range lines {
lines[i] = bytes.Replace(line, []byte("LINE"), []byte(fmt.Sprint(i+1)), -1)
}
// Add a function that is not gofmt'ed. This used to cause a crash.
// We don't put it in test.go because then we would have to gofmt it.
// Issue 23927.
lines = append(lines, []byte("func unFormatted() {"),
[]byte("\tif true {"),
[]byte("\t}else{"),
[]byte("\t}"),
[]byte("}"))
lines = append(lines, []byte("func unFormatted2(b bool) {if b{}else{}}"))
if err := ioutil.WriteFile(coverInput, bytes.Join(lines, []byte("\n")), 0666); err != nil {
t.Fatal(err)
}
......@@ -246,6 +257,7 @@ func TestCoverFunc(t *testing.T) {
}
func run(c *exec.Cmd, t *testing.T) {
t.Helper()
c.Stdout = os.Stdout
c.Stderr = os.Stderr
err := c.Run()
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment