aboutsummaryrefslogtreecommitdiff
path: root/src/dotty/tools
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2013-02-03 14:41:31 +0100
committerMartin Odersky <odersky@gmail.com>2013-02-03 14:41:31 +0100
commit7209deef4f254dc1a2e8d7a0429771df9d58e308 (patch)
tree01e6128ddba82657af093e496230d5107e26b68b /src/dotty/tools
parent900dca87c35d74a893ab93ff2d73a72bd7fdbb78 (diff)
downloaddotty-7209deef4f254dc1a2e8d7a0429771df9d58e308.tar.gz
dotty-7209deef4f254dc1a2e8d7a0429771df9d58e308.tar.bz2
dotty-7209deef4f254dc1a2e8d7a0429771df9d58e308.zip
Refined completion protocol to account for missing toplevel symbols.
Diffstat (limited to 'src/dotty/tools')
-rw-r--r--src/dotty/tools/dotc/core/Contexts.scala2
-rw-r--r--src/dotty/tools/dotc/core/SymDenotations.scala31
-rw-r--r--src/dotty/tools/dotc/core/SymbolLoaders.scala67
3 files changed, 44 insertions, 56 deletions
diff --git a/src/dotty/tools/dotc/core/Contexts.scala b/src/dotty/tools/dotc/core/Contexts.scala
index 8edbec847..6a674dba8 100644
--- a/src/dotty/tools/dotc/core/Contexts.scala
+++ b/src/dotty/tools/dotc/core/Contexts.scala
@@ -64,8 +64,10 @@ object Contexts {
def enclClass: Context = ???
def erasedTypes: Boolean = ???
def debug: Boolean = ???
+ def error(msg: String) = ???
def warning(msg: String) = ???
def inform(msg: String) = ???
+ def informTime(msg: String, start: Long): Unit = ???
def fresh: FreshContext = {
val newctx = super.clone.asInstanceOf[FreshContext]
diff --git a/src/dotty/tools/dotc/core/SymDenotations.scala b/src/dotty/tools/dotc/core/SymDenotations.scala
index b8fc49a45..f103e14d4 100644
--- a/src/dotty/tools/dotc/core/SymDenotations.scala
+++ b/src/dotty/tools/dotc/core/SymDenotations.scala
@@ -27,9 +27,10 @@ object SymDenotations {
def info: Type
- // The following 4 members are overridden is instances of isLazy
+ // The following 5 members are overridden by instances of isLazy
def isLoaded = true
def isCompleted = true
+ def exists(implicit ctx: Context) = true
protected[core] def tryLoad(): Unit = unsupported("tryLoad")
protected[core] def tryComplete(): Unit = unsupported("tryComplete")
@@ -622,6 +623,9 @@ object SymDenotations {
var completer: SymCompleter
) extends SymDenotation(initFlags) with isLazy[LazySymDenotation] {
+ final override def exists(implicit ctx: Context) =
+ !isModuleVal || moduleClass.denot.exists
+
private[this] var _info: Type = _
protected[core] def info_=(tp: Type) = if (_info == null) _info = tp
override def info = { if (info == null) tryComplete(); _info }
@@ -663,6 +667,8 @@ object SymDenotations {
def selfType: Type = { if (_selfType == null) tryComplete(); _selfType }
final def decls: Scope = { if (_decls == null) tryComplete(); _decls }
final def preCompleteDecls = { if (_decls == null) tryLoad(); _decls }
+
+ final override def exists(implicit ctx: Context) = { ensureCompleted(); _parents != null }
}
object NoDenotation extends SymDenotation(EmptyFlags) {
@@ -692,12 +698,19 @@ object SymDenotations {
flags &~= Locked
}
- override protected[core] def tryComplete(): Unit = {
- val c = completer
- completer = null
- if (c == null) throw new CyclicReference(symbol)
- c.complete(this)
- }
+ override protected[core] def tryComplete(): Unit =
+ try {
+ if (flags is Locked) throw new CyclicReference(symbol)
+ setFlags(Locked)
+ val c = completer
+ completer = null // set completer to null to avoid space leaks
+ // and to make any subsequent completion attempt a CompletionError
+ c.complete(this)
+ } catch {
+ case _: NullPointerException => throw new CompletionError(this)
+ } finally {
+ flags &~= Locked
+ }
private[this] var _privateWithin: Symbol = _
def privateWithin: Symbol = { if (_privateWithin == null) tryLoad(); _privateWithin }
@@ -718,7 +731,7 @@ object SymDenotations {
type ClassCompleter = Completer[LazyClassDenotation]
class ModuleCompleter(cctx: CondensedContext) extends Completer[LazySymDenotation] {
- implicit val ctx: Context = cctx
+ implicit def ctx: Context = cctx
def classDenot(denot: LazySymDenotation) =
denot.moduleClass.denot.asInstanceOf[LazyClassDenotation]
def copyLoadedFields(denot: LazySymDenotation, from: LazyClassDenotation) = {
@@ -735,6 +748,8 @@ object SymDenotations {
copyCompletedFields(denot, classDenot(denot))
}
+ class CompletionError(denot: SymDenotation) extends Error("Trying to access missing symbol ${denot.symbol.fullName}")
+
// ---- Name filter --------------------------------------------------------
object NameFilter {
diff --git a/src/dotty/tools/dotc/core/SymbolLoaders.scala b/src/dotty/tools/dotc/core/SymbolLoaders.scala
index 6aa959887..671c4ea65 100644
--- a/src/dotty/tools/dotc/core/SymbolLoaders.scala
+++ b/src/dotty/tools/dotc/core/SymbolLoaders.scala
@@ -14,9 +14,8 @@ import Contexts._, Symbols._, Flags._, SymDenotations._, Types._
import Decorators.StringDecorator
//import classfile.ClassfileParser
-abstract class SymbolLoader extends ClassCompleter
-
+/** A base class for Symbol loaders with some overridable behavior */
class SymbolLoaders {
protected def enterIfNew(owner: Symbol, member: Symbol, completer: SymbolLoader)(implicit ctx: Context): Symbol = {
@@ -28,14 +27,14 @@ class SymbolLoaders {
/** Enter class with given `name` into scope of `owner`.
*/
def enterClass(owner: Symbol, name: String, completer: SymbolLoader)(implicit ctx: Context): Symbol = {
- val cls = ctx.newLazyClassSymbol(owner, name.toTypeName, EmptyFlags, completer)
+ val cls = ctx.newLazyClassSymbol(owner, name.toTypeName, EmptyFlags, completer, assocFile = completer.sourceFileOrNull)
enterIfNew(owner, cls, completer)
}
/** Enter module with given `name` into scope of `owner`.
*/
def enterModule(owner: Symbol, name: String, completer: SymbolLoader)(implicit ctx: Context): Symbol = {
- val module = ctx.newLazyModuleSymbol(owner, name.toTermName, EmptyFlags, completer)
+ val module = ctx.newLazyModuleSymbol(owner, name.toTermName, EmptyFlags, completer, assocFile = completer.sourceFileOrNull)
enterIfNew(owner, module, completer)
}
@@ -119,20 +118,20 @@ class SymbolLoaders {
def needCompile(bin: AbstractFile, src: AbstractFile) =
src.lastModified >= bin.lastModified
-}/*
+}
/**
* 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 ClassCompleter {
+ abstract class SymbolLoader(cctx: CondensedContext) extends ClassCompleter {
+ implicit def ctx: Context = cctx
/** Load source or class file for `root`, return */
- protected def doComplete(root: Symbol): Unit
-
- def sourcefile: Option[AbstractFile] = None
+ protected def doComplete(root: LazyClassDenotation): Unit
+ def sourceFileOrNull: AbstractFile = null
/**
* Description of the resource (ClassPath, AbstractFile, MsilFile)
* being processed by this loader
@@ -141,62 +140,34 @@ class SymbolLoaders {
private var ok = false
- private def setSource(sym: Symbol) {
- sourcefile foreach (sf => sym match {
- case cls: ClassSymbol => cls.sourceFile = sf
- case mod: ModuleSymbol => mod.moduleClass.sourceFile = sf
- case _ => ()
- })
- }
-
- override def complete(root: Symbol) {
+ override def complete(root: LazyClassDenotation) {
def signalError(ex: Exception) {
ok = false
- if (settings.debug.value) ex.printStackTrace()
+ if (ctx.settings.debug.value) ex.printStackTrace()
val msg = ex.getMessage()
- // SI-5593 Scaladoc's current strategy is to visit all packages in search of user code that can be documented
- // therefore, it will rummage through the classpath triggering errors whenever it encounters package objects
- // that are not in their correct place (see bug for details)
- if (!settings.isScaladoc)
- globalError(
- if (msg eq null) "i/o error while loading " + root.name
- else "error while loading " + root.name + ", " + msg);
+ ctx.error(
+ if (msg eq null) "i/o error while loading " + root.name
+ else "error while loading " + root.name + ", " + msg);
}
try {
val start = currentTime
- val currentphase = phase
doComplete(root)
- phase = currentphase
- informTime("loaded " + description, start)
+ ctx.informTime("loaded " + description, start)
ok = true
- setSource(root)
- setSource(root.companionSymbol) // module -> class, class -> module
} catch {
case ex: IOException =>
signalError(ex)
case ex: MissingRequirementError =>
signalError(ex)
}
- initRoot(root)
- if (!root.isPackageClass) initRoot(root.companionSymbol)
- }
-
- override def load(root: Symbol) { complete(root) }
-
- private def markAbsent(sym: Symbol): Unit = {
- val tpe: Type = if (ok) NoType else ErrorType
-
- if (sym != NoSymbol)
- sym setInfo tpe
- }
- private def initRoot(root: Symbol) {
- if (root.rawInfo == this)
- List(root, root.moduleClass) foreach markAbsent
- else if (root.isClass && !root.isModuleClass)
- root.rawInfo.load(root)
+ root.linkedClass.denot match {
+ case companion: LazyClassDenotation => companion.completer = null
+ }
}
}
+ /*
+
/**
* Load contents of a package
*/