FIR checker: report NOT_A_FUNCTION_LABEL
This commit is contained in:
committed by
TeamCityServer
parent
ab9a23cbfa
commit
5c716ea979
+6
@@ -3404,6 +3404,12 @@ internal val KT_DIAGNOSTIC_CONVERTER = KtDiagnosticConverterBuilder.buildConvert
|
||||
token,
|
||||
)
|
||||
}
|
||||
add(FirErrors.NOT_A_FUNCTION_LABEL) { firDiagnostic ->
|
||||
NotAFunctionLabelImpl(
|
||||
firDiagnostic as FirPsiDiagnostic,
|
||||
token,
|
||||
)
|
||||
}
|
||||
add(FirErrors.RETURN_IN_FUNCTION_WITH_EXPRESSION_BODY) { firDiagnostic ->
|
||||
ReturnInFunctionWithExpressionBodyImpl(
|
||||
firDiagnostic as FirPsiDiagnostic,
|
||||
|
||||
+4
@@ -2371,6 +2371,10 @@ sealed class KtFirDiagnostic<PSI : PsiElement> : KtDiagnosticWithPsi<PSI> {
|
||||
override val diagnosticClass get() = ReturnNotAllowed::class
|
||||
}
|
||||
|
||||
abstract class NotAFunctionLabel : KtFirDiagnostic<KtReturnExpression>() {
|
||||
override val diagnosticClass get() = NotAFunctionLabel::class
|
||||
}
|
||||
|
||||
abstract class ReturnInFunctionWithExpressionBody : KtFirDiagnostic<KtReturnExpression>() {
|
||||
override val diagnosticClass get() = ReturnInFunctionWithExpressionBody::class
|
||||
}
|
||||
|
||||
+5
@@ -2859,6 +2859,11 @@ internal class ReturnNotAllowedImpl(
|
||||
override val token: ValidityToken,
|
||||
) : KtFirDiagnostic.ReturnNotAllowed(), KtAbstractFirDiagnostic<KtReturnExpression>
|
||||
|
||||
internal class NotAFunctionLabelImpl(
|
||||
override val firDiagnostic: FirPsiDiagnostic,
|
||||
override val token: ValidityToken,
|
||||
) : KtFirDiagnostic.NotAFunctionLabel(), KtAbstractFirDiagnostic<KtReturnExpression>
|
||||
|
||||
internal class ReturnInFunctionWithExpressionBodyImpl(
|
||||
override val firDiagnostic: FirPsiDiagnostic,
|
||||
override val token: ValidityToken,
|
||||
|
||||
+1
@@ -1216,6 +1216,7 @@ object DIAGNOSTICS_LIST : DiagnosticList("FirErrors") {
|
||||
|
||||
val RETURNS by object : DiagnosticGroup("Returns") {
|
||||
val RETURN_NOT_ALLOWED by error<KtReturnExpression>(PositioningStrategy.RETURN_WITH_LABEL)
|
||||
val NOT_A_FUNCTION_LABEL by error<KtReturnExpression>(PositioningStrategy.RETURN_WITH_LABEL)
|
||||
val RETURN_IN_FUNCTION_WITH_EXPRESSION_BODY by error<KtReturnExpression>(PositioningStrategy.RETURN_WITH_LABEL)
|
||||
val NO_RETURN_IN_FUNCTION_WITH_BLOCK_BODY by error<KtDeclarationWithBody>(PositioningStrategy.DECLARATION_WITH_BODY)
|
||||
|
||||
|
||||
@@ -647,6 +647,7 @@ object FirErrors {
|
||||
|
||||
// Returns
|
||||
val RETURN_NOT_ALLOWED by error0<KtReturnExpression>(SourceElementPositioningStrategies.RETURN_WITH_LABEL)
|
||||
val NOT_A_FUNCTION_LABEL by error0<KtReturnExpression>(SourceElementPositioningStrategies.RETURN_WITH_LABEL)
|
||||
val RETURN_IN_FUNCTION_WITH_EXPRESSION_BODY by error0<KtReturnExpression>(SourceElementPositioningStrategies.RETURN_WITH_LABEL)
|
||||
val NO_RETURN_IN_FUNCTION_WITH_BLOCK_BODY by error0<KtDeclarationWithBody>(SourceElementPositioningStrategies.DECLARATION_WITH_BODY)
|
||||
val ANONYMOUS_INITIALIZER_IN_INTERFACE by error0<KtAnonymousInitializer>(SourceElementPositioningStrategies.DECLARATION_SIGNATURE)
|
||||
|
||||
+7
-3
@@ -12,6 +12,8 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.reportOn
|
||||
import org.jetbrains.kotlin.fir.declarations.*
|
||||
import org.jetbrains.kotlin.fir.diagnostics.ConeSimpleDiagnostic
|
||||
import org.jetbrains.kotlin.fir.diagnostics.DiagnosticKind
|
||||
import org.jetbrains.kotlin.fir.expressions.*
|
||||
import org.jetbrains.kotlin.fir.expressions.impl.FirSingleExpressionBlock
|
||||
import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference
|
||||
@@ -24,9 +26,11 @@ object FirReturnAllowedChecker : FirReturnExpressionChecker() {
|
||||
val source = expression.source
|
||||
if (source?.kind == FirFakeSourceElementKind.ImplicitReturn) return
|
||||
|
||||
val targetSymbol = expression.target.labeledElement.symbol
|
||||
|
||||
if (!isReturnAllowed(targetSymbol, context)) {
|
||||
val labeledElement = expression.target.labeledElement
|
||||
val targetSymbol = labeledElement.symbol
|
||||
if (labeledElement is FirErrorFunction && (labeledElement.diagnostic as? ConeSimpleDiagnostic)?.kind == DiagnosticKind.NotAFunctionLabel) {
|
||||
reporter.reportOn(source, FirErrors.NOT_A_FUNCTION_LABEL, context)
|
||||
} else if (!isReturnAllowed(targetSymbol, context)) {
|
||||
reporter.reportOn(source, FirErrors.RETURN_NOT_ALLOWED, context)
|
||||
}
|
||||
|
||||
|
||||
+17
-15
@@ -5,10 +5,10 @@
|
||||
|
||||
package org.jetbrains.kotlin.fir.analysis.diagnostics
|
||||
|
||||
import org.jetbrains.kotlin.diagnostics.rendering.LanguageFeatureMessageRenderer
|
||||
import org.jetbrains.kotlin.diagnostics.rendering.CommonRenderers.RENDER_POSITION_VARIANCE
|
||||
import org.jetbrains.kotlin.diagnostics.rendering.CommonRenderers.STRING
|
||||
import org.jetbrains.kotlin.diagnostics.rendering.CommonRenderers.commaSeparated
|
||||
import org.jetbrains.kotlin.diagnostics.rendering.LanguageFeatureMessageRenderer
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirDiagnosticRenderers.AMBIGUOUS_CALLS
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirDiagnosticRenderers.COLLECTION
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirDiagnosticRenderers.DECLARATION_NAME
|
||||
@@ -165,15 +165,6 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.EXPECTED_FUNCTION
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.EXPECTED_LATEINIT_PROPERTY
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.EXPECTED_PRIVATE_DECLARATION
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.EXPECTED_PROPERTY_INITIALIZER
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.OPT_IN_MARKER_WITH_WRONG_RETENTION
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.OPT_IN_MARKER_WITH_WRONG_TARGET
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.OPT_IN_USAGE
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.OPT_IN_USAGE_ERROR
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.OPT_IN_CAN_ONLY_BE_USED_AS_ANNOTATION
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.OPT_IN_IS_NOT_ENABLED
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.OPT_IN_MARKER_CAN_ONLY_BE_USED_AS_ANNOTATION_OR_ARGUMENT_IN_OPT_IN
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.OPT_IN_OVERRIDE
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.OPT_IN_OVERRIDE_ERROR
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.EXPLICIT_BACKING_FIELD_IN_ABSTRACT_PROPERTY
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.EXPLICIT_BACKING_FIELD_IN_EXTENSION
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.EXPLICIT_BACKING_FIELD_IN_INTERFACE
|
||||
@@ -304,6 +295,7 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NON_VARARG_SPREAD
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NOTHING_TO_INLINE
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NOTHING_TO_OVERRIDE
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NOT_AN_ANNOTATION_CLASS
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NOT_A_FUNCTION_LABEL
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NOT_A_LOOP_LABEL
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NOT_A_SUPERTYPE
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NOT_NULL_ASSERTION_ON_CALLABLE_REFERENCE
|
||||
@@ -326,6 +318,20 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NULLABLE_TYPE_IN_
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NULLABLE_TYPE_OF_ANNOTATION_MEMBER
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ONLY_ONE_CLASS_BOUND_ALLOWED
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.OPERATOR_RENAMED_ON_IMPORT
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.OPT_IN_ARGUMENT_IS_NOT_MARKER
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.OPT_IN_CAN_ONLY_BE_USED_AS_ANNOTATION
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.OPT_IN_IS_NOT_ENABLED
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.OPT_IN_MARKER_CAN_ONLY_BE_USED_AS_ANNOTATION_OR_ARGUMENT_IN_OPT_IN
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.OPT_IN_MARKER_ON_OVERRIDE
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.OPT_IN_MARKER_ON_OVERRIDE_WARNING
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.OPT_IN_MARKER_ON_WRONG_TARGET
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.OPT_IN_MARKER_WITH_WRONG_RETENTION
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.OPT_IN_MARKER_WITH_WRONG_TARGET
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.OPT_IN_OVERRIDE
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.OPT_IN_OVERRIDE_ERROR
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.OPT_IN_USAGE
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.OPT_IN_USAGE_ERROR
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.OPT_IN_WITHOUT_ARGUMENTS
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.OTHER_ERROR
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.OUTER_CLASS_ARGUMENTS_REQUIRED
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.OVERLOAD_RESOLUTION_AMBIGUITY
|
||||
@@ -475,11 +481,6 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.USELESS_ELVIS
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.USELESS_ELVIS_RIGHT_IS_NULL
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.USELESS_IS_CHECK
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.USELESS_VARARG_ON_PARAMETER
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.OPT_IN_ARGUMENT_IS_NOT_MARKER
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.OPT_IN_MARKER_ON_OVERRIDE
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.OPT_IN_MARKER_ON_OVERRIDE_WARNING
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.OPT_IN_MARKER_ON_WRONG_TARGET
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.OPT_IN_WITHOUT_ARGUMENTS
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.VALUE_CLASS_CANNOT_BE_CLONEABLE
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.VALUE_PARAMETER_WITH_NO_TYPE_ANNOTATION
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.VAL_OR_VAR_ON_CATCH_PARAMETER
|
||||
@@ -1619,6 +1620,7 @@ class FirDefaultErrorMessages {
|
||||
|
||||
// Returns
|
||||
map.put(RETURN_NOT_ALLOWED, "'return' is not allowed here")
|
||||
map.put(NOT_A_FUNCTION_LABEL, "Target label does not denote a function")
|
||||
map.put(
|
||||
RETURN_IN_FUNCTION_WITH_EXPRESSION_BODY,
|
||||
"Returns are not allowed for functions with expression body. Use block body in '{...}'"
|
||||
|
||||
+1
@@ -366,6 +366,7 @@ private fun ConeSimpleDiagnostic.getFactory(source: FirSourceElement): FirDiagno
|
||||
return when (kind) {
|
||||
DiagnosticKind.Syntax -> FirErrors.SYNTAX
|
||||
DiagnosticKind.ReturnNotAllowed -> FirErrors.RETURN_NOT_ALLOWED
|
||||
DiagnosticKind.NotAFunctionLabel -> FirErrors.NOT_A_FUNCTION_LABEL
|
||||
DiagnosticKind.UnresolvedLabel -> FirErrors.UNRESOLVED_LABEL
|
||||
DiagnosticKind.NoThis -> FirErrors.NO_THIS
|
||||
DiagnosticKind.IllegalConstExpression -> FirErrors.ILLEGAL_CONST_EXPRESSION
|
||||
|
||||
+5
-1
@@ -183,7 +183,11 @@ abstract class BaseFirBuilder<T>(val baseSession: FirSession, val context: Conte
|
||||
}
|
||||
}
|
||||
target = FirFunctionTarget(labelName, false).apply {
|
||||
bindToErrorFunction("Cannot bind label $labelName to a function", DiagnosticKind.UnresolvedLabel)
|
||||
if (context.firLabels.any { it.name == labelName } || context.firLoopTargets.any { it.labelName == labelName }) {
|
||||
bindToErrorFunction("Label $labelName does not target a function", DiagnosticKind.NotAFunctionLabel)
|
||||
} else {
|
||||
bindToErrorFunction("Cannot bind label $labelName to a function", DiagnosticKind.UnresolvedLabel)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,6 +32,7 @@ enum class DiagnosticKind {
|
||||
|
||||
ReturnNotAllowed,
|
||||
UnresolvedLabel,
|
||||
NotAFunctionLabel,
|
||||
NoThis,
|
||||
IllegalConstExpression,
|
||||
IllegalSelector,
|
||||
|
||||
+2
-2
@@ -31,7 +31,7 @@ fun testAnnotatedLambdaLabel() =
|
||||
|
||||
fun testLambdaMultipleLabels1() =
|
||||
lambda1@ lambda2@ {
|
||||
<!RETURN_NOT_ALLOWED!>return@lambda1<!>
|
||||
<!NOT_A_FUNCTION_LABEL!>return@lambda1<!>
|
||||
}
|
||||
|
||||
fun testLambdaMultipleLabels2() =
|
||||
@@ -46,7 +46,7 @@ fun testAnonymousFunctionLabel() =
|
||||
|
||||
fun testLoopLabelInReturn(xs: List<Int>) {
|
||||
L@ for (x in xs) {
|
||||
if (x > 0) <!RETURN_NOT_ALLOWED!>return@L<!>
|
||||
if (x > 0) <!NOT_A_FUNCTION_LABEL!>return@L<!>
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+2
-2
@@ -31,7 +31,7 @@ fun testAnnotatedLambdaLabel() =
|
||||
|
||||
fun testLambdaMultipleLabels1() =
|
||||
lambda1@ lambda2@ {
|
||||
<!RETURN_NOT_ALLOWED!>return@lambda1<!>
|
||||
<!NOT_A_FUNCTION_LABEL!>return@lambda1<!>
|
||||
}
|
||||
|
||||
fun testLambdaMultipleLabels2() =
|
||||
@@ -46,7 +46,7 @@ fun testAnonymousFunctionLabel() =
|
||||
|
||||
fun testLoopLabelInReturn(xs: List<Int>) {
|
||||
L@ for (x in xs) {
|
||||
if (x > 0) <!RETURN_NOT_ALLOWED!>return@L<!>
|
||||
if (x > 0) <!NOT_A_FUNCTION_LABEL!>return@L<!>
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user