FIR: introduce delegated & overridden conflict checks
This commit is contained in:
+8
@@ -336,6 +336,14 @@ object DIAGNOSTICS_LIST : DiagnosticList() {
|
||||
parameter<FirClass<*>>("classOrObject")
|
||||
parameter<FirCallableDeclaration<*>>("missingDeclaration")
|
||||
}
|
||||
val OVERRIDING_FINAL_MEMBER_BY_DELEGATION by error<FirSourceElement, KtClassOrObject>(PositioningStrategy.DECLARATION_NAME) {
|
||||
parameter<FirCallableDeclaration<*>>("delegatedDeclaration")
|
||||
parameter<FirCallableDeclaration<*>>("overriddenDeclaration")
|
||||
}
|
||||
val DELEGATED_MEMBER_HIDES_SUPERTYPE_OVERRIDE by warning<FirSourceElement, KtClassOrObject>(PositioningStrategy.DECLARATION_NAME) {
|
||||
parameter<FirCallableDeclaration<*>>("delegatedDeclaration")
|
||||
parameter<FirCallableDeclaration<*>>("overriddenDeclaration")
|
||||
}
|
||||
|
||||
val RETURN_TYPE_MISMATCH_ON_OVERRIDE by error<FirSourceElement, KtNamedDeclaration>(PositioningStrategy.DECLARATION_RETURN_TYPE) {
|
||||
parameter<FirMemberDeclaration>("function")
|
||||
|
||||
@@ -225,6 +225,8 @@ object FirErrors {
|
||||
val INVISIBLE_ABSTRACT_MEMBER_FROM_SUPER_WARNING by warning2<FirSourceElement, KtClassOrObject, FirClass<*>, FirCallableDeclaration<*>>(SourceElementPositioningStrategies.DECLARATION_NAME)
|
||||
val MANY_IMPL_MEMBER_NOT_IMPLEMENTED by error2<FirSourceElement, KtClassOrObject, FirClass<*>, FirCallableDeclaration<*>>(SourceElementPositioningStrategies.DECLARATION_NAME)
|
||||
val MANY_INTERFACES_MEMBER_NOT_IMPLEMENTED by error2<FirSourceElement, KtClassOrObject, FirClass<*>, FirCallableDeclaration<*>>(SourceElementPositioningStrategies.DECLARATION_NAME)
|
||||
val OVERRIDING_FINAL_MEMBER_BY_DELEGATION by error2<FirSourceElement, KtClassOrObject, FirCallableDeclaration<*>, FirCallableDeclaration<*>>(SourceElementPositioningStrategies.DECLARATION_NAME)
|
||||
val DELEGATED_MEMBER_HIDES_SUPERTYPE_OVERRIDE by warning2<FirSourceElement, KtClassOrObject, FirCallableDeclaration<*>, FirCallableDeclaration<*>>(SourceElementPositioningStrategies.DECLARATION_NAME)
|
||||
val RETURN_TYPE_MISMATCH_ON_OVERRIDE by error2<FirSourceElement, KtNamedDeclaration, FirMemberDeclaration, FirMemberDeclaration>(SourceElementPositioningStrategies.DECLARATION_RETURN_TYPE)
|
||||
val PROPERTY_TYPE_MISMATCH_ON_OVERRIDE by error2<FirSourceElement, KtNamedDeclaration, FirMemberDeclaration, FirMemberDeclaration>(SourceElementPositioningStrategies.DECLARATION_RETURN_TYPE)
|
||||
val VAR_TYPE_MISMATCH_ON_OVERRIDE by error2<FirSourceElement, KtNamedDeclaration, FirMemberDeclaration, FirMemberDeclaration>(SourceElementPositioningStrategies.DECLARATION_RETURN_TYPE)
|
||||
|
||||
+53
-9
@@ -18,10 +18,12 @@ import org.jetbrains.kotlin.fir.analysis.checkers.unsubstitutedScope
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ABSTRACT_CLASS_MEMBER_NOT_IMPLEMENTED
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ABSTRACT_MEMBER_NOT_IMPLEMENTED
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.DELEGATED_MEMBER_HIDES_SUPERTYPE_OVERRIDE
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.INVISIBLE_ABSTRACT_MEMBER_FROM_SUPER
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.INVISIBLE_ABSTRACT_MEMBER_FROM_SUPER_WARNING
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.MANY_IMPL_MEMBER_NOT_IMPLEMENTED
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.MANY_INTERFACES_MEMBER_NOT_IMPLEMENTED
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.OVERRIDING_FINAL_MEMBER_BY_DELEGATION
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.reportOn
|
||||
import org.jetbrains.kotlin.fir.containingClass
|
||||
import org.jetbrains.kotlin.fir.declarations.*
|
||||
@@ -135,16 +137,58 @@ object FirNotImplementedOverrideChecker : FirClassChecker() {
|
||||
}
|
||||
}
|
||||
if (notImplementedIntersectionSymbols.isNotEmpty()) {
|
||||
val notImplementedIntersectionSymbol = notImplementedIntersectionSymbols.first()
|
||||
val notImplementedIntersection = notImplementedIntersectionSymbol.fir
|
||||
val intersections = (notImplementedIntersectionSymbol as FirIntersectionCallableSymbol).intersections
|
||||
if (intersections.any {
|
||||
(it.containingClass()?.toSymbol(context.session)?.fir as? FirRegularClass)?.classKind == ClassKind.CLASS
|
||||
var overridingFinalByDelegationReported = false
|
||||
var manyMemberNotImplementedReported = false
|
||||
var delegatedHidesSupertypeReported = false
|
||||
for (notImplementedIntersectionSymbol in notImplementedIntersectionSymbols) {
|
||||
val notImplementedIntersection = notImplementedIntersectionSymbol.fir
|
||||
val intersections = (notImplementedIntersectionSymbol as FirIntersectionCallableSymbol).intersections
|
||||
val delegatedIntersected = intersections.find {
|
||||
val fir = it.fir as FirCallableMemberDeclaration
|
||||
fir.origin == FirDeclarationOrigin.Delegated
|
||||
}
|
||||
) {
|
||||
reporter.reportOn(source, MANY_IMPL_MEMBER_NOT_IMPLEMENTED, declaration, notImplementedIntersection, context)
|
||||
} else {
|
||||
reporter.reportOn(source, MANY_INTERFACES_MEMBER_NOT_IMPLEMENTED, declaration, notImplementedIntersection, context)
|
||||
if (delegatedIntersected != null) {
|
||||
val finalIntersected = intersections.find { (it.fir as FirCallableMemberDeclaration).modality == Modality.FINAL }
|
||||
if (finalIntersected != null) {
|
||||
if (!overridingFinalByDelegationReported) {
|
||||
reporter.reportOn(
|
||||
source,
|
||||
OVERRIDING_FINAL_MEMBER_BY_DELEGATION,
|
||||
delegatedIntersected.fir,
|
||||
finalIntersected.fir,
|
||||
context
|
||||
)
|
||||
overridingFinalByDelegationReported = true
|
||||
}
|
||||
continue
|
||||
}
|
||||
val notDelegatedIntersected = intersections.firstOrNull {
|
||||
(it.fir as FirCallableMemberDeclaration).origin != FirDeclarationOrigin.Delegated
|
||||
}
|
||||
if (notDelegatedIntersected != null) {
|
||||
if (!delegatedHidesSupertypeReported) {
|
||||
reporter.reportOn(
|
||||
source,
|
||||
DELEGATED_MEMBER_HIDES_SUPERTYPE_OVERRIDE,
|
||||
delegatedIntersected.fir,
|
||||
notDelegatedIntersected.fir,
|
||||
context
|
||||
)
|
||||
delegatedHidesSupertypeReported = true
|
||||
}
|
||||
continue
|
||||
}
|
||||
}
|
||||
if (manyMemberNotImplementedReported) continue
|
||||
if (intersections.any {
|
||||
(it.containingClass()?.toSymbol(context.session)?.fir as? FirRegularClass)?.classKind == ClassKind.CLASS
|
||||
}
|
||||
) {
|
||||
reporter.reportOn(source, MANY_IMPL_MEMBER_NOT_IMPLEMENTED, declaration, notImplementedIntersection, context)
|
||||
} else {
|
||||
reporter.reportOn(source, MANY_INTERFACES_MEMBER_NOT_IMPLEMENTED, declaration, notImplementedIntersection, context)
|
||||
}
|
||||
manyMemberNotImplementedReported = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user