[FE] Prohibit protected members in final expected or actual classes

^KT-28850 Fixed
This commit is contained in:
Roman Efremov
2023-04-05 15:07:08 +02:00
committed by Space Team
parent 2f5b1dff16
commit b368b78faa
8 changed files with 107 additions and 4 deletions
@@ -21232,6 +21232,12 @@ public class DiagnosticCompilerTestFE10TestdataTestGenerated extends AbstractDia
runTest("compiler/testData/diagnostics/tests/modifiers/protected.kt");
}
@Test
@TestMetadata("protectedInExpectActual.kt")
public void testProtectedInExpectActual() throws Exception {
runTest("compiler/testData/diagnostics/tests/modifiers/protectedInExpectActual.kt");
}
@Test
@TestMetadata("redundantTargets.kt")
public void testRedundantTargets() throws Exception {
@@ -21232,6 +21232,12 @@ public class LLFirPreresolvedReversedDiagnosticCompilerFE10TestDataTestGenerated
runTest("compiler/testData/diagnostics/tests/modifiers/protected.kt");
}
@Test
@TestMetadata("protectedInExpectActual.kt")
public void testProtectedInExpectActual() throws Exception {
runTest("compiler/testData/diagnostics/tests/modifiers/protectedInExpectActual.kt");
}
@Test
@TestMetadata("redundantTargets.kt")
public void testRedundantTargets() throws Exception {
@@ -21232,6 +21232,12 @@ public class FirLightTreeOldFrontendDiagnosticsTestGenerated extends AbstractFir
runTest("compiler/testData/diagnostics/tests/modifiers/protected.kt");
}
@Test
@TestMetadata("protectedInExpectActual.kt")
public void testProtectedInExpectActual() throws Exception {
runTest("compiler/testData/diagnostics/tests/modifiers/protectedInExpectActual.kt");
}
@Test
@TestMetadata("redundantTargets.kt")
public void testRedundantTargets() throws Exception {
@@ -21238,6 +21238,12 @@ public class FirPsiOldFrontendDiagnosticsTestGenerated extends AbstractFirPsiDia
runTest("compiler/testData/diagnostics/tests/modifiers/protected.kt");
}
@Test
@TestMetadata("protectedInExpectActual.kt")
public void testProtectedInExpectActual() throws Exception {
runTest("compiler/testData/diagnostics/tests/modifiers/protectedInExpectActual.kt");
}
@Test
@TestMetadata("redundantTargets.kt")
public void testRedundantTargets() throws Exception {
@@ -22,9 +22,7 @@ import org.jetbrains.kotlin.diagnostics.KtDiagnosticFactory2
import org.jetbrains.kotlin.diagnostics.reportOn
import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.declarations.impl.FirPrimaryConstructor
import org.jetbrains.kotlin.fir.declarations.utils.isCompanion
import org.jetbrains.kotlin.fir.declarations.utils.isInner
import org.jetbrains.kotlin.fir.declarations.utils.isLocal
import org.jetbrains.kotlin.fir.declarations.utils.*
import org.jetbrains.kotlin.fir.languageVersionSettings
import org.jetbrains.kotlin.lexer.KtModifierKeywordToken
import org.jetbrains.kotlin.lexer.KtTokens
@@ -85,7 +83,7 @@ object FirModifierChecker : FirBasicDeclarationChecker() {
val modifier = secondModifier.token
when {
!checkTarget(modifierSource, modifier, actualTargets, parent, context, reporter) -> reportedNodes += secondModifier
!checkParent(modifierSource, modifier, actualParents, context, reporter) -> reportedNodes += secondModifier
!checkParent(modifierSource, modifier, actualParents, parent, context, reporter) -> reportedNodes += secondModifier
}
}
}
@@ -236,6 +234,7 @@ object FirModifierChecker : FirBasicDeclarationChecker() {
modifierSource: KtSourceElement,
modifierToken: KtModifierKeywordToken,
actualParents: List<KotlinTarget>,
parent: FirDeclaration?,
context: CheckerContext,
reporter: DiagnosticReporter
): Boolean {
@@ -251,6 +250,15 @@ object FirModifierChecker : FirBasicDeclarationChecker() {
return true
}
if (modifierToken == KtTokens.PROTECTED_KEYWORD && isFinalExpectOrActualClass(parent)) {
reporter.reportOn(
modifierSource,
FirErrors.WRONG_MODIFIER_CONTAINING_DECLARATION,
modifierToken,
"final expect or actual class",
context,
)
}
val possibleParentPredicate = possibleParentTargetPredicateMap[modifierToken] ?: return true
if (actualParents.any { possibleParentPredicate.isAllowed(it, context.session.languageVersionSettings) }) return true
@@ -268,4 +276,8 @@ object FirModifierChecker : FirBasicDeclarationChecker() {
private fun List<KotlinTarget>.firstOrThis(): String {
return firstOrNull()?.description ?: "this"
}
private fun isFinalExpectOrActualClass(d: FirDeclaration?): Boolean {
return d is FirClass && d.isFinal && (d.isExpect || d.isActual)
}
}
@@ -180,6 +180,15 @@ object ModifierCheckerCore {
)
return true
}
if (modifier == PROTECTED_KEYWORD && isFinalExpectOrActualClass(parentDescriptor)) {
trace.report(
Errors.WRONG_MODIFIER_CONTAINING_DECLARATION.on(
node.psi,
modifier,
"final expect or actual class"
)
)
}
val possibleParentPredicate = possibleParentTargetPredicateMap[modifier] ?: return true
if (actualParents.any { possibleParentPredicate.isAllowed(it, languageVersionSettings) }) return true
trace.report(
@@ -237,4 +246,8 @@ object ModifierCheckerCore {
return true
}
private fun isFinalExpectOrActualClass(d: DeclarationDescriptor?): Boolean {
return d is ClassDescriptor && d.isFinalOrEnum && (d.isExpect || d.isActual)
}
}
@@ -0,0 +1,48 @@
// LANGUAGE: +MultiPlatformProjects
// !DIAGNOSTICS: -NO_ACTUAL_FOR_EXPECT, -ACTUAL_WITHOUT_EXPECT
// FIR_IDENTICAL
class SimpleClass {
protected fun foo() = Unit
}
expect class ExpClass {
<!WRONG_MODIFIER_CONTAINING_DECLARATION!>protected<!> fun foo()
<!WRONG_MODIFIER_CONTAINING_DECLARATION!>protected<!> val bar: Int
}
actual class ActClass {
actual <!WRONG_MODIFIER_CONTAINING_DECLARATION!>protected<!> fun foo() = Unit
actual <!WRONG_MODIFIER_CONTAINING_DECLARATION!>protected<!> val bar: Int = 42
}
expect open class ExpOpenClass {
protected fun foo()
}
actual open class ActOpenClass {
actual protected fun foo() = Unit
}
enum class SimpleEnum {
ENTRY;
protected fun foo() = Unit
}
expect enum class ExpEnumClass {
ENTRY;
<!WRONG_MODIFIER_CONTAINING_DECLARATION!>protected<!> fun foo()
<!WRONG_MODIFIER_CONTAINING_DECLARATION!>protected<!> val bar: Int
}
actual enum class ActEnumClass {
ENTRY;
actual <!WRONG_MODIFIER_CONTAINING_DECLARATION!>protected<!> fun foo() = Unit
<!WRONG_MODIFIER_CONTAINING_DECLARATION!>protected<!> val bar: Int = 42
}
@@ -21238,6 +21238,12 @@ public class DiagnosticTestGenerated extends AbstractDiagnosticTest {
runTest("compiler/testData/diagnostics/tests/modifiers/protected.kt");
}
@Test
@TestMetadata("protectedInExpectActual.kt")
public void testProtectedInExpectActual() throws Exception {
runTest("compiler/testData/diagnostics/tests/modifiers/protectedInExpectActual.kt");
}
@Test
@TestMetadata("redundantTargets.kt")
public void testRedundantTargets() throws Exception {