From dcd76e73094efdbfac5ca457a2a0059bc746f858 Mon Sep 17 00:00:00 2001 From: Tianyu Geng Date: Wed, 23 Jun 2021 18:29:39 -0700 Subject: [PATCH] FIR IDE: handle reference to package and outer classes For a qualified name like `foo.bar.Outer.Inner`, FIR represents it as one atomic FIR element. Hence, to properly resolve these names to the corresponding package and class, we need some additional work. Original commit: 84f8d4d315f30cec46b4f50bbeafe834215dd057 GitOrigin-RevId: ef33f5fd039acfae0e4f171bc9f7a831131fde83 --- .../AbstractFirReferenceResolveTest.kt | 11 ----- .../FirReferenceResolveTestGenerated.java | 48 +++++++++++++++++++ .../kotlin/test/utils/IgnoreTests.kt | 1 + .../resolve/AbstractReferenceResolveTest.kt | 10 +++- .../ReferenceResolveTestGenerated.java | 48 +++++++++++++++++++ .../kotlin/companionObject/named.0.kt | 1 + .../kotlin/companionObject/simple.0.kt | 1 + .../kotlinLocalObjectUsages1.0.kt | 1 + .../kotlinLocalObjectUsages1.results.txt | 2 +- .../kotlinLocalObjectUsages2.0.kt | 1 + .../kotlinLocalObjectUsages2.results.txt | 2 +- .../TopLevelClassVsLocalClassQualifier.kt | 2 - .../TopLevelObjectVsLocalClassQualifier.kt | 1 + ...veFirstPackageOfFullyQualifiedReference.kt | 13 +++++ .../ResolveFullyQualifiedCompanionObject.kt | 14 ++++++ ...olveOuterClassOfFullyQualifiedReference.kt | 13 +++++ ...ResolvePackageOfFullyQualifiedReference.kt | 13 +++++ .../qualifiedAccess/callableReference1.kt | 11 +++++ .../qualifiedAccess/callableReference2.kt | 14 ++++++ .../qualifiedAccess/callableReference3.kt | 14 ++++++ 20 files changed, 205 insertions(+), 16 deletions(-) create mode 100644 plugins/kotlin/idea/tests/testData/resolve/references/qualifiedAccess/ResolveFirstPackageOfFullyQualifiedReference.kt create mode 100644 plugins/kotlin/idea/tests/testData/resolve/references/qualifiedAccess/ResolveFullyQualifiedCompanionObject.kt create mode 100644 plugins/kotlin/idea/tests/testData/resolve/references/qualifiedAccess/ResolveOuterClassOfFullyQualifiedReference.kt create mode 100644 plugins/kotlin/idea/tests/testData/resolve/references/qualifiedAccess/ResolvePackageOfFullyQualifiedReference.kt create mode 100644 plugins/kotlin/idea/tests/testData/resolve/references/qualifiedAccess/callableReference1.kt create mode 100644 plugins/kotlin/idea/tests/testData/resolve/references/qualifiedAccess/callableReference2.kt create mode 100644 plugins/kotlin/idea/tests/testData/resolve/references/qualifiedAccess/callableReference3.kt diff --git a/plugins/kotlin/fir/test/org/jetbrains/kotlin/idea/fir/resolve/AbstractFirReferenceResolveTest.kt b/plugins/kotlin/fir/test/org/jetbrains/kotlin/idea/fir/resolve/AbstractFirReferenceResolveTest.kt index 5b630e6becea..ae6e2d8fcff4 100644 --- a/plugins/kotlin/fir/test/org/jetbrains/kotlin/idea/fir/resolve/AbstractFirReferenceResolveTest.kt +++ b/plugins/kotlin/fir/test/org/jetbrains/kotlin/idea/fir/resolve/AbstractFirReferenceResolveTest.kt @@ -2,13 +2,11 @@ package org.jetbrains.kotlin.idea.fir.resolve -import org.jetbrains.kotlin.idea.completion.test.configureWithExtraFile import org.jetbrains.kotlin.idea.fir.invalidateCaches import org.jetbrains.kotlin.idea.resolve.AbstractReferenceResolveTest import org.jetbrains.kotlin.idea.test.KotlinLightProjectDescriptor import org.jetbrains.kotlin.idea.test.KotlinWithJdkAndRuntimeLightProjectDescriptor import org.jetbrains.kotlin.psi.KtFile -import org.jetbrains.kotlin.test.utils.IgnoreTests abstract class AbstractFirReferenceResolveTest : AbstractReferenceResolveTest() { override fun isFirPlugin(): Boolean = true @@ -20,13 +18,4 @@ abstract class AbstractFirReferenceResolveTest : AbstractReferenceResolveTest() project.invalidateCaches(myFixture.file as? KtFile) super.tearDown() } - - override fun doTest(path: String) { - assert(path.endsWith(".kt")) { path } - myFixture.configureWithExtraFile(path, ".Data") - - IgnoreTests.runTestIfNotDisabledByFileDirective(testDataFile().toPath(), IgnoreTests.DIRECTIVES.IGNORE_FIR) { - performChecks() - } - } } \ No newline at end of file diff --git a/plugins/kotlin/fir/test/org/jetbrains/kotlin/idea/fir/resolve/FirReferenceResolveTestGenerated.java b/plugins/kotlin/fir/test/org/jetbrains/kotlin/idea/fir/resolve/FirReferenceResolveTestGenerated.java index 408100ebe550..c51bb543518e 100644 --- a/plugins/kotlin/fir/test/org/jetbrains/kotlin/idea/fir/resolve/FirReferenceResolveTestGenerated.java +++ b/plugins/kotlin/fir/test/org/jetbrains/kotlin/idea/fir/resolve/FirReferenceResolveTestGenerated.java @@ -886,4 +886,52 @@ public class FirReferenceResolveTestGenerated extends AbstractFirReferenceResolv runTest("../idea/tests/testData/resolve/references/packageReference/kotlinPackageSecondQualifier.kt"); } } + + @TestMetadata("idea/testData/resolve/references/qualifiedAccess") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class QualifiedAccess extends AbstractFirReferenceResolveTest { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); + } + + public void testAllFilesPresentInQualifiedAccess() throws Exception { + KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("idea/testData/resolve/references/qualifiedAccess"), Pattern.compile("^([^.]+)\\.kt$"), null, true); + } + + @TestMetadata("callableReference1.kt") + public void testCallableReference1() throws Exception { + runTest("idea/testData/resolve/references/qualifiedAccess/callableReference1.kt"); + } + + @TestMetadata("callableReference2.kt") + public void testCallableReference2() throws Exception { + runTest("idea/testData/resolve/references/qualifiedAccess/callableReference2.kt"); + } + + @TestMetadata("callableReference3.kt") + public void testCallableReference3() throws Exception { + runTest("idea/testData/resolve/references/qualifiedAccess/callableReference3.kt"); + } + + @TestMetadata("ResolveFirstPackageOfFullyQualifiedReference.kt") + public void testResolveFirstPackageOfFullyQualifiedReference() throws Exception { + runTest("idea/testData/resolve/references/qualifiedAccess/ResolveFirstPackageOfFullyQualifiedReference.kt"); + } + + @TestMetadata("ResolveFullyQualifiedCompanionObject.kt") + public void testResolveFullyQualifiedCompanionObject() throws Exception { + runTest("idea/testData/resolve/references/qualifiedAccess/ResolveFullyQualifiedCompanionObject.kt"); + } + + @TestMetadata("ResolveOuterClassOfFullyQualifiedReference.kt") + public void testResolveOuterClassOfFullyQualifiedReference() throws Exception { + runTest("idea/testData/resolve/references/qualifiedAccess/ResolveOuterClassOfFullyQualifiedReference.kt"); + } + + @TestMetadata("ResolvePackageOfFullyQualifiedReference.kt") + public void testResolvePackageOfFullyQualifiedReference() throws Exception { + runTest("idea/testData/resolve/references/qualifiedAccess/ResolvePackageOfFullyQualifiedReference.kt"); + } + } } diff --git a/plugins/kotlin/frontend-independent/tests/test/org/jetbrains/kotlin/test/utils/IgnoreTests.kt b/plugins/kotlin/frontend-independent/tests/test/org/jetbrains/kotlin/test/utils/IgnoreTests.kt index 27d339312bb8..0ea98b308ece 100644 --- a/plugins/kotlin/frontend-independent/tests/test/org/jetbrains/kotlin/test/utils/IgnoreTests.kt +++ b/plugins/kotlin/frontend-independent/tests/test/org/jetbrains/kotlin/test/utils/IgnoreTests.kt @@ -215,6 +215,7 @@ object IgnoreTests { const val FIR_IDENTICAL = "// FIR_IDENTICAL" const val IGNORE_FE10_BINDING_BY_FIR = "// IGNORE_FE10_BINDING_BY_FIR" + const val IGNORE_FE10 = "// IGNORE_FE10" } enum class DirectivePosition { diff --git a/plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/idea/resolve/AbstractReferenceResolveTest.kt b/plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/idea/resolve/AbstractReferenceResolveTest.kt index 31bb1e7e124b..2e3b96817037 100644 --- a/plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/idea/resolve/AbstractReferenceResolveTest.kt +++ b/plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/idea/resolve/AbstractReferenceResolveTest.kt @@ -15,6 +15,7 @@ import org.jetbrains.kotlin.idea.test.KotlinWithJdkAndRuntimeLightProjectDescrip import org.jetbrains.kotlin.idea.util.application.runReadAction import org.jetbrains.kotlin.idea.test.InTextDirectivesUtils import org.jetbrains.kotlin.test.util.renderAsGotoImplementation +import org.jetbrains.kotlin.test.utils.IgnoreTests import org.junit.Assert import kotlin.test.assertTrue @@ -29,7 +30,14 @@ abstract class AbstractReferenceResolveTest : KotlinLightCodeInsightFixtureTestC protected open fun doTest(path: String) { assert(path.endsWith(".kt")) { path } myFixture.configureWithExtraFile(path, ".Data") - performChecks() + val controlDirective = if (isFirPlugin()) { + IgnoreTests.DIRECTIVES.IGNORE_FIR + } else { + IgnoreTests.DIRECTIVES.IGNORE_FE10 + } + IgnoreTests.runTestIfNotDisabledByFileDirective(testDataFile().toPath(), controlDirective) { + performChecks() + } } protected fun performChecks() { diff --git a/plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/idea/resolve/ReferenceResolveTestGenerated.java b/plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/idea/resolve/ReferenceResolveTestGenerated.java index c4dcfb48ba29..3259e4a8c00b 100644 --- a/plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/idea/resolve/ReferenceResolveTestGenerated.java +++ b/plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/idea/resolve/ReferenceResolveTestGenerated.java @@ -898,4 +898,52 @@ public abstract class ReferenceResolveTestGenerated extends AbstractReferenceRes runTest("testData/resolve/references/packageReference/kotlinPackageSecondQualifier.kt"); } } + + @TestMetadata("idea/testData/resolve/references/qualifiedAccess") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class QualifiedAccess extends AbstractReferenceResolveTest { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); + } + + public void testAllFilesPresentInQualifiedAccess() throws Exception { + KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("idea/testData/resolve/references/qualifiedAccess"), Pattern.compile("^([^.]+)\\.kt$"), null, true); + } + + @TestMetadata("callableReference1.kt") + public void testCallableReference1() throws Exception { + runTest("idea/testData/resolve/references/qualifiedAccess/callableReference1.kt"); + } + + @TestMetadata("callableReference2.kt") + public void testCallableReference2() throws Exception { + runTest("idea/testData/resolve/references/qualifiedAccess/callableReference2.kt"); + } + + @TestMetadata("callableReference3.kt") + public void testCallableReference3() throws Exception { + runTest("idea/testData/resolve/references/qualifiedAccess/callableReference3.kt"); + } + + @TestMetadata("ResolveFirstPackageOfFullyQualifiedReference.kt") + public void testResolveFirstPackageOfFullyQualifiedReference() throws Exception { + runTest("idea/testData/resolve/references/qualifiedAccess/ResolveFirstPackageOfFullyQualifiedReference.kt"); + } + + @TestMetadata("ResolveFullyQualifiedCompanionObject.kt") + public void testResolveFullyQualifiedCompanionObject() throws Exception { + runTest("idea/testData/resolve/references/qualifiedAccess/ResolveFullyQualifiedCompanionObject.kt"); + } + + @TestMetadata("ResolveOuterClassOfFullyQualifiedReference.kt") + public void testResolveOuterClassOfFullyQualifiedReference() throws Exception { + runTest("idea/testData/resolve/references/qualifiedAccess/ResolveOuterClassOfFullyQualifiedReference.kt"); + } + + @TestMetadata("ResolvePackageOfFullyQualifiedReference.kt") + public void testResolvePackageOfFullyQualifiedReference() throws Exception { + runTest("idea/testData/resolve/references/qualifiedAccess/ResolvePackageOfFullyQualifiedReference.kt"); + } + } } diff --git a/plugins/kotlin/idea/tests/testData/findUsages/kotlin/companionObject/named.0.kt b/plugins/kotlin/idea/tests/testData/findUsages/kotlin/companionObject/named.0.kt index f33d970177cb..b6cff595d048 100644 --- a/plugins/kotlin/idea/tests/testData/findUsages/kotlin/companionObject/named.0.kt +++ b/plugins/kotlin/idea/tests/testData/findUsages/kotlin/companionObject/named.0.kt @@ -1,3 +1,4 @@ +// FIR_COMPARISON // PSI_ELEMENT: org.jetbrains.kotlin.psi.KtObjectDeclaration // OPTIONS: usages class Foo { diff --git a/plugins/kotlin/idea/tests/testData/findUsages/kotlin/companionObject/simple.0.kt b/plugins/kotlin/idea/tests/testData/findUsages/kotlin/companionObject/simple.0.kt index 782d1d15ddda..9c3f56e480a2 100644 --- a/plugins/kotlin/idea/tests/testData/findUsages/kotlin/companionObject/simple.0.kt +++ b/plugins/kotlin/idea/tests/testData/findUsages/kotlin/companionObject/simple.0.kt @@ -1,3 +1,4 @@ +// FIR_COMPARISON // PSI_ELEMENT: org.jetbrains.kotlin.psi.KtObjectDeclaration // OPTIONS: usages class Foo { diff --git a/plugins/kotlin/idea/tests/testData/findUsages/kotlin/findObjectUsages/kotlinLocalObjectUsages1.0.kt b/plugins/kotlin/idea/tests/testData/findUsages/kotlin/findObjectUsages/kotlinLocalObjectUsages1.0.kt index 3a868157a759..47179c5bc947 100644 --- a/plugins/kotlin/idea/tests/testData/findUsages/kotlin/findObjectUsages/kotlinLocalObjectUsages1.0.kt +++ b/plugins/kotlin/idea/tests/testData/findUsages/kotlin/findObjectUsages/kotlinLocalObjectUsages1.0.kt @@ -1,3 +1,4 @@ +// FIR_COMPARISON // PSI_ELEMENT: org.jetbrains.kotlin.psi.KtProperty // OPTIONS: usages fun foo(): Any { diff --git a/plugins/kotlin/idea/tests/testData/findUsages/kotlin/findObjectUsages/kotlinLocalObjectUsages1.results.txt b/plugins/kotlin/idea/tests/testData/findUsages/kotlin/findObjectUsages/kotlinLocalObjectUsages1.results.txt index 6cf46b74dc1c..4c1da4283d01 100644 --- a/plugins/kotlin/idea/tests/testData/findUsages/kotlin/findObjectUsages/kotlinLocalObjectUsages1.results.txt +++ b/plugins/kotlin/idea/tests/testData/findUsages/kotlin/findObjectUsages/kotlinLocalObjectUsages1.results.txt @@ -1 +1 @@ -Value read 6 return Bar +Value read 7 return Bar diff --git a/plugins/kotlin/idea/tests/testData/findUsages/kotlin/findObjectUsages/kotlinLocalObjectUsages2.0.kt b/plugins/kotlin/idea/tests/testData/findUsages/kotlin/findObjectUsages/kotlinLocalObjectUsages2.0.kt index 88e256892b3c..60c6fd0e1ddc 100644 --- a/plugins/kotlin/idea/tests/testData/findUsages/kotlin/findObjectUsages/kotlinLocalObjectUsages2.0.kt +++ b/plugins/kotlin/idea/tests/testData/findUsages/kotlin/findObjectUsages/kotlinLocalObjectUsages2.0.kt @@ -1,3 +1,4 @@ +// FIR_COMPARISON // PSI_ELEMENT: org.jetbrains.kotlin.psi.KtProperty // OPTIONS: usages fun foo(): Any { diff --git a/plugins/kotlin/idea/tests/testData/findUsages/kotlin/findObjectUsages/kotlinLocalObjectUsages2.results.txt b/plugins/kotlin/idea/tests/testData/findUsages/kotlin/findObjectUsages/kotlinLocalObjectUsages2.results.txt index 4c1da4283d01..a0bfcfe4645e 100644 --- a/plugins/kotlin/idea/tests/testData/findUsages/kotlin/findObjectUsages/kotlinLocalObjectUsages2.results.txt +++ b/plugins/kotlin/idea/tests/testData/findUsages/kotlin/findObjectUsages/kotlinLocalObjectUsages2.results.txt @@ -1 +1 @@ -Value read 7 return Bar +Value read 8 return Bar diff --git a/plugins/kotlin/idea/tests/testData/resolve/references/TopLevelClassVsLocalClassQualifier.kt b/plugins/kotlin/idea/tests/testData/resolve/references/TopLevelClassVsLocalClassQualifier.kt index 7c59f471bc46..bcfd753bfecd 100644 --- a/plugins/kotlin/idea/tests/testData/resolve/references/TopLevelClassVsLocalClassQualifier.kt +++ b/plugins/kotlin/idea/tests/testData/resolve/references/TopLevelClassVsLocalClassQualifier.kt @@ -1,5 +1,3 @@ -// IGNORE_FIR - package test class Conflict diff --git a/plugins/kotlin/idea/tests/testData/resolve/references/TopLevelObjectVsLocalClassQualifier.kt b/plugins/kotlin/idea/tests/testData/resolve/references/TopLevelObjectVsLocalClassQualifier.kt index 8567aa99d58a..33e2d97c45b9 100644 --- a/plugins/kotlin/idea/tests/testData/resolve/references/TopLevelObjectVsLocalClassQualifier.kt +++ b/plugins/kotlin/idea/tests/testData/resolve/references/TopLevelObjectVsLocalClassQualifier.kt @@ -1,3 +1,4 @@ +// IGNORE_FIR package test object Conflict diff --git a/plugins/kotlin/idea/tests/testData/resolve/references/qualifiedAccess/ResolveFirstPackageOfFullyQualifiedReference.kt b/plugins/kotlin/idea/tests/testData/resolve/references/qualifiedAccess/ResolveFirstPackageOfFullyQualifiedReference.kt new file mode 100644 index 000000000000..269a1dc9fe4e --- /dev/null +++ b/plugins/kotlin/idea/tests/testData/resolve/references/qualifiedAccess/ResolveFirstPackageOfFullyQualifiedReference.kt @@ -0,0 +1,13 @@ +package foo.bar.baz + +class AA { + class BB { + companion object + } +} + +fun test() { + val b = foo.bar.baz.AA.BB +} + +// REF: foo diff --git a/plugins/kotlin/idea/tests/testData/resolve/references/qualifiedAccess/ResolveFullyQualifiedCompanionObject.kt b/plugins/kotlin/idea/tests/testData/resolve/references/qualifiedAccess/ResolveFullyQualifiedCompanionObject.kt new file mode 100644 index 000000000000..de4640d74d08 --- /dev/null +++ b/plugins/kotlin/idea/tests/testData/resolve/references/qualifiedAccess/ResolveFullyQualifiedCompanionObject.kt @@ -0,0 +1,14 @@ +// IGNORE_FIR +package foo.bar.baz + +class AA { + class BB { + companion object + } +} + +fun test() { + val b = foo.bar.baz.AA.BB +} + +// REF: companion object of (in foo.bar.baz.AA).BB diff --git a/plugins/kotlin/idea/tests/testData/resolve/references/qualifiedAccess/ResolveOuterClassOfFullyQualifiedReference.kt b/plugins/kotlin/idea/tests/testData/resolve/references/qualifiedAccess/ResolveOuterClassOfFullyQualifiedReference.kt new file mode 100644 index 000000000000..177c8936686a --- /dev/null +++ b/plugins/kotlin/idea/tests/testData/resolve/references/qualifiedAccess/ResolveOuterClassOfFullyQualifiedReference.kt @@ -0,0 +1,13 @@ +package foo.bar.baz + +class AA { + class BB { + companion object + } +} + +fun test() { + val b = foo.bar.baz.AA.BB +} + +// REF: (foo.bar.baz).AA diff --git a/plugins/kotlin/idea/tests/testData/resolve/references/qualifiedAccess/ResolvePackageOfFullyQualifiedReference.kt b/plugins/kotlin/idea/tests/testData/resolve/references/qualifiedAccess/ResolvePackageOfFullyQualifiedReference.kt new file mode 100644 index 000000000000..bad812bcfa56 --- /dev/null +++ b/plugins/kotlin/idea/tests/testData/resolve/references/qualifiedAccess/ResolvePackageOfFullyQualifiedReference.kt @@ -0,0 +1,13 @@ +package foo.bar.baz + +class AA { + class BB { + companion object + } +} + +fun test() { + val b = foo.bar.baz.AA.BB +} + +// REF: baz diff --git a/plugins/kotlin/idea/tests/testData/resolve/references/qualifiedAccess/callableReference1.kt b/plugins/kotlin/idea/tests/testData/resolve/references/qualifiedAccess/callableReference1.kt new file mode 100644 index 000000000000..5179d7b36f84 --- /dev/null +++ b/plugins/kotlin/idea/tests/testData/resolve/references/qualifiedAccess/callableReference1.kt @@ -0,0 +1,11 @@ +package foo.bar.baz + +class AA { + fun foo() {} +} + +fun test() { + AA::foo +} + +// REF: (foo.bar.baz).AA diff --git a/plugins/kotlin/idea/tests/testData/resolve/references/qualifiedAccess/callableReference2.kt b/plugins/kotlin/idea/tests/testData/resolve/references/qualifiedAccess/callableReference2.kt new file mode 100644 index 000000000000..61ec16f06402 --- /dev/null +++ b/plugins/kotlin/idea/tests/testData/resolve/references/qualifiedAccess/callableReference2.kt @@ -0,0 +1,14 @@ +// IGNORE_FE10 +package foo.bar.baz + +class AA { + companion object { + fun foo() {} + } +} + +fun test() { + AA::foo // FE1.0 won't resolve this +} + +// REF: companion object of (foo.bar.baz).AA diff --git a/plugins/kotlin/idea/tests/testData/resolve/references/qualifiedAccess/callableReference3.kt b/plugins/kotlin/idea/tests/testData/resolve/references/qualifiedAccess/callableReference3.kt new file mode 100644 index 000000000000..500244af6132 --- /dev/null +++ b/plugins/kotlin/idea/tests/testData/resolve/references/qualifiedAccess/callableReference3.kt @@ -0,0 +1,14 @@ +// IGNORE_FE10 +package foo.bar.baz + +class AA { + companion object +} + +fun AA.Companion.foo() {} + +fun test() { + AA::foo // FE1.0 won't resolve this +} + +// REF: companion object of (foo.bar.baz).AA