[FIR] Implement CONFLICTING_INHERITED_MEMBERS diagnostic
This commit is contained in:
committed by
teamcityserver
parent
78519f851e
commit
3f7d050f8f
+4
@@ -617,6 +617,10 @@ object DIAGNOSTICS_LIST : DiagnosticList("FirErrors") {
|
||||
parameter<FirCallableDeclaration<*>>("baseDeclaration")
|
||||
}
|
||||
|
||||
val CONFLICTING_INHERITED_MEMBERS by error<KtClassOrObject>(PositioningStrategy.DECLARATION_NAME) {
|
||||
parameter<List<FirCallableDeclaration<*>>>("conflictingDeclarations")
|
||||
}
|
||||
|
||||
val ABSTRACT_MEMBER_NOT_IMPLEMENTED by error<KtClassOrObject>(PositioningStrategy.DECLARATION_NAME) {
|
||||
parameter<FirClass>("classOrObject")
|
||||
parameter<FirCallableDeclaration>("missingDeclaration")
|
||||
|
||||
@@ -353,6 +353,7 @@ object FirErrors {
|
||||
val RETURN_TYPE_MISMATCH_BY_DELEGATION by error2<KtClassOrObject, FirCallableDeclaration<*>, FirCallableDeclaration<*>>(SourceElementPositioningStrategies.DECLARATION_NAME)
|
||||
val PROPERTY_TYPE_MISMATCH_BY_DELEGATION by error2<KtClassOrObject, FirCallableDeclaration<*>, FirCallableDeclaration<*>>(SourceElementPositioningStrategies.DECLARATION_NAME)
|
||||
val VAR_OVERRIDDEN_BY_VAL_BY_DELEGATION by error2<KtClassOrObject, FirCallableDeclaration<*>, FirCallableDeclaration<*>>(SourceElementPositioningStrategies.DECLARATION_NAME)
|
||||
val CONFLICTING_INHERITED_MEMBERS by error1<KtClassOrObject, List<FirCallableDeclaration<*>>>(SourceElementPositioningStrategies.DECLARATION_NAME)
|
||||
val ABSTRACT_MEMBER_NOT_IMPLEMENTED by error2<KtClassOrObject, FirClass, FirCallableDeclaration>(SourceElementPositioningStrategies.DECLARATION_NAME)
|
||||
val ABSTRACT_CLASS_MEMBER_NOT_IMPLEMENTED by error2<KtClassOrObject, FirClass, FirCallableDeclaration>(SourceElementPositioningStrategies.DECLARATION_NAME)
|
||||
val INVISIBLE_ABSTRACT_MEMBER_FROM_SUPER by error2<KtClassOrObject, FirClass, FirCallableDeclaration>(SourceElementPositioningStrategies.DECLARATION_NAME)
|
||||
|
||||
+33
@@ -14,6 +14,7 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.impl.deduplicating
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.reportOn
|
||||
import org.jetbrains.kotlin.fir.declarations.*
|
||||
import org.jetbrains.kotlin.fir.scopes.FirTypeScope
|
||||
import org.jetbrains.kotlin.fir.scopes.impl.delegatedWrapperData
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.*
|
||||
import org.jetbrains.kotlin.fir.typeContext
|
||||
@@ -21,6 +22,7 @@ import org.jetbrains.kotlin.fir.types.ConeKotlinErrorType
|
||||
import org.jetbrains.kotlin.fir.types.ConeKotlinType
|
||||
import org.jetbrains.kotlin.fir.types.ConeTypeCheckerContext
|
||||
import org.jetbrains.kotlin.fir.types.coneType
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.types.AbstractTypeChecker
|
||||
|
||||
object FirImplementationMismatchChecker : FirClassChecker() {
|
||||
@@ -46,6 +48,7 @@ object FirImplementationMismatchChecker : FirClassChecker() {
|
||||
checkInheritanceClash(declaration, context, dedupReporter, typeCheckerContext, it)
|
||||
checkValOverrideVar(declaration, context, dedupReporter, it)
|
||||
}
|
||||
checkConflictingMembers(declaration, context, dedupReporter, classScope, name)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -154,4 +157,34 @@ object FirImplementationMismatchChecker : FirClassChecker() {
|
||||
reporter.reportOn(containingClass.source, FirErrors.VAR_OVERRIDDEN_BY_VAL_BY_DELEGATION, delegatedVal.fir, baseVar.fir, context)
|
||||
}
|
||||
}
|
||||
|
||||
private fun checkConflictingMembers(
|
||||
containingClass: FirClass<*>,
|
||||
context: CheckerContext,
|
||||
reporter: DiagnosticReporter,
|
||||
scope: FirTypeScope,
|
||||
name: Name
|
||||
) {
|
||||
val allFunctions = mutableListOf<FirSimpleFunction>()
|
||||
scope.processFunctionsByName(name) { sym ->
|
||||
val declaredInThisClass = sym.callableId.classId == containingClass.classId
|
||||
when {
|
||||
sym is FirIntersectionOverrideFunctionSymbol && declaredInThisClass ->
|
||||
sym.intersections.mapNotNullTo(allFunctions) { (it as? FirNamedFunctionSymbol)?.fir }
|
||||
!declaredInThisClass -> allFunctions.add(sym.fir)
|
||||
}
|
||||
}
|
||||
|
||||
val sameArgumentGroups = allFunctions.groupBy { function ->
|
||||
function.valueParameters.map { it.returnTypeRef.coneType }
|
||||
}.values
|
||||
|
||||
val clash = sameArgumentGroups.mapNotNull { fs ->
|
||||
fs.zipWithNext().find { (m1, m2) ->
|
||||
m1.isSuspend != m2.isSuspend || m1.typeParameters.size != m2.typeParameters.size
|
||||
}
|
||||
}.firstOrNull() ?: return
|
||||
|
||||
reporter.reportOn(containingClass.source, FirErrors.CONFLICTING_INHERITED_MEMBERS, clash.toList(), context)
|
||||
}
|
||||
}
|
||||
+8
@@ -8,6 +8,7 @@ package org.jetbrains.kotlin.fir.analysis.diagnostics
|
||||
import org.jetbrains.kotlin.diagnostics.rendering.DefaultErrorMessages
|
||||
import org.jetbrains.kotlin.diagnostics.rendering.LanguageFeatureMessageRenderer
|
||||
import org.jetbrains.kotlin.diagnostics.rendering.Renderers.RENDER_POSITION_VARIANCE
|
||||
import org.jetbrains.kotlin.diagnostics.rendering.Renderers.commaSeparated
|
||||
import org.jetbrains.kotlin.diagnostics.rendering.Renderers.STRING
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirDiagnosticRenderers.AMBIGUOUS_CALLS
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirDiagnosticRenderers.DECLARATION_NAME
|
||||
@@ -76,6 +77,7 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.COMPONENT_FUNCTIO
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.COMPONENT_FUNCTION_RETURN_TYPE_MISMATCH
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.CONDITION_TYPE_MISMATCH
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.CONFLICTING_IMPORT
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.CONFLICTING_INHERITED_MEMBERS
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.CONFLICTING_OVERLOADS
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.CONFLICTING_PROJECTION
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.CONFLICTING_PROJECTION_IN_TYPEALIAS_EXPANSION
|
||||
@@ -983,6 +985,12 @@ class FirDefaultErrorMessages {
|
||||
NAME
|
||||
)
|
||||
|
||||
map.put(
|
||||
CONFLICTING_INHERITED_MEMBERS,
|
||||
"{0} inherits conflicting members: {1}",
|
||||
commaSeparated(NAME)
|
||||
)
|
||||
|
||||
// Redeclarations
|
||||
map.put(MANY_COMPANION_OBJECTS, "Only one companion object is allowed per class")
|
||||
map.put(CONFLICTING_OVERLOADS, "Conflicting overloads: {0}", SYMBOLS) // *
|
||||
|
||||
+1
-1
@@ -15,7 +15,7 @@ interface B {
|
||||
fun <T> a(@An arg: @An Int)
|
||||
}
|
||||
|
||||
interface C : A, B
|
||||
<!CONFLICTING_INHERITED_MEMBERS!>interface C<!> : A, B
|
||||
|
||||
@An
|
||||
abstract class D {
|
||||
|
||||
+1
-1
@@ -8,6 +8,6 @@ interface B {
|
||||
fun bar()
|
||||
}
|
||||
|
||||
interface C1 : A, B {
|
||||
<!CONFLICTING_INHERITED_MEMBERS!>interface C1<!> : A, B {
|
||||
override fun bar()
|
||||
}
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
interface AsyncVal { suspend fun getVal(): Int = 1}
|
||||
interface SyncVal { fun getVal(): Int = 1 }
|
||||
|
||||
<!MANY_INTERFACES_MEMBER_NOT_IMPLEMENTED!>class MixSuspend<!> : AsyncVal, SyncVal {
|
||||
<!CONFLICTING_INHERITED_MEMBERS, MANY_INTERFACES_MEMBER_NOT_IMPLEMENTED!>class MixSuspend<!> : AsyncVal, SyncVal {
|
||||
|
||||
}
|
||||
|
||||
Generated
+1
-1
@@ -20624,7 +20624,7 @@ public class DiagnosticTestGenerated extends AbstractDiagnosticTest {
|
||||
|
||||
@Test
|
||||
@TestMetadata("kt13355viaJava.kt")
|
||||
public void testKt13355viaJava1111() throws Exception {
|
||||
public void testKt13355viaJava() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/override/clashesOnInheritance/kt13355viaJava.kt");
|
||||
}
|
||||
|
||||
|
||||
+9
@@ -1700,6 +1700,15 @@ internal val KT_DIAGNOSTIC_CONVERTER = KtDiagnosticConverterBuilder.buildConvert
|
||||
token,
|
||||
)
|
||||
}
|
||||
add(FirErrors.CONFLICTING_INHERITED_MEMBERS) { firDiagnostic ->
|
||||
ConflictingInheritedMembersImpl(
|
||||
firDiagnostic.a.map { firCallableDeclaration ->
|
||||
firSymbolBuilder.callableBuilder.buildCallableSymbol(firCallableDeclaration as FirCallableDeclaration)
|
||||
},
|
||||
firDiagnostic as FirPsiDiagnostic<*>,
|
||||
token,
|
||||
)
|
||||
}
|
||||
add(FirErrors.ABSTRACT_MEMBER_NOT_IMPLEMENTED) { firDiagnostic ->
|
||||
AbstractMemberNotImplementedImpl(
|
||||
firSymbolBuilder.classifierBuilder.buildClassLikeSymbol(firDiagnostic.a),
|
||||
|
||||
+5
@@ -1207,6 +1207,11 @@ sealed class KtFirDiagnostic<PSI: PsiElement> : KtDiagnosticWithPsi<PSI> {
|
||||
abstract val baseDeclaration: KtCallableSymbol
|
||||
}
|
||||
|
||||
abstract class ConflictingInheritedMembers : KtFirDiagnostic<KtClassOrObject>() {
|
||||
override val diagnosticClass get() = ConflictingInheritedMembers::class
|
||||
abstract val conflictingDeclarations: List<KtCallableSymbol>
|
||||
}
|
||||
|
||||
abstract class AbstractMemberNotImplemented : KtFirDiagnostic<KtClassOrObject>() {
|
||||
override val diagnosticClass get() = AbstractMemberNotImplemented::class
|
||||
abstract val classOrObject: KtClassLikeSymbol
|
||||
|
||||
+8
@@ -1937,6 +1937,14 @@ internal class VarOverriddenByValByDelegationImpl(
|
||||
override val firDiagnostic: FirPsiDiagnostic<*> by weakRef(firDiagnostic)
|
||||
}
|
||||
|
||||
internal class ConflictingInheritedMembersImpl(
|
||||
override val conflictingDeclarations: List<KtCallableSymbol>,
|
||||
firDiagnostic: FirPsiDiagnostic<*>,
|
||||
override val token: ValidityToken,
|
||||
) : KtFirDiagnostic.ConflictingInheritedMembers(), KtAbstractFirDiagnostic<KtClassOrObject> {
|
||||
override val firDiagnostic: FirPsiDiagnostic<*> by weakRef(firDiagnostic)
|
||||
}
|
||||
|
||||
internal class AbstractMemberNotImplementedImpl(
|
||||
override val classOrObject: KtClassLikeSymbol,
|
||||
override val missingDeclaration: KtCallableSymbol,
|
||||
|
||||
Reference in New Issue
Block a user