From d2fbd8e33877f74a58510cf5dabcf130b1c99124 Mon Sep 17 00:00:00 2001 From: Roman Golyshev Date: Fri, 10 Jul 2020 13:06:14 +0300 Subject: [PATCH] Remove `KotlinFirCompletionProvider` - We should strive to use only high-level API for completion from now on --- .../KotlinFirCompletionContributor.kt | 127 +----------------- 1 file changed, 4 insertions(+), 123 deletions(-) diff --git a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/completion/KotlinFirCompletionContributor.kt b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/completion/KotlinFirCompletionContributor.kt index 6651556adc4..52a58bf8e53 100644 --- a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/completion/KotlinFirCompletionContributor.kt +++ b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/completion/KotlinFirCompletionContributor.kt @@ -11,21 +11,6 @@ import com.intellij.openapi.project.Project import com.intellij.patterns.PlatformPatterns import com.intellij.psi.search.GlobalSearchScope import com.intellij.util.ProcessingContext -import org.jetbrains.kotlin.fir.declarations.FirFile -import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccessExpression -import org.jetbrains.kotlin.fir.resolve.ScopeSession -import org.jetbrains.kotlin.fir.resolve.scope -import org.jetbrains.kotlin.fir.scopes.FirScope -import org.jetbrains.kotlin.fir.scopes.impl.FirAbstractSimpleImportingScope -import org.jetbrains.kotlin.fir.scopes.impl.FirAbstractStarImportingScope -import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol -import org.jetbrains.kotlin.fir.symbols.impl.FirConstructorSymbol -import org.jetbrains.kotlin.fir.typeContext -import org.jetbrains.kotlin.fir.types.ConeKotlinType -import org.jetbrains.kotlin.fir.types.coneTypeUnsafe -import org.jetbrains.kotlin.idea.fir.getFirOfClosestParent -import org.jetbrains.kotlin.idea.fir.getOrBuildFirSafe -import org.jetbrains.kotlin.idea.fir.low.level.api.LowLevelFirApiFacade import org.jetbrains.kotlin.idea.frontend.api.getAnalysisSessionFor import org.jetbrains.kotlin.idea.frontend.api.symbols.KtCallableSymbol import org.jetbrains.kotlin.idea.frontend.api.symbols.KtNamedSymbol @@ -37,87 +22,19 @@ import org.jetbrains.kotlin.idea.stubindex.KotlinTopLevelFunctionByPackageIndex import org.jetbrains.kotlin.idea.stubindex.KotlinTopLevelPropertyByPackageIndex import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.Name -import org.jetbrains.kotlin.psi.* -import org.jetbrains.kotlin.psi.psiUtil.getNonStrictParentOfType +import org.jetbrains.kotlin.psi.KtCallableDeclaration +import org.jetbrains.kotlin.psi.KtFile +import org.jetbrains.kotlin.psi.KtLabelReferenceExpression +import org.jetbrains.kotlin.psi.KtSimpleNameExpression import org.jetbrains.kotlin.psi.psiUtil.getQualifiedExpressionForSelector -import org.jetbrains.kotlin.types.AbstractTypeChecker -import org.jetbrains.kotlin.types.model.TypeCheckerProviderContext class KotlinFirCompletionContributor : CompletionContributor() { init { -// extend(CompletionType.BASIC, PlatformPatterns.psiElement(), KotlinFirCompletionProvider) extend(CompletionType.BASIC, PlatformPatterns.psiElement(), KotlinHighLevelApiContributor) } } -private object KotlinFirCompletionProvider : CompletionProvider() { - override fun addCompletions(parameters: CompletionParameters, context: ProcessingContext, result: CompletionResultSet) { - val originalFile = parameters.originalFile as? KtFile ?: return - - val originalFileFir = originalFile.getOrBuildFirSafe(LowLevelFirApiFacade.getResolveStateFor(originalFile)) ?: return - - val reference = (parameters.position.parent as? KtSimpleNameExpression)?.mainReference ?: return - val nameExpression = reference.expression.takeIf { it !is KtLabelReferenceExpression } ?: return - - val parentFunction = nameExpression.getNonStrictParentOfType() ?: return - - val completionContext = LowLevelFirApiFacade.buildCompletionContextForFunction( - originalFileFir, - parentFunction, - LowLevelFirApiFacade.getResolveStateFor(originalFile) - ) - - val element = nameExpression.getFirOfClosestParent() as? FirQualifiedAccessExpression ?: return - val towerDataContext = completionContext.getTowerDataContext(nameExpression) - - val symbols: Sequence> = sequence { - val packageIndexHelper = PackageIndexHelper(parameters.position.project) - - val explicitReceiver = element.explicitReceiver - val explicitReceiverType = explicitReceiver?.typeRef?.coneTypeUnsafe() - val explicitReceiverScope = explicitReceiverType?.scope(completionContext.session, ScopeSession()) - - val implicitReceivers = towerDataContext.nonLocalTowerDataElements.mapNotNull { it.implicitReceiver } - val implicitReceiversTypes = implicitReceivers.map { it.type } - - val localScopes = towerDataContext.localScopes - val nonLocalScopes = towerDataContext.nonLocalTowerDataElements.mapNotNull { it.scope } - val implicitReceiversScopes = implicitReceivers.mapNotNull { it.implicitScope } - - val allNonExplicitScopes = localScopes.asSequence() + nonLocalScopes + implicitReceiversScopes - - val typeContext = completionContext.session.typeContext - - if (explicitReceiverScope != null) { - val nonExtensionMembers = explicitReceiverScope.collectCallableSymbols(packageIndexHelper).filter { !it.isExtension } - yieldAll(nonExtensionMembers) - - val allApplicableExtensions = allNonExplicitScopes - .flatMap { it.collectCallableSymbols(packageIndexHelper) } - .filter { it.isExtension && it.isExtensionThatCanBeCalledOnTypes(listOf(explicitReceiverType), typeContext) } - - yieldAll(allApplicableExtensions) - } else { - val allAvailableSymbols = allNonExplicitScopes - .flatMap { it.collectCallableSymbols(packageIndexHelper) } - .filter { !it.isExtension || it.isExtensionThatCanBeCalledOnTypes(implicitReceiversTypes, typeContext) } - - yieldAll(allAvailableSymbols) - } - } - - for (symbol in symbols) { - if (symbol is FirConstructorSymbol) continue - val symbolName = symbol.callableId.callableName - - result.addElement(LookupElementBuilder.create(symbolName.toString())) - } - } - -} - private object KotlinHighLevelApiContributor : CompletionProvider() { - override fun addCompletions(parameters: CompletionParameters, context: ProcessingContext, result: CompletionResultSet) { val originalFile = parameters.originalFile as? KtFile ?: return @@ -172,34 +89,6 @@ private fun KtCallableSymbol.canBeCalledWith(implicitReceivers: List): B return implicitReceivers.any { it.isSubTypeOf(requiredReceiverType) } } -private val FirCallableSymbol<*>.isExtension get() = fir.receiverTypeRef != null - - -private fun FirScope.getScopeNames(indexHelper: PackageIndexHelper): Set = when (this) { - is FirAbstractStarImportingScope -> { - this.starImports.flatMapTo(mutableSetOf()) { indexHelper.getPackageTopLevelNames(it.packageFqName) } - } - - is FirAbstractSimpleImportingScope -> simpleImports.keys - - else -> getCallableNames() -} - -private fun FirScope.collectCallableSymbols(packageIndexHelper: PackageIndexHelper): MutableList> { - val allCallableSymbols = mutableListOf>() - fun symbolsCollector(symbol: FirCallableSymbol<*>) { - allCallableSymbols.add(symbol) - } - - val scopeNames = getScopeNames(packageIndexHelper) - for (name in scopeNames) { - processFunctionsByName(name, ::symbolsCollector) - processPropertiesByName(name, ::symbolsCollector) - } - - return allCallableSymbols -} - class PackageIndexHelper(private val project: Project) { //todo use more concrete scope private val searchScope = GlobalSearchScope.allScope(project) @@ -217,11 +106,3 @@ class PackageIndexHelper(private val project: Project) { addAll(propertyByPackageIndex.get(packageFqName.asString(), project, searchScope)) } } - -private fun FirCallableSymbol<*>.isExtensionThatCanBeCalledOnTypes( - receivers: List, - session: TypeCheckerProviderContext -): Boolean { - val expectedReceiverType = fir.receiverTypeRef?.coneTypeUnsafe() ?: return false - return receivers.any { AbstractTypeChecker.isSubtypeOf(session, it, expectedReceiverType) } -}