From d689c1a38fec874bdaf6361ec49ddaf45c7e7dac Mon Sep 17 00:00:00 2001 From: Dmitrii Gridin Date: Thu, 19 Oct 2023 22:14:58 +0200 Subject: [PATCH] [FIR] FirJavaFacade: fix contract violation from annotations `isJavaDeprecatedAnnotation` can't be used here because it triggers the resolution of an annotation ClassId ^KT-62705 Fixed --- ...CompilerTestFE10TestdataTestGenerated.java | 6 ++++ ...sticCompilerFE10TestDataTestGenerated.java | 6 ++++ ...eeOldFrontendDiagnosticsTestGenerated.java | 6 ++++ ...siOldFrontendDiagnosticsTestGenerated.java | 6 ++++ .../kotlin/fir/java/FirJavaFacade.kt | 7 +--- .../fir/java/declarations/FirJavaClass.kt | 9 +++-- .../kotlin/fir/java/javaAnnotationsMapping.kt | 13 ++++---- .../annotations/DeprecatedInJavaDoc.fir.kt | 33 +++++++++++++++++++ .../tests/annotations/DeprecatedInJavaDoc.kt | 33 +++++++++++++++++++ .../test/runners/DiagnosticTestGenerated.java | 6 ++++ 10 files changed, 110 insertions(+), 15 deletions(-) create mode 100644 compiler/testData/diagnostics/tests/annotations/DeprecatedInJavaDoc.fir.kt create mode 100644 compiler/testData/diagnostics/tests/annotations/DeprecatedInJavaDoc.kt diff --git a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/DiagnosticCompilerTestFE10TestdataTestGenerated.java b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/DiagnosticCompilerTestFE10TestdataTestGenerated.java index 368b89893e0..9a4e0218017 100644 --- a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/DiagnosticCompilerTestFE10TestdataTestGenerated.java +++ b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/DiagnosticCompilerTestFE10TestdataTestGenerated.java @@ -1884,6 +1884,12 @@ public class DiagnosticCompilerTestFE10TestdataTestGenerated extends AbstractDia runTest("compiler/testData/diagnostics/tests/annotations/Deprecated.kt"); } + @Test + @TestMetadata("DeprecatedInJavaDoc.kt") + public void testDeprecatedInJavaDoc() throws Exception { + runTest("compiler/testData/diagnostics/tests/annotations/DeprecatedInJavaDoc.kt"); + } + @Test @TestMetadata("DeprecationOnAny.kt") public void testDeprecationOnAny() throws Exception { diff --git a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/LLFirPreresolvedReversedDiagnosticCompilerFE10TestDataTestGenerated.java b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/LLFirPreresolvedReversedDiagnosticCompilerFE10TestDataTestGenerated.java index 16d3beff44d..eb95c94bdd2 100644 --- a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/LLFirPreresolvedReversedDiagnosticCompilerFE10TestDataTestGenerated.java +++ b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/LLFirPreresolvedReversedDiagnosticCompilerFE10TestDataTestGenerated.java @@ -1884,6 +1884,12 @@ public class LLFirPreresolvedReversedDiagnosticCompilerFE10TestDataTestGenerated runTest("compiler/testData/diagnostics/tests/annotations/Deprecated.kt"); } + @Test + @TestMetadata("DeprecatedInJavaDoc.kt") + public void testDeprecatedInJavaDoc() throws Exception { + runTest("compiler/testData/diagnostics/tests/annotations/DeprecatedInJavaDoc.kt"); + } + @Test @TestMetadata("DeprecationOnAny.kt") public void testDeprecationOnAny() throws Exception { diff --git a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirLightTreeOldFrontendDiagnosticsTestGenerated.java b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirLightTreeOldFrontendDiagnosticsTestGenerated.java index 2ab269f744e..bb5052d0bfd 100644 --- a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirLightTreeOldFrontendDiagnosticsTestGenerated.java +++ b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirLightTreeOldFrontendDiagnosticsTestGenerated.java @@ -1884,6 +1884,12 @@ public class FirLightTreeOldFrontendDiagnosticsTestGenerated extends AbstractFir runTest("compiler/testData/diagnostics/tests/annotations/Deprecated.kt"); } + @Test + @TestMetadata("DeprecatedInJavaDoc.kt") + public void testDeprecatedInJavaDoc() throws Exception { + runTest("compiler/testData/diagnostics/tests/annotations/DeprecatedInJavaDoc.kt"); + } + @Test @TestMetadata("DeprecationOnAny.kt") public void testDeprecationOnAny() throws Exception { diff --git a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirPsiOldFrontendDiagnosticsTestGenerated.java b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirPsiOldFrontendDiagnosticsTestGenerated.java index b51fc06e8fa..d41cf4f36ce 100644 --- a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirPsiOldFrontendDiagnosticsTestGenerated.java +++ b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirPsiOldFrontendDiagnosticsTestGenerated.java @@ -1890,6 +1890,12 @@ public class FirPsiOldFrontendDiagnosticsTestGenerated extends AbstractFirPsiDia runTest("compiler/testData/diagnostics/tests/annotations/Deprecated.kt"); } + @Test + @TestMetadata("DeprecatedInJavaDoc.kt") + public void testDeprecatedInJavaDoc() throws Exception { + runTest("compiler/testData/diagnostics/tests/annotations/DeprecatedInJavaDoc.kt"); + } + @Test @TestMetadata("DeprecationOnAny.kt") public void testDeprecationOnAny() throws Exception { diff --git a/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/FirJavaFacade.kt b/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/FirJavaFacade.kt index 0942b5f22bf..df8f6cb0440 100644 --- a/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/FirJavaFacade.kt +++ b/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/FirJavaFacade.kt @@ -42,9 +42,6 @@ import org.jetbrains.kotlin.load.java.JavaClassFinder import org.jetbrains.kotlin.load.java.structure.* import org.jetbrains.kotlin.load.java.structure.impl.JavaElementImpl import org.jetbrains.kotlin.load.java.structure.impl.classFiles.BinaryJavaClass -import org.jetbrains.kotlin.load.kotlin.KotlinJvmBinaryClass -import org.jetbrains.kotlin.load.kotlin.KotlinJvmBinarySourceElement -import org.jetbrains.kotlin.load.kotlin.header.KotlinClassHeader import org.jetbrains.kotlin.name.* import org.jetbrains.kotlin.types.Variance.INVARIANT @@ -244,9 +241,7 @@ abstract class FirJavaFacade( return buildJavaClass { resolvePhase = FirResolvePhase.BODY_RESOLVE javaAnnotations += javaClass.annotations - if (javaClass.isDeprecatedInJavaDoc && javaAnnotations.none { it.isJavaDeprecatedAnnotation() }) { - javaAnnotations += DeprecatedInJavaDocAnnotation - } + isDeprecatedInJavaDoc = javaClass.isDeprecatedInJavaDoc source = javaClass.toSourceElement() this.moduleData = moduleData symbol = classSymbol diff --git a/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/declarations/FirJavaClass.kt b/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/declarations/FirJavaClass.kt index c06ba310eb7..6e3e9b0baa4 100644 --- a/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/declarations/FirJavaClass.kt +++ b/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/declarations/FirJavaClass.kt @@ -50,7 +50,8 @@ class FirJavaClass @FirImplementationDetail internal constructor( override val typeParameters: MutableList, internal val javaPackage: JavaPackage?, val javaTypeParameterStack: JavaTypeParameterStack, - internal val existingNestedClassifierNames: List + internal val existingNestedClassifierNames: List, + private val isDeprecatedInJavaDoc: Boolean, ) : FirRegularClass() { override val hasLazyNestedClassifiers: Boolean get() = true override val controlFlowGraphReference: FirControlFlowGraphReference? get() = null @@ -75,7 +76,7 @@ class FirJavaClass @FirImplementationDetail internal constructor( // TODO: the lazy annotations is a workaround for KT-55387, some non-lazy solution should probably be used instead override val annotations: List by lazy { - unEnhancedAnnotations.convertAnnotationsToFir(moduleData.session) + unEnhancedAnnotations.convertAnnotationsToFir(moduleData.session, isDeprecatedInJavaDoc) } // TODO: the lazy deprecationsProvider is a workaround for KT-55387, some non-lazy solution should probably be used instead @@ -157,6 +158,7 @@ class FirJavaClassBuilder : FirRegularClassBuilder(), FirAnnotationContainerBuil var javaPackage: JavaPackage? = null lateinit var javaTypeParameterStack: JavaTypeParameterStack val existingNestedClassifierNames: MutableList = mutableListOf() + var isDeprecatedInJavaDoc: Boolean = false override var source: KtSourceElement? = null override var resolvePhase: FirResolvePhase = FirResolvePhase.RAW_FIR @@ -184,7 +186,8 @@ class FirJavaClassBuilder : FirRegularClassBuilder(), FirAnnotationContainerBuil typeParameters, javaPackage, javaTypeParameterStack, - existingNestedClassifierNames + existingNestedClassifierNames, + isDeprecatedInJavaDoc, ) } diff --git a/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/javaAnnotationsMapping.kt b/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/javaAnnotationsMapping.kt index b50ecca5ee5..37fc50ca08b 100644 --- a/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/javaAnnotationsMapping.kt +++ b/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/javaAnnotationsMapping.kt @@ -5,9 +5,6 @@ package org.jetbrains.kotlin.fir.java -import com.intellij.patterns.PsiJavaPatterns.psiAnnotation -import org.jetbrains.kotlin.KtFakeSourceElement -import org.jetbrains.kotlin.KtFakeSourceElementKind import org.jetbrains.kotlin.KtSourceElement import org.jetbrains.kotlin.fir.FirAnnotationContainer import org.jetbrains.kotlin.fir.FirElement @@ -46,19 +43,19 @@ import org.jetbrains.kotlin.name.* import org.jetbrains.kotlin.toKtPsiSourceElement import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull import org.jetbrains.kotlin.utils.addToStdlib.ifNotEmpty -import org.jetbrains.kotlin.utils.exceptions.requireWithAttachment import java.util.* internal fun Iterable.convertAnnotationsToFir( session: FirSession, ): List = map { it.toFirAnnotationCall(session) } -internal fun JavaAnnotationOwner.convertAnnotationsToFir( +internal fun Iterable.convertAnnotationsToFir( session: FirSession, + isDeprecatedInJavaDoc: Boolean, ): List = buildList { var isDeprecated = false - annotations.mapTo(this) { + this@convertAnnotationsToFir.mapTo(this) { if (it.isJavaDeprecatedAnnotation()) isDeprecated = true it.toFirAnnotationCall(session) } @@ -68,6 +65,10 @@ internal fun JavaAnnotationOwner.convertAnnotationsToFir( } } +internal fun JavaAnnotationOwner.convertAnnotationsToFir( + session: FirSession, +): List = annotations.convertAnnotationsToFir(session, isDeprecatedInJavaDoc) + internal object DeprecatedInJavaDocAnnotation : JavaAnnotation { override val arguments: Collection get() = emptyList() override val classId: ClassId get() = JvmStandardClassIds.Annotations.Java.Deprecated diff --git a/compiler/testData/diagnostics/tests/annotations/DeprecatedInJavaDoc.fir.kt b/compiler/testData/diagnostics/tests/annotations/DeprecatedInJavaDoc.fir.kt new file mode 100644 index 00000000000..9a2b33bc020 --- /dev/null +++ b/compiler/testData/diagnostics/tests/annotations/DeprecatedInJavaDoc.fir.kt @@ -0,0 +1,33 @@ +// FILE: usage.kt +package first + +import third.JavaClass.NestedJavaClass + +// FILE: KotlinAnnotation.kt +package second + +class KotlinClass { + fun foo(i: Int) {} + annotation class KotlinAnnotation +} + +// FILE: third/JavaClass.java +package third; + +import second.KotlinClass.*; + +import static second.KotlinClass.*; + +/** + * @deprecated deprecated message + */ +@KotlinAnnotation +public class JavaClass { + /** + * @deprecated deprecated message + */ + @KotlinAnnotation + public static class NestedJavaClass { + + } +} diff --git a/compiler/testData/diagnostics/tests/annotations/DeprecatedInJavaDoc.kt b/compiler/testData/diagnostics/tests/annotations/DeprecatedInJavaDoc.kt new file mode 100644 index 00000000000..c589b73e1a9 --- /dev/null +++ b/compiler/testData/diagnostics/tests/annotations/DeprecatedInJavaDoc.kt @@ -0,0 +1,33 @@ +// FILE: usage.kt +package first + +import third.JavaClass.NestedJavaClass + +// FILE: KotlinAnnotation.kt +package second + +class KotlinClass { + fun foo(i: Int) {} + annotation class KotlinAnnotation +} + +// FILE: third/JavaClass.java +package third; + +import second.KotlinClass.*; + +import static second.KotlinClass.*; + +/** + * @deprecated deprecated message + */ +@KotlinAnnotation +public class JavaClass { + /** + * @deprecated deprecated message + */ + @KotlinAnnotation + public static class NestedJavaClass { + + } +} 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 c06f9f34c72..f2fd221fd38 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 @@ -1890,6 +1890,12 @@ public class DiagnosticTestGenerated extends AbstractDiagnosticTest { runTest("compiler/testData/diagnostics/tests/annotations/Deprecated.kt"); } + @Test + @TestMetadata("DeprecatedInJavaDoc.kt") + public void testDeprecatedInJavaDoc() throws Exception { + runTest("compiler/testData/diagnostics/tests/annotations/DeprecatedInJavaDoc.kt"); + } + @Test @TestMetadata("DeprecationOnAny.kt") public void testDeprecationOnAny() throws Exception {