]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/cover: change covered block for switch/select case to exclude expression
authorRuss Cox <rsc@golang.org>
Thu, 3 Nov 2016 00:18:47 +0000 (20:18 -0400)
committerRuss Cox <rsc@golang.org>
Thu, 3 Nov 2016 16:13:06 +0000 (16:13 +0000)
Consider a switch like

switch x {
case foo:
f()
g()
}

Before, the coverage annotation for the block calling f and g included
in its position span the text for 'case foo:'. This looks nice in the coverage
report, but it breaks the invariant that coverage blocks are disjoint if
you have a more complex expression like:

switch x {
case func() int { return foo }():
f()
g()
}

Then the coverage analysis wants to annotate the func literal body,
which overlaps with the case body, because the case body is considered
to begin at the case token.

Change the annotation for a case body to start just after the colon of
the case clause, avoiding any potential conflict with complex case
expressions. Could have started at the colon instead, but it seemed
less weird to start just after it.

Fixes #16540.

Change-Id: I1fec4bc2a53c7092e649dc0d4be1680a697cb79b
Reviewed-on: https://go-review.googlesource.com/32612
Run-TryBot: Russ Cox <rsc@golang.org>
Reviewed-by: Andrew Gerrand <adg@golang.org>
src/cmd/cover/cover.go
src/cmd/cover/testdata/test.go

index 222737571fb72c7853d9dfaf11b003b02c4ce5c2..b7d9125d60a70224bed05df9c503cc9467b19738 100644 (file)
@@ -168,13 +168,13 @@ func (f *File) Visit(node ast.Node) ast.Visitor {
                        case *ast.CaseClause: // switch
                                for _, n := range n.List {
                                        clause := n.(*ast.CaseClause)
-                                       clause.Body = f.addCounters(clause.Pos(), clause.End(), clause.Body, false)
+                                       clause.Body = f.addCounters(clause.Colon+1, clause.End(), clause.Body, false)
                                }
                                return f
                        case *ast.CommClause: // select
                                for _, n := range n.List {
                                        clause := n.(*ast.CommClause)
-                                       clause.Body = f.addCounters(clause.Pos(), clause.End(), clause.Body, false)
+                                       clause.Body = f.addCounters(clause.Colon+1, clause.End(), clause.Body, false)
                                }
                                return f
                        }
index 71cb1153313a958b723faa87af8bb52bccf768c2..61b40eaa740927be44ba1714adede1493ae4b315 100644 (file)
@@ -246,6 +246,18 @@ func testFunctionLiteral() {
                check(LINE, 2)
        }) {
        }
+
+       x := 2
+       switch x {
+       case func() int { check(LINE, 1); return 1 }():
+               check(LINE, 0)
+               panic("2=1")
+       case func() int { check(LINE, 1); return 2 }():
+               check(LINE, 1)
+       case func() int { check(LINE, 0); return 3 }():
+               check(LINE, 0)
+               panic("2=3")
+       }
 }
 
 func testGoto() {