From bdfc879f0050d152463c78507f81b2c198179d28 Mon Sep 17 00:00:00 2001 From: Jinseong Jeon Date: Thu, 22 Apr 2021 23:48:15 -0700 Subject: [PATCH] FIR checker: report UNINITIALIZED_PARAMETER --- .../diagnostics/FirDiagnosticsList.kt | 3 ++ .../fir/analysis/diagnostics/FirErrors.kt | 1 + .../FirFunctionParameterChecker.kt | 35 +++++++++++++++++++ .../diagnostics/FirDefaultErrorMessages.kt | 4 ++- .../body/resolve/BodyResolveContext.kt | 32 +++++++++++------ .../FirDeclarationsResolveTransformer.kt | 4 +-- .../FirExpressionsResolveTransformer.kt | 2 +- compiler/testData/cli/jvm/firError.out | 2 +- .../defaultArguments/useNextParamInLambda.kt | 1 - .../DefaultValuesCheckWithoutBody.fir.kt | 9 ----- .../tests/DefaultValuesCheckWithoutBody.kt | 1 + .../tests/DefaultValuesTypechecking.fir.kt | 29 +++++++++++++-- .../tests/DefaultValuesTypechecking.kt | 23 ++++++++++++ .../tests/DefaultValuesTypechecking.txt | 5 +++ ...ameterAsDefaultValueInLocalFunction.fir.kt | 6 ---- .../parameterAsDefaultValueInLocalFunction.kt | 4 ++- .../resolve/underscoreInCatchBlock.fir.kt | 2 +- ...scoreInCatchBlockWithEnabledFeature.fir.kt | 2 +- .../diagnostics/KtFirDataClassConverters.kt | 7 ++++ .../api/fir/diagnostics/KtFirDiagnostics.kt | 5 +++ .../fir/diagnostics/KtFirDiagnosticsImpl.kt | 8 +++++ 21 files changed, 146 insertions(+), 39 deletions(-) delete mode 100644 compiler/testData/diagnostics/tests/DefaultValuesCheckWithoutBody.fir.kt delete mode 100644 compiler/testData/diagnostics/tests/resolve/parameterAsDefaultValueInLocalFunction.fir.kt diff --git a/compiler/fir/checkers/checkers-component-generator/src/org/jetbrains/kotlin/fir/checkers/generator/diagnostics/FirDiagnosticsList.kt b/compiler/fir/checkers/checkers-component-generator/src/org/jetbrains/kotlin/fir/checkers/generator/diagnostics/FirDiagnosticsList.kt index 30f84b407a5..1bd239e7ed5 100644 --- a/compiler/fir/checkers/checkers-component-generator/src/org/jetbrains/kotlin/fir/checkers/generator/diagnostics/FirDiagnosticsList.kt +++ b/compiler/fir/checkers/checkers-component-generator/src/org/jetbrains/kotlin/fir/checkers/generator/diagnostics/FirDiagnosticsList.kt @@ -605,6 +605,9 @@ object DIAGNOSTICS_LIST : DiagnosticList() { val UNINITIALIZED_VARIABLE by error { parameter("variable") } + val UNINITIALIZED_PARAMETER by error { + parameter>("parameter") + } val UNINITIALIZED_ENUM_ENTRY by error { parameter>("enumEntry") } diff --git a/compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrors.kt b/compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrors.kt index 0e98d6ba236..3cc61bd4d0f 100644 --- a/compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrors.kt +++ b/compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrors.kt @@ -370,6 +370,7 @@ object FirErrors { // Control flow diagnostics val UNINITIALIZED_VARIABLE by error1() + val UNINITIALIZED_PARAMETER by error1>() val UNINITIALIZED_ENUM_ENTRY by error1>() val UNINITIALIZED_ENUM_COMPANION by error1(SourceElementPositioningStrategies.REFERENCE_BY_QUALIFIED) val VAL_REASSIGNMENT by error1>() diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirFunctionParameterChecker.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirFunctionParameterChecker.kt index a458a051490..1b3ca6e6233 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirFunctionParameterChecker.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirFunctionParameterChecker.kt @@ -5,6 +5,7 @@ package org.jetbrains.kotlin.fir.analysis.checkers.declaration +import org.jetbrains.kotlin.fir.FirElement import org.jetbrains.kotlin.fir.FirRealSourceElementKind import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext import org.jetbrains.kotlin.fir.analysis.checkers.isInline @@ -12,19 +13,24 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors import org.jetbrains.kotlin.fir.analysis.diagnostics.reportOnWithSuppression import org.jetbrains.kotlin.fir.declarations.FirFunction +import org.jetbrains.kotlin.fir.declarations.FirValueParameter import org.jetbrains.kotlin.fir.diagnostics.ConeSimpleDiagnostic import org.jetbrains.kotlin.fir.diagnostics.DiagnosticKind +import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccessExpression +import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference import org.jetbrains.kotlin.fir.typeContext import org.jetbrains.kotlin.fir.types.FirErrorTypeRef import org.jetbrains.kotlin.fir.types.arrayElementType import org.jetbrains.kotlin.fir.types.coneType import org.jetbrains.kotlin.fir.types.isUnsignedTypeOrNullableUnsignedType +import org.jetbrains.kotlin.fir.visitors.FirVisitorVoid import org.jetbrains.kotlin.types.AbstractTypeChecker object FirFunctionParameterChecker : FirFunctionChecker() { override fun check(declaration: FirFunction<*>, context: CheckerContext, reporter: DiagnosticReporter) { checkVarargParameters(declaration, context, reporter) checkParameterTypes(declaration, context, reporter) + checkUninitializedParameter(declaration, context, reporter) } private fun checkParameterTypes(declaration: FirFunction<*>, context: CheckerContext, reporter: DiagnosticReporter) { @@ -70,4 +76,33 @@ object FirFunctionParameterChecker : FirFunctionChecker() { } } } + + private fun checkUninitializedParameter(function: FirFunction<*>, context: CheckerContext, reporter: DiagnosticReporter) { + for ((index, parameter) in function.valueParameters.withIndex()) { + // Alas, CheckerContext.qualifiedAccesses stack is not available at this point. + // Thus, manually visit default value expression and report the diagnostic on qualified accesses of interest. + parameter.defaultValue?.accept(object : FirVisitorVoid() { + override fun visitElement(element: FirElement) { + element.acceptChildren(this) + } + + override fun visitQualifiedAccessExpression(qualifiedAccessExpression: FirQualifiedAccessExpression) { + val namedReference = qualifiedAccessExpression.calleeReference as? FirResolvedNamedReference ?: return + val referredParameter = namedReference.resolvedSymbol.fir as? FirValueParameter ?: return + val referredParameterIndex = function.valueParameters.indexOf(referredParameter) + // Skip if the referred parameter is not declared in the same function. + if (referredParameterIndex < 0) return + + if (index <= referredParameterIndex) { + reporter.reportOnWithSuppression( + qualifiedAccessExpression, + FirErrors.UNINITIALIZED_PARAMETER, + referredParameter.symbol, + context + ) + } + } + }) + } + } } diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirDefaultErrorMessages.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirDefaultErrorMessages.kt index 1550b33aefa..554f94c417b 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirDefaultErrorMessages.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirDefaultErrorMessages.kt @@ -271,6 +271,7 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.TYPE_PARAMETER_ON import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.UNEXPECTED_SAFE_CALL import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.UNINITIALIZED_ENUM_COMPANION import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.UNINITIALIZED_ENUM_ENTRY +import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.UNINITIALIZED_PARAMETER import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.UNINITIALIZED_VARIABLE import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.UNNECESSARY_LATEINIT import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.UNNECESSARY_NOT_NULL_ASSERTION @@ -830,7 +831,8 @@ class FirDefaultErrorMessages : DefaultErrorMessages.Extension { ) // Control flow diagnostics - map.put(UNINITIALIZED_VARIABLE, "{0} must be initialized before access", VARIABLE_NAME) + map.put(UNINITIALIZED_VARIABLE, "Variable ''{0}'' must be initialized", VARIABLE_NAME) + map.put(UNINITIALIZED_PARAMETER, "Parameter ''{0}'' is uninitialized here", VARIABLE_NAME) map.put(UNINITIALIZED_ENUM_ENTRY, "Enum entry ''{0}'' is uninitialized here", VARIABLE_NAME) map.put(UNINITIALIZED_ENUM_COMPANION, "Companion object of enum class ''{0}'' is uninitialized here", SYMBOL) map.put(VAL_REASSIGNMENT, "Val cannot be reassigned", VARIABLE_NAME) diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/BodyResolveContext.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/BodyResolveContext.kt index f37f9a357db..67a66f973ce 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/BodyResolveContext.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/BodyResolveContext.kt @@ -238,7 +238,7 @@ class BodyResolveContext( return FirMemberTypeParameterScope(this) } - private fun buildSecondaryConstructorParametersScope(constructor: FirConstructor): FirLocalScope = + fun buildSecondaryConstructorParametersScope(constructor: FirConstructor): FirLocalScope = constructor.valueParameters.fold(FirLocalScope()) { acc, param -> acc.storeVariable(param) } @PrivateForInline @@ -486,6 +486,12 @@ class BodyResolveContext( return withTowerDataCleanup { addLocalScope(FirLocalScope()) if (function is FirSimpleFunction) { + // Make all value parameters available in the local scope so that even one parameter that refers to another parameter, + // which may not be initialized yet, can be resolved. [FirFunctionParameterChecker] will detect and report an error + // if an uninitialized parameter is accessed by a preceding parameter. + for (parameter in function.valueParameters) { + storeVariable(parameter) + } val receiverTypeRef = function.receiverTypeRef withLabelAndReceiverType(function.name, function, receiverTypeRef?.coneType, holder, f) } else { @@ -665,19 +671,23 @@ class BodyResolveContext( f: () -> T ): T { // Default values of constructor can't access members of constructing class - return withTowerDataMode(FirTowerDataMode.CONSTRUCTOR_HEADER) { - if (!constructor.isPrimary) { - addInaccessibleImplicitReceiverValue(owningClass, holder) - } - withTowerDataCleanup { - addLocalScope(FirLocalScope()) - f() - } - } + // But, let them get resolved, then [FirFunctionParameterChecker] will detect and report an error + // if an uninitialized parameter is accessed by a preceding parameter. + return forConstructorParametersOrDelegatedConstructorCall(constructor, owningClass, holder, f) } @OptIn(PrivateForInline::class) - fun forDelegatedConstructor( + inline fun forDelegatedConstructorCall( + constructor: FirConstructor, + owningClass: FirRegularClass?, + holder: SessionHolder, + f: () -> T + ): T { + return forConstructorParametersOrDelegatedConstructorCall(constructor, owningClass, holder, f) + } + + @OptIn(PrivateForInline::class) + inline fun forConstructorParametersOrDelegatedConstructorCall( constructor: FirConstructor, owningClass: FirRegularClass?, holder: SessionHolder, diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirDeclarationsResolveTransformer.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirDeclarationsResolveTransformer.kt index 867ca6673ce..068b81c8ff8 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirDeclarationsResolveTransformer.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirDeclarationsResolveTransformer.kt @@ -594,9 +594,7 @@ open class FirDeclarationsResolveTransformer(transformer: FirBodyResolveTransfor ConeSimpleDiagnostic("No type for parameter", DiagnosticKind.ValueParameterWithNoTypeAnnotation) ) ) - return context.withValueParameter(valueParameter) { - valueParameter - } + return valueParameter } dataFlowAnalyzer.enterValueParameter(valueParameter) diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirExpressionsResolveTransformer.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirExpressionsResolveTransformer.kt index cc164225d4b..7c4d5bf952e 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirExpressionsResolveTransformer.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirExpressionsResolveTransformer.kt @@ -863,7 +863,7 @@ open class FirExpressionsResolveTransformer(transformer: FirBodyResolveTransform var result = delegatedConstructorCall try { val lastDispatchReceiver = implicitReceiverStack.lastDispatchReceiver() - context.forDelegatedConstructor(containingConstructor, containingClass as? FirRegularClass, components) { + context.forDelegatedConstructorCall(containingConstructor, containingClass as? FirRegularClass, components) { delegatedConstructorCall.transformChildren(transformer, ResolutionMode.ContextDependent) } diff --git a/compiler/testData/cli/jvm/firError.out b/compiler/testData/cli/jvm/firError.out index df1c018d1e8..320e809382d 100644 --- a/compiler/testData/cli/jvm/firError.out +++ b/compiler/testData/cli/jvm/firError.out @@ -1,7 +1,7 @@ warning: ATTENTION! This build uses in-dev FIR: -Xuse-fir -compiler/testData/cli/jvm/firError.kt:5:13: error: x must be initialized before access +compiler/testData/cli/jvm/firError.kt:5:13: error: variable 'x' must be initialized println(x) ^ compiler/testData/cli/jvm/firError.kt:10:16: error: public subclass exposes its private-in-file supertype 'Private' diff --git a/compiler/testData/codegen/box/defaultArguments/useNextParamInLambda.kt b/compiler/testData/codegen/box/defaultArguments/useNextParamInLambda.kt index dcf5548b4bf..c49f1f3e419 100644 --- a/compiler/testData/codegen/box/defaultArguments/useNextParamInLambda.kt +++ b/compiler/testData/codegen/box/defaultArguments/useNextParamInLambda.kt @@ -1,6 +1,5 @@ // DONT_TARGET_EXACT_BACKEND: WASM // WASM_MUTE_REASON: EXCEPTIONS_NOT_IMPLEMENTED -// IGNORE_BACKEND_FIR: JVM_IR // IGNORE_BACKEND: JS, JS_IR, NATIVE // IGNORE_BACKEND: JS_IR_ES6 diff --git a/compiler/testData/diagnostics/tests/DefaultValuesCheckWithoutBody.fir.kt b/compiler/testData/diagnostics/tests/DefaultValuesCheckWithoutBody.fir.kt deleted file mode 100644 index b508a1436dd..00000000000 --- a/compiler/testData/diagnostics/tests/DefaultValuesCheckWithoutBody.fir.kt +++ /dev/null @@ -1,9 +0,0 @@ -interface Inter { - fun foo(x: Int = y, y: Int = x) -} - -abstract class Abst { - abstract fun foo(x: Int = y, y: Int = x) -} - -fun extraDiagnostics(x: Int = y, y: Int) diff --git a/compiler/testData/diagnostics/tests/DefaultValuesCheckWithoutBody.kt b/compiler/testData/diagnostics/tests/DefaultValuesCheckWithoutBody.kt index 2f90e0a8ee7..20b50ae50b1 100644 --- a/compiler/testData/diagnostics/tests/DefaultValuesCheckWithoutBody.kt +++ b/compiler/testData/diagnostics/tests/DefaultValuesCheckWithoutBody.kt @@ -1,3 +1,4 @@ +// FIR_IDENTICAL interface Inter { fun foo(x: Int = y, y: Int = x) } diff --git a/compiler/testData/diagnostics/tests/DefaultValuesTypechecking.fir.kt b/compiler/testData/diagnostics/tests/DefaultValuesTypechecking.fir.kt index 5ea18909bba..4e96a72204b 100644 --- a/compiler/testData/diagnostics/tests/DefaultValuesTypechecking.fir.kt +++ b/compiler/testData/diagnostics/tests/DefaultValuesTypechecking.fir.kt @@ -7,10 +7,33 @@ fun bar(x : Int = "", y : Int = x, z : String = y) { // KT-371 Resolve default parameters for constructors -class A(x : Int = y, y : Int = x) { // None of the references is resolved, no types checked - fun foo(bool: Boolean, a: Int = b, b: String = a) {} +class A(x : Int = y, y : Int = x) { // None of the references is resolved, no types checked + constructor(x : Int = x) : this(x, x) + fun foo(bool: Boolean, a: Int = b, b: String = a) {} } val z = 3 -fun foo(x: Int = y, y: Int = x, i : Int = z): Int = x + y +fun foo(x: Int = y, y: Int = x, i : Int = z): Int = x + y + +fun foo(x: () -> Int = { y }, y: Int = x(), i : Int = z): Int = x() + y + +fun bar(x: () -> Int = { y; 1 }, y: Int) {} + +fun baz( + x: () -> Int = { + fun bar(xx: () -> Int = { y; 1 }) = xx + bar()() + }, + y: Int +) { +} + +fun boo( + x: () -> Int = { + fun bar(): Int = y + bar() + }, + y: Int +) { +} diff --git a/compiler/testData/diagnostics/tests/DefaultValuesTypechecking.kt b/compiler/testData/diagnostics/tests/DefaultValuesTypechecking.kt index be2442c7a76..6296df3218a 100644 --- a/compiler/testData/diagnostics/tests/DefaultValuesTypechecking.kt +++ b/compiler/testData/diagnostics/tests/DefaultValuesTypechecking.kt @@ -8,9 +8,32 @@ fun bar(x : Int = "", y : Int = x, z : String = y, y : Int = x) { // None of the references is resolved, no types checked + constructor(x : Int = x) : this(x, x) fun foo(bool: Boolean, a: Int = b, b: String = a) {} } val z = 3 fun foo(x: Int = y, y: Int = x, i : Int = z): Int = x + y + +fun foo(x: () -> Int = { y }, y: Int = x(), i : Int = z): Int = x() + y + +fun bar(x: () -> Int = { y; 1 }, y: Int) {} + +fun baz( + x: () -> Int = { + fun bar(xx: () -> Int = { y; 1 }) = xx + bar()() + }, + y: Int +) { +} + +fun boo( + x: () -> Int = { + fun bar(): Int = y + bar() + }, + y: Int +) { +} diff --git a/compiler/testData/diagnostics/tests/DefaultValuesTypechecking.txt b/compiler/testData/diagnostics/tests/DefaultValuesTypechecking.txt index 74f29d00ff6..bd3c754fbe3 100644 --- a/compiler/testData/diagnostics/tests/DefaultValuesTypechecking.txt +++ b/compiler/testData/diagnostics/tests/DefaultValuesTypechecking.txt @@ -2,10 +2,15 @@ package public val x: kotlin.String = "" public val z: kotlin.Int = 3 +public fun bar(/*0*/ x: () -> kotlin.Int = ..., /*1*/ y: kotlin.Int): kotlin.Unit public fun bar(/*0*/ x: kotlin.Int = ..., /*1*/ y: kotlin.Int = ..., /*2*/ z: kotlin.String = ...): kotlin.Unit +public fun baz(/*0*/ x: () -> kotlin.Int = ..., /*1*/ y: kotlin.Int): kotlin.Unit +public fun boo(/*0*/ x: () -> kotlin.Int = ..., /*1*/ y: kotlin.Int): kotlin.Unit +public fun foo(/*0*/ x: () -> kotlin.Int = ..., /*1*/ y: kotlin.Int = ..., /*2*/ i: kotlin.Int = ...): kotlin.Int public fun foo(/*0*/ x: kotlin.Int = ..., /*1*/ y: kotlin.Int = ..., /*2*/ i: kotlin.Int = ...): kotlin.Int public final class A { + public constructor A(/*0*/ x: kotlin.Int = ...) public constructor A(/*0*/ x: kotlin.Int = ..., /*1*/ y: kotlin.Int = ...) public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean public final fun foo(/*0*/ bool: kotlin.Boolean, /*1*/ a: kotlin.Int = ..., /*2*/ b: kotlin.String = ...): kotlin.Unit diff --git a/compiler/testData/diagnostics/tests/resolve/parameterAsDefaultValueInLocalFunction.fir.kt b/compiler/testData/diagnostics/tests/resolve/parameterAsDefaultValueInLocalFunction.fir.kt deleted file mode 100644 index b0180e74966..00000000000 --- a/compiler/testData/diagnostics/tests/resolve/parameterAsDefaultValueInLocalFunction.fir.kt +++ /dev/null @@ -1,6 +0,0 @@ -// !DIAGNOSTICS: -UNUSED_PARAMETER - -fun foo() { - fun bar(x: String, y: String = x) {} - fun baz(x: Int = y, y: Int) {} -} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/resolve/parameterAsDefaultValueInLocalFunction.kt b/compiler/testData/diagnostics/tests/resolve/parameterAsDefaultValueInLocalFunction.kt index 5d10ec7a338..2ba6db8fbf0 100644 --- a/compiler/testData/diagnostics/tests/resolve/parameterAsDefaultValueInLocalFunction.kt +++ b/compiler/testData/diagnostics/tests/resolve/parameterAsDefaultValueInLocalFunction.kt @@ -1,6 +1,8 @@ +// FIR_IDENTICAL // !DIAGNOSTICS: -UNUSED_PARAMETER fun foo() { + fun foo(x: Int = x) {} fun bar(x: String, y: String = x) {} fun baz(x: Int = y, y: Int) {} -} \ No newline at end of file +} diff --git a/compiler/testData/diagnostics/tests/resolve/underscoreInCatchBlock.fir.kt b/compiler/testData/diagnostics/tests/resolve/underscoreInCatchBlock.fir.kt index 3e8db42e491..b0650b9785f 100644 --- a/compiler/testData/diagnostics/tests/resolve/underscoreInCatchBlock.fir.kt +++ b/compiler/testData/diagnostics/tests/resolve/underscoreInCatchBlock.fir.kt @@ -23,7 +23,7 @@ fun foo() { 10 } fun bar(x: Exception = `_`) {} - class Bar(`_`: Exception = `_`) { + class Bar(`_`: Exception = `_`) { inner class Bar2(x: Exception = `_`) { } } } diff --git a/compiler/testData/diagnostics/tests/resolve/underscoreInCatchBlockWithEnabledFeature.fir.kt b/compiler/testData/diagnostics/tests/resolve/underscoreInCatchBlockWithEnabledFeature.fir.kt index ebce02da3ea..45d84f8a50d 100644 --- a/compiler/testData/diagnostics/tests/resolve/underscoreInCatchBlockWithEnabledFeature.fir.kt +++ b/compiler/testData/diagnostics/tests/resolve/underscoreInCatchBlockWithEnabledFeature.fir.kt @@ -23,7 +23,7 @@ fun foo() { 10 } fun bar(x: Exception = `_`) {} - class Bar(`_`: Exception = `_`) { + class Bar(`_`: Exception = `_`) { inner class Bar2(x: Exception = `_`) { } } } diff --git a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/diagnostics/KtFirDataClassConverters.kt b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/diagnostics/KtFirDataClassConverters.kt index 49e267510b8..99e8c92313b 100644 --- a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/diagnostics/KtFirDataClassConverters.kt +++ b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/diagnostics/KtFirDataClassConverters.kt @@ -1730,6 +1730,13 @@ internal val KT_DIAGNOSTIC_CONVERTER = KtDiagnosticConverterBuilder.buildConvert token, ) } + add(FirErrors.UNINITIALIZED_PARAMETER) { firDiagnostic -> + UninitializedParameterImpl( + firSymbolBuilder.variableLikeBuilder.buildVariableLikeSymbol(firDiagnostic.a.fir), + firDiagnostic as FirPsiDiagnostic<*>, + token, + ) + } add(FirErrors.UNINITIALIZED_ENUM_ENTRY) { firDiagnostic -> UninitializedEnumEntryImpl( firSymbolBuilder.variableLikeBuilder.buildVariableLikeSymbol(firDiagnostic.a.fir), diff --git a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/diagnostics/KtFirDiagnostics.kt b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/diagnostics/KtFirDiagnostics.kt index 7cdf10947af..c77df8c8a93 100644 --- a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/diagnostics/KtFirDiagnostics.kt +++ b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/diagnostics/KtFirDiagnostics.kt @@ -1215,6 +1215,11 @@ sealed class KtFirDiagnostic : KtDiagnosticWithPsi { abstract val variable: KtVariableSymbol } + abstract class UninitializedParameter : KtFirDiagnostic() { + override val diagnosticClass get() = UninitializedParameter::class + abstract val parameter: KtVariableLikeSymbol + } + abstract class UninitializedEnumEntry : KtFirDiagnostic() { override val diagnosticClass get() = UninitializedEnumEntry::class abstract val enumEntry: KtVariableLikeSymbol diff --git a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/diagnostics/KtFirDiagnosticsImpl.kt b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/diagnostics/KtFirDiagnosticsImpl.kt index 20e4403bb49..293b998cf2b 100644 --- a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/diagnostics/KtFirDiagnosticsImpl.kt +++ b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/diagnostics/KtFirDiagnosticsImpl.kt @@ -1972,6 +1972,14 @@ internal class UninitializedVariableImpl( override val firDiagnostic: FirPsiDiagnostic<*> by weakRef(firDiagnostic) } +internal class UninitializedParameterImpl( + override val parameter: KtVariableLikeSymbol, + firDiagnostic: FirPsiDiagnostic<*>, + override val token: ValidityToken, +) : KtFirDiagnostic.UninitializedParameter(), KtAbstractFirDiagnostic { + override val firDiagnostic: FirPsiDiagnostic<*> by weakRef(firDiagnostic) +} + internal class UninitializedEnumEntryImpl( override val enumEntry: KtVariableLikeSymbol, firDiagnostic: FirPsiDiagnostic<*>,