diff --git a/idea/idea-fir/src/org/jetbrains/kotlin/idea/completion/contributors/FirCompletionContributorBase.kt b/idea/idea-fir/src/org/jetbrains/kotlin/idea/completion/contributors/FirCompletionContributorBase.kt index 37b168a9651..36b3505d164 100644 --- a/idea/idea-fir/src/org/jetbrains/kotlin/idea/completion/contributors/FirCompletionContributorBase.kt +++ b/idea/idea-fir/src/org/jetbrains/kotlin/idea/completion/contributors/FirCompletionContributorBase.kt @@ -16,9 +16,11 @@ import org.jetbrains.kotlin.idea.completion.context.FirRawPositionCompletionCont import org.jetbrains.kotlin.idea.completion.weighers.Weighers import org.jetbrains.kotlin.idea.fir.low.level.api.IndexHelper import org.jetbrains.kotlin.idea.frontend.api.KtAnalysisSession +import org.jetbrains.kotlin.idea.frontend.api.scopes.KtScopeNameFilter import org.jetbrains.kotlin.idea.frontend.api.symbols.* import org.jetbrains.kotlin.idea.frontend.api.symbols.markers.KtNamedSymbol import org.jetbrains.kotlin.idea.frontend.api.types.KtType +import org.jetbrains.kotlin.idea.stubindex.KotlinSourceFilterScope import org.jetbrains.kotlin.platform.TargetPlatform import org.jetbrains.kotlin.psi.KtFile @@ -32,6 +34,10 @@ internal abstract class FirCompletionContributorBase !name.isSpecial && prefixMatcher.prefixMatches(name.identifier) } abstract fun KtAnalysisSession.complete(positionContext: C) diff --git a/idea/idea-fir/src/org/jetbrains/kotlin/idea/completion/contributors/FirContextCompletionContributorBase.kt b/idea/idea-fir/src/org/jetbrains/kotlin/idea/completion/contributors/FirContextCompletionContributorBase.kt index acb471820fe..f64867dea2f 100644 --- a/idea/idea-fir/src/org/jetbrains/kotlin/idea/completion/contributors/FirContextCompletionContributorBase.kt +++ b/idea/idea-fir/src/org/jetbrains/kotlin/idea/completion/contributors/FirContextCompletionContributorBase.kt @@ -14,8 +14,4 @@ import org.jetbrains.kotlin.idea.frontend.api.scopes.KtScopeNameFilter internal abstract class FirContextCompletionContributorBase( basicContext: FirBasicCompletionContext -) : FirCompletionContributorBase(basicContext) { - - protected val scopeNameFilter: KtScopeNameFilter = - { name -> !name.isSpecial && prefixMatcher.prefixMatches(name.identifier) } -} \ No newline at end of file +) : FirCompletionContributorBase(basicContext) \ No newline at end of file diff --git a/idea/idea-fir/src/org/jetbrains/kotlin/idea/completion/contributors/FirPackageCompletionContributor.kt b/idea/idea-fir/src/org/jetbrains/kotlin/idea/completion/contributors/FirPackageCompletionContributor.kt new file mode 100644 index 00000000000..34396a86631 --- /dev/null +++ b/idea/idea-fir/src/org/jetbrains/kotlin/idea/completion/contributors/FirPackageCompletionContributor.kt @@ -0,0 +1,42 @@ +/* + * Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.idea.completion.contributors + +import com.intellij.psi.JavaPsiFacade +import org.jetbrains.kotlin.idea.completion.context.FirBasicCompletionContext +import org.jetbrains.kotlin.idea.completion.context.FirNameReferenceRawPositionContext +import org.jetbrains.kotlin.idea.completion.context.FirRawPositionCompletionContext +import org.jetbrains.kotlin.idea.frontend.api.KtAnalysisSession +import org.jetbrains.kotlin.idea.frontend.api.symbols.KtPackageSymbol +import org.jetbrains.kotlin.idea.references.mainReference +import org.jetbrains.kotlin.idea.stubindex.PackageIndexUtil +import org.jetbrains.kotlin.name.FqName +import org.jetbrains.kotlin.platform.jvm.isJvm +import org.jetbrains.kotlin.psi.KtDotQualifiedExpression +import org.jetbrains.kotlin.psi.KtExpression + +internal class FirPackageCompletionContributor( + basicContext: FirBasicCompletionContext, +) : FirCompletionContributorBase(basicContext) { + + override fun KtAnalysisSession.complete(positionContext: FirRawPositionCompletionContext) { + val rootSymbol = if (positionContext !is FirNameReferenceRawPositionContext || positionContext.explicitReceiver == null) { + ROOT_PACKAGE_SYMBOL + } else { + positionContext.explicitReceiver?.reference()?.resolveToSymbol() as? KtPackageSymbol + } ?: return + rootSymbol.getPackageScope() + .getPackageSymbols(scopeNameFilter) + .forEach { packageSymbol -> + result.addElement(lookupElementFactory.createPackageLookupElement(packageSymbol.fqName)) + } + } + + private fun KtExpression.reference() = when (this) { + is KtDotQualifiedExpression -> selectorExpression?.mainReference + else -> mainReference + } +} \ No newline at end of file diff --git a/idea/idea-fir/tests/org/jetbrains/kotlin/idea/fir/resolve/FirReferenceResolveTestGenerated.java b/idea/idea-fir/tests/org/jetbrains/kotlin/idea/fir/resolve/FirReferenceResolveTestGenerated.java index fbe82c50473..b44b08721ce 100644 --- a/idea/idea-fir/tests/org/jetbrains/kotlin/idea/fir/resolve/FirReferenceResolveTestGenerated.java +++ b/idea/idea-fir/tests/org/jetbrains/kotlin/idea/fir/resolve/FirReferenceResolveTestGenerated.java @@ -866,4 +866,37 @@ public class FirReferenceResolveTestGenerated extends AbstractFirReferenceResolv runTest("idea/testData/resolve/references/nestedTypes/ResolveTypeInTheStartOfType.kt"); } } + + @TestMetadata("idea/testData/resolve/references/packageReference") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class PackageReference extends AbstractFirReferenceResolveTest { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); + } + + public void testAllFilesPresentInPackageReference() throws Exception { + KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("idea/testData/resolve/references/packageReference"), Pattern.compile("^([^.]+)\\.kt$"), null, true); + } + + @TestMetadata("javaPackageFirstQualifier.kt") + public void testJavaPackageFirstQualifier() throws Exception { + runTest("idea/testData/resolve/references/packageReference/javaPackageFirstQualifier.kt"); + } + + @TestMetadata("javaPackageSecondQualifier.kt") + public void testJavaPackageSecondQualifier() throws Exception { + runTest("idea/testData/resolve/references/packageReference/javaPackageSecondQualifier.kt"); + } + + @TestMetadata("kotlinPackageFirstQualifier.kt") + public void testKotlinPackageFirstQualifier() throws Exception { + runTest("idea/testData/resolve/references/packageReference/kotlinPackageFirstQualifier.kt"); + } + + @TestMetadata("kotlinPackageSecondQualifier.kt") + public void testKotlinPackageSecondQualifier() throws Exception { + runTest("idea/testData/resolve/references/packageReference/kotlinPackageSecondQualifier.kt"); + } + } } diff --git a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/symbols/KtFirPackageSymbol.kt b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/symbols/KtFirPackageSymbol.kt index 1ba04e83d84..964a6c4e484 100644 --- a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/symbols/KtFirPackageSymbol.kt +++ b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/symbols/KtFirPackageSymbol.kt @@ -26,7 +26,8 @@ class KtFirPackageSymbol( override val token: ValidityToken ) : KtPackageSymbol(), ValidityTokenOwner { override val psi: PsiElement? by cached { - KtPackage(PsiManager.getInstance(project), fqName, GlobalSearchScope.allScope(project)/*TODO*/) + JavaPsiFacade.getInstance(project).findPackage(fqName.asString()) + ?: KtPackage(PsiManager.getInstance(project), fqName, GlobalSearchScope.allScope(project)/*TODO*/) } override val origin: KtSymbolOrigin diff --git a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/references/FirReferenceResolveHelper.kt b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/references/FirReferenceResolveHelper.kt index ab45bd83feb..e2cf1b39a4e 100644 --- a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/references/FirReferenceResolveHelper.kt +++ b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/references/FirReferenceResolveHelper.kt @@ -366,7 +366,7 @@ internal object FirReferenceResolveHelper { analysisSession: KtFirAnalysisSession ): Collection { // TODO refactor that block - val classId = fir.classId ?: return emptyList() + val classId = fir.classId ?: return listOfNotNull(getPackageSymbolFor(expression, symbolBuilder, forQualifiedType = false)) var parent = expression.parent as? KtDotQualifiedExpression // Distinguish A.foo() from A(.Companion).foo() diff --git a/idea/testData/resolve/references/packageReference/javaPackageFirstQualifier.kt b/idea/testData/resolve/references/packageReference/javaPackageFirstQualifier.kt new file mode 100644 index 00000000000..5a005984251 --- /dev/null +++ b/idea/testData/resolve/references/packageReference/javaPackageFirstQualifier.kt @@ -0,0 +1,4 @@ +fun x() { + val z = java.util.ArrayList() +} +// REF: java diff --git a/idea/testData/resolve/references/packageReference/javaPackageSecondQualifier.kt b/idea/testData/resolve/references/packageReference/javaPackageSecondQualifier.kt new file mode 100644 index 00000000000..dd378155879 --- /dev/null +++ b/idea/testData/resolve/references/packageReference/javaPackageSecondQualifier.kt @@ -0,0 +1,4 @@ +fun x() { + val z = java.util.ArrayList() +} +// REF: util diff --git a/idea/testData/resolve/references/packageReference/kotlinPackageFirstQualifier.kt b/idea/testData/resolve/references/packageReference/kotlinPackageFirstQualifier.kt new file mode 100644 index 00000000000..bcedc90a2ce --- /dev/null +++ b/idea/testData/resolve/references/packageReference/kotlinPackageFirstQualifier.kt @@ -0,0 +1,4 @@ +fun x() { + val z = kotlin.text.toString() +} +// REF: kotlin diff --git a/idea/testData/resolve/references/packageReference/kotlinPackageSecondQualifier.kt b/idea/testData/resolve/references/packageReference/kotlinPackageSecondQualifier.kt new file mode 100644 index 00000000000..08ff2af2d35 --- /dev/null +++ b/idea/testData/resolve/references/packageReference/kotlinPackageSecondQualifier.kt @@ -0,0 +1,4 @@ +fun x() { + val z = kotlin.text.toString() +} +// REF: text diff --git a/idea/tests/org/jetbrains/kotlin/idea/resolve/ReferenceResolveTestGenerated.java b/idea/tests/org/jetbrains/kotlin/idea/resolve/ReferenceResolveTestGenerated.java index de0b2bf499d..cf923f1de51 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/resolve/ReferenceResolveTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/idea/resolve/ReferenceResolveTestGenerated.java @@ -866,4 +866,37 @@ public class ReferenceResolveTestGenerated extends AbstractReferenceResolveTest runTest("idea/testData/resolve/references/nestedTypes/ResolveTypeInTheStartOfType.kt"); } } + + @TestMetadata("idea/testData/resolve/references/packageReference") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class PackageReference extends AbstractReferenceResolveTest { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); + } + + public void testAllFilesPresentInPackageReference() throws Exception { + KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("idea/testData/resolve/references/packageReference"), Pattern.compile("^([^.]+)\\.kt$"), null, true); + } + + @TestMetadata("javaPackageFirstQualifier.kt") + public void testJavaPackageFirstQualifier() throws Exception { + runTest("idea/testData/resolve/references/packageReference/javaPackageFirstQualifier.kt"); + } + + @TestMetadata("javaPackageSecondQualifier.kt") + public void testJavaPackageSecondQualifier() throws Exception { + runTest("idea/testData/resolve/references/packageReference/javaPackageSecondQualifier.kt"); + } + + @TestMetadata("kotlinPackageFirstQualifier.kt") + public void testKotlinPackageFirstQualifier() throws Exception { + runTest("idea/testData/resolve/references/packageReference/kotlinPackageFirstQualifier.kt"); + } + + @TestMetadata("kotlinPackageSecondQualifier.kt") + public void testKotlinPackageSecondQualifier() throws Exception { + runTest("idea/testData/resolve/references/packageReference/kotlinPackageSecondQualifier.kt"); + } + } }