[IR] Support ACTUAL_ANNOTATION_CONFLICTING_DEFAULT_ARGUMENT_VALUE in K2
It's implemented as IR checker because in K2 constant expressions are evaluated on backend. FIR diagnostic removed because isn't needed. "annotationViaActualTypeAlias" test has no `// FIR_IDENTICAL` because diagnostic reported on entire typealias declaration instead of its name. This is because in IR+LightTree we have only offsets, so can't navigate to typealias name element. ^KT-59940 Fixed
This commit is contained in:
committed by
Space Team
parent
ce666182a2
commit
ad4d1a5ba8
-7
@@ -3604,13 +3604,6 @@ internal val KT_DIAGNOSTIC_CONVERTER = KtDiagnosticConverterBuilder.buildConvert
|
||||
token,
|
||||
)
|
||||
}
|
||||
add(FirErrors.ACTUAL_ANNOTATION_CONFLICTING_DEFAULT_ARGUMENT_VALUE) { firDiagnostic ->
|
||||
ActualAnnotationConflictingDefaultArgumentValueImpl(
|
||||
firSymbolBuilder.variableLikeBuilder.buildVariableLikeSymbol(firDiagnostic.a),
|
||||
firDiagnostic as KtPsiDiagnostic,
|
||||
token,
|
||||
)
|
||||
}
|
||||
add(FirErrors.EXPECTED_FUNCTION_SOURCE_WITH_DEFAULT_ARGUMENTS_NOT_FOUND) { firDiagnostic ->
|
||||
ExpectedFunctionSourceWithDefaultArgumentsNotFoundImpl(
|
||||
firDiagnostic as KtPsiDiagnostic,
|
||||
|
||||
-5
@@ -2536,11 +2536,6 @@ sealed interface KtFirDiagnostic<PSI : PsiElement> : KtDiagnosticWithPsi<PSI> {
|
||||
val members: List<KtCallableSymbol>
|
||||
}
|
||||
|
||||
interface ActualAnnotationConflictingDefaultArgumentValue : KtFirDiagnostic<PsiElement> {
|
||||
override val diagnosticClass get() = ActualAnnotationConflictingDefaultArgumentValue::class
|
||||
val parameter: KtVariableLikeSymbol
|
||||
}
|
||||
|
||||
interface ExpectedFunctionSourceWithDefaultArgumentsNotFound : KtFirDiagnostic<PsiElement> {
|
||||
override val diagnosticClass get() = ExpectedFunctionSourceWithDefaultArgumentsNotFound::class
|
||||
}
|
||||
|
||||
-6
@@ -3057,12 +3057,6 @@ internal class DefaultArgumentsInExpectWithActualTypealiasImpl(
|
||||
token: KtLifetimeToken,
|
||||
) : KtAbstractFirDiagnostic<KtTypeAlias>(firDiagnostic, token), KtFirDiagnostic.DefaultArgumentsInExpectWithActualTypealias
|
||||
|
||||
internal class ActualAnnotationConflictingDefaultArgumentValueImpl(
|
||||
override val parameter: KtVariableLikeSymbol,
|
||||
firDiagnostic: KtPsiDiagnostic,
|
||||
token: KtLifetimeToken,
|
||||
) : KtAbstractFirDiagnostic<PsiElement>(firDiagnostic, token), KtFirDiagnostic.ActualAnnotationConflictingDefaultArgumentValue
|
||||
|
||||
internal class ExpectedFunctionSourceWithDefaultArgumentsNotFoundImpl(
|
||||
firDiagnostic: KtPsiDiagnostic,
|
||||
token: KtLifetimeToken,
|
||||
|
||||
-4
@@ -1223,10 +1223,6 @@ object DIAGNOSTICS_LIST : DiagnosticList("FirErrors") {
|
||||
parameter<FirClassSymbol<*>>("expectClassSymbol")
|
||||
parameter<Collection<FirCallableSymbol<*>>>("members")
|
||||
}
|
||||
val ACTUAL_ANNOTATION_CONFLICTING_DEFAULT_ARGUMENT_VALUE by error<PsiElement> {
|
||||
parameter<FirVariableSymbol<*>>("parameter")
|
||||
}
|
||||
|
||||
val EXPECTED_FUNCTION_SOURCE_WITH_DEFAULT_ARGUMENTS_NOT_FOUND by error<PsiElement>()
|
||||
|
||||
val NO_ACTUAL_FOR_EXPECT by error<KtNamedDeclaration>(PositioningStrategy.INCOMPATIBLE_DECLARATION) {
|
||||
|
||||
@@ -650,7 +650,6 @@ object FirErrors {
|
||||
val ACTUAL_TYPE_ALIAS_TO_NOTHING by error0<KtTypeAlias>(SourceElementPositioningStrategies.DECLARATION_SIGNATURE)
|
||||
val ACTUAL_FUNCTION_WITH_DEFAULT_ARGUMENTS by error0<KtFunction>(SourceElementPositioningStrategies.PARAMETERS_WITH_DEFAULT_VALUE)
|
||||
val DEFAULT_ARGUMENTS_IN_EXPECT_WITH_ACTUAL_TYPEALIAS by error2<KtTypeAlias, FirClassSymbol<*>, Collection<FirCallableSymbol<*>>>()
|
||||
val ACTUAL_ANNOTATION_CONFLICTING_DEFAULT_ARGUMENT_VALUE by error1<PsiElement, FirVariableSymbol<*>>()
|
||||
val EXPECTED_FUNCTION_SOURCE_WITH_DEFAULT_ARGUMENTS_NOT_FOUND by error0<PsiElement>()
|
||||
val NO_ACTUAL_FOR_EXPECT by error3<KtNamedDeclaration, FirBasedSymbol<*>, FirModuleData, Map<ExpectActualCompatibility<FirBasedSymbol<*>>, Collection<FirBasedSymbol<*>>>>(SourceElementPositioningStrategies.INCOMPATIBLE_DECLARATION)
|
||||
val ACTUAL_WITHOUT_EXPECT by error2<KtNamedDeclaration, FirBasedSymbol<*>, Map<ExpectActualCompatibility<FirBasedSymbol<*>>, Collection<FirBasedSymbol<*>>>>(SourceElementPositioningStrategies.DECLARATION_NAME_ONLY)
|
||||
|
||||
-1
@@ -450,7 +450,6 @@ val FIR_NON_SUPPRESSIBLE_ERROR_NAMES: Set<String> = setOf(
|
||||
"ACTUAL_TYPE_ALIAS_TO_NOTHING",
|
||||
"ACTUAL_FUNCTION_WITH_DEFAULT_ARGUMENTS",
|
||||
"DEFAULT_ARGUMENTS_IN_EXPECT_WITH_ACTUAL_TYPEALIAS",
|
||||
"ACTUAL_ANNOTATION_CONFLICTING_DEFAULT_ARGUMENT_VALUE",
|
||||
"EXPECTED_FUNCTION_SOURCE_WITH_DEFAULT_ARGUMENTS_NOT_FOUND",
|
||||
"NO_ACTUAL_FOR_EXPECT",
|
||||
"ACTUAL_WITHOUT_EXPECT",
|
||||
|
||||
-6
@@ -57,7 +57,6 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ABSTRACT_SUPER_CA
|
||||
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_ANNOTATIONS_NOT_MATCH_EXPECT
|
||||
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
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ACTUAL_MISSING
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ACTUAL_TYPEALIAS_TO_SPECIAL_ANNOTATION
|
||||
@@ -1959,11 +1958,6 @@ object FirErrorsDefaultMessages : BaseDiagnosticRendererFactory() {
|
||||
DECLARATION_NAME,
|
||||
SYMBOLS_ON_NEWLINE_WITH_INDENT,
|
||||
)
|
||||
map.put(
|
||||
ACTUAL_ANNOTATION_CONFLICTING_DEFAULT_ARGUMENT_VALUE,
|
||||
"Parameter ''{0}'' has conflicting values in expected and actual annotations.",
|
||||
SYMBOL
|
||||
)
|
||||
map.put(
|
||||
EXPECTED_FUNCTION_SOURCE_WITH_DEFAULT_ARGUMENTS_NOT_FOUND,
|
||||
"Expected function source is not found, so generating default argument values declared there is impossible. Please add the corresponding file to compilation sources."
|
||||
|
||||
+9
@@ -8,6 +8,7 @@ package org.jetbrains.kotlin.backend.common
|
||||
import com.intellij.psi.PsiElement
|
||||
import org.jetbrains.kotlin.backend.common.BackendDiagnosticRenderers.EXPECT_ACTUAL_ANNOTATION_INCOMPATIBILITY
|
||||
import org.jetbrains.kotlin.backend.common.BackendDiagnosticRenderers.INCOMPATIBILITY
|
||||
import org.jetbrains.kotlin.backend.common.BackendDiagnosticRenderers.DECLARATION_NAME
|
||||
import org.jetbrains.kotlin.backend.common.BackendDiagnosticRenderers.SYMBOL_OWNER_DECLARATION_FQ_NAME
|
||||
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
|
||||
import org.jetbrains.kotlin.diagnostics.*
|
||||
@@ -17,6 +18,7 @@ import org.jetbrains.kotlin.diagnostics.rendering.Renderer
|
||||
import org.jetbrains.kotlin.diagnostics.rendering.Renderers.MODULE_WITH_PLATFORM
|
||||
import org.jetbrains.kotlin.diagnostics.rendering.RootDiagnosticRendererFactory
|
||||
import org.jetbrains.kotlin.ir.declarations.IrDeclarationWithName
|
||||
import org.jetbrains.kotlin.ir.declarations.IrValueParameter
|
||||
import org.jetbrains.kotlin.ir.expressions.IrConstructorCall
|
||||
import org.jetbrains.kotlin.ir.symbols.IrSymbol
|
||||
import org.jetbrains.kotlin.ir.types.classFqName
|
||||
@@ -31,6 +33,7 @@ object CommonBackendErrors {
|
||||
val INCOMPATIBLE_MATCHING by error3<PsiElement, String, String, ExpectActualCompatibility.Incompatible<*>>()
|
||||
val ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT by warning3<PsiElement, IrSymbol, IrSymbol, ExpectActualAnnotationsIncompatibilityType<IrConstructorCall>>()
|
||||
val EVALUATION_ERROR by error1<PsiElement, String>()
|
||||
val ACTUAL_ANNOTATION_CONFLICTING_DEFAULT_ARGUMENT_VALUE by error1<PsiElement, IrValueParameter>()
|
||||
|
||||
init {
|
||||
RootDiagnosticRendererFactory.registerFactory(KtDefaultCommonBackendErrorMessages)
|
||||
@@ -77,6 +80,11 @@ object KtDefaultCommonBackendErrorMessages : BaseDiagnosticRendererFactory() {
|
||||
"Cannot evaluate constant expression: {0}",
|
||||
STRING,
|
||||
)
|
||||
map.put(
|
||||
CommonBackendErrors.ACTUAL_ANNOTATION_CONFLICTING_DEFAULT_ARGUMENT_VALUE,
|
||||
"Parameter ''{0}'' has conflicting values in expected and actual annotations.",
|
||||
DECLARATION_NAME,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -96,4 +104,5 @@ object BackendDiagnosticRenderers {
|
||||
}
|
||||
"Annotation `$expectAnnotationFqName` $reason"
|
||||
}
|
||||
val DECLARATION_NAME = Renderer<IrDeclarationWithName> { it.name.asString() }
|
||||
}
|
||||
|
||||
+11
@@ -138,6 +138,17 @@ internal fun KtDiagnosticReporterWithImplicitIrBasedContext.reportActualAnnotati
|
||||
)
|
||||
}
|
||||
|
||||
internal fun KtDiagnosticReporterWithImplicitIrBasedContext.reportActualAnnotationConflictingDefaultArgumentValue(
|
||||
reportOn: IrElement,
|
||||
file: IrFile,
|
||||
actualParam: IrValueParameter,
|
||||
) {
|
||||
at(reportOn, file).report(
|
||||
CommonBackendErrors.ACTUAL_ANNOTATION_CONFLICTING_DEFAULT_ARGUMENT_VALUE,
|
||||
actualParam,
|
||||
)
|
||||
}
|
||||
|
||||
internal fun IrElement.containsOptionalExpectation(): Boolean {
|
||||
return this is IrClass &&
|
||||
this.kind == ClassKind.ANNOTATION_CLASS &&
|
||||
|
||||
+63
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* Copyright 2010-2023 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.backend.common.actualizer.checker
|
||||
|
||||
import org.jetbrains.kotlin.backend.common.actualizer.reportActualAnnotationConflictingDefaultArgumentValue
|
||||
import org.jetbrains.kotlin.descriptors.ClassKind
|
||||
import org.jetbrains.kotlin.ir.declarations.IrClass
|
||||
import org.jetbrains.kotlin.ir.declarations.IrValueParameter
|
||||
import org.jetbrains.kotlin.ir.expressions.IrExpression
|
||||
import org.jetbrains.kotlin.ir.symbols.IrConstructorSymbol
|
||||
import org.jetbrains.kotlin.ir.util.file
|
||||
import org.jetbrains.kotlin.ir.util.parentAsClass
|
||||
import org.jetbrains.kotlin.resolve.calls.mpp.ExpectActualCollectionArgumentsCompatibilityCheckStrategy
|
||||
|
||||
internal object IrExpectActualAnnotationConflictingDefaultArgumentValueChecker : IrExpectActualChecker {
|
||||
override fun check(context: IrExpectActualChecker.Context) = with(context) {
|
||||
for ((expectSymbol, actualSymbol) in matchedExpectToActual) {
|
||||
if (expectSymbol !is IrConstructorSymbol || actualSymbol !is IrConstructorSymbol) continue
|
||||
|
||||
val expectClass = expectSymbol.owner.parentAsClass
|
||||
if (expectClass.kind != ClassKind.ANNOTATION_CLASS) continue
|
||||
|
||||
val expectValueParams = expectSymbol.owner.valueParameters
|
||||
val actualValueParams = actualSymbol.owner.valueParameters
|
||||
if (expectValueParams.size != actualValueParams.size) continue
|
||||
|
||||
for ((expectParam, actualParam) in expectValueParams.zip(actualValueParams)) {
|
||||
val expectDefaultValue = expectParam.defaultValue?.expression ?: continue
|
||||
val actualDefaultValue = actualParam.defaultValue?.expression ?: continue
|
||||
with(matchingContext) {
|
||||
if (!areIrExpressionConstValuesEqual(
|
||||
expectDefaultValue, actualDefaultValue,
|
||||
ExpectActualCollectionArgumentsCompatibilityCheckStrategy.Default
|
||||
)
|
||||
) {
|
||||
reportError(expectClass, actualDefaultValue, actualParam)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun IrExpectActualChecker.Context.reportError(
|
||||
expectAnnotationClass: IrClass,
|
||||
actualDefaultValue: IrExpression,
|
||||
actualParam: IrValueParameter,
|
||||
) {
|
||||
val actualTypealias = getTypealiasSymbolIfActualizedViaTypealias(expectAnnotationClass, classActualizationInfo)?.owner
|
||||
if (actualTypealias != null) {
|
||||
diagnosticsReporter.reportActualAnnotationConflictingDefaultArgumentValue(
|
||||
actualTypealias, actualTypealias.file, actualParam
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
diagnosticsReporter.reportActualAnnotationConflictingDefaultArgumentValue(
|
||||
actualDefaultValue, actualParam.file, actualParam
|
||||
)
|
||||
}
|
||||
}
|
||||
+2
-1
@@ -20,7 +20,8 @@ internal class IrExpectActualCheckers(
|
||||
) : IrExpectActualChecker.Context {
|
||||
|
||||
private val checkers: Set<IrExpectActualChecker> = setOf(
|
||||
IrExpectActualAnnotationMatchingChecker
|
||||
IrExpectActualAnnotationMatchingChecker,
|
||||
IrExpectActualAnnotationConflictingDefaultArgumentValueChecker,
|
||||
)
|
||||
|
||||
override val matchingContext = object : IrExpectActualMatchingContext(typeSystemContext, classActualizationInfo.actualClasses) {
|
||||
|
||||
+1
-1
@@ -13,7 +13,7 @@ sealed class ExpectActualCollectionArgumentsCompatibilityCheckStrategy {
|
||||
elementsEqual: (T, T) -> Boolean,
|
||||
): Boolean
|
||||
|
||||
internal data object Default : ExpectActualCollectionArgumentsCompatibilityCheckStrategy() {
|
||||
data object Default : ExpectActualCollectionArgumentsCompatibilityCheckStrategy() {
|
||||
override fun <T> areCompatible(
|
||||
expectArg: Collection<T>,
|
||||
actualArg: Collection<T>,
|
||||
|
||||
-32
@@ -1,32 +0,0 @@
|
||||
// MODULE: m1-common
|
||||
// FILE: common.kt
|
||||
|
||||
expect annotation class A1(val x: Int, val y: String = "OK")
|
||||
|
||||
expect annotation class A2(val x: Int = 42, val y: String = "OK")
|
||||
|
||||
expect annotation class A3(val x: Int, val y: String)
|
||||
|
||||
expect annotation class A4(val x: Int = 42, val y: String)
|
||||
|
||||
expect annotation class A5(val x: Int = 42, val y: String)
|
||||
|
||||
@A1(0)
|
||||
@A2
|
||||
@A3(0, "")
|
||||
@A4(0, "")
|
||||
@A5(0, "")
|
||||
fun test() {}
|
||||
|
||||
// MODULE: m2-jvm()()(m1-common)
|
||||
// FILE: jvm.kt
|
||||
|
||||
actual annotation class A1(actual val x: Int, actual val y: String)
|
||||
|
||||
actual annotation class A2(actual val x: Int, actual val y: String = "OK")
|
||||
|
||||
actual annotation class A3(actual val x: Int = 42, actual val y: String = "OK")
|
||||
|
||||
actual annotation class A4(actual val x: Int, actual val y: String = "OK")
|
||||
|
||||
actual annotation class A5(actual val x: Int = 239, actual val y: String = "OK")
|
||||
+1
@@ -1,3 +1,4 @@
|
||||
// FIR_IDENTICAL
|
||||
// MODULE: m1-common
|
||||
// FILE: common.kt
|
||||
|
||||
|
||||
+1
-1
@@ -25,7 +25,7 @@ actual typealias A1 = J1
|
||||
actual typealias A2 = J2
|
||||
actual typealias A3 = J3
|
||||
actual typealias A4 = J4
|
||||
actual typealias A5 = J5
|
||||
<!ACTUAL_ANNOTATION_CONFLICTING_DEFAULT_ARGUMENT_VALUE!>actual typealias A5 = J5<!>
|
||||
|
||||
// FILE: J1.java
|
||||
|
||||
|
||||
Reference in New Issue
Block a user