[FE 1.0] Deprecate declaration of expect and actual in the same module

^KT-40904 Fixed
^KT-55177 Fixed
This commit is contained in:
Dmitriy Novozhilov
2023-01-13 12:57:59 +02:00
committed by Space Team
parent 71a80c5e36
commit b09561c3c3
18 changed files with 120 additions and 9 deletions
@@ -21228,6 +21228,12 @@ public class DiagnosisCompilerTestFE10TestdataTestGenerated extends AbstractDiag
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/tests/multiplatform"), Pattern.compile("^(.+)\\.kt$"), Pattern.compile("^(.+)\\.(fir|ll)\\.kts?$"), true);
}
@Test
@TestMetadata("expectAndActualInSameModule.kt")
public void testExpectAndActualInSameModule() throws Exception {
runTest("compiler/testData/diagnostics/tests/multiplatform/expectAndActualInSameModule.kt");
}
@Test
@TestMetadata("expectDataObject.kt")
public void testExpectDataObject() throws Exception {
@@ -21234,6 +21234,12 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirDiagnosti
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/tests/multiplatform"), Pattern.compile("^(.*)\\.kts?$"), Pattern.compile("^(.+)\\.(fir|ll)\\.kts?$"), true);
}
@Test
@TestMetadata("expectAndActualInSameModule.kt")
public void testExpectAndActualInSameModule() throws Exception {
runTest("compiler/testData/diagnostics/tests/multiplatform/expectAndActualInSameModule.kt");
}
@Test
@TestMetadata("expectDataObject.kt")
public void testExpectDataObject() throws Exception {
@@ -21228,6 +21228,12 @@ public class FirOldFrontendDiagnosticsWithLightTreeTestGenerated extends Abstrac
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/tests/multiplatform"), Pattern.compile("^(.+)\\.kt$"), Pattern.compile("^(.+)\\.(fir|ll)\\.kts?$"), true);
}
@Test
@TestMetadata("expectAndActualInSameModule.kt")
public void testExpectAndActualInSameModule() throws Exception {
runTest("compiler/testData/diagnostics/tests/multiplatform/expectAndActualInSameModule.kt");
}
@Test
@TestMetadata("expectDataObject.kt")
public void testExpectDataObject() throws Exception {
@@ -805,6 +805,8 @@ public interface Errors {
DiagnosticFactory2.create(ERROR, ACTUAL_DECLARATION_NAME);
DiagnosticFactory0<KtNamedDeclaration> ACTUAL_MISSING = DiagnosticFactory0.create(ERROR, ACTUAL_DECLARATION_NAME);
DiagnosticFactory0<KtNamedDeclaration> EXPECT_AND_ACTUAL_IN_THE_SAME_MODULE = DiagnosticFactory0.create(WARNING, DECLARATION_NAME);
DiagnosticFactory0<PsiElement> OPTIONAL_EXPECTATION_NOT_ON_EXPECTED = DiagnosticFactory0.create(ERROR);
DiagnosticFactory0<PsiElement> OPTIONAL_DECLARATION_OUTSIDE_OF_ANNOTATION_ENTRY = DiagnosticFactory0.create(ERROR);
DiagnosticFactory0<PsiElement> OPTIONAL_DECLARATION_USAGE_IN_NON_COMMON_SOURCE = DiagnosticFactory0.create(ERROR);
@@ -339,6 +339,7 @@ public class DefaultErrorMessages {
MAP.put(NO_ACTUAL_CLASS_MEMBER_FOR_EXPECTED_CLASS, "Actual class ''{0}'' has no corresponding members for expected class members:{1}",
NAME, adaptGenerics2(IncompatibleExpectedActualClassScopesRenderer.TEXT));
MAP.put(ACTUAL_MISSING, "Declaration must be marked with 'actual'");
MAP.put(EXPECT_AND_ACTUAL_IN_THE_SAME_MODULE, "Expect and corresponding actual are declared in the same module, which will be prohibited in Kotlin 2.0. See https://youtrack.jetbrains.com/issue/KT-55177");
MAP.put(OPTIONAL_EXPECTATION_NOT_ON_EXPECTED, "'@OptionalExpectation' can only be used on an expected annotation class");
MAP.put(OPTIONAL_DECLARATION_OUTSIDE_OF_ANNOTATION_ENTRY, "Declaration annotated with '@OptionalExpectation' can only be used inside an annotation entry");
@@ -181,27 +181,46 @@ class ExpectedActualDeclarationChecker(
}
// Here we have exactly one compatible actual and/or some weakly incompatible. In either case, we don't report anything on expect...
val actualMembers = actuals.asSequence()
.filter { it.key.isCompatibleOrWeakCompatible() }.flatMap { it.value.asSequence() }
val actualMembers = actuals.filter { it.key.isCompatibleOrWeakCompatible() }.flatMap { it.value }
// ...except diagnostics regarding missing actual keyword, because in that case we won't start looking for the actual at all
if (checkActualModifier) {
actualMembers.forEach { reportMissingActualModifier(it, reportOn = null, trace) }
}
reportExpectAndActualInTheSameModule(reportOn, actualMembers, trace)
expectActualTracker.reportExpectActual(expected = expectDescriptor, actualMembers = actualMembers)
}
private fun reportMissingActualModifier(actual: MemberDescriptor, reportOn: KtNamedDeclaration?, trace: BindingTrace) {
if (actual.isActual) return
@Suppress("NAME_SHADOWING")
val reportOn = reportOn ?: (actual.source as? KotlinSourceElement)?.psi as? KtNamedDeclaration ?: return
val reportOn = reportOn ?: actual.declarationSource ?: return
if (requireActualModifier(actual)) {
trace.report(Errors.ACTUAL_MISSING.on(reportOn))
}
}
private val MemberDescriptor.declarationSource: KtNamedDeclaration?
get() = (this.source as? KotlinSourceElement)?.psi as? KtNamedDeclaration
private fun reportExpectAndActualInTheSameModule(
expectSource: KtNamedDeclaration,
actualMembers: List<MemberDescriptor>,
trace: BindingTrace
) {
if (expectSource.containingKtFile.isCommonSource == true) return
val actualMembersWithModifier = actualMembers.filter { it.isActual }
if (actualMembersWithModifier.isEmpty()) return
trace.report(Errors.EXPECT_AND_ACTUAL_IN_THE_SAME_MODULE.on(expectSource))
for (actual in actualMembersWithModifier) {
val actualSource = actual.declarationSource ?: continue
trace.report(Errors.EXPECT_AND_ACTUAL_IN_THE_SAME_MODULE.on(actualSource))
}
}
private fun MemberDescriptor.hasNoActualWithDiagnostic(
compatibility: Map<ExpectActualCompatibility<MemberDescriptor>, List<MemberDescriptor>>
): Boolean {
@@ -211,7 +230,7 @@ class ExpectedActualDeclarationChecker(
}
}
private fun ExpectActualTracker.reportExpectActual(expected: MemberDescriptor, actualMembers: Sequence<MemberDescriptor>) {
private fun ExpectActualTracker.reportExpectActual(expected: MemberDescriptor, actualMembers: List<MemberDescriptor>) {
if (this is ExpectActualTracker.DoNothing) return
val expectedFile = sourceFile(expected) ?: return
@@ -1,3 +1,5 @@
@file:Suppress("EXPECT_AND_ACTUAL_IN_THE_SAME_MODULE")
package test
@Suppress("INLINE_CLASS_DEPRECATED", "EXPERIMENTAL_FEATURE_WARNING")
@@ -1,3 +1,5 @@
@file:Suppress("EXPECT_AND_ACTUAL_IN_THE_SAME_MODULE")
package test
@kotlin.jvm.JvmInline
@@ -0,0 +1,10 @@
// !LANGUAGE: +MultiPlatformProjects
// SKIP_TXT
// Issue: KT-49714
expect class Counter {
operator fun inc(): Counter
operator fun dec(): Counter
}
actual typealias Counter = Int
@@ -1,11 +1,10 @@
// FIR_IDENTICAL
// !LANGUAGE: +MultiPlatformProjects
// SKIP_TXT
// Issue: KT-49714
expect class Counter {
expect <!EXPECT_AND_ACTUAL_IN_THE_SAME_MODULE!>class Counter<!> {
operator fun inc(): Counter
operator fun dec(): Counter
}
actual typealias Counter = Int
actual typealias <!EXPECT_AND_ACTUAL_IN_THE_SAME_MODULE!>Counter<!> = Int
@@ -0,0 +1,17 @@
// ISSUE: KT-40904, KT-55177
expect class Foo {
fun memberFun()
val memberProp: Int
}
actual class Foo {
<!ACTUAL_WITHOUT_EXPECT!>actual fun memberFun() {}<!>
<!ACTUAL_WITHOUT_EXPECT!>actual val memberProp: Int = 10<!>
}
expect fun foo()
<!ACTUAL_WITHOUT_EXPECT!>actual fun foo() {}<!>
expect val x: String
<!ACTUAL_WITHOUT_EXPECT!>actual val x: String
get() = "hello"<!>
@@ -0,0 +1,17 @@
// ISSUE: KT-40904, KT-55177
expect <!EXPECT_AND_ACTUAL_IN_THE_SAME_MODULE!>class Foo<!> {
fun memberFun()
val memberProp: Int
}
actual <!EXPECT_AND_ACTUAL_IN_THE_SAME_MODULE!>class Foo<!> {
actual fun memberFun() {}
actual val memberProp: Int = 10
}
expect fun <!EXPECT_AND_ACTUAL_IN_THE_SAME_MODULE!>foo<!>()
actual fun <!EXPECT_AND_ACTUAL_IN_THE_SAME_MODULE!>foo<!>() {}
expect val <!EXPECT_AND_ACTUAL_IN_THE_SAME_MODULE!>x<!>: String
actual val <!EXPECT_AND_ACTUAL_IN_THE_SAME_MODULE!>x<!>: String
get() = "hello"
@@ -0,0 +1,14 @@
package
public actual val x: kotlin.String
public actual fun foo(): kotlin.Unit
public final actual class Foo {
public constructor Foo()
public actual final val memberProp: kotlin.Int = 10
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 final actual fun memberFun(): kotlin.Unit
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
@@ -21234,6 +21234,12 @@ public class DiagnosticTestGenerated extends AbstractDiagnosticTest {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/tests/multiplatform"), Pattern.compile("^(.*)\\.kts?$"), Pattern.compile("^(.+)\\.(fir|ll)\\.kts?$"), true);
}
@Test
@TestMetadata("expectAndActualInSameModule.kt")
public void testExpectAndActualInSameModule() throws Exception {
runTest("compiler/testData/diagnostics/tests/multiplatform/expectAndActualInSameModule.kt");
}
@Test
@TestMetadata("expectDataObject.kt")
public void testExpectDataObject() throws Exception {
@@ -2,6 +2,7 @@
* Copyright 2010-2018 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
@file:Suppress("EXPECT_AND_ACTUAL_IN_THE_SAME_MODULE")
package test.collections.js
+2 -1
View File
@@ -2,6 +2,7 @@
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
@file:Suppress("EXPECT_AND_ACTUAL_IN_THE_SAME_MODULE")
package test
@@ -33,4 +34,4 @@ public expect object BackReferenceHandling {
val nonExistentGroup: HandlingOption
val nonExistentNamedGroup: HandlingOption
val groupZero: HandlingOption
}
}
+1
View File
@@ -2,6 +2,7 @@
* Copyright 2010-2018 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
@file:Suppress("EXPECT_AND_ACTUAL_IN_THE_SAME_MODULE")
package test.collections.js
+2 -1
View File
@@ -2,6 +2,7 @@
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
@file:Suppress("EXPECT_AND_ACTUAL_IN_THE_SAME_MODULE")
package test
@@ -38,4 +39,4 @@ public actual object BackReferenceHandling {
actual val nonExistentGroup: HandlingOption = HandlingOption.MATCH_NOTHING
actual val nonExistentNamedGroup: HandlingOption = HandlingOption.THROW
actual val groupZero: HandlingOption = HandlingOption.THROW
}
}