@@ -145,6 +145,29 @@ 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)) 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  other    =>  transform(other)
168+ 
169+     private  def  allConstArgs (args : List [Tree ]) = 
170+       args.forall(arg =>  arg.isInstanceOf [Literal ] ||  arg.isInstanceOf [Ident ])
148171    /**  
149172      * Tries to instrument an `Apply`. 
150173      * These "tryInstrument" methods are useful to tweak the generation of coverage instrumentation, 
@@ -158,10 +181,12 @@ class InstrumentCoverage extends MacroTransform with IdentityDenotTransformer:
158181        //  Create a call to Invoker.invoked(coverageDirectory, newStatementId)
159182        val  coverageCall  =  createInvokeCall(tree, tree.sourcePos)
160183
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))
184+         //  Transform args and fun, i.e. instrument them if needed (and if possible)
185+         val  app  = 
186+           if  (tree.fun.symbol eq defn.throwMethod) tree
187+           else  cpy.Apply (tree)(transformInnerApply(tree.fun), transformApplyArgs(tree.args))
164188
189+         if  needsLift(tree) then 
165190          //  Lifts the arguments. Note that if only one argument needs to be lifted, we lift them all.
166191          //  Also, tree.fun can be lifted too.
167192          //  See LiftCoverage for the internal working of this lifting.
@@ -171,11 +196,10 @@ class InstrumentCoverage extends MacroTransform with IdentityDenotTransformer:
171196          InstrumentedParts (liftedDefs.toList, coverageCall, liftedApp)
172197        else 
173198          //  Instrument without lifting
174-           val  transformed  =  cpy.Apply (tree)(transform(tree.fun), transform(tree.args))
175-           InstrumentedParts .singleExpr(coverageCall, transformed)
199+           InstrumentedParts .singleExpr(coverageCall, app)
176200      else 
177201        //  Transform recursively but don't instrument the tree itself
178-         val  transformed  =  cpy.Apply (tree)(transform (tree.fun), transform(tree.args))
202+         val  transformed  =  cpy.Apply (tree)(transformInnerApply (tree.fun), transform(tree.args))
179203        InstrumentedParts .notCovered(transformed)
180204
181205    private  def  tryInstrument (tree : Ident )(using  Context ):  InstrumentedParts  = 
@@ -187,9 +211,14 @@ class InstrumentCoverage extends MacroTransform with IdentityDenotTransformer:
187211      else 
188212        InstrumentedParts .notCovered(tree)
189213
214+     private  def  tryInstrument (tree : Literal )(using  Context ):  InstrumentedParts  = 
215+       val  coverageCall  =  createInvokeCall(tree, tree.sourcePos)
216+       InstrumentedParts .singleExpr(coverageCall, tree)
217+ 
190218    private  def  tryInstrument (tree : Select )(using  Context ):  InstrumentedParts  = 
191219      val  sym  =  tree.symbol
192-       val  transformed  =  cpy.Select (tree)(transform(tree.qualifier), tree.name)
220+       val  qual  =  transform(tree.qualifier).ensureConforms(tree.qualifier.tpe)
221+       val  transformed  =  cpy.Select (tree)(qual, tree.name)
193222      if  canInstrumentParameterless(sym) then 
194223        //  call to a parameterless method
195224        val  coverageCall  =  createInvokeCall(tree, tree.sourcePos)
@@ -202,6 +231,7 @@ class InstrumentCoverage extends MacroTransform with IdentityDenotTransformer:
202231      tree match 
203232        case  t : Apply  =>  tryInstrument(t)
204233        case  t : Ident  =>  tryInstrument(t)
234+         case  t : Literal  =>  tryInstrument(t)
205235        case  t : Select  =>  tryInstrument(t)
206236        case  _ =>  InstrumentedParts .notCovered(transform(tree))
207237
@@ -223,10 +253,14 @@ class InstrumentCoverage extends MacroTransform with IdentityDenotTransformer:
223253      inContext(transformCtx(tree)) { //  necessary to position inlined code properly
224254        tree match 
225255          //  simple cases
226-           case  tree : (Import  |  Export  |  Literal   |   This  |  Super  |  New ) =>  tree
256+           case  tree : (Import  |  Export  |  This  |  Super  |  New ) =>  tree
227257          case  tree if  tree.isEmpty ||  tree.isType =>  tree //  empty Thicket, Ident (referring to a type), TypeTree, ...
228258          case  tree if  ! tree.span.exists ||  tree.span.isZeroExtent =>  tree //  no meaningful position
229259
260+           case  tree : Literal  => 
261+             val  rest  =  tryInstrument(tree).toTree
262+             rest
263+ 
230264          //  identifier
231265          case  tree : Ident  => 
232266            tryInstrument(tree).toTree
@@ -280,6 +314,9 @@ class InstrumentCoverage extends MacroTransform with IdentityDenotTransformer:
280314          case  tree : CaseDef  => 
281315            transformCaseDef(tree)
282316
317+           case  tree : ValDef  if  tree.symbol.is(Inline ) => 
318+             tree //  transforming inline vals will result in `inline value must be pure` errors
319+ 
283320          case  tree : ValDef  => 
284321            //  only transform the rhs
285322            val  rhs  =  transform(tree.rhs)
@@ -323,13 +360,13 @@ class InstrumentCoverage extends MacroTransform with IdentityDenotTransformer:
323360            )
324361
325362          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 
363+             //  Inlined code contents might come from another file (or project) ,
364+             //  which means that  we cannot clearly designate which part of  the inlined code 
365+             //  was run using the API  we are given .
366+             //  At best, we can show that the Inlined tree itself was reached. 
367+             //  Additionally, Scala 2's coverage ignores macro calls entirely, 
368+             //  so let's do that here too, also for regular inlined calls. 
369+             tree 
333370
334371          //  For everything else just recurse and transform
335372          case  _ => 
@@ -559,15 +596,14 @@ class InstrumentCoverage extends MacroTransform with IdentityDenotTransformer:
559596    private  def  isCompilerIntrinsicMethod (sym : Symbol )(using  Context ):  Boolean  = 
560597      val  owner  =  sym.maybeOwner
561598      owner.exists &&  (
562-         owner.eq(defn.AnyClass ) || 
563-         owner.isPrimitiveValueClass || 
599+         (owner.eq(defn.AnyClass ) &&  (sym ==  defn.Any_asInstanceOf  ||  sym ==  defn.Any_isInstanceOf )) || 
564600        owner.maybeOwner ==  defn.CompiletimePackageClass 
565601      )
566602
567603object  InstrumentCoverage : 
568604  val  name :  String  =  " instrumentCoverage" 
569605  val  description :  String  =  " instrument code for coverage checking" 
570-   val  ExcludeMethodFlags :  FlagSet  =  Synthetic   |   Artifact  |  Erased 
606+   val  ExcludeMethodFlags :  FlagSet  =  Artifact  |  Erased 
571607
572608  /**  
573609   * An instrumented Tree, in 3 parts. 
0 commit comments