diff --git a/idea/src/org/jetbrains/jet/plugin/codeInsight/TipsManager.kt b/idea/src/org/jetbrains/jet/plugin/codeInsight/TipsManager.kt index f9fcba677a4..cae9d2a6913 100644 --- a/idea/src/org/jetbrains/jet/plugin/codeInsight/TipsManager.kt +++ b/idea/src/org/jetbrains/jet/plugin/codeInsight/TipsManager.kt @@ -52,49 +52,44 @@ public object TipsManager{ kindFilter: DescriptorKindFilter, nameFilter: (Name) -> Boolean ): Collection { - val receiverExpression = expression.getReceiverExpression() val parent = expression.getParent() val resolutionScope = context[BindingContext.RESOLUTION_SCOPE, expression] ?: return listOf() - if (receiverExpression != null) { - val inPositionForCompletionWithReceiver = parent is JetCallExpression - || parent is JetQualifiedExpression - || parent is JetBinaryExpression - if (inPositionForCompletionWithReceiver) { - val isInfixCall = parent is JetBinaryExpression - fun filterIfInfix(descriptor: DeclarationDescriptor) - = if (isInfixCall) descriptor is SimpleFunctionDescriptor && descriptor.getValueParameters().size == 1 else true - - // Process as call expression - val descriptors = HashSet() - - val qualifier = context[BindingContext.QUALIFIER, receiverExpression] - if (qualifier != null) { - // It's impossible to add extension function for package or class (if it's class object, expression type is not null) - qualifier.scope.getDescriptorsFiltered(kindFilter exclude DescriptorKindExclude.Extensions, nameFilter).filterTo(descriptors, ::filterIfInfix) - } - - val expressionType = context[BindingContext.EXPRESSION_TYPE, receiverExpression] - if (expressionType != null && !expressionType.isError()) { - val receiverValue = ExpressionReceiver(receiverExpression, expressionType) - val dataFlowInfo = context.getDataFlowInfo(expression) - - val mask = kindFilter.withoutKinds(DescriptorKindFilter.NON_SINGLETON_CLASSIFIERS_MASK).exclude(DescriptorKindExclude.Extensions) - for (variant in SmartCastUtils.getSmartCastVariantsWithLessSpecificExcluded(receiverValue, context, dataFlowInfo)) { - variant.getMemberScope().getDescriptorsFiltered(mask, nameFilter).filterTo(descriptors, ::filterIfInfix) - } - - descriptors.addCallableExtensions(resolutionScope, receiverValue, context, dataFlowInfo, isInfixCall, kindFilter, nameFilter) - } - - return descriptors - } - } - if (parent is JetImportDirective || parent is JetPackageDirective) { val restrictedFilter = kindFilter.restrictedToKinds(DescriptorKindFilter.PACKAGES_MASK) ?: return listOf() return resolutionScope.getDescriptorsFiltered(restrictedFilter, nameFilter) } + + val receiverExpression = getReferenceVariantsReceiver(expression) + if (receiverExpression != null) { + val isInfixCall = parent is JetBinaryExpression + fun filterIfInfix(descriptor: DeclarationDescriptor) + = if (isInfixCall) descriptor is SimpleFunctionDescriptor && descriptor.getValueParameters().size == 1 else true + + // Process as call expression + val descriptors = HashSet() + + val qualifier = context[BindingContext.QUALIFIER, receiverExpression] + if (qualifier != null) { + // It's impossible to add extension function for package or class (if it's class object, expression type is not null) + qualifier.scope.getDescriptorsFiltered(kindFilter exclude DescriptorKindExclude.Extensions, nameFilter).filterTo(descriptors, ::filterIfInfix) + } + + val expressionType = context[BindingContext.EXPRESSION_TYPE, receiverExpression] + if (expressionType != null && !expressionType.isError()) { + val receiverValue = ExpressionReceiver(receiverExpression, expressionType) + val dataFlowInfo = context.getDataFlowInfo(expression) + + val mask = kindFilter.withoutKinds(DescriptorKindFilter.NON_SINGLETON_CLASSIFIERS_MASK).exclude(DescriptorKindExclude.Extensions) + for (variant in SmartCastUtils.getSmartCastVariantsWithLessSpecificExcluded(receiverValue, context, dataFlowInfo)) { + variant.getMemberScope().getDescriptorsFiltered(mask, nameFilter).filterTo(descriptors, ::filterIfInfix) + } + + descriptors.addCallableExtensions(resolutionScope, receiverValue, context, dataFlowInfo, isInfixCall, kindFilter, nameFilter) + } + + return descriptors + } else { val descriptorsSet = HashSet() @@ -117,6 +112,29 @@ public object TipsManager{ } } + public fun getReferenceVariantsReceivers(expression: JetSimpleNameExpression, context: BindingContext): Collection { + val receiverExpression = getReferenceVariantsReceiver(expression) + if (receiverExpression != null) { + val expressionType = context[BindingContext.EXPRESSION_TYPE, receiverExpression] ?: return listOf() + return listOf(ExpressionReceiver(receiverExpression, expressionType)) + } + else { + val resolutionScope = context[BindingContext.RESOLUTION_SCOPE, expression] ?: return listOf() + return resolutionScope.getImplicitReceiversHierarchy().map { it.getValue() } + } + } + + private fun getReferenceVariantsReceiver(expression: JetSimpleNameExpression): JetExpression? { + val parent = expression.getParent() + val inPositionForCompletionWithReceiver = parent is JetCallExpression + || parent is JetQualifiedExpression + || parent is JetBinaryExpression + return if (inPositionForCompletionWithReceiver) + expression.getReceiverExpression() + else + null + } + private fun MutableCollection.addCallableExtensions( resolutionScope: JetScope, receiver: ReceiverValue, diff --git a/idea/src/org/jetbrains/jet/plugin/completion/AllClassesCompletion.kt b/idea/src/org/jetbrains/jet/plugin/completion/AllClassesCompletion.kt index 7ced68cc651..62e819181ec 100644 --- a/idea/src/org/jetbrains/jet/plugin/completion/AllClassesCompletion.kt +++ b/idea/src/org/jetbrains/jet/plugin/completion/AllClassesCompletion.kt @@ -68,7 +68,7 @@ class AllClassesCompletion(val parameters: CompletionParameters, else -> ClassKind.CLASS } if (kindFilter(kind)) { - collector.addElementWithAutoInsertionSuppressed(KotlinLookupElementFactory.createLookupElementForJavaClass(psiClass)) + collector.addElementWithAutoInsertionSuppressed(LookupElementFactory.DEFAULT.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 04cdf4e7095..975fe939891 100644 --- a/idea/src/org/jetbrains/jet/plugin/completion/CompletionSession.kt +++ b/idea/src/org/jetbrains/jet/plugin/completion/CompletionSession.kt @@ -33,9 +33,10 @@ import org.jetbrains.jet.plugin.caches.KotlinIndicesHelper import com.intellij.openapi.project.Project import com.intellij.psi.search.DelegatingGlobalSearchScope import com.intellij.openapi.vfs.VirtualFile -import org.jetbrains.jet.lang.resolve.scopes.JetScope import org.jetbrains.jet.lang.resolve.java.descriptor.SamConstructorDescriptorKindExclude import org.jetbrains.jet.lang.resolve.scopes.DescriptorKindFilter +import org.jetbrains.jet.lang.resolve.calls.smartcasts.SmartCastUtils +import org.jetbrains.jet.lang.resolve.bindingContextUtil.getDataFlowInfo class CompletionSessionConfiguration( val completeNonImportedDeclarations: Boolean, @@ -62,7 +63,22 @@ abstract class CompletionSessionBase(protected val configuration: CompletionSess protected val prefixMatcher: PrefixMatcher = this.resultSet.getPrefixMatcher() - protected val collector: LookupElementsCollector = LookupElementsCollector(prefixMatcher, parameters, resolveSession) + protected val boldImmediateLookupElementFactory: LookupElementFactory = run { + if (jetReference != null) { + val expression = jetReference.expression + val receivers = TipsManager.getReferenceVariantsReceivers(expression, bindingContext!!) + val dataFlowInfo = bindingContext.getDataFlowInfo(expression) + val receiverTypes = receivers.flatMap { + SmartCastUtils.getSmartCastVariantsWithLessSpecificExcluded(it, bindingContext, dataFlowInfo) + } + BoldImmediateLookupElementFactory(receiverTypes) + } + else { + LookupElementFactory.DEFAULT + } + } + + protected val collector: LookupElementsCollector = LookupElementsCollector(prefixMatcher, parameters, resolveSession, boldImmediateLookupElementFactory) protected val project: Project = position.getProject() @@ -209,7 +225,7 @@ class SmartCompletionSession(configuration: CompletionSessionConfiguration, para override fun doComplete() { if (jetReference != null) { - val completion = SmartCompletion(jetReference.expression, resolveSession, { isVisibleDescriptor(it) }, parameters.getOriginalFile() as JetFile) + val completion = SmartCompletion(jetReference.expression, resolveSession, { isVisibleDescriptor(it) }, parameters.getOriginalFile() as JetFile, boldImmediateLookupElementFactory) val result = completion.execute() if (result != null) { collector.addElements(result.additionalItems) diff --git a/idea/src/org/jetbrains/jet/plugin/completion/KotlinLookupElementFactory.kt b/idea/src/org/jetbrains/jet/plugin/completion/LookupElementFactory.kt similarity index 61% rename from idea/src/org/jetbrains/jet/plugin/completion/KotlinLookupElementFactory.kt rename to idea/src/org/jetbrains/jet/plugin/completion/LookupElementFactory.kt index a4e475ebc76..153ebef4e14 100644 --- a/idea/src/org/jetbrains/jet/plugin/completion/KotlinLookupElementFactory.kt +++ b/idea/src/org/jetbrains/jet/plugin/completion/LookupElementFactory.kt @@ -33,18 +33,17 @@ import com.intellij.psi.PsiClass import org.jetbrains.jet.asJava.KotlinLightClass import org.jetbrains.jet.lang.resolve.java.JavaResolverUtils import com.intellij.codeInsight.completion.JavaPsiClassReferenceElement +import com.intellij.codeInsight.lookup.LookupElementDecorator +import com.intellij.codeInsight.lookup.LookupElementPresentation +import org.jetbrains.jet.lang.types.JetType -public object KotlinLookupElementFactory { - public fun createLookupElement(analyzer: KotlinCodeAnalyzer, descriptor: DeclarationDescriptor, boldImmediateMembers: Boolean): LookupElement { +public open class LookupElementFactory protected() { + public open fun createLookupElement(analyzer: KotlinCodeAnalyzer, descriptor: DeclarationDescriptor): LookupElement { val _descriptor = if (descriptor is CallableMemberDescriptor) DescriptorUtils.unwrapFakeOverride(descriptor) else descriptor - val bold = boldImmediateMembers - && descriptor is CallableMemberDescriptor - && descriptor.getContainingDeclaration() is ClassifierDescriptor - && descriptor.getKind() == CallableMemberDescriptor.Kind.DECLARATION - return createLookupElement(analyzer, _descriptor, DescriptorToSourceUtils.descriptorToDeclaration(_descriptor), bold) + return createLookupElement(analyzer, _descriptor, DescriptorToSourceUtils.descriptorToDeclaration(_descriptor)) } public fun createLookupElementForJavaClass(psiClass: PsiClass): LookupElement { @@ -54,8 +53,7 @@ public object KotlinLookupElementFactory { private fun createLookupElement( analyzer: KotlinCodeAnalyzer, descriptor: DeclarationDescriptor, - declaration: PsiElement?, - bold: Boolean + declaration: PsiElement? ): LookupElement { if (descriptor is ClassifierDescriptor && declaration is PsiClass && @@ -104,10 +102,6 @@ public object KotlinLookupElementFactory { element = element.withStrikeoutness(true) } - if (bold) { - element = element.withBoldness(true) - } - val insertHandler = getDefaultInsertHandler(descriptor) element = element.withInsertHandler(insertHandler) @@ -118,34 +112,65 @@ public object KotlinLookupElementFactory { return element } - public fun getDefaultInsertHandler(descriptor: DeclarationDescriptor): InsertHandler { - return when (descriptor) { - is FunctionDescriptor -> { - val parameters = descriptor.getValueParameters() - when (parameters.size) { - 0 -> KotlinFunctionInsertHandler.NO_PARAMETERS_HANDLER + class object { + public val DEFAULT: LookupElementFactory = LookupElementFactory() - 1 -> { - val parameterType = parameters.single().getType() - if (KotlinBuiltIns.getInstance().isFunctionOrExtensionFunctionType(parameterType)) { - val parameterCount = KotlinBuiltIns.getInstance().getParameterTypeProjectionsFromFunctionType(parameterType).size() - if (parameterCount <= 1) { - // otherwise additional item with lambda template is to be added - return KotlinFunctionInsertHandler(CaretPosition.IN_BRACKETS, GenerateLambdaInfo(parameterType, false)) + public fun getDefaultInsertHandler(descriptor: DeclarationDescriptor): InsertHandler { + return when (descriptor) { + is FunctionDescriptor -> { + val parameters = descriptor.getValueParameters() + when (parameters.size) { + 0 -> KotlinFunctionInsertHandler.NO_PARAMETERS_HANDLER + + 1 -> { + val parameterType = parameters.single().getType() + if (KotlinBuiltIns.getInstance().isFunctionOrExtensionFunctionType(parameterType)) { + val parameterCount = KotlinBuiltIns.getInstance().getParameterTypeProjectionsFromFunctionType(parameterType).size() + if (parameterCount <= 1) { + // otherwise additional item with lambda template is to be added + return KotlinFunctionInsertHandler(CaretPosition.IN_BRACKETS, GenerateLambdaInfo(parameterType, false)) + } } + KotlinFunctionInsertHandler.WITH_PARAMETERS_HANDLER } - KotlinFunctionInsertHandler.WITH_PARAMETERS_HANDLER + + else -> KotlinFunctionInsertHandler.WITH_PARAMETERS_HANDLER } - - else -> KotlinFunctionInsertHandler.WITH_PARAMETERS_HANDLER } + + is PropertyDescriptor -> KotlinPropertyInsertHandler + + is ClassDescriptor -> KotlinClassInsertHandler + + else -> BaseDeclarationInsertHandler() } - - is PropertyDescriptor -> KotlinPropertyInsertHandler - - is ClassDescriptor -> KotlinClassInsertHandler - - else -> BaseDeclarationInsertHandler() + } + } +} + +public class BoldImmediateLookupElementFactory(private val receiverTypes: Collection) : LookupElementFactory() { + override fun createLookupElement(analyzer: KotlinCodeAnalyzer, descriptor: DeclarationDescriptor): LookupElement { + val element = super.createLookupElement(analyzer, descriptor) + + if (descriptor !is CallableMemberDescriptor) return element + val receiverParameter = descriptor.getExtensionReceiverParameter() + val bold = if (receiverParameter != null) { + receiverTypes.any { it == receiverParameter.getType() } + } + else { + descriptor.getContainingDeclaration() is ClassifierDescriptor && descriptor.getKind() == CallableMemberDescriptor.Kind.DECLARATION + } + + return if (bold) { + object : LookupElementDecorator(element) { + override fun renderElement(presentation: LookupElementPresentation) { + super.renderElement(presentation) + presentation.setItemTextBold(true) + } + } + } + else { + element } } } diff --git a/idea/src/org/jetbrains/jet/plugin/completion/LookupElementsCollector.kt b/idea/src/org/jetbrains/jet/plugin/completion/LookupElementsCollector.kt index 6061797ce64..b77a26b0cb4 100644 --- a/idea/src/org/jetbrains/jet/plugin/completion/LookupElementsCollector.kt +++ b/idea/src/org/jetbrains/jet/plugin/completion/LookupElementsCollector.kt @@ -34,7 +34,8 @@ import com.intellij.codeInsight.completion.CompletionParameters class LookupElementsCollector( private val prefixMatcher: PrefixMatcher, private val completionParameters: CompletionParameters, - private val resolveSession: ResolveSessionForBodies + private val resolveSession: ResolveSessionForBodies, + private val boldImmediateLookupElementFactory: LookupElementFactory ) { private val elements = ArrayList() @@ -59,7 +60,7 @@ class LookupElementsCollector( public fun addDescriptorElements(descriptor: DeclarationDescriptor, suppressAutoInsertion: Boolean) { run { - val lookupElement = KotlinLookupElementFactory.createLookupElement(resolveSession, descriptor, true) + val lookupElement = boldImmediateLookupElementFactory.createLookupElement(resolveSession, descriptor) if (suppressAutoInsertion) { addElementWithAutoInsertionSuppressed(lookupElement) } @@ -76,7 +77,7 @@ class LookupElementsCollector( if (KotlinBuiltIns.getInstance().isFunctionOrExtensionFunctionType(parameterType)) { val parameterCount = KotlinBuiltIns.getInstance().getParameterTypeProjectionsFromFunctionType(parameterType).size() if (parameterCount > 1) { - val lookupElement = KotlinLookupElementFactory.createLookupElement(resolveSession, descriptor, true) + val lookupElement = boldImmediateLookupElementFactory.createLookupElement(resolveSession, descriptor) 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 7eb96405e06..141c80b4a01 100644 --- a/idea/src/org/jetbrains/jet/plugin/completion/PackageDirectiveCompletion.kt +++ b/idea/src/org/jetbrains/jet/plugin/completion/PackageDirectiveCompletion.kt @@ -55,7 +55,7 @@ object PackageDirectiveCompletion { val variants = TipsManager.getPackageReferenceVariants(ref.expression, bindingContext, prefixMatcher.asNameFilter()) for (variant in variants) { - val lookupElement = KotlinLookupElementFactory.createLookupElement(resolveSession, variant, false) + val lookupElement = LookupElementFactory.DEFAULT.createLookupElement(resolveSession, variant) 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 c9981a4b33b..d2d2d2ef4e3 100644 --- a/idea/src/org/jetbrains/jet/plugin/completion/smart/SmartCompletion.kt +++ b/idea/src/org/jetbrains/jet/plugin/completion/smart/SmartCompletion.kt @@ -34,12 +34,12 @@ import org.jetbrains.jet.plugin.caches.resolve.getLazyResolveSession import org.jetbrains.jet.renderer.DescriptorRenderer import org.jetbrains.jet.lang.psi.psiUtil.getReceiverExpression import org.jetbrains.jet.plugin.util.IdeDescriptorRenderers -import org.jetbrains.jet.lang.resolve.java.descriptor.SamConstructorDescriptor class SmartCompletion(val expression: JetSimpleNameExpression, val resolveSession: ResolveSessionForBodies, val visibilityFilter: (DeclarationDescriptor) -> Boolean, - val originalFile: JetFile) { + val originalFile: JetFile, + val boldImmediateLookupElementFactory: LookupElementFactory) { private val bindingContext = resolveSession.resolveToElement(expression) private val project = expression.getProject() @@ -117,7 +117,7 @@ class SmartCompletion(val expression: JetSimpleNameExpression, else -> ExpectedInfoClassification.NOT_MATCHES } } - result.addLookupElements(expectedInfos, classifier, { createLookupElement(descriptor, resolveSession, bindingContext, true) }) + result.addLookupElements(expectedInfos, classifier, { boldImmediateLookupElementFactory.createLookupElement(descriptor, resolveSession, bindingContext) }) if (receiver == null) { toFunctionReferenceLookupElement(descriptor, functionExpectedInfos)?.let { result.add(it) } @@ -237,7 +237,7 @@ class SmartCompletion(val expression: JetSimpleNameExpression, val matchedExpectedInfos = functionExpectedInfos.filter { functionType.isSubtypeOf(it.type) } if (matchedExpectedInfos.isEmpty()) return null - var lookupElement = createLookupElement(descriptor, resolveSession, bindingContext, true) + var lookupElement = boldImmediateLookupElementFactory.createLookupElement(descriptor, resolveSession, bindingContext) val text = "::" + (if (descriptor is ConstructorDescriptor) descriptor.getContainingDeclaration().getName() else descriptor.getName()) lookupElement = object: LookupElementDecorator(lookupElement) { override fun getLookupString() = text @@ -296,7 +296,7 @@ class SmartCompletion(val expression: JetSimpleNameExpression, if (jetType.isError()) return null val classifier = jetType.getConstructor().getDeclarationDescriptor() ?: return null - val lookupElement = createLookupElement(classifier, resolveSession, bindingContext, false) + val lookupElement = LookupElementFactory.DEFAULT.createLookupElement(classifier, resolveSession, bindingContext) 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 47e8b33c5fc..81e7c277d18 100644 --- a/idea/src/org/jetbrains/jet/plugin/completion/smart/StaticMembers.kt +++ b/idea/src/org/jetbrains/jet/plugin/completion/smart/StaticMembers.kt @@ -33,6 +33,7 @@ import org.jetbrains.jet.plugin.util.makeNotNullable import org.jetbrains.jet.plugin.completion.qualifiedNameForSourceCode import org.jetbrains.jet.lang.resolve.descriptorUtil.isExtension import org.jetbrains.jet.plugin.util.IdeDescriptorRenderers +import org.jetbrains.jet.plugin.completion.LookupElementFactory // adds java static members, enum members and members from class object class StaticMembers(val bindingContext: BindingContext, val resolveSession: ResolveSessionForBodies) { @@ -105,7 +106,7 @@ class StaticMembers(val bindingContext: BindingContext, val resolveSession: Reso } private fun createLookupElement(memberDescriptor: DeclarationDescriptor, classDescriptor: ClassDescriptor): LookupElement { - val lookupElement = createLookupElement(memberDescriptor, resolveSession, bindingContext, false) + val lookupElement = LookupElementFactory.DEFAULT.createLookupElement(memberDescriptor, resolveSession, bindingContext) 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 cfee77a4fc3..fefc6209186 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,7 @@ class TypeInstantiationItems(val resolveSession: ResolveSessionForBodies, val bi } if (allConstructors.isNotEmpty() && visibleConstructors.isEmpty()) return - var lookupElement = createLookupElement(classifier, resolveSession, bindingContext, false) + var lookupElement = LookupElementFactory.DEFAULT.createLookupElement(classifier, resolveSession, bindingContext) var lookupString = lookupElement.getLookupString() var allLookupStrings = setOf(lookupString) @@ -108,7 +108,7 @@ class TypeInstantiationItems(val resolveSession: ResolveSessionForBodies, val bi val baseInsertHandler = when (visibleConstructors.size) { 0 -> KotlinFunctionInsertHandler.NO_PARAMETERS_HANDLER - 1 -> KotlinLookupElementFactory.getDefaultInsertHandler(visibleConstructors.single()) as KotlinFunctionInsertHandler + 1 -> LookupElementFactory.getDefaultInsertHandler(visibleConstructors.single()) as KotlinFunctionInsertHandler else -> KotlinFunctionInsertHandler.WITH_PARAMETERS_HANDLER } @@ -164,7 +164,7 @@ class TypeInstantiationItems(val resolveSession: ResolveSessionForBodies, val bi val samConstructor = scope.getFunctions(`class`.getName()) .filterIsInstance(javaClass()) .singleOrNull() ?: return - val lookupElement = createLookupElement(samConstructor, resolveSession, bindingContext, false) + val lookupElement = LookupElementFactory.DEFAULT.createLookupElement(samConstructor, resolveSession, bindingContext) .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 a176991a1c6..c453c451829 100644 --- a/idea/src/org/jetbrains/jet/plugin/completion/smart/Utils.kt +++ b/idea/src/org/jetbrains/jet/plugin/completion/smart/Utils.kt @@ -186,13 +186,12 @@ fun functionType(function: FunctionDescriptor): JetType? { function.getReturnType() ?: return null) } -fun createLookupElement( +fun LookupElementFactory.createLookupElement( descriptor: DeclarationDescriptor, resolveSession: ResolveSessionForBodies, - bindingContext: BindingContext, - boldImmediateMembers: Boolean + bindingContext: BindingContext ): LookupElement { - var element = KotlinLookupElementFactory.createLookupElement(resolveSession, descriptor, boldImmediateMembers) + var element = createLookupElement(resolveSession, descriptor) if (descriptor is FunctionDescriptor && descriptor.getValueParameters().isNotEmpty()) { element = element.keepOldArgumentListOnTab() diff --git a/idea/testData/completion/basic/common/ImmediateExtensionMembers1.kt b/idea/testData/completion/basic/common/ImmediateExtensionMembers1.kt new file mode 100644 index 00000000000..8da751284c5 --- /dev/null +++ b/idea/testData/completion/basic/common/ImmediateExtensionMembers1.kt @@ -0,0 +1,18 @@ +fun String.extFunForString(){} +fun Any.extFunForAny(){} +fun String?.extFunForStringNullable(){} + +class C { + fun Any.memberExtFunForAny(){} + fun String?.memberExtFunForStringNullable(){} + + fun foo() { + "". + } +} + +// EXIST: { itemText: "extFunForString", attributes: "bold" } +// EXIST: { itemText: "extFunForAny", attributes: "" } +// EXIST: { itemText: "extFunForStringNullable", attributes: "" } +// EXIST: { itemText: "memberExtFunForAny", attributes: "" } +// EXIST: { itemText: "memberExtFunForStringNullable", attributes: "" } diff --git a/idea/testData/completion/basic/common/ImmediateExtensionMembers2.kt b/idea/testData/completion/basic/common/ImmediateExtensionMembers2.kt new file mode 100644 index 00000000000..f508bea0ff3 --- /dev/null +++ b/idea/testData/completion/basic/common/ImmediateExtensionMembers2.kt @@ -0,0 +1,15 @@ +fun String.extFunForString(){} +fun Any.extFunForAny(){} +fun String?.extFunForStringNullable(){} + +class C { + fun foo(s: String?) { + if (s != null) { + s. + } + } +} + +// EXIST: { itemText: "extFunForString", attributes: "bold" } +// EXIST: { itemText: "extFunForAny", attributes: "" } +// EXIST: { itemText: "extFunForStringNullable", attributes: "" } diff --git a/idea/testData/completion/basic/common/ImmediateExtensionMembers3.kt b/idea/testData/completion/basic/common/ImmediateExtensionMembers3.kt new file mode 100644 index 00000000000..3aa29d76c88 --- /dev/null +++ b/idea/testData/completion/basic/common/ImmediateExtensionMembers3.kt @@ -0,0 +1,17 @@ +fun C.extFunForC(){} +fun D.extFunForD(){} +fun Any.extFunForAny(){} + +open class C { + fun foo() { + if (this is D) { + + } + } +} + +class D : C + +// EXIST: { itemText: "extFunForD", attributes: "bold" } +// EXIST: { itemText: "extFunForC", attributes: "" } +// EXIST: { itemText: "extFunForAny", attributes: "" } diff --git a/idea/testData/completion/basic/common/ImmediateExtensionMembers4.kt b/idea/testData/completion/basic/common/ImmediateExtensionMembers4.kt new file mode 100644 index 00000000000..a82d36cf255 --- /dev/null +++ b/idea/testData/completion/basic/common/ImmediateExtensionMembers4.kt @@ -0,0 +1,17 @@ +fun C.extFunForC(){} +fun T.extFunForT(){} +fun Any.extFunForAny(){} + +open class C { + fun foo() { + if (this is T) { + + } + } +} + +trait T + +// EXIST: { itemText: "extFunForT", attributes: "bold" } +// EXIST: { itemText: "extFunForC", attributes: "bold" } +// EXIST: { itemText: "extFunForAny", attributes: "" } diff --git a/idea/tests/org/jetbrains/jet/completion/JSBasicCompletionTestGenerated.java b/idea/tests/org/jetbrains/jet/completion/JSBasicCompletionTestGenerated.java index 20db843e9da..f2e0a079bdc 100644 --- a/idea/tests/org/jetbrains/jet/completion/JSBasicCompletionTestGenerated.java +++ b/idea/tests/org/jetbrains/jet/completion/JSBasicCompletionTestGenerated.java @@ -304,6 +304,30 @@ public class JSBasicCompletionTestGenerated extends AbstractJSBasicCompletionTes doTest(fileName); } + @TestMetadata("ImmediateExtensionMembers1.kt") + public void testImmediateExtensionMembers1() throws Exception { + String fileName = JetTestUtils.navigationMetadata("idea/testData/completion/basic/common/ImmediateExtensionMembers1.kt"); + doTest(fileName); + } + + @TestMetadata("ImmediateExtensionMembers2.kt") + public void testImmediateExtensionMembers2() throws Exception { + String fileName = JetTestUtils.navigationMetadata("idea/testData/completion/basic/common/ImmediateExtensionMembers2.kt"); + doTest(fileName); + } + + @TestMetadata("ImmediateExtensionMembers3.kt") + public void testImmediateExtensionMembers3() throws Exception { + String fileName = JetTestUtils.navigationMetadata("idea/testData/completion/basic/common/ImmediateExtensionMembers3.kt"); + doTest(fileName); + } + + @TestMetadata("ImmediateExtensionMembers4.kt") + public void testImmediateExtensionMembers4() throws Exception { + String fileName = JetTestUtils.navigationMetadata("idea/testData/completion/basic/common/ImmediateExtensionMembers4.kt"); + doTest(fileName); + } + @TestMetadata("ImmediateMembers1.kt") public void testImmediateMembers1() throws Exception { String fileName = JetTestUtils.navigationMetadata("idea/testData/completion/basic/common/ImmediateMembers1.kt"); diff --git a/idea/tests/org/jetbrains/jet/completion/JvmBasicCompletionTestGenerated.java b/idea/tests/org/jetbrains/jet/completion/JvmBasicCompletionTestGenerated.java index fa3c3093daa..6aa6dd5d8ad 100644 --- a/idea/tests/org/jetbrains/jet/completion/JvmBasicCompletionTestGenerated.java +++ b/idea/tests/org/jetbrains/jet/completion/JvmBasicCompletionTestGenerated.java @@ -304,6 +304,30 @@ public class JvmBasicCompletionTestGenerated extends AbstractJvmBasicCompletionT doTest(fileName); } + @TestMetadata("ImmediateExtensionMembers1.kt") + public void testImmediateExtensionMembers1() throws Exception { + String fileName = JetTestUtils.navigationMetadata("idea/testData/completion/basic/common/ImmediateExtensionMembers1.kt"); + doTest(fileName); + } + + @TestMetadata("ImmediateExtensionMembers2.kt") + public void testImmediateExtensionMembers2() throws Exception { + String fileName = JetTestUtils.navigationMetadata("idea/testData/completion/basic/common/ImmediateExtensionMembers2.kt"); + doTest(fileName); + } + + @TestMetadata("ImmediateExtensionMembers3.kt") + public void testImmediateExtensionMembers3() throws Exception { + String fileName = JetTestUtils.navigationMetadata("idea/testData/completion/basic/common/ImmediateExtensionMembers3.kt"); + doTest(fileName); + } + + @TestMetadata("ImmediateExtensionMembers4.kt") + public void testImmediateExtensionMembers4() throws Exception { + String fileName = JetTestUtils.navigationMetadata("idea/testData/completion/basic/common/ImmediateExtensionMembers4.kt"); + doTest(fileName); + } + @TestMetadata("ImmediateMembers1.kt") public void testImmediateMembers1() throws Exception { String fileName = JetTestUtils.navigationMetadata("idea/testData/completion/basic/common/ImmediateMembers1.kt");