Recompile all sealed class usages when new derived class is added
This commit is contained in:
@@ -177,6 +177,7 @@ private class DifferenceCalculatorForClass(oldData: ProtoMapValue, newData: Prot
|
||||
override fun difference(): Difference {
|
||||
var isClassSignatureChanged = false
|
||||
val names = hashSetOf<String>()
|
||||
val classIsSealed = newProto.isSealed && oldProto.isSealed
|
||||
|
||||
fun Int.oldToNames() = names.add(oldNameResolver.getString(this))
|
||||
fun Int.newToNames() = names.add(newNameResolver.getString(this))
|
||||
@@ -193,8 +194,15 @@ private class DifferenceCalculatorForClass(oldData: ProtoMapValue, newData: Prot
|
||||
if (oldProto.hasCompanionObjectName()) oldProto.companionObjectName.oldToNames()
|
||||
if (newProto.hasCompanionObjectName()) newProto.companionObjectName.newToNames()
|
||||
}
|
||||
ProtoBufClassKind.NESTED_CLASS_NAME_LIST ->
|
||||
ProtoBufClassKind.NESTED_CLASS_NAME_LIST -> {
|
||||
if (classIsSealed) {
|
||||
// when class is sealed, adding an implementation can break exhaustive when expressions
|
||||
// the workaround is to recompile all class usages
|
||||
isClassSignatureChanged = true
|
||||
}
|
||||
|
||||
names.addAll(calcDifferenceForNames(oldProto.nestedClassNameList, newProto.nestedClassNameList))
|
||||
}
|
||||
ProtoBufClassKind.CONSTRUCTOR_LIST ->
|
||||
names.addAll(calcDifferenceForNonPrivateMembers(ProtoBuf.Class::getConstructorList))
|
||||
ProtoBufClassKind.FUNCTION_LIST ->
|
||||
@@ -255,3 +263,6 @@ private class DifferenceCalculatorForPackageFacade(oldData: ProtoMapValue, newDa
|
||||
return Difference(isClassSignatureChanged = false, changedMembersNames = names)
|
||||
}
|
||||
}
|
||||
|
||||
private val ProtoBuf.Class.isSealed: Boolean
|
||||
get() = ProtoBuf.Modality.SEALED == Flags.MODALITY.get(flags)
|
||||
|
||||
+6
@@ -1159,6 +1159,12 @@ public class ExperimentalIncrementalJpsTestGenerated extends AbstractExperimenta
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("sealedClassImplAdded")
|
||||
public void testSealedClassImplAdded() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("jps-plugin/testData/incremental/classHierarchyAffected/sealedClassImplAdded/");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("starProjectionUpperBoundChanged")
|
||||
public void testStarProjectionUpperBoundChanged() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("jps-plugin/testData/incremental/classHierarchyAffected/starProjectionUpperBoundChanged/");
|
||||
|
||||
@@ -159,6 +159,12 @@ public class ProtoComparisonTestGenerated extends AbstractProtoComparisonTest {
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("sealedClassImplAdded")
|
||||
public void testSealedClassImplAdded() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("jps-plugin/testData/comparison/classMembersOnlyChanged/sealedClassImplAdded/");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@TestMetadata("jps-plugin/testData/comparison/packageMembers")
|
||||
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
package test
|
||||
|
||||
sealed class Base {
|
||||
class A : Base()
|
||||
class B : Base()
|
||||
class C : Base()
|
||||
}
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
package test
|
||||
|
||||
sealed class Base {
|
||||
class A : Base()
|
||||
class B : Base()
|
||||
}
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
ADDED: class Base$C.class
|
||||
changes in test/Base.A: NONE
|
||||
changes in test/Base.B: NONE
|
||||
changes in test/Base: CLASS_SIGNATURE, MEMBERS
|
||||
[C]
|
||||
+4
@@ -0,0 +1,4 @@
|
||||
sealed class Base {
|
||||
class A : Base()
|
||||
class B : Base()
|
||||
}
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
sealed class Base {
|
||||
class A : Base()
|
||||
class B : Base()
|
||||
class C : Base()
|
||||
}
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
Cleaning output files:
|
||||
out/production/module/Base$A.class
|
||||
out/production/module/Base$B.class
|
||||
out/production/module/Base.class
|
||||
End of files
|
||||
Compiling files:
|
||||
src/Base.kt
|
||||
End of files
|
||||
Cleaning output files:
|
||||
out/production/module/META-INF/module.kotlin_module
|
||||
out/production/module/UseKt.class
|
||||
End of files
|
||||
Compiling files:
|
||||
src/use.kt
|
||||
End of files
|
||||
COMPILATION FAILED
|
||||
'when' expression must be exhaustive or contain an 'else' branch
|
||||
|
||||
|
||||
Cleaning output files:
|
||||
out/production/module/Base$A.class
|
||||
out/production/module/Base$B.class
|
||||
out/production/module/Base$C.class
|
||||
out/production/module/Base.class
|
||||
End of files
|
||||
Compiling files:
|
||||
src/Base.kt
|
||||
src/use.kt
|
||||
End of files
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
import Base.*
|
||||
|
||||
fun use(x: Base): String =
|
||||
when (x) {
|
||||
is A -> "A"
|
||||
is B -> "B"
|
||||
}
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
import Base.*
|
||||
|
||||
fun use(x: Base): String =
|
||||
when (x) {
|
||||
is A -> "A"
|
||||
is B -> "B"
|
||||
is C -> "C"
|
||||
}
|
||||
Reference in New Issue
Block a user