From 6992a707dc65c32bb4289853cc647024c124b0f0 Mon Sep 17 00:00:00 2001 From: Dmitrii Gridin Date: Mon, 12 Jun 2023 13:41:58 +0200 Subject: [PATCH] [LL FIR, Java] fix resolve contract violation from java symbol provider from supertypes To create a smart psi type pointer, IJ Platform uses resolve We cannot use resolve from JavaSymbolProvider, as it may lead to resolve contract violation ^KT-59240 Fixed --- ...entDelegatingTypeSourceWithSmartPointer.kt | 8 ++++++ ...avaElementSourceWithSmartPointerFactory.kt | 12 ++++++++ ...cCompilerTestFirTestdataTestGenerated.java | 12 ++++++++ ...osticCompilerFirTestDataTestGenerated.java | 12 ++++++++ .../LazyBodyIsNotTouchedTestGenerated.java | 10 +++++++ ...ccessJavaFromKotlinViaStaticImport.fir.txt | 11 ++++++++ .../accessJavaFromKotlinViaStaticImport.kt | 24 ++++++++++++++++ ...cessJavaFromKotlinViaStaticImport2.fir.txt | 11 ++++++++ .../accessJavaFromKotlinViaStaticImport2.kt | 28 +++++++++++++++++++ .../FirLightTreeDiagnosticsTestGenerated.java | 12 ++++++++ .../FirPsiDiagnosticTestGenerated.java | 12 ++++++++ .../load/java/structure/impl/JavaClassImpl.kt | 4 ++- .../JavaElementCollectionFromPsiArrayUtil.kt | 6 ++++ .../impl/source/JavaElementSourceFactory.kt | 11 ++++++++ 14 files changed, 172 insertions(+), 1 deletion(-) create mode 100644 compiler/fir/analysis-tests/testData/resolve/accessJavaFromKotlinViaStaticImport.fir.txt create mode 100644 compiler/fir/analysis-tests/testData/resolve/accessJavaFromKotlinViaStaticImport.kt create mode 100644 compiler/fir/analysis-tests/testData/resolve/accessJavaFromKotlinViaStaticImport2.fir.txt create mode 100644 compiler/fir/analysis-tests/testData/resolve/accessJavaFromKotlinViaStaticImport2.kt diff --git a/analysis/analysis-api-impl-base/src/org/jetbrains/kotlin/analysis/api/impl/base/java/source/JavaElementDelegatingTypeSourceWithSmartPointer.kt b/analysis/analysis-api-impl-base/src/org/jetbrains/kotlin/analysis/api/impl/base/java/source/JavaElementDelegatingTypeSourceWithSmartPointer.kt index e02074c7c66..1553c08b977 100644 --- a/analysis/analysis-api-impl-base/src/org/jetbrains/kotlin/analysis/api/impl/base/java/source/JavaElementDelegatingTypeSourceWithSmartPointer.kt +++ b/analysis/analysis-api-impl-base/src/org/jetbrains/kotlin/analysis/api/impl/base/java/source/JavaElementDelegatingTypeSourceWithSmartPointer.kt @@ -60,3 +60,11 @@ internal class JavaElementDelegatingTypeParameterBoundTypeSourceWithSmartPointer return psi.bounds[boundIndex] as TYPE } } + +internal class JavaElementDelegatingSuperTypeSourceWithSmartPointer( + override val psiPointer: SmartPsiElementPointer, + private val superTypeIndex: Int, + override val factory: JavaElementSourceFactory, +) : JavaElementDelegatingTypeSourceWithSmartPointer() { + override fun getType(psi: PsiClass): PsiClassType = psi.superTypes[superTypeIndex] +} diff --git a/analysis/analysis-api-impl-base/src/org/jetbrains/kotlin/analysis/api/impl/base/java/source/JavaElementSourceWithSmartPointerFactory.kt b/analysis/analysis-api-impl-base/src/org/jetbrains/kotlin/analysis/api/impl/base/java/source/JavaElementSourceWithSmartPointerFactory.kt index 84b07714de3..060bd5755b9 100644 --- a/analysis/analysis-api-impl-base/src/org/jetbrains/kotlin/analysis/api/impl/base/java/source/JavaElementSourceWithSmartPointerFactory.kt +++ b/analysis/analysis-api-impl-base/src/org/jetbrains/kotlin/analysis/api/impl/base/java/source/JavaElementSourceWithSmartPointerFactory.kt @@ -45,6 +45,18 @@ class JavaElementSourceWithSmartPointerFactory(project: Project) : JavaElementSo ) } + override fun createSuperTypeSource( + psiTypeParameterSource: JavaElementPsiSource, + superTypeIndex: Int + ): JavaElementTypeSource { + require(psiTypeParameterSource is JavaElementPsiSourceWithSmartPointer) + return JavaElementDelegatingSuperTypeSourceWithSmartPointer( + psiTypeParameterSource.pointer, + superTypeIndex, + psiTypeParameterSource.factory, + ) + } + override fun createExpressionTypeSource(psiExpressionSource: JavaElementPsiSource): JavaElementTypeSource { require(psiExpressionSource is JavaElementPsiSourceWithSmartPointer) return JavaElementDelegatingExpressionTypeSourceWithSmartPointer(psiExpressionSource.pointer, psiExpressionSource.factory) diff --git a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/DiagnosticCompilerTestFirTestdataTestGenerated.java b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/DiagnosticCompilerTestFirTestdataTestGenerated.java index cc0926446e4..73600644f98 100644 --- a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/DiagnosticCompilerTestFirTestdataTestGenerated.java +++ b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/DiagnosticCompilerTestFirTestdataTestGenerated.java @@ -27,6 +27,18 @@ public class DiagnosticCompilerTestFirTestdataTestGenerated extends AbstractDiag runTest("compiler/fir/analysis-tests/testData/resolve/accessJavaFromKotlinViaImport.kt"); } + @Test + @TestMetadata("accessJavaFromKotlinViaStaticImport.kt") + public void testAccessJavaFromKotlinViaStaticImport() throws Exception { + runTest("compiler/fir/analysis-tests/testData/resolve/accessJavaFromKotlinViaStaticImport.kt"); + } + + @Test + @TestMetadata("accessJavaFromKotlinViaStaticImport2.kt") + public void testAccessJavaFromKotlinViaStaticImport2() throws Exception { + runTest("compiler/fir/analysis-tests/testData/resolve/accessJavaFromKotlinViaStaticImport2.kt"); + } + @Test public void testAllFilesPresentInResolve() throws Exception { KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/fir/analysis-tests/testData/resolve"), Pattern.compile("^([^.]+)\\.kt$"), null, true); diff --git a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/LLFirPreresolvedReversedDiagnosticCompilerFirTestDataTestGenerated.java b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/LLFirPreresolvedReversedDiagnosticCompilerFirTestDataTestGenerated.java index 9bb0f50cb93..503715de505 100644 --- a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/LLFirPreresolvedReversedDiagnosticCompilerFirTestDataTestGenerated.java +++ b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/LLFirPreresolvedReversedDiagnosticCompilerFirTestDataTestGenerated.java @@ -27,6 +27,18 @@ public class LLFirPreresolvedReversedDiagnosticCompilerFirTestDataTestGenerated runTest("compiler/fir/analysis-tests/testData/resolve/accessJavaFromKotlinViaImport.kt"); } + @Test + @TestMetadata("accessJavaFromKotlinViaStaticImport.kt") + public void testAccessJavaFromKotlinViaStaticImport() throws Exception { + runTest("compiler/fir/analysis-tests/testData/resolve/accessJavaFromKotlinViaStaticImport.kt"); + } + + @Test + @TestMetadata("accessJavaFromKotlinViaStaticImport2.kt") + public void testAccessJavaFromKotlinViaStaticImport2() throws Exception { + runTest("compiler/fir/analysis-tests/testData/resolve/accessJavaFromKotlinViaStaticImport2.kt"); + } + @Test public void testAllFilesPresentInResolve() throws Exception { KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/fir/analysis-tests/testData/resolve"), Pattern.compile("^([^.]+)\\.kt$"), null, true); diff --git a/compiler/fir/analysis-tests/legacy-fir-tests/tests-gen/org/jetbrains/kotlin/fir/LazyBodyIsNotTouchedTestGenerated.java b/compiler/fir/analysis-tests/legacy-fir-tests/tests-gen/org/jetbrains/kotlin/fir/LazyBodyIsNotTouchedTestGenerated.java index eacf12bbff2..ce357e34804 100644 --- a/compiler/fir/analysis-tests/legacy-fir-tests/tests-gen/org/jetbrains/kotlin/fir/LazyBodyIsNotTouchedTestGenerated.java +++ b/compiler/fir/analysis-tests/legacy-fir-tests/tests-gen/org/jetbrains/kotlin/fir/LazyBodyIsNotTouchedTestGenerated.java @@ -30,6 +30,16 @@ public class LazyBodyIsNotTouchedTestGenerated extends AbstractLazyBodyIsNotTouc runTest("compiler/fir/analysis-tests/testData/resolve/accessJavaFromKotlinViaImport.kt"); } + @TestMetadata("accessJavaFromKotlinViaStaticImport.kt") + public void testAccessJavaFromKotlinViaStaticImport() throws Exception { + runTest("compiler/fir/analysis-tests/testData/resolve/accessJavaFromKotlinViaStaticImport.kt"); + } + + @TestMetadata("accessJavaFromKotlinViaStaticImport2.kt") + public void testAccessJavaFromKotlinViaStaticImport2() throws Exception { + runTest("compiler/fir/analysis-tests/testData/resolve/accessJavaFromKotlinViaStaticImport2.kt"); + } + public void testAllFilesPresentInResolve() throws Exception { KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/fir/analysis-tests/testData/resolve"), Pattern.compile("^([^.]+)\\.kt$"), null, true); } diff --git a/compiler/fir/analysis-tests/testData/resolve/accessJavaFromKotlinViaStaticImport.fir.txt b/compiler/fir/analysis-tests/testData/resolve/accessJavaFromKotlinViaStaticImport.fir.txt new file mode 100644 index 00000000000..ad57860018b --- /dev/null +++ b/compiler/fir/analysis-tests/testData/resolve/accessJavaFromKotlinViaStaticImport.fir.txt @@ -0,0 +1,11 @@ +FILE: useSite.kt + public final fun foo(): R|kotlin/Int| { + ^foo Int(4) + } +FILE: KotlinInterface.kt + public abstract interface KotlinInterface : R|kotlin/Any| { + public abstract var selectedOptions: R|kotlin/Int| + public get(): R|kotlin/Int| + public set(value: R|kotlin/Int|): R|kotlin/Unit| + + } diff --git a/compiler/fir/analysis-tests/testData/resolve/accessJavaFromKotlinViaStaticImport.kt b/compiler/fir/analysis-tests/testData/resolve/accessJavaFromKotlinViaStaticImport.kt new file mode 100644 index 00000000000..4e9c772c065 --- /dev/null +++ b/compiler/fir/analysis-tests/testData/resolve/accessJavaFromKotlinViaStaticImport.kt @@ -0,0 +1,24 @@ +// FILE: useSite.kt + +import InspectionProfileImpl.INIT_INSPECTIONS + +fun foo(): Int = 4 + +// FILE: InspectionProfileImpl.java +import static Configuration.StaticConfigurationClass + +public class InspectionProfileImpl extends StaticConfigurationClass { + public static boolean INIT_INSPECTIONS; +} + +// FILE: Configuration.java +public class Configuration implements KotlinInterface { + public static class StaticConfigurationClass { + + } +} + +// FILE: KotlinInterface.kt +interface KotlinInterface { + var selectedOptions: Int +} diff --git a/compiler/fir/analysis-tests/testData/resolve/accessJavaFromKotlinViaStaticImport2.fir.txt b/compiler/fir/analysis-tests/testData/resolve/accessJavaFromKotlinViaStaticImport2.fir.txt new file mode 100644 index 00000000000..ad57860018b --- /dev/null +++ b/compiler/fir/analysis-tests/testData/resolve/accessJavaFromKotlinViaStaticImport2.fir.txt @@ -0,0 +1,11 @@ +FILE: useSite.kt + public final fun foo(): R|kotlin/Int| { + ^foo Int(4) + } +FILE: KotlinInterface.kt + public abstract interface KotlinInterface : R|kotlin/Any| { + public abstract var selectedOptions: R|kotlin/Int| + public get(): R|kotlin/Int| + public set(value: R|kotlin/Int|): R|kotlin/Unit| + + } diff --git a/compiler/fir/analysis-tests/testData/resolve/accessJavaFromKotlinViaStaticImport2.kt b/compiler/fir/analysis-tests/testData/resolve/accessJavaFromKotlinViaStaticImport2.kt new file mode 100644 index 00000000000..4fe5610cc85 --- /dev/null +++ b/compiler/fir/analysis-tests/testData/resolve/accessJavaFromKotlinViaStaticImport2.kt @@ -0,0 +1,28 @@ +// FILE: useSite.kt + +import InspectionProfileImpl.INIT_INSPECTIONS + +fun foo(): Int = 4 + +// FILE: InspectionProfileImpl.java +import static Configuration.StaticConfigurationClass + +public class InspectionProfileImpl extends InspectionProfile { + public static boolean INIT_INSPECTIONS; +} + +// FILE: InspectionProfile.java +public class InspectionProfile { +} + +// FILE: Configuration.java +public class Configuration implements KotlinInterface { + public static class StaticConfigurationClass { + + } +} + +// FILE: KotlinInterface.kt +interface KotlinInterface { + var selectedOptions: Int +} diff --git a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirLightTreeDiagnosticsTestGenerated.java b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirLightTreeDiagnosticsTestGenerated.java index 2f6bcc6a2a0..db722706aba 100644 --- a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirLightTreeDiagnosticsTestGenerated.java +++ b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirLightTreeDiagnosticsTestGenerated.java @@ -27,6 +27,18 @@ public class FirLightTreeDiagnosticsTestGenerated extends AbstractFirLightTreeDi runTest("compiler/fir/analysis-tests/testData/resolve/accessJavaFromKotlinViaImport.kt"); } + @Test + @TestMetadata("accessJavaFromKotlinViaStaticImport.kt") + public void testAccessJavaFromKotlinViaStaticImport() throws Exception { + runTest("compiler/fir/analysis-tests/testData/resolve/accessJavaFromKotlinViaStaticImport.kt"); + } + + @Test + @TestMetadata("accessJavaFromKotlinViaStaticImport2.kt") + public void testAccessJavaFromKotlinViaStaticImport2() throws Exception { + runTest("compiler/fir/analysis-tests/testData/resolve/accessJavaFromKotlinViaStaticImport2.kt"); + } + @Test public void testAllFilesPresentInResolve() throws Exception { KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/fir/analysis-tests/testData/resolve"), Pattern.compile("^([^.]+)\\.kt$"), null, true); diff --git a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirPsiDiagnosticTestGenerated.java b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirPsiDiagnosticTestGenerated.java index 6fb7bb71a70..a16d3577742 100644 --- a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirPsiDiagnosticTestGenerated.java +++ b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirPsiDiagnosticTestGenerated.java @@ -27,6 +27,18 @@ public class FirPsiDiagnosticTestGenerated extends AbstractFirPsiDiagnosticTest runTest("compiler/fir/analysis-tests/testData/resolve/accessJavaFromKotlinViaImport.kt"); } + @Test + @TestMetadata("accessJavaFromKotlinViaStaticImport.kt") + public void testAccessJavaFromKotlinViaStaticImport() throws Exception { + runTest("compiler/fir/analysis-tests/testData/resolve/accessJavaFromKotlinViaStaticImport.kt"); + } + + @Test + @TestMetadata("accessJavaFromKotlinViaStaticImport2.kt") + public void testAccessJavaFromKotlinViaStaticImport2() throws Exception { + runTest("compiler/fir/analysis-tests/testData/resolve/accessJavaFromKotlinViaStaticImport2.kt"); + } + @Test public void testAllFilesPresentInResolve() throws Exception { KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/fir/analysis-tests/testData/resolve"), Pattern.compile("^([^.]+)\\.kt$"), null, true); diff --git a/compiler/resolution.common.jvm/src/org/jetbrains/kotlin/load/java/structure/impl/JavaClassImpl.kt b/compiler/resolution.common.jvm/src/org/jetbrains/kotlin/load/java/structure/impl/JavaClassImpl.kt index 78d4183546e..8d5a13b988e 100644 --- a/compiler/resolution.common.jvm/src/org/jetbrains/kotlin/load/java/structure/impl/JavaClassImpl.kt +++ b/compiler/resolution.common.jvm/src/org/jetbrains/kotlin/load/java/structure/impl/JavaClassImpl.kt @@ -84,7 +84,9 @@ class JavaClassImpl(psiClassSource: JavaElementPsiSource) : JavaClassi get() = typeParameters(psi.typeParameters, sourceFactory) override val supertypes: Collection - get() = classifierTypes(psi.superTypes, sourceFactory) + get() = psi.superTypes.convertIndexed { index, _ -> + JavaClassifierTypeImpl(sourceFactory.createSuperTypeSource(psiElementSource, index)) + } override val methods: Collection get() { diff --git a/compiler/resolution.common.jvm/src/org/jetbrains/kotlin/load/java/structure/impl/JavaElementCollectionFromPsiArrayUtil.kt b/compiler/resolution.common.jvm/src/org/jetbrains/kotlin/load/java/structure/impl/JavaElementCollectionFromPsiArrayUtil.kt index 455baaa962f..db8719a1a4c 100644 --- a/compiler/resolution.common.jvm/src/org/jetbrains/kotlin/load/java/structure/impl/JavaElementCollectionFromPsiArrayUtil.kt +++ b/compiler/resolution.common.jvm/src/org/jetbrains/kotlin/load/java/structure/impl/JavaElementCollectionFromPsiArrayUtil.kt @@ -32,6 +32,12 @@ inline fun Array.convert(factory: (Psi) -> Java): List = else -> map(factory) } +inline fun Array.convertIndexed(factory: (Int, Psi) -> Java): List = when (size) { + 0 -> emptyList() + 1 -> listOf(factory(0, first())) + else -> mapIndexed(factory) +} + fun Collection.convert(factory: (Psi) -> Java): List = when (size) { 0 -> emptyList() diff --git a/compiler/resolution.common.jvm/src/org/jetbrains/kotlin/load/java/structure/impl/source/JavaElementSourceFactory.kt b/compiler/resolution.common.jvm/src/org/jetbrains/kotlin/load/java/structure/impl/source/JavaElementSourceFactory.kt index d01d69ef730..8a5e6a82fea 100644 --- a/compiler/resolution.common.jvm/src/org/jetbrains/kotlin/load/java/structure/impl/source/JavaElementSourceFactory.kt +++ b/compiler/resolution.common.jvm/src/org/jetbrains/kotlin/load/java/structure/impl/source/JavaElementSourceFactory.kt @@ -19,6 +19,11 @@ abstract class JavaElementSourceFactory { boundIndex: Int, ): JavaElementTypeSource + abstract fun createSuperTypeSource( + psiTypeParameterSource: JavaElementPsiSource, + superTypeIndex: Int, + ): JavaElementTypeSource + abstract fun createExpressionTypeSource(psiExpressionSource: JavaElementPsiSource): JavaElementTypeSource companion object { @@ -51,6 +56,12 @@ class JavaFixedElementSourceFactory : JavaElementSourceFactory() { return createTypeSource(psiTypeParameterSource.psi.bounds[boundIndex] as TYPE) } + override fun createSuperTypeSource( + psiTypeParameterSource: JavaElementPsiSource, + superTypeIndex: Int, + ): JavaElementTypeSource { + return createTypeSource(psiTypeParameterSource.psi.superTypes[superTypeIndex]) + } override fun createExpressionTypeSource(psiExpressionSource: JavaElementPsiSource): JavaElementTypeSource { @Suppress("UNCHECKED_CAST")