diff --git a/compiler/fir/analysis-tests/testData/resolve/diagnostics/superIsNotAnExpression.kt b/compiler/fir/analysis-tests/testData/resolve/diagnostics/superIsNotAnExpression.kt new file mode 100644 index 00000000000..3d2ec315190 --- /dev/null +++ b/compiler/fir/analysis-tests/testData/resolve/diagnostics/superIsNotAnExpression.kt @@ -0,0 +1,13 @@ +class A + +class B: A() { + fun act() { + super() + + invoke() + + super { + println('weird') + } + } +} diff --git a/compiler/fir/analysis-tests/testData/resolve/diagnostics/superIsNotAnExpression.txt b/compiler/fir/analysis-tests/testData/resolve/diagnostics/superIsNotAnExpression.txt new file mode 100644 index 00000000000..bf84fa6d262 --- /dev/null +++ b/compiler/fir/analysis-tests/testData/resolve/diagnostics/superIsNotAnExpression.txt @@ -0,0 +1,22 @@ +FILE: superIsNotAnExpression.kt + public final class A : R|kotlin/Any| { + public constructor(): R|A| { + super() + } + + } + public final class B : R|A| { + public constructor(): R|B| { + super() + } + + public final fun act(): R|kotlin/Unit| { + #() + #() + #( = @fun .(): { + println#(ERROR_EXPR(Incorrect character: 'weird')) + } + ) + } + + } diff --git a/compiler/fir/analysis-tests/tests/org/jetbrains/kotlin/fir/FirDiagnosticsTestGenerated.java b/compiler/fir/analysis-tests/tests/org/jetbrains/kotlin/fir/FirDiagnosticsTestGenerated.java index e499306b6d9..98643e10dc8 100644 --- a/compiler/fir/analysis-tests/tests/org/jetbrains/kotlin/fir/FirDiagnosticsTestGenerated.java +++ b/compiler/fir/analysis-tests/tests/org/jetbrains/kotlin/fir/FirDiagnosticsTestGenerated.java @@ -739,6 +739,11 @@ public class FirDiagnosticsTestGenerated extends AbstractFirDiagnosticsTest { public void testInfixFunctions() throws Exception { runTest("compiler/fir/analysis-tests/testData/resolve/diagnostics/infixFunctions.kt"); } + + @TestMetadata("superIsNotAnExpression.kt") + public void testSuperIsNotAnExpression() throws Exception { + runTest("compiler/fir/analysis-tests/testData/resolve/diagnostics/superIsNotAnExpression.kt"); + } } @TestMetadata("compiler/fir/analysis-tests/testData/resolve/expresssions") diff --git a/compiler/fir/analysis-tests/tests/org/jetbrains/kotlin/fir/FirDiagnosticsWithLightTreeTestGenerated.java b/compiler/fir/analysis-tests/tests/org/jetbrains/kotlin/fir/FirDiagnosticsWithLightTreeTestGenerated.java index 16606de8a5c..b542ccdd78b 100644 --- a/compiler/fir/analysis-tests/tests/org/jetbrains/kotlin/fir/FirDiagnosticsWithLightTreeTestGenerated.java +++ b/compiler/fir/analysis-tests/tests/org/jetbrains/kotlin/fir/FirDiagnosticsWithLightTreeTestGenerated.java @@ -739,6 +739,11 @@ public class FirDiagnosticsWithLightTreeTestGenerated extends AbstractFirDiagnos public void testInfixFunctions() throws Exception { runTest("compiler/fir/analysis-tests/testData/resolve/diagnostics/infixFunctions.kt"); } + + @TestMetadata("superIsNotAnExpression.kt") + public void testSuperIsNotAnExpression() throws Exception { + runTest("compiler/fir/analysis-tests/testData/resolve/diagnostics/superIsNotAnExpression.kt"); + } } @TestMetadata("compiler/fir/analysis-tests/testData/resolve/expresssions") diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/collectors/components/ErrorNodeDiagnosticCollectorComponent.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/collectors/components/ErrorNodeDiagnosticCollectorComponent.kt index 2c901906c66..759d78e24b6 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/collectors/components/ErrorNodeDiagnosticCollectorComponent.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/collectors/components/ErrorNodeDiagnosticCollectorComponent.kt @@ -7,18 +7,17 @@ package org.jetbrains.kotlin.fir.analysis.collectors.components import com.intellij.psi.PsiElement import org.jetbrains.kotlin.diagnostics.DiagnosticFactory0 +import org.jetbrains.kotlin.diagnostics.DiagnosticFactory1 import org.jetbrains.kotlin.diagnostics.Errors import org.jetbrains.kotlin.fir.FirSourceElement import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext import org.jetbrains.kotlin.fir.analysis.collectors.AbstractDiagnosticCollector +import org.jetbrains.kotlin.fir.analysis.diagnostics.ConeDiagnostic import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors import org.jetbrains.kotlin.fir.analysis.diagnostics.onSource import org.jetbrains.kotlin.fir.declarations.FirErrorFunction -import org.jetbrains.kotlin.fir.diagnostics.DiagnosticKind -import org.jetbrains.kotlin.fir.diagnostics.FirDiagnostic -import org.jetbrains.kotlin.fir.diagnostics.FirSimpleDiagnostic -import org.jetbrains.kotlin.fir.diagnostics.FirStubDiagnostic +import org.jetbrains.kotlin.fir.diagnostics.* import org.jetbrains.kotlin.fir.expressions.FirErrorExpression import org.jetbrains.kotlin.fir.expressions.FirErrorLoop import org.jetbrains.kotlin.fir.references.FirErrorNamedReference @@ -62,6 +61,7 @@ class ErrorNodeDiagnosticCollectorComponent(collector: AbstractDiagnosticCollect is FirVariableExpectedError -> Errors.VARIABLE_EXPECTED.onSource(source) is FirTypeMismatchError -> FirErrors.TYPE_MISMATCH.onSource(source, diagnostic.expectedType, diagnostic.actualType) is FirSimpleDiagnostic -> diagnostic.getFactory().onSource(source) + is FirDiagnosticWithParameters1<*> -> diagnostic.getFactory().tryOnSource(source, diagnostic.a) is FirStubDiagnostic -> null else -> throw IllegalArgumentException("Unsupported diagnostic type: ${diagnostic.javaClass}") } @@ -85,6 +85,23 @@ class ErrorNodeDiagnosticCollectorComponent(collector: AbstractDiagnosticCollect DiagnosticKind.RecursionInImplicitTypes -> FirErrors.RECURSION_IN_IMPLICIT_TYPES DiagnosticKind.Java -> FirErrors.ERROR_FROM_JAVA_RESOLUTION DiagnosticKind.Other -> FirErrors.OTHER_ERROR + else -> throw IllegalArgumentException("Unsupported diagnostic kind: $kind at $javaClass") } as DiagnosticFactory0 } + + private fun FirDiagnosticWithParameters1<*>.getFactory(): DiagnosticFactory1 { + @Suppress("UNCHECKED_CAST") + return when (kind) { + DiagnosticKind.SuperNotAllowed -> Errors.SUPER_IS_NOT_AN_EXPRESSION + else -> throw IllegalArgumentException("Unsupported diagnostic kind: $kind at $javaClass") + } as DiagnosticFactory1 + } + + private inline fun DiagnosticFactory1.tryOnSource( + source: FirSourceElement, + a: Any? + ): ConeDiagnostic? { + val aa = a as? A ?: throw IllegalArgumentException("Parameter passed to the factory is of incompatible type!") + return onSource(source, aa) + } } \ No newline at end of file diff --git a/compiler/fir/lightTree/src/org/jetbrains/kotlin/fir/lightTree/converter/ExpressionsConverter.kt b/compiler/fir/lightTree/src/org/jetbrains/kotlin/fir/lightTree/converter/ExpressionsConverter.kt index dbb520fe87c..49d62c2d42c 100644 --- a/compiler/fir/lightTree/src/org/jetbrains/kotlin/fir/lightTree/converter/ExpressionsConverter.kt +++ b/compiler/fir/lightTree/src/org/jetbrains/kotlin/fir/lightTree/converter/ExpressionsConverter.kt @@ -19,6 +19,7 @@ import org.jetbrains.kotlin.fir.declarations.builder.buildProperty import org.jetbrains.kotlin.fir.declarations.builder.buildValueParameter import org.jetbrains.kotlin.fir.declarations.impl.FirDeclarationStatusImpl import org.jetbrains.kotlin.fir.diagnostics.DiagnosticKind +import org.jetbrains.kotlin.fir.diagnostics.FirDiagnosticWithParameters1 import org.jetbrains.kotlin.fir.diagnostics.FirSimpleDiagnostic import org.jetbrains.kotlin.fir.expressions.* import org.jetbrains.kotlin.fir.expressions.builder.* @@ -465,12 +466,16 @@ class ExpressionsConverter( val valueArguments = mutableListOf() var additionalArgument: FirExpression? = null var hasArguments = false + var superNode: LighterASTNode? = null callSuffix.forEachChildren { child -> fun process(node: LighterASTNode) { when (node.tokenType) { REFERENCE_EXPRESSION -> { name = node.asText } + SUPER_EXPRESSION -> { + superNode = node + } PARENTHESIZED -> node.getExpressionInParentheses()?.let { process(it) } ?: run { additionalArgument = getAsFirExpression(node, "Incorrect invoke receiver") } @@ -495,7 +500,16 @@ class ExpressionsConverter( additionalArgument != null -> { buildSimpleNamedReference { this.name = OperatorNameConventions.INVOKE } to additionalArgument!! } - else -> buildErrorNamedReference {diagnostic = FirSimpleDiagnostic("Call has no callee", DiagnosticKind.Syntax) } to null + superNode != null -> { + buildErrorNamedReference { + val node = superNode!! + source = node.toFirSourceElement() + diagnostic = FirDiagnosticWithParameters1("Super cannot be a callee", node.asText, DiagnosticKind.SuperNotAllowed) + } to null + } + else -> buildErrorNamedReference { + diagnostic = FirSimpleDiagnostic("Call has no callee", DiagnosticKind.Syntax) + } to null } val builder: FirQualifiedAccessBuilder = if (hasArguments) { diff --git a/compiler/fir/psi2fir/src/org/jetbrains/kotlin/fir/builder/RawFirBuilder.kt b/compiler/fir/psi2fir/src/org/jetbrains/kotlin/fir/builder/RawFirBuilder.kt index cd20b938da2..5a3e3c3b036 100644 --- a/compiler/fir/psi2fir/src/org/jetbrains/kotlin/fir/builder/RawFirBuilder.kt +++ b/compiler/fir/psi2fir/src/org/jetbrains/kotlin/fir/builder/RawFirBuilder.kt @@ -19,6 +19,7 @@ import org.jetbrains.kotlin.fir.declarations.impl.FirDefaultPropertyAccessor import org.jetbrains.kotlin.fir.declarations.impl.FirDefaultPropertyGetter import org.jetbrains.kotlin.fir.declarations.impl.FirDefaultPropertySetter import org.jetbrains.kotlin.fir.diagnostics.DiagnosticKind +import org.jetbrains.kotlin.fir.diagnostics.FirDiagnosticWithParameters1 import org.jetbrains.kotlin.fir.diagnostics.FirSimpleDiagnostic import org.jetbrains.kotlin.fir.expressions.* import org.jetbrains.kotlin.fir.expressions.builder.* @@ -1489,6 +1490,13 @@ class RawFirBuilder( buildErrorNamedReference { diagnostic = FirSimpleDiagnostic("Call has no callee", DiagnosticKind.Syntax) } to null } + is KtSuperExpression -> { + buildErrorNamedReference { + source = calleeExpression.toFirSourceElement() + diagnostic = FirDiagnosticWithParameters1("Super cannot be a callee", calleeExpression.text, DiagnosticKind.SuperNotAllowed) + } to null + } + else -> { buildSimpleNamedReference { source = defaultSource diff --git a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/diagnostics/FirSimpleDiagnostic.kt b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/diagnostics/FirSimpleDiagnostic.kt index 430b80b8fa3..7dbcefa63ca 100644 --- a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/diagnostics/FirSimpleDiagnostic.kt +++ b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/diagnostics/FirSimpleDiagnostic.kt @@ -7,6 +7,8 @@ package org.jetbrains.kotlin.fir.diagnostics class FirSimpleDiagnostic(override val reason: String, val kind: DiagnosticKind = DiagnosticKind.Other) : FirDiagnostic() +class FirDiagnosticWithParameters1(override val reason: String, val a: A, val kind: DiagnosticKind = DiagnosticKind.Other) : FirDiagnostic() + enum class DiagnosticKind { Syntax, ReturnNotAllowed, @@ -21,5 +23,6 @@ enum class DiagnosticKind { RecursionInSupertypes, RecursionInImplicitTypes, Java, + SuperNotAllowed, Other } \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/thisAndSuper/implicitInvokeOnSuper.fir.kt b/compiler/testData/diagnostics/tests/thisAndSuper/implicitInvokeOnSuper.fir.kt deleted file mode 100644 index 87fa9a1ce94..00000000000 --- a/compiler/testData/diagnostics/tests/thisAndSuper/implicitInvokeOnSuper.fir.kt +++ /dev/null @@ -1,15 +0,0 @@ -// !DIAGNOSTICS: -UNUSED_PARAMETER - -open class A { - operator fun invoke() {} - operator fun invoke(f: () -> Unit) {} -} - -class B : A() { - fun bar() { - super() - (super)() - super {} - (super) {} - } -} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/thisAndSuper/implicitInvokeOnSuper.kt b/compiler/testData/diagnostics/tests/thisAndSuper/implicitInvokeOnSuper.kt index a997400e73f..85519178692 100644 --- a/compiler/testData/diagnostics/tests/thisAndSuper/implicitInvokeOnSuper.kt +++ b/compiler/testData/diagnostics/tests/thisAndSuper/implicitInvokeOnSuper.kt @@ -1,3 +1,4 @@ +// FIR_IDENTICAL // !DIAGNOSTICS: -UNUSED_PARAMETER open class A {