Forbid usages of super if in fact it accesses an abstract member
#KT-49017 Fixed
This commit is contained in:
+6
@@ -392,6 +392,12 @@ internal val KT_DIAGNOSTIC_CONVERTER = KtDiagnosticConverterBuilder.buildConvert
|
|||||||
token,
|
token,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
add(FirErrors.ABSTRACT_SUPER_CALL_WARNING) { firDiagnostic ->
|
||||||
|
AbstractSuperCallWarningImpl(
|
||||||
|
firDiagnostic as KtPsiDiagnostic,
|
||||||
|
token,
|
||||||
|
)
|
||||||
|
}
|
||||||
add(FirErrors.INSTANCE_ACCESS_BEFORE_SUPER_CALL) { firDiagnostic ->
|
add(FirErrors.INSTANCE_ACCESS_BEFORE_SUPER_CALL) { firDiagnostic ->
|
||||||
InstanceAccessBeforeSuperCallImpl(
|
InstanceAccessBeforeSuperCallImpl(
|
||||||
firDiagnostic.a,
|
firDiagnostic.a,
|
||||||
|
|||||||
+4
@@ -307,6 +307,10 @@ sealed class KtFirDiagnostic<PSI : PsiElement> : KtDiagnosticWithPsi<PSI> {
|
|||||||
override val diagnosticClass get() = AbstractSuperCall::class
|
override val diagnosticClass get() = AbstractSuperCall::class
|
||||||
}
|
}
|
||||||
|
|
||||||
|
abstract class AbstractSuperCallWarning : KtFirDiagnostic<PsiElement>() {
|
||||||
|
override val diagnosticClass get() = AbstractSuperCallWarning::class
|
||||||
|
}
|
||||||
|
|
||||||
abstract class InstanceAccessBeforeSuperCall : KtFirDiagnostic<PsiElement>() {
|
abstract class InstanceAccessBeforeSuperCall : KtFirDiagnostic<PsiElement>() {
|
||||||
override val diagnosticClass get() = InstanceAccessBeforeSuperCall::class
|
override val diagnosticClass get() = InstanceAccessBeforeSuperCall::class
|
||||||
abstract val target: String
|
abstract val target: String
|
||||||
|
|||||||
+5
@@ -356,6 +356,11 @@ internal class AbstractSuperCallImpl(
|
|||||||
override val token: ValidityToken,
|
override val token: ValidityToken,
|
||||||
) : KtFirDiagnostic.AbstractSuperCall(), KtAbstractFirDiagnostic<PsiElement>
|
) : KtFirDiagnostic.AbstractSuperCall(), KtAbstractFirDiagnostic<PsiElement>
|
||||||
|
|
||||||
|
internal class AbstractSuperCallWarningImpl(
|
||||||
|
override val firDiagnostic: KtPsiDiagnostic,
|
||||||
|
override val token: ValidityToken,
|
||||||
|
) : KtFirDiagnostic.AbstractSuperCallWarning(), KtAbstractFirDiagnostic<PsiElement>
|
||||||
|
|
||||||
internal class InstanceAccessBeforeSuperCallImpl(
|
internal class InstanceAccessBeforeSuperCallImpl(
|
||||||
override val target: String,
|
override val target: String,
|
||||||
override val firDiagnostic: KtPsiDiagnostic,
|
override val firDiagnostic: KtPsiDiagnostic,
|
||||||
|
|||||||
+12
@@ -18587,6 +18587,18 @@ public class DiagnosisCompilerTestFE10TestdataTestGenerated extends AbstractDiag
|
|||||||
runTest("compiler/testData/diagnostics/tests/java8Overrides/abstractBaseClassMemberNotImplemented_15.kt");
|
runTest("compiler/testData/diagnostics/tests/java8Overrides/abstractBaseClassMemberNotImplemented_15.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("abstractFakeOverrideSuperCall.kt")
|
||||||
|
public void testAbstractFakeOverrideSuperCall() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/java8Overrides/abstractFakeOverrideSuperCall.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("abstractFakeOverrideSuperCallForbidden.kt")
|
||||||
|
public void testAbstractFakeOverrideSuperCallForbidden() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/java8Overrides/abstractFakeOverrideSuperCallForbidden.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestMetadata("abstractVsAbstract.kt")
|
@TestMetadata("abstractVsAbstract.kt")
|
||||||
public void testAbstractVsAbstract() throws Exception {
|
public void testAbstractVsAbstract() throws Exception {
|
||||||
|
|||||||
+12
@@ -18587,6 +18587,18 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirDiagnosti
|
|||||||
runTest("compiler/testData/diagnostics/tests/java8Overrides/abstractBaseClassMemberNotImplemented_15.kt");
|
runTest("compiler/testData/diagnostics/tests/java8Overrides/abstractBaseClassMemberNotImplemented_15.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("abstractFakeOverrideSuperCall.kt")
|
||||||
|
public void testAbstractFakeOverrideSuperCall() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/java8Overrides/abstractFakeOverrideSuperCall.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("abstractFakeOverrideSuperCallForbidden.kt")
|
||||||
|
public void testAbstractFakeOverrideSuperCallForbidden() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/java8Overrides/abstractFakeOverrideSuperCallForbidden.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestMetadata("abstractVsAbstract.kt")
|
@TestMetadata("abstractVsAbstract.kt")
|
||||||
public void testAbstractVsAbstract() throws Exception {
|
public void testAbstractVsAbstract() throws Exception {
|
||||||
|
|||||||
+12
@@ -18587,6 +18587,18 @@ public class FirOldFrontendDiagnosticsWithLightTreeTestGenerated extends Abstrac
|
|||||||
runTest("compiler/testData/diagnostics/tests/java8Overrides/abstractBaseClassMemberNotImplemented_15.kt");
|
runTest("compiler/testData/diagnostics/tests/java8Overrides/abstractBaseClassMemberNotImplemented_15.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("abstractFakeOverrideSuperCall.kt")
|
||||||
|
public void testAbstractFakeOverrideSuperCall() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/java8Overrides/abstractFakeOverrideSuperCall.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("abstractFakeOverrideSuperCallForbidden.kt")
|
||||||
|
public void testAbstractFakeOverrideSuperCallForbidden() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/java8Overrides/abstractFakeOverrideSuperCallForbidden.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestMetadata("abstractVsAbstract.kt")
|
@TestMetadata("abstractVsAbstract.kt")
|
||||||
public void testAbstractVsAbstract() throws Exception {
|
public void testAbstractVsAbstract() throws Exception {
|
||||||
|
|||||||
+1
@@ -149,6 +149,7 @@ object DIAGNOSTICS_LIST : DiagnosticList("FirErrors") {
|
|||||||
val SUPER_IS_NOT_AN_EXPRESSION by error<PsiElement>(PositioningStrategy.REFERENCED_NAME_BY_QUALIFIED)
|
val SUPER_IS_NOT_AN_EXPRESSION by error<PsiElement>(PositioningStrategy.REFERENCED_NAME_BY_QUALIFIED)
|
||||||
val SUPER_NOT_AVAILABLE by error<PsiElement>(PositioningStrategy.REFERENCED_NAME_BY_QUALIFIED)
|
val SUPER_NOT_AVAILABLE by error<PsiElement>(PositioningStrategy.REFERENCED_NAME_BY_QUALIFIED)
|
||||||
val ABSTRACT_SUPER_CALL by error<PsiElement>(PositioningStrategy.REFERENCED_NAME_BY_QUALIFIED)
|
val ABSTRACT_SUPER_CALL by error<PsiElement>(PositioningStrategy.REFERENCED_NAME_BY_QUALIFIED)
|
||||||
|
val ABSTRACT_SUPER_CALL_WARNING by warning<PsiElement>(PositioningStrategy.REFERENCED_NAME_BY_QUALIFIED)
|
||||||
val INSTANCE_ACCESS_BEFORE_SUPER_CALL by error<PsiElement> {
|
val INSTANCE_ACCESS_BEFORE_SUPER_CALL by error<PsiElement> {
|
||||||
parameter<String>("target")
|
parameter<String>("target")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -165,6 +165,7 @@ object FirErrors {
|
|||||||
val SUPER_IS_NOT_AN_EXPRESSION by error0<PsiElement>(SourceElementPositioningStrategies.REFERENCED_NAME_BY_QUALIFIED)
|
val SUPER_IS_NOT_AN_EXPRESSION by error0<PsiElement>(SourceElementPositioningStrategies.REFERENCED_NAME_BY_QUALIFIED)
|
||||||
val SUPER_NOT_AVAILABLE by error0<PsiElement>(SourceElementPositioningStrategies.REFERENCED_NAME_BY_QUALIFIED)
|
val SUPER_NOT_AVAILABLE by error0<PsiElement>(SourceElementPositioningStrategies.REFERENCED_NAME_BY_QUALIFIED)
|
||||||
val ABSTRACT_SUPER_CALL by error0<PsiElement>(SourceElementPositioningStrategies.REFERENCED_NAME_BY_QUALIFIED)
|
val ABSTRACT_SUPER_CALL by error0<PsiElement>(SourceElementPositioningStrategies.REFERENCED_NAME_BY_QUALIFIED)
|
||||||
|
val ABSTRACT_SUPER_CALL_WARNING by warning0<PsiElement>(SourceElementPositioningStrategies.REFERENCED_NAME_BY_QUALIFIED)
|
||||||
val INSTANCE_ACCESS_BEFORE_SUPER_CALL by error1<PsiElement, String>()
|
val INSTANCE_ACCESS_BEFORE_SUPER_CALL by error1<PsiElement, String>()
|
||||||
|
|
||||||
// Supertypes
|
// Supertypes
|
||||||
|
|||||||
+19
-2
@@ -5,12 +5,14 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.fir.analysis.checkers.expression
|
package org.jetbrains.kotlin.fir.analysis.checkers.expression
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.config.LanguageFeature
|
||||||
import org.jetbrains.kotlin.descriptors.ClassKind
|
import org.jetbrains.kotlin.descriptors.ClassKind
|
||||||
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
||||||
import org.jetbrains.kotlin.fir.analysis.checkers.context.findClosest
|
import org.jetbrains.kotlin.fir.analysis.checkers.context.findClosest
|
||||||
import org.jetbrains.kotlin.diagnostics.DiagnosticReporter
|
import org.jetbrains.kotlin.diagnostics.DiagnosticReporter
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
||||||
import org.jetbrains.kotlin.diagnostics.reportOn
|
import org.jetbrains.kotlin.diagnostics.reportOn
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.checkers.classKind
|
||||||
import org.jetbrains.kotlin.fir.containingClass
|
import org.jetbrains.kotlin.fir.containingClass
|
||||||
import org.jetbrains.kotlin.fir.declarations.FirRegularClass
|
import org.jetbrains.kotlin.fir.declarations.FirRegularClass
|
||||||
import org.jetbrains.kotlin.fir.declarations.utils.isAbstract
|
import org.jetbrains.kotlin.fir.declarations.utils.isAbstract
|
||||||
@@ -18,6 +20,7 @@ import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccessExpression
|
|||||||
import org.jetbrains.kotlin.fir.expressions.toResolvedCallableSymbol
|
import org.jetbrains.kotlin.fir.expressions.toResolvedCallableSymbol
|
||||||
import org.jetbrains.kotlin.fir.references.FirSuperReference
|
import org.jetbrains.kotlin.fir.references.FirSuperReference
|
||||||
import org.jetbrains.kotlin.fir.resolve.toSymbol
|
import org.jetbrains.kotlin.fir.resolve.toSymbol
|
||||||
|
import org.jetbrains.kotlin.fir.symbols.impl.FirIntersectionCallableSymbol
|
||||||
import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol
|
import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol
|
||||||
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
||||||
|
|
||||||
@@ -37,8 +40,22 @@ object FirAbstractSuperCallChecker : FirQualifiedAccessExpressionChecker() {
|
|||||||
|
|
||||||
val containingClassSymbol = declarationSymbol.containingClass()?.toSymbol(context.session) as? FirRegularClassSymbol ?: return
|
val containingClassSymbol = declarationSymbol.containingClass()?.toSymbol(context.session) as? FirRegularClassSymbol ?: return
|
||||||
|
|
||||||
if (containingClassSymbol.isAbstract && declarationSymbol.isAbstract) {
|
if (containingClassSymbol.isAbstract) {
|
||||||
reporter.reportOn(expression.calleeReference.source, FirErrors.ABSTRACT_SUPER_CALL, context)
|
if (declarationSymbol.isAbstract) {
|
||||||
|
reporter.reportOn(expression.calleeReference.source, FirErrors.ABSTRACT_SUPER_CALL, context)
|
||||||
|
}
|
||||||
|
if (declarationSymbol is FirIntersectionCallableSymbol) {
|
||||||
|
val symbolFromBaseClass = declarationSymbol.intersections.firstOrNull {
|
||||||
|
it.containingClass()?.toSymbol(context.session)?.classKind != ClassKind.INTERFACE
|
||||||
|
}
|
||||||
|
if (symbolFromBaseClass?.isAbstract == true) {
|
||||||
|
if (context.languageVersionSettings.supportsFeature(LanguageFeature.ForbidSuperDelegationToAbstractFakeOverride)) {
|
||||||
|
reporter.reportOn(expression.calleeReference.source, FirErrors.ABSTRACT_SUPER_CALL, context)
|
||||||
|
} else {
|
||||||
|
reporter.reportOn(expression.calleeReference.source, FirErrors.ABSTRACT_SUPER_CALL_WARNING, context)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+2
@@ -45,6 +45,7 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ABSTRACT_PROPERTY
|
|||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ABSTRACT_PROPERTY_WITH_INITIALIZER
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ABSTRACT_PROPERTY_WITH_INITIALIZER
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ABSTRACT_PROPERTY_WITH_SETTER
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ABSTRACT_PROPERTY_WITH_SETTER
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ABSTRACT_SUPER_CALL
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ABSTRACT_SUPER_CALL
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ABSTRACT_SUPER_CALL_WARNING
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ACCESSOR_FOR_DELEGATED_PROPERTY
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ACCESSOR_FOR_DELEGATED_PROPERTY
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ACTUAL_ANNOTATION_CONFLICTING_DEFAULT_ARGUMENT_VALUE
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ACTUAL_ANNOTATION_CONFLICTING_DEFAULT_ARGUMENT_VALUE
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ACTUAL_FUNCTION_WITH_DEFAULT_ARGUMENTS
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ACTUAL_FUNCTION_WITH_DEFAULT_ARGUMENTS
|
||||||
@@ -642,6 +643,7 @@ object FirErrorsDefaultMessages : BaseDiagnosticRendererFactory() {
|
|||||||
map.put(SUPER_IS_NOT_AN_EXPRESSION, "Super cannot be a callee")
|
map.put(SUPER_IS_NOT_AN_EXPRESSION, "Super cannot be a callee")
|
||||||
map.put(SUPER_NOT_AVAILABLE, "No supertypes are accessible in this context")
|
map.put(SUPER_NOT_AVAILABLE, "No supertypes are accessible in this context")
|
||||||
map.put(ABSTRACT_SUPER_CALL, "Abstract member cannot be accessed directly")
|
map.put(ABSTRACT_SUPER_CALL, "Abstract member cannot be accessed directly")
|
||||||
|
map.put(ABSTRACT_SUPER_CALL_WARNING, "Abstract fake override member access is deprecated")
|
||||||
map.put(
|
map.put(
|
||||||
INSTANCE_ACCESS_BEFORE_SUPER_CALL,
|
INSTANCE_ACCESS_BEFORE_SUPER_CALL,
|
||||||
"Cannot access ''{0}'' before superclass constructor has been called",
|
"Cannot access ''{0}'' before superclass constructor has been called",
|
||||||
|
|||||||
@@ -933,6 +933,7 @@ public interface Errors {
|
|||||||
DiagnosticFactory0<KtSuperExpression> SUPERCLASS_NOT_ACCESSIBLE_FROM_INTERFACE = DiagnosticFactory0.create(ERROR);
|
DiagnosticFactory0<KtSuperExpression> SUPERCLASS_NOT_ACCESSIBLE_FROM_INTERFACE = DiagnosticFactory0.create(ERROR);
|
||||||
DiagnosticFactory0<KtSuperExpression> AMBIGUOUS_SUPER = DiagnosticFactory0.create(ERROR);
|
DiagnosticFactory0<KtSuperExpression> AMBIGUOUS_SUPER = DiagnosticFactory0.create(ERROR);
|
||||||
DiagnosticFactory0<KtExpression> ABSTRACT_SUPER_CALL = DiagnosticFactory0.create(ERROR);
|
DiagnosticFactory0<KtExpression> ABSTRACT_SUPER_CALL = DiagnosticFactory0.create(ERROR);
|
||||||
|
DiagnosticFactory0<KtExpression> ABSTRACT_SUPER_CALL_WARNING = DiagnosticFactory0.create(WARNING);
|
||||||
DiagnosticFactory0<KtTypeReference> NOT_A_SUPERTYPE = DiagnosticFactory0.create(ERROR);
|
DiagnosticFactory0<KtTypeReference> NOT_A_SUPERTYPE = DiagnosticFactory0.create(ERROR);
|
||||||
DiagnosticFactory0<PsiElement> TYPE_ARGUMENTS_REDUNDANT_IN_SUPER_QUALIFIER = DiagnosticFactory0.create(WARNING);
|
DiagnosticFactory0<PsiElement> TYPE_ARGUMENTS_REDUNDANT_IN_SUPER_QUALIFIER = DiagnosticFactory0.create(WARNING);
|
||||||
DiagnosticFactory1<KtTypeReference, KotlinType> QUALIFIED_SUPERTYPE_EXTENDED_BY_OTHER_SUPERTYPE = DiagnosticFactory1.create(ERROR);
|
DiagnosticFactory1<KtTypeReference, KotlinType> QUALIFIED_SUPERTYPE_EXTENDED_BY_OTHER_SUPERTYPE = DiagnosticFactory1.create(ERROR);
|
||||||
|
|||||||
+1
@@ -491,6 +491,7 @@ public class DefaultErrorMessages {
|
|||||||
MAP.put(SUPERCLASS_NOT_ACCESSIBLE_FROM_INTERFACE, "Superclass is not accessible from interface");
|
MAP.put(SUPERCLASS_NOT_ACCESSIBLE_FROM_INTERFACE, "Superclass is not accessible from interface");
|
||||||
MAP.put(AMBIGUOUS_SUPER, "Many supertypes available, please specify the one you mean in angle brackets, e.g. 'super<Foo>'");
|
MAP.put(AMBIGUOUS_SUPER, "Many supertypes available, please specify the one you mean in angle brackets, e.g. 'super<Foo>'");
|
||||||
MAP.put(ABSTRACT_SUPER_CALL, "Abstract member cannot be accessed directly");
|
MAP.put(ABSTRACT_SUPER_CALL, "Abstract member cannot be accessed directly");
|
||||||
|
MAP.put(ABSTRACT_SUPER_CALL_WARNING, "Abstract fake override member access is deprecated");
|
||||||
MAP.put(NOT_A_SUPERTYPE, "Not an immediate supertype");
|
MAP.put(NOT_A_SUPERTYPE, "Not an immediate supertype");
|
||||||
MAP.put(TYPE_ARGUMENTS_REDUNDANT_IN_SUPER_QUALIFIER, "Type arguments do not need to be specified in a 'super' qualifier");
|
MAP.put(TYPE_ARGUMENTS_REDUNDANT_IN_SUPER_QUALIFIER, "Type arguments do not need to be specified in a 'super' qualifier");
|
||||||
MAP.put(QUALIFIED_SUPERTYPE_EXTENDED_BY_OTHER_SUPERTYPE, "Explicitly qualified supertype is extended by another supertype ''{0}''", RENDER_TYPE);
|
MAP.put(QUALIFIED_SUPERTYPE_EXTENDED_BY_OTHER_SUPERTYPE, "Explicitly qualified supertype is extended by another supertype ''{0}''", RENDER_TYPE);
|
||||||
|
|||||||
+7
@@ -77,6 +77,13 @@ class DiagnosticReporterByTrackingStrategy(
|
|||||||
)
|
)
|
||||||
InstantiationOfAbstractClass::class.java -> tracingStrategy.instantiationOfAbstractClass(trace)
|
InstantiationOfAbstractClass::class.java -> tracingStrategy.instantiationOfAbstractClass(trace)
|
||||||
AbstractSuperCall::class.java -> tracingStrategy.abstractSuperCall(trace)
|
AbstractSuperCall::class.java -> tracingStrategy.abstractSuperCall(trace)
|
||||||
|
AbstractFakeOverrideSuperCall::class.java -> {
|
||||||
|
if (context.languageVersionSettings.supportsFeature(LanguageFeature.ForbidSuperDelegationToAbstractFakeOverride)) {
|
||||||
|
tracingStrategy.abstractSuperCall(trace)
|
||||||
|
} else {
|
||||||
|
tracingStrategy.abstractFakeOverrideSuperCall(trace)
|
||||||
|
}
|
||||||
|
}
|
||||||
NonApplicableCallForBuilderInferenceDiagnostic::class.java -> {
|
NonApplicableCallForBuilderInferenceDiagnostic::class.java -> {
|
||||||
val reportOn = (diagnostic as NonApplicableCallForBuilderInferenceDiagnostic).kotlinCall
|
val reportOn = (diagnostic as NonApplicableCallForBuilderInferenceDiagnostic).kotlinCall
|
||||||
trace.reportDiagnosticOnce(NON_APPLICABLE_CALL_FOR_BUILDER_INFERENCE.on(reportOn.psiKotlinCall.psiCall.callElement))
|
trace.reportDiagnosticOnce(NON_APPLICABLE_CALL_FOR_BUILDER_INFERENCE.on(reportOn.psiKotlinCall.psiCall.callElement))
|
||||||
|
|||||||
+5
@@ -142,6 +142,11 @@ public abstract class AbstractTracingStrategy implements TracingStrategy {
|
|||||||
trace.report(ABSTRACT_SUPER_CALL.on(reference));
|
trace.report(ABSTRACT_SUPER_CALL.on(reference));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void abstractFakeOverrideSuperCall(@NotNull BindingTrace trace) {
|
||||||
|
trace.report(ABSTRACT_SUPER_CALL_WARNING.on(reference));
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void nestedClassAccessViaInstanceReference(
|
public void nestedClassAccessViaInstanceReference(
|
||||||
@NotNull BindingTrace trace,
|
@NotNull BindingTrace trace,
|
||||||
|
|||||||
@@ -148,6 +148,10 @@ public interface TracingStrategy {
|
|||||||
|
|
||||||
void abstractSuperCall(@NotNull BindingTrace trace);
|
void abstractSuperCall(@NotNull BindingTrace trace);
|
||||||
|
|
||||||
|
default void abstractFakeOverrideSuperCall(@NotNull BindingTrace trace) {
|
||||||
|
abstractSuperCall(trace);
|
||||||
|
}
|
||||||
|
|
||||||
void nestedClassAccessViaInstanceReference(
|
void nestedClassAccessViaInstanceReference(
|
||||||
@NotNull BindingTrace trace,
|
@NotNull BindingTrace trace,
|
||||||
@NotNull ClassDescriptor classDescriptor,
|
@NotNull ClassDescriptor classDescriptor,
|
||||||
|
|||||||
+12
-2
@@ -23,6 +23,7 @@ import org.jetbrains.kotlin.resolve.calls.tower.ContextReceiverAmbiguity
|
|||||||
import org.jetbrains.kotlin.resolve.calls.tower.InfixCallNoInfixModifier
|
import org.jetbrains.kotlin.resolve.calls.tower.InfixCallNoInfixModifier
|
||||||
import org.jetbrains.kotlin.resolve.calls.tower.InvokeConventionCallNoOperatorModifier
|
import org.jetbrains.kotlin.resolve.calls.tower.InvokeConventionCallNoOperatorModifier
|
||||||
import org.jetbrains.kotlin.resolve.calls.tower.VisibilityError
|
import org.jetbrains.kotlin.resolve.calls.tower.VisibilityError
|
||||||
|
import org.jetbrains.kotlin.resolve.descriptorUtil.isInsideInterface
|
||||||
import org.jetbrains.kotlin.resolve.scopes.LexicalScope
|
import org.jetbrains.kotlin.resolve.scopes.LexicalScope
|
||||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValueWithSmartCastInfo
|
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValueWithSmartCastInfo
|
||||||
import org.jetbrains.kotlin.resolve.scopes.utils.parentsWithSelf
|
import org.jetbrains.kotlin.resolve.scopes.utils.parentsWithSelf
|
||||||
@@ -809,8 +810,17 @@ internal object CheckSuperExpressionCallPart : ResolutionPart() {
|
|||||||
val candidateDescriptor = resolvedCall.candidateDescriptor
|
val candidateDescriptor = resolvedCall.candidateDescriptor
|
||||||
|
|
||||||
if (callComponents.statelessCallbacks.isSuperExpression(resolvedCall.dispatchReceiverArgument)) {
|
if (callComponents.statelessCallbacks.isSuperExpression(resolvedCall.dispatchReceiverArgument)) {
|
||||||
if (candidateDescriptor is MemberDescriptor && candidateDescriptor.modality == Modality.ABSTRACT) {
|
if (candidateDescriptor is CallableMemberDescriptor) {
|
||||||
addDiagnostic(AbstractSuperCall)
|
if (candidateDescriptor.modality == Modality.ABSTRACT) {
|
||||||
|
addDiagnostic(AbstractSuperCall)
|
||||||
|
}
|
||||||
|
if (candidateDescriptor.kind == CallableMemberDescriptor.Kind.FAKE_OVERRIDE &&
|
||||||
|
candidateDescriptor.overriddenDescriptors.size > 1
|
||||||
|
) {
|
||||||
|
if (candidateDescriptor.overriddenDescriptors.firstOrNull { !it.isInsideInterface }?.modality == Modality.ABSTRACT) {
|
||||||
|
addDiagnostic(AbstractFakeOverrideSuperCall)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+6
@@ -208,6 +208,12 @@ object AbstractSuperCall : KotlinCallDiagnostic(RUNTIME_ERROR) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
object AbstractFakeOverrideSuperCall : KotlinCallDiagnostic(RUNTIME_ERROR) {
|
||||||
|
override fun report(reporter: DiagnosticReporter) {
|
||||||
|
reporter.onCall(this)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
class SuperAsExtensionReceiver(val receiver: SimpleKotlinCallArgument) : KotlinCallDiagnostic(RUNTIME_ERROR) {
|
class SuperAsExtensionReceiver(val receiver: SimpleKotlinCallArgument) : KotlinCallDiagnostic(RUNTIME_ERROR) {
|
||||||
override fun report(reporter: DiagnosticReporter) {
|
override fun report(reporter: DiagnosticReporter) {
|
||||||
reporter.onCallReceiver(receiver, this)
|
reporter.onCallReceiver(receiver, this)
|
||||||
|
|||||||
+26
@@ -0,0 +1,26 @@
|
|||||||
|
// FIR_IDENTICAL
|
||||||
|
// !LANGUAGE: -ForbidSuperDelegationToAbstractFakeOverride
|
||||||
|
interface Foo {
|
||||||
|
fun check(): String = "OK"
|
||||||
|
}
|
||||||
|
abstract class Base {
|
||||||
|
abstract fun check(): String
|
||||||
|
}
|
||||||
|
abstract class Derived : Base(), Foo
|
||||||
|
|
||||||
|
class Derived2 : Derived() {
|
||||||
|
override fun check(): String {
|
||||||
|
super<Derived>.<!ABSTRACT_SUPER_CALL_WARNING!>check<!>()
|
||||||
|
return super.<!ABSTRACT_SUPER_CALL_WARNING!>check<!>()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract class A {
|
||||||
|
abstract override fun hashCode(): Int
|
||||||
|
}
|
||||||
|
|
||||||
|
interface I
|
||||||
|
|
||||||
|
class B : A(), I { // I is necessary here
|
||||||
|
override fun hashCode() = super.hashCode()
|
||||||
|
}
|
||||||
+52
@@ -0,0 +1,52 @@
|
|||||||
|
package
|
||||||
|
|
||||||
|
public abstract class A {
|
||||||
|
public constructor A()
|
||||||
|
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
|
public abstract override /*1*/ fun hashCode(): kotlin.Int
|
||||||
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
}
|
||||||
|
|
||||||
|
public final class B : A, I {
|
||||||
|
public constructor B()
|
||||||
|
public open override /*2*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
|
public open override /*2*/ fun hashCode(): kotlin.Int
|
||||||
|
public open override /*2*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract class Base {
|
||||||
|
public constructor Base()
|
||||||
|
public abstract fun check(): kotlin.String
|
||||||
|
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 open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract class Derived : Base, Foo {
|
||||||
|
public constructor Derived()
|
||||||
|
public open override /*2*/ /*fake_override*/ fun check(): kotlin.String
|
||||||
|
public open override /*2*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
|
public open override /*2*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||||
|
public open override /*2*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
}
|
||||||
|
|
||||||
|
public final class Derived2 : Derived {
|
||||||
|
public constructor Derived2()
|
||||||
|
public open override /*1*/ fun check(): kotlin.String
|
||||||
|
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 open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface Foo {
|
||||||
|
public open fun check(): kotlin.String
|
||||||
|
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 open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface I {
|
||||||
|
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 open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
}
|
||||||
Vendored
+26
@@ -0,0 +1,26 @@
|
|||||||
|
// FIR_IDENTICAL
|
||||||
|
// !LANGUAGE: +ForbidSuperDelegationToAbstractFakeOverride
|
||||||
|
interface Foo {
|
||||||
|
fun check(): String = "OK"
|
||||||
|
}
|
||||||
|
abstract class Base {
|
||||||
|
abstract fun check(): String
|
||||||
|
}
|
||||||
|
abstract class Derived : Base(), Foo
|
||||||
|
|
||||||
|
class Derived2 : Derived() {
|
||||||
|
override fun check(): String {
|
||||||
|
super<Derived>.<!ABSTRACT_SUPER_CALL!>check<!>()
|
||||||
|
return super.<!ABSTRACT_SUPER_CALL!>check<!>()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract class A {
|
||||||
|
abstract override fun hashCode(): Int
|
||||||
|
}
|
||||||
|
|
||||||
|
interface I
|
||||||
|
|
||||||
|
class B : A(), I { // I is necessary here
|
||||||
|
override fun hashCode() = super.hashCode()
|
||||||
|
}
|
||||||
Vendored
+52
@@ -0,0 +1,52 @@
|
|||||||
|
package
|
||||||
|
|
||||||
|
public abstract class A {
|
||||||
|
public constructor A()
|
||||||
|
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
|
public abstract override /*1*/ fun hashCode(): kotlin.Int
|
||||||
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
}
|
||||||
|
|
||||||
|
public final class B : A, I {
|
||||||
|
public constructor B()
|
||||||
|
public open override /*2*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
|
public open override /*2*/ fun hashCode(): kotlin.Int
|
||||||
|
public open override /*2*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract class Base {
|
||||||
|
public constructor Base()
|
||||||
|
public abstract fun check(): kotlin.String
|
||||||
|
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 open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract class Derived : Base, Foo {
|
||||||
|
public constructor Derived()
|
||||||
|
public open override /*2*/ /*fake_override*/ fun check(): kotlin.String
|
||||||
|
public open override /*2*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
|
public open override /*2*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||||
|
public open override /*2*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
}
|
||||||
|
|
||||||
|
public final class Derived2 : Derived {
|
||||||
|
public constructor Derived2()
|
||||||
|
public open override /*1*/ fun check(): kotlin.String
|
||||||
|
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 open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface Foo {
|
||||||
|
public open fun check(): kotlin.String
|
||||||
|
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 open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface I {
|
||||||
|
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 open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
}
|
||||||
Generated
+12
@@ -18593,6 +18593,18 @@ public class DiagnosticTestGenerated extends AbstractDiagnosticTest {
|
|||||||
runTest("compiler/testData/diagnostics/tests/java8Overrides/abstractBaseClassMemberNotImplemented_15.kt");
|
runTest("compiler/testData/diagnostics/tests/java8Overrides/abstractBaseClassMemberNotImplemented_15.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("abstractFakeOverrideSuperCall.kt")
|
||||||
|
public void testAbstractFakeOverrideSuperCall() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/java8Overrides/abstractFakeOverrideSuperCall.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("abstractFakeOverrideSuperCallForbidden.kt")
|
||||||
|
public void testAbstractFakeOverrideSuperCallForbidden() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/java8Overrides/abstractFakeOverrideSuperCallForbidden.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestMetadata("abstractVsAbstract.kt")
|
@TestMetadata("abstractVsAbstract.kt")
|
||||||
public void testAbstractVsAbstract() throws Exception {
|
public void testAbstractVsAbstract() throws Exception {
|
||||||
|
|||||||
@@ -253,6 +253,7 @@ enum class LanguageFeature(
|
|||||||
ProhibitConfusingSyntaxInWhenBranches(KOTLIN_1_8, kind = BUG_FIX), // KT-48385
|
ProhibitConfusingSyntaxInWhenBranches(KOTLIN_1_8, kind = BUG_FIX), // KT-48385
|
||||||
UseConsistentRulesForPrivateConstructorsOfSealedClasses(sinceVersion = KOTLIN_1_8, kind = BUG_FIX), // KT-44866
|
UseConsistentRulesForPrivateConstructorsOfSealedClasses(sinceVersion = KOTLIN_1_8, kind = BUG_FIX), // KT-44866
|
||||||
ProgressionsChangingResolve(KOTLIN_1_8), // KT-49276
|
ProgressionsChangingResolve(KOTLIN_1_8), // KT-49276
|
||||||
|
ForbidSuperDelegationToAbstractFakeOverride(KOTLIN_1_8), // KT-49017 (+ KT-38078)
|
||||||
|
|
||||||
// 1.9
|
// 1.9
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user