summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorIulian Dragos <jaguarul@gmail.com>2011-09-16 11:46:22 +0000
committerIulian Dragos <jaguarul@gmail.com>2011-09-16 11:46:22 +0000
commitbe57a47dcf257df8efef485e126b9b39c878e0b8 (patch)
tree3eb463ba979a00425ca07e4bf5137bbae16257c7 /src
parent36bdc192b2f170d06354253e82c2b17d78704b82 (diff)
downloadscala-be57a47dcf257df8efef485e126b9b39c878e0b8.tar.gz
scala-be57a47dcf257df8efef485e126b9b39c878e0b8.tar.bz2
scala-be57a47dcf257df8efef485e126b9b39c878e0b8.zip
Better behavior with problematic sources in the...
Better behavior with problematic sources in the presentation compiler: - if the presentation compiler crashes while type checking a source file, it puts it into an ignore buffer, and it will not type check it during background compilation rounds. Any subsequent calls to waitLoadedTyped will fail with the last exception. To remove it from the ignore list call either 'enableIgnoredFile' or 'askToDoFirst' on that file. - sources with syntax errors are not type checked during background compilation. This leads to less spurious errors. For instance, type errors may occur much earlier in the file than the actual syntax error that caused them. review by odersky.
Diffstat (limited to 'src')
-rw-r--r--src/compiler/scala/tools/nsc/interactive/CompilerControl.scala9
-rw-r--r--src/compiler/scala/tools/nsc/interactive/Global.scala55
2 files changed, 55 insertions, 9 deletions
diff --git a/src/compiler/scala/tools/nsc/interactive/CompilerControl.scala b/src/compiler/scala/tools/nsc/interactive/CompilerControl.scala
index 63793fa21a..f37f45298e 100644
--- a/src/compiler/scala/tools/nsc/interactive/CompilerControl.scala
+++ b/src/compiler/scala/tools/nsc/interactive/CompilerControl.scala
@@ -167,7 +167,9 @@ trait CompilerControl { self: Global =>
def askScopeCompletion(pos: Position, response: Response[List[Member]]) =
postWorkItem(new AskScopeCompletionItem(pos, response))
- /** Asks to do unit corresponding to given source file on present and subsequent type checking passes */
+ /** Asks to do unit corresponding to given source file on present and subsequent type checking passes.
+ * If the file is in the 'crashedFiles' ignore list it is removed and typechecked normally.
+ */
def askToDoFirst(source: SourceFile) =
postWorkItem(new AskToDoFirstItem(source))
@@ -330,7 +332,10 @@ trait CompilerControl { self: Global =>
}
class AskToDoFirstItem(val source: SourceFile) extends WorkItem {
- def apply() = moveToFront(List(source))
+ def apply() = {
+ moveToFront(List(source))
+ enableIgnoredFile(source.file)
+ }
override def toString = "dofirst "+source
def raiseMissing() = ()
diff --git a/src/compiler/scala/tools/nsc/interactive/Global.scala b/src/compiler/scala/tools/nsc/interactive/Global.scala
index 78169941c8..a0913bd75d 100644
--- a/src/compiler/scala/tools/nsc/interactive/Global.scala
+++ b/src/compiler/scala/tools/nsc/interactive/Global.scala
@@ -48,7 +48,6 @@ class Global(settings: Settings, reporter: Reporter, projectName: String = "")
else NullLogger
import log.logreplay
- debugLog("interactive compiler from 20 Feb")
debugLog("logger: " + log.getClass + " writing to " + (new java.io.File(logName)).getAbsolutePath)
debugLog("classpath: "+classPath)
@@ -161,6 +160,25 @@ class Global(settings: Settings, reporter: Reporter, projectName: String = "")
*/
protected var allSources: List[SourceFile] = List()
+ private var lastException: Option[Throwable] = None
+
+ /** A list of files that crashed the compiler. They will be ignored during background
+ * compilation until they are removed from this list.
+ */
+ private var ignoredFiles: Set[AbstractFile] = Set()
+
+ /** Flush the buffer of sources that are ignored during background compilation. */
+ def clearIgnoredFiles() {
+ ignoredFiles = Set()
+ }
+
+ /** Remove a crashed file from the ignore buffer. Background compilation will take it into account
+ * and errors will be reported against it. */
+ def enableIgnoredFile(file: AbstractFile) {
+ ignoredFiles -= file
+ debugLog("Removed crashed file %s. Still in the ignored buffer: %s".format(file, ignoredFiles))
+ }
+
/** The currently active typer run */
private var currentTyperRun: TyperRun = _
newTyperRun()
@@ -440,12 +458,33 @@ class Global(settings: Settings, reporter: Reporter, projectName: String = "")
}
// ensure all loaded units are typechecked
- for (s <- allSources; unit <- getUnit(s)) {
- if (!unit.isUpToDate) typeCheck(unit)
- else debugLog("already up to date: "+unit)
- for (r <- waitLoadedTypeResponses(unit.source))
- r set unit.body
- serviceParsedEntered()
+ for (s <- allSources; if !ignoredFiles(s.file); unit <- getUnit(s)) {
+ try {
+ if (!unit.isUpToDate)
+ if (unit.problems.isEmpty)
+ typeCheck(unit)
+ else debugLog("%s has syntax errors. Skipped typechecking".format(unit))
+ else debugLog("already up to date: "+unit)
+ for (r <- waitLoadedTypeResponses(unit.source))
+ r set unit.body
+ serviceParsedEntered()
+ } catch {
+ case ex: FreshRunReq => throw ex // propagate a new run request
+
+ case ex =>
+ println("[%s]: exception during background compile: ".format(unit.source) + ex)
+ ex.printStackTrace()
+ for (r <- waitLoadedTypeResponses(unit.source)) {
+ r.raise(ex)
+ }
+ serviceParsedEntered()
+
+ lastException = Some(ex)
+ ignoredFiles += unit.source.file
+ println("[%s] marking unit as crashed (crashedFiles: %s)".format(unit, ignoredFiles))
+
+ reporter.error(unit.body.pos, "Presentation compiler crashed while type checking this file: %s".format(ex.toString()))
+ }
}
// clean out stale waiting responses
@@ -890,6 +929,8 @@ class Global(settings: Settings, reporter: Reporter, projectName: String = "")
if (unit.isUpToDate) {
debugLog("already typed");
response set unit.body
+ } else if (ignoredFiles(source.file)) {
+ response.raise(lastException.getOrElse(CancelException))
} else if (onSameThread) {
getTypedTree(source, forceReload = false, response)
} else {