@@ -2,20 +2,20 @@ package dotty.tools.dotc
2
2
package transform
3
3
4
4
import java .io .File
5
-
6
5
import ast .tpd .*
6
+
7
7
import collection .mutable
8
8
import core .Flags .*
9
9
import core .Contexts .{Context , ctx , inContext }
10
10
import core .DenotTransformers .IdentityDenotTransformer
11
- import core .Symbols .{defn , Symbol }
11
+ import core .Symbols .{Symbol , defn }
12
12
import core .Constants .Constant
13
13
import core .NameOps .isContextFunction
14
14
import core .StdNames .nme
15
15
import core .Types .*
16
16
import coverage .*
17
17
import typer .LiftCoverage
18
- import util .{SourcePosition , SourceFile }
18
+ import util .{SourceFile , SourcePosition }
19
19
import util .Spans .Span
20
20
import localopt .StringInterpolatorOpt
21
21
import inlines .Inlines
@@ -120,6 +120,7 @@ class InstrumentCoverage extends MacroTransform with IdentityDenotTransformer:
120
120
*/
121
121
private def createInvokeCall (tree : Tree , pos : SourcePosition , branch : Boolean = false )(using Context ): Apply =
122
122
val statementId = recordStatement(tree, pos, branch)
123
+ println(s " createInvokeCall: $statementId" )
123
124
val span = pos.span.toSynthetic
124
125
invokeCall(statementId, span)
125
126
@@ -132,6 +133,8 @@ class InstrumentCoverage extends MacroTransform with IdentityDenotTransformer:
132
133
* @return instrumentation result, with the preparation statement, coverage call and tree separated
133
134
*/
134
135
private def tryInstrument (tree : Apply )(using Context ): InstrumentedParts =
136
+ println(s " tryInstrument Tree: ${tree}" )
137
+
135
138
if canInstrumentApply(tree) then
136
139
// Create a call to Invoker.invoked(coverageDirectory, newStatementId)
137
140
val coverageCall = createInvokeCall(tree, tree.sourcePos)
@@ -156,20 +159,33 @@ class InstrumentCoverage extends MacroTransform with IdentityDenotTransformer:
156
159
val transformed = cpy.Apply (tree)(transform(tree.fun), transform(tree.args))
157
160
InstrumentedParts .notCovered(transformed)
158
161
159
- private def tryInstrument (tree : Ident )(using Context ): InstrumentedParts =
162
+ private def tryInstrument (tree : Ident )(using Context ): InstrumentedParts = {
163
+ println(s " tryInstrument Ident: ${tree}" )
164
+
165
+
160
166
val sym = tree.symbol
161
- if canInstrumentParameterless(sym) then
167
+
168
+ if (canInstrumentParameterless(sym)) {
162
169
// call to a local parameterless method f
163
170
val coverageCall = createInvokeCall(tree, tree.sourcePos)
164
171
InstrumentedParts .singleExpr(coverageCall, tree)
165
- else
166
- InstrumentedParts .notCovered(tree)
172
+ } else {
173
+ println(s " tryInstrument Ident: ${tree} not instrumented " )
174
+ InstrumentedParts .notCovered(tree)
175
+ }
176
+ }
167
177
168
- private def tryInstrument (tree : Select )(using Context ): InstrumentedParts =
178
+ private def tryInstrument (tree : Select )(using Context ): InstrumentedParts = {
179
+ val sym = tree.symbol
169
180
val transformed = cpy.Select (tree)(transform(tree.qualifier), tree.name)
170
- val coverageCall = createInvokeCall(tree, tree.sourcePos)
171
- InstrumentedParts .singleExpr(coverageCall, transformed)
172
-
181
+ println(s " tryInstrument Select: ${tree}" )
182
+ if canInstrumentParameterless(sym) then
183
+ // call to a parameterless method
184
+ val coverageCall = createInvokeCall(tree, tree.sourcePos)
185
+ InstrumentedParts .singleExpr(coverageCall, transformed)
186
+ else
187
+ InstrumentedParts .notCovered(transformed)
188
+ }
173
189
/** Generic tryInstrument */
174
190
private def tryInstrument (tree : Tree )(using Context ): InstrumentedParts =
175
191
tree match
@@ -229,6 +245,7 @@ class InstrumentCoverage extends MacroTransform with IdentityDenotTransformer:
229
245
case TypeApply (fun, args) =>
230
246
// Here is where `InstrumentedParts` becomes useful!
231
247
// We extract its components and act carefully.
248
+ println(s " TypeApply: ${fun}" )
232
249
val InstrumentedParts (pre, coverageCall, expr) = tryInstrument(fun)
233
250
234
251
if coverageCall.isEmpty then
@@ -439,6 +456,7 @@ class InstrumentCoverage extends MacroTransform with IdentityDenotTransformer:
439
456
* should not be changed to {val $x = f(); T($x)}(1) but to {val $x = f(); val $y = 1; T($x)($y)}
440
457
*/
441
458
private def needsLift (tree : Apply )(using Context ): Boolean =
459
+ println(s " start needsLift: $tree" )
442
460
def isShortCircuitedOp (sym : Symbol ) =
443
461
sym == defn.Boolean_&& || sym == defn.Boolean_||
444
462
@@ -460,8 +478,10 @@ class InstrumentCoverage extends MacroTransform with IdentityDenotTransformer:
460
478
case a : Apply => needsLift(a)
461
479
case _ => false
462
480
463
- nestedApplyNeedsLift ||
481
+ val liftMe = nestedApplyNeedsLift ||
464
482
! isUnliftableFun(fun) && ! tree.args.isEmpty && ! tree.args.forall(LiftCoverage .noLift)
483
+ println(s " end needsLift: $tree, liftMe: $liftMe, nestedApplyNeedsLift: $nestedApplyNeedsLift, isUnliftableFun: ${isUnliftableFun(fun)}, tree.args.isEmpty: ${tree.args}, tree.args.forall(LiftCoverage.noLift): ${tree.args.forall(LiftCoverage .noLift)}" )
484
+ liftMe
465
485
466
486
/** Check if an Apply can be instrumented. Prevents this phase from generating incorrect code. */
467
487
private def canInstrumentApply (tree : Apply )(using Context ): Boolean =
@@ -470,10 +490,10 @@ class InstrumentCoverage extends MacroTransform with IdentityDenotTransformer:
470
490
case _ => false
471
491
472
492
val sym = tree.symbol
473
- ! sym.isOneOf(ExcludeMethodFlags )
493
+ val canI = ! sym.isOneOf(ExcludeMethodFlags )
474
494
&& ! isCompilerIntrinsicMethod(sym)
475
495
&& ! (sym.isClassConstructor && isSecondaryCtorDelegateCall)
476
- && (tree.typeOpt match
496
+ && (tree.typeOpt match {
477
497
case AppliedType (tycon : NamedType , _) =>
478
498
/* If the last expression in a block is a context function, we'll try to
479
499
summon its arguments at the current point, even if the expected type
@@ -496,19 +516,25 @@ class InstrumentCoverage extends MacroTransform with IdentityDenotTransformer:
496
516
*/
497
517
false
498
518
case _ =>
499
- true
500
- )
519
+ false
520
+ })
521
+ println(s " canInstrumentApply ${tree.symbol}: $canI is ${sym.name} is method ${sym.is(Method )} is compiler intrinsic ${isCompilerIntrinsicMethod(sym)} typeOpt ${tree.typeOpt}" )
522
+ canI
523
+
501
524
502
525
/** Is this the symbol of a parameterless method that we can instrument?
503
526
* Note: it is crucial that `asInstanceOf` and `isInstanceOf`, among others,
504
527
* do NOT get instrumented, because that would generate invalid code and crash
505
528
* in post-erasure checking.
506
529
*/
507
- private def canInstrumentParameterless (sym : Symbol )(using Context ): Boolean =
508
- sym.is(Method , butNot = ExcludeMethodFlags )
530
+ private def canInstrumentParameterless (sym : Symbol )(using Context ): Boolean = {
531
+ val isP = ( sym.is(Method , butNot = ExcludeMethodFlags )
509
532
&& sym.info.isParameterless
510
533
&& ! isCompilerIntrinsicMethod(sym)
511
- && ! sym.info.typeSymbol.name.isContextFunction // exclude context functions like in canInstrumentApply
534
+ && ! sym.info.typeSymbol.name.isContextFunction ) // exclude context functions like in canInstrumentApply)
535
+ println(s " canInstrumentParameterless $sym: $isP is ${sym.name} kind string ${sym.kindString} is method ${sym.is(Method )} is parameterless ${sym.info.isParameterless} is compiler intrinsic ${isCompilerIntrinsicMethod(sym)} typeSymbol ${sym.info.typeSymbol} is context function ${sym.info.typeSymbol.name.isContextFunction}" )
536
+ isP
537
+ }
512
538
513
539
/** Does sym refer to a "compiler intrinsic" method, which only exist during compilation,
514
540
* like Any.isInstanceOf?
0 commit comments