summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2011-08-30 21:04:51 +0000
committerMartin Odersky <odersky@gmail.com>2011-08-30 21:04:51 +0000
commitd8add367dd9e432b53d98a33880bdf56a4505be1 (patch)
tree579437a1b376e8e5628556fa87c8d38cd903f92f /src
parent476e4816f831fcacbc0cb809cabbad726900a975 (diff)
downloadscala-d8add367dd9e432b53d98a33880bdf56a4505be1.tar.gz
scala-d8add367dd9e432b53d98a33880bdf56a4505be1.tar.bz2
scala-d8add367dd9e432b53d98a33880bdf56a4505be1.zip
More fixes to reflection and reflective compiler.
Diffstat (limited to 'src')
-rw-r--r--src/compiler/scala/reflect/internal/Types.scala3
-rw-r--r--src/compiler/scala/reflect/runtime/JavaToScala.scala83
-rw-r--r--src/compiler/scala/reflect/runtime/Loaders.scala1
3 files changed, 63 insertions, 24 deletions
diff --git a/src/compiler/scala/reflect/internal/Types.scala b/src/compiler/scala/reflect/internal/Types.scala
index 5049b6bd90..ded4627e97 100644
--- a/src/compiler/scala/reflect/internal/Types.scala
+++ b/src/compiler/scala/reflect/internal/Types.scala
@@ -1909,7 +1909,8 @@ A type's typeSymbol should never be inspected directly.
// @M: initialize (by sym.info call) needed (see test/files/pos/ticket0137.scala)
@inline private def etaExpand: Type = {
val tpars = sym.info.typeParams // must go through sym.info for typeParams to initialise symbol
- typeFunAnon(tpars, copyTypeRef(this, pre, sym, tpars map (_.tpeHK))) // todo: also beta-reduce?
+ if (tpars.isEmpty) this
+ else typeFunAnon(tpars, copyTypeRef(this, pre, sym, tpars map (_.tpeHK))) // todo: also beta-reduce?
}
override def dealias: Type =
diff --git a/src/compiler/scala/reflect/runtime/JavaToScala.scala b/src/compiler/scala/reflect/runtime/JavaToScala.scala
index e598e7751d..92d9bc5aae 100644
--- a/src/compiler/scala/reflect/runtime/JavaToScala.scala
+++ b/src/compiler/scala/reflect/runtime/JavaToScala.scala
@@ -12,6 +12,7 @@ import java.lang.reflect.{
Type => jType,
TypeVariable => jTypeVariable,
GenericDeclaration,
+ GenericArrayType,
ParameterizedType,
WildcardType,
AnnotatedElement
@@ -100,6 +101,7 @@ trait JavaToScala extends ConversionUtil { self: SymbolTable =>
* @param jtvar The Java type variable
*/
private class TypeParamCompleter(jtvar: jTypeVariable[_ <: GenericDeclaration]) extends LazyType {
+ override def load(sym: Symbol) = complete(sym)
override def complete(sym: Symbol) = {
sym setInfo TypeBounds(NothingClass.tpe, glb(jtvar.getBounds.toList map typeToScala map objToAny))
}
@@ -124,18 +126,31 @@ trait JavaToScala extends ConversionUtil { self: SymbolTable =>
* @param jclazz The Java class
*/
private class FromJavaClassCompleter(clazz: Symbol, module: Symbol, jclazz: jClass[_]) extends LazyType {
- override def complete(sym: Symbol) = {
+ override def load(sym: Symbol) = {
info("completing from Java " + sym + "/" + clazz.fullName)//debug
- assert(sym == clazz || sym == module || sym == module.moduleClass, sym)
+ assert(sym == clazz || (module != NoSymbol && (sym == module || sym == module.moduleClass)), sym)
val flags = toScalaFlags(jclazz.getModifiers, isClass = true)
clazz setFlag (flags | JAVA)
- module setFlag (flags & PRIVATE | JAVA)
- module.moduleClass setFlag (flags & PRIVATE | JAVA)
+ if (module != NoSymbol) {
+ module setFlag (flags & PRIVATE | JAVA)
+ module.moduleClass setFlag (flags & PRIVATE | JAVA)
+ }
copyAnnotations(clazz, jclazz)
// to do: annotations to set also for module?
- val tparams = jclazz.getTypeParameters.toList map createTypeParameter
+ clazz setInfo new LazyPolyType(jclazz.getTypeParameters.toList map createTypeParameter)
+ if (module != NoSymbol) {
+ module setInfo module.moduleClass.tpe
+ module.moduleClass setInfo new LazyPolyType(List())
+ }
+ }
+ override def complete(sym: Symbol): Unit = {
+ load(sym)
+ completeRest()
+ }
+ def completeRest(): Unit = {
+ val tparams = clazz.rawInfo.typeParams
val parents = try {
parentsLevel += 1
@@ -146,22 +161,30 @@ trait JavaToScala extends ConversionUtil { self: SymbolTable =>
parentsLevel -= 1
}
clazz setInfo polyType(tparams, new ClassInfoType(parents, newScope, clazz))
- module.moduleClass setInfo new ClassInfoType(List(), newScope, module.moduleClass)
- module setInfo module.moduleClass.tpe
+ if (module != NoSymbol) {
+ module.moduleClass setInfo new ClassInfoType(List(), newScope, module.moduleClass)
+ }
- def enter(sym: Symbol) =
- (if (sym.isStatic) module.moduleClass else clazz).info.decls enter sym
+ def enter(sym: Symbol, mods: Int) =
+ (if (jModifier.isStatic(mods)) module.moduleClass else clazz).info.decls enter sym
pendingLoadActions = { () =>
+ println("entering members of "+jclazz)
+
+ for (jinner <- jclazz.getDeclaredClasses) {
+ println("... entering "+jinner)
+ enter(jclassAsScala(jinner, clazz), jinner.getModifiers)
+ }
+
for (jfield <- jclazz.getDeclaredFields)
- enter(jfieldAsScala(jfield))
+ enter(jfieldAsScala(jfield), jfield.getModifiers)
for (jmeth <- jclazz.getDeclaredMethods)
- enter(jmethodAsScala(jmeth))
+ enter(jmethodAsScala(jmeth), jmeth.getModifiers)
for (jconstr <- jclazz.getConstructors)
- enter(jconstrAsScala(jconstr))
+ enter(jconstrAsScala(jconstr), jconstr.getModifiers)
} :: pendingLoadActions
@@ -173,6 +196,11 @@ trait JavaToScala extends ConversionUtil { self: SymbolTable =>
}
}
}
+ class LazyPolyType(override val typeParams: List[Symbol]) extends LazyType {
+ override def complete(sym: Symbol) {
+ completeRest()
+ }
+ }
}
/** used to avoid cyclies */
@@ -304,7 +332,9 @@ trait JavaToScala extends ConversionUtil { self: SymbolTable =>
*/
def classToScala(jclazz: jClass[_]): Symbol = classCache.toScala(jclazz) {
if (jclazz.isMemberClass) {
- sOwner(jclazz).info.decl(newTypeName(jclazz.getSimpleName)).asInstanceOf[ClassSymbol]
+ val sym = sOwner(jclazz).info.decl(newTypeName(jclazz.getSimpleName))
+ assert(sym.isType, sym+"/"+jclazz+"/"+sOwner(jclazz)+"/"+jclazz.getSimpleName)
+ sym.asInstanceOf[ClassSymbol]
} else if (jclazz.isLocalClass) { // local classes not preserved by unpickling - treat as Java
jclassAsScala(jclazz)
} else if (jclazz.isArray) {
@@ -361,7 +391,7 @@ trait JavaToScala extends ConversionUtil { self: SymbolTable =>
val tparam = owner.newExistential(NoPosition, newTypeName("T$" + tparams.length))
.setInfo(TypeBounds(
lub(jwild.getLowerBounds.toList map typeToScala),
- glb(scala.tools.nsc.util.trace("glb args of "+owner)(jwild.getUpperBounds.toList) map typeToScala map objToAny)))
+ glb(jwild.getUpperBounds.toList map typeToScala map objToAny)))
tparams += tparam
typeRef(NoPrefix, tparam, List())
case _ =>
@@ -389,6 +419,8 @@ trait JavaToScala extends ConversionUtil { self: SymbolTable =>
val args0 = japplied.getActualTypeArguments
val (args, bounds) = targsToScala(pre.typeSymbol, args0.toList)
ExistentialType(bounds, typeRef(pre, sym, args))
+ case jarr: GenericArrayType =>
+ arrayType(typeToScala(jarr.getGenericComponentType))
case jtvar: jTypeVariable[_] =>
val tparam = tparamToScala(jtvar)
typeRef(NoPrefix, tparam, List())
@@ -400,10 +432,12 @@ trait JavaToScala extends ConversionUtil { self: SymbolTable =>
* @param jclazz The Java class
* @return A Scala class symbol that wraps all reflection info of `jclazz`
*/
- private def jclassAsScala(jclazz: jClass[_]): Symbol = {
- val (clazz, module) = createClassModule(
- sOwner(jclazz), newTypeName(jclazz.getSimpleName), new FromJavaClassCompleter(_, _, jclazz))
- clazz
+ private def jclassAsScala(jclazz: jClass[_]): Symbol = jclassAsScala(jclazz, sOwner(jclazz))
+
+ private def jclassAsScala(jclazz: jClass[_], owner: Symbol): Symbol = {
+ val clazz = owner.newClass(NoPosition, newTypeName(jclazz.getSimpleName))
+ classCache enter (jclazz, clazz)
+ clazz setInfo new FromJavaClassCompleter(clazz, NoSymbol, jclazz)
}
/**
@@ -416,6 +450,7 @@ trait JavaToScala extends ConversionUtil { self: SymbolTable =>
val field = sOwner(jfield).newValue(NoPosition, newTermName(jfield.getName))
.setFlag(toScalaFlags(jfield.getModifiers, isClass = false) | JAVA)
.setInfo(typeToScala(jfield.getGenericType))
+ fieldCache enter (jfield, field)
copyAnnotations(field, jfield)
field
}
@@ -434,6 +469,7 @@ trait JavaToScala extends ConversionUtil { self: SymbolTable =>
val clazz = sOwner(jmeth)
val meth = clazz.newMethod(NoPosition, newTermName(jmeth.getName))
.setFlag(toScalaFlags(jmeth.getModifiers, isClass = false) | JAVA)
+ methodCache enter (jmeth, meth)
val tparams = jmeth.getTypeParameters.toList map createTypeParameter
val paramtpes = jmeth.getGenericParameterTypes.toList map typeToScala
val resulttpe = typeToScala(jmeth.getGenericReturnType)
@@ -451,14 +487,15 @@ trait JavaToScala extends ConversionUtil { self: SymbolTable =>
private def jconstrAsScala(jconstr: jConstructor[_]): Symbol = {
// [Martin] Note: I know there's a lot of duplication wrt jmethodAsScala, but don't think it's worth it to factor this out.
val clazz = sOwner(jconstr)
- val meth = clazz.newMethod(NoPosition, nme.CONSTRUCTOR)
+ val constr = clazz.newMethod(NoPosition, nme.CONSTRUCTOR)
.setFlag(toScalaFlags(jconstr.getModifiers, isClass = false) | JAVA)
+ constructorCache enter (jconstr, constr)
val tparams = jconstr.getTypeParameters.toList map createTypeParameter
val paramtpes = jconstr.getGenericParameterTypes.toList map typeToScala
- setMethType(meth, tparams, paramtpes, clazz.tpe)
- meth setInfo polyType(tparams, MethodType(clazz.newSyntheticValueParams(paramtpes), clazz.tpe))
- copyAnnotations(meth, jconstr)
- meth
+ setMethType(constr, tparams, paramtpes, clazz.tpe)
+ constr setInfo polyType(tparams, MethodType(clazz.newSyntheticValueParams(paramtpes), clazz.tpe))
+ copyAnnotations(constr, jconstr)
+ constr
}
}
diff --git a/src/compiler/scala/reflect/runtime/Loaders.scala b/src/compiler/scala/reflect/runtime/Loaders.scala
index 070221fc00..3a1fcbda5f 100644
--- a/src/compiler/scala/reflect/runtime/Loaders.scala
+++ b/src/compiler/scala/reflect/runtime/Loaders.scala
@@ -49,6 +49,7 @@ trait Loaders { self: SymbolTable =>
// You'll see an error that class `parallel` has the wrong name.
// }
}
+ override def load(sym: Symbol) = complete(sym)
}
/** Create a class and a companion object, enter in enclosing scope,