From 11e77d464d4734b0f785f8fcd8ebceff2ea70c48 Mon Sep 17 00:00:00 2001 From: Ilya Kirillov Date: Mon, 17 May 2021 20:36:43 +0200 Subject: [PATCH] FIR IDE: add completion with package receiver --- .../FirCallableCompletionContributor.kt | 30 +++++++++++++++++++ .../FirClassifierCompletionContributor.kt | 10 +++++-- .../FirCompletionContributorBase.kt | 8 +++++ .../FirPackageCompletionContributor.kt | 5 ---- .../api/fir/scopes/KtFirPackageScope.kt | 14 +++++---- 5 files changed, 53 insertions(+), 14 deletions(-) diff --git a/idea/idea-fir/src/org/jetbrains/kotlin/idea/completion/contributors/FirCallableCompletionContributor.kt b/idea/idea-fir/src/org/jetbrains/kotlin/idea/completion/contributors/FirCallableCompletionContributor.kt index d364759d7fb..38d4d95149e 100644 --- a/idea/idea-fir/src/org/jetbrains/kotlin/idea/completion/contributors/FirCallableCompletionContributor.kt +++ b/idea/idea-fir/src/org/jetbrains/kotlin/idea/completion/contributors/FirCallableCompletionContributor.kt @@ -16,6 +16,7 @@ import org.jetbrains.kotlin.idea.frontend.api.scopes.KtCompositeScope import org.jetbrains.kotlin.idea.frontend.api.scopes.KtScope import org.jetbrains.kotlin.idea.frontend.api.symbols.KtCallableSymbol import org.jetbrains.kotlin.idea.frontend.api.symbols.KtClassOrObjectSymbol +import org.jetbrains.kotlin.idea.frontend.api.symbols.KtPackageSymbol import org.jetbrains.kotlin.idea.frontend.api.types.KtClassType import org.jetbrains.kotlin.idea.frontend.api.types.KtType import org.jetbrains.kotlin.psi.KtExpression @@ -88,6 +89,35 @@ internal class FirCallableCompletionContributor( expectedType: KtType?, extensionChecker: ExtensionApplicabilityChecker, visibilityChecker: CompletionVisibilityChecker, + ) { + val packageSymbol = explicitReceiver.reference()?.resolveToSymbol() as? KtPackageSymbol + if (packageSymbol == null) { + collectDotCompletionForCallableReceiver(implicitScopes, explicitReceiver, expectedType, extensionChecker, visibilityChecker) + } else { + collectDotCompletionForPackageReceiver(packageSymbol, expectedType, visibilityChecker) + } + } + + private fun KtAnalysisSession.collectDotCompletionForPackageReceiver( + packageSymbol: KtPackageSymbol, + expectedType: KtType?, + visibilityChecker: CompletionVisibilityChecker + ) { + packageSymbol.getPackageScope() + .getCallableSymbols(scopeNameFilter) + .filterNot { it.isExtension } + .filter { with(visibilityChecker) { isVisible(it) } } + .forEach { callable -> + addSymbolToCompletion(expectedType, callable) + } + } + + private fun KtAnalysisSession.collectDotCompletionForCallableReceiver( + implicitScopes: KtCompositeScope, + explicitReceiver: KtExpression, + expectedType: KtType?, + extensionChecker: ExtensionApplicabilityChecker, + visibilityChecker: CompletionVisibilityChecker, ) { val typeOfPossibleReceiver = explicitReceiver.getKtType() val possibleReceiverScope = typeOfPossibleReceiver.getTypeScope() ?: return diff --git a/idea/idea-fir/src/org/jetbrains/kotlin/idea/completion/contributors/FirClassifierCompletionContributor.kt b/idea/idea-fir/src/org/jetbrains/kotlin/idea/completion/contributors/FirClassifierCompletionContributor.kt index 0261f25e56f..6b0977fa365 100644 --- a/idea/idea-fir/src/org/jetbrains/kotlin/idea/completion/contributors/FirClassifierCompletionContributor.kt +++ b/idea/idea-fir/src/org/jetbrains/kotlin/idea/completion/contributors/FirClassifierCompletionContributor.kt @@ -41,9 +41,13 @@ internal open class FirClassifierCompletionContributor( receiver: KtExpression, visibilityChecker: CompletionVisibilityChecker ) { - val reference = receiver.mainReference ?: return - val symbol = reference.resolveToSymbol() as? KtSymbolWithMembers ?: return - symbol.getMemberScope() + val reference = receiver.reference() ?: return + val scope = when (val symbol = reference.resolveToSymbol()) { + is KtSymbolWithMembers -> symbol.getMemberScope() + is KtPackageSymbol -> symbol.getPackageScope() + else -> return + } + scope .getClassifierSymbols(scopeNameFilter) .filter { filterClassifiers(it) } .filter { with(visibilityChecker) { isVisible(it) } } 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 36b3505d164..bb9376c8e8a 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 @@ -20,8 +20,11 @@ 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.references.mainReference import org.jetbrains.kotlin.idea.stubindex.KotlinSourceFilterScope import org.jetbrains.kotlin.platform.TargetPlatform +import org.jetbrains.kotlin.psi.KtDotQualifiedExpression +import org.jetbrains.kotlin.psi.KtExpression import org.jetbrains.kotlin.psi.KtFile internal abstract class FirCompletionContributorBase(protected val basicContext: FirBasicCompletionContext) { @@ -61,6 +64,11 @@ internal abstract class FirCompletionContributorBase selectorExpression?.mainReference + else -> mainReference + } + private fun KtAnalysisSession.applyWeighers( lookupElement: LookupElement, symbol: KtSymbol, 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 index 34396a86631..2576778b2bd 100644 --- 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 @@ -34,9 +34,4 @@ internal class FirPackageCompletionContributor( 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-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/scopes/KtFirPackageScope.kt b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/scopes/KtFirPackageScope.kt index 1abce5296f2..7cd4792f595 100644 --- a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/scopes/KtFirPackageScope.kt +++ b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/frontend/api/fir/scopes/KtFirPackageScope.kt @@ -48,19 +48,21 @@ internal class KtFirPackageScope( override fun getPossibleCallableNames() = withValidityAssertion { hashSetOf().apply { - KotlinTopLevelPropertyByPackageIndex.getInstance()[fqName.asString(), project, firScope.session.searchScope] + KotlinTopLevelPropertyByPackageIndex.getInstance()[fqName.asString(), project, searchScope] .mapNotNullTo(this) { it.nameAsName } - KotlinTopLevelFunctionByPackageIndex.getInstance()[fqName.asString(), project, firScope.session.searchScope] + KotlinTopLevelFunctionByPackageIndex.getInstance()[fqName.asString(), project, searchScope] .mapNotNullTo(this) { it.nameAsName } } } override fun getPossibleClassifierNames(): Set = withValidityAssertion { - KotlinTopLevelClassByPackageIndex.getInstance()[fqName.asString(), project, firScope.session.searchScope] - .mapNotNullTo(hashSetOf()) { it.nameAsName } + hashSetOf().apply { + KotlinTopLevelClassByPackageIndex.getInstance()[fqName.asString(), project, searchScope] + .mapNotNullTo(this) { it.nameAsName } - KotlinTopLevelTypeAliasByPackageIndex.getInstance()[fqName.asString(), project, firScope.session.searchScope] - .mapNotNullTo(hashSetOf()) { it.nameAsName } + KotlinTopLevelTypeAliasByPackageIndex.getInstance()[fqName.asString(), project, searchScope] + .mapNotNullTo(this) { it.nameAsName } + } } override fun getCallableSymbols(nameFilter: KtScopeNameFilter): Sequence = withValidityAssertion {