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
|
package scala.reflect
package runtime
import java.lang.{Class => jClass, Package => jPackage}
import java.lang.reflect.{
Method => jMethod, Constructor => jConstructor, Modifier => jModifier, Field => jField,
Member => jMember, Type => jType, TypeVariable => jTypeVariable, GenericDeclaration}
import collection.mutable.HashMap
trait ConversionUtil { self: SymbolTable =>
/** A cache that maintains a bijection between Java reflection type `J`
* and Scala reflection type `S`.
*/
protected class TwoWayCache[J, S] {
private val toScalaMap = new HashMap[J, S]
private val toJavaMap = new HashMap[S, J]
def enter(j: J, s: S) = synchronized {
debugInfo("cached: "+j+"/"+s)
toScalaMap(j) = s
toJavaMap(s) = j
}
def toScala(key: J)(body: => S): S = synchronized {
toScalaMap get key match {
case Some(v) =>
v
case none =>
val result = body
enter(key, result)
result
}
}
def toJava(key: S)(body: => J): J = synchronized {
toJavaMap get key match {
case Some(v) =>
v
case none =>
val result = body
enter(result, key)
result
}
}
def toJavaOption(key: S)(body: => Option[J]): Option[J] = synchronized {
toJavaMap get key match {
case None =>
val result = body
for (value <- result) enter(value, key)
result
case some => some
}
}
}
protected val classCache = new TwoWayCache[jClass[_], Symbol]
protected val packageCache = new TwoWayCache[Package, Symbol]
protected val methodCache = new TwoWayCache[jMethod, Symbol]
protected val constructorCache = new TwoWayCache[jConstructor[_], Symbol]
protected val fieldCache = new TwoWayCache[jField, Symbol]
protected val tparamCache = new TwoWayCache[jTypeVariable[_], Symbol]
/** the type of this symbol after Scala -> Java transformsi in refChecks, uncurry, erasure
*/
def transformedType(sym: Symbol): Type
/** The Java class thaty given type compiles to */
def typeToJavaClass(tpe: Type): jClass[_]
/** Does method `meth` erase to Java method `jmeth`?
* This is true if the Java method type is the same as the Scala method type after performing
* all Scala-specific transformations in InfoTransformers. (to be done)
*/
protected def erasesTo(meth: Symbol, jmeth: jMethod): Boolean = {
val mtpe = transformedType(meth)
(mtpe.paramTypes map typeToJavaClass) == jmeth.getParameterTypes.toList &&
typeToJavaClass(mtpe.resultType) == jmeth.getReturnType
}
/** Does constructor `meth` erase to Java method `jconstr`?
* This is true if the Java constructor type is the same as the Scala constructor type after performing
* all Scala-specific transformations in InfoTransformers. (to be done)
*/
protected def erasesTo(meth: Symbol, jconstr: jConstructor[_]): Boolean = {
val mtpe = transformedType(meth)
(mtpe.paramTypes map typeToJavaClass) == jconstr.getParameterTypes.toList
}
}
|