[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");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("enumEntries.kt")
|
||||
public void testEnumEntries() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/multiplatform/annotationMatching/enumEntries.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("fakeOverrides.kt")
|
||||
public void testFakeOverrides() throws Exception {
|
||||
|
||||
+6
@@ -758,6 +758,12 @@ public class FirOldFrontendMPPDiagnosticsWithPsiTestGenerated extends AbstractFi
|
||||
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
|
||||
@TestMetadata("fakeOverrides.kt")
|
||||
public void testFakeOverrides() throws Exception {
|
||||
|
||||
+4
@@ -238,6 +238,10 @@ class FirExpectActualMatchingContextImpl private constructor(
|
||||
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?
|
||||
get() = asSymbol().dispatchReceiverType
|
||||
override val CallableSymbolMarker.extensionReceiverType: KotlinTypeMarker?
|
||||
|
||||
+4
@@ -267,6 +267,10 @@ internal abstract class IrExpectActualMatchingContext(
|
||||
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?
|
||||
get() = (asIr().parent as? IrClass)?.defaultType
|
||||
|
||||
|
||||
+28
@@ -5,8 +5,10 @@
|
||||
|
||||
package org.jetbrains.kotlin.resolve.calls.mpp
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.ClassKind
|
||||
import org.jetbrains.kotlin.mpp.*
|
||||
import org.jetbrains.kotlin.name.ClassId
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.name.StandardClassIds
|
||||
import org.jetbrains.kotlin.resolve.checkers.OptInNames
|
||||
import org.jetbrains.kotlin.resolve.multiplatform.ExpectActualCompatibility
|
||||
@@ -80,6 +82,9 @@ object AbstractExpectActualAnnotationMatchChecker {
|
||||
if (checkClassScopesForAnnotationCompatibility) {
|
||||
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
|
||||
}
|
||||
@@ -170,4 +175,27 @@ object AbstractExpectActualAnnotationMatchChecker {
|
||||
}
|
||||
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.collectEnumEntryNames(): List<Name>
|
||||
fun RegularClassSymbolMarker.collectEnumEntries(): List<DeclarationSymbolMarker>
|
||||
|
||||
val CallableSymbolMarker.dispatchReceiverType: KotlinTypeMarker?
|
||||
val CallableSymbolMarker.extensionReceiverType: KotlinTypeMarker?
|
||||
|
||||
+4
-1
@@ -176,11 +176,14 @@ class ClassicExpectActualMatchingContext(
|
||||
}
|
||||
|
||||
override fun RegularClassSymbolMarker.collectEnumEntryNames(): List<Name> {
|
||||
return collectEnumEntries().map { it.name }
|
||||
}
|
||||
|
||||
override fun RegularClassSymbolMarker.collectEnumEntries(): List<DeclarationDescriptor> {
|
||||
return asDescriptor()
|
||||
.unsubstitutedMemberScope
|
||||
.getDescriptorsFiltered()
|
||||
.filter(DescriptorUtils::isEnumEntry)
|
||||
.map { it.name }
|
||||
}
|
||||
|
||||
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");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("enumEntries.kt")
|
||||
public void testEnumEntries() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/multiplatform/annotationMatching/enumEntries.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("fakeOverrides.kt")
|
||||
public void testFakeOverrides() throws Exception {
|
||||
|
||||
Reference in New Issue
Block a user