summaryrefslogtreecommitdiff
path: root/src/compiler/scala/tools/nsc/interactive/Global.scala
diff options
context:
space:
mode:
Diffstat (limited to 'src/compiler/scala/tools/nsc/interactive/Global.scala')
-rw-r--r--src/compiler/scala/tools/nsc/interactive/Global.scala157
1 files changed, 106 insertions, 51 deletions
diff --git a/src/compiler/scala/tools/nsc/interactive/Global.scala b/src/compiler/scala/tools/nsc/interactive/Global.scala
index 4ab7b98b3d..105b0e4833 100644
--- a/src/compiler/scala/tools/nsc/interactive/Global.scala
+++ b/src/compiler/scala/tools/nsc/interactive/Global.scala
@@ -225,7 +225,10 @@ class Global(settings: Settings, _reporter: Reporter, projectName: String = "")
/** Called from parser, which signals hereby that a method definition has been parsed.
*/
override def signalParseProgress(pos: Position) {
- checkForMoreWork(pos)
+ // We only want to be interruptible when running on the PC thread.
+ if(onCompilerThread) {
+ checkForMoreWork(pos)
+ }
}
/** Called from typechecker, which signals hereby that a node has been completely typechecked.
@@ -447,7 +450,7 @@ class Global(settings: Settings, _reporter: Reporter, projectName: String = "")
*/
@elidable(elidable.WARNING)
override def assertCorrectThread() {
- assert(initializing || (Thread.currentThread() eq compileRunner),
+ assert(initializing || onCompilerThread,
"Race condition detected: You are running a presentation compiler method outside the PC thread.[phase: %s]".format(globalPhase) +
" Please file a ticket with the current stack trace at https://www.assembla.com/spaces/scala-ide/support/tickets")
}
@@ -462,6 +465,9 @@ class Global(settings: Settings, _reporter: Reporter, projectName: String = "")
compileRunner
}
+ private def ensureUpToDate(unit: RichCompilationUnit) =
+ if (!unit.isUpToDate && unit.status != JustParsed) reset(unit) // reparse previously typechecked units.
+
/** Compile all loaded source files in the order given by `allSources`.
*/
private[interactive] final def backgroundCompile() {
@@ -474,7 +480,7 @@ class Global(settings: Settings, _reporter: Reporter, projectName: String = "")
// ensure all loaded units are parsed
for (s <- allSources; unit <- getUnit(s)) {
// checkForMoreWork(NoPosition) // disabled, as any work done here would be in an inconsistent state
- if (!unit.isUpToDate && unit.status != JustParsed) reset(unit) // reparse previously typechecked units.
+ ensureUpToDate(unit)
parseAndEnter(unit)
serviceParsedEntered()
}
@@ -727,7 +733,7 @@ class Global(settings: Settings, _reporter: Reporter, projectName: String = "")
try {
debugLog("starting targeted type check")
typeCheck(unit)
- println("tree not found at "+pos)
+// println("tree not found at "+pos)
EmptyTree
} catch {
case ex: TyperResult => new Locator(pos) locateIn ex.tree
@@ -758,64 +764,69 @@ class Global(settings: Settings, _reporter: Reporter, projectName: String = "")
respond(response)(typedTree(source, forceReload))
}
- /** Implements CompilerControl.askLinkPos */
- private[interactive] def getLinkPos(sym: Symbol, source: SourceFile, response: Response[Position]) {
+ private def withTempUnit[T](source: SourceFile)(f: RichCompilationUnit => T): T =
+ getUnit(source) match {
+ case None =>
+ reloadSources(List(source))
+ try f(getUnit(source).get)
+ finally afterRunRemoveUnitOf(source)
+ case Some(unit) =>
+ f(unit)
+ }
- /** Find position of symbol `sym` in unit `unit`. Pre: `unit is loaded. */
- def findLinkPos(unit: RichCompilationUnit): Position = {
- val originalTypeParams = sym.owner.typeParams
- parseAndEnter(unit)
- val pre = adaptToNewRunMap(ThisType(sym.owner))
- val rawsym = pre.typeSymbol.info.decl(sym.name)
- val newsym = rawsym filter { alt =>
- sym.isType || {
- try {
- val tp1 = pre.memberType(alt) onTypeError NoType
- val tp2 = adaptToNewRunMap(sym.tpe) substSym (originalTypeParams, sym.owner.typeParams)
- matchesType(tp1, tp2, false) || {
- debugLog(s"getLinkPos matchesType($tp1, $tp2) failed")
- val tp3 = adaptToNewRunMap(sym.tpe) substSym (originalTypeParams, alt.owner.typeParams)
- matchesType(tp1, tp3, false) || {
- debugLog(s"getLinkPos fallback matchesType($tp1, $tp3) failed")
- false
- }
- }
- }
- catch {
- case ex: ControlThrowable => throw ex
- case ex: Throwable =>
- println("error in hyperlinking: " + ex)
- ex.printStackTrace()
+ /** Find a 'mirror' of symbol `sym` in unit `unit`. Pre: `unit is loaded. */
+ private def findMirrorSymbol(sym: Symbol, unit: RichCompilationUnit): Symbol = {
+ val originalTypeParams = sym.owner.typeParams
+ ensureUpToDate(unit)
+ parseAndEnter(unit)
+ val pre = adaptToNewRunMap(ThisType(sym.owner))
+ val rawsym = pre.typeSymbol.info.decl(sym.name)
+ val newsym = rawsym filter { alt =>
+ sym.isType || {
+ try {
+ val tp1 = pre.memberType(alt) onTypeError NoType
+ val tp2 = adaptToNewRunMap(sym.tpe) substSym (originalTypeParams, sym.owner.typeParams)
+ matchesType(tp1, tp2, false) || {
+ debugLog(s"findMirrorSymbol matchesType($tp1, $tp2) failed")
+ val tp3 = adaptToNewRunMap(sym.tpe) substSym (originalTypeParams, alt.owner.typeParams)
+ matchesType(tp1, tp3, false) || {
+ debugLog(s"findMirrorSymbol fallback matchesType($tp1, $tp3) failed")
false
+ }
}
}
- }
- if (newsym == NoSymbol) {
- if (rawsym.exists && !rawsym.isOverloaded) rawsym.pos
- else {
- debugLog("link not found " + sym + " " + source + " " + pre)
- NoPosition
+ catch {
+ case ex: ControlThrowable => throw ex
+ case ex: Throwable =>
+ debugLog("error in findMirrorSymbol: " + ex)
+ ex.printStackTrace()
+ false
}
- } else if (newsym.isOverloaded) {
- settings.uniqid.value = true
- debugLog("link ambiguous " + sym + " " + source + " " + pre + " " + newsym.alternatives)
- NoPosition
- } else {
- debugLog("link found for " + newsym + ": " + newsym.pos)
- newsym.pos
}
}
+ if (newsym == NoSymbol) {
+ if (rawsym.exists && !rawsym.isOverloaded) rawsym
+ else {
+ debugLog("mirror not found " + sym + " " + unit.source + " " + pre)
+ NoSymbol
+ }
+ } else if (newsym.isOverloaded) {
+ settings.uniqid.value = true
+ debugLog("mirror ambiguous " + sym + " " + unit.source + " " + pre + " " + newsym.alternatives)
+ NoSymbol
+ } else {
+ debugLog("mirror found for " + newsym + ": " + newsym.pos)
+ newsym
+ }
+ }
+ /** Implements CompilerControl.askLinkPos */
+ private[interactive] def getLinkPos(sym: Symbol, source: SourceFile, response: Response[Position]) {
informIDE("getLinkPos "+sym+" "+source)
respond(response) {
if (sym.owner.isClass) {
- getUnit(source) match {
- case None =>
- reloadSources(List(source))
- try findLinkPos(getUnit(source).get)
- finally afterRunRemoveUnitOf(source)
- case Some(unit) =>
- findLinkPos(unit)
+ withTempUnit(source){ u =>
+ findMirrorSymbol(sym, u).pos
}
} else {
debugLog("link not in class "+sym+" "+source+" "+sym.owner)
@@ -824,6 +835,50 @@ class Global(settings: Settings, _reporter: Reporter, projectName: String = "")
}
}
+ /** Implements CompilerControl.askDocComment */
+ private[interactive] def getDocComment(sym: Symbol, site: Symbol, source: SourceFile, response: Response[(String, String, Position)]) {
+ informIDE("getDocComment "+sym+" "+source)
+ respond(response) {
+ withTempUnit(source){ u =>
+ val mirror = findMirrorSymbol(sym, u)
+ if (mirror eq NoSymbol)
+ ("", "", NoPosition)
+ else {
+ forceDocComment(mirror, u)
+ (expandedDocComment(mirror), rawDocComment(mirror), docCommentPos(mirror))
+ }
+ }
+ }
+ }
+
+ private def forceDocComment(sym: Symbol, unit: RichCompilationUnit) {
+ // Either typer has been run and we don't find DocDef,
+ // or we force the targeted typecheck here.
+ // In both cases doc comment maps should be filled for the subject symbol.
+ val docTree =
+ unit.body find {
+ case DocDef(_, defn) if defn.symbol eq sym => true
+ case _ => false
+ }
+
+ for (t <- docTree) {
+ debugLog("Found DocDef tree for "+sym)
+ // Cannot get a typed tree at position since DocDef range is transparent.
+ val prevPos = unit.targetPos
+ val prevInterruptsEnabled = interruptsEnabled
+ try {
+ unit.targetPos = t.pos
+ interruptsEnabled = true
+ typeCheck(unit)
+ } catch {
+ case _: TyperResult => // ignore since we are after the side effect.
+ } finally {
+ unit.targetPos = prevPos
+ interruptsEnabled = prevInterruptsEnabled
+ }
+ }
+ }
+
def stabilizedType(tree: Tree): Type = tree match {
case Ident(_) if tree.symbol.isStable =>
singleType(NoPrefix, tree.symbol)