[kotlin] KTIJ-26747 smooth refactoring

GitOrigin-RevId: ea2aec3ef2f715d687bf9496aa3c150db93951be
This commit is contained in:
Andrew Kozlov
2024-09-05 11:16:36 +00:00
committed by intellij-monorepo-bot
parent bf87308d07
commit 446dcfbbda
2 changed files with 40 additions and 36 deletions
@@ -145,7 +145,7 @@ internal open class FirCallableCompletionContributor(
}
.filterIfInsideAnnotationEntryArgument(positionContext.position, weighingContext.expectedType)
.filterOutShadowedCallables(weighingContext.expectedType)
.filterOutUninitializedCallables(positionContext.position)
.filterNot(isUninitializedCallable(positionContext.position))
for (callableWithMetadata in callablesWithMetadata) {
addCallableSymbolToCompletion(
@@ -520,43 +520,49 @@ internal open class FirCallableCompletionContributor(
explicitReceiverTypeHint: KaType? = null,
) = CallableWithMetadataForCompletion(signature, explicitReceiverTypeHint, options, symbolOrigin)
context(KaSession)
private fun Sequence<CallableWithMetadataForCompletion>.filterOutUninitializedCallables(
position: PsiElement
): Sequence<CallableWithMetadataForCompletion> {
val uninitializedCallablesForPosition = collectUninitializedCallablesForPosition(position)
return filterNot { it.signature.symbol.psi in uninitializedCallablesForPosition }
}
private fun isUninitializedCallable(
position: PsiElement,
): (CallableWithMetadataForCompletion) -> Boolean {
val uninitializedCallablesForPosition = buildSet<KtCallableDeclaration> {
for (parent in position.parents(withSelf = false)) {
when (val grandParent = parent.parent) {
is KtParameter -> {
if (grandParent.defaultValue == parent) {
// Filter out the current parameter and all parameters initialized after the current one.
// In the following example:
// ```
// fun test(a, b: Int = <caret>, c: Int) {}
// ```
// `a` and `b` should not show up in completion.
val originalOrSelf = getOriginalDeclarationOrSelf(
declaration = grandParent,
originalKtFile = basicContext.originalKtFile,
)
generateSequence(originalOrSelf) { it.nextSiblingOfSameType() }
.forEach(::add)
}
}
context(KaSession)
private fun collectUninitializedCallablesForPosition(position: PsiElement): Set<KtCallableDeclaration> = buildSet {
for (parent in position.parents(withSelf = false)) {
when (val grandParent = parent.parent) {
is KtParameter -> {
if (grandParent.defaultValue == parent) {
// Filter out current parameter and all parameters initialized after current parameter. In the following example:
// ```
// fun test(a, b: Int = <caret>, c: Int) {}
// ```
// `a` and `b` should not show up in completion.
val originalOrSelf = getOriginalDeclarationOrSelf(grandParent, basicContext.originalKtFile)
originalOrSelf.getNextParametersWithSelf().forEach { add(it) }
is KtProperty -> {
if (grandParent.initializer == parent) {
val declaration = getOriginalDeclarationOrSelf(
declaration = grandParent,
originalKtFile = basicContext.originalKtFile,
)
add(declaration)
}
}
}
is KtProperty -> {
if (grandParent.initializer == parent) {
add(getOriginalDeclarationOrSelf(grandParent, basicContext.originalKtFile))
}
}
if (parent is KtDeclaration) break // we can use variable inside lambda or anonymous object located in its initializer
}
}
if (parent is KtDeclaration) break // we can use variable inside lambda or anonymous object located in its initializer
return { callable: CallableWithMetadataForCompletion ->
callable.signature.symbol.psi in uninitializedCallablesForPosition
}
}
private fun KtParameter.getNextParametersWithSelf(): Sequence<KtParameter> = generateSequence({ this }, { it.nextSiblingOfSameType() })
context(KaSession)
private fun Sequence<CallableWithMetadataForCompletion>.filterOutShadowedCallables(
expectedType: KaType?,
@@ -45,15 +45,13 @@ internal class ShadowedCallablesFilter {
typeArgumentsAreRequired: Boolean,
): FilterResult {
// there is no need to create simplified signature if `KaCallableSignature<*>` is already processed
if (callable in processedSignatures) return FilterResult(excludeFromCompletion = true, options)
processedSignatures.add(callable)
val importingStrategy = options.importingStrategy
val updatedImportingStrategy = ImportStrategy.DoNothing
if (!processedSignatures.add(callable)) return FilterResult(excludeFromCompletion = true, options)
// if callable is already imported, try updating importing strategy
if ((isAlreadyImported || symbolOrigin is CompletionSymbolOrigin.Scope) && importingStrategy != updatedImportingStrategy) {
val updatedOptions = options.withImportingStrategy(updatedImportingStrategy)
if ((isAlreadyImported || symbolOrigin is CompletionSymbolOrigin.Scope)
&& options.importingStrategy != ImportStrategy.DoNothing
) {
val updatedOptions = options.withImportingStrategy(ImportStrategy.DoNothing)
val excludeFromCompletion = processSignatureConsideringOptions(callable, updatedOptions, symbolOrigin, typeArgumentsAreRequired)
if (!excludeFromCompletion) {
return FilterResult(excludeFromCompletion, updatedOptions)