[FIR] Forbid creating abstract class instances via any qualified access
^KT-58938 Fixed
This commit is contained in:
committed by
Space Team
parent
fccb391f31
commit
5daec16ce0
+6
@@ -34,6 +34,12 @@ public class DiagnosticCompilerTestFE10TestdataTestGenerated extends AbstractDia
|
|||||||
runTest("compiler/testData/diagnostics/tests/AbstractAccessor.kt");
|
runTest("compiler/testData/diagnostics/tests/AbstractAccessor.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("abstractClassReference.kt")
|
||||||
|
public void testAbstractClassReference() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/abstractClassReference.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestMetadata("AbstractInAbstractClass.kt")
|
@TestMetadata("AbstractInAbstractClass.kt")
|
||||||
public void testAbstractInAbstractClass() throws Exception {
|
public void testAbstractInAbstractClass() throws Exception {
|
||||||
|
|||||||
+6
@@ -34,6 +34,12 @@ public class LLFirPreresolvedReversedDiagnosticCompilerFE10TestDataTestGenerated
|
|||||||
runTest("compiler/testData/diagnostics/tests/AbstractAccessor.kt");
|
runTest("compiler/testData/diagnostics/tests/AbstractAccessor.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("abstractClassReference.kt")
|
||||||
|
public void testAbstractClassReference() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/abstractClassReference.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestMetadata("AbstractInAbstractClass.kt")
|
@TestMetadata("AbstractInAbstractClass.kt")
|
||||||
public void testAbstractInAbstractClass() throws Exception {
|
public void testAbstractInAbstractClass() throws Exception {
|
||||||
|
|||||||
+6
@@ -34,6 +34,12 @@ public class FirLightTreeOldFrontendDiagnosticsTestGenerated extends AbstractFir
|
|||||||
runTest("compiler/testData/diagnostics/tests/AbstractAccessor.kt");
|
runTest("compiler/testData/diagnostics/tests/AbstractAccessor.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("abstractClassReference.kt")
|
||||||
|
public void testAbstractClassReference() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/abstractClassReference.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestMetadata("AbstractInAbstractClass.kt")
|
@TestMetadata("AbstractInAbstractClass.kt")
|
||||||
public void testAbstractInAbstractClass() throws Exception {
|
public void testAbstractInAbstractClass() throws Exception {
|
||||||
|
|||||||
+6
@@ -34,6 +34,12 @@ public class FirPsiOldFrontendDiagnosticsTestGenerated extends AbstractFirPsiDia
|
|||||||
runTest("compiler/testData/diagnostics/tests/AbstractAccessor.kt");
|
runTest("compiler/testData/diagnostics/tests/AbstractAccessor.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("abstractClassReference.kt")
|
||||||
|
public void testAbstractClassReference() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/abstractClassReference.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestMetadata("AbstractInAbstractClass.kt")
|
@TestMetadata("AbstractInAbstractClass.kt")
|
||||||
public void testAbstractInAbstractClass() throws Exception {
|
public void testAbstractInAbstractClass() throws Exception {
|
||||||
|
|||||||
+1
@@ -48,6 +48,7 @@ object CommonExpressionCheckers : ExpressionCheckers() {
|
|||||||
FirReifiedChecker,
|
FirReifiedChecker,
|
||||||
FirSuspendCallChecker,
|
FirSuspendCallChecker,
|
||||||
FirLateinitIntrinsicApplicabilityChecker,
|
FirLateinitIntrinsicApplicabilityChecker,
|
||||||
|
FirAbstractClassInstantiationChecker,
|
||||||
)
|
)
|
||||||
|
|
||||||
override val callCheckers: Set<FirCallChecker>
|
override val callCheckers: Set<FirCallChecker>
|
||||||
|
|||||||
+34
@@ -0,0 +1,34 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.fir.analysis.checkers.expression
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.descriptors.ClassKind
|
||||||
|
import org.jetbrains.kotlin.diagnostics.DiagnosticReporter
|
||||||
|
import org.jetbrains.kotlin.diagnostics.reportOn
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
||||||
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
||||||
|
import org.jetbrains.kotlin.fir.declarations.utils.isAbstract
|
||||||
|
import org.jetbrains.kotlin.fir.expressions.FirCallableReferenceAccess
|
||||||
|
import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccessExpression
|
||||||
|
import org.jetbrains.kotlin.fir.references.toResolvedConstructorSymbol
|
||||||
|
import org.jetbrains.kotlin.fir.types.coneType
|
||||||
|
import org.jetbrains.kotlin.fir.types.toRegularClassSymbol
|
||||||
|
|
||||||
|
object FirAbstractClassInstantiationChecker : FirQualifiedAccessExpressionChecker() {
|
||||||
|
override fun check(expression: FirQualifiedAccessExpression, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||||
|
val constructorSymbol = expression.calleeReference.toResolvedConstructorSymbol() ?: return
|
||||||
|
val declarationClass = constructorSymbol.resolvedReturnTypeRef.coneType.toRegularClassSymbol(context.session) ?: return
|
||||||
|
|
||||||
|
if (declarationClass.isAbstract && declarationClass.classKind == ClassKind.CLASS) {
|
||||||
|
val source = when (expression) {
|
||||||
|
is FirCallableReferenceAccess -> expression.calleeReference.source
|
||||||
|
else -> expression.source
|
||||||
|
}
|
||||||
|
|
||||||
|
reporter.reportOn(source, FirErrors.CREATING_AN_INSTANCE_OF_ABSTRACT_CLASS, context)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
-3
@@ -25,9 +25,6 @@ object FirConstructorCallChecker : FirFunctionCallChecker() {
|
|||||||
val declarationClass = constructorSymbol.resolvedReturnTypeRef.coneType.toRegularClassSymbol(context.session)
|
val declarationClass = constructorSymbol.resolvedReturnTypeRef.coneType.toRegularClassSymbol(context.session)
|
||||||
|
|
||||||
if (declarationClass != null) {
|
if (declarationClass != null) {
|
||||||
if (declarationClass.isAbstract && declarationClass.classKind == ClassKind.CLASS) {
|
|
||||||
reporter.reportOn(expression.source, FirErrors.CREATING_AN_INSTANCE_OF_ABSTRACT_CLASS, context)
|
|
||||||
}
|
|
||||||
if (declarationClass.classKind == ClassKind.ANNOTATION_CLASS &&
|
if (declarationClass.classKind == ClassKind.ANNOTATION_CLASS &&
|
||||||
context.qualifiedAccessOrAssignmentsOrAnnotationCalls.all { call ->
|
context.qualifiedAccessOrAssignmentsOrAnnotationCalls.all { call ->
|
||||||
call !is FirAnnotation
|
call !is FirAnnotation
|
||||||
|
|||||||
@@ -0,0 +1,9 @@
|
|||||||
|
// FIR_IDENTICAL
|
||||||
|
// ISSUE: KT-58938
|
||||||
|
|
||||||
|
abstract class AbstractClass()
|
||||||
|
|
||||||
|
fun main(args: Array<String>) {
|
||||||
|
val abstractClass = ::<!CREATING_AN_INSTANCE_OF_ABSTRACT_CLASS!>AbstractClass<!>
|
||||||
|
abstractClass.invoke()
|
||||||
|
}
|
||||||
Vendored
+1
-1
@@ -6,7 +6,7 @@ enum class D
|
|||||||
|
|
||||||
fun main() {
|
fun main() {
|
||||||
::<!UNRESOLVED_REFERENCE!>A<!>
|
::<!UNRESOLVED_REFERENCE!>A<!>
|
||||||
::B
|
::<!CREATING_AN_INSTANCE_OF_ABSTRACT_CLASS!>B<!>
|
||||||
::<!CALLABLE_REFERENCE_TO_ANNOTATION_CONSTRUCTOR!>C<!> // KT-3465
|
::<!CALLABLE_REFERENCE_TO_ANNOTATION_CONSTRUCTOR!>C<!> // KT-3465
|
||||||
::<!UNRESOLVED_REFERENCE!>D<!>
|
::<!UNRESOLVED_REFERENCE!>D<!>
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +0,0 @@
|
|||||||
|
|
||||||
abstract class Abstract
|
|
||||||
|
|
||||||
fun <D> create(fn: () -> D): D {
|
|
||||||
return fn()
|
|
||||||
}
|
|
||||||
|
|
||||||
fun main() {
|
|
||||||
create(::Abstract)
|
|
||||||
}
|
|
||||||
@@ -1,3 +1,4 @@
|
|||||||
|
// FIR_IDENTICAL
|
||||||
|
|
||||||
abstract class Abstract
|
abstract class Abstract
|
||||||
|
|
||||||
|
|||||||
Generated
+6
@@ -34,6 +34,12 @@ public class DiagnosticTestGenerated extends AbstractDiagnosticTest {
|
|||||||
runTest("compiler/testData/diagnostics/tests/AbstractAccessor.kt");
|
runTest("compiler/testData/diagnostics/tests/AbstractAccessor.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("abstractClassReference.kt")
|
||||||
|
public void testAbstractClassReference() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/abstractClassReference.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestMetadata("AbstractInAbstractClass.kt")
|
@TestMetadata("AbstractInAbstractClass.kt")
|
||||||
public void testAbstractInAbstractClass() throws Exception {
|
public void testAbstractInAbstractClass() throws Exception {
|
||||||
|
|||||||
Reference in New Issue
Block a user