summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2011-09-05 10:44:04 +0000
committerMartin Odersky <odersky@gmail.com>2011-09-05 10:44:04 +0000
commit0d99f59ebaa42eb8717b01de06e8582371b6ccbf (patch)
treec5d7574aeda099ac7826bd4a7e49024bc1966707 /src
parent0d379b728ae11dcc2f15d1e3e3143cb650acf0c3 (diff)
downloadscala-0d99f59ebaa42eb8717b01de06e8582371b6ccbf.tar.gz
scala-0d99f59ebaa42eb8717b01de06e8582371b6ccbf.tar.bz2
scala-0d99f59ebaa42eb8717b01de06e8582371b6ccbf.zip
More refinements to reflection and the reflecti...
More refinements to reflection and the reflective compiler.
Diffstat (limited to 'src')
-rw-r--r--src/compiler/scala/reflect/internal/Definitions.scala2
-rw-r--r--src/compiler/scala/reflect/internal/MissingRequirementError.scala12
-rw-r--r--src/compiler/scala/reflect/internal/SymbolTable.scala27
-rw-r--r--src/compiler/scala/reflect/internal/Symbols.scala2
-rw-r--r--src/compiler/scala/reflect/internal/Types.scala2
-rw-r--r--src/compiler/scala/reflect/internal/pickling/UnPickler.scala12
-rw-r--r--src/compiler/scala/reflect/runtime/JavaToScala.scala22
-rw-r--r--src/compiler/scala/reflect/runtime/Loaders.scala12
-rw-r--r--src/compiler/scala/reflect/runtime/SymbolTable.scala4
-rw-r--r--src/compiler/scala/tools/nsc/symtab/SymbolLoaders.scala5
-rw-r--r--src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala23
-rw-r--r--src/compiler/scala/tools/nsc/symtab/classfile/ICodeReader.scala2
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Namers.scala2
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Typers.scala3
14 files changed, 76 insertions, 54 deletions
diff --git a/src/compiler/scala/reflect/internal/Definitions.scala b/src/compiler/scala/reflect/internal/Definitions.scala
index f677b10c32..2bffca6335 100644
--- a/src/compiler/scala/reflect/internal/Definitions.scala
+++ b/src/compiler/scala/reflect/internal/Definitions.scala
@@ -670,7 +670,7 @@ trait Definitions extends reflect.api.StandardDefinitions {
else {
if (settings.debug.value) { log(sym.info); log(sym.info.members) }//debug
missingHook(owner, name) orElse {
- throw new MissingRequirementError((if (path.isTermName) "object " else "class ")+path)
+ MissingRequirementError.notFound((if (path.isTermName) "object " else "class ")+path)
}
}
}
diff --git a/src/compiler/scala/reflect/internal/MissingRequirementError.scala b/src/compiler/scala/reflect/internal/MissingRequirementError.scala
index 37e46bcac0..f6be9fa8c6 100644
--- a/src/compiler/scala/reflect/internal/MissingRequirementError.scala
+++ b/src/compiler/scala/reflect/internal/MissingRequirementError.scala
@@ -6,12 +6,18 @@
package scala.reflect
package internal
-class MissingRequirementError(val req: String) extends FatalError(req + " not found.")
+class MissingRequirementError private (msg: String) extends FatalError(msg) {
+ import MissingRequirementError.suffix
+ def req: String = if (msg endsWith suffix) msg dropRight suffix.length else msg
+}
object MissingRequirementError {
+ private val suffix = " not found."
+ def signal(msg: String): Nothing = throw new MissingRequirementError(msg)
+ def notFound(req: String): Nothing = signal(req + suffix)
def unapply(x: Throwable) = x match {
- case x: MissingRequirementError => Some(x.req)
- case _ => None
+ case x: MissingRequirementError => x.req
+ case _ => None
}
}
diff --git a/src/compiler/scala/reflect/internal/SymbolTable.scala b/src/compiler/scala/reflect/internal/SymbolTable.scala
index 3ab2408cf7..65c2dc4d46 100644
--- a/src/compiler/scala/reflect/internal/SymbolTable.scala
+++ b/src/compiler/scala/reflect/internal/SymbolTable.scala
@@ -147,12 +147,37 @@ abstract class SymbolTable extends api.Universe
}
}
+ /** Convert array parameters denoting a repeated parameter of a Java method
+ * to `JavaRepeatedParamClass` types.
+ */
+ def arrayToRepeated(tp: Type): Type = tp match {
+ case MethodType(params, rtpe) =>
+ val formals = tp.paramTypes
+ assert(formals.last.typeSymbol == definitions.ArrayClass)
+ val method = params.last.owner
+ val elemtp = formals.last.typeArgs.head match {
+ case RefinedType(List(t1, t2), _) if (t1.typeSymbol.isAbstractType && t2.typeSymbol == definitions.ObjectClass) =>
+ t1 // drop intersection with Object for abstract types in varargs. UnCurry can handle them.
+ case t =>
+ t
+ }
+ val newParams = method.newSyntheticValueParams(
+ formals.init :+ appliedType(definitions.JavaRepeatedParamClass.typeConstructor, List(elemtp)))
+ MethodType(newParams, rtpe)
+ case PolyType(tparams, rtpe) =>
+ PolyType(tparams, arrayToRepeated(rtpe))
+ }
+
+ abstract class SymLoader extends LazyType {
+ def fromSource = false
+ }
+
/** if there's a `package` member object in `pkgClass`, enter its members into it. */
def openPackageModule(pkgClass: Symbol) {
val pkgModule = pkgClass.info.decl(nme.PACKAGEkw)
def fromSource = pkgModule.rawInfo match {
- case ltp: LazyType => ltp.fromSource
+ case ltp: SymLoader => ltp.fromSource
case _ => false
}
if (pkgModule.isModule && !fromSource) {
diff --git a/src/compiler/scala/reflect/internal/Symbols.scala b/src/compiler/scala/reflect/internal/Symbols.scala
index 03ae81adee..2a38e6ee9b 100644
--- a/src/compiler/scala/reflect/internal/Symbols.scala
+++ b/src/compiler/scala/reflect/internal/Symbols.scala
@@ -1817,7 +1817,7 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
*/
override def toString = compose(
kindString,
- if (hasMeaninglessName) owner.nameString else nameString
+ if (hasMeaninglessName) owner.decodedName + idString else nameString
)
/** String representation of location.
diff --git a/src/compiler/scala/reflect/internal/Types.scala b/src/compiler/scala/reflect/internal/Types.scala
index ded4627e97..dab6839353 100644
--- a/src/compiler/scala/reflect/internal/Types.scala
+++ b/src/compiler/scala/reflect/internal/Types.scala
@@ -1146,6 +1146,7 @@ trait Types extends api.Types { self: SymbolTable =>
/** A class for this-types of the form <sym>.this.type
*/
abstract case class ThisType(sym: Symbol) extends SingletonType {
+ assert(sym.isClass)
//assert(sym.isClass && !sym.isModuleClass || sym.isRoot, sym)
override def isTrivial: Boolean = sym.isPackageClass
override def isNotNull = true
@@ -2759,7 +2760,6 @@ A type's typeSymbol should never be inspected directly.
/** A class representing an as-yet unevaluated type.
*/
abstract class LazyType extends Type {
- def fromSource = false
override def isComplete: Boolean = false
override def complete(sym: Symbol)
override def safeToString = "<?>"
diff --git a/src/compiler/scala/reflect/internal/pickling/UnPickler.scala b/src/compiler/scala/reflect/internal/pickling/UnPickler.scala
index 335533f1ca..70a8d734b7 100644
--- a/src/compiler/scala/reflect/internal/pickling/UnPickler.scala
+++ b/src/compiler/scala/reflect/internal/pickling/UnPickler.scala
@@ -195,12 +195,12 @@ abstract class UnPickler /*extends reflect.generic.UnPickler*/ {
val name = readNameRef()
val owner = if (atEnd) definitions.RootClass else readSymbolRef()
+ def adjust(sym: Symbol) = if (tag == EXTref) sym else sym.moduleClass
+
def fromName(name: Name) = name.toTermName match {
case nme.ROOT => definitions.RootClass
case nme.ROOTPKG => definitions.RootPackage
- case _ =>
- val s = owner.info.decl(name)
- if (tag == EXTref) s else s.moduleClass
+ case _ => adjust(owner.info.decl(name))
}
def nestedObjectSymbol: Symbol = {
// If the owner is overloaded (i.e. a method), it's not possible to select the
@@ -227,7 +227,7 @@ abstract class UnPickler /*extends reflect.generic.UnPickler*/ {
// (3) Try as a nested object symbol.
nestedObjectSymbol orElse {
// (4) Otherwise, fail.
- errorMissingRequirement(name, owner)
+ adjust(errorMissingRequirement(name, owner))
}
}
}
@@ -819,9 +819,9 @@ abstract class UnPickler /*extends reflect.generic.UnPickler*/ {
protected def errorMissingRequirement(name: Name, owner: Symbol): Symbol =
missingHook(owner, name) orElse {
- throw new MissingRequirementError(
+ MissingRequirementError.notFound(
"reference " + (if (name.isTypeName) "type " else "value ") +
- name.decode + " of " + owner.tpe.widen)
+ name.decode + " of " + owner.tpe.widen + "/" +owner.tpe.typeSymbol.ownerChain)
}
def inferMethodAlternative(fun: Tree, argtpes: List[Type], restpe: Type) {} // can't do it; need a compiler for that.
diff --git a/src/compiler/scala/reflect/runtime/JavaToScala.scala b/src/compiler/scala/reflect/runtime/JavaToScala.scala
index 161e694cfd..81063a63b3 100644
--- a/src/compiler/scala/reflect/runtime/JavaToScala.scala
+++ b/src/compiler/scala/reflect/runtime/JavaToScala.scala
@@ -47,9 +47,9 @@ trait JavaToScala extends ConversionUtil { self: SymbolTable =>
markAbsent(ErrorType)
if (settings.debug.value) ex.printStackTrace()
val msg = ex.getMessage()
- throw new MissingRequirementError(
- if (msg eq null) "reflection error while loading " + clazz.name
- else "error while loading " + clazz.name + ", " + msg)
+ MissingRequirementError.signal(
+ (if (msg eq null) "reflection error while loading " + clazz.name
+ else "error while loading " + clazz.name) + ", " + msg)
}
try {
info("unpickling " + clazz + " " + module) //debug
@@ -145,6 +145,7 @@ trait JavaToScala extends ConversionUtil { self: SymbolTable =>
module.moduleClass setInfo new LazyPolyType(List())
}
}
+
override def complete(sym: Symbol): Unit = {
load(sym)
completeRest()
@@ -168,14 +169,12 @@ trait JavaToScala extends ConversionUtil { self: SymbolTable =>
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 (jinner <- jclazz.getDeclaredClasses) {
- println("... entering "+jinner)
- enter(jclassAsScala(jinner, clazz), jinner.getModifiers)
- }
+ pendingLoadActions = { () =>
for (jfield <- jclazz.getDeclaredFields)
enter(jfieldAsScala(jfield), jfield.getModifiers)
@@ -475,6 +474,9 @@ trait JavaToScala extends ConversionUtil { self: SymbolTable =>
val resulttpe = typeToScala(jmeth.getGenericReturnType)
setMethType(meth, tparams, paramtpes, resulttpe)
copyAnnotations(meth, jmeth)
+ if ((jmeth.getModifiers & JAVA_ACC_VARARGS) != 0) {
+ meth.setInfo(arrayToRepeated(meth.info))
+ }
meth
}
diff --git a/src/compiler/scala/reflect/runtime/Loaders.scala b/src/compiler/scala/reflect/runtime/Loaders.scala
index 3a1fcbda5f..3a6700a105 100644
--- a/src/compiler/scala/reflect/runtime/Loaders.scala
+++ b/src/compiler/scala/reflect/runtime/Loaders.scala
@@ -20,7 +20,7 @@ trait Loaders { self: SymbolTable =>
* by unpickling information from the corresponding Java class. If no Java class
* is found, a package is created instead.
*/
- class TopClassCompleter(clazz: Symbol, module: Symbol) extends LazyType {
+ class TopClassCompleter(clazz: Symbol, module: Symbol) extends SymLoader {
// def makePackage() {
// println("wrong guess; making package "+clazz)
// val ptpe = newPackageType(module.moduleClass)
@@ -85,18 +85,24 @@ trait Loaders { self: SymbolTable =>
}
}
+ def invalidClassName(name: Name) = {
+ val dp = name pos '$'
+ 0 < dp && dp < (name.length - 1)
+ }
+
class PackageScope(pkgClass: Symbol) extends Scope {
+ assert(pkgClass.isType)
private var negatives = mutable.Set[Name]()
override def lookupEntry(name: Name): ScopeEntry = {
val e = super.lookupEntry(name)
if (e != null)
e
- else if (negatives contains name)
+ else if (invalidClassName(name) || (negatives contains name))
null
else try {
jClass.forName(pkgClass.fullName + "." + name)
val (clazz, module) = createClassModule(pkgClass, name.toTypeName, new TopClassCompleter(_, _))
- info("created "+module+"/"+module.moduleClass+" in "+pkgClass+", scope = "+(this map (_.name)))
+ info("created "+module+"/"+module.moduleClass+" in "+pkgClass)
lookupEntry(name)
} catch {
case (_: ClassNotFoundException) | (_: NoClassDefFoundError) =>
diff --git a/src/compiler/scala/reflect/runtime/SymbolTable.scala b/src/compiler/scala/reflect/runtime/SymbolTable.scala
index 419fed14bb..62784d8973 100644
--- a/src/compiler/scala/reflect/runtime/SymbolTable.scala
+++ b/src/compiler/scala/reflect/runtime/SymbolTable.scala
@@ -24,8 +24,6 @@ trait SymbolTable extends internal.SymbolTable with JavaToScala with ScalaToJava
assert(!tp.typeSymbol.isPackageClass || tp.decls.isInstanceOf[PackageScope])
}
- protected var verbose = false
-
def info(msg: => String) =
- if (verbose) println("[reflect-compiler] "+msg)
+ if (settings.verbose.value) println("[reflect-compiler] "+msg)
}
diff --git a/src/compiler/scala/tools/nsc/symtab/SymbolLoaders.scala b/src/compiler/scala/tools/nsc/symtab/SymbolLoaders.scala
index 45114a1dc0..2212a42c78 100644
--- a/src/compiler/scala/tools/nsc/symtab/SymbolLoaders.scala
+++ b/src/compiler/scala/tools/nsc/symtab/SymbolLoaders.scala
@@ -82,8 +82,10 @@ abstract class SymbolLoaders {
/**
* A lazy type that completes itself by calling parameter doComplete.
* Any linked modules/classes or module classes are also initialized.
+ * Todo: consider factoring out behavior from TopClassCompleter/SymbolLoader into
+ * supertrait SymLoader
*/
- abstract class SymbolLoader extends LazyType {
+ abstract class SymbolLoader extends SymLoader {
/** Load source or class file for `root`, return */
protected def doComplete(root: Symbol): Unit
@@ -105,6 +107,7 @@ abstract class SymbolLoaders {
case _ => ()
})
}
+
override def complete(root: Symbol) : Unit = {
def signalError(ex: Exception) {
ok = false
diff --git a/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala b/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala
index 47fadd9fd5..d9eaad55a0 100644
--- a/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala
+++ b/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala
@@ -437,7 +437,7 @@ abstract class ClassfileParser {
def loadClassSymbol(name: Name) = {
val s = name.toString
val file = global.classPath findSourceFile s getOrElse {
- throw new MissingRequirementError("class " + s)
+ MissingRequirementError.notFound("class " + s)
}
val completer = new global.loaders.ClassfileLoader(file)
var owner: Symbol = definitions.RootClass
@@ -673,27 +673,6 @@ abstract class ClassfileParser {
}
}
- /** Convert array parameters denoting a repeated parameter of a Java method
- * to `JavaRepeatedParamClass` types.
- */
- private def arrayToRepeated(tp: Type): Type = tp match {
- case MethodType(params, rtpe) =>
- val formals = tp.paramTypes
- assert(formals.last.typeSymbol == definitions.ArrayClass)
- val method = params.last.owner
- val elemtp = formals.last.typeArgs.head match {
- case RefinedType(List(t1, t2), _) if (t1.typeSymbol.isAbstractType && t2.typeSymbol == definitions.ObjectClass) =>
- t1 // drop intersection with Object for abstract types in varargs. UnCurry can handle them.
- case t =>
- t
- }
- val newParams = method.newSyntheticValueParams(
- formals.init :+ appliedType(definitions.JavaRepeatedParamClass.typeConstructor, List(elemtp)))
- MethodType(newParams, rtpe)
- case PolyType(tparams, rtpe) =>
- PolyType(tparams, arrayToRepeated(rtpe))
- }
-
private def sigToType(sym: Symbol, sig: Name): Type = {
var index = 0
val end = sig.length
diff --git a/src/compiler/scala/tools/nsc/symtab/classfile/ICodeReader.scala b/src/compiler/scala/tools/nsc/symtab/classfile/ICodeReader.scala
index cbc394f94c..930459e7cd 100644
--- a/src/compiler/scala/tools/nsc/symtab/classfile/ICodeReader.scala
+++ b/src/compiler/scala/tools/nsc/symtab/classfile/ICodeReader.scala
@@ -45,7 +45,7 @@ abstract class ICodeReader extends ClassfileParser {
classPath.findSourceFile(name) match {
case Some(classFile) => parse(classFile, cls)
- case _ => throw new MissingRequirementError("Could not find bytecode for " + cls)
+ case _ => MissingRequirementError.notFound("Could not find bytecode for " + cls)
}
(staticCode, instanceCode)
diff --git a/src/compiler/scala/tools/nsc/typechecker/Namers.scala b/src/compiler/scala/tools/nsc/typechecker/Namers.scala
index 9adb7dce20..56651f9af9 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Namers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Namers.scala
@@ -92,7 +92,7 @@ trait Namers { self: Analyzer =>
updatePosFlags(sym.moduleClass, pos, moduleClassFlags(flags))
var companion: Symbol = NoSymbol
if (sym.owner.isPackageClass && {companion = companionSymbolOf(sym, context); companion != NoSymbol} &&
- (companion.rawInfo.isInstanceOf[loaders.SymbolLoader] ||
+ (companion.rawInfo.isInstanceOf[SymLoader] ||
companion.rawInfo.isComplete && runId(sym.validTo) != currentRunId))
// pre-set linked symbol to NoType, in case it is not loaded together with this symbol.
companion.setInfo(NoType)
diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
index 3b6b44316b..eb5a575596 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
@@ -3880,6 +3880,9 @@ trait Typers extends Modes with Adaptations {
else if (settings.exposeEmptyPackage.value && checkEmptyPackage())
log("Allowing empty package member " + name + " due to settings.")
else {
+ val lastTry = missingHook(RootClass, name)
+ if (lastTry != NoSymbol) return typed1(tree setSymbol lastTry, mode, pt)
+
if (settings.debug.value) {
log(context.imports)//debug
}