Refactor KotlinFirCompletionContributor
Replace extensions checking lambdas with `ExtensionApplicabilityChecker` type
This commit is contained in:
+19
-16
@@ -82,6 +82,10 @@ private object KotlinFirCompletionProvider : CompletionProvider<CompletionParame
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun interface ExtensionApplicabilityChecker {
|
||||||
|
fun isApplicable(symbol: KtCallableSymbol): Boolean
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Currently, this class is responsible for collecting all possible completion variants.
|
* Currently, this class is responsible for collecting all possible completion variants.
|
||||||
*
|
*
|
||||||
@@ -138,8 +142,9 @@ private class KotlinCommonCompletionProvider(
|
|||||||
|
|
||||||
val scopesContext = originalFile.getScopeContextForPosition(nameExpression)
|
val scopesContext = originalFile.getScopeContextForPosition(nameExpression)
|
||||||
|
|
||||||
fun KtCallableSymbol.hasSuitableExtensionReceiver(): Boolean =
|
val extensionChecker = ExtensionApplicabilityChecker {
|
||||||
checkExtensionIsSuitable(originalFile, nameExpression, explicitReceiver)
|
it.checkExtensionIsSuitable(originalFile, nameExpression, explicitReceiver)
|
||||||
|
}
|
||||||
|
|
||||||
when {
|
when {
|
||||||
nameExpression.parent is KtUserType -> collectTypesCompletion(result, scopesContext.scopes, expectedType)
|
nameExpression.parent is KtUserType -> collectTypesCompletion(result, scopesContext.scopes, expectedType)
|
||||||
@@ -148,9 +153,9 @@ private class KotlinCommonCompletionProvider(
|
|||||||
scopesContext.scopes,
|
scopesContext.scopes,
|
||||||
explicitReceiver,
|
explicitReceiver,
|
||||||
expectedType,
|
expectedType,
|
||||||
KtCallableSymbol::hasSuitableExtensionReceiver
|
extensionChecker
|
||||||
)
|
)
|
||||||
else -> collectDefaultCompletion(result, scopesContext, expectedType, KtCallableSymbol::hasSuitableExtensionReceiver)
|
else -> collectDefaultCompletion(result, scopesContext, expectedType, extensionChecker)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -172,18 +177,18 @@ private class KotlinCommonCompletionProvider(
|
|||||||
implicitScopes: KtCompositeScope,
|
implicitScopes: KtCompositeScope,
|
||||||
explicitReceiver: KtExpression,
|
explicitReceiver: KtExpression,
|
||||||
expectedType: KtType?,
|
expectedType: KtType?,
|
||||||
hasSuitableExtensionReceiver: KtCallableSymbol.() -> Boolean
|
extensionChecker: ExtensionApplicabilityChecker,
|
||||||
) {
|
) {
|
||||||
val typeOfPossibleReceiver = explicitReceiver.getKtType()
|
val typeOfPossibleReceiver = explicitReceiver.getKtType()
|
||||||
val possibleReceiverScope = typeOfPossibleReceiver.getTypeScope() ?: return
|
val possibleReceiverScope = typeOfPossibleReceiver.getTypeScope() ?: return
|
||||||
|
|
||||||
val nonExtensionMembers = possibleReceiverScope.collectNonExtensions()
|
val nonExtensionMembers = possibleReceiverScope.collectNonExtensions()
|
||||||
val extensionNonMembers = implicitScopes.collectSuitableExtensions(hasSuitableExtensionReceiver)
|
val extensionNonMembers = implicitScopes.collectSuitableExtensions(extensionChecker)
|
||||||
|
|
||||||
nonExtensionMembers.forEach { addSymbolToCompletion(result, expectedType, it) }
|
nonExtensionMembers.forEach { addSymbolToCompletion(result, expectedType, it) }
|
||||||
extensionNonMembers.forEach { addSymbolToCompletion(result, expectedType, it) }
|
extensionNonMembers.forEach { addSymbolToCompletion(result, expectedType, it) }
|
||||||
|
|
||||||
collectTopLevelExtensionsFromIndices(listOf(typeOfPossibleReceiver), hasSuitableExtensionReceiver)
|
collectTopLevelExtensionsFromIndices(listOf(typeOfPossibleReceiver), extensionChecker)
|
||||||
.forEach { addSymbolToCompletion(result, expectedType, it) }
|
.forEach { addSymbolToCompletion(result, expectedType, it) }
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -192,12 +197,12 @@ private class KotlinCommonCompletionProvider(
|
|||||||
result: CompletionResultSet,
|
result: CompletionResultSet,
|
||||||
implicitScopesContext: KtScopeContext,
|
implicitScopesContext: KtScopeContext,
|
||||||
expectedType: KtType?,
|
expectedType: KtType?,
|
||||||
hasSuitableExtensionReceiver: KtCallableSymbol.() -> Boolean,
|
extensionChecker: ExtensionApplicabilityChecker,
|
||||||
) {
|
) {
|
||||||
val (implicitScopes, implicitReceiversTypes) = implicitScopesContext
|
val (implicitScopes, implicitReceiversTypes) = implicitScopesContext
|
||||||
|
|
||||||
val availableNonExtensions = implicitScopes.collectNonExtensions()
|
val availableNonExtensions = implicitScopes.collectNonExtensions()
|
||||||
val extensionsWhichCanBeCalled = implicitScopes.collectSuitableExtensions(hasSuitableExtensionReceiver)
|
val extensionsWhichCanBeCalled = implicitScopes.collectSuitableExtensions(extensionChecker)
|
||||||
|
|
||||||
availableNonExtensions.forEach { addSymbolToCompletion(result, expectedType, it) }
|
availableNonExtensions.forEach { addSymbolToCompletion(result, expectedType, it) }
|
||||||
extensionsWhichCanBeCalled.forEach { addSymbolToCompletion(result, expectedType, it) }
|
extensionsWhichCanBeCalled.forEach { addSymbolToCompletion(result, expectedType, it) }
|
||||||
@@ -209,7 +214,7 @@ private class KotlinCommonCompletionProvider(
|
|||||||
.forEach { addSymbolToCompletion(result, expectedType, it) }
|
.forEach { addSymbolToCompletion(result, expectedType, it) }
|
||||||
}
|
}
|
||||||
|
|
||||||
collectTopLevelExtensionsFromIndices(implicitReceiversTypes, hasSuitableExtensionReceiver)
|
collectTopLevelExtensionsFromIndices(implicitReceiversTypes, extensionChecker)
|
||||||
.forEach { addSymbolToCompletion(result, expectedType, it) }
|
.forEach { addSymbolToCompletion(result, expectedType, it) }
|
||||||
|
|
||||||
collectTypesCompletion(result, implicitScopes, expectedType)
|
collectTypesCompletion(result, implicitScopes, expectedType)
|
||||||
@@ -217,23 +222,21 @@ private class KotlinCommonCompletionProvider(
|
|||||||
|
|
||||||
private fun KtAnalysisSession.collectTopLevelExtensionsFromIndices(
|
private fun KtAnalysisSession.collectTopLevelExtensionsFromIndices(
|
||||||
receiverTypes: List<KtType>,
|
receiverTypes: List<KtType>,
|
||||||
hasSuitableExtensionReceiver: KtCallableSymbol.() -> Boolean
|
extensionChecker: ExtensionApplicabilityChecker,
|
||||||
): Sequence<KtCallableSymbol> {
|
): Sequence<KtCallableSymbol> {
|
||||||
val implicitReceiverNames = findAllNamesOfTypes(receiverTypes)
|
val implicitReceiverNames = findAllNamesOfTypes(receiverTypes)
|
||||||
val topLevelExtensions = indexHelper.getTopLevelExtensions(scopeNameFilter, implicitReceiverNames)
|
val topLevelExtensions = indexHelper.getTopLevelExtensions(scopeNameFilter, implicitReceiverNames)
|
||||||
|
|
||||||
return topLevelExtensions.asSequence()
|
return topLevelExtensions.asSequence()
|
||||||
.map { it.getSymbol() as KtCallableSymbol }
|
.map { it.getSymbol() as KtCallableSymbol }
|
||||||
.filter(hasSuitableExtensionReceiver)
|
.filter { extensionChecker.isApplicable(it) }
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun KtScope.collectNonExtensions(): Sequence<KtCallableSymbol> =
|
private fun KtScope.collectNonExtensions(): Sequence<KtCallableSymbol> =
|
||||||
getCallableSymbols(scopeNameFilter).filterNot { it.isExtension }
|
getCallableSymbols(scopeNameFilter).filterNot { it.isExtension }
|
||||||
|
|
||||||
private fun KtScope.collectSuitableExtensions(
|
private fun KtScope.collectSuitableExtensions(extensionChecker: ExtensionApplicabilityChecker): Sequence<KtCallableSymbol> =
|
||||||
hasSuitableExtensionReceiver: KtCallableSymbol.() -> Boolean
|
getCallableSymbols(scopeNameFilter).filter { it.isExtension && extensionChecker.isApplicable(it) }
|
||||||
): Sequence<KtCallableSymbol> =
|
|
||||||
getCallableSymbols(scopeNameFilter).filter { it.isExtension && it.hasSuitableExtensionReceiver() }
|
|
||||||
|
|
||||||
private fun KtAnalysisSession.findAllNamesOfTypes(implicitReceiversTypes: List<KtType>) =
|
private fun KtAnalysisSession.findAllNamesOfTypes(implicitReceiversTypes: List<KtType>) =
|
||||||
implicitReceiversTypes.flatMapTo(hashSetOf()) { with(typeNamesProvider) { findAllNames(it) } }
|
implicitReceiversTypes.flatMapTo(hashSetOf()) { with(typeNamesProvider) { findAllNames(it) } }
|
||||||
|
|||||||
Reference in New Issue
Block a user