More fixes to reflection and reflective compiler.

git-svn-id: http://lampsvn.epfl.ch/svn-repos/scala/scala/trunk@25589 5e8d7ff9-d8ef-0310-90f0-a4852d11357a
This commit is contained in:
odersky 2011-08-30 21:04:51 +00:00
parent a484db70b7
commit 5e323a8969
3 changed files with 63 additions and 24 deletions

View File

@ -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 =

View File

@ -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)
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))
if (module != NoSymbol) {
module.moduleClass setInfo new ClassInfoType(List(), newScope, module.moduleClass)
module setInfo module.moduleClass.tpe
}
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
}
}

View File

@ -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,