diff options
author | Simon Ochsenreither <simon@ochsenreither.de> | 2015-08-31 05:03:29 +0200 |
---|---|---|
committer | Simon Ochsenreither <simon@ochsenreither.de> | 2016-01-25 19:21:43 +0100 |
commit | c78d771e6f025e767801f7fe118acc2ea7540acd (patch) | |
tree | e2e4faa4bcc60e7b5fd0d9a59d5586ed5522b900 /test/files/run/t9437c/Test.scala | |
parent | 94a228f90e7d0cb997c866a8b9a7663c67e2df3d (diff) | |
download | scala-c78d771e6f025e767801f7fe118acc2ea7540acd.tar.gz scala-c78d771e6f025e767801f7fe118acc2ea7540acd.tar.bz2 scala-c78d771e6f025e767801f7fe118acc2ea7540acd.zip |
SI-9437 Emit and support parameter names in class files
JEP 118 added a MethodParameters attribute to the class file spec which
holds the parameter names of methods when compiling Java code with
`javac -parameters`.
We emit parameter names by default now.
Diffstat (limited to 'test/files/run/t9437c/Test.scala')
-rw-r--r-- | test/files/run/t9437c/Test.scala | 92 |
1 files changed, 92 insertions, 0 deletions
diff --git a/test/files/run/t9437c/Test.scala b/test/files/run/t9437c/Test.scala new file mode 100644 index 0000000000..4be233a258 --- /dev/null +++ b/test/files/run/t9437c/Test.scala @@ -0,0 +1,92 @@ +import java.io.{File, FileOutputStream} + +import scala.tools.nsc.settings.ScalaVersion +import scala.tools.partest._ +import scala.tools.asm +import asm.{AnnotationVisitor, ClassWriter, FieldVisitor, Handle, MethodVisitor, Opcodes} +import Opcodes._ + +// This test ensures that we can read JDK 8 (classfile format 52) files with +// parameter names. To do that it first uses ASM to generate a class containing +// these additional attributes. Then it runs a normal compile on Scala source +// that uses the class with named arguments. +// Any failure will be dumped to std out. +object Test extends DirectTest { + override def extraSettings: String = "-usejavacp -d " + testOutput.path + " -cp " + testOutput.path + + def generateCode(): Unit = { + val className = "Foo" + + val cw = new ClassWriter(0) + cw.visit(52, ACC_PUBLIC + ACC_SUPER, className, null, "java/lang/Object", null); + + val mvC = cw.visitMethod(ACC_PUBLIC, "<init>", "(ILjava/lang/String;JFD)V", null, null); + mvC.visitParameter("a", ACC_FINAL); + mvC.visitParameter("_", ACC_FINAL); + mvC.visitParameter("***", ACC_FINAL); + mvC.visitParameter("unary_!", ACC_FINAL); + mvC.visitParameter("ABC", ACC_FINAL); + mvC.visitCode(); + mvC.visitVarInsn(ALOAD, 0); + mvC.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V", false); + mvC.visitInsn(RETURN); + mvC.visitMaxs(1, 8); + mvC.visitEnd(); + + val mvM = cw.visitMethod(ACC_PUBLIC, "bar", "(ILjava/lang/String;JFD)Lscala/runtime/Null$;", null, null); + mvM.visitParameter("a", ACC_FINAL); + mvM.visitParameter("_", ACC_FINAL); + mvM.visitParameter("***", ACC_FINAL); + mvM.visitParameter("unary_!", ACC_FINAL); + mvM.visitParameter("ABC", ACC_FINAL); + mvM.visitCode(); + mvM.visitInsn(ACONST_NULL); + mvM.visitInsn(ARETURN); + mvM.visitMaxs(1, 8); + mvM.visitEnd(); + + cw.visitEnd(); + + val bytes = cw.toByteArray() + + val fos = new FileOutputStream(new File(s"${testOutput.path}/$className.class")) + try + fos write bytes + finally + fos.close() + + } + + def code = +""" +class Driver { + val constrParams = classOf[Foo].getConstructors.head.getParameters + val methodParams = classOf[Foo].getDeclaredMethods.head.getParameters + + def printParams(params: Array[java.lang.reflect.Parameter]) = { + params.foreach { param => + println(s"name: ${param.getName}; isNamePresent: ${param.isNamePresent}; isSynthetic: ${param.isSynthetic}") + } + } + + printParams(constrParams) + printParams(methodParams) + + val foo = new Foo(a = 1, `_` = "2", *** = 3L, `unary_!` = 4.0f, ABC = 5.0) + foo.bar(a = 1, `_` = "2", *** = 3L, `unary_!` = 4.0f, ABC = 5.0) +} +""" + + override def show(): Unit = { + // redirect err to out, for logging + val prevErr = System.err + System.setErr(System.out) + try { + generateCode() + compile() + Class.forName("Driver").newInstance() + } + finally + System.setErr(prevErr) + } +} |