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) action(lookupElementFactory)
} }
protected fun createLookupElementFactory(contextVariablesProvider: ContextVariablesProvider): LookupElementFactory { protected open fun createLookupElementFactory(contextVariablesProvider: ContextVariablesProvider): LookupElementFactory {
return LookupElementFactory(basicLookupElementFactory, receiverTypes, return LookupElementFactory(basicLookupElementFactory, receiverTypes,
callTypeAndReceiver.callType, inDescriptor, contextVariablesProvider) callTypeAndReceiver.callType, inDescriptor, contextVariablesProvider)
} }
@@ -48,7 +48,8 @@ class LookupElementFactory(
private val receiverTypes: Collection<KotlinType>?, private val receiverTypes: Collection<KotlinType>?,
private val callType: CallType<*>?, private val callType: CallType<*>?,
private val inDescriptor: DeclarationDescriptor, private val inDescriptor: DeclarationDescriptor,
private val contextVariablesProvider: ContextVariablesProvider private val contextVariablesProvider: ContextVariablesProvider,
private val standardLookupElementsPostProcessor: (LookupElement) -> LookupElement = { it }
) { ) {
companion object { companion object {
fun hasSingleFunctionTypeParameter(descriptor: FunctionDescriptor): Boolean { 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 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(createLookupElement(descriptor, useReceiverTypes, parametersAndTypeGrayed = !isNormalCall && callType != CallType.INFIX))
result.add(lookupElement)
// add special item for function with one argument of function type with more than one parameter // add special item for function with one argument of function type with more than one parameter
if (descriptor is FunctionDescriptor && isNormalCall) { 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) { private fun MutableCollection<LookupElement>.addSpecialFunctionCallElements(descriptor: FunctionDescriptor, useReceiverTypes: Boolean) {
@@ -163,7 +163,7 @@ class SmartCompletion(
val infoMatcher = { expectedInfo: ExpectedInfo -> types.matchExpectedInfo(expectedInfo) } val infoMatcher = { expectedInfo: ExpectedInfo -> types.matchExpectedInfo(expectedInfo) }
result.addLookupElements(descriptor, expectedInfos, infoMatcher, noNameSimilarityForReturnItself = callTypeAndReceiver is CallTypeAndReceiver.DEFAULT) { descriptor -> 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) { 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.CompletionParameters
import com.intellij.codeInsight.completion.CompletionResultSet import com.intellij.codeInsight.completion.CompletionResultSet
import com.intellij.codeInsight.completion.CompletionSorter import com.intellij.codeInsight.completion.CompletionSorter
import com.intellij.codeInsight.lookup.LookupElement
import com.intellij.psi.impl.source.tree.LeafPsiElement 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.completion.*
import org.jetbrains.kotlin.idea.core.completion.DeclarationLookupObject
import org.jetbrains.kotlin.idea.util.CallTypeAndReceiver import org.jetbrains.kotlin.idea.util.CallTypeAndReceiver
import org.jetbrains.kotlin.load.java.descriptors.SamConstructorDescriptorKindExclude import org.jetbrains.kotlin.load.java.descriptors.SamConstructorDescriptorKindExclude
import org.jetbrains.kotlin.psi.FunctionLiteralArgument import org.jetbrains.kotlin.psi.FunctionLiteralArgument
import org.jetbrains.kotlin.psi.KtCodeFragment import org.jetbrains.kotlin.psi.KtCodeFragment
import org.jetbrains.kotlin.psi.ValueArgumentName 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.callUtil.getCall
import org.jetbrains.kotlin.resolve.calls.util.DelegatingCall import org.jetbrains.kotlin.resolve.calls.util.DelegatingCall
import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter
@@ -161,4 +166,25 @@ class SmartCompletionSession(configuration: CompletionSessionConfiguration, para
return super.createSorter() return super.createSorter()
.weighBefore(KindWeigher.toString(), NameSimilarityWeigher, SmartCompletionPriorityWeigher) .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> { private fun createLookupElements(memberDescriptor: DeclarationDescriptor): Collection<LookupElement> {
return lookupElementFactory.createLookupElementsInSmartCompletion(memberDescriptor, bindingContext, useReceiverTypes = false) return lookupElementFactory.createStandardLookupElementsForDescriptor(memberDescriptor, useReceiverTypes = false)
.map { .map {
it.decorateAsStaticMember(memberDescriptor, classNameAsLookupString = true)!! it.decorateAsStaticMember(memberDescriptor, classNameAsLookupString = true)!!
.assignSmartCompletionPriority(SmartCompletionItemPriority.STATIC_MEMBER) .assignSmartCompletionPriority(SmartCompletionItemPriority.STATIC_MEMBER)
@@ -281,7 +281,7 @@ class TypeInstantiationItems(
val samConstructor = scope.getContributedFunctions(`class`.name, NoLookupLocation.FROM_IDE) val samConstructor = scope.getContributedFunctions(`class`.name, NoLookupLocation.FROM_IDE)
.filterIsInstance<SamConstructorDescriptor>() .filterIsInstance<SamConstructorDescriptor>()
.singleOrNull() ?: return .singleOrNull() ?: return
lookupElementFactory.createLookupElementsInSmartCompletion(samConstructor, bindingContext, useReceiverTypes = false) lookupElementFactory.createStandardLookupElementsForDescriptor(samConstructor, useReceiverTypes = false)
.mapTo(collection) { .mapTo(collection) {
it.assignSmartCompletionPriority(SmartCompletionItemPriority.INSTANTIATION).addTail(tail) 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.completion.handlers.WithTailInsertHandler
import org.jetbrains.kotlin.idea.resolve.ResolutionFacade import org.jetbrains.kotlin.idea.resolve.ResolutionFacade
import org.jetbrains.kotlin.idea.util.* import org.jetbrains.kotlin.idea.util.*
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.callableReferences.getReflectionTypeForCandidateDescriptor import org.jetbrains.kotlin.resolve.callableReferences.getReflectionTypeForCandidateDescriptor
import org.jetbrains.kotlin.types.TypeSubstitutor import org.jetbrains.kotlin.types.TypeSubstitutor
import org.jetbrains.kotlin.types.typeUtil.TypeNullability import org.jetbrains.kotlin.types.typeUtil.TypeNullability
@@ -249,26 +248,6 @@ fun CallableDescriptor.callableReferenceType(resolutionFacade: ResolutionFacade)
return FuzzyType(type, emptyList()) 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 { enum class SmartCompletionItemPriority {
MULTIPLE_ARGUMENTS_ITEM, MULTIPLE_ARGUMENTS_ITEM,
IT, IT,