From 5bb5fe0c49cf02ef9879aadaa86d3dd628be5da3 Mon Sep 17 00:00:00 2001 From: Evgeny Gerashchenko Date: Mon, 16 Feb 2015 16:30:45 +0300 Subject: [PATCH] KT-6586 accessing Kotlin class static class object variable's value from Java does not properly update between compiles #KT-6586 fixed Original commit: d1a2fd9c66f69c96d2b233e29be303eb8b4c31da --- .../kotlin/jps/build/KotlinBuilder.kt | 16 +++-- .../jps/incremental/IncrementalCacheImpl.kt | 12 ++-- .../jps/build/AbstractIncrementalJpsTest.kt | 14 ++++- .../build/IncrementalConstantSearchTest.kt | 60 +++++++++++++++++++ .../JavaClass.java | 3 + .../JavaClass.java.new | 3 + .../javaConstantChangedUsedInKotlin/build.log | 12 ++++ .../javaConstantChangedUsedInKotlin/usage.kt | 2 + .../JavaClass.java | 3 + .../JavaClass.java.new | 3 + .../build.log | 6 ++ .../usage.kt | 2 + .../Usage.java | 7 +++ .../kotlinConstantChangedUsedInJava/build.log | 16 +++++ .../kotlinConstantChangedUsedInJava/const.kt | 8 +++ .../const.kt.new | 8 +++ .../Usage.java | 7 +++ .../build.log | 7 +++ .../const.kt | 7 +++ .../const.kt.new | 7 +++ 20 files changed, 187 insertions(+), 16 deletions(-) create mode 100644 jps/jps-plugin/test/org/jetbrains/kotlin/jps/build/IncrementalConstantSearchTest.kt create mode 100644 jps/jps-plugin/testData/incremental/custom/javaConstantChangedUsedInKotlin/JavaClass.java create mode 100644 jps/jps-plugin/testData/incremental/custom/javaConstantChangedUsedInKotlin/JavaClass.java.new create mode 100644 jps/jps-plugin/testData/incremental/custom/javaConstantChangedUsedInKotlin/build.log create mode 100644 jps/jps-plugin/testData/incremental/custom/javaConstantChangedUsedInKotlin/usage.kt create mode 100644 jps/jps-plugin/testData/incremental/custom/javaConstantUnchangedUsedInKotlin/JavaClass.java create mode 100644 jps/jps-plugin/testData/incremental/custom/javaConstantUnchangedUsedInKotlin/JavaClass.java.new create mode 100644 jps/jps-plugin/testData/incremental/custom/javaConstantUnchangedUsedInKotlin/build.log create mode 100644 jps/jps-plugin/testData/incremental/custom/javaConstantUnchangedUsedInKotlin/usage.kt create mode 100644 jps/jps-plugin/testData/incremental/custom/kotlinConstantChangedUsedInJava/Usage.java create mode 100644 jps/jps-plugin/testData/incremental/custom/kotlinConstantChangedUsedInJava/build.log create mode 100644 jps/jps-plugin/testData/incremental/custom/kotlinConstantChangedUsedInJava/const.kt create mode 100644 jps/jps-plugin/testData/incremental/custom/kotlinConstantChangedUsedInJava/const.kt.new create mode 100644 jps/jps-plugin/testData/incremental/custom/kotlinConstantUnchangedUsedInJava/Usage.java create mode 100644 jps/jps-plugin/testData/incremental/custom/kotlinConstantUnchangedUsedInJava/build.log create mode 100644 jps/jps-plugin/testData/incremental/custom/kotlinConstantUnchangedUsedInJava/const.kt create mode 100644 jps/jps-plugin/testData/incremental/custom/kotlinConstantUnchangedUsedInJava/const.kt.new diff --git a/jps/jps-plugin/src/org/jetbrains/kotlin/jps/build/KotlinBuilder.kt b/jps/jps-plugin/src/org/jetbrains/kotlin/jps/build/KotlinBuilder.kt index 7bdca13a063..1d5cd4e977a 100644 --- a/jps/jps-plugin/src/org/jetbrains/kotlin/jps/build/KotlinBuilder.kt +++ b/jps/jps-plugin/src/org/jetbrains/kotlin/jps/build/KotlinBuilder.kt @@ -167,28 +167,26 @@ public class KotlinBuilder : ModuleLevelBuilder(BuilderCategory.SOURCE_PROCESSOR } if (IncrementalCompilation.ENABLED) { - val fileFilter = FileFilter { file -> - KotlinSourceFileCollector.isKotlinSourceFile(file) && file !in allCompiledFiles - } - when (recompilationDecision) { - RECOMPILE_ALL_CHUNK_AND_DEPENDANTS -> { + RECOMPILE_ALL_IN_CHUNK_AND_DEPENDANTS -> { allCompiledFiles.clear() FSOperations.markDirtyRecursively(context, chunk) } - RECOMPILE_OTHERS_WITH_DEPENDANTS -> { + RECOMPILE_OTHER_IN_CHUNK_AND_DEPENDANTS -> { // 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, fileFilter) + FSOperations.markDirtyRecursively(context, CompilationRound.NEXT, chunk, { file -> file !in allCompiledFiles }) } catch (e: ClassNotFoundException) { allCompiledFiles.clear() FSOperations.markDirtyRecursively(context, chunk) } } - RECOMPILE_OTHERS_IN_CHUNK -> { - FSOperations.markDirty(context, chunk, fileFilter) + RECOMPILE_OTHER_KOTLIN_IN_CHUNK -> { + FSOperations.markDirty(context, chunk, { file -> + KotlinSourceFileCollector.isKotlinSourceFile(file) && file !in allCompiledFiles + }) } } return ADDITIONAL_PASS_REQUIRED diff --git a/jps/jps-plugin/src/org/jetbrains/kotlin/jps/incremental/IncrementalCacheImpl.kt b/jps/jps-plugin/src/org/jetbrains/kotlin/jps/incremental/IncrementalCacheImpl.kt index a45bc64f8ad..953d3f8a2a4 100644 --- a/jps/jps-plugin/src/org/jetbrains/kotlin/jps/incremental/IncrementalCacheImpl.kt +++ b/jps/jps-plugin/src/org/jetbrains/kotlin/jps/incremental/IncrementalCacheImpl.kt @@ -119,9 +119,9 @@ public class IncrementalCacheImpl(targetDataRoot: File) : StorageOwner, Incremen private fun getRecompilationDecision(protoChanged: Boolean, constantsChanged: Boolean, inlinesChanged: Boolean) = when { - inlinesChanged -> RECOMPILE_ALL_CHUNK_AND_DEPENDANTS - constantsChanged -> RECOMPILE_OTHERS_WITH_DEPENDANTS - protoChanged -> RECOMPILE_OTHERS_IN_CHUNK + inlinesChanged -> RECOMPILE_ALL_IN_CHUNK_AND_DEPENDANTS + constantsChanged -> RECOMPILE_OTHER_IN_CHUNK_AND_DEPENDANTS + protoChanged -> RECOMPILE_OTHER_KOTLIN_IN_CHUNK else -> DO_NOTHING } @@ -589,9 +589,9 @@ public class IncrementalCacheImpl(targetDataRoot: File) : StorageOwner, Incremen enum class RecompilationDecision { DO_NOTHING - RECOMPILE_OTHERS_IN_CHUNK - RECOMPILE_OTHERS_WITH_DEPENDANTS - RECOMPILE_ALL_CHUNK_AND_DEPENDANTS + RECOMPILE_OTHER_KOTLIN_IN_CHUNK + RECOMPILE_OTHER_IN_CHUNK_AND_DEPENDANTS + RECOMPILE_ALL_IN_CHUNK_AND_DEPENDANTS fun merge(other: RecompilationDecision): RecompilationDecision { return if (other.ordinal() > this.ordinal()) other else this diff --git a/jps/jps-plugin/test/org/jetbrains/kotlin/jps/build/AbstractIncrementalJpsTest.kt b/jps/jps-plugin/test/org/jetbrains/kotlin/jps/build/AbstractIncrementalJpsTest.kt index 9ca202a651b..50c5e60d43b 100644 --- a/jps/jps-plugin/test/org/jetbrains/kotlin/jps/build/AbstractIncrementalJpsTest.kt +++ b/jps/jps-plugin/test/org/jetbrains/kotlin/jps/build/AbstractIncrementalJpsTest.kt @@ -44,6 +44,11 @@ import junit.framework.TestCase import org.jetbrains.kotlin.jps.incremental.getKotlinCache import java.io.ByteArrayOutputStream import java.io.PrintStream +import org.jetbrains.jps.incremental.IncProjectBuilder +import org.jetbrains.jps.builders.BuildResult +import org.jetbrains.jps.incremental.BuilderRegistry +import org.jetbrains.jps.api.CanceledStatus +import org.jetbrains.jps.builders.java.dependencyView.Callbacks public abstract class AbstractIncrementalJpsTest : JpsBuildTestCase() { class object { @@ -70,12 +75,19 @@ public abstract class AbstractIncrementalJpsTest : JpsBuildTestCase() { protected open val customTest: Boolean get() = false + protected open val mockConstantSearch: Callbacks.ConstantAffectionResolver? + get() = null + fun build(scope: CompileScopeTestBuilder = CompileScopeTestBuilder.make().all()): MakeResult { val workDirPath = FileUtil.toSystemIndependentName(workDir.getAbsolutePath()) val logger = MyLogger(workDirPath) val descriptor = createProjectDescriptor(BuildLoggingManager(logger)) try { - val buildResult = doBuild(descriptor, scope)!! + val builder = IncProjectBuilder(descriptor, BuilderRegistry.getInstance(), myBuildParams, CanceledStatus.NULL, mockConstantSearch, true) + val buildResult = BuildResult() + builder.addMessageHandler(buildResult) + builder.build(scope.build(), false) + if (!buildResult.isSuccessful()) { val errorMessages = buildResult diff --git a/jps/jps-plugin/test/org/jetbrains/kotlin/jps/build/IncrementalConstantSearchTest.kt b/jps/jps-plugin/test/org/jetbrains/kotlin/jps/build/IncrementalConstantSearchTest.kt new file mode 100644 index 00000000000..8293f92313f --- /dev/null +++ b/jps/jps-plugin/test/org/jetbrains/kotlin/jps/build/IncrementalConstantSearchTest.kt @@ -0,0 +1,60 @@ +/* + * Copyright 2010-2015 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.kotlin.jps.build + +import org.jetbrains.jps.builders.java.dependencyView.Callbacks +import com.intellij.util.concurrency.FixedFuture +import java.io.File +import java.util.concurrent.Future + +public class IncrementalConstantSearchTest : AbstractIncrementalJpsTest() { + fun testJavaConstantChangedUsedInKotlin() { + doTest("jps-plugin/testData/incremental/custom/javaConstantChangedUsedInKotlin/") + } + + fun testJavaConstantUnchangedUsedInKotlin() { + doTest("jps-plugin/testData/incremental/custom/javaConstantUnchangedUsedInKotlin/") + } + + fun testKotlinConstantChangedUsedInJava() { + doTest("jps-plugin/testData/incremental/custom/kotlinConstantChangedUsedInJava/") + } + + fun testKotlinConstantUnchangedUsedInJava() { + doTest("jps-plugin/testData/incremental/custom/kotlinConstantUnchangedUsedInJava/") + } + + override val mockConstantSearch: Callbacks.ConstantAffectionResolver? + get() = object : Callbacks.ConstantAffectionResolver { + override fun request( + ownerClassName: String?, + fieldName: String?, + accessFlags: Int, + fieldRemoved: Boolean, + accessChanged: Boolean + ): Future { + // We emulate how constant affection service works in IDEA: + // it is able to find Kotlin usages of Java constant, but can't find Java usages of Kotlin constant + val affectedFiles = if (ownerClassName == "JavaClass" && fieldName == "CONST") { + listOf(File(workDir, "src/usage.kt")) + } else { + emptyList() + } + return FixedFuture(Callbacks.ConstantAffection(affectedFiles)) + } + } +} \ No newline at end of file diff --git a/jps/jps-plugin/testData/incremental/custom/javaConstantChangedUsedInKotlin/JavaClass.java b/jps/jps-plugin/testData/incremental/custom/javaConstantChangedUsedInKotlin/JavaClass.java new file mode 100644 index 00000000000..888f27db4e3 --- /dev/null +++ b/jps/jps-plugin/testData/incremental/custom/javaConstantChangedUsedInKotlin/JavaClass.java @@ -0,0 +1,3 @@ +public class JavaClass { + public static final String CONST = "A"; +} diff --git a/jps/jps-plugin/testData/incremental/custom/javaConstantChangedUsedInKotlin/JavaClass.java.new b/jps/jps-plugin/testData/incremental/custom/javaConstantChangedUsedInKotlin/JavaClass.java.new new file mode 100644 index 00000000000..96ac5cb2bca --- /dev/null +++ b/jps/jps-plugin/testData/incremental/custom/javaConstantChangedUsedInKotlin/JavaClass.java.new @@ -0,0 +1,3 @@ +public class JavaClass { + public static final String CONST = "B"; +} diff --git a/jps/jps-plugin/testData/incremental/custom/javaConstantChangedUsedInKotlin/build.log b/jps/jps-plugin/testData/incremental/custom/javaConstantChangedUsedInKotlin/build.log new file mode 100644 index 00000000000..554d1e2cead --- /dev/null +++ b/jps/jps-plugin/testData/incremental/custom/javaConstantChangedUsedInKotlin/build.log @@ -0,0 +1,12 @@ +Cleaning output files: +out/production/module/JavaClass.class +End of files +Compiling files: +src/JavaClass.java +End of files +Cleaning output files: +out/production/module/Usage.class +End of files +Compiling files: +src/usage.kt +End of files \ No newline at end of file diff --git a/jps/jps-plugin/testData/incremental/custom/javaConstantChangedUsedInKotlin/usage.kt b/jps/jps-plugin/testData/incremental/custom/javaConstantChangedUsedInKotlin/usage.kt new file mode 100644 index 00000000000..9f972262826 --- /dev/null +++ b/jps/jps-plugin/testData/incremental/custom/javaConstantChangedUsedInKotlin/usage.kt @@ -0,0 +1,2 @@ +deprecated(JavaClass.CONST + JavaClass.CONST) +class Usage diff --git a/jps/jps-plugin/testData/incremental/custom/javaConstantUnchangedUsedInKotlin/JavaClass.java b/jps/jps-plugin/testData/incremental/custom/javaConstantUnchangedUsedInKotlin/JavaClass.java new file mode 100644 index 00000000000..888f27db4e3 --- /dev/null +++ b/jps/jps-plugin/testData/incremental/custom/javaConstantUnchangedUsedInKotlin/JavaClass.java @@ -0,0 +1,3 @@ +public class JavaClass { + public static final String CONST = "A"; +} diff --git a/jps/jps-plugin/testData/incremental/custom/javaConstantUnchangedUsedInKotlin/JavaClass.java.new b/jps/jps-plugin/testData/incremental/custom/javaConstantUnchangedUsedInKotlin/JavaClass.java.new new file mode 100644 index 00000000000..888f27db4e3 --- /dev/null +++ b/jps/jps-plugin/testData/incremental/custom/javaConstantUnchangedUsedInKotlin/JavaClass.java.new @@ -0,0 +1,3 @@ +public class JavaClass { + public static final String CONST = "A"; +} diff --git a/jps/jps-plugin/testData/incremental/custom/javaConstantUnchangedUsedInKotlin/build.log b/jps/jps-plugin/testData/incremental/custom/javaConstantUnchangedUsedInKotlin/build.log new file mode 100644 index 00000000000..1cefb7c31b1 --- /dev/null +++ b/jps/jps-plugin/testData/incremental/custom/javaConstantUnchangedUsedInKotlin/build.log @@ -0,0 +1,6 @@ +Cleaning output files: +out/production/module/JavaClass.class +End of files +Compiling files: +src/JavaClass.java +End of files \ No newline at end of file diff --git a/jps/jps-plugin/testData/incremental/custom/javaConstantUnchangedUsedInKotlin/usage.kt b/jps/jps-plugin/testData/incremental/custom/javaConstantUnchangedUsedInKotlin/usage.kt new file mode 100644 index 00000000000..9f972262826 --- /dev/null +++ b/jps/jps-plugin/testData/incremental/custom/javaConstantUnchangedUsedInKotlin/usage.kt @@ -0,0 +1,2 @@ +deprecated(JavaClass.CONST + JavaClass.CONST) +class Usage diff --git a/jps/jps-plugin/testData/incremental/custom/kotlinConstantChangedUsedInJava/Usage.java b/jps/jps-plugin/testData/incremental/custom/kotlinConstantChangedUsedInJava/Usage.java new file mode 100644 index 00000000000..9430b8d5f66 --- /dev/null +++ b/jps/jps-plugin/testData/incremental/custom/kotlinConstantChangedUsedInJava/Usage.java @@ -0,0 +1,7 @@ +import test.*; + +class Usage { + public static void main(String[] args) { + System.out.println(Klass.CONST + Klass.CONST); + } +} diff --git a/jps/jps-plugin/testData/incremental/custom/kotlinConstantChangedUsedInJava/build.log b/jps/jps-plugin/testData/incremental/custom/kotlinConstantChangedUsedInJava/build.log new file mode 100644 index 00000000000..8d7fdb6175c --- /dev/null +++ b/jps/jps-plugin/testData/incremental/custom/kotlinConstantChangedUsedInJava/build.log @@ -0,0 +1,16 @@ +Cleaning output files: +out/production/module/test/Klass$Default.class +out/production/module/test/Klass.class +End of files +Compiling files: +src/const.kt +End of files +Compiling files: +src/Usage.java +End of files +Cleaning output files: +out/production/module/Usage.class +End of files +Compiling files: +src/Usage.java +End of files \ No newline at end of file diff --git a/jps/jps-plugin/testData/incremental/custom/kotlinConstantChangedUsedInJava/const.kt b/jps/jps-plugin/testData/incremental/custom/kotlinConstantChangedUsedInJava/const.kt new file mode 100644 index 00000000000..a3b30360e52 --- /dev/null +++ b/jps/jps-plugin/testData/incremental/custom/kotlinConstantChangedUsedInJava/const.kt @@ -0,0 +1,8 @@ +package test + +class Klass { + class object { + // Old and new constant values are different, but their hashes are the same + val CONST = "BF" + } +} diff --git a/jps/jps-plugin/testData/incremental/custom/kotlinConstantChangedUsedInJava/const.kt.new b/jps/jps-plugin/testData/incremental/custom/kotlinConstantChangedUsedInJava/const.kt.new new file mode 100644 index 00000000000..8835b725265 --- /dev/null +++ b/jps/jps-plugin/testData/incremental/custom/kotlinConstantChangedUsedInJava/const.kt.new @@ -0,0 +1,8 @@ +package test + +class Klass { + class object { + // Old and new constant values are different, but their hashes are the same + val CONST = "Ae" + } +} diff --git a/jps/jps-plugin/testData/incremental/custom/kotlinConstantUnchangedUsedInJava/Usage.java b/jps/jps-plugin/testData/incremental/custom/kotlinConstantUnchangedUsedInJava/Usage.java new file mode 100644 index 00000000000..9430b8d5f66 --- /dev/null +++ b/jps/jps-plugin/testData/incremental/custom/kotlinConstantUnchangedUsedInJava/Usage.java @@ -0,0 +1,7 @@ +import test.*; + +class Usage { + public static void main(String[] args) { + System.out.println(Klass.CONST + Klass.CONST); + } +} diff --git a/jps/jps-plugin/testData/incremental/custom/kotlinConstantUnchangedUsedInJava/build.log b/jps/jps-plugin/testData/incremental/custom/kotlinConstantUnchangedUsedInJava/build.log new file mode 100644 index 00000000000..6bc3a50bee0 --- /dev/null +++ b/jps/jps-plugin/testData/incremental/custom/kotlinConstantUnchangedUsedInJava/build.log @@ -0,0 +1,7 @@ +Cleaning output files: +out/production/module/test/Klass$Default.class +out/production/module/test/Klass.class +End of files +Compiling files: +src/const.kt +End of files \ No newline at end of file diff --git a/jps/jps-plugin/testData/incremental/custom/kotlinConstantUnchangedUsedInJava/const.kt b/jps/jps-plugin/testData/incremental/custom/kotlinConstantUnchangedUsedInJava/const.kt new file mode 100644 index 00000000000..b13ee1c3c3b --- /dev/null +++ b/jps/jps-plugin/testData/incremental/custom/kotlinConstantUnchangedUsedInJava/const.kt @@ -0,0 +1,7 @@ +package test + +class Klass { + class object { + val CONST = "bar" + } +} diff --git a/jps/jps-plugin/testData/incremental/custom/kotlinConstantUnchangedUsedInJava/const.kt.new b/jps/jps-plugin/testData/incremental/custom/kotlinConstantUnchangedUsedInJava/const.kt.new new file mode 100644 index 00000000000..b13ee1c3c3b --- /dev/null +++ b/jps/jps-plugin/testData/incremental/custom/kotlinConstantUnchangedUsedInJava/const.kt.new @@ -0,0 +1,7 @@ +package test + +class Klass { + class object { + val CONST = "bar" + } +}