summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHubert Plociniczak <hubert.plociniczak@epfl.ch>2009-11-26 12:05:45 +0000
committerHubert Plociniczak <hubert.plociniczak@epfl.ch>2009-11-26 12:05:45 +0000
commit797b2aeda3786b4d38ad389380ee5f24fff1c9d6 (patch)
tree6ecf579c39a7887a4e9a6189652e33847849f697
parent83d96af554734a69a4f1a03a05df3a8ef589ff95 (diff)
downloadscala-797b2aeda3786b4d38ad389380ee5f24fff1c9d6.tar.gz
scala-797b2aeda3786b4d38ad389380ee5f24fff1c9d6.tar.bz2
scala-797b2aeda3786b4d38ad389380ee5f24fff1c9d6.zip
Closes #2562
-rw-r--r--src/compiler/scala/tools/nsc/interactive/RefinedBuildManager.scala54
1 files changed, 42 insertions, 12 deletions
diff --git a/src/compiler/scala/tools/nsc/interactive/RefinedBuildManager.scala b/src/compiler/scala/tools/nsc/interactive/RefinedBuildManager.scala
index 6af23f8fde..893ed7b0e9 100644
--- a/src/compiler/scala/tools/nsc/interactive/RefinedBuildManager.scala
+++ b/src/compiler/scala/tools/nsc/interactive/RefinedBuildManager.scala
@@ -87,7 +87,10 @@ class RefinedBuildManager(val settings: Settings) extends Changes with BuildMana
* of the dependency analysis.
*/
private def update(files: Set[AbstractFile]) = {
- def update0(files: Set[AbstractFile], updated: Set[AbstractFile]): Unit = if (!files.isEmpty) {
+ val coll: mutable.Map[AbstractFile, immutable.Set[AbstractFile]] =
+ mutable.HashMap[AbstractFile, immutable.Set[AbstractFile]]()
+
+ def update0(files: Set[AbstractFile]): Unit = if (!files.isEmpty) {
deleteClassfiles(files)
val run = compiler.newRun()
compiler.inform("compiling " + files)
@@ -105,8 +108,8 @@ class RefinedBuildManager(val settings: Settings) extends Changes with BuildMana
val defs = compiler.dependencyAnalysis.definitions
for (src <- files) {
if (definitions(src).isEmpty)
- additionalDefs ++= compiler.dependencyAnalysis.
- dependencies.dependentFiles(1, mutable.Set(src))
+ additionalDefs ++= compiler.dependencyAnalysis.
+ dependencies.dependentFiles(1, mutable.Set(src))
else {
val syms = defs(src)
for (sym <- syms) {
@@ -130,29 +133,56 @@ class RefinedBuildManager(val settings: Settings) extends Changes with BuildMana
}
println("Changes: " + changesOf)
updateDefinitions(files)
- val compiled = updated ++ files
- val invalid = invalidated(files, changesOf, additionalDefs.clone() ++= compiled)
- update0(invalid -- compiled, compiled)
+ val invalid = invalidated(files, changesOf, additionalDefs)
+ update0(checkCycles(invalid, files, coll))
}
- update0(files, immutable.Set())
+ update0(files)
}
+ // Attempt to break the cycling reference deps as soon as possible and reduce
+ // the number of compilations to minimum without having too coarse grained rules
+ private def checkCycles(files: Set[AbstractFile], initial: Set[AbstractFile],
+ collect: mutable.Map[AbstractFile, immutable.Set[AbstractFile]]):
+ Set[AbstractFile] = {
+ def followChain(set: Set[AbstractFile], rest: immutable.Set[AbstractFile]):
+ immutable.Set[AbstractFile] = {
+ val deps:Set[AbstractFile] = set.flatMap(
+ s => collect.get(s) match {
+ case Some(x) => x
+ case _ => Set[AbstractFile]()
+ })
+ val newDeps = deps -- rest
+ if (newDeps.isEmpty) rest else followChain(newDeps, rest ++ newDeps)
+ }
+ var res:Set[AbstractFile] = mutable.Set()
+ files.foreach( f =>
+ if (collect contains f) {
+ val chain = followChain(Set(f), immutable.Set()) ++ files
+ chain.foreach((fc: AbstractFile) => collect += fc -> chain)
+ res ++= chain
+ } else
+ res += f
+ )
+
+ initial.foreach((f: AbstractFile) => collect += (f -> (collect.getOrElse(f, immutable.Set()) ++ res)))
+ if (res.subsetOf(initial)) Set() else res
+ }
/** Return the set of source files that are invalidated by the given changes. */
def invalidated(files: Set[AbstractFile], changesOf: collection.Map[Symbol, List[Change]],
- processed: Set[AbstractFile] = Set.empty): Set[AbstractFile] = {
+ processed: Set[AbstractFile] = Set.empty):
+ Set[AbstractFile] = {
val buf = new mutable.HashSet[AbstractFile]
val newChangesOf = new mutable.HashMap[Symbol, List[Change]]
var directDeps =
compiler.dependencyAnalysis.dependencies.dependentFiles(1, files)
- directDeps --= processed
def invalidate(file: AbstractFile, reason: String, change: Change) = {
println("invalidate " + file + " because " + reason + " [" + change + "]")
buf += file
directDeps -= file
- for (sym <- definitions(file))
+ for (sym <- definitions(file)) // fixes #2557
newChangesOf(sym) = List(change)
break
}
@@ -160,7 +190,7 @@ class RefinedBuildManager(val settings: Settings) extends Changes with BuildMana
for ((oldSym, changes) <- changesOf; change <- changes) {
def checkParents(cls: Symbol, file: AbstractFile) {
val parentChange = cls.info.parents.exists(_.typeSymbol.fullNameString == oldSym.fullNameString)
-// println("checkParents " + cls + " oldSym: " + oldSym + " parentChange: " + parentChange + " " + cls.info.parents)
+ // println("checkParents " + cls + " oldSym: " + oldSym + " parentChange: " + parentChange + " " + cls.info.parents)
change match {
case Changed(Class(_)) if parentChange =>
invalidate(file, "parents have changed", change)
@@ -192,7 +222,7 @@ class RefinedBuildManager(val settings: Settings) extends Changes with BuildMana
}
def checkReferences(file: AbstractFile) {
-// println(file + ":" + references(file))
+ // println(file + ":" + references(file))
val refs = references(file)
if (refs.isEmpty)
invalidate(file, "it is a direct dependency and we don't yet have finer-grained dependency information", change)