KT-6586 accessing Kotlin class static class object variable's value from Java does not properly update between compiles
#KT-6586 fixed
Original commit: d1a2fd9c66
This commit is contained in:
@@ -167,28 +167,26 @@ public class KotlinBuilder : ModuleLevelBuilder(BuilderCategory.SOURCE_PROCESSOR
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (IncrementalCompilation.ENABLED) {
|
if (IncrementalCompilation.ENABLED) {
|
||||||
val fileFilter = FileFilter { file ->
|
|
||||||
KotlinSourceFileCollector.isKotlinSourceFile(file) && file !in allCompiledFiles
|
|
||||||
}
|
|
||||||
|
|
||||||
when (recompilationDecision) {
|
when (recompilationDecision) {
|
||||||
RECOMPILE_ALL_CHUNK_AND_DEPENDANTS -> {
|
RECOMPILE_ALL_IN_CHUNK_AND_DEPENDANTS -> {
|
||||||
allCompiledFiles.clear()
|
allCompiledFiles.clear()
|
||||||
FSOperations.markDirtyRecursively(context, chunk)
|
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
|
// Workaround for IDEA 14.0-14.0.2: extended version of markDirtyRecursively is not available
|
||||||
try {
|
try {
|
||||||
Class.forName("org.jetbrains.jps.incremental.fs.CompilationRound")
|
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) {
|
} catch (e: ClassNotFoundException) {
|
||||||
allCompiledFiles.clear()
|
allCompiledFiles.clear()
|
||||||
FSOperations.markDirtyRecursively(context, chunk)
|
FSOperations.markDirtyRecursively(context, chunk)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
RECOMPILE_OTHERS_IN_CHUNK -> {
|
RECOMPILE_OTHER_KOTLIN_IN_CHUNK -> {
|
||||||
FSOperations.markDirty(context, chunk, fileFilter)
|
FSOperations.markDirty(context, chunk, { file ->
|
||||||
|
KotlinSourceFileCollector.isKotlinSourceFile(file) && file !in allCompiledFiles
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return ADDITIONAL_PASS_REQUIRED
|
return ADDITIONAL_PASS_REQUIRED
|
||||||
|
|||||||
@@ -119,9 +119,9 @@ public class IncrementalCacheImpl(targetDataRoot: File) : StorageOwner, Incremen
|
|||||||
|
|
||||||
private fun getRecompilationDecision(protoChanged: Boolean, constantsChanged: Boolean, inlinesChanged: Boolean) =
|
private fun getRecompilationDecision(protoChanged: Boolean, constantsChanged: Boolean, inlinesChanged: Boolean) =
|
||||||
when {
|
when {
|
||||||
inlinesChanged -> RECOMPILE_ALL_CHUNK_AND_DEPENDANTS
|
inlinesChanged -> RECOMPILE_ALL_IN_CHUNK_AND_DEPENDANTS
|
||||||
constantsChanged -> RECOMPILE_OTHERS_WITH_DEPENDANTS
|
constantsChanged -> RECOMPILE_OTHER_IN_CHUNK_AND_DEPENDANTS
|
||||||
protoChanged -> RECOMPILE_OTHERS_IN_CHUNK
|
protoChanged -> RECOMPILE_OTHER_KOTLIN_IN_CHUNK
|
||||||
else -> DO_NOTHING
|
else -> DO_NOTHING
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -589,9 +589,9 @@ public class IncrementalCacheImpl(targetDataRoot: File) : StorageOwner, Incremen
|
|||||||
|
|
||||||
enum class RecompilationDecision {
|
enum class RecompilationDecision {
|
||||||
DO_NOTHING
|
DO_NOTHING
|
||||||
RECOMPILE_OTHERS_IN_CHUNK
|
RECOMPILE_OTHER_KOTLIN_IN_CHUNK
|
||||||
RECOMPILE_OTHERS_WITH_DEPENDANTS
|
RECOMPILE_OTHER_IN_CHUNK_AND_DEPENDANTS
|
||||||
RECOMPILE_ALL_CHUNK_AND_DEPENDANTS
|
RECOMPILE_ALL_IN_CHUNK_AND_DEPENDANTS
|
||||||
|
|
||||||
fun merge(other: RecompilationDecision): RecompilationDecision {
|
fun merge(other: RecompilationDecision): RecompilationDecision {
|
||||||
return if (other.ordinal() > this.ordinal()) other else this
|
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 org.jetbrains.kotlin.jps.incremental.getKotlinCache
|
||||||
import java.io.ByteArrayOutputStream
|
import java.io.ByteArrayOutputStream
|
||||||
import java.io.PrintStream
|
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() {
|
public abstract class AbstractIncrementalJpsTest : JpsBuildTestCase() {
|
||||||
class object {
|
class object {
|
||||||
@@ -70,12 +75,19 @@ public abstract class AbstractIncrementalJpsTest : JpsBuildTestCase() {
|
|||||||
protected open val customTest: Boolean
|
protected open val customTest: Boolean
|
||||||
get() = false
|
get() = false
|
||||||
|
|
||||||
|
protected open val mockConstantSearch: Callbacks.ConstantAffectionResolver?
|
||||||
|
get() = null
|
||||||
|
|
||||||
fun build(scope: CompileScopeTestBuilder = CompileScopeTestBuilder.make().all()): MakeResult {
|
fun build(scope: CompileScopeTestBuilder = CompileScopeTestBuilder.make().all()): MakeResult {
|
||||||
val workDirPath = FileUtil.toSystemIndependentName(workDir.getAbsolutePath())
|
val workDirPath = FileUtil.toSystemIndependentName(workDir.getAbsolutePath())
|
||||||
val logger = MyLogger(workDirPath)
|
val logger = MyLogger(workDirPath)
|
||||||
val descriptor = createProjectDescriptor(BuildLoggingManager(logger))
|
val descriptor = createProjectDescriptor(BuildLoggingManager(logger))
|
||||||
try {
|
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()) {
|
if (!buildResult.isSuccessful()) {
|
||||||
val errorMessages =
|
val errorMessages =
|
||||||
buildResult
|
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))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+3
@@ -0,0 +1,3 @@
|
|||||||
|
public class JavaClass {
|
||||||
|
public static final String CONST = "A";
|
||||||
|
}
|
||||||
+3
@@ -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
|
||||||
+3
@@ -0,0 +1,3 @@
|
|||||||
|
public class JavaClass {
|
||||||
|
public static final String CONST = "A";
|
||||||
|
}
|
||||||
+3
@@ -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"
|
||||||
|
}
|
||||||
|
}
|
||||||
+8
@@ -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"
|
||||||
|
}
|
||||||
|
}
|
||||||
+7
@@ -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"
|
||||||
|
}
|
||||||
|
}
|
||||||
+7
@@ -0,0 +1,7 @@
|
|||||||
|
package test
|
||||||
|
|
||||||
|
class Klass {
|
||||||
|
class object {
|
||||||
|
val CONST = "bar"
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user