diff options
4 files changed, 62 insertions, 4 deletions
diff --git a/src/compiler/scala/tools/nsc/interactive/CompilerControl.scala b/src/compiler/scala/tools/nsc/interactive/CompilerControl.scala index 16a7b2377a..f993d7c168 100644 --- a/src/compiler/scala/tools/nsc/interactive/CompilerControl.scala +++ b/src/compiler/scala/tools/nsc/interactive/CompilerControl.scala @@ -48,6 +48,11 @@ trait CompilerControl { self: Global => override def toString = "dofirst "+source } + class AskLinkPosItem(sym: Symbol, val source: SourceFile, response: Response[Position]) extends WorkItem { + def apply() = self.getLinkPos(sym, source, response) + override def toString = "linkpos "+sym+" in "+source + } + /** Info given for every member found by completion */ abstract class Member { @@ -145,6 +150,18 @@ trait CompilerControl { self: Global => def askType(source: SourceFile, forceReload: Boolean, response: Response[Tree]) = scheduler postWorkItem new AskTypeItem(source, forceReload, response) + /** Set sync var `response` to the position of the definition of the given link in + * the given sourcefile. + * + * @param sym The symbol referenced by the link (might come from a classfile) + * @param source The source file that's supposed to contain the definition + * @param response A response that will be set to the following: + * If `source` contains a definition that is referenced by the given link + * the position of that definition, otherwise NoPosition. + */ + def askLinkPos(sym: Symbol, source: SourceFile, response: Response[Position]) = + scheduler postWorkItem new AskLinkPosItem(sym, source, response) + /** Set sync var `response` to the last fully attributed & typechecked tree produced from `source`. * If no such tree exists yet, do a normal askType(source, false, response) */ @@ -181,8 +198,13 @@ trait CompilerControl { self: Global => // ---------------- Interpreted exceptions ------------------- -/** It has to stay top-level so that the PresentationCompilerThread may access it. */ +/** Signals a request for a fresh background compiler run. + * Note: The object has to stay top-level so that the PresentationCompilerThread may access it. + */ object FreshRunReq extends ControlThrowable -/** It has to stay top-level so that the PresentationCompilerThread may access it. */ +/** Signals a request for a shutdown of the presentation compiler. + * Note: The object has to stay top-level so that the PresentationCompilerThread may access it. + */ object ShutdownReq extends ControlThrowable + diff --git a/src/compiler/scala/tools/nsc/interactive/Global.scala b/src/compiler/scala/tools/nsc/interactive/Global.scala index 0787142c9a..6efe96861e 100644 --- a/src/compiler/scala/tools/nsc/interactive/Global.scala +++ b/src/compiler/scala/tools/nsc/interactive/Global.scala @@ -170,6 +170,7 @@ self => var moreWorkAtNode: Int = -1 var nodesSeen = 0 + var noWorkFoundAtNode: Int = -1 /** Called from runner thread and signalDone: * Poll for interrupts and execute them immediately. @@ -226,7 +227,10 @@ self => debugLog("quitting work item: "+action) } case None => - debugLog("no work found") + if (nodesSeen > noWorkFoundAtNode) { + debugLog("no work found") + noWorkFoundAtNode = nodesSeen + } } } } @@ -480,6 +484,32 @@ self => } } + def getLinkPos(sym: Symbol, source: SourceFile, response: Response[Position]) { + informIDE("getLinkPos "+sym+" "+source) + respond(response) { + reloadSources(List(source)) + val owner = sym.owner + if (owner.isClass) { + val pre = adaptToNewRunMap(ThisType(owner)) + val newsym = pre.decl(sym.name) filter { alt => + sym.isType || matchesType(pre.memberType(alt), pre.memberType(sym), false) + } + if (newsym == NoSymbol) { + debugLog("link not found "+sym+" "+source+" "+pre) + NoPosition + } else if (newsym.isOverloaded) { + debugLog("link ambiguous "+sym+" "+source+" "+pre+" "+newsym.alternatives) + NoPosition + } else { + debugLog("link found for "+newsym+": "+newsym.pos) + newsym.pos + } + } else + debugLog("link not in class "+sym+" "+source+" "+owner) + NoPosition + } + } + def stabilizedType(tree: Tree): Type = tree match { case Ident(_) if tree.symbol.isStable => singleType(NoPrefix, tree.symbol) diff --git a/src/compiler/scala/tools/nsc/interactive/Picklers.scala b/src/compiler/scala/tools/nsc/interactive/Picklers.scala index ee816e8f8b..e9f9a98eff 100644 --- a/src/compiler/scala/tools/nsc/interactive/Picklers.scala +++ b/src/compiler/scala/tools/nsc/interactive/Picklers.scala @@ -109,6 +109,12 @@ trait Picklers { self: Global => .wrapped { new AskToDoFirstItem(_) } { _.source } .asClass (classOf[AskToDoFirstItem]) + /** We cannot pickle symbols, so we return always RootClass */ + implicit def askLinkPosItem: CondPickler[AskLinkPosItem] = + pkl[SourceFile] + .wrapped { new AskLinkPosItem(definitions.RootClass, _, new Response) } { _.source } + .asClass (classOf[AskLinkPosItem]) + implicit def emptyAction: CondPickler[EmptyAction] = pkl[Unit] .wrapped { _ => new EmptyAction } { _ => () } diff --git a/src/compiler/scala/tools/nsc/typechecker/Implicits.scala b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala index 2035c5e3bd..5e0f5779fe 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Implicits.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala @@ -959,7 +959,7 @@ trait Implicits { def allImplicits: List[SearchResult] = { def search(iss: Infoss, isLocal: Boolean) = applicableInfos(iss, isLocal).values - search(context.implicitss, true) ++ search(implicitsOfExpectedType, false) toList + (search(context.implicitss, true) ++ search(implicitsOfExpectedType, false)).toList.filter(_.tree ne EmptyTree) } } |