@@ -145,6 +145,31 @@ class InstrumentCoverage extends MacroTransform with IdentityDenotTransformer:
145145      val  span  =  pos.span.toSynthetic
146146      invokeCall(statementId, span)
147147
148+     private  def  transformApplyArgs (trees : List [Tree ])(using  Context ):  List [Tree ] = 
149+       if  allConstArgs(trees) then  trees else  transform(trees)
150+ 
151+     private  def  transformInnerApply (tree : Tree )(using  Context ):  Tree  =  tree match 
152+       case  a : Apply  if  a.fun.symbol ==  defn.StringContextModule_apply  => 
153+         a
154+       case  a : Apply  => 
155+         cpy.Apply (a)(
156+           transformInnerApply(a.fun),
157+           transformApplyArgs(a.args)
158+         )
159+       case  a : TypeApply  => 
160+         cpy.TypeApply (a)(
161+           transformInnerApply(a.fun),
162+           transformApplyArgs(a.args)
163+         )
164+       case  s : Select  => 
165+         cpy.Select (s)(transformInnerApply(s.qualifier), s.name)
166+       case  i : (Ident  |  This ) =>  i
167+       case  t : Typed  => 
168+         cpy.Typed (t)(transformInnerApply(t.expr), t.tpt)
169+       case  other    =>  transform(other)
170+ 
171+     private  def  allConstArgs (args : List [Tree ]) = 
172+       args.forall(arg =>  arg.isInstanceOf [Literal ] ||  arg.isInstanceOf [Ident ])
148173    /**  
149174      * Tries to instrument an `Apply`. 
150175      * These "tryInstrument" methods are useful to tweak the generation of coverage instrumentation, 
@@ -158,10 +183,12 @@ class InstrumentCoverage extends MacroTransform with IdentityDenotTransformer:
158183        //  Create a call to Invoker.invoked(coverageDirectory, newStatementId)
159184        val  coverageCall  =  createInvokeCall(tree, tree.sourcePos)
160185
161-         if  needsLift(tree) then 
162-           //  Transform args and fun, i.e. instrument them if needed (and if possible)
163-           val  app  =  cpy.Apply (tree)(transform(tree.fun), tree.args.map(transform))
186+         //  Transform args and fun, i.e. instrument them if needed (and if possible)
187+         val  app  = 
188+           if  tree.fun.symbol eq defn.throwMethod then  tree
189+           else  cpy.Apply (tree)(transformInnerApply(tree.fun), transformApplyArgs(tree.args))
164190
191+         if  needsLift(tree) then 
165192          //  Lifts the arguments. Note that if only one argument needs to be lifted, we lift them all.
166193          //  Also, tree.fun can be lifted too.
167194          //  See LiftCoverage for the internal working of this lifting.
@@ -171,11 +198,10 @@ class InstrumentCoverage extends MacroTransform with IdentityDenotTransformer:
171198          InstrumentedParts (liftedDefs.toList, coverageCall, liftedApp)
172199        else 
173200          //  Instrument without lifting
174-           val  transformed  =  cpy.Apply (tree)(transform(tree.fun), transform(tree.args))
175-           InstrumentedParts .singleExpr(coverageCall, transformed)
201+           InstrumentedParts .singleExpr(coverageCall, app)
176202      else 
177203        //  Transform recursively but don't instrument the tree itself
178-         val  transformed  =  cpy.Apply (tree)(transform (tree.fun), transform(tree.args))
204+         val  transformed  =  cpy.Apply (tree)(transformInnerApply (tree.fun), transform(tree.args))
179205        InstrumentedParts .notCovered(transformed)
180206
181207    private  def  tryInstrument (tree : Ident )(using  Context ):  InstrumentedParts  = 
@@ -187,9 +213,14 @@ class InstrumentCoverage extends MacroTransform with IdentityDenotTransformer:
187213      else 
188214        InstrumentedParts .notCovered(tree)
189215
216+     private  def  tryInstrument (tree : Literal )(using  Context ):  InstrumentedParts  = 
217+       val  coverageCall  =  createInvokeCall(tree, tree.sourcePos)
218+       InstrumentedParts .singleExpr(coverageCall, tree)
219+ 
190220    private  def  tryInstrument (tree : Select )(using  Context ):  InstrumentedParts  = 
191221      val  sym  =  tree.symbol
192-       val  transformed  =  cpy.Select (tree)(transform(tree.qualifier), tree.name)
222+       val  qual  =  transform(tree.qualifier).ensureConforms(tree.qualifier.tpe)
223+       val  transformed  =  cpy.Select (tree)(qual, tree.name)
193224      if  canInstrumentParameterless(sym) then 
194225        //  call to a parameterless method
195226        val  coverageCall  =  createInvokeCall(tree, tree.sourcePos)
@@ -202,6 +233,7 @@ class InstrumentCoverage extends MacroTransform with IdentityDenotTransformer:
202233      tree match 
203234        case  t : Apply  =>  tryInstrument(t)
204235        case  t : Ident  =>  tryInstrument(t)
236+         case  t : Literal  =>  tryInstrument(t)
205237        case  t : Select  =>  tryInstrument(t)
206238        case  _ =>  InstrumentedParts .notCovered(transform(tree))
207239
@@ -223,10 +255,14 @@ class InstrumentCoverage extends MacroTransform with IdentityDenotTransformer:
223255      inContext(transformCtx(tree)) { //  necessary to position inlined code properly
224256        tree match 
225257          //  simple cases
226-           case  tree : (Import  |  Export  |  Literal   |   This  |  Super  |  New ) =>  tree
258+           case  tree : (Import  |  Export  |  This  |  Super  |  New ) =>  tree
227259          case  tree if  tree.isEmpty ||  tree.isType =>  tree //  empty Thicket, Ident (referring to a type), TypeTree, ...
228260          case  tree if  ! tree.span.exists ||  tree.span.isZeroExtent =>  tree //  no meaningful position
229261
262+           case  tree : Literal  => 
263+             val  rest  =  tryInstrument(tree).toTree
264+             rest
265+ 
230266          //  identifier
231267          case  tree : Ident  => 
232268            tryInstrument(tree).toTree
@@ -280,6 +316,9 @@ class InstrumentCoverage extends MacroTransform with IdentityDenotTransformer:
280316          case  tree : CaseDef  => 
281317            transformCaseDef(tree)
282318
319+           case  tree : ValDef  if  tree.symbol.is(Inline ) => 
320+             tree //  transforming inline vals will result in `inline value must be pure` errors
321+ 
283322          case  tree : ValDef  => 
284323            //  only transform the rhs
285324            val  rhs  =  transform(tree.rhs)
@@ -323,13 +362,13 @@ class InstrumentCoverage extends MacroTransform with IdentityDenotTransformer:
323362            )
324363
325364          case  tree : Inlined  => 
326-             //  Ideally, tree.call would provide precise information about the inlined call ,
327-             //  and  we would use this information for  the coverage report. 
328-             //  But PostTyper simplifies tree.call, so  we can't report the actual method that was inlined .
329-             //  In any case, the subtrees need to be repositioned right now, otherwise the 
330-             //  coverage statement will point to a potentially unreachable source file. 
331-             val   dropped   =   Inlines .dropInlined(tree)  //  drop and reposition 
332-             transform(dropped)  //  transform the content of the Inlined 
365+             //  Inlined code contents might come from another file (or project) ,
366+             //  which means that  we cannot clearly designate which part of  the inlined code 
367+             //  was run using the API  we are given .
368+             //  At best, we can show that the Inlined tree itself was reached. 
369+             //  Additionally, Scala 2's coverage ignores macro calls entirely, 
370+             //  so let's do that here too, also for regular inlined calls. 
371+             tree 
333372
334373          //  For everything else just recurse and transform
335374          case  _ => 
@@ -559,15 +598,14 @@ class InstrumentCoverage extends MacroTransform with IdentityDenotTransformer:
559598    private  def  isCompilerIntrinsicMethod (sym : Symbol )(using  Context ):  Boolean  = 
560599      val  owner  =  sym.maybeOwner
561600      owner.exists &&  (
562-         owner.eq(defn.AnyClass ) || 
563-         owner.isPrimitiveValueClass || 
601+         (owner.eq(defn.AnyClass ) &&  (sym ==  defn.Any_asInstanceOf  ||  sym ==  defn.Any_isInstanceOf )) || 
564602        owner.maybeOwner ==  defn.CompiletimePackageClass 
565603      )
566604
567605object  InstrumentCoverage : 
568606  val  name :  String  =  " instrumentCoverage" 
569607  val  description :  String  =  " instrument code for coverage checking" 
570-   val  ExcludeMethodFlags :  FlagSet  =  Synthetic   |   Artifact  |  Erased 
608+   val  ExcludeMethodFlags :  FlagSet  =  Artifact  |  Erased 
571609
572610  /**  
573611   * An instrumented Tree, in 3 parts. 
0 commit comments