From b8f15cbbb3e7ef53e0b8580fa15088c8805421cf Mon Sep 17 00:00:00 2001 From: Ilya Kirillov Date: Wed, 7 Jun 2023 14:56:56 +0200 Subject: [PATCH] [LL FIR, Java] fix resolve contract violation from java symbol provider 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-59133 fixed --- ...entDelegatingTypeSourceWithSmartPointer.kt | 13 ++++++++++++ ...avaElementSourceWithSmartPointerFactory.kt | 12 +++++++++++ ...cCompilerTestFirTestdataTestGenerated.java | 6 ++++++ ...osticCompilerFirTestDataTestGenerated.java | 6 ++++++ .../LazyBodyIsNotTouchedTestGenerated.java | 5 +++++ .../accessJavaFromKotlinViaImport.fir.txt | 11 ++++++++++ .../resolve/accessJavaFromKotlinViaImport.kt | 21 +++++++++++++++++++ .../FirLightTreeDiagnosticsTestGenerated.java | 6 ++++++ .../FirPsiDiagnosticTestGenerated.java | 6 ++++++ .../structure/impl/JavaTypeParameterImpl.java | 16 +++++++++++++- .../impl/source/JavaElementSourceFactory.kt | 13 ++++++++++++ 11 files changed, 114 insertions(+), 1 deletion(-) create mode 100644 compiler/fir/analysis-tests/testData/resolve/accessJavaFromKotlinViaImport.fir.txt create mode 100644 compiler/fir/analysis-tests/testData/resolve/accessJavaFromKotlinViaImport.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 3cb08d5888a..e02074c7c66 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 @@ -47,3 +47,16 @@ internal class JavaElementDelegatingExpressionTypeSourceWithSmartPointer( + override val psiPointer: SmartPsiElementPointer, + private val boundIndex: Int, + override val factory: JavaElementSourceFactory, +) : JavaElementDelegatingTypeSourceWithSmartPointer() { + + override fun getType(psi: PsiTypeParameter): TYPE { + @Suppress("UNCHECKED_CAST") + return psi.bounds[boundIndex] as TYPE + } +} 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 4aca20cc55a..84b07714de3 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 @@ -33,6 +33,18 @@ class JavaElementSourceWithSmartPointerFactory(project: Project) : JavaElementSo return JavaElementDelegatingMethodReturnTypeSourceWithSmartPointer(psiMethodSource.pointer, psiMethodSource.factory) } + override fun createTypeParameterUpperBoundTypeSource( + psiTypeParameterSource: JavaElementPsiSource, + boundIndex: Int + ): JavaElementTypeSource { + require(psiTypeParameterSource is JavaElementPsiSourceWithSmartPointer) + return JavaElementDelegatingTypeParameterBoundTypeSourceWithSmartPointer( + psiTypeParameterSource.pointer, + boundIndex, + 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 d0ad7b42e4b..cc0926446e4 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 @@ -21,6 +21,12 @@ public class DiagnosticCompilerTestFirTestdataTestGenerated extends AbstractDiag @TestMetadata("compiler/fir/analysis-tests/testData/resolve") @TestDataPath("$PROJECT_ROOT") public class Resolve { + @Test + @TestMetadata("accessJavaFromKotlinViaImport.kt") + public void testAccessJavaFromKotlinViaImport() throws Exception { + runTest("compiler/fir/analysis-tests/testData/resolve/accessJavaFromKotlinViaImport.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 7583bbf1907..9bb0f50cb93 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 @@ -21,6 +21,12 @@ public class LLFirPreresolvedReversedDiagnosticCompilerFirTestDataTestGenerated @TestMetadata("compiler/fir/analysis-tests/testData/resolve") @TestDataPath("$PROJECT_ROOT") public class Resolve { + @Test + @TestMetadata("accessJavaFromKotlinViaImport.kt") + public void testAccessJavaFromKotlinViaImport() throws Exception { + runTest("compiler/fir/analysis-tests/testData/resolve/accessJavaFromKotlinViaImport.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 a8b2f3924ae..eacf12bbff2 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 @@ -25,6 +25,11 @@ public class LazyBodyIsNotTouchedTestGenerated extends AbstractLazyBodyIsNotTouc KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); } + @TestMetadata("accessJavaFromKotlinViaImport.kt") + public void testAccessJavaFromKotlinViaImport() throws Exception { + runTest("compiler/fir/analysis-tests/testData/resolve/accessJavaFromKotlinViaImport.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/accessJavaFromKotlinViaImport.fir.txt b/compiler/fir/analysis-tests/testData/resolve/accessJavaFromKotlinViaImport.fir.txt new file mode 100644 index 00000000000..c19055c3ee5 --- /dev/null +++ b/compiler/fir/analysis-tests/testData/resolve/accessJavaFromKotlinViaImport.fir.txt @@ -0,0 +1,11 @@ +FILE: useSite.kt + public final fun foo(): R|kotlin/Unit| { + Q|InspectionProfileImpl|.R|/InspectionProfileImpl.INIT_INSPECTIONS| = Boolean(true) + } +FILE: NewInspectionProfile.kt + public abstract class NewInspectionProfile : R|kotlin/Any| { + public constructor(): R|NewInspectionProfile| { + super() + } + + } diff --git a/compiler/fir/analysis-tests/testData/resolve/accessJavaFromKotlinViaImport.kt b/compiler/fir/analysis-tests/testData/resolve/accessJavaFromKotlinViaImport.kt new file mode 100644 index 00000000000..dd9e2c276f6 --- /dev/null +++ b/compiler/fir/analysis-tests/testData/resolve/accessJavaFromKotlinViaImport.kt @@ -0,0 +1,21 @@ +// FILE: useSite.kt + +fun foo() { + InspectionProfileImpl.INIT_INSPECTIONS = true +} + +// FILE: InspectionProfileImpl.java +public class InspectionProfileImpl extends NewInspectionProfile { + public static boolean INIT_INSPECTIONS; + + public T getUnwrappedTool() { } +} + + +// FILE: NewInspectionProfile.kt +import InspectionProfileImpl.INIT_INSPECTIONS + +abstract class NewInspectionProfile + +// FILE: InspectionProfileEntry.java +public abstract class InspectionProfileEntry {} 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 74dd31493e2..2f6bcc6a2a0 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 @@ -21,6 +21,12 @@ public class FirLightTreeDiagnosticsTestGenerated extends AbstractFirLightTreeDi @TestMetadata("compiler/fir/analysis-tests/testData/resolve") @TestDataPath("$PROJECT_ROOT") public class Resolve { + @Test + @TestMetadata("accessJavaFromKotlinViaImport.kt") + public void testAccessJavaFromKotlinViaImport() throws Exception { + runTest("compiler/fir/analysis-tests/testData/resolve/accessJavaFromKotlinViaImport.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 72729bc3fc5..6fb7bb71a70 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 @@ -21,6 +21,12 @@ public class FirPsiDiagnosticTestGenerated extends AbstractFirPsiDiagnosticTest @TestMetadata("compiler/fir/analysis-tests/testData/resolve") @TestDataPath("$PROJECT_ROOT") public class Resolve { + @Test + @TestMetadata("accessJavaFromKotlinViaImport.kt") + public void testAccessJavaFromKotlinViaImport() throws Exception { + runTest("compiler/fir/analysis-tests/testData/resolve/accessJavaFromKotlinViaImport.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/JavaTypeParameterImpl.java b/compiler/resolution.common.jvm/src/org/jetbrains/kotlin/load/java/structure/impl/JavaTypeParameterImpl.java index d71cd5411ce..9089e127dc7 100644 --- a/compiler/resolution.common.jvm/src/org/jetbrains/kotlin/load/java/structure/impl/JavaTypeParameterImpl.java +++ b/compiler/resolution.common.jvm/src/org/jetbrains/kotlin/load/java/structure/impl/JavaTypeParameterImpl.java @@ -17,6 +17,7 @@ package org.jetbrains.kotlin.load.java.structure.impl; import com.intellij.psi.PsiAnnotationOwner; +import com.intellij.psi.PsiClassType; import com.intellij.psi.PsiField; import com.intellij.psi.PsiTypeParameter; import org.jetbrains.annotations.NotNull; @@ -25,10 +26,14 @@ import org.jetbrains.kotlin.load.java.structure.JavaClassifierType; import org.jetbrains.kotlin.load.java.structure.JavaTypeParameter; import org.jetbrains.kotlin.load.java.structure.impl.source.JavaElementPsiSource; import org.jetbrains.kotlin.load.java.structure.impl.source.JavaElementSourceFactory; +import org.jetbrains.kotlin.load.java.structure.impl.source.JavaElementTypeSource; import org.jetbrains.kotlin.name.Name; import org.jetbrains.kotlin.name.SpecialNames; +import java.util.ArrayList; +import java.util.Arrays; import java.util.Collection; +import java.util.Collections; import static org.jetbrains.kotlin.load.java.structure.impl.JavaElementCollectionFromPsiArrayUtil.classifierTypes; @@ -51,7 +56,16 @@ public class JavaTypeParameterImpl extends JavaClassifierImpl @Override @NotNull public Collection getUpperBounds() { - return classifierTypes(getPsi().getExtendsList().getReferencedTypes(), getSourceFactory()); + PsiClassType[] referencedTypes = getPsi().getExtendsList().getReferencedTypes(); + if (referencedTypes.length == 0) return Collections.emptyList(); + Collection result = new ArrayList<>(referencedTypes.length); + JavaElementSourceFactory sourceFactory = getSourceFactory(); + for (int boundIndex = 0; boundIndex < referencedTypes.length; boundIndex++) { + JavaElementTypeSource source = + sourceFactory.createTypeParameterUpperBoundTypeSource(psiElementSource, boundIndex); + result.add(new JavaClassifierTypeImpl(source)); + } + return result; } @Nullable 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 a2a951407a2..d01d69ef730 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 @@ -14,6 +14,11 @@ abstract class JavaElementSourceFactory { abstract fun createVariableReturnTypeSource(psiVariableSource: JavaElementPsiSource): JavaElementTypeSource abstract fun createMethodReturnTypeSource(psiMethodSource: JavaElementPsiSource): JavaElementTypeSource + abstract fun createTypeParameterUpperBoundTypeSource( + psiTypeParameterSource: JavaElementPsiSource, + boundIndex: Int, + ): JavaElementTypeSource + abstract fun createExpressionTypeSource(psiExpressionSource: JavaElementPsiSource): JavaElementTypeSource companion object { @@ -38,6 +43,14 @@ class JavaFixedElementSourceFactory : JavaElementSourceFactory() { return createTypeSource(psiVariableSource.psi.type as TYPE) } + override fun createTypeParameterUpperBoundTypeSource( + psiTypeParameterSource: JavaElementPsiSource, + boundIndex: Int + ): JavaElementTypeSource { + @Suppress("UNCHECKED_CAST") + return createTypeSource(psiTypeParameterSource.psi.bounds[boundIndex] as TYPE) + } + override fun createExpressionTypeSource(psiExpressionSource: JavaElementPsiSource): JavaElementTypeSource { @Suppress("UNCHECKED_CAST")