[FE] Support sealed classes and interfaces from java
KT-43551 KT-41215
This commit is contained in:
committed by
TeamCityServer
parent
bdfb71b149
commit
7897bb6adb
Vendored
+44
@@ -0,0 +1,44 @@
|
|||||||
|
// !DIAGNOSTICS: -UNUSED_VARIABLE
|
||||||
|
// ISSUE: KT-41215, KT-43551
|
||||||
|
|
||||||
|
// FILE: Base.java
|
||||||
|
public sealed class Base permits A, B {}
|
||||||
|
|
||||||
|
// FILE: A.java
|
||||||
|
public final class A extends Base {}
|
||||||
|
|
||||||
|
// FILE: B.java
|
||||||
|
public sealed class B extends Base permits B.C, B.D {
|
||||||
|
public static final class C implements B {}
|
||||||
|
|
||||||
|
public static non-sealed class D extends B {}
|
||||||
|
}
|
||||||
|
|
||||||
|
// FILE: main.kt
|
||||||
|
fun test_ok_1(base: Base) {
|
||||||
|
val x = when (base) {
|
||||||
|
is A -> 1
|
||||||
|
is B -> 2
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun test_ok_2(base: Base) {
|
||||||
|
val x = when (base) {
|
||||||
|
is A -> 1
|
||||||
|
is B.C -> 2
|
||||||
|
is B.D -> 3
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun test_error_1(base: Base) {
|
||||||
|
val x = <!NO_ELSE_IN_WHEN!>when<!> (base) {
|
||||||
|
is A -> 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun test_error_2(base: Base) {
|
||||||
|
val x = <!NO_ELSE_IN_WHEN!>when<!> (base) {
|
||||||
|
is A -> 1
|
||||||
|
is B.C -> 2
|
||||||
|
}
|
||||||
|
}
|
||||||
Vendored
+41
@@ -0,0 +1,41 @@
|
|||||||
|
package
|
||||||
|
|
||||||
|
public fun test_error_1(/*0*/ base: Base): kotlin.Unit
|
||||||
|
public fun test_error_2(/*0*/ base: Base): kotlin.Unit
|
||||||
|
public fun test_ok_1(/*0*/ base: Base): kotlin.Unit
|
||||||
|
public fun test_ok_2(/*0*/ base: Base): kotlin.Unit
|
||||||
|
|
||||||
|
public final class A : Base {
|
||||||
|
public constructor A()
|
||||||
|
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
|
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||||
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
}
|
||||||
|
|
||||||
|
public sealed class B : Base {
|
||||||
|
public constructor B()
|
||||||
|
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
|
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||||
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
|
||||||
|
public final class C : B {
|
||||||
|
public constructor C()
|
||||||
|
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
|
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||||
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
}
|
||||||
|
|
||||||
|
public open class D : B {
|
||||||
|
public constructor D()
|
||||||
|
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
|
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||||
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public sealed class Base {
|
||||||
|
public constructor Base()
|
||||||
|
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
|
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||||
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
}
|
||||||
Vendored
+64
@@ -0,0 +1,64 @@
|
|||||||
|
// !DIAGNOSTICS: -UNUSED_VARIABLE
|
||||||
|
// ISSUE: KT-41215, KT-43551
|
||||||
|
|
||||||
|
// FILE: Base.java
|
||||||
|
public sealed interface Base permits A, B, E {}
|
||||||
|
|
||||||
|
// FILE: A.java
|
||||||
|
public non-sealed interface A extends Base {}
|
||||||
|
|
||||||
|
// FILE: B.java
|
||||||
|
public sealed interface B extends Base permits B.C, B.D {
|
||||||
|
public static final class C implements B {}
|
||||||
|
|
||||||
|
public static non-sealed interface D extends B {}
|
||||||
|
}
|
||||||
|
|
||||||
|
// FILE: E.java
|
||||||
|
public enum E implements Base {
|
||||||
|
First, Second
|
||||||
|
}
|
||||||
|
|
||||||
|
// FILE: main.kt
|
||||||
|
fun test_ok_1(base: Base) {
|
||||||
|
val x = when (base) {
|
||||||
|
is A -> 1
|
||||||
|
is B -> 2
|
||||||
|
is E -> 3
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun test_ok_2(base: Base) {
|
||||||
|
val x = when (base) {
|
||||||
|
is A -> 1
|
||||||
|
is B.C -> 2
|
||||||
|
is B.D -> 3
|
||||||
|
E.First -> 4
|
||||||
|
E.Second -> 5
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun test_error_1(base: Base) {
|
||||||
|
val x = <!NO_ELSE_IN_WHEN!>when<!> (base) {
|
||||||
|
is A -> 1
|
||||||
|
is B -> 2
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun test_error_2(base: Base) {
|
||||||
|
val x = <!NO_ELSE_IN_WHEN!>when<!> (base) {
|
||||||
|
is A -> 1
|
||||||
|
is B.C -> 2
|
||||||
|
is B.D -> 3
|
||||||
|
E.Second -> 5
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun test_error_3(base: Base) {
|
||||||
|
val x = <!NO_ELSE_IN_WHEN!>when<!> (base) {
|
||||||
|
is A -> 1
|
||||||
|
is B.C -> 2
|
||||||
|
E.First -> 4
|
||||||
|
E.Second -> 5
|
||||||
|
}
|
||||||
|
}
|
||||||
Vendored
+60
@@ -0,0 +1,60 @@
|
|||||||
|
package
|
||||||
|
|
||||||
|
public fun test_error_1(/*0*/ base: Base): kotlin.Unit
|
||||||
|
public fun test_error_2(/*0*/ base: Base): kotlin.Unit
|
||||||
|
public fun test_error_3(/*0*/ base: Base): kotlin.Unit
|
||||||
|
public fun test_ok_1(/*0*/ base: Base): kotlin.Unit
|
||||||
|
public fun test_ok_2(/*0*/ base: Base): kotlin.Unit
|
||||||
|
|
||||||
|
public interface A : Base {
|
||||||
|
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
|
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||||
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
}
|
||||||
|
|
||||||
|
public sealed interface B : Base {
|
||||||
|
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
|
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||||
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
|
||||||
|
public final class C : B {
|
||||||
|
public constructor C()
|
||||||
|
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
|
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||||
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface D : B {
|
||||||
|
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
|
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||||
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public sealed interface Base {
|
||||||
|
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
|
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||||
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
}
|
||||||
|
|
||||||
|
public final enum class E : kotlin.Enum<E!>, Base {
|
||||||
|
enum entry First
|
||||||
|
|
||||||
|
enum entry Second
|
||||||
|
|
||||||
|
public constructor E()
|
||||||
|
public final override /*1*/ /*fake_override*/ val name: kotlin.String
|
||||||
|
public final override /*1*/ /*fake_override*/ val ordinal: kotlin.Int
|
||||||
|
protected final override /*1*/ /*fake_override*/ fun clone(): kotlin.Any
|
||||||
|
public final override /*1*/ /*fake_override*/ fun compareTo(/*0*/ other: E!): kotlin.Int
|
||||||
|
@kotlin.Deprecated(level = DeprecationLevel.WARNING, message = "This member is not fully supported by Kotlin compiler, so it may be absent or have different signature in next major version", replaceWith = kotlin.ReplaceWith(expression = "", imports = {})) public final override /*1*/ /*fake_override*/ fun describeConstable(): java.util.Optional<java.lang.Enum.EnumDesc<E!>!>!
|
||||||
|
public final override /*2*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
|
protected/*protected and package*/ final override /*1*/ /*fake_override*/ /*isHiddenForResolutionEverywhereBesideSupercalls*/ fun finalize(): kotlin.Unit
|
||||||
|
public final override /*1*/ /*fake_override*/ /*isHiddenForResolutionEverywhereBesideSupercalls*/ fun getDeclaringClass(): java.lang.Class<E!>!
|
||||||
|
public final override /*2*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||||
|
public open override /*2*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
|
||||||
|
// Static members
|
||||||
|
public final /*synthesized*/ fun valueOf(/*0*/ value: kotlin.String): E
|
||||||
|
public final /*synthesized*/ fun values(): kotlin.Array<E>
|
||||||
|
}
|
||||||
+33
@@ -70,4 +70,37 @@ public class DiagnosticsWithJdk15TestGenerated extends AbstractDiagnosticsWithJd
|
|||||||
runTest("compiler/testData/diagnostics/testsWithJava15/jvmRecord/supertypesCheck.kt");
|
runTest("compiler/testData/diagnostics/testsWithJava15/jvmRecord/supertypesCheck.kt");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("compiler/testData/diagnostics/testsWithJava15/sealedClasses")
|
||||||
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
|
@RunWith(JUnit3RunnerWithInners.class)
|
||||||
|
public static class SealedClasses extends AbstractDiagnosticsWithJdk15Test {
|
||||||
|
private void runTest(String testDataFilePath) throws Exception {
|
||||||
|
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testAllFilesPresentInSealedClasses() throws Exception {
|
||||||
|
KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/testsWithJava15/sealedClasses"), Pattern.compile("^(.+)\\.kt$"), null, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("javaSealedClassExhaustiveness.kt")
|
||||||
|
public void testJavaSealedClassExhaustiveness() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/testsWithJava15/sealedClasses/javaSealedClassExhaustiveness.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("javaSealedInterfaceExhaustiveness.kt")
|
||||||
|
public void testJavaSealedInterfaceExhaustiveness() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/testsWithJava15/sealedClasses/javaSealedInterfaceExhaustiveness.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("kotlinInheritsJavaClass.kt")
|
||||||
|
public void testKotlinInheritsJavaClass() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/testsWithJava15/sealedClasses/kotlinInheritsJavaClass.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("kotlinInheritsJavaInterface.kt")
|
||||||
|
public void testKotlinInheritsJavaInterface() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/testsWithJava15/sealedClasses/kotlinInheritsJavaInterface.kt");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,12 +15,13 @@ enum class Modality {
|
|||||||
ABSTRACT;
|
ABSTRACT;
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
fun convertFromFlags(sealed: Boolean, abstract: Boolean, open: Boolean): Modality {
|
||||||
// NB: never returns SEALED
|
return when {
|
||||||
fun convertFromFlags(abstract: Boolean, open: Boolean): Modality {
|
sealed -> SEALED
|
||||||
if (abstract) return ABSTRACT
|
abstract -> ABSTRACT
|
||||||
if (open) return OPEN
|
open -> OPEN
|
||||||
return FINAL
|
else -> FINAL
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+9
-2
@@ -76,7 +76,7 @@ class LazyJavaClassDescriptor(
|
|||||||
|
|
||||||
private val modality =
|
private val modality =
|
||||||
if (jClass.isAnnotationType || jClass.isEnum) Modality.FINAL
|
if (jClass.isAnnotationType || jClass.isEnum) Modality.FINAL
|
||||||
else Modality.convertFromFlags(jClass.isAbstract || jClass.isInterface, !jClass.isFinal)
|
else Modality.convertFromFlags(jClass.isSealed, jClass.isAbstract || jClass.isInterface, !jClass.isFinal)
|
||||||
|
|
||||||
private val visibility = jClass.visibility
|
private val visibility = jClass.visibility
|
||||||
private val isInner = jClass.outerClass != null && !jClass.isStatic
|
private val isInner = jClass.outerClass != null && !jClass.isStatic
|
||||||
@@ -180,7 +180,14 @@ class LazyJavaClassDescriptor(
|
|||||||
fun wasScopeContentRequested() =
|
fun wasScopeContentRequested() =
|
||||||
getUnsubstitutedMemberScope().wasContentRequested() || staticScope.wasContentRequested()
|
getUnsubstitutedMemberScope().wasContentRequested() || staticScope.wasContentRequested()
|
||||||
|
|
||||||
override fun getSealedSubclasses(): Collection<ClassDescriptor> = emptyList()
|
override fun getSealedSubclasses(): Collection<ClassDescriptor> = if (modality == Modality.SEALED) {
|
||||||
|
val attributes = TypeUsage.COMMON.toAttributes()
|
||||||
|
jClass.permittedTypes.mapNotNull {
|
||||||
|
c.typeResolver.transformJavaType(it, attributes).constructor.declarationDescriptor as? ClassDescriptor
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
emptyList()
|
||||||
|
}
|
||||||
|
|
||||||
override fun toString() = "Lazy Java class ${this.fqNameUnsafe}"
|
override fun toString() = "Lazy Java class ${this.fqNameUnsafe}"
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -515,7 +515,7 @@ class LazyJavaClassMemberScope(
|
|||||||
returnType,
|
returnType,
|
||||||
// Those functions are generated as open in bytecode
|
// Those functions are generated as open in bytecode
|
||||||
// Actually, it should not be important because the class is final anyway, but leaving them open is convenient for consistency
|
// Actually, it should not be important because the class is final anyway, but leaving them open is convenient for consistency
|
||||||
Modality.convertFromFlags(abstract = false, open = true),
|
Modality.convertFromFlags(sealed = false, abstract = false, open = true),
|
||||||
DescriptorVisibilities.PUBLIC,
|
DescriptorVisibilities.PUBLIC,
|
||||||
null,
|
null,
|
||||||
)
|
)
|
||||||
|
|||||||
+1
-1
@@ -181,7 +181,7 @@ abstract class LazyJavaScope(
|
|||||||
effectiveSignature.typeParameters,
|
effectiveSignature.typeParameters,
|
||||||
effectiveSignature.valueParameters,
|
effectiveSignature.valueParameters,
|
||||||
effectiveSignature.returnType,
|
effectiveSignature.returnType,
|
||||||
Modality.convertFromFlags(method.isAbstract, !method.isFinal),
|
Modality.convertFromFlags(sealed = false, method.isAbstract, !method.isFinal),
|
||||||
method.visibility.toDescriptorVisibility(),
|
method.visibility.toDescriptorVisibility(),
|
||||||
if (effectiveSignature.receiverType != null)
|
if (effectiveSignature.receiverType != null)
|
||||||
mapOf(JavaMethodDescriptor.ORIGINAL_VALUE_PARAMETER_FOR_EXTENSION_RECEIVER to valueParameters.descriptors.first())
|
mapOf(JavaMethodDescriptor.ORIGINAL_VALUE_PARAMETER_FOR_EXTENSION_RECEIVER to valueParameters.descriptors.first())
|
||||||
|
|||||||
Reference in New Issue
Block a user