diff options
author | Iulian Dragos <jaguarul@gmail.com> | 2011-09-16 11:46:22 +0000 |
---|---|---|
committer | Iulian Dragos <jaguarul@gmail.com> | 2011-09-16 11:46:22 +0000 |
commit | be57a47dcf257df8efef485e126b9b39c878e0b8 (patch) | |
tree | 3eb463ba979a00425ca07e4bf5137bbae16257c7 | |
parent | 36bdc192b2f170d06354253e82c2b17d78704b82 (diff) | |
download | scala-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.
-rw-r--r-- | src/compiler/scala/tools/nsc/interactive/CompilerControl.scala | 9 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/interactive/Global.scala | 55 |
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 { |