diff --git a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendMPPDiagnosticsWithLightTreeTestGenerated.java b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendMPPDiagnosticsWithLightTreeTestGenerated.java index 654666d009a..cc0e2022666 100644 --- a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendMPPDiagnosticsWithLightTreeTestGenerated.java +++ b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendMPPDiagnosticsWithLightTreeTestGenerated.java @@ -1392,6 +1392,34 @@ public class FirOldFrontendMPPDiagnosticsWithLightTreeTestGenerated extends Abst public void testSealedInheritorsInComplexModuleStructure() throws Exception { runTest("compiler/testData/diagnostics/tests/multiplatform/hmpp/multiplatformCompositeAnalysis/sealedInheritorsInComplexModuleStructure.kt"); } + + @Nested + @TestMetadata("compiler/testData/diagnostics/tests/multiplatform/hmpp/multiplatformCompositeAnalysis/annotationMatching") + @TestDataPath("$PROJECT_ROOT") + public class AnnotationMatching { + @Test + public void testAllFilesPresentInAnnotationMatching() throws Exception { + KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/tests/multiplatform/hmpp/multiplatformCompositeAnalysis/annotationMatching"), Pattern.compile("^(.*)\\.kts?$"), Pattern.compile("^(.+)\\.(reversed|fir|ll)\\.kts?$"), TargetBackend.JVM_IR, true); + } + + @Test + @TestMetadata("sourceRetentionAnnotationsWhenTypealias.kt") + public void testSourceRetentionAnnotationsWhenTypealias() throws Exception { + runTest("compiler/testData/diagnostics/tests/multiplatform/hmpp/multiplatformCompositeAnalysis/annotationMatching/sourceRetentionAnnotationsWhenTypealias.kt"); + } + + @Test + @TestMetadata("typealiasedAnnotation.kt") + public void testTypealiasedAnnotation() throws Exception { + runTest("compiler/testData/diagnostics/tests/multiplatform/hmpp/multiplatformCompositeAnalysis/annotationMatching/typealiasedAnnotation.kt"); + } + + @Test + @TestMetadata("typealiasedAnnotationAsArgument.kt") + public void testTypealiasedAnnotationAsArgument() throws Exception { + runTest("compiler/testData/diagnostics/tests/multiplatform/hmpp/multiplatformCompositeAnalysis/annotationMatching/typealiasedAnnotationAsArgument.kt"); + } + } } } diff --git a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendMPPDiagnosticsWithPsiTestGenerated.java b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendMPPDiagnosticsWithPsiTestGenerated.java index 0907f1cfa8b..37a0a3c9d85 100644 --- a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendMPPDiagnosticsWithPsiTestGenerated.java +++ b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendMPPDiagnosticsWithPsiTestGenerated.java @@ -1392,6 +1392,34 @@ public class FirOldFrontendMPPDiagnosticsWithPsiTestGenerated extends AbstractFi public void testSealedInheritorsInComplexModuleStructure() throws Exception { runTest("compiler/testData/diagnostics/tests/multiplatform/hmpp/multiplatformCompositeAnalysis/sealedInheritorsInComplexModuleStructure.kt"); } + + @Nested + @TestMetadata("compiler/testData/diagnostics/tests/multiplatform/hmpp/multiplatformCompositeAnalysis/annotationMatching") + @TestDataPath("$PROJECT_ROOT") + public class AnnotationMatching { + @Test + public void testAllFilesPresentInAnnotationMatching() throws Exception { + KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/tests/multiplatform/hmpp/multiplatformCompositeAnalysis/annotationMatching"), Pattern.compile("^(.*)\\.kts?$"), Pattern.compile("^(.+)\\.(reversed|fir|ll)\\.kts?$"), TargetBackend.JVM_IR, true); + } + + @Test + @TestMetadata("sourceRetentionAnnotationsWhenTypealias.kt") + public void testSourceRetentionAnnotationsWhenTypealias() throws Exception { + runTest("compiler/testData/diagnostics/tests/multiplatform/hmpp/multiplatformCompositeAnalysis/annotationMatching/sourceRetentionAnnotationsWhenTypealias.kt"); + } + + @Test + @TestMetadata("typealiasedAnnotation.kt") + public void testTypealiasedAnnotation() throws Exception { + runTest("compiler/testData/diagnostics/tests/multiplatform/hmpp/multiplatformCompositeAnalysis/annotationMatching/typealiasedAnnotation.kt"); + } + + @Test + @TestMetadata("typealiasedAnnotationAsArgument.kt") + public void testTypealiasedAnnotationAsArgument() throws Exception { + runTest("compiler/testData/diagnostics/tests/multiplatform/hmpp/multiplatformCompositeAnalysis/annotationMatching/typealiasedAnnotationAsArgument.kt"); + } + } } } 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 79648708387..87b146b7815 100644 --- a/compiler/resolution/src/org/jetbrains/kotlin/resolve/multiplatform/ClassicExpectActualMatchingContext.kt +++ b/compiler/resolution/src/org/jetbrains/kotlin/resolve/multiplatform/ClassicExpectActualMatchingContext.kt @@ -7,6 +7,7 @@ package org.jetbrains.kotlin.resolve.multiplatform import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor +import org.jetbrains.kotlin.descriptors.annotations.KotlinRetention import org.jetbrains.kotlin.incremental.components.NoLookupLocation import org.jetbrains.kotlin.mpp.* import org.jetbrains.kotlin.name.CallableId @@ -368,19 +369,34 @@ class ClassicExpectActualMatchingContext( ) } - private class AnnotationCallInfoImpl( + private inner class AnnotationCallInfoImpl( val annotationDescriptor: AnnotationDescriptor, ) : AnnotationCallInfo { override val annotationSymbol: AnnotationDescriptor = annotationDescriptor override val classId: ClassId? - get() = annotationDescriptor.annotationClass?.classId + get() = getAnnotationClassDescriptor()?.classId override val isRetentionSource: Boolean - get() = annotationDescriptor.isSourceAnnotation + get() = getAnnotationClassDescriptor()?.getAnnotationRetention() == KotlinRetention.SOURCE override val isOptIn: Boolean - get() = annotationDescriptor.annotationClass?.annotations?.hasAnnotation(OptInNames.REQUIRES_OPT_IN_FQ_NAME) ?: false + get() = getAnnotationClassDescriptor()?.annotations?.hasAnnotation(OptInNames.REQUIRES_OPT_IN_FQ_NAME) ?: false + + private fun getAnnotationClassDescriptor(): ClassDescriptor? { + val classDescriptor = annotationDescriptor.annotationClass ?: return null + if (!classDescriptor.isExpect) { + return classDescriptor + } + val classId = classDescriptor.classId + // For IDE composite module analysis, when actual annotation may differ + val platformDescriptor = platformModule.findClassifierAcrossModuleDependencies(classId) + return when (platformDescriptor) { + is ClassDescriptor -> platformDescriptor + is TypeAliasDescriptor -> platformDescriptor.classDescriptor ?: classDescriptor + else -> classDescriptor + } + } } override val DeclarationSymbolMarker.hasSourceAnnotationsErased: Boolean diff --git a/compiler/resolution/src/org/jetbrains/kotlin/resolve/multiplatform/constExpressionValuesEqualityChecker.kt b/compiler/resolution/src/org/jetbrains/kotlin/resolve/multiplatform/constExpressionValuesEqualityChecker.kt index 977f46b6aa8..4c9e6c771f8 100644 --- a/compiler/resolution/src/org/jetbrains/kotlin/resolve/multiplatform/constExpressionValuesEqualityChecker.kt +++ b/compiler/resolution/src/org/jetbrains/kotlin/resolve/multiplatform/constExpressionValuesEqualityChecker.kt @@ -19,8 +19,7 @@ internal fun ExpectActualMatchingContext<*>.areExpressionConstValuesEqual( a is AnnotationDescriptor && b is AnnotationDescriptor -> { val aArgs = a.allValueArguments val bArgs = b.allValueArguments - a.fqName == b.fqName && - aArgs.size == bArgs.size && + aArgs.size == bArgs.size && areCompatibleExpectActualTypes(a.type, b.type) && aArgs.keys.all { k -> areExpressionConstValuesEqual(aArgs[k], bArgs[k], collectionArgumentsCompatibilityCheckStrategy) } } diff --git a/compiler/testData/diagnostics/tests/multiplatform/hmpp/multiplatformCompositeAnalysis/annotationMatching/sourceRetentionAnnotationsWhenTypealias.kt b/compiler/testData/diagnostics/tests/multiplatform/hmpp/multiplatformCompositeAnalysis/annotationMatching/sourceRetentionAnnotationsWhenTypealias.kt new file mode 100644 index 00000000000..8e1fa87e5f3 --- /dev/null +++ b/compiler/testData/diagnostics/tests/multiplatform/hmpp/multiplatformCompositeAnalysis/annotationMatching/sourceRetentionAnnotationsWhenTypealias.kt @@ -0,0 +1,15 @@ +// FIR_IDENTICAL +// WITH_STDLIB +// MODULE: common +// TARGET_PLATFORM: Common +expect annotation class Ann() // No @Retention SOURCE set + +@Ann +expect annotation class CommonVolatile + +// MODULE: main()()(common) +// TARGET_PLATFORM: JVM +@Retention(AnnotationRetention.SOURCE) +actual annotation class Ann + +actual typealias CommonVolatile = kotlin.jvm.Volatile diff --git a/compiler/testData/diagnostics/tests/multiplatform/hmpp/multiplatformCompositeAnalysis/annotationMatching/typealiasedAnnotation.kt b/compiler/testData/diagnostics/tests/multiplatform/hmpp/multiplatformCompositeAnalysis/annotationMatching/typealiasedAnnotation.kt new file mode 100644 index 00000000000..a67b0a2b78e --- /dev/null +++ b/compiler/testData/diagnostics/tests/multiplatform/hmpp/multiplatformCompositeAnalysis/annotationMatching/typealiasedAnnotation.kt @@ -0,0 +1,22 @@ +// FIR_IDENTICAL +// MODULE: common +// TARGET_PLATFORM: Common +expect annotation class Test() + +@Test +expect fun unexpandedOnActual() + +@Test +expect fun expandedOnActual() + +// MODULE: main()()(common) +annotation class JunitTestInLib + +actual typealias Test = JunitTestInLib + +@Test +actual fun unexpandedOnActual() {} + +@JunitTestInLib +actual fun expandedOnActual() {} + diff --git a/compiler/testData/diagnostics/tests/multiplatform/hmpp/multiplatformCompositeAnalysis/annotationMatching/typealiasedAnnotationAsArgument.kt b/compiler/testData/diagnostics/tests/multiplatform/hmpp/multiplatformCompositeAnalysis/annotationMatching/typealiasedAnnotationAsArgument.kt new file mode 100644 index 00000000000..f1d9e6647a2 --- /dev/null +++ b/compiler/testData/diagnostics/tests/multiplatform/hmpp/multiplatformCompositeAnalysis/annotationMatching/typealiasedAnnotationAsArgument.kt @@ -0,0 +1,19 @@ +// FIR_IDENTICAL +// DIAGNOSTICS: -TYPE_MISMATCH +// MODULE: common +// TARGET_PLATFORM: Common +expect annotation class Typealiased() + +annotation class Ann(val p: Typealiased) + +@Ann(Typealiased()) +expect fun test() + +// MODULE: main()()(common) +annotation class TypealiasedImpl + +actual typealias Typealiased = TypealiasedImpl + +@Ann(Typealiased()) +actual fun test() {} + diff --git a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/DiagnosticTestGenerated.java b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/DiagnosticTestGenerated.java index 762c6c44535..1cd752d4e8b 100644 --- a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/DiagnosticTestGenerated.java +++ b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/DiagnosticTestGenerated.java @@ -24179,6 +24179,34 @@ public class DiagnosticTestGenerated extends AbstractDiagnosticTest { public void testSealedInheritorsInComplexModuleStructure() throws Exception { runTest("compiler/testData/diagnostics/tests/multiplatform/hmpp/multiplatformCompositeAnalysis/sealedInheritorsInComplexModuleStructure.kt"); } + + @Nested + @TestMetadata("compiler/testData/diagnostics/tests/multiplatform/hmpp/multiplatformCompositeAnalysis/annotationMatching") + @TestDataPath("$PROJECT_ROOT") + public class AnnotationMatching { + @Test + public void testAllFilesPresentInAnnotationMatching() throws Exception { + KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/tests/multiplatform/hmpp/multiplatformCompositeAnalysis/annotationMatching"), Pattern.compile("^(.*)\\.kts?$"), Pattern.compile("^(.+)\\.(reversed|fir|ll)\\.kts?$"), true); + } + + @Test + @TestMetadata("sourceRetentionAnnotationsWhenTypealias.kt") + public void testSourceRetentionAnnotationsWhenTypealias() throws Exception { + runTest("compiler/testData/diagnostics/tests/multiplatform/hmpp/multiplatformCompositeAnalysis/annotationMatching/sourceRetentionAnnotationsWhenTypealias.kt"); + } + + @Test + @TestMetadata("typealiasedAnnotation.kt") + public void testTypealiasedAnnotation() throws Exception { + runTest("compiler/testData/diagnostics/tests/multiplatform/hmpp/multiplatformCompositeAnalysis/annotationMatching/typealiasedAnnotation.kt"); + } + + @Test + @TestMetadata("typealiasedAnnotationAsArgument.kt") + public void testTypealiasedAnnotationAsArgument() throws Exception { + runTest("compiler/testData/diagnostics/tests/multiplatform/hmpp/multiplatformCompositeAnalysis/annotationMatching/typealiasedAnnotationAsArgument.kt"); + } + } } }