diff --git a/analysis/analysis-api-fir/analysis-api-fir-generator/src/org/jetbrains/kotlin/analysis/api/fir/generator/HLDiagnosticConverter.kt b/analysis/analysis-api-fir/analysis-api-fir-generator/src/org/jetbrains/kotlin/analysis/api/fir/generator/HLDiagnosticConverter.kt index 5d90cbcfa9c..7a9f064e4c0 100644 --- a/analysis/analysis-api-fir/analysis-api-fir-generator/src/org/jetbrains/kotlin/analysis/api/fir/generator/HLDiagnosticConverter.kt +++ b/analysis/analysis-api-fir/analysis-api-fir-generator/src/org/jetbrains/kotlin/analysis/api/fir/generator/HLDiagnosticConverter.kt @@ -214,6 +214,14 @@ internal object FirToKtConversionCreator { "org.jetbrains.kotlin.psi" ) ), + KtSourceElement::class to HLFunctionCallConversion( + "({0} as? KtPsiSourceElement)?.psi", + PsiElement::class.createType(nullable = true), + importsToAdd = listOf( + "org.jetbrains.kotlin.psi", + "org.jetbrains.kotlin.KtPsiSourceElement" + ) + ), ) private val typeMapping: Map, HLFunctionCallConversion> = mapOf( diff --git a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDataClassConverters.kt b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDataClassConverters.kt index f531868aa64..4bdf28d2c2d 100644 --- a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDataClassConverters.kt +++ b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDataClassConverters.kt @@ -3717,7 +3717,8 @@ internal val KT_DIAGNOSTIC_CONVERTER = KtDiagnosticConverterBuilder.buildConvert ActualAnnotationsNotMatchExpectImpl( firSymbolBuilder.buildSymbol(firDiagnostic.a), firSymbolBuilder.buildSymbol(firDiagnostic.b), - firDiagnostic.c, + (firDiagnostic.c as? KtPsiSourceElement)?.psi, + firDiagnostic.d, firDiagnostic as KtPsiDiagnostic, token, ) diff --git a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDiagnostics.kt b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDiagnostics.kt index 3216a1c66ff..b3b318c3be3 100644 --- a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDiagnostics.kt +++ b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDiagnostics.kt @@ -2601,6 +2601,7 @@ sealed interface KtFirDiagnostic : KtDiagnosticWithPsi { override val diagnosticClass get() = ActualAnnotationsNotMatchExpect::class val expectSymbol: KtSymbol val actualSymbol: KtSymbol + val actualAnnotationTargetSourceElement: PsiElement? val incompatibilityType: ExpectActualAnnotationsIncompatibilityType } diff --git a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDiagnosticsImpl.kt b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDiagnosticsImpl.kt index 1e0682a515f..49300357df5 100644 --- a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDiagnosticsImpl.kt +++ b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDiagnosticsImpl.kt @@ -3133,6 +3133,7 @@ internal class ActualTypealiasToSpecialAnnotationImpl( internal class ActualAnnotationsNotMatchExpectImpl( override val expectSymbol: KtSymbol, override val actualSymbol: KtSymbol, + override val actualAnnotationTargetSourceElement: PsiElement?, override val incompatibilityType: ExpectActualAnnotationsIncompatibilityType, firDiagnostic: KtPsiDiagnostic, token: KtLifetimeToken, 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 45a103696c5..5c9cfb8a0e6 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 @@ -17,6 +17,7 @@ import org.jetbrains.kotlin.descriptors.ClassKind import org.jetbrains.kotlin.descriptors.EffectiveVisibility import org.jetbrains.kotlin.descriptors.Visibility import org.jetbrains.kotlin.diagnostics.WhenMissingCase +import org.jetbrains.kotlin.fir.FirElement import org.jetbrains.kotlin.fir.FirModuleData import org.jetbrains.kotlin.fir.checkers.generator.diagnostics.model.* import org.jetbrains.kotlin.fir.declarations.FirFunction @@ -41,6 +42,7 @@ import org.jetbrains.kotlin.resolve.multiplatform.ExpectActualCompatibility.Inco import org.jetbrains.kotlin.serialization.deserialization.IncompatibleVersionErrorData import org.jetbrains.kotlin.types.Variance import org.jetbrains.kotlin.util.PrivateForInline +import java.util.Optional import kotlin.properties.PropertyDelegateProvider import kotlin.properties.ReadOnlyProperty @@ -1268,6 +1270,7 @@ object DIAGNOSTICS_LIST : DiagnosticList("FirErrors") { val ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT by warning(PositioningStrategy.DECLARATION_NAME_ONLY) { parameter("expectSymbol") parameter("actualSymbol") + parameter("actualAnnotationTargetSourceElement") parameter>("incompatibilityType") } 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 9f440120851..92b98a788ce 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 @@ -662,7 +662,7 @@ object FirErrors { val NOT_A_MULTIPLATFORM_COMPILATION by error0() val EXPECT_ACTUAL_OPT_IN_ANNOTATION by error0(SourceElementPositioningStrategies.EXPECT_ACTUAL_MODIFIER) val ACTUAL_TYPEALIAS_TO_SPECIAL_ANNOTATION by error1(SourceElementPositioningStrategies.TYPEALIAS_TYPE_REFERENCE) - val ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT by warning3, FirBasedSymbol<*>, ExpectActualAnnotationsIncompatibilityType>(SourceElementPositioningStrategies.DECLARATION_NAME_ONLY) + val ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT by warning4, FirBasedSymbol<*>, KtSourceElement?, ExpectActualAnnotationsIncompatibilityType>(SourceElementPositioningStrategies.DECLARATION_NAME_ONLY) val OPTIONAL_DECLARATION_OUTSIDE_OF_ANNOTATION_ENTRY by error0() val OPTIONAL_DECLARATION_USAGE_IN_NON_COMMON_SOURCE by error0() val OPTIONAL_EXPECTATION_NOT_ON_EXPECTED by error0() diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirExpectActualDeclarationChecker.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirExpectActualDeclarationChecker.kt index b4b943831ef..679f4985fb0 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirExpectActualDeclarationChecker.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirExpectActualDeclarationChecker.kt @@ -8,10 +8,9 @@ package org.jetbrains.kotlin.fir.analysis.checkers.declaration import org.jetbrains.kotlin.KtFakeSourceElementKind import org.jetbrains.kotlin.config.LanguageFeature import org.jetbrains.kotlin.descriptors.ClassKind -import org.jetbrains.kotlin.diagnostics.DiagnosticReporter -import org.jetbrains.kotlin.diagnostics.SourceElementPositioningStrategies -import org.jetbrains.kotlin.diagnostics.reportOn +import org.jetbrains.kotlin.diagnostics.* import org.jetbrains.kotlin.fir.FirSession +import org.jetbrains.kotlin.fir.FirSourceElement import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext import org.jetbrains.kotlin.fir.analysis.checkers.getModifierList import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors @@ -35,7 +34,8 @@ import org.jetbrains.kotlin.name.StandardClassIds import org.jetbrains.kotlin.resolve.calls.mpp.AbstractExpectActualAnnotationMatchChecker import org.jetbrains.kotlin.resolve.checkers.OptInNames import org.jetbrains.kotlin.resolve.multiplatform.ExpectActualCompatibility -import org.jetbrains.kotlin.resolve.multiplatform.ExpectActualCompatibility.* +import org.jetbrains.kotlin.resolve.multiplatform.ExpectActualCompatibility.Compatible +import org.jetbrains.kotlin.resolve.multiplatform.ExpectActualCompatibility.Incompatible import org.jetbrains.kotlin.resolve.multiplatform.isCompatibleOrWeaklyIncompatible @Suppress("DuplicatedCode") @@ -276,6 +276,7 @@ object FirExpectActualDeclarationChecker : FirBasicDeclarationChecker() { return result } + @OptIn(InternalDiagnosticFactoryMethod::class) private fun checkAnnotationsMatch( expectSymbol: FirBasedSymbol<*>, actualSymbol: FirBasedSymbol<*>, @@ -286,12 +287,18 @@ object FirExpectActualDeclarationChecker : FirBasicDeclarationChecker() { val matchingContext = context.session.expectActualMatchingContextFactory.create(context.session, context.scopeSession) val incompatibility = AbstractExpectActualAnnotationMatchChecker.areAnnotationsCompatible(expectSymbol, actualSymbol, matchingContext) ?: return - reporter.reportOn( - actualSymbol.source, FirErrors.ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT, - incompatibility.expectSymbol as FirBasedSymbol<*>, - incompatibility.actualSymbol as FirBasedSymbol<*>, - incompatibility.type.mapAnnotationType { it.annotationSymbol as FirAnnotation }, - context + val actualAnnotationTargetSourceElement = (incompatibility.actualAnnotationTargetElement as FirSourceElement).element + + reporter.report( + FirErrors.ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT.on( + actualSymbol.source.requireNotNull(), + incompatibility.expectSymbol as FirBasedSymbol<*>, + incompatibility.actualSymbol as FirBasedSymbol<*>, + actualAnnotationTargetSourceElement, + incompatibility.type.mapAnnotationType { it.annotationSymbol as FirAnnotation }, + positioningStrategy = null, + ), + context, ) } diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrorsDefaultMessages.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrorsDefaultMessages.kt index b58a8fd8de0..f8b2d59b886 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrorsDefaultMessages.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrorsDefaultMessages.kt @@ -2005,10 +2005,11 @@ object FirErrorsDefaultMessages : BaseDiagnosticRendererFactory() { ) map.put( ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT, - "{2}.\n" + + "{3}.\n" + "All annotations from expect ''{0}'' must be present with the same arguments on actual ''{1}'', otherwise they might behave incorrectly.", FirExpectActualAnnotationIncompatibilityDiagnosticRenderers.SYMBOL_RENDERER, FirExpectActualAnnotationIncompatibilityDiagnosticRenderers.SYMBOL_RENDERER, + NOT_RENDERED, FirExpectActualAnnotationIncompatibilityDiagnosticRenderers.INCOMPATIBILITY, ) map.put( diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/mpp/FirExpectActualMatchingContextImpl.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/mpp/FirExpectActualMatchingContextImpl.kt index 8a0f63a7a1b..df908c1c952 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/mpp/FirExpectActualMatchingContextImpl.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/mpp/FirExpectActualMatchingContextImpl.kt @@ -27,6 +27,7 @@ import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.resolve.calls.mpp.ExpectActualCollectionArgumentsCompatibilityCheckStrategy import org.jetbrains.kotlin.resolve.calls.mpp.ExpectActualMatchingContext.AnnotationCallInfo +import org.jetbrains.kotlin.mpp.SourceElementMarker import org.jetbrains.kotlin.resolve.checkers.OptInNames import org.jetbrains.kotlin.resolve.multiplatform.ExpectActualCompatibility import org.jetbrains.kotlin.types.AbstractTypeChecker @@ -480,6 +481,8 @@ class FirExpectActualMatchingContextImpl private constructor( return mapping?.get(actualMember to expectClass) ?: emptyMap() } + override fun DeclarationSymbolMarker.getSourceElement(): SourceElementMarker = FirSourceElement(asSymbol().source) + object Factory : FirExpectActualMatchingContextFactory { override fun create( session: FirSession, scopeSession: ScopeSession, diff --git a/compiler/fir/semantics/src/org/jetbrains/kotlin/fir/FirSourceElement.kt b/compiler/fir/semantics/src/org/jetbrains/kotlin/fir/FirSourceElement.kt new file mode 100644 index 00000000000..2d31fcce7f9 --- /dev/null +++ b/compiler/fir/semantics/src/org/jetbrains/kotlin/fir/FirSourceElement.kt @@ -0,0 +1,11 @@ +/* + * 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.fir + +import org.jetbrains.kotlin.KtSourceElement +import org.jetbrains.kotlin.mpp.SourceElementMarker + +class FirSourceElement(val element: KtSourceElement?) : SourceElementMarker \ No newline at end of file diff --git a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java index 2479f61547e..08578112963 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java @@ -34,6 +34,7 @@ import org.jetbrains.kotlin.resolve.calls.tower.CandidateApplicability; import org.jetbrains.kotlin.resolve.calls.tower.WrongResolutionToClassifier; import org.jetbrains.kotlin.resolve.calls.util.BuilderLambdaLabelingInfo; import org.jetbrains.kotlin.resolve.deprecation.DescriptorBasedDeprecationInfo; +import org.jetbrains.kotlin.resolve.multiplatform.ClassicSourceElement; import org.jetbrains.kotlin.resolve.multiplatform.ExpectActualAnnotationsIncompatibilityType; import org.jetbrains.kotlin.resolve.multiplatform.ExpectActualCompatibility.Incompatible; import org.jetbrains.kotlin.resolve.multiplatform.ExpectActualMemberDiff; @@ -42,10 +43,7 @@ import org.jetbrains.kotlin.types.KotlinType; import java.lang.reflect.Field; import java.lang.reflect.Modifier; -import java.util.Collection; -import java.util.List; -import java.util.Map; -import java.util.Set; +import java.util.*; import static org.jetbrains.kotlin.diagnostics.ClassicPositioningStrategies.ACTUAL_DECLARATION_NAME; import static org.jetbrains.kotlin.diagnostics.ClassicPositioningStrategies.INCOMPATIBLE_DECLARATION; @@ -875,9 +873,9 @@ public interface Errors { DiagnosticFactory0 EXPECT_ACTUAL_OPT_IN_ANNOTATION = DiagnosticFactory0.create(ERROR, EXPECT_ACTUAL_MODIFIER); DiagnosticFactory1 ACTUAL_TYPEALIAS_TO_SPECIAL_ANNOTATION = DiagnosticFactory1.create(ERROR, TYPEALIAS_TYPE_REFERENCE); - DiagnosticFactory3, ExpectActualAnnotationsIncompatibilityType> ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT = - DiagnosticFactory3.create(WARNING, DECLARATION_NAME_ONLY); + DiagnosticFactory4.create(WARNING, DECLARATION_NAME_ONLY); //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java index 18fcf433776..68c02bc6de8 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java @@ -444,10 +444,11 @@ public class DefaultErrorMessages { "`actual typealias` to annotation which affects code compilation can lead to incorrect behavior. Instead, use ''{0}'' annotation directly.", TO_STRING); MAP.put(ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT, - "{2}.\n" + + "{3}.\n" + "All annotations from expect `{0}` must be present with the same arguments on actual `{1}`, otherwise they might behave incorrectly.", ExpectActualAnnotationIncompatibilityDiagnosticRenderers.DESCRIPTOR_RENDERER, ExpectActualAnnotationIncompatibilityDiagnosticRenderers.DESCRIPTOR_RENDERER, + NOT_RENDERED, ExpectActualAnnotationIncompatibilityDiagnosticRenderers.INCOMPATIBILITY); MAP.put(PROJECTION_ON_NON_CLASS_TYPE_ARGUMENT, "Projections are not allowed on type arguments of functions and properties"); diff --git a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/Renderers.kt b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/Renderers.kt index 4c09656155b..2b01e3861ce 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/Renderers.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/Renderers.kt @@ -69,6 +69,9 @@ object Renderers { element.toString() } + @JvmField + val NOT_RENDERED = Renderer { _ -> "" } + @JvmField val NAME = Renderer { it.name.asString() } diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/checkers/ExpectedActualDeclarationChecker.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/checkers/ExpectedActualDeclarationChecker.kt index 4d9058b6684..dda08dcc28d 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/checkers/ExpectedActualDeclarationChecker.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/checkers/ExpectedActualDeclarationChecker.kt @@ -41,6 +41,7 @@ import org.jetbrains.kotlin.resolve.source.KotlinSourceElement import org.jetbrains.kotlin.resolve.source.PsiSourceFile import org.jetbrains.kotlin.types.KotlinType import java.io.File +import java.util.* private val implicitlyActualizedAnnotationFqn = StandardClassIds.Annotations.ImplicitlyActualizedByJvmDeclaration.asSingleFqName() @@ -514,11 +515,13 @@ class ExpectedActualDeclarationChecker( val matchingContext = ClassicExpectActualMatchingContext(actualDescriptor.module) val incompatibility = AbstractExpectActualAnnotationMatchChecker.areAnnotationsCompatible(expectDescriptor, actualDescriptor, matchingContext) ?: return + val actualAnnotationTargetSourceElement = (incompatibility.actualAnnotationTargetElement as ClassicSourceElement).element context.trace.report( Errors.ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT.on( reportOn, incompatibility.expectSymbol as DeclarationDescriptor, incompatibility.actualSymbol as DeclarationDescriptor, + Optional.ofNullable(actualAnnotationTargetSourceElement), incompatibility.type.mapAnnotationType { it.annotationSymbol as AnnotationDescriptor } ) ) diff --git a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/actualizer/IrExpectActualMatchingContext.kt b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/actualizer/IrExpectActualMatchingContext.kt index 802ae5054b1..f2596a85525 100644 --- a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/actualizer/IrExpectActualMatchingContext.kt +++ b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/actualizer/IrExpectActualMatchingContext.kt @@ -27,6 +27,7 @@ import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.resolve.calls.mpp.ExpectActualCollectionArgumentsCompatibilityCheckStrategy import org.jetbrains.kotlin.resolve.calls.mpp.ExpectActualMatchingContext import org.jetbrains.kotlin.resolve.calls.mpp.ExpectActualMatchingContext.AnnotationCallInfo +import org.jetbrains.kotlin.mpp.SourceElementMarker import org.jetbrains.kotlin.resolve.checkers.OptInNames import org.jetbrains.kotlin.resolve.multiplatform.ExpectActualCompatibility import org.jetbrains.kotlin.types.AbstractTypeChecker @@ -523,4 +524,9 @@ internal abstract class IrExpectActualMatchingContext( actualMember: DeclarationSymbolMarker, checkClassScopesCompatibility: Boolean, ): Map> = error("Should not be called") + + // It's a stub, because not needed anywhere + private object IrSourceElementStub : SourceElementMarker + + override fun DeclarationSymbolMarker.getSourceElement(): SourceElementMarker = IrSourceElementStub } diff --git a/compiler/resolution.common/src/org/jetbrains/kotlin/resolve/calls/mpp/AbstractExpectActualAnnotationMatchChecker.kt b/compiler/resolution.common/src/org/jetbrains/kotlin/resolve/calls/mpp/AbstractExpectActualAnnotationMatchChecker.kt index da63de306a7..8ecab52cd8d 100644 --- a/compiler/resolution.common/src/org/jetbrains/kotlin/resolve/calls/mpp/AbstractExpectActualAnnotationMatchChecker.kt +++ b/compiler/resolution.common/src/org/jetbrains/kotlin/resolve/calls/mpp/AbstractExpectActualAnnotationMatchChecker.kt @@ -38,6 +38,13 @@ object AbstractExpectActualAnnotationMatchChecker { */ val expectSymbol: DeclarationSymbolMarker, val actualSymbol: DeclarationSymbolMarker, + + /** + * Link to source code element (possibly holding null, if no source) from actual declaration + * where mismatched actual annotation is set (or should be set if it is missing). + * Needed for the implementation of IDE intention. + */ + val actualAnnotationTargetElement: SourceElementMarker, val type: IncompatibilityType, ) @@ -122,7 +129,7 @@ object AbstractExpectActualAnnotationMatchChecker { return expectParams.zip(actualParams).firstNotNullOfOrNull { (expectParam, actualParam) -> areAnnotationsSetOnDeclarationsCompatible(expectParam, actualParam)?.let { // Write containing declarations into diagnostic - Incompatibility(expectSymbol, actualSymbol, it.type) + Incompatibility(expectSymbol, actualSymbol, actualParam.getSourceElement(), it.type) } } } @@ -150,6 +157,7 @@ object AbstractExpectActualAnnotationMatchChecker { return Incompatibility( expectSymbol, actualSymbol, + actualSymbol.getSourceElement(), IncompatibilityType.MissingOnActual(expectAnnotation) ) } @@ -163,7 +171,7 @@ object AbstractExpectActualAnnotationMatchChecker { // In the case of repeatable annotations, we can't choose on which to report IncompatibilityType.MissingOnActual(expectAnnotation) } - return Incompatibility(expectSymbol, actualSymbol, incompatibilityType) + return Incompatibility(expectSymbol, actualSymbol, actualSymbol.getSourceElement(), incompatibilityType) } } return null diff --git a/compiler/resolution.common/src/org/jetbrains/kotlin/resolve/calls/mpp/ExpectActualMatchingContext.kt b/compiler/resolution.common/src/org/jetbrains/kotlin/resolve/calls/mpp/ExpectActualMatchingContext.kt index 5bc4d296212..667306c5a65 100644 --- a/compiler/resolution.common/src/org/jetbrains/kotlin/resolve/calls/mpp/ExpectActualMatchingContext.kt +++ b/compiler/resolution.common/src/org/jetbrains/kotlin/resolve/calls/mpp/ExpectActualMatchingContext.kt @@ -213,4 +213,6 @@ interface ExpectActualMatchingContext : TypeSystemC actualMember: DeclarationSymbolMarker, checkClassScopesCompatibility: Boolean, ): Map> + + fun DeclarationSymbolMarker.getSourceElement(): SourceElementMarker } diff --git a/compiler/resolution/src/org/jetbrains/kotlin/resolve/multiplatform/ClassicExpectActualMatchingContext.kt b/compiler/resolution/src/org/jetbrains/kotlin/resolve/multiplatform/ClassicExpectActualMatchingContext.kt index 0aad92a7c9a..bf891193fab 100644 --- a/compiler/resolution/src/org/jetbrains/kotlin/resolve/multiplatform/ClassicExpectActualMatchingContext.kt +++ b/compiler/resolution/src/org/jetbrains/kotlin/resolve/multiplatform/ClassicExpectActualMatchingContext.kt @@ -442,4 +442,8 @@ class ClassicExpectActualMatchingContext( } } } + + override fun DeclarationSymbolMarker.getSourceElement(): SourceElementMarker { + return ClassicSourceElement((asDescriptor() as? DeclarationDescriptorWithSource)?.source) + } } diff --git a/compiler/resolution/src/org/jetbrains/kotlin/resolve/multiplatform/ClassicSourceElement.kt b/compiler/resolution/src/org/jetbrains/kotlin/resolve/multiplatform/ClassicSourceElement.kt new file mode 100644 index 00000000000..907ad6de38d --- /dev/null +++ b/compiler/resolution/src/org/jetbrains/kotlin/resolve/multiplatform/ClassicSourceElement.kt @@ -0,0 +1,11 @@ +/* + * 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.resolve.multiplatform + +import org.jetbrains.kotlin.descriptors.SourceElement +import org.jetbrains.kotlin.mpp.SourceElementMarker + +class ClassicSourceElement(val element: SourceElement?) : SourceElementMarker diff --git a/core/compiler.common/src/org/jetbrains/kotlin/mpp/SourceElementMarker.kt b/core/compiler.common/src/org/jetbrains/kotlin/mpp/SourceElementMarker.kt new file mode 100644 index 00000000000..8c19b1f9ff5 --- /dev/null +++ b/core/compiler.common/src/org/jetbrains/kotlin/mpp/SourceElementMarker.kt @@ -0,0 +1,14 @@ +/* + * 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.mpp + +/** + * Common interface, which stores a link to a source element of declaration or type reference (or null, if no source). + * The idea is similar to [DeclarationSymbolMarker], but it doesn't fit, because + * sources of type references also must be supported, which are not declarations. + * Used in [org.jetbrains.kotlin.resolve.calls.mpp.AbstractExpectActualAnnotationMatchChecker]. + */ +interface SourceElementMarker