From 7c675667199ceddcbccd4e226cace74aff86a449 Mon Sep 17 00:00:00 2001 From: Valentin Kipyatkov Date: Mon, 1 Dec 2014 16:22:57 +0300 Subject: [PATCH] Completion: got rid of special LookupElementFactory implementation to highlight immediate members --- .../plugin/completion/AllClassesCompletion.kt | 6 +- .../plugin/completion/CompletionSession.kt | 15 +- .../plugin/completion/LookupElementFactory.kt | 131 +++++++++--------- .../completion/LookupElementsCollector.kt | 7 +- .../completion/PackageDirectiveCompletion.kt | 2 +- .../completion/smart/SmartCompletion.kt | 12 +- .../plugin/completion/smart/StaticMembers.kt | 8 +- .../smart/TypeInstantiationItems.kt | 7 +- .../jet/plugin/completion/smart/Utils.kt | 5 +- 9 files changed, 101 insertions(+), 92 deletions(-) diff --git a/idea/src/org/jetbrains/jet/plugin/completion/AllClassesCompletion.kt b/idea/src/org/jetbrains/jet/plugin/completion/AllClassesCompletion.kt index 4a1790fd06e..34ed40d7af0 100644 --- a/idea/src/org/jetbrains/jet/plugin/completion/AllClassesCompletion.kt +++ b/idea/src/org/jetbrains/jet/plugin/completion/AllClassesCompletion.kt @@ -31,13 +31,11 @@ import org.jetbrains.jet.plugin.caches.KotlinIndicesHelper import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor import com.intellij.psi.search.GlobalSearchScope import org.jetbrains.jet.lang.resolve.BindingContext -import org.jetbrains.jet.lang.descriptors.ModuleDescriptor -import org.jetbrains.jet.plugin.caches.resolve.ResolutionFacade -import org.jetbrains.jet.lang.resolve.BindingContext import org.jetbrains.jet.plugin.caches.resolve.ResolutionFacade import org.jetbrains.jet.lang.descriptors.ModuleDescriptor class AllClassesCompletion(val parameters: CompletionParameters, + val lookupElementFactory: LookupElementFactory, val resolutionFacade: ResolutionFacade, val bindingContext: BindingContext, val moduleDescriptor: ModuleDescriptor, @@ -75,7 +73,7 @@ class AllClassesCompletion(val parameters: CompletionParameters, else -> ClassKind.CLASS } if (kindFilter(kind)) { - collector.addElementWithAutoInsertionSuppressed(LookupElementFactory.DEFAULT.createLookupElementForJavaClass(psiClass)) + collector.addElementWithAutoInsertionSuppressed(lookupElementFactory.createLookupElementForJavaClass(psiClass)) } } } diff --git a/idea/src/org/jetbrains/jet/plugin/completion/CompletionSession.kt b/idea/src/org/jetbrains/jet/plugin/completion/CompletionSession.kt index 414e2cc35de..ce731f543d5 100644 --- a/idea/src/org/jetbrains/jet/plugin/completion/CompletionSession.kt +++ b/idea/src/org/jetbrains/jet/plugin/completion/CompletionSession.kt @@ -72,8 +72,8 @@ abstract class CompletionSessionBase(protected val configuration: CompletionSess protected val referenceVariantsHelper: ReferenceVariantsHelper? = if (bindingContext != null) ReferenceVariantsHelper(bindingContext) { isVisibleDescriptor(it) } else null - protected val boldImmediateLookupElementFactory: LookupElementFactory = run { - if (jetReference != null) { + protected val lookupElementFactory: LookupElementFactory = run { + val receiverTypes = if (jetReference != null) { val expression = jetReference.expression val (receivers, callType) = referenceVariantsHelper!!.getReferenceVariantsReceivers(expression) val dataFlowInfo = bindingContext!!.getDataFlowInfo(expression) @@ -83,14 +83,15 @@ abstract class CompletionSessionBase(protected val configuration: CompletionSess if (callType == ReferenceVariantsHelper.CallType.SAFE) { receiverTypes = receiverTypes.map { it.makeNotNullable() } } - BoldImmediateLookupElementFactory(receiverTypes) + receiverTypes } else { - LookupElementFactory.DEFAULT + null } + LookupElementFactory(receiverTypes) } - protected val collector: LookupElementsCollector = LookupElementsCollector(prefixMatcher, parameters, resolutionFacade, boldImmediateLookupElementFactory) + protected val collector: LookupElementsCollector = LookupElementsCollector(prefixMatcher, parameters, resolutionFacade, lookupElementFactory) protected val project: Project = position.getProject() @@ -166,7 +167,7 @@ abstract class CompletionSessionBase(protected val configuration: CompletionSess protected fun addAllClasses(kindFilter: (ClassKind) -> Boolean) { AllClassesCompletion( - parameters, resolutionFacade, bindingContext!!, moduleDescriptor, + parameters, lookupElementFactory, resolutionFacade, bindingContext!!, moduleDescriptor, searchScope, prefixMatcher, kindFilter, { isVisibleDescriptor(it) } ).collect(collector) } @@ -265,7 +266,7 @@ class SmartCompletionSession(configuration: CompletionSessionConfiguration, para val mapper = ToFromOriginalFileMapper(parameters.getOriginalFile() as JetFile, position.getContainingFile() as JetFile, parameters.getOffset()) val completion = SmartCompletion(jetReference.expression, resolutionFacade, moduleDescriptor, bindingContext!!, { isVisibleDescriptor(it) }, originalSearchScope, - mapper, boldImmediateLookupElementFactory) + mapper, lookupElementFactory) val result = completion.execute() if (result != null) { collector.addElements(result.additionalItems) diff --git a/idea/src/org/jetbrains/jet/plugin/completion/LookupElementFactory.kt b/idea/src/org/jetbrains/jet/plugin/completion/LookupElementFactory.kt index cd4575318b0..51f93a229e9 100644 --- a/idea/src/org/jetbrains/jet/plugin/completion/LookupElementFactory.kt +++ b/idea/src/org/jetbrains/jet/plugin/completion/LookupElementFactory.kt @@ -39,13 +39,78 @@ import java.awt.Color import org.jetbrains.jet.lang.types.TypeUtils import com.intellij.codeInsight.lookup.DefaultLookupItemRenderer -public open class LookupElementFactory protected() { - public open fun createLookupElement(resolutionFacade: ResolutionFacade, descriptor: DeclarationDescriptor): LookupElement { +public class LookupElementFactory( + private val receiverTypes: Collection? +) { + public fun createLookupElement( + resolutionFacade: ResolutionFacade, + descriptor: DeclarationDescriptor, + boldImmediateMembers: Boolean + ): LookupElement { val _descriptor = if (descriptor is CallableMemberDescriptor) DescriptorUtils.unwrapFakeOverride(descriptor) else descriptor - return createLookupElement(resolutionFacade, _descriptor, DescriptorToSourceUtils.descriptorToDeclaration(_descriptor)) + var element = createLookupElement(resolutionFacade, _descriptor, DescriptorToSourceUtils.descriptorToDeclaration(_descriptor)) + if (boldImmediateMembers) { + element = element.boldIfImmediate(descriptor) + } + return element + } + + private fun LookupElement.boldIfImmediate(descriptor: DeclarationDescriptor): LookupElement { + if (receiverTypes == null) return this + if (descriptor !is CallableMemberDescriptor) return this + + val isReceiverNullable = receiverTypes.all { it.isNullable() } + val receiverParameter = descriptor.getExtensionReceiverParameter() + + val style: Style = if (receiverParameter != null) { + val receiverParamType = receiverParameter.getType() + if (isReceiverNullable && !receiverParamType.isNullable()) + Style.GRAYED + else if (receiverTypes.any { TypeUtils.equalTypes(it, receiverParamType) }) + Style.BOLD + else + Style.NORMAL + } + else { + if (isReceiverNullable) + Style.GRAYED + else if (descriptor.getContainingDeclaration() is ClassifierDescriptor && descriptor.getKind() == CallableMemberDescriptor.Kind.DECLARATION) + Style.BOLD + else + Style.NORMAL + } + + return if (style != Style.NORMAL) { + object : LookupElementDecorator(this) { + override fun renderElement(presentation: LookupElementPresentation) { + super.renderElement(presentation) + if (style == Style.BOLD) { + presentation.setItemTextBold(true) + } + else { + presentation.setItemTextForeground(Color.GRAY) + // gray all tail fragments too: + val fragments = presentation.getTailFragments() + presentation.clearTail() + for (fragment in fragments) { + presentation.appendTailText(fragment.text, true) + } + } + } + } + } + else { + this + } + } + + private enum class Style { + NORMAL + BOLD + GRAYED } public fun createLookupElementForJavaClass(psiClass: PsiClass): LookupElement { @@ -146,8 +211,6 @@ public open class LookupElementFactory protected() { } class object { - public val DEFAULT: LookupElementFactory = LookupElementFactory() - public fun getDefaultInsertHandler(descriptor: DeclarationDescriptor): InsertHandler { return when (descriptor) { is FunctionDescriptor -> { @@ -180,61 +243,3 @@ public open class LookupElementFactory protected() { } } } - -public class BoldImmediateLookupElementFactory(private val receiverTypes: Collection) : LookupElementFactory() { - override fun createLookupElement(resolutionFacade: ResolutionFacade, descriptor: DeclarationDescriptor): LookupElement { - val element = super.createLookupElement(resolutionFacade, descriptor) - - if (descriptor !is CallableMemberDescriptor) return element - - val isReceiverNullable = receiverTypes.all { it.isNullable() } - val receiverParameter = descriptor.getExtensionReceiverParameter() - - val style: Style = if (receiverParameter != null) { - val receiverParamType = receiverParameter.getType() - if (isReceiverNullable && !receiverParamType.isNullable()) - Style.GRAYED - else if (receiverTypes.any { TypeUtils.equalTypes(it, receiverParamType) }) - Style.BOLD - else - Style.NORMAL - } - else { - if (isReceiverNullable) - Style.GRAYED - else if (descriptor.getContainingDeclaration() is ClassifierDescriptor && descriptor.getKind() == CallableMemberDescriptor.Kind.DECLARATION) - Style.BOLD - else - Style.NORMAL - } - - return if (style != Style.NORMAL) { - object : LookupElementDecorator(element) { - override fun renderElement(presentation: LookupElementPresentation) { - super.renderElement(presentation) - if (style == Style.BOLD) { - presentation.setItemTextBold(true) - } - else { - presentation.setItemTextForeground(Color.GRAY) - // gray all tail fragments too: - val fragments = presentation.getTailFragments() - presentation.clearTail() - for (fragment in fragments) { - presentation.appendTailText(fragment.text, true) - } - } - } - } - } - else { - element - } - } - - private enum class Style { - NORMAL - BOLD - GRAYED - } -} diff --git a/idea/src/org/jetbrains/jet/plugin/completion/LookupElementsCollector.kt b/idea/src/org/jetbrains/jet/plugin/completion/LookupElementsCollector.kt index 9acdce70c21..6333c4cbad6 100644 --- a/idea/src/org/jetbrains/jet/plugin/completion/LookupElementsCollector.kt +++ b/idea/src/org/jetbrains/jet/plugin/completion/LookupElementsCollector.kt @@ -35,7 +35,7 @@ class LookupElementsCollector( private val prefixMatcher: PrefixMatcher, private val completionParameters: CompletionParameters, private val resolutionFacade: ResolutionFacade, - private val boldImmediateLookupElementFactory: LookupElementFactory + private val lookupElementFactory: LookupElementFactory ) { private val elements = ArrayList() @@ -61,11 +61,10 @@ class LookupElementsCollector( public fun addDescriptorElements(descriptor: DeclarationDescriptor, suppressAutoInsertion: Boolean, shouldCastToRuntimeType: Boolean) { run { - var lookupElement = boldImmediateLookupElementFactory.createLookupElement(resolutionFacade, descriptor) + var lookupElement = lookupElementFactory.createLookupElement(resolutionFacade, descriptor, true) if (shouldCastToRuntimeType) { lookupElement = lookupElement.shouldCastReceiver() } - if (suppressAutoInsertion) { addElementWithAutoInsertionSuppressed(lookupElement) } @@ -82,7 +81,7 @@ class LookupElementsCollector( if (KotlinBuiltIns.isFunctionOrExtensionFunctionType(parameterType)) { val parameterCount = KotlinBuiltIns.getParameterTypeProjectionsFromFunctionType(parameterType).size() if (parameterCount > 1) { - val lookupElement = boldImmediateLookupElementFactory.createLookupElement(resolutionFacade, descriptor) + val lookupElement = lookupElementFactory.createLookupElement(resolutionFacade, descriptor, true) addElement(object : LookupElementDecorator(lookupElement) { override fun renderElement(presentation: LookupElementPresentation) { super.renderElement(presentation) diff --git a/idea/src/org/jetbrains/jet/plugin/completion/PackageDirectiveCompletion.kt b/idea/src/org/jetbrains/jet/plugin/completion/PackageDirectiveCompletion.kt index 4fa67831978..d8987e5e3d6 100644 --- a/idea/src/org/jetbrains/jet/plugin/completion/PackageDirectiveCompletion.kt +++ b/idea/src/org/jetbrains/jet/plugin/completion/PackageDirectiveCompletion.kt @@ -52,7 +52,7 @@ object PackageDirectiveCompletion { val variants = ReferenceVariantsHelper(bindingContext, { true }).getPackageReferenceVariants(ref.expression, prefixMatcher.asNameFilter()) for (variant in variants) { - val lookupElement = LookupElementFactory.DEFAULT.createLookupElement(resolutionFacade, variant) + val lookupElement = LookupElementFactory(null).createLookupElement(resolutionFacade, variant, false) if (!lookupElement.getLookupString().contains(DUMMY_IDENTIFIER)) { result.addElement(lookupElement) } diff --git a/idea/src/org/jetbrains/jet/plugin/completion/smart/SmartCompletion.kt b/idea/src/org/jetbrains/jet/plugin/completion/smart/SmartCompletion.kt index 8b7c879c25f..9aea4c41b99 100644 --- a/idea/src/org/jetbrains/jet/plugin/completion/smart/SmartCompletion.kt +++ b/idea/src/org/jetbrains/jet/plugin/completion/smart/SmartCompletion.kt @@ -47,7 +47,7 @@ class SmartCompletion(val expression: JetSimpleNameExpression, val visibilityFilter: (DeclarationDescriptor) -> Boolean, val inheritorSearchScope: GlobalSearchScope, val toFromOriginalFileMapper: ToFromOriginalFileMapper, - val boldImmediateLookupElementFactory: LookupElementFactory) { + val lookupElementFactory: LookupElementFactory) { private val project = expression.getProject() public class Result( @@ -133,7 +133,7 @@ class SmartCompletion(val expression: JetSimpleNameExpression, else -> ExpectedInfoClassification.NOT_MATCHES } } - result.addLookupElements(expectedInfos, classifier, { boldImmediateLookupElementFactory.createLookupElement(descriptor, resolutionFacade, bindingContext) }) + result.addLookupElements(expectedInfos, classifier, { lookupElementFactory.createLookupElement(descriptor, resolutionFacade, bindingContext, true) }) if (receiver == null) { toFunctionReferenceLookupElement(descriptor, functionExpectedInfos)?.let { result.add(it) } @@ -145,10 +145,10 @@ class SmartCompletion(val expression: JetSimpleNameExpression, val additionalItems = ArrayList() val inheritanceSearchers = ArrayList() if (receiver == null) { - TypeInstantiationItems(resolutionFacade, moduleDescriptor, bindingContext, visibilityFilter, toFromOriginalFileMapper, inheritorSearchScope) + TypeInstantiationItems(resolutionFacade, moduleDescriptor, bindingContext, visibilityFilter, toFromOriginalFileMapper, inheritorSearchScope, lookupElementFactory) .addTo(additionalItems, inheritanceSearchers, expectedInfos) - StaticMembers(bindingContext, resolutionFacade).addToCollection(additionalItems, expectedInfos, expression, itemsToSkip) + StaticMembers(bindingContext, resolutionFacade, lookupElementFactory).addToCollection(additionalItems, expectedInfos, expression, itemsToSkip) ThisItems(bindingContext).addToCollection(additionalItems, expressionWithType, expectedInfos) @@ -262,7 +262,7 @@ class SmartCompletion(val expression: JetSimpleNameExpression, val matchedExpectedInfos = functionExpectedInfos.filter { functionType.isSubtypeOf(it.type) } if (matchedExpectedInfos.isEmpty()) return null - var lookupElement = boldImmediateLookupElementFactory.createLookupElement(descriptor, resolutionFacade, bindingContext) + var lookupElement = lookupElementFactory.createLookupElement(descriptor, resolutionFacade, bindingContext, true) val text = "::" + (if (descriptor is ConstructorDescriptor) descriptor.getContainingDeclaration().getName() else descriptor.getName()) lookupElement = object: LookupElementDecorator(lookupElement) { override fun getLookupString() = text @@ -321,7 +321,7 @@ class SmartCompletion(val expression: JetSimpleNameExpression, if (jetType.isError()) return null val classifier = jetType.getConstructor().getDeclarationDescriptor() ?: return null - val lookupElement = LookupElementFactory.DEFAULT.createLookupElement(classifier, resolutionFacade, bindingContext) + val lookupElement = lookupElementFactory.createLookupElement(classifier, resolutionFacade, bindingContext, false) val lookupString = lookupElement.getLookupString() val typeArgs = jetType.getArguments() diff --git a/idea/src/org/jetbrains/jet/plugin/completion/smart/StaticMembers.kt b/idea/src/org/jetbrains/jet/plugin/completion/smart/StaticMembers.kt index 26b8b088717..43c5d6b2f12 100644 --- a/idea/src/org/jetbrains/jet/plugin/completion/smart/StaticMembers.kt +++ b/idea/src/org/jetbrains/jet/plugin/completion/smart/StaticMembers.kt @@ -36,7 +36,11 @@ import org.jetbrains.jet.plugin.caches.resolve.ResolutionFacade import org.jetbrains.jet.plugin.completion.LookupElementFactory // adds java static members, enum members and members from class object -class StaticMembers(val bindingContext: BindingContext, val resolutionFacade: ResolutionFacade) { +class StaticMembers( + val bindingContext: BindingContext, + val resolutionFacade: ResolutionFacade, + val lookupElementFactory: LookupElementFactory +) { public fun addToCollection(collection: MutableCollection, expectedInfos: Collection, context: JetExpression, @@ -101,7 +105,7 @@ class StaticMembers(val bindingContext: BindingContext, val resolutionFacade: Re } private fun createLookupElement(memberDescriptor: DeclarationDescriptor, classDescriptor: ClassDescriptor): LookupElement { - val lookupElement = LookupElementFactory.DEFAULT.createLookupElement(memberDescriptor, resolutionFacade, bindingContext) + val lookupElement = lookupElementFactory.createLookupElement(memberDescriptor, resolutionFacade, bindingContext, false) val qualifierPresentation = classDescriptor.getName().asString() val qualifierText = qualifiedNameForSourceCode(classDescriptor) diff --git a/idea/src/org/jetbrains/jet/plugin/completion/smart/TypeInstantiationItems.kt b/idea/src/org/jetbrains/jet/plugin/completion/smart/TypeInstantiationItems.kt index 7111ddc3930..fdb812de2da 100644 --- a/idea/src/org/jetbrains/jet/plugin/completion/smart/TypeInstantiationItems.kt +++ b/idea/src/org/jetbrains/jet/plugin/completion/smart/TypeInstantiationItems.kt @@ -67,7 +67,8 @@ class TypeInstantiationItems( val bindingContext: BindingContext, val visibilityFilter: (DeclarationDescriptor) -> Boolean, val toFromOriginalFileMapper: ToFromOriginalFileMapper, - val inheritorSearchScope: GlobalSearchScope + val inheritorSearchScope: GlobalSearchScope, + val lookupElementFactory: LookupElementFactory ) { public fun addTo( items: MutableCollection, @@ -132,7 +133,7 @@ class TypeInstantiationItems( typeArgs: List, tail: Tail? ): LookupElement? { - var lookupElement = LookupElementFactory.DEFAULT.createLookupElement(classifier, resolutionFacade, bindingContext) + var lookupElement = lookupElementFactory.createLookupElement(classifier, resolutionFacade, bindingContext, false) if (classifier.getKind() == ClassKind.OBJECT) { return lookupElement.addTail(tail) @@ -259,7 +260,7 @@ class TypeInstantiationItems( val samConstructor = scope.getFunctions(`class`.getName()) .filterIsInstance() .singleOrNull() ?: return - val lookupElement = LookupElementFactory.DEFAULT.createLookupElement(samConstructor, resolutionFacade, bindingContext) + val lookupElement = lookupElementFactory.createLookupElement(samConstructor, resolutionFacade, bindingContext, false) .assignSmartCompletionPriority(SmartCompletionItemPriority.INSTANTIATION) .addTail(tail) collection.add(lookupElement) diff --git a/idea/src/org/jetbrains/jet/plugin/completion/smart/Utils.kt b/idea/src/org/jetbrains/jet/plugin/completion/smart/Utils.kt index ecd1e1f0e94..602be5b4ef1 100644 --- a/idea/src/org/jetbrains/jet/plugin/completion/smart/Utils.kt +++ b/idea/src/org/jetbrains/jet/plugin/completion/smart/Utils.kt @@ -189,9 +189,10 @@ fun functionType(function: FunctionDescriptor): JetType? { fun LookupElementFactory.createLookupElement( descriptor: DeclarationDescriptor, resolutionFacade: ResolutionFacade, - bindingContext: BindingContext + bindingContext: BindingContext, + boldImmediateMembers: Boolean ): LookupElement { - var element = createLookupElement(resolutionFacade, descriptor) + var element = createLookupElement(resolutionFacade, descriptor, boldImmediateMembers) if (descriptor is FunctionDescriptor && descriptor.getValueParameters().isNotEmpty()) { element = element.keepOldArgumentListOnTab()