Skip to content

Commit

Permalink
Ensure that calls to methods without parameter list are instrumented
Browse files Browse the repository at this point in the history
  • Loading branch information
TheElectronWill committed Jun 27, 2022
1 parent 8d2f6c0 commit 9362f57
Show file tree
Hide file tree
Showing 4 changed files with 302 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -118,12 +118,17 @@ class InstrumentCoverage extends MacroTransform with IdentityDenotTransformer:
instrument(tree)
else
val transformed = cpy.Select(tree)(transform(qual), name)
if transformed.qualifier.isDef then
if transformed.symbol.is(Method) then
// instrument calls to methods without parameter list
instrument(transformed)
else
transformed

// f
case tree: Ident if tree.symbol.is(Method) =>
// instrument calls to method without parameter list
instrument(tree)

case tree: CaseDef => instrumentCaseDef(tree)
case tree: ValDef =>
// only transform the rhs
Expand Down
3 changes: 3 additions & 0 deletions compiler/src/dotty/tools/dotc/typer/EtaExpansion.scala
Original file line number Diff line number Diff line change
Expand Up @@ -177,10 +177,13 @@ object LiftCoverage extends LiftImpure {
* - all the impure arguments
*
* There's no need to lift the other arguments.
* Note: at the instrumentCoverage phase, calls to functions that have no parameter list aren't Apply,
* but Ident (e.g. `f` with f in scope) or Select (e.g. `A.f`).
*/
private def noLiftArg(arg: tpd.Tree)(using Context): Boolean =
arg match
case a: tpd.Apply => a.symbol.is(Erased) // don't lift erased applications, but lift all others
case s: (tpd.Select | tpd.Ident) if s.symbol.is(Method) => s.symbol.is(Erased) // take care of calls to functions without parameter lists
case tpd.Block(stats, expr) => stats.forall(noLiftArg) && noLiftArg(expr)
case tpd.Inlined(_, bindings, expr) => noLiftArg(expr)
case tpd.Typed(expr, _) => noLiftArg(expr)
Expand Down
18 changes: 18 additions & 0 deletions tests/coverage/pos/NoParams.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
object A:
def noParam = 0

object B:
def f(x: Any) = println("f")
def noParam = 0

def testSelect =
A.noParam // call should be instrumented

def testSelectArg =
f(A.noParam) // arg should be lifted and instrumented

def testIdent =
noParam // call should be instrumented

def testIdentArg =
f(noParam) // arg should be lifted and instrumented
275 changes: 275 additions & 0 deletions tests/coverage/pos/NoParams.scoverage.check
Original file line number Diff line number Diff line change
@@ -0,0 +1,275 @@
# Coverage data, format version: 3.0
# Statement data:
# - id
# - source path
# - package name
# - class name
# - class type (Class, Object or Trait)
# - full class name
# - method name
# - start offset
# - end offset
# - line number
# - symbol name
# - tree name
# - is branch
# - invocations count
# - is ignored
# - description (can be multi-line)
# ' ' sign
# ------------------------------------------
0
NoParams.scala
<empty>
A$
Object
<empty>.A$
noParam
12
23
1
noParam
DefDef
false
0
false
def noParam

1
NoParams.scala
<empty>
B$
Object
<empty>.B$
f
57
64
4
println
Ident
false
0
false
println

2
NoParams.scala
<empty>
B$
Object
<empty>.B$
f
57
69
4
<none>
Apply
false
0
false
println("f")

3
NoParams.scala
<empty>
B$
Object
<empty>.B$
f
41
46
4
f
DefDef
false
0
false
def f

4
NoParams.scala
<empty>
B$
Object
<empty>.B$
noParam
72
83
5
noParam
DefDef
false
0
false
def noParam

5
NoParams.scala
<empty>
B$
Object
<empty>.B$
testSelect
112
121
8
noParam
Select
false
0
false
A.noParam

6
NoParams.scala
<empty>
B$
Object
<empty>.B$
testSelect
91
105
7
testSelect
DefDef
false
0
false
def testSelect

7
NoParams.scala
<empty>
B$
Object
<empty>.B$
testSelectArg
182
191
11
noParam
Select
false
0
false
A.noParam

8
NoParams.scala
<empty>
B$
Object
<empty>.B$
testSelectArg
180
192
11
f
Apply
false
0
false
f(A.noParam)

9
NoParams.scala
<empty>
B$
Object
<empty>.B$
testSelectArg
156
173
10
testSelectArg
DefDef
false
0
false
def testSelectArg

10
NoParams.scala
<empty>
B$
Object
<empty>.B$
testIdent
257
264
14
noParam
Ident
false
0
false
noParam

11
NoParams.scala
<empty>
B$
Object
<empty>.B$
testIdent
237
250
13
testIdent
DefDef
false
0
false
def testIdent

12
NoParams.scala
<empty>
B$
Object
<empty>.B$
testIdentArg
324
331
17
noParam
Ident
false
0
false
noParam

13
NoParams.scala
<empty>
B$
Object
<empty>.B$
testIdentArg
322
332
17
f
Apply
false
0
false
f(noParam)

14
NoParams.scala
<empty>
B$
Object
<empty>.B$
testIdentArg
299
315
16
testIdentArg
DefDef
false
0
false
def testIdentArg

0 comments on commit 9362f57

Please sign in to comment.