1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
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)
}
}
|