Forbid usages of super if in fact it accesses an abstract member

#KT-49017 Fixed
This commit is contained in:
Mikhail Glukhikh
2022-01-10 14:19:19 +03:00
parent d15270b9e5
commit b689bbf5c7
23 changed files with 279 additions and 4 deletions
@@ -18587,6 +18587,18 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirDiagnosti
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
@TestMetadata("abstractVsAbstract.kt")
public void testAbstractVsAbstract() throws Exception {
@@ -18587,6 +18587,18 @@ public class FirOldFrontendDiagnosticsWithLightTreeTestGenerated extends Abstrac
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
@TestMetadata("abstractVsAbstract.kt")
public void testAbstractVsAbstract() throws Exception {
@@ -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_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_WARNING by warning<PsiElement>(PositioningStrategy.REFERENCED_NAME_BY_QUALIFIED)
val INSTANCE_ACCESS_BEFORE_SUPER_CALL by error<PsiElement> {
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_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_WARNING by warning0<PsiElement>(SourceElementPositioningStrategies.REFERENCED_NAME_BY_QUALIFIED)
val INSTANCE_ACCESS_BEFORE_SUPER_CALL by error1<PsiElement, String>()
// Supertypes
@@ -5,12 +5,14 @@
package org.jetbrains.kotlin.fir.analysis.checkers.expression
import org.jetbrains.kotlin.config.LanguageFeature
import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
import org.jetbrains.kotlin.fir.analysis.checkers.context.findClosest
import org.jetbrains.kotlin.diagnostics.DiagnosticReporter
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
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.declarations.FirRegularClass
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.references.FirSuperReference
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.utils.addToStdlib.safeAs
@@ -37,8 +40,22 @@ object FirAbstractSuperCallChecker : FirQualifiedAccessExpressionChecker() {
val containingClassSymbol = declarationSymbol.containingClass()?.toSymbol(context.session) as? FirRegularClassSymbol ?: return
if (containingClassSymbol.isAbstract && declarationSymbol.isAbstract) {
reporter.reportOn(expression.calleeReference.source, FirErrors.ABSTRACT_SUPER_CALL, context)
if (containingClassSymbol.isAbstract) {
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)
}
}
}
}
}
}
@@ -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_SETTER
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.ACTUAL_ANNOTATION_CONFLICTING_DEFAULT_ARGUMENT_VALUE
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_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_WARNING, "Abstract fake override member access is deprecated")
map.put(
INSTANCE_ACCESS_BEFORE_SUPER_CALL,
"Cannot access ''{0}'' before superclass constructor has been called",