KT-6586 accessing Kotlin class static class object variable's value from Java does not properly update between compiles

#KT-6586 fixed
This commit is contained in:
Evgeny Gerashchenko
2015-02-16 16:30:45 +03:00
parent 15a3496dbd
commit d1a2fd9c66
21 changed files with 188 additions and 16 deletions
@@ -20,6 +20,7 @@
<patterns>
<pattern testClass="org.jetbrains.kotlin.jps.build.IncrementalJpsTestGenerated" />
<pattern testClass="org.jetbrains.kotlin.jps.build.IncrementalCacheVersionChangedTest" />
<pattern testClass="org.jetbrains.kotlin.jps.build.IncrementalConstantSearchTest" />
</patterns>
<RunnerSettings RunnerId="Debug">
<option name="DEBUG_PORT" value="" />
@@ -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
@@ -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
@@ -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
@@ -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<Callbacks.ConstantAffection> {
// 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))
}
}
}
@@ -0,0 +1,3 @@
public class JavaClass {
public static final String CONST = "A";
}
@@ -0,0 +1,3 @@
public class JavaClass {
public static final String CONST = "B";
}
@@ -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
@@ -0,0 +1,2 @@
deprecated(JavaClass.CONST + JavaClass.CONST)
class Usage
@@ -0,0 +1,3 @@
public class JavaClass {
public static final String CONST = "A";
}
@@ -0,0 +1,3 @@
public class JavaClass {
public static final String CONST = "A";
}
@@ -0,0 +1,6 @@
Cleaning output files:
out/production/module/JavaClass.class
End of files
Compiling files:
src/JavaClass.java
End of files
@@ -0,0 +1,2 @@
deprecated(JavaClass.CONST + JavaClass.CONST)
class Usage
@@ -0,0 +1,7 @@
import test.*;
class Usage {
public static void main(String[] args) {
System.out.println(Klass.CONST + Klass.CONST);
}
}
@@ -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
@@ -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"
}
}
@@ -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"
}
}
@@ -0,0 +1,7 @@
import test.*;
class Usage {
public static void main(String[] args) {
System.out.println(Klass.CONST + Klass.CONST);
}
}
@@ -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
@@ -0,0 +1,7 @@
package test
class Klass {
class object {
val CONST = "bar"
}
}
@@ -0,0 +1,7 @@
package test
class Klass {
class object {
val CONST = "bar"
}
}