FIR IDE: introduce base class for completion provider

This commit is contained in:
Ilya Kirillov
2021-05-06 15:40:26 +02:00
committed by TeamCityServer
parent 81c6f38f79
commit ca1fd185dc
3 changed files with 40 additions and 18 deletions
@@ -15,6 +15,7 @@ import org.jetbrains.kotlin.idea.completion.context.FirBasicCompletionContext
import org.jetbrains.kotlin.idea.completion.context.FirNameReferencePositionContext import org.jetbrains.kotlin.idea.completion.context.FirNameReferencePositionContext
import org.jetbrains.kotlin.idea.completion.context.FirPositionCompletionContextDetector import org.jetbrains.kotlin.idea.completion.context.FirPositionCompletionContextDetector
import org.jetbrains.kotlin.idea.completion.context.FirUnknownPositionContext import org.jetbrains.kotlin.idea.completion.context.FirUnknownPositionContext
import org.jetbrains.kotlin.idea.completion.contributors.FirCompletionContributorBase
import org.jetbrains.kotlin.idea.completion.weighers.Weighers import org.jetbrains.kotlin.idea.completion.weighers.Weighers
import org.jetbrains.kotlin.idea.fir.low.level.api.IndexHelper import org.jetbrains.kotlin.idea.fir.low.level.api.IndexHelper
import org.jetbrains.kotlin.idea.fir.low.level.api.util.originalKtFile import org.jetbrains.kotlin.idea.fir.low.level.api.util.originalKtFile
@@ -48,7 +49,7 @@ private object KotlinFirCompletionProvider : CompletionProvider<CompletionParame
parameters.position.getModuleInfo().contentScope() parameters.position.getModuleInfo().contentScope()
) )
val basicContext = FirBasicCompletionContext.createFromParameters(parameters, result) ?: return val basicContext = FirBasicCompletionContext.createFromParameters(parameters, resultSet) ?: return
recordOriginalFile(basicContext) recordOriginalFile(basicContext)
val positionContext = FirPositionCompletionContextDetector.detect(basicContext) val positionContext = FirPositionCompletionContextDetector.detect(basicContext)
@@ -65,9 +66,9 @@ private object KotlinFirCompletionProvider : CompletionProvider<CompletionParame
FirPositionCompletionContextDetector.analyseInContext(basicContext, positionContext) { FirPositionCompletionContextDetector.analyseInContext(basicContext, positionContext) {
when (positionContext) { when (positionContext) {
is FirNameReferencePositionContext -> with( is FirNameReferencePositionContext -> with(
KotlinWithNameReferenceCompletionProvider(resultSet.prefixMatcher, indexHelper) KotlinWithNameReferenceCompletionProvider(basicContext, indexHelper)
) { ) {
addCompletions(basicContext, positionContext) addCompletions(positionContext)
} }
is FirUnknownPositionContext -> { is FirUnknownPositionContext -> {
// TODO // TODO
@@ -135,9 +136,9 @@ internal fun interface CompletionVisibilityChecker {
* TODO refactor it, try to split into several classes, or decompose it into several classes. * TODO refactor it, try to split into several classes, or decompose it into several classes.
*/ */
private class KotlinWithNameReferenceCompletionProvider( private class KotlinWithNameReferenceCompletionProvider(
private val prefixMatcher: PrefixMatcher, basicContext: FirBasicCompletionContext,
private val indexHelper: IndexHelper private val indexHelper: IndexHelper
) { ): FirCompletionContributorBase(basicContext) {
private val lookupElementFactory = KotlinFirLookupElementFactory() private val lookupElementFactory = KotlinFirLookupElementFactory()
private val typeNamesProvider = TypeNamesProvider(indexHelper) private val typeNamesProvider = TypeNamesProvider(indexHelper)
@@ -165,20 +166,19 @@ private class KotlinWithNameReferenceCompletionProvider(
} }
fun KtAnalysisSession.addCompletions( fun KtAnalysisSession.addCompletions(
basicContext: FirBasicCompletionContext,
positionContext: FirNameReferencePositionContext positionContext: FirNameReferencePositionContext
) = with(positionContext) { ) = with(positionContext) {
val fileSymbol = basicContext.originalKtFile.getFileSymbol() val fileSymbol = originalKtFile.getFileSymbol()
val expectedType = nameExpression.getExpectedType() val expectedType = nameExpression.getExpectedType()
val scopesContext = basicContext.originalKtFile.getScopeContextForPosition(nameExpression) val scopesContext = originalKtFile.getScopeContextForPosition(nameExpression)
val extensionChecker = ExtensionApplicabilityChecker { val extensionChecker = ExtensionApplicabilityChecker {
it.checkExtensionIsSuitable(basicContext.originalKtFile, nameExpression, explicitReceiver) it.checkExtensionIsSuitable(originalKtFile, nameExpression, explicitReceiver)
} }
val visibilityChecker = CompletionVisibilityChecker { val visibilityChecker = CompletionVisibilityChecker {
basicContext.parameters.invocationCount > 1 || isVisible( parameters.invocationCount > 1 || isVisible(
it, it,
fileSymbol, fileSymbol,
positionContext.explicitReceiver, positionContext.explicitReceiver,
@@ -188,14 +188,12 @@ private class KotlinWithNameReferenceCompletionProvider(
when { when {
nameExpression.parent is KtUserType -> collectTypesCompletion( nameExpression.parent is KtUserType -> collectTypesCompletion(
basicContext.result,
scopesContext.scopes, scopesContext.scopes,
expectedType, expectedType,
visibilityChecker visibilityChecker
) )
explicitReceiver != null -> { explicitReceiver != null -> {
collectDotCompletion( collectDotCompletion(
basicContext.result,
scopesContext.scopes, scopesContext.scopes,
explicitReceiver, explicitReceiver,
expectedType, expectedType,
@@ -204,13 +202,12 @@ private class KotlinWithNameReferenceCompletionProvider(
) )
} }
else -> collectDefaultCompletion(basicContext.result, scopesContext, expectedType, extensionChecker, visibilityChecker) else -> collectDefaultCompletion(scopesContext, expectedType, extensionChecker, visibilityChecker)
} }
} }
private fun KtAnalysisSession.collectTypesCompletion( private fun KtAnalysisSession.collectTypesCompletion(
result: CompletionResultSet,
implicitScopes: KtScope, implicitScopes: KtScope,
expectedType: KtType?, expectedType: KtType?,
visibilityChecker: CompletionVisibilityChecker, visibilityChecker: CompletionVisibilityChecker,
@@ -229,7 +226,6 @@ private class KotlinWithNameReferenceCompletionProvider(
} }
private fun KtAnalysisSession.collectDotCompletion( private fun KtAnalysisSession.collectDotCompletion(
result: CompletionResultSet,
implicitScopes: KtCompositeScope, implicitScopes: KtCompositeScope,
explicitReceiver: KtExpression, explicitReceiver: KtExpression,
expectedType: KtType?, expectedType: KtType?,
@@ -250,7 +246,6 @@ private class KotlinWithNameReferenceCompletionProvider(
} }
private fun KtAnalysisSession.collectDefaultCompletion( private fun KtAnalysisSession.collectDefaultCompletion(
result: CompletionResultSet,
implicitScopesContext: KtScopeContext, implicitScopesContext: KtScopeContext,
expectedType: KtType?, expectedType: KtType?,
extensionChecker: ExtensionApplicabilityChecker, extensionChecker: ExtensionApplicabilityChecker,
@@ -275,7 +270,7 @@ private class KotlinWithNameReferenceCompletionProvider(
collectTopLevelExtensionsFromIndices(implicitReceiversTypes, extensionChecker, visibilityChecker) collectTopLevelExtensionsFromIndices(implicitReceiversTypes, extensionChecker, visibilityChecker)
.forEach { addSymbolToCompletion(result, expectedType, it) } .forEach { addSymbolToCompletion(result, expectedType, it) }
collectTypesCompletion(result, implicitScopes, expectedType, visibilityChecker) collectTypesCompletion(implicitScopes, expectedType, visibilityChecker)
} }
private fun KtAnalysisSession.collectTopLevelExtensionsFromIndices( private fun KtAnalysisSession.collectTopLevelExtensionsFromIndices(
@@ -7,6 +7,7 @@ package org.jetbrains.kotlin.idea.completion.context
import com.intellij.codeInsight.completion.CompletionParameters import com.intellij.codeInsight.completion.CompletionParameters
import com.intellij.codeInsight.completion.CompletionResultSet import com.intellij.codeInsight.completion.CompletionResultSet
import com.intellij.codeInsight.completion.PrefixMatcher
import com.intellij.openapi.project.Project import com.intellij.openapi.project.Project
import org.jetbrains.kotlin.idea.project.TargetPlatformDetector import org.jetbrains.kotlin.idea.project.TargetPlatformDetector
import org.jetbrains.kotlin.platform.TargetPlatform import org.jetbrains.kotlin.platform.TargetPlatform
@@ -15,6 +16,7 @@ import org.jetbrains.kotlin.psi.KtFile
internal class FirBasicCompletionContext( internal class FirBasicCompletionContext(
val parameters: CompletionParameters, val parameters: CompletionParameters,
val result: CompletionResultSet, val result: CompletionResultSet,
val prefixMatcher: PrefixMatcher,
val originalKtFile: KtFile, val originalKtFile: KtFile,
val fakeKtFile: KtFile, val fakeKtFile: KtFile,
val project: Project, val project: Project,
@@ -22,11 +24,12 @@ internal class FirBasicCompletionContext(
) { ) {
companion object { companion object {
fun createFromParameters(parameters: CompletionParameters, result: CompletionResultSet): FirBasicCompletionContext? { fun createFromParameters(parameters: CompletionParameters, result: CompletionResultSet): FirBasicCompletionContext? {
val prefixMatcher = result.prefixMatcher
val originalKtFile = parameters.originalFile as? KtFile ?: return null val originalKtFile = parameters.originalFile as? KtFile ?: return null
val fakeKtFile = parameters.position.containingFile as? KtFile ?: return null val fakeKtFile = parameters.position.containingFile as? KtFile ?: return null
val targetPlatform = TargetPlatformDetector.getPlatform(originalKtFile) val targetPlatform = TargetPlatformDetector.getPlatform(originalKtFile)
val project = originalKtFile.project val project = originalKtFile.project
return FirBasicCompletionContext(parameters, result, originalKtFile, fakeKtFile, project, targetPlatform) return FirBasicCompletionContext(parameters, result, prefixMatcher, originalKtFile, fakeKtFile, project, targetPlatform)
} }
} }
} }
@@ -0,0 +1,24 @@
/*
* 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.codeInsight.completion.CompletionParameters
import com.intellij.codeInsight.completion.CompletionResultSet
import com.intellij.codeInsight.completion.PrefixMatcher
import com.intellij.openapi.project.Project
import org.jetbrains.kotlin.idea.completion.context.FirBasicCompletionContext
import org.jetbrains.kotlin.platform.TargetPlatform
import org.jetbrains.kotlin.psi.KtFile
internal abstract class FirCompletionContributorBase(protected val basicContext: FirBasicCompletionContext) {
protected val prefixMatcher: PrefixMatcher get() = basicContext.prefixMatcher
protected val parameters: CompletionParameters get() = basicContext.parameters
protected val result: CompletionResultSet get() = basicContext.result
protected val originalKtFile: KtFile get() = basicContext.originalKtFile
protected val fakeKtFile: KtFile get() = basicContext.fakeKtFile
protected val project: Project get() = basicContext.project
protected val targetPlatform: TargetPlatform get() = basicContext.targetPlatform
}