Fix issues with incremental cache version change

#KT-9360 fixed

Original commit: a564724fa8
This commit is contained in:
Alexey Tsvetkov
2015-10-06 22:52:18 +03:00
parent 9d7712fdf6
commit c8f50089a8
22 changed files with 191 additions and 39 deletions
@@ -30,15 +30,11 @@ import org.jetbrains.jps.builders.java.JavaBuilderUtil
import org.jetbrains.jps.builders.java.JavaSourceRootDescriptor import org.jetbrains.jps.builders.java.JavaSourceRootDescriptor
import org.jetbrains.jps.builders.java.dependencyView.Mappings import org.jetbrains.jps.builders.java.dependencyView.Mappings
import org.jetbrains.jps.incremental.* import org.jetbrains.jps.incremental.*
import org.jetbrains.jps.incremental.ModuleLevelBuilder.ExitCode.ABORT import org.jetbrains.jps.incremental.ModuleLevelBuilder.ExitCode.*
import org.jetbrains.jps.incremental.ModuleLevelBuilder.ExitCode.ADDITIONAL_PASS_REQUIRED
import org.jetbrains.jps.incremental.ModuleLevelBuilder.ExitCode.NOTHING_DONE
import org.jetbrains.jps.incremental.ModuleLevelBuilder.ExitCode.OK
import org.jetbrains.jps.incremental.fs.CompilationRound import org.jetbrains.jps.incremental.fs.CompilationRound
import org.jetbrains.jps.incremental.java.JavaBuilder import org.jetbrains.jps.incremental.java.JavaBuilder
import org.jetbrains.jps.incremental.messages.BuildMessage import org.jetbrains.jps.incremental.messages.BuildMessage
import org.jetbrains.jps.incremental.messages.CompilerMessage import org.jetbrains.jps.incremental.messages.CompilerMessage
import org.jetbrains.jps.incremental.storage.StorageOwner
import org.jetbrains.jps.model.JpsProject import org.jetbrains.jps.model.JpsProject
import org.jetbrains.jps.model.JpsSimpleElement import org.jetbrains.jps.model.JpsSimpleElement
import org.jetbrains.jps.model.ex.JpsElementChildRoleBase import org.jetbrains.jps.model.ex.JpsElementChildRoleBase
@@ -141,10 +137,8 @@ public class KotlinBuilder : ModuleLevelBuilder(BuilderCategory.SOURCE_PROCESSOR
if (chunk.targets.any { dataManager.dataPaths.getKotlinCacheVersion(it).isIncompatible() }) { if (chunk.targets.any { dataManager.dataPaths.getKotlinCacheVersion(it).isIncompatible() }) {
LOG.info("Clearing caches for " + chunk.targets.map { it.presentableName }.join()) LOG.info("Clearing caches for " + chunk.targets.map { it.presentableName }.join())
val incrementalCaches = getIncrementalCaches(chunk, context) chunk.targets.forEach { dataManager.getKotlinCache(it).clean() }
incrementalCaches.values().forEach(StorageOwner::clean) return CHUNK_REBUILD_REQUIRED
FSOperations.markDirtyRecursively(context, CompilationRound.NEXT, chunk)
return ADDITIONAL_PASS_REQUIRED
} }
if (!dirtyFilesHolder.hasDirtyFiles() && !dirtyFilesHolder.hasRemovedFiles() if (!dirtyFilesHolder.hasDirtyFiles() && !dirtyFilesHolder.hasRemovedFiles()
@@ -238,13 +232,22 @@ public class KotlinBuilder : ModuleLevelBuilder(BuilderCategory.SOURCE_PROCESSOR
} }
private fun ChangesInfo.doProcessChanges() { private fun ChangesInfo.doProcessChanges() {
fun isKotlin(file: File) = KotlinSourceFileCollector.isKotlinSourceFile(file)
fun isNotCompiled(file: File) = file !in allCompiledFiles
when { when {
inlineAdded -> { inlineAdded -> {
recompileEverything() allCompiledFiles.clear()
FSOperations.markDirtyRecursively(context, CompilationRound.NEXT, chunk, ::isKotlin)
return return
} }
constantsChanged -> recompileOtherAndDependents() constantsChanged -> {
protoChanged -> recompileOtherKotlinInChunk() FSOperations.markDirtyRecursively(context, CompilationRound.NEXT, chunk, ::isNotCompiled)
return
}
protoChanged -> {
FSOperations.markDirty(context, CompilationRound.NEXT, chunk, { isKotlin(it) && isNotCompiled(it) })
}
} }
if (inlineChanged) { if (inlineChanged) {
@@ -261,28 +264,6 @@ public class KotlinBuilder : ModuleLevelBuilder(BuilderCategory.SOURCE_PROCESSOR
} }
} }
} }
private fun recompileEverything() {
allCompiledFiles.clear()
FSOperations.markDirtyRecursively(context, CompilationRound.NEXT, chunk)
}
private fun recompileOtherAndDependents() {
// Workaround for IDEA 14.0-14.0.2: extended version of markDirtyRecursively is not available
try {
Class.forName("org.jetbrains.jps.incremental.fs.CompilationRound")
FSOperations.markDirtyRecursively(context, CompilationRound.NEXT, chunk, { file -> file !in allCompiledFiles })
} catch (e: ClassNotFoundException) {
recompileEverything()
}
}
private fun recompileOtherKotlinInChunk() {
FSOperations.markDirty(context, chunk, { file ->
KotlinSourceFileCollector.isKotlinSourceFile(file) && file !in allCompiledFiles
})
}
} }
private fun doCompileModuleChunk( private fun doCompileModuleChunk(
@@ -40,6 +40,7 @@ import org.jetbrains.jps.incremental.ModuleBuildTarget
import org.jetbrains.jps.incremental.messages.BuildMessage import org.jetbrains.jps.incremental.messages.BuildMessage
import org.jetbrains.jps.model.JpsElementFactory import org.jetbrains.jps.model.JpsElementFactory
import org.jetbrains.jps.model.JpsModuleRootModificationUtil import org.jetbrains.jps.model.JpsModuleRootModificationUtil
import org.jetbrains.jps.model.java.JpsJavaDependencyScope
import org.jetbrains.jps.model.java.JpsJavaExtensionService import org.jetbrains.jps.model.java.JpsJavaExtensionService
import org.jetbrains.jps.util.JpsPathUtil import org.jetbrains.jps.util.JpsPathUtil
import org.jetbrains.kotlin.incremental.components.LookupTracker import org.jetbrains.kotlin.incremental.components.LookupTracker
@@ -249,18 +250,17 @@ public abstract class AbstractIncrementalJpsTest(
rebuildAndCheckOutput(makeOverallResult) rebuildAndCheckOutput(makeOverallResult)
} }
private fun readModuleDependencies(): Map<String, List<String>>? { private fun readModuleDependencies(): Map<String, List<DependencyDescriptor>>? {
val dependenciesTxt = File(testDataDir, "dependencies.txt") val dependenciesTxt = File(testDataDir, "dependencies.txt")
if (!dependenciesTxt.exists()) return null if (!dependenciesTxt.exists()) return null
val result = HashMap<String, List<String>>() val result = HashMap<String, List<DependencyDescriptor>>()
for (line in dependenciesTxt.readLines()) { for (line in dependenciesTxt.readLines()) {
val split = line.split("->") val split = line.split("->")
val module = split[0] val module = split[0]
val dependencies = if (split.size() > 1) split[1] else "" val dependencies = if (split.size() > 1) split[1] else ""
val dependencyList = dependencies.split(",").filterNot { it.isEmpty() } val dependencyList = dependencies.split(",").filterNot { it.isEmpty() }
result[module] = dependencyList.map(::parseDependency)
result[module] = dependencyList
} }
return result return result
@@ -377,8 +377,10 @@ public abstract class AbstractIncrementalJpsTest(
for ((moduleName, dependencies) in moduleDependencies) { for ((moduleName, dependencies) in moduleDependencies) {
val module = nameToModule[moduleName]!! val module = nameToModule[moduleName]!!
for (dependency in dependencies) { for (dependency in dependencies) {
JpsModuleRootModificationUtil.addDependency(module, nameToModule[dependency]) JpsModuleRootModificationUtil.addDependency(module, nameToModule[dependency.name],
JpsJavaDependencyScope.COMPILE, dependency.exported)
} }
} }
@@ -449,3 +451,10 @@ public abstract class AbstractIncrementalJpsTest(
internal val ProjectDescriptor.allModuleTargets: Collection<ModuleBuildTarget> internal val ProjectDescriptor.allModuleTargets: Collection<ModuleBuildTarget>
get() = buildTargetIndex.allTargets.filterIsInstance<ModuleBuildTarget>() get() = buildTargetIndex.allTargets.filterIsInstance<ModuleBuildTarget>()
private class DependencyDescriptor(val name: String, val exported: Boolean)
private fun parseDependency(dependency: String): DependencyDescriptor =
DependencyDescriptor(dependency.removeSuffix(EXPORTED_SUFFIX), dependency.endsWith(EXPORTED_SUFFIX))
private val EXPORTED_SUFFIX = "[exported]"
@@ -35,6 +35,12 @@ public class IncrementalCacheVersionChangedTestGenerated extends AbstractIncreme
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("jps-plugin/testData/incremental/cacheVersionChanged"), Pattern.compile("^([^\\.]+)$"), true); JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("jps-plugin/testData/incremental/cacheVersionChanged"), Pattern.compile("^([^\\.]+)$"), true);
} }
@TestMetadata("exportedModule")
public void testExportedModule() throws Exception {
String fileName = JetTestUtils.navigationMetadata("jps-plugin/testData/incremental/cacheVersionChanged/exportedModule/");
doTest(fileName);
}
@TestMetadata("module1Modified") @TestMetadata("module1Modified")
public void testModule1Modified() throws Exception { public void testModule1Modified() throws Exception {
String fileName = JetTestUtils.navigationMetadata("jps-plugin/testData/incremental/cacheVersionChanged/module1Modified/"); String fileName = JetTestUtils.navigationMetadata("jps-plugin/testData/incremental/cacheVersionChanged/module1Modified/");
@@ -47,6 +53,18 @@ public class IncrementalCacheVersionChangedTestGenerated extends AbstractIncreme
doTest(fileName); doTest(fileName);
} }
@TestMetadata("moduleWithConstantModified")
public void testModuleWithConstantModified() throws Exception {
String fileName = JetTestUtils.navigationMetadata("jps-plugin/testData/incremental/cacheVersionChanged/moduleWithConstantModified/");
doTest(fileName);
}
@TestMetadata("moduleWithInlineModified")
public void testModuleWithInlineModified() throws Exception {
String fileName = JetTestUtils.navigationMetadata("jps-plugin/testData/incremental/cacheVersionChanged/moduleWithInlineModified/");
doTest(fileName);
}
@TestMetadata("touchedFile") @TestMetadata("touchedFile")
public void testTouchedFile() throws Exception { public void testTouchedFile() throws Exception {
String fileName = JetTestUtils.navigationMetadata("jps-plugin/testData/incremental/cacheVersionChanged/touchedFile/"); String fileName = JetTestUtils.navigationMetadata("jps-plugin/testData/incremental/cacheVersionChanged/touchedFile/");
@@ -0,0 +1,24 @@
Cleaning output files:
out/production/module1/a/A.class
End of files
Compiling files:
module1/src/module1_A.kt
End of files
Cleaning output files:
out/production/module2/b/B.class
End of files
Compiling files:
module2/src/module2_B.kt
End of files
Cleaning output files:
out/production/module3/c/C.class
End of files
Compiling files:
module3/src/module3_C.kt
End of files
Cleaning output files:
out/production/module4/D/D.class
End of files
Compiling files:
module4/src/module4_D.kt
End of files
@@ -0,0 +1,4 @@
module1->
module2->module1[exported]
module3->module2
module4->module3
@@ -0,0 +1,3 @@
package a
open class A
@@ -0,0 +1,3 @@
package a
open class A
@@ -0,0 +1,7 @@
package b
import a.A
open class B {
val a = A()
}
@@ -0,0 +1,7 @@
package c
import b.B
open class C {
val b = B()
}
@@ -0,0 +1,7 @@
package D
import c.C
open class D {
val c = C()
}
@@ -0,0 +1,18 @@
Cleaning output files:
out/production/module1/META-INF/module1.kotlin_module
out/production/module1/a/APackage.class
out/production/module1/a/Module1_AKt.class
End of files
Compiling files:
module1/src/module1_A.kt
End of files
Cleaning output files:
out/production/module2/b/B.class
out/production/module2/b/C.class
End of files
Compiling files:
module2/src/module2_B.kt
End of files
Compiling files:
module2/src/module2_C.java
End of files
@@ -0,0 +1,2 @@
module1->
module2->module1
@@ -0,0 +1,3 @@
package a
val X = 10
@@ -0,0 +1,5 @@
package b
class B {
val x = a.X
}
@@ -0,0 +1,7 @@
package b;
class C {
C() {
new B();
}
}
@@ -0,0 +1,21 @@
Cleaning output files:
out/production/module1/META-INF/module1.kotlin_module
out/production/module1/a/A.class
out/production/module1/a/APackage.class
out/production/module1/a/Module1_AKt.class
End of files
Compiling files:
module1/src/module1_A.kt
End of files
Cleaning output files:
out/production/module2/b/B.class
End of files
Cleaning output files:
out/production/module2/b/C.class
End of files
Compiling files:
module2/src/module2_B.kt
End of files
Compiling files:
module2/src/module2_C.java
End of files
@@ -0,0 +1,2 @@
module1->
module2->module1
@@ -0,0 +1,7 @@
package a
open class A
inline fun f(): A {
return A()
}
@@ -0,0 +1,7 @@
package a
open class A
inline fun f(): A {
return A()
}
@@ -0,0 +1,7 @@
package b
import a.*
open class B {
val a = f()
}
@@ -0,0 +1,7 @@
package b;
class C {
C() {
new B();
}
}