[FIR] KT-54507: Report redundant for abstract interfaces

^KT-54507 Fixed

Merge-request: KT-MR-8490
Merged-by: Nikolay Lunyak <Nikolay.Lunyak@jetbrains.com>
This commit is contained in:
Nikolay Lunyak
2023-01-30 16:45:20 +00:00
committed by Space Team
parent 7ef7d0e062
commit 5994a99dbb
4 changed files with 41 additions and 25 deletions
@@ -83,6 +83,9 @@ FILE: RedundantModalityModifierChecker.kt
public open override val gav: R|kotlin/Int| = Int(13)
public get(): R|kotlin/Int|
private final fun fan(): R|kotlin/Unit| {
}
}
public final class Final : R|kotlin/Any| {
public constructor(): R|Final| {
@@ -136,3 +139,15 @@ FILE: RedundantModalityModifierChecker.kt
}
public open interface OpenInterface : R|kotlin/Any| {
}
public final class FinalDerived2 : R|Base| {
public constructor(gav: R|kotlin/Int|): R|FinalDerived2| {
super<R|Base|>()
}
public final override val gav: R|kotlin/Int| = R|<local>/gav|
public get(): R|kotlin/Int|
public open override fun bar(): R|kotlin/Unit| {
}
}
@@ -55,6 +55,8 @@ open class OpenDerived : Base() {
override final fun bar() {}
// Redundant open
override <!REDUNDANT_MODALITY_MODIFIER!>open<!> val gav = 13
private <!REDUNDANT_MODALITY_MODIFIER!>final<!> fun fan() {}
}
// Redundant final
<!REDUNDANT_MODALITY_MODIFIER!>final<!> class Final
@@ -78,8 +80,12 @@ abstract class AbstractDerived2 : Interface {
override <!REDUNDANT_MODALITY_MODIFIER!>open<!> val gav = 13
}
// Redundant abstract interface
abstract interface AbstractInterface
<!REDUNDANT_MODALITY_MODIFIER!>abstract<!> interface AbstractInterface
// Redundant final object
<!REDUNDANT_MODALITY_MODIFIER!>final<!> object FinalObject
// Open interface
<!REDUNDANT_MODIFIER_FOR_TARGET!>open<!> interface OpenInterface
class FinalDerived2(override <!REDUNDANT_MODALITY_MODIFIER!>final<!> val gav: Int) : Base() {
override fun bar() {}
}
@@ -34,7 +34,6 @@ import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
import org.jetbrains.kotlin.fir.symbols.SymbolInternals
import org.jetbrains.kotlin.fir.symbols.impl.*
import org.jetbrains.kotlin.fir.types.*
import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.name.*
import org.jetbrains.kotlin.psi.KtParameter
import org.jetbrains.kotlin.psi.KtParameter.VAL_VAR_TOKEN_SET
@@ -225,32 +224,23 @@ fun FirClass.modality(): Modality? {
* returns implicit modality by FirMemberDeclaration<*>
*/
fun FirMemberDeclaration.implicitModality(context: CheckerContext): Modality {
if (this is FirRegularClass && (this.classKind == ClassKind.CLASS || this.classKind == ClassKind.OBJECT)) {
if (this.classKind == ClassKind.INTERFACE) return Modality.ABSTRACT
return Modality.FINAL
}
val klass = context.findClosestClassOrObject() ?: return Modality.FINAL
val source = source ?: return Modality.FINAL
val tree = source.treeStructure
if (tree.overrideModifier(source.lighterASTNode) != null) {
val klassModalityTokenType = klass.source?.let { tree.modalityModifier(it.lighterASTNode)?.tokenType }
if (klassModalityTokenType == KtTokens.ABSTRACT_KEYWORD ||
klassModalityTokenType == KtTokens.OPEN_KEYWORD ||
klassModalityTokenType == KtTokens.SEALED_KEYWORD
) {
return Modality.OPEN
if (this is FirRegularClass) {
return when (classKind) {
ClassKind.INTERFACE -> Modality.ABSTRACT
else -> Modality.FINAL
}
}
if (klass is FirRegularClass
&& klass.classKind == ClassKind.INTERFACE
&& tree.visibilityModifier(source.lighterASTNode)?.tokenType != KtTokens.PRIVATE_KEYWORD
) {
return if (this.hasBody()) Modality.OPEN else Modality.ABSTRACT
}
val containingClass = context.findClosestClassOrObject() ?: return Modality.FINAL
return Modality.FINAL
return when {
isOverride && !containingClass.isFinal -> Modality.OPEN
containingClass.isInterface -> when {
hasBody() -> Modality.OPEN
else -> Modality.ABSTRACT
}
else -> Modality.FINAL
}
}
private fun FirDeclaration.hasBody(): Boolean = when (this) {
@@ -6,6 +6,7 @@
package org.jetbrains.kotlin.fir.analysis.checkers.extended
import org.jetbrains.kotlin.KtFakeSourceElementKind
import org.jetbrains.kotlin.KtRealSourceElementKind
import org.jetbrains.kotlin.KtSourceElement
import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.descriptors.Modality
@@ -19,13 +20,17 @@ import org.jetbrains.kotlin.diagnostics.reportOn
import org.jetbrains.kotlin.fir.declarations.FirClass
import org.jetbrains.kotlin.fir.declarations.FirDeclaration
import org.jetbrains.kotlin.fir.declarations.FirMemberDeclaration
import org.jetbrains.kotlin.fir.declarations.FirValueParameter
import org.jetbrains.kotlin.fir.declarations.utils.modality
import org.jetbrains.kotlin.psi.KtDeclaration
object RedundantModalityModifierSyntaxChecker : FirDeclarationSyntaxChecker<FirDeclaration, KtDeclaration>() {
override fun isApplicable(element: FirDeclaration, source: KtSourceElement): Boolean =
source.kind !is KtFakeSourceElementKind && element is FirMemberDeclaration
element.isMemberWithRealSource && element !is FirValueParameter
|| element.source?.kind == KtFakeSourceElementKind.PropertyFromParameter
private val FirDeclaration.isMemberWithRealSource get() = this is FirMemberDeclaration && source?.kind is KtRealSourceElementKind
override fun checkPsiOrLightTree(
element: FirDeclaration,