diff --git a/compiler/src/dotty/tools/dotc/transform/ElimRepeated.scala b/compiler/src/dotty/tools/dotc/transform/ElimRepeated.scala index 9e4e45829cff..bdc2a268c1f8 100644 --- a/compiler/src/dotty/tools/dotc/transform/ElimRepeated.scala +++ b/compiler/src/dotty/tools/dotc/transform/ElimRepeated.scala @@ -124,17 +124,21 @@ class ElimRepeated extends MiniPhase with InfoTransformer { thisPhase => tp override def transformApply(tree: Apply)(using Context): Tree = - val args = tree.args.mapConserve { - case arg: Typed if isWildcardStarArg(arg) => + val args = tree.args.mapConserve { arg => + if isWildcardStarArg(arg) then + val expr = arg match + case t: Typed => t.expr + case _ => arg // if the argument has been lifted it's not a Typed (often it's an Ident) + val isJavaDefined = tree.fun.symbol.is(JavaDefined) - val tpe = arg.expr.tpe if isJavaDefined then - adaptToArray(arg.expr) - else if tpe.derivesFrom(defn.ArrayClass) then - arrayToSeq(arg.expr) + adaptToArray(expr) + else if expr.tpe.derivesFrom(defn.ArrayClass) then + arrayToSeq(expr) else - arg.expr - case arg => arg + expr + else + arg } cpy.Apply(tree)(tree.fun, args) @@ -287,9 +291,9 @@ class ElimRepeated extends MiniPhase with InfoTransformer { thisPhase => val array = tp.translateFromRepeated(toArray = true) // Array[? <: T] val element = array.elemType.hiBound // T - if element <:< defn.AnyRefType || ctx.mode.is(Mode.SafeNulls) && element.stripNull <:< defn.AnyRefType - || element.typeSymbol.isPrimitiveValueClass then array + || element.typeSymbol.isPrimitiveValueClass + then array else defn.ArrayOf(TypeBounds.upper(AndType(element, defn.AnyRefType))) // Array[? <: T & AnyRef] } diff --git a/compiler/src/dotty/tools/dotc/transform/InstrumentCoverage.scala b/compiler/src/dotty/tools/dotc/transform/InstrumentCoverage.scala index aee8b7af907b..3c7f6e0e8a7a 100644 --- a/compiler/src/dotty/tools/dotc/transform/InstrumentCoverage.scala +++ b/compiler/src/dotty/tools/dotc/transform/InstrumentCoverage.scala @@ -4,6 +4,7 @@ package transform import java.io.File import java.util.concurrent.atomic.AtomicInteger +import ast.tpd.* import collection.mutable import core.Flags.* import core.Contexts.{Context, ctx, inContext} @@ -17,13 +18,13 @@ import typer.LiftCoverage import util.{SourcePosition, Property} import util.Spans.Span import coverage.* +import localopt.StringInterpolatorOpt.isCompilerIntrinsic /** Implements code coverage by inserting calls to scala.runtime.coverage.Invoker * ("instruments" the source code). * The result can then be consumed by the Scoverage tool. */ class InstrumentCoverage extends MacroTransform with IdentityDenotTransformer: - import ast.tpd._ override def phaseName = InstrumentCoverage.name @@ -60,7 +61,7 @@ class InstrumentCoverage extends MacroTransform with IdentityDenotTransformer: /** Transforms trees to insert calls to Invoker.invoked to compute the coverage when the code is called */ private class CoverageTransformer extends Transformer: - override def transform(tree: Tree)(using ctx: Context): Tree = + override def transform(tree: Tree)(using Context): Tree = inContext(transformCtx(tree)) { // necessary to position inlined code properly tree match // simple cases @@ -278,16 +279,21 @@ class InstrumentCoverage extends MacroTransform with IdentityDenotTransformer: * should not be changed to {val $x = f(); T($x)}(1) but to {val $x = f(); val $y = 1; T($x)($y)} */ private def needsLift(tree: Apply)(using Context): Boolean = - def isBooleanOperator(fun: Tree) = - // We don't want to lift a || getB(), to avoid calling getB if a is true. - // Same idea with a && getB(): if a is false, getB shouldn't be called. - val sym = fun.symbol - sym.exists && + def isShortCircuitedOp(sym: Symbol) = sym == defn.Boolean_&& || sym == defn.Boolean_|| - def isContextual(fun: Apply): Boolean = - val args = fun.args - args.nonEmpty && args.head.symbol.isAllOf(GivenOrImplicit) + def isUnliftableFun(fun: Tree) = + /* + * We don't want to lift a || getB(), to avoid calling getB if a is true. + * Same idea with a && getB(): if a is false, getB shouldn't be called. + * + * On top of that, the `s`, `f` and `raw` string interpolators are special-cased + * by the compiler and will disappear in phase StringInterpolatorOpt, therefore + * they shouldn't be lifted. + */ + val sym = fun.symbol + sym.exists && (isShortCircuitedOp(sym) || isCompilerIntrinsic(sym)) + end val fun = tree.fun val nestedApplyNeedsLift = fun match @@ -295,7 +301,7 @@ class InstrumentCoverage extends MacroTransform with IdentityDenotTransformer: case _ => false nestedApplyNeedsLift || - !isBooleanOperator(fun) && !tree.args.isEmpty && !tree.args.forall(LiftCoverage.noLift) + !isUnliftableFun(fun) && !tree.args.isEmpty && !tree.args.forall(LiftCoverage.noLift) /** Check if the body of a DefDef can be instrumented with instrumentBody. */ private def canInstrumentDefDef(tree: DefDef)(using Context): Boolean = diff --git a/compiler/src/dotty/tools/dotc/transform/localopt/StringInterpolatorOpt.scala b/compiler/src/dotty/tools/dotc/transform/localopt/StringInterpolatorOpt.scala index 681641853b10..5cad7ba72831 100644 --- a/compiler/src/dotty/tools/dotc/transform/localopt/StringInterpolatorOpt.scala +++ b/compiler/src/dotty/tools/dotc/transform/localopt/StringInterpolatorOpt.scala @@ -31,7 +31,7 @@ class StringInterpolatorOpt extends MiniPhase: tree match case tree: RefTree => val sym = tree.symbol - assert(sym != defn.StringContext_raw && sym != defn.StringContext_s && sym != defn.StringContext_f, + assert(!StringInterpolatorOpt.isCompilerIntrinsic(sym), i"$tree in ${ctx.owner.showLocated} should have been rewritten by phase $phaseName") case _ => @@ -162,3 +162,9 @@ class StringInterpolatorOpt extends MiniPhase: object StringInterpolatorOpt: val name: String = "interpolators" val description: String = "optimize s, f, and raw string interpolators" + + /** Is this symbol one of the s, f or raw string interpolator? */ + def isCompilerIntrinsic(sym: Symbol)(using Context): Boolean = + sym == defn.StringContext_s || + sym == defn.StringContext_f || + sym == defn.StringContext_raw diff --git a/compiler/src/dotty/tools/dotc/typer/EtaExpansion.scala b/compiler/src/dotty/tools/dotc/typer/EtaExpansion.scala index 34b7bd96b343..46725f0fa6b2 100644 --- a/compiler/src/dotty/tools/dotc/typer/EtaExpansion.scala +++ b/compiler/src/dotty/tools/dotc/typer/EtaExpansion.scala @@ -159,23 +159,39 @@ class LiftComplex extends Lifter { } object LiftComplex extends LiftComplex -/** Lift complex + lift the prefixes */ -object LiftCoverage extends LiftComplex { +/** Lift impure + lift the prefixes */ +object LiftCoverage extends LiftImpure { - private val LiftEverything = new Property.Key[Boolean] + // Property indicating whether we're currently lifting the arguments of an application + private val LiftingArgs = new Property.Key[Boolean] - private inline def liftEverything(using Context): Boolean = - ctx.property(LiftEverything).contains(true) + private inline def liftingArgs(using Context): Boolean = + ctx.property(LiftingArgs).contains(true) - private def liftEverythingContext(using Context): Context = - ctx.fresh.setProperty(LiftEverything, true) + private def liftingArgsContext(using Context): Context = + ctx.fresh.setProperty(LiftingArgs, true) + + /** Variant of `noLift` for the arguments of applications. + * To produce the right coverage information (especially in case of exceptions), we must lift: + * - all the applications, except the erased ones + * - all the impure arguments + * + * There's no need to lift the other arguments. + */ + 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 tpd.Block(stats, expr) => stats.forall(noLiftArg) && noLiftArg(expr) + case tpd.Inlined(_, bindings, expr) => noLiftArg(expr) + case tpd.Typed(expr, _) => noLiftArg(expr) + case _ => super.noLift(arg) override def noLift(expr: tpd.Tree)(using Context) = - !liftEverything && super.noLift(expr) + if liftingArgs then noLiftArg(expr) else super.noLift(expr) def liftForCoverage(defs: mutable.ListBuffer[tpd.Tree], tree: tpd.Apply)(using Context) = { val liftedFun = liftApp(defs, tree.fun) - val liftedArgs = liftArgs(defs, tree.fun.tpe, tree.args)(using liftEverythingContext) + val liftedArgs = liftArgs(defs, tree.fun.tpe, tree.args)(using liftingArgsContext) tpd.cpy.Apply(tree)(liftedFun, liftedArgs) } } diff --git a/compiler/test/dotty/tools/dotc/coverage/CoverageTests.scala b/compiler/test/dotty/tools/dotc/coverage/CoverageTests.scala index 12c2cca34911..6db6a330f55e 100644 --- a/compiler/test/dotty/tools/dotc/coverage/CoverageTests.scala +++ b/compiler/test/dotty/tools/dotc/coverage/CoverageTests.scala @@ -69,10 +69,11 @@ class CoverageTests: def computeCoverageInTmp(inputFile: Path, sourceRoot: Path, run: Boolean)(using TestGroup): Path = val target = Files.createTempDirectory("coverage") val options = defaultOptions.and("-Ycheck:instrumentCoverage", "-coverage-out", target.toString, "-sourceroot", sourceRoot.toString) - val test = compileFile(inputFile.toString, options) if run then + val test = compileDir(inputFile.getParent.toString, options) test.checkRuns() else + val test = compileFile(inputFile.toString, options) test.checkCompile() target diff --git a/tests/coverage/pos/ContextFunctions.scoverage.check b/tests/coverage/pos/ContextFunctions.scoverage.check index 74a76df8bbf4..9c2ed02d8b44 100644 --- a/tests/coverage/pos/ContextFunctions.scoverage.check +++ b/tests/coverage/pos/ContextFunctions.scoverage.check @@ -92,16 +92,16 @@ covtest Imperative Class covtest.Imperative -$anonfun -267 -294 +readPerson +252 +295 13 invoked Apply false 0 false -readName2(using e)(using s) +OnError((e) => readName2(using e)(using s)) 5 ContextFunctions.scala @@ -113,7 +113,7 @@ $anonfun 267 294 13 -apply +invoked Apply false 0 @@ -126,16 +126,16 @@ covtest Imperative Class covtest.Imperative -readPerson -252 -295 +$anonfun +267 +294 13 -invoked +apply Apply false 0 false -OnError((e) => readName2(using e)(using s)) +readName2(using e)(using s) 7 ContextFunctions.scala diff --git a/tests/coverage/run/erased/test.check b/tests/coverage/run/erased/test.check new file mode 100644 index 000000000000..3e287ad0ce91 --- /dev/null +++ b/tests/coverage/run/erased/test.check @@ -0,0 +1,3 @@ +foo(a)(b) +identity(idem) +foo(a)(idem) \ No newline at end of file diff --git a/tests/coverage/run/erased/test.scala b/tests/coverage/run/erased/test.scala new file mode 100644 index 000000000000..9419d68f955c --- /dev/null +++ b/tests/coverage/run/erased/test.scala @@ -0,0 +1,15 @@ +import scala.language.experimental.erasedDefinitions + +erased def e(x: String): String = "x" +def foo(erased a: String)(b: String): String = + println(s"foo(a)($b)") + b + +def identity(s: String): String = + println(s"identity($s)") + s + +@main +def Test: Unit = + foo(e("a"))("b") + foo(e("a"))(identity("idem")) diff --git a/tests/coverage/run/erased/test.scoverage.check b/tests/coverage/run/erased/test.scoverage.check new file mode 100644 index 000000000000..3cd9ff86c40a --- /dev/null +++ b/tests/coverage/run/erased/test.scoverage.check @@ -0,0 +1,208 @@ +# 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 +erased/test.scala + +test$package$ +Object +.test$package$ +foo +149 +162 +4 +s +Apply +false +0 +false +s"foo(a)($b)" + +1 +erased/test.scala + +test$package$ +Object +.test$package$ +foo +141 +163 +4 +println +Apply +false +0 +false +println(s"foo(a)($b)") + +2 +erased/test.scala + +test$package$ +Object +.test$package$ +foo +92 +99 +3 +foo +DefDef +false +0 +false +def foo + +3 +erased/test.scala + +test$package$ +Object +.test$package$ +identity +213 +228 +8 +s +Apply +false +0 +false +s"identity($s)" + +4 +erased/test.scala + +test$package$ +Object +.test$package$ +identity +205 +229 +8 +println +Apply +false +0 +false +println(s"identity($s)") + +5 +erased/test.scala + +test$package$ +Object +.test$package$ +identity +169 +181 +7 +identity +DefDef +false +0 +false +def identity + +6 +erased/test.scala + +test$package$ +Object +.test$package$ +Test +264 +270 +13 +e +Apply +false +0 +false +e("a") + +7 +erased/test.scala + +test$package$ +Object +.test$package$ +Test +260 +276 +13 +foo +Apply +false +0 +false +foo(e("a"))("b") + +8 +erased/test.scala + +test$package$ +Object +.test$package$ +Test +291 +307 +14 +identity +Apply +false +0 +false +identity("idem") + +9 +erased/test.scala + +test$package$ +Object +.test$package$ +Test +279 +308 +14 +foo +Apply +false +0 +false +foo(e("a"))(identity("idem")) + +10 +erased/test.scala + +test$package$ +Object +.test$package$ +Test +235 +249 +12 +Test +DefDef +false +0 +false +@main +def Test + diff --git a/tests/coverage/run/interpolation/test.check b/tests/coverage/run/interpolation/test.check index 9ce4b367db49..34408817a623 100644 --- a/tests/coverage/run/interpolation/test.check +++ b/tests/coverage/run/interpolation/test.check @@ -3,3 +3,6 @@ 2: t 3: t 4: y +1, 3 +0x007f +a\nb diff --git a/tests/coverage/run/interpolation/test.scala b/tests/coverage/run/interpolation/test.scala index 3745367b593d..183b1131b22b 100644 --- a/tests/coverage/run/interpolation/test.scala +++ b/tests/coverage/run/interpolation/test.scala @@ -3,7 +3,13 @@ object Test: def simple(a: Int, b: String): String = s"$a, ${b.length}" + def hexa(i: Int): String = + f"0x${i}%04x" + def main(args: Array[String]): Unit = val xs: List[String] = List("d", "o", "t", "t", "y") - xs.zipWithIndex.map((s, i) => println(s"$i: $s")) + + println(simple(1, "abc")) + println(hexa(127)) + println(raw"a\nb") diff --git a/tests/coverage/run/interpolation/test.scoverage.check b/tests/coverage/run/interpolation/test.scoverage.check index 9c93d58f182c..f30b391d20e5 100644 --- a/tests/coverage/run/interpolation/test.scoverage.check +++ b/tests/coverage/run/interpolation/test.scoverage.check @@ -75,10 +75,44 @@ interpolation/test.scala Test$ Object .Test$ -main -147 -176 +hexa +113 +126 6 +f +Apply +false +0 +false +f"0x${i}%04x" + +4 +interpolation/test.scala + +Test$ +Object +.Test$ +hexa +82 +90 +5 +hexa +DefDef +false +0 +false +def hexa + +5 +interpolation/test.scala + +Test$ +Object +.Test$ +main +195 +224 +9 apply Apply false @@ -86,16 +120,16 @@ false false List("d", "o", "t", "t", "y") -4 +6 interpolation/test.scala Test$ Object .Test$ $anonfun -220 -229 -8 +267 +276 +10 s Apply false @@ -103,16 +137,16 @@ false false s"$i: $s" -5 +7 interpolation/test.scala Test$ Object .Test$ $anonfun -212 -230 -8 +259 +277 +10 println Apply false @@ -120,16 +154,16 @@ false false println(s"$i: $s") -6 +8 interpolation/test.scala Test$ Object .Test$ main -182 -231 -8 +229 +278 +10 map Apply false @@ -137,16 +171,118 @@ false false xs.zipWithIndex.map((s, i) => println(s"$i: $s")) -7 +9 interpolation/test.scala Test$ Object .Test$ main -82 -90 -5 +292 +308 +12 +simple +Apply +false +0 +false +simple(1, "abc") + +10 +interpolation/test.scala + +Test$ +Object +.Test$ +main +284 +309 +12 +println +Apply +false +0 +false +println(simple(1, "abc")) + +11 +interpolation/test.scala + +Test$ +Object +.Test$ +main +322 +331 +13 +hexa +Apply +false +0 +false +hexa(127) + +12 +interpolation/test.scala + +Test$ +Object +.Test$ +main +314 +332 +13 +println +Apply +false +0 +false +println(hexa(127)) + +13 +interpolation/test.scala + +Test$ +Object +.Test$ +main +345 +354 +14 +raw +Apply +false +0 +false +raw"a\nb" + +14 +interpolation/test.scala + +Test$ +Object +.Test$ +main +337 +355 +14 +println +Apply +false +0 +false +println(raw"a\nb") + +15 +interpolation/test.scala + +Test$ +Object +.Test$ +main +130 +138 +8 main DefDef false diff --git a/tests/coverage/run/lifting-bool/test.check b/tests/coverage/run/lifting-bool/test.check new file mode 100644 index 000000000000..c388c06b06fb --- /dev/null +++ b/tests/coverage/run/lifting-bool/test.check @@ -0,0 +1,3 @@ +true false true false false +true +true \ No newline at end of file diff --git a/tests/coverage/run/lifting-bool/test.scala b/tests/coverage/run/lifting-bool/test.scala new file mode 100644 index 000000000000..f03a01fae60b --- /dev/null +++ b/tests/coverage/run/lifting-bool/test.scala @@ -0,0 +1,19 @@ + +def notCalled() = ??? + +def f(x: Boolean, y: Boolean): Boolean = x + +@main +def Test: Unit = + val a = true || notCalled() // true + val b = false && notCalled() // false + val c = (true || false) || notCalled() // true + val d = true && (false && notCalled()) // false + val e = (true && false) && notCalled() // false + println(s"$a $b $c $d $e") + + var x = f(true, false) + println(x) // true + + x = f(true || notCalled(), false && notCalled()) + println(x) // true diff --git a/tests/coverage/run/lifting-bool/test.scoverage.check b/tests/coverage/run/lifting-bool/test.scoverage.check new file mode 100644 index 000000000000..49f83b4eecc8 --- /dev/null +++ b/tests/coverage/run/lifting-bool/test.scoverage.check @@ -0,0 +1,463 @@ +# 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 +lifting-bool/test.scala + +test$package$ +Object +.test$package$ +notCalled +1 +14 +1 +notCalled +DefDef +false +0 +false +def notCalled + +1 +lifting-bool/test.scala + +test$package$ +Object +.test$package$ +f +24 +29 +3 +f +DefDef +false +0 +false +def f + +2 +lifting-bool/test.scala + +test$package$ +Object +.test$package$ +Test +109 +120 +7 +notCalled +Apply +false +0 +false +notCalled() + +3 +lifting-bool/test.scala + +test$package$ +Object +.test$package$ +Test +101 +120 +7 +|| +Apply +false +0 +false +true || notCalled() + +4 +lifting-bool/test.scala + +test$package$ +Object +.test$package$ +Test +159 +170 +8 +notCalled +Apply +false +0 +false +notCalled() + +5 +lifting-bool/test.scala + +test$package$ +Object +.test$package$ +Test +150 +170 +8 +&& +Apply +false +0 +false +false && notCalled() + +6 +lifting-bool/test.scala + +test$package$ +Object +.test$package$ +Test +201 +214 +9 +|| +Apply +false +0 +false +true || false + +7 +lifting-bool/test.scala + +test$package$ +Object +.test$package$ +Test +219 +230 +9 +notCalled +Apply +false +0 +false +notCalled() + +8 +lifting-bool/test.scala + +test$package$ +Object +.test$package$ +Test +200 +230 +9 +|| +Apply +false +0 +false +(true || false) || notCalled() + +9 +lifting-bool/test.scala + +test$package$ +Object +.test$package$ +Test +267 +278 +10 +notCalled +Apply +false +0 +false +notCalled() + +10 +lifting-bool/test.scala + +test$package$ +Object +.test$package$ +Test +258 +278 +10 +&& +Apply +false +0 +false +false && notCalled() + +11 +lifting-bool/test.scala + +test$package$ +Object +.test$package$ +Test +249 +278 +10 +&& +Apply +false +0 +false +true && (false && notCalled() + +12 +lifting-bool/test.scala + +test$package$ +Object +.test$package$ +Test +300 +313 +11 +&& +Apply +false +0 +false +true && false + +13 +lifting-bool/test.scala + +test$package$ +Object +.test$package$ +Test +318 +329 +11 +notCalled +Apply +false +0 +false +notCalled() + +14 +lifting-bool/test.scala + +test$package$ +Object +.test$package$ +Test +299 +329 +11 +&& +Apply +false +0 +false +(true && false) && notCalled() + +15 +lifting-bool/test.scala + +test$package$ +Object +.test$package$ +Test +349 +366 +12 +s +Apply +false +0 +false +s"$a $b $c $d $e" + +16 +lifting-bool/test.scala + +test$package$ +Object +.test$package$ +Test +341 +367 +12 +println +Apply +false +0 +false +println(s"$a $b $c $d $e") + +17 +lifting-bool/test.scala + +test$package$ +Object +.test$package$ +Test +379 +393 +14 +f +Apply +false +0 +false +f(true, false) + +18 +lifting-bool/test.scala + +test$package$ +Object +.test$package$ +Test +396 +406 +15 +println +Apply +false +0 +false +println(x) + +19 +lifting-bool/test.scala + +test$package$ +Object +.test$package$ +Test +432 +443 +17 +notCalled +Apply +false +0 +false +notCalled() + +20 +lifting-bool/test.scala + +test$package$ +Object +.test$package$ +Test +424 +443 +17 +|| +Apply +false +0 +false +true || notCalled() + +21 +lifting-bool/test.scala + +test$package$ +Object +.test$package$ +Test +454 +465 +17 +notCalled +Apply +false +0 +false +notCalled() + +22 +lifting-bool/test.scala + +test$package$ +Object +.test$package$ +Test +445 +465 +17 +&& +Apply +false +0 +false +false && notCalled() + +23 +lifting-bool/test.scala + +test$package$ +Object +.test$package$ +Test +422 +466 +17 +f +Apply +false +0 +false +f(true || notCalled(), false && notCalled()) + +24 +lifting-bool/test.scala + +test$package$ +Object +.test$package$ +Test +469 +479 +18 +println +Apply +false +0 +false +println(x) + +25 +lifting-bool/test.scala + +test$package$ +Object +.test$package$ +Test +68 +82 +6 +Test +DefDef +false +0 +false +@main +def Test + diff --git a/tests/coverage/run/varargs/JavaVarargs_1.java b/tests/coverage/run/varargs/JavaVarargs_1.java new file mode 100644 index 000000000000..2d3a300715cc --- /dev/null +++ b/tests/coverage/run/varargs/JavaVarargs_1.java @@ -0,0 +1,7 @@ +class JavaVarargs_1 { + static void method(String... args) {} + + static Object multiple(Object first, String... others) { + return String.valueOf(first) + others.length; + } +} diff --git a/tests/coverage/run/varargs/test_1.check b/tests/coverage/run/varargs/test_1.check new file mode 100644 index 000000000000..d28df10f66db --- /dev/null +++ b/tests/coverage/run/varargs/test_1.check @@ -0,0 +1,3 @@ +first0 +first0 +first3 \ No newline at end of file diff --git a/tests/coverage/run/varargs/test_1.scala b/tests/coverage/run/varargs/test_1.scala new file mode 100644 index 000000000000..0e6f76d06909 --- /dev/null +++ b/tests/coverage/run/varargs/test_1.scala @@ -0,0 +1,20 @@ +import java.nio.file.Files +import java.io.File + +def repeated(s: String*) = () + +def f(s: String) = s + +@main +def Test = + repeated() + repeated(f(""), "b") + JavaVarargs_1.method() + JavaVarargs_1.method("") + + var m = JavaVarargs_1.multiple("first") + println(m) + m = JavaVarargs_1.multiple(f("first")) + println(m) + m = JavaVarargs_1.multiple(f("first"), "a", "b", "c") + println(m) diff --git a/tests/coverage/run/varargs/test_1.scoverage.check b/tests/coverage/run/varargs/test_1.scoverage.check new file mode 100644 index 000000000000..3a242f7a97a4 --- /dev/null +++ b/tests/coverage/run/varargs/test_1.scoverage.check @@ -0,0 +1,293 @@ +# 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 +varargs/test_1.scala + +test_1$package$ +Object +.test_1$package$ +repeated +48 +60 +3 +repeated +DefDef +false +0 +false +def repeated + +1 +varargs/test_1.scala + +test_1$package$ +Object +.test_1$package$ +f +79 +84 +5 +f +DefDef +false +0 +false +def f + +2 +varargs/test_1.scala + +test_1$package$ +Object +.test_1$package$ +Test +120 +130 +9 +repeated +Apply +false +0 +false +repeated() + +3 +varargs/test_1.scala + +test_1$package$ +Object +.test_1$package$ +Test +142 +147 +10 +f +Apply +false +0 +false +f("") + +4 +varargs/test_1.scala + +test_1$package$ +Object +.test_1$package$ +Test +133 +153 +10 +repeated +Apply +false +0 +false +repeated(f(""), "b") + +5 +varargs/test_1.scala + +test_1$package$ +Object +.test_1$package$ +Test +156 +178 +11 +method +Apply +false +0 +false +JavaVarargs_1.method() + +6 +varargs/test_1.scala + +test_1$package$ +Object +.test_1$package$ +Test +181 +205 +12 +method +Apply +false +0 +false +JavaVarargs_1.method("") + +7 +varargs/test_1.scala + +test_1$package$ +Object +.test_1$package$ +Test +217 +248 +14 +multiple +Apply +false +0 +false +JavaVarargs_1.multiple("first") + +8 +varargs/test_1.scala + +test_1$package$ +Object +.test_1$package$ +Test +251 +261 +15 +println +Apply +false +0 +false +println(m) + +9 +varargs/test_1.scala + +test_1$package$ +Object +.test_1$package$ +Test +291 +301 +16 +f +Apply +false +0 +false +f("first") + +10 +varargs/test_1.scala + +test_1$package$ +Object +.test_1$package$ +Test +268 +302 +16 +multiple +Apply +false +0 +false +JavaVarargs_1.multiple(f("first")) + +11 +varargs/test_1.scala + +test_1$package$ +Object +.test_1$package$ +Test +305 +315 +17 +println +Apply +false +0 +false +println(m) + +12 +varargs/test_1.scala + +test_1$package$ +Object +.test_1$package$ +Test +345 +355 +18 +f +Apply +false +0 +false +f("first") + +13 +varargs/test_1.scala + +test_1$package$ +Object +.test_1$package$ +Test +322 +371 +18 +multiple +Apply +false +0 +false +JavaVarargs_1.multiple(f("first"), "a", "b", "c") + +14 +varargs/test_1.scala + +test_1$package$ +Object +.test_1$package$ +Test +374 +384 +19 +println +Apply +false +0 +false +println(m) + +15 +varargs/test_1.scala + +test_1$package$ +Object +.test_1$package$ +Test +101 +115 +8 +Test +DefDef +false +0 +false +@main +def Test +