diff options
Diffstat (limited to 'test/junit/scala/tools/nsc/backend/jvm/CodeGenTools.scala')
-rw-r--r-- | test/junit/scala/tools/nsc/backend/jvm/CodeGenTools.scala | 74 |
1 files changed, 69 insertions, 5 deletions
diff --git a/test/junit/scala/tools/nsc/backend/jvm/CodeGenTools.scala b/test/junit/scala/tools/nsc/backend/jvm/CodeGenTools.scala index ee9580c1c3..fe43ed2f6a 100644 --- a/test/junit/scala/tools/nsc/backend/jvm/CodeGenTools.scala +++ b/test/junit/scala/tools/nsc/backend/jvm/CodeGenTools.scala @@ -48,11 +48,13 @@ object CodeGenTools { resetOutput(compiler) compiler } - + def newCompilerWithoutVirtualOutdir(defaultArgs: String = "-usejavacp", extraArgs: String = ""): Global = { - val settings = new Settings() + def showError(s: String) = throw new Exception(s) + val settings = new Settings(showError) val args = (CommandLineParser tokenize defaultArgs) ++ (CommandLineParser tokenize extraArgs) - settings.processArguments(args, processAll = true) + val (_, nonSettingsArgs) = settings.processArguments(args, processAll = true) + if (nonSettingsArgs.nonEmpty) showError("invalid compiler flags: " + nonSettingsArgs.mkString(" ")) new Global(settings, new StoreReporter) } @@ -93,6 +95,23 @@ object CodeGenTools { getGeneratedClassfiles(compiler.settings.outputDirs.getSingleOutput.get) } + def compileTransformed(compiler: Global)(scalaCode: String, javaCode: List[(String, String)] = Nil, beforeBackend: compiler.Tree => compiler.Tree): List[(String, Array[Byte])] = { + compiler.settings.stopBefore.value = "jvm" :: Nil + val run = newRun(compiler) + import compiler._ + val scalaUnit = newCompilationUnit(scalaCode, "unitTestSource.scala") + val javaUnits = javaCode.map(p => newCompilationUnit(p._1, p._2)) + val units = scalaUnit :: javaUnits + run.compileUnits(units, run.parserPhase) + compiler.settings.stopBefore.value = Nil + scalaUnit.body = beforeBackend(scalaUnit.body) + checkReport(compiler, _ => false) + val run1 = newRun(compiler) + run1.compileUnits(units, run1.phaseNamed("jvm")) + checkReport(compiler, _ => false) + getGeneratedClassfiles(compiler.settings.outputDirs.getSingleOutput.get) + } + /** * Compile multiple Scala files separately into a single output directory. * @@ -145,13 +164,54 @@ object CodeGenTools { convertMethod(m) } + def assertSameCode(method: Method, expected: List[Instruction]): Unit = assertSameCode(method.instructions.dropNonOp, expected) def assertSameCode(actual: List[Instruction], expected: List[Instruction]): Unit = { - assertTrue(s"\nExpected: $expected\nActual : $actual", actual === expected) + assert(actual === expected, s"\nExpected: $expected\nActual : $actual") + } + + def assertSameSummary(method: Method, expected: List[Any]): Unit = assertSameSummary(method.instructions, expected) + def assertSameSummary(actual: List[Instruction], expected: List[Any]): Unit = { + def expectedString = expected.map({ + case s: String => s""""$s"""" + case i: Int => opcodeToString(i, i) + }).mkString("List(", ", ", ")") + assert(actual.summary == expected, s"\nFound : ${actual.summaryText}\nExpected: $expectedString") + } + + def assertNoInvoke(m: Method): Unit = assertNoInvoke(m.instructions) + def assertNoInvoke(ins: List[Instruction]): Unit = { + assert(!ins.exists(_.isInstanceOf[Invoke]), ins.stringLines) + } + + def assertInvoke(m: Method, receiver: String, method: String): Unit = assertInvoke(m.instructions, receiver, method) + def assertInvoke(l: List[Instruction], receiver: String, method: String): Unit = { + assert(l.exists { + case Invoke(_, `receiver`, `method`, _, _) => true + case _ => false + }, l.stringLines) + } + + def assertDoesNotInvoke(m: Method, method: String): Unit = assertDoesNotInvoke(m.instructions, method) + def assertDoesNotInvoke(l: List[Instruction], method: String): Unit = { + assert(!l.exists { + case i: Invoke => i.name == method + case _ => false + }, l.stringLines) + } + + def assertInvokedMethods(m: Method, expected: List[String]): Unit = assertInvokedMethods(m.instructions, expected) + def assertInvokedMethods(l: List[Instruction], expected: List[String]): Unit = { + def quote(l: List[String]) = l.map(s => s""""$s"""").mkString("List(", ", ", ")") + val actual = l collect { case i: Invoke => i.owner + "." + i.name } + assert(actual == expected, s"\nFound : ${quote(actual)}\nExpected: ${quote(expected)}") } def getSingleMethod(classNode: ClassNode, name: String): Method = convertMethod(classNode.methods.asScala.toList.find(_.name == name).get) + def findAsmMethods(c: ClassNode, p: String => Boolean) = c.methods.iterator.asScala.filter(m => p(m.name)).toList.sortBy(_.name) + def findAsmMethod(c: ClassNode, name: String) = findAsmMethods(c, _ == name).head + /** * Instructions that match `query` when textified. * If `query` starts with a `+`, the next instruction is returned. @@ -159,7 +219,7 @@ object CodeGenTools { def findInstr(method: MethodNode, query: String): List[AbstractInsnNode] = { val useNext = query(0) == '+' val instrPart = if (useNext) query.drop(1) else query - val insns = method.instructions.iterator.asScala.find(i => textify(i) contains instrPart).toList + val insns = method.instructions.iterator.asScala.filter(i => textify(i) contains instrPart).toList if (useNext) insns.map(_.getNext) else insns } @@ -175,4 +235,8 @@ object CodeGenTools { implicit class MortalInstruction(val ins: Instruction) extends AnyVal { def dead: (Instruction, Boolean) = (ins, false) } + + implicit class listStringLines[T](val l: List[T]) extends AnyVal { + def stringLines = l.mkString("\n") + } } |