Refactoring in smart completion

This commit is contained in:
Valentin Kipyatkov
2015-11-05 14:10:24 +03:00
parent 576b79de0a
commit 1283f5f4e1
7 changed files with 34 additions and 29 deletions
@@ -429,7 +429,7 @@ abstract class CompletionSession(
action(lookupElementFactory)
}
protected fun createLookupElementFactory(contextVariablesProvider: ContextVariablesProvider): LookupElementFactory {
protected open fun createLookupElementFactory(contextVariablesProvider: ContextVariablesProvider): LookupElementFactory {
return LookupElementFactory(basicLookupElementFactory, receiverTypes,
callTypeAndReceiver.callType, inDescriptor, contextVariablesProvider)
}
@@ -48,7 +48,8 @@ class LookupElementFactory(
private val receiverTypes: Collection<KotlinType>?,
private val callType: CallType<*>?,
private val inDescriptor: DeclarationDescriptor,
private val contextVariablesProvider: ContextVariablesProvider
private val contextVariablesProvider: ContextVariablesProvider,
private val standardLookupElementsPostProcessor: (LookupElement) -> LookupElement = { it }
) {
companion object {
fun hasSingleFunctionTypeParameter(descriptor: FunctionDescriptor): Boolean {
@@ -73,8 +74,7 @@ class LookupElementFactory(
val isNormalCall = callType == CallType.DEFAULT || callType == CallType.DOT || callType == CallType.SAFE || callType == CallType.SUPER_MEMBERS
var lookupElement = createLookupElement(descriptor, useReceiverTypes, parametersAndTypeGrayed = !isNormalCall && callType != CallType.INFIX)
result.add(lookupElement)
result.add(createLookupElement(descriptor, useReceiverTypes, parametersAndTypeGrayed = !isNormalCall && callType != CallType.INFIX))
// add special item for function with one argument of function type with more than one parameter
if (descriptor is FunctionDescriptor && isNormalCall) {
@@ -86,7 +86,7 @@ class LookupElementFactory(
}
}
return result
return result.map(standardLookupElementsPostProcessor)
}
private fun MutableCollection<LookupElement>.addSpecialFunctionCallElements(descriptor: FunctionDescriptor, useReceiverTypes: Boolean) {
@@ -163,7 +163,7 @@ class SmartCompletion(
val infoMatcher = { expectedInfo: ExpectedInfo -> types.matchExpectedInfo(expectedInfo) }
result.addLookupElements(descriptor, expectedInfos, infoMatcher, noNameSimilarityForReturnItself = callTypeAndReceiver is CallTypeAndReceiver.DEFAULT) { descriptor ->
lookupElementFactory.createLookupElementsInSmartCompletion(descriptor, bindingContext, true)
lookupElementFactory.createStandardLookupElementsForDescriptor(descriptor, useReceiverTypes = true)
}
if (callTypeAndReceiver is CallTypeAndReceiver.DEFAULT) {
@@ -19,13 +19,18 @@ package org.jetbrains.kotlin.idea.completion.smart
import com.intellij.codeInsight.completion.CompletionParameters
import com.intellij.codeInsight.completion.CompletionResultSet
import com.intellij.codeInsight.completion.CompletionSorter
import com.intellij.codeInsight.lookup.LookupElement
import com.intellij.psi.impl.source.tree.LeafPsiElement
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
import org.jetbrains.kotlin.idea.completion.*
import org.jetbrains.kotlin.idea.core.completion.DeclarationLookupObject
import org.jetbrains.kotlin.idea.util.CallTypeAndReceiver
import org.jetbrains.kotlin.load.java.descriptors.SamConstructorDescriptorKindExclude
import org.jetbrains.kotlin.psi.FunctionLiteralArgument
import org.jetbrains.kotlin.psi.KtCodeFragment
import org.jetbrains.kotlin.psi.ValueArgumentName
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.calls.callUtil.getCall
import org.jetbrains.kotlin.resolve.calls.util.DelegatingCall
import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter
@@ -161,4 +166,25 @@ class SmartCompletionSession(configuration: CompletionSessionConfiguration, para
return super.createSorter()
.weighBefore(KindWeigher.toString(), NameSimilarityWeigher, SmartCompletionPriorityWeigher)
}
override fun createLookupElementFactory(contextVariablesProvider: ContextVariablesProvider): LookupElementFactory {
return super.createLookupElementFactory(contextVariablesProvider).copy(
standardLookupElementsPostProcessor = { wrapStandardLookupElement(it) }
)
}
private fun wrapStandardLookupElement(lookupElement: LookupElement): LookupElement {
val descriptor = (lookupElement.`object` as DeclarationLookupObject).descriptor
var element = lookupElement
if (descriptor is FunctionDescriptor && descriptor.valueParameters.isNotEmpty()) {
element = element.keepOldArgumentListOnTab()
}
if (descriptor is ValueParameterDescriptor && bindingContext[BindingContext.AUTO_CREATED_IT, descriptor]!!) {
element = element.assignSmartCompletionPriority(SmartCompletionItemPriority.IT)
}
return element
}
}
@@ -98,7 +98,7 @@ class StaticMembers(
}
private fun createLookupElements(memberDescriptor: DeclarationDescriptor): Collection<LookupElement> {
return lookupElementFactory.createLookupElementsInSmartCompletion(memberDescriptor, bindingContext, useReceiverTypes = false)
return lookupElementFactory.createStandardLookupElementsForDescriptor(memberDescriptor, useReceiverTypes = false)
.map {
it.decorateAsStaticMember(memberDescriptor, classNameAsLookupString = true)!!
.assignSmartCompletionPriority(SmartCompletionItemPriority.STATIC_MEMBER)
@@ -281,7 +281,7 @@ class TypeInstantiationItems(
val samConstructor = scope.getContributedFunctions(`class`.name, NoLookupLocation.FROM_IDE)
.filterIsInstance<SamConstructorDescriptor>()
.singleOrNull() ?: return
lookupElementFactory.createLookupElementsInSmartCompletion(samConstructor, bindingContext, useReceiverTypes = false)
lookupElementFactory.createStandardLookupElementsForDescriptor(samConstructor, useReceiverTypes = false)
.mapTo(collection) {
it.assignSmartCompletionPriority(SmartCompletionItemPriority.INSTANTIATION).addTail(tail)
}
@@ -31,7 +31,6 @@ import org.jetbrains.kotlin.idea.completion.handlers.WithExpressionPrefixInsertH
import org.jetbrains.kotlin.idea.completion.handlers.WithTailInsertHandler
import org.jetbrains.kotlin.idea.resolve.ResolutionFacade
import org.jetbrains.kotlin.idea.util.*
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.callableReferences.getReflectionTypeForCandidateDescriptor
import org.jetbrains.kotlin.types.TypeSubstitutor
import org.jetbrains.kotlin.types.typeUtil.TypeNullability
@@ -249,26 +248,6 @@ fun CallableDescriptor.callableReferenceType(resolutionFacade: ResolutionFacade)
return FuzzyType(type, emptyList())
}
fun LookupElementFactory.createLookupElementsInSmartCompletion(
descriptor: DeclarationDescriptor,
bindingContext: BindingContext,
useReceiverTypes: Boolean
): Collection<LookupElement> {
return createStandardLookupElementsForDescriptor(descriptor, useReceiverTypes).map {
var element = it
if (descriptor is FunctionDescriptor && descriptor.valueParameters.isNotEmpty()) {
element = element.keepOldArgumentListOnTab()
}
if (descriptor is ValueParameterDescriptor && bindingContext[BindingContext.AUTO_CREATED_IT, descriptor]!!) {
element = element.assignSmartCompletionPriority(SmartCompletionItemPriority.IT)
}
element
}
}
enum class SmartCompletionItemPriority {
MULTIPLE_ARGUMENTS_ITEM,
IT,