[FE, IR] Check annotations on expect and actual enum entries
^KT-60668 ^KT-60936
This commit is contained in:
committed by
Space Team
parent
b57940a59b
commit
def4388c19
+6
@@ -758,6 +758,12 @@ public class FirOldFrontendMPPDiagnosticsWithLightTreeTestGenerated extends Abst
|
|||||||
runTest("compiler/testData/diagnostics/tests/multiplatform/annotationMatching/differentOrder.kt");
|
runTest("compiler/testData/diagnostics/tests/multiplatform/annotationMatching/differentOrder.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("enumEntries.kt")
|
||||||
|
public void testEnumEntries() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/multiplatform/annotationMatching/enumEntries.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestMetadata("fakeOverrides.kt")
|
@TestMetadata("fakeOverrides.kt")
|
||||||
public void testFakeOverrides() throws Exception {
|
public void testFakeOverrides() throws Exception {
|
||||||
|
|||||||
+6
@@ -758,6 +758,12 @@ public class FirOldFrontendMPPDiagnosticsWithPsiTestGenerated extends AbstractFi
|
|||||||
runTest("compiler/testData/diagnostics/tests/multiplatform/annotationMatching/differentOrder.kt");
|
runTest("compiler/testData/diagnostics/tests/multiplatform/annotationMatching/differentOrder.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("enumEntries.kt")
|
||||||
|
public void testEnumEntries() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/multiplatform/annotationMatching/enumEntries.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestMetadata("fakeOverrides.kt")
|
@TestMetadata("fakeOverrides.kt")
|
||||||
public void testFakeOverrides() throws Exception {
|
public void testFakeOverrides() throws Exception {
|
||||||
|
|||||||
+4
@@ -238,6 +238,10 @@ class FirExpectActualMatchingContextImpl private constructor(
|
|||||||
return asSymbol().fir.collectEnumEntries().map { it.name }
|
return asSymbol().fir.collectEnumEntries().map { it.name }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun RegularClassSymbolMarker.collectEnumEntries(): List<DeclarationSymbolMarker> {
|
||||||
|
return asSymbol().fir.collectEnumEntries().map { it.symbol }
|
||||||
|
}
|
||||||
|
|
||||||
override val CallableSymbolMarker.dispatchReceiverType: SimpleTypeMarker?
|
override val CallableSymbolMarker.dispatchReceiverType: SimpleTypeMarker?
|
||||||
get() = asSymbol().dispatchReceiverType
|
get() = asSymbol().dispatchReceiverType
|
||||||
override val CallableSymbolMarker.extensionReceiverType: KotlinTypeMarker?
|
override val CallableSymbolMarker.extensionReceiverType: KotlinTypeMarker?
|
||||||
|
|||||||
+4
@@ -267,6 +267,10 @@ internal abstract class IrExpectActualMatchingContext(
|
|||||||
return asIr().declarations.filterIsInstance<IrEnumEntry>().map { it.name }
|
return asIr().declarations.filterIsInstance<IrEnumEntry>().map { it.name }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun RegularClassSymbolMarker.collectEnumEntries(): List<DeclarationSymbolMarker> {
|
||||||
|
return asIr().declarations.filterIsInstance<IrEnumEntry>().map { it.symbol }
|
||||||
|
}
|
||||||
|
|
||||||
override val CallableSymbolMarker.dispatchReceiverType: KotlinTypeMarker?
|
override val CallableSymbolMarker.dispatchReceiverType: KotlinTypeMarker?
|
||||||
get() = (asIr().parent as? IrClass)?.defaultType
|
get() = (asIr().parent as? IrClass)?.defaultType
|
||||||
|
|
||||||
|
|||||||
+28
@@ -5,8 +5,10 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.resolve.calls.mpp
|
package org.jetbrains.kotlin.resolve.calls.mpp
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.descriptors.ClassKind
|
||||||
import org.jetbrains.kotlin.mpp.*
|
import org.jetbrains.kotlin.mpp.*
|
||||||
import org.jetbrains.kotlin.name.ClassId
|
import org.jetbrains.kotlin.name.ClassId
|
||||||
|
import org.jetbrains.kotlin.name.Name
|
||||||
import org.jetbrains.kotlin.name.StandardClassIds
|
import org.jetbrains.kotlin.name.StandardClassIds
|
||||||
import org.jetbrains.kotlin.resolve.checkers.OptInNames
|
import org.jetbrains.kotlin.resolve.checkers.OptInNames
|
||||||
import org.jetbrains.kotlin.resolve.multiplatform.ExpectActualCompatibility
|
import org.jetbrains.kotlin.resolve.multiplatform.ExpectActualCompatibility
|
||||||
@@ -80,6 +82,9 @@ object AbstractExpectActualAnnotationMatchChecker {
|
|||||||
if (checkClassScopesForAnnotationCompatibility) {
|
if (checkClassScopesForAnnotationCompatibility) {
|
||||||
checkAnnotationsInClassMemberScope(expectSymbol, actualSymbol)?.let { return it }
|
checkAnnotationsInClassMemberScope(expectSymbol, actualSymbol)?.let { return it }
|
||||||
}
|
}
|
||||||
|
if (expectSymbol.classKind == ClassKind.ENUM_CLASS && actualSymbol.classKind == ClassKind.ENUM_CLASS) {
|
||||||
|
checkAnnotationsOnEnumEntries(expectSymbol, actualSymbol)?.let { return it }
|
||||||
|
}
|
||||||
|
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
@@ -170,4 +175,27 @@ object AbstractExpectActualAnnotationMatchChecker {
|
|||||||
}
|
}
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
context (ExpectActualMatchingContext<*>)
|
||||||
|
private fun checkAnnotationsOnEnumEntries(
|
||||||
|
expectClassSymbol: RegularClassSymbolMarker,
|
||||||
|
actualClassSymbol: RegularClassSymbolMarker,
|
||||||
|
): Incompatibility? {
|
||||||
|
fun DeclarationSymbolMarker.getEnumEntryName(): Name =
|
||||||
|
when (this) {
|
||||||
|
is CallableSymbolMarker -> callableId.callableName
|
||||||
|
is RegularClassSymbolMarker -> classId.shortClassName
|
||||||
|
else -> error("Unexpected type $this")
|
||||||
|
}
|
||||||
|
|
||||||
|
val expectEnumEntries = expectClassSymbol.collectEnumEntries()
|
||||||
|
val actualEnumEntriesByName = actualClassSymbol.collectEnumEntries().associateBy { it.getEnumEntryName() }
|
||||||
|
|
||||||
|
for (expectEnumEntry in expectEnumEntries) {
|
||||||
|
val actualEnumEntry = actualEnumEntriesByName[expectEnumEntry.getEnumEntryName()] ?: continue
|
||||||
|
areAnnotationsSetOnDeclarationsCompatible(expectEnumEntry, actualEnumEntry)
|
||||||
|
?.let { return it }
|
||||||
|
}
|
||||||
|
return null
|
||||||
|
}
|
||||||
}
|
}
|
||||||
+1
@@ -111,6 +111,7 @@ interface ExpectActualMatchingContext<T : DeclarationSymbolMarker> : TypeSystemC
|
|||||||
fun RegularClassSymbolMarker.getMembersForExpectClass(name: Name): List<DeclarationSymbolMarker>
|
fun RegularClassSymbolMarker.getMembersForExpectClass(name: Name): List<DeclarationSymbolMarker>
|
||||||
|
|
||||||
fun RegularClassSymbolMarker.collectEnumEntryNames(): List<Name>
|
fun RegularClassSymbolMarker.collectEnumEntryNames(): List<Name>
|
||||||
|
fun RegularClassSymbolMarker.collectEnumEntries(): List<DeclarationSymbolMarker>
|
||||||
|
|
||||||
val CallableSymbolMarker.dispatchReceiverType: KotlinTypeMarker?
|
val CallableSymbolMarker.dispatchReceiverType: KotlinTypeMarker?
|
||||||
val CallableSymbolMarker.extensionReceiverType: KotlinTypeMarker?
|
val CallableSymbolMarker.extensionReceiverType: KotlinTypeMarker?
|
||||||
|
|||||||
+4
-1
@@ -176,11 +176,14 @@ class ClassicExpectActualMatchingContext(
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun RegularClassSymbolMarker.collectEnumEntryNames(): List<Name> {
|
override fun RegularClassSymbolMarker.collectEnumEntryNames(): List<Name> {
|
||||||
|
return collectEnumEntries().map { it.name }
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun RegularClassSymbolMarker.collectEnumEntries(): List<DeclarationDescriptor> {
|
||||||
return asDescriptor()
|
return asDescriptor()
|
||||||
.unsubstitutedMemberScope
|
.unsubstitutedMemberScope
|
||||||
.getDescriptorsFiltered()
|
.getDescriptorsFiltered()
|
||||||
.filter(DescriptorUtils::isEnumEntry)
|
.filter(DescriptorUtils::isEnumEntry)
|
||||||
.map { it.name }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override val CallableSymbolMarker.dispatchReceiverType: KotlinTypeMarker?
|
override val CallableSymbolMarker.dispatchReceiverType: KotlinTypeMarker?
|
||||||
|
|||||||
+15
@@ -0,0 +1,15 @@
|
|||||||
|
// MODULE: m1-common
|
||||||
|
// FILE: common.kt
|
||||||
|
annotation class Ann
|
||||||
|
|
||||||
|
<!INCOMPATIBLE_MATCHING{JVM}!>expect enum class E {
|
||||||
|
@Ann
|
||||||
|
FOO,
|
||||||
|
<!NO_ACTUAL_FOR_EXPECT{JVM}!>MISSING_ON_ACTUAL<!>
|
||||||
|
}<!>
|
||||||
|
|
||||||
|
// MODULE: m1-jvm()()(m1-common)
|
||||||
|
// FILE: jvm.kt
|
||||||
|
actual enum class <!ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT, ACTUAL_WITHOUT_EXPECT!>E<!> {
|
||||||
|
<!ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT!>FOO<!>
|
||||||
|
}
|
||||||
+15
@@ -0,0 +1,15 @@
|
|||||||
|
// MODULE: m1-common
|
||||||
|
// FILE: common.kt
|
||||||
|
annotation class Ann
|
||||||
|
|
||||||
|
expect enum class E {
|
||||||
|
@Ann
|
||||||
|
FOO,
|
||||||
|
MISSING_ON_ACTUAL
|
||||||
|
}
|
||||||
|
|
||||||
|
// MODULE: m1-jvm()()(m1-common)
|
||||||
|
// FILE: jvm.kt
|
||||||
|
actual enum class <!ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT, ACTUAL_WITHOUT_EXPECT!>E<!> {
|
||||||
|
FOO
|
||||||
|
}
|
||||||
Generated
+6
@@ -23527,6 +23527,12 @@ public class DiagnosticTestGenerated extends AbstractDiagnosticTest {
|
|||||||
runTest("compiler/testData/diagnostics/tests/multiplatform/annotationMatching/differentOrder.kt");
|
runTest("compiler/testData/diagnostics/tests/multiplatform/annotationMatching/differentOrder.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("enumEntries.kt")
|
||||||
|
public void testEnumEntries() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/multiplatform/annotationMatching/enumEntries.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestMetadata("fakeOverrides.kt")
|
@TestMetadata("fakeOverrides.kt")
|
||||||
public void testFakeOverrides() throws Exception {
|
public void testFakeOverrides() throws Exception {
|
||||||
|
|||||||
Reference in New Issue
Block a user