diff options
7 files changed, 63 insertions, 10 deletions
diff --git a/src/compiler/scala/tools/nsc/Global.scala b/src/compiler/scala/tools/nsc/Global.scala index ea6543bb71..ee03aa1ac2 100644 --- a/src/compiler/scala/tools/nsc/Global.scala +++ b/src/compiler/scala/tools/nsc/Global.scala @@ -356,6 +356,15 @@ class Global(var currentSettings: Settings, var reporter: Reporter) lazy val loaders = new SymbolLoaders { val global: Global.this.type = Global.this + def lookupMemberAtTyperPhaseIfPossible(sym: Symbol, name: Name): Symbol = { + def lookup = sym.info.member(name) + // if loading during initialization of `definitions` typerPhase is not yet set. + // in that case we simply load the member at the current phase + if (currentRun.typerPhase eq null) + lookup + else + enteringTyper { lookup } + } } /** Returns the mirror that loaded given symbol */ diff --git a/src/compiler/scala/tools/nsc/backend/icode/ICodes.scala b/src/compiler/scala/tools/nsc/backend/icode/ICodes.scala index 3f2141782a..1fd24d4e1f 100644 --- a/src/compiler/scala/tools/nsc/backend/icode/ICodes.scala +++ b/src/compiler/scala/tools/nsc/backend/icode/ICodes.scala @@ -108,6 +108,16 @@ abstract class ICodes extends AnyRef object icodeReader extends ICodeReader { lazy val global: ICodes.this.global.type = ICodes.this.global + import global._ + def lookupMemberAtTyperPhaseIfPossible(sym: Symbol, name: Name): Symbol = { + def lookup = sym.info.member(name) + // if loading during initialization of `definitions` typerPhase is not yet set. + // in that case we simply load the member at the current phase + if (currentRun.typerPhase eq null) + lookup + else + enteringTyper { lookup } + } } /** A phase which works on icode. */ diff --git a/src/compiler/scala/tools/nsc/symtab/BrowsingLoaders.scala b/src/compiler/scala/tools/nsc/symtab/BrowsingLoaders.scala index 4e4efef607..f93be78a3f 100644 --- a/src/compiler/scala/tools/nsc/symtab/BrowsingLoaders.scala +++ b/src/compiler/scala/tools/nsc/symtab/BrowsingLoaders.scala @@ -17,6 +17,20 @@ abstract class BrowsingLoaders extends SymbolLoaders { import syntaxAnalyzer.{OutlineParser, MalformedInput} + /* + * BrowsingLoaders has dependency on Global so we can implement this method here instead of forcing subclasses + * of BrowsingLoaders (e.g. in interactive) to implement it. + */ + override def lookupMemberAtTyperPhaseIfPossible(sym: Symbol, name: Name): Symbol = { + def lookup = sym.info.member(name) + // if loading during initialization of `definitions` typerPhase is not yet set. + // in that case we simply load the member at the current phase + if (currentRun.typerPhase eq null) + lookup + else + enteringTyper { lookup } + } + /** In browse mode, it can happen that an encountered symbol is already * present. For instance, if the source file has a name different from * the classes and objects it contains, the symbol loader will always diff --git a/src/compiler/scala/tools/nsc/symtab/SymbolLoaders.scala b/src/compiler/scala/tools/nsc/symtab/SymbolLoaders.scala index bd157ed691..ac38e24787 100644 --- a/src/compiler/scala/tools/nsc/symtab/SymbolLoaders.scala +++ b/src/compiler/scala/tools/nsc/symtab/SymbolLoaders.scala @@ -22,6 +22,11 @@ import scala.reflect.io.{ AbstractFile, NoAbstractFile } abstract class SymbolLoaders { val global: Global import global._ + + /** + * Required by ClassfileParser. Check documentation in that class for details. + */ + protected def lookupMemberAtTyperPhaseIfPossible(sym: Symbol, name: Name): Symbol import SymbolLoadersStats._ protected def enterIfNew(owner: Symbol, member: Symbol, completer: SymbolLoader): Symbol = { @@ -249,6 +254,8 @@ abstract class SymbolLoaders { } with ClassfileParser { override protected type ThisConstantPool = ConstantPool override protected def newConstantPool: ThisConstantPool = new ConstantPool + override protected def lookupMemberAtTyperPhaseIfPossible(sym: Symbol, name: Name): Symbol = + SymbolLoaders.this.lookupMemberAtTyperPhaseIfPossible(sym, name) } protected def description = "class file "+ classfile.toString diff --git a/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala b/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala index e8abeb7674..4743260c79 100644 --- a/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala +++ b/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala @@ -26,6 +26,17 @@ import scala.tools.nsc.io.AbstractFile abstract class ClassfileParser { val global: Global import global._ + + /** + * If typer phase is defined then perform member lookup of a symbol + * `sym` at typer phase. This method results from refactoring. The + * original author of the logic that uses typer phase didn't explain + * why we need to force infos at that phase specifically. It only mentioned + * that ClassfileParse can be called late (e.g. at flatten phase) and + * we make to make sure we handle such situation properly. + */ + protected def lookupMemberAtTyperPhaseIfPossible(sym: Symbol, name: Name): Symbol + import definitions._ import scala.reflect.internal.ClassfileConstants._ import Flags._ @@ -1093,19 +1104,15 @@ abstract class ClassfileParser { case Some(entry) => innerSymbol(entry) case _ => NoSymbol } - // if loading during initialization of `definitions` typerPhase is not yet set. - // in that case we simply load the member at the current phase - @inline private def enteringTyperIfPossible(body: => Symbol): Symbol = - if (currentRun.typerPhase eq null) body else enteringTyper(body) private def innerSymbol(entry: InnerClassEntry): Symbol = { val name = entry.originalName.toTypeName val enclosing = entry.enclosing def getMember = ( if (enclosing == clazz) entry.scope lookup name - else enclosing.info member name + else lookupMemberAtTyperPhaseIfPossible(enclosing, name) ) - enteringTyperIfPossible(getMember) + getMember /* There used to be an assertion that this result is not NoSymbol; changing it to an error * revealed it had been going off all the time, but has been swallowed by a catch t: Throwable * in Repository.scala. Since it has been accomplishing nothing except misleading anyone who diff --git a/src/scaladoc/scala/tools/nsc/doc/ScaladocGlobal.scala b/src/scaladoc/scala/tools/nsc/doc/ScaladocGlobal.scala index 20f24dc753..91d5fef4cf 100644 --- a/src/scaladoc/scala/tools/nsc/doc/ScaladocGlobal.scala +++ b/src/scaladoc/scala/tools/nsc/doc/ScaladocGlobal.scala @@ -32,6 +32,16 @@ trait ScaladocGlobalTrait extends Global { override protected def signalError(root: Symbol, ex: Throwable) { log(s"Suppressing error involving $root: $ex") } + + def lookupMemberAtTyperPhaseIfPossible(sym: Symbol, name: Name): Symbol = { + def lookup = sym.info.member(name) + // if loading during initialization of `definitions` typerPhase is not yet set. + // in that case we simply load the member at the current phase + if (currentRun.typerPhase eq null) + lookup + else + enteringTyper { lookup } + } } } diff --git a/test/files/presentation/doc/doc.scala b/test/files/presentation/doc/doc.scala index c884b6425b..f2233f1828 100755 --- a/test/files/presentation/doc/doc.scala +++ b/test/files/presentation/doc/doc.scala @@ -51,10 +51,6 @@ object Test extends InteractiveTest { new Typer(context) with InteractiveTyper with ScaladocTyper } - override lazy val loaders = new scala.tools.nsc.symtab.SymbolLoaders { - val global: outer.type = outer - } - def chooseLink(links: List[LinkTo]): LinkTo = links.head def internalLink(sym: Symbol, site: Symbol) = None def toString(link: LinkTo) = link.toString |