[FE, IR] Store PsiElement for mismatched annotation's actual target

There is IDE quick fix which suggests to copy mismatched annotation
from `expect` to `actual` (see KTIJ-26633). It needs to find
`actual` PsiElement where to add annotation. Before previous commit, it
was easy - just get source of `Incompatibility.actualSymbol`.
After previous commit, the problem might be in value parameter, while
`actualSymbol` would contain function symbol. This is solved by adding
new field `Incompatibility.actualAnnotationTargetElement`.

`SourceElementMarker` introduced, because it's needed to be used in
abstract checker. Existing `DeclarationSymbolMarker` doesn't fit
because in next PR for this issue annotations set on types will be reported,
and types are not declarations.

^KT-60671
This commit is contained in:
Roman Efremov
2023-09-07 16:50:34 +02:00
committed by Space Team
parent 5c95f69aef
commit 420dceb7d8
20 changed files with 108 additions and 22 deletions
@@ -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<KtNamedDeclaration> EXPECT_ACTUAL_OPT_IN_ANNOTATION = DiagnosticFactory0.create(ERROR, EXPECT_ACTUAL_MODIFIER);
DiagnosticFactory1<KtTypeAlias, ClassId> ACTUAL_TYPEALIAS_TO_SPECIAL_ANNOTATION =
DiagnosticFactory1.create(ERROR, TYPEALIAS_TYPE_REFERENCE);
DiagnosticFactory3<KtNamedDeclaration, DeclarationDescriptor, DeclarationDescriptor,
DiagnosticFactory4<KtNamedDeclaration, DeclarationDescriptor, DeclarationDescriptor, Optional<SourceElement>,
ExpectActualAnnotationsIncompatibilityType<AnnotationDescriptor>> ACTUAL_ANNOTATIONS_NOT_MATCH_EXPECT =
DiagnosticFactory3.create(WARNING, DECLARATION_NAME_ONLY);
DiagnosticFactory4.create(WARNING, DECLARATION_NAME_ONLY);
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -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");
@@ -69,6 +69,9 @@ object Renderers {
element.toString()
}
@JvmField
val NOT_RENDERED = Renderer<Any?> { _ -> "" }
@JvmField
val NAME = Renderer<Named> { it.name.asString() }
@@ -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 }
)
)