diff options
author | Hubert Plociniczak <hubert.plociniczak@epfl.ch> | 2009-11-26 12:05:45 +0000 |
---|---|---|
committer | Hubert Plociniczak <hubert.plociniczak@epfl.ch> | 2009-11-26 12:05:45 +0000 |
commit | 797b2aeda3786b4d38ad389380ee5f24fff1c9d6 (patch) | |
tree | 6ecf579c39a7887a4e9a6189652e33847849f697 /src/compiler | |
parent | 83d96af554734a69a4f1a03a05df3a8ef589ff95 (diff) | |
download | scala-797b2aeda3786b4d38ad389380ee5f24fff1c9d6.tar.gz scala-797b2aeda3786b4d38ad389380ee5f24fff1c9d6.tar.bz2 scala-797b2aeda3786b4d38ad389380ee5f24fff1c9d6.zip |
Closes #2562
Diffstat (limited to 'src/compiler')
-rw-r--r-- | src/compiler/scala/tools/nsc/interactive/RefinedBuildManager.scala | 54 |
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) |