From 6221de9849b2632e356a2081b66e0f7455a89a55 Mon Sep 17 00:00:00 2001 From: Valentin Kipyatkov Date: Tue, 29 Jul 2014 12:49:17 +0400 Subject: [PATCH] KT-5157 Code completion named parameter items should have lowest priority KT-4157 Auto-popup code completion pre-selects wrong item #KT-5157 Fixed #KT-4157 Fixed --- idea/src/META-INF/plugin.xml | 34 ++++++++++----- .../jet/plugin/completion/CompletionUtils.kt | 43 +++++++++++++++++++ .../completion/JetCompletionContributor.java | 15 ++++++- .../KotlinNamedParametersContributor.kt | 7 +-- .../handlers/WithTailInsertHandler.kt | 2 +- .../plugin/completion/smart/LambdaItems.kt | 3 +- .../jet/plugin/completion/smart/Utils.kt | 9 ---- .../weigher/JetCompletionSorting.kt | 23 ++++++---- .../JetLiveTemplateCompletionContributor.java | 22 +--------- .../completion/weighers/NamedParameters.kt | 4 +- 10 files changed, 103 insertions(+), 59 deletions(-) create mode 100644 idea/src/org/jetbrains/jet/plugin/completion/CompletionUtils.kt diff --git a/idea/src/META-INF/plugin.xml b/idea/src/META-INF/plugin.xml index 02757a03dde..55778994f44 100644 --- a/idea/src/META-INF/plugin.xml +++ b/idea/src/META-INF/plugin.xml @@ -223,23 +223,35 @@ - - - - - - - - + + + + + ("ITEM_PRIORITY_KEY") + +fun LookupElement.assignPriority(priority: ItemPriority): LookupElement { + putUserData(ITEM_PRIORITY_KEY, priority) + return this +} + +fun LookupElement.suppressAutoInsertion() = AutoCompletionPolicy.NEVER_AUTOCOMPLETE.applyPolicy(this) + +val KEEP_OLD_ARGUMENT_LIST_ON_TAB_KEY = Key("KEEP_OLD_ARGUMENT_LIST_ON_TAB_KEY") + +fun LookupElement.keepOldArgumentListOnTab(): LookupElement { + putUserData(KEEP_OLD_ARGUMENT_LIST_ON_TAB_KEY, Unit) + return this +} + diff --git a/idea/src/org/jetbrains/jet/plugin/completion/JetCompletionContributor.java b/idea/src/org/jetbrains/jet/plugin/completion/JetCompletionContributor.java index 1f843a4d9f5..131ae22a455 100644 --- a/idea/src/org/jetbrains/jet/plugin/completion/JetCompletionContributor.java +++ b/idea/src/org/jetbrains/jet/plugin/completion/JetCompletionContributor.java @@ -19,6 +19,7 @@ package org.jetbrains.jet.plugin.completion; import com.intellij.codeInsight.completion.*; import com.intellij.openapi.editor.Document; import com.intellij.openapi.progress.ProcessCanceledException; +import com.intellij.patterns.ElementPattern; import com.intellij.patterns.PlatformPatterns; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiReference; @@ -29,10 +30,18 @@ import org.jetbrains.jet.lang.psi.JetBlockExpression; import org.jetbrains.jet.lang.psi.JetCallExpression; import org.jetbrains.jet.lang.psi.JetExpression; import org.jetbrains.jet.lang.psi.JetFile; +import org.jetbrains.jet.lexer.JetTokens; import org.jetbrains.jet.plugin.completion.smart.SmartCompletion; import org.jetbrains.jet.plugin.references.JetSimpleNameReference; +import static com.intellij.patterns.PsiJavaPatterns.elementType; +import static com.intellij.patterns.PsiJavaPatterns.psiElement; + public class JetCompletionContributor extends CompletionContributor { + private static final ElementPattern AFTER_NUMBER_LITERAL = psiElement().afterLeafSkipping( + psiElement().withText(""), + psiElement().withElementType(elementType().oneOf(JetTokens.FLOAT_LITERAL, JetTokens.INTEGER_LITERAL))); + public JetCompletionContributor() { CompletionProvider provider = new CompletionProvider() { @Override @@ -51,7 +60,11 @@ public class JetCompletionContributor extends CompletionContributor { public static void doSimpleReferenceCompletion(CompletionParameters parameters, CompletionResultSet result) { PsiElement position = parameters.getPosition(); - if (!(position.getContainingFile() instanceof JetFile)) { + if (!(position.getContainingFile() instanceof JetFile)) return; + + if (AFTER_NUMBER_LITERAL.accepts(parameters.getPosition())) { + // First Kotlin completion contributors - stop here will stop all completion + result.stopHere(); return; } diff --git a/idea/src/org/jetbrains/jet/plugin/completion/KotlinNamedParametersContributor.kt b/idea/src/org/jetbrains/jet/plugin/completion/KotlinNamedParametersContributor.kt index 2a94ac109c0..ab1d83a9ae7 100644 --- a/idea/src/org/jetbrains/jet/plugin/completion/KotlinNamedParametersContributor.kt +++ b/idea/src/org/jetbrains/jet/plugin/completion/KotlinNamedParametersContributor.kt @@ -72,7 +72,7 @@ public class KotlinNamedParametersContributor : CompletionContributor() { }) } - fun doParamsCompletion(parameters: CompletionParameters, result: CompletionResultSet) { + private fun doParamsCompletion(parameters: CompletionParameters, result: CompletionResultSet) { val valueArgument = PsiTreeUtil.getParentOfType(parameters.getPosition(), javaClass())!! val callElement = PsiTreeUtil.getParentOfType(valueArgument, javaClass()) @@ -95,13 +95,14 @@ public class KotlinNamedParametersContributor : CompletionContributor() { for (parameter in funDescriptor.getValueParameters()) { val name = parameter.getName().asString() if (result.getPrefixMatcher().prefixMatches(name) && name !in usedArguments) { - val lookupElementBuilder = LookupElementBuilder.create(NamedParameterLookupObject(parameter.getName()), "${name}") + val lookupElement = LookupElementBuilder.create(NamedParameterLookupObject(parameter.getName()), "${name}") .withPresentableText("${name} = ") .withTailText("${DescriptorRenderer.SHORT_NAMES_IN_TYPES.renderType(parameter.getType())}") .withIcon(JetIcons.PARAMETER) .withInsertHandler(NamedParameterInsertHandler) + .assignPriority(ItemPriority.NAMED_PARAMETER) - kotlinResultSet.addElement(lookupElementBuilder) + kotlinResultSet.addElement(lookupElement) } } } diff --git a/idea/src/org/jetbrains/jet/plugin/completion/handlers/WithTailInsertHandler.kt b/idea/src/org/jetbrains/jet/plugin/completion/handlers/WithTailInsertHandler.kt index e0a31a80cb4..1d4f1c3c3b2 100644 --- a/idea/src/org/jetbrains/jet/plugin/completion/handlers/WithTailInsertHandler.kt +++ b/idea/src/org/jetbrains/jet/plugin/completion/handlers/WithTailInsertHandler.kt @@ -22,7 +22,7 @@ import com.intellij.psi.PsiDocumentManager import com.intellij.codeInsight.AutoPopupController import com.intellij.codeInsight.lookup.Lookup import org.jetbrains.jet.plugin.completion.smart.SmartCompletion -import org.jetbrains.jet.plugin.completion.smart.KEEP_OLD_ARGUMENT_LIST_ON_TAB_KEY +import org.jetbrains.jet.plugin.completion.KEEP_OLD_ARGUMENT_LIST_ON_TAB_KEY import com.intellij.openapi.util.TextRange class WithTailInsertHandler(val tailText: String, diff --git a/idea/src/org/jetbrains/jet/plugin/completion/smart/LambdaItems.kt b/idea/src/org/jetbrains/jet/plugin/completion/smart/LambdaItems.kt index c95ee2316bf..94cd6768db5 100644 --- a/idea/src/org/jetbrains/jet/plugin/completion/smart/LambdaItems.kt +++ b/idea/src/org/jetbrains/jet/plugin/completion/smart/LambdaItems.kt @@ -19,13 +19,12 @@ package org.jetbrains.jet.plugin.completion.smart import com.intellij.codeInsight.lookup.LookupElement import com.intellij.codeInsight.lookup.LookupElementBuilder import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns -import org.jetbrains.jet.plugin.completion.handlers.functionParameterTypes -import org.jetbrains.jet.renderer.DescriptorRenderer import org.jetbrains.jet.plugin.completion.handlers.insertLambdaTemplate import com.intellij.openapi.util.TextRange import org.jetbrains.jet.plugin.completion.JetCompletionCharFilter import org.jetbrains.jet.plugin.completion.ExpectedInfo import org.jetbrains.jet.plugin.completion.handlers.buildLambdaPresentation +import org.jetbrains.jet.plugin.completion.suppressAutoInsertion object LambdaItems { public fun addToCollection(collection: MutableCollection, functionExpectedInfos: Collection) { 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 7bbdfc3e8a2..d3ff189b1de 100644 --- a/idea/src/org/jetbrains/jet/plugin/completion/smart/Utils.kt +++ b/idea/src/org/jetbrains/jet/plugin/completion/smart/Utils.kt @@ -90,15 +90,6 @@ fun LookupElement.addTail(tail: Tail?): LookupElement { fun LookupElement.addTail(matchedExpectedInfos: Collection): LookupElement = addTail(mergeTails(matchedExpectedInfos.map { it.tail })) -fun LookupElement.suppressAutoInsertion() = AutoCompletionPolicy.NEVER_AUTOCOMPLETE.applyPolicy(this) - -val KEEP_OLD_ARGUMENT_LIST_ON_TAB_KEY = Key("KEEP_OLD_ARGUMENT_LIST_ON_TAB_KEY") - -fun LookupElement.keepOldArgumentListOnTab(): LookupElement { - putUserData(KEEP_OLD_ARGUMENT_LIST_ON_TAB_KEY, Unit) - return this -} - enum class ExpectedInfoClassification { MATCHES MAKE_NOT_NULLABLE diff --git a/idea/src/org/jetbrains/jet/plugin/completion/weigher/JetCompletionSorting.kt b/idea/src/org/jetbrains/jet/plugin/completion/weigher/JetCompletionSorting.kt index 3e4622fe8e9..9dfdf7a68f4 100644 --- a/idea/src/org/jetbrains/jet/plugin/completion/weigher/JetCompletionSorting.kt +++ b/idea/src/org/jetbrains/jet/plugin/completion/weigher/JetCompletionSorting.kt @@ -23,25 +23,30 @@ import org.jetbrains.jet.lang.psi.JetFile import com.intellij.codeInsight.lookup.LookupElementWeigher import com.intellij.codeInsight.lookup.LookupElement import com.intellij.codeInsight.lookup.WeighingContext +import org.jetbrains.jet.plugin.completion.* public fun CompletionResultSet.addJetSorting(parameters: CompletionParameters): CompletionResultSet { var sorter = CompletionSorter.defaultSorter(parameters, getPrefixMatcher())!! - sorter = sorter.weighBefore("stats", JetKindWeigher()) + object PriorityWeigher : LookupElementWeigher("priority", false, false) { + override fun weigh(element: LookupElement, context: WeighingContext) + = (element.getUserData(ITEM_PRIORITY_KEY) ?: ItemPriority.DEFAULT).ordinal() + } + + sorter = sorter.weighBefore("stats", PriorityWeigher, JetKindWeigher()) sorter = sorter.weighAfter( "stats", JetDeclarationRemotenessWeigher(parameters.getOriginalFile() as JetFile), JetAccessibleWeigher()) - sorter = sorter.weighBefore("middleMatching", PreferMatchingItemWeigher()) + object PreferMatchingItemWeigher : LookupElementWeigher("preferMatching", false, true) { + override fun weigh(element: LookupElement, context: WeighingContext): Comparable { + val prefix = context.itemPattern(element) + return if (element.getLookupString() == prefix) 0 else 1 + } + } + sorter = sorter.weighBefore("middleMatching", PreferMatchingItemWeigher) return withRelevanceSorter(sorter) } - -class PreferMatchingItemWeigher : LookupElementWeigher("preferMatching", false, true) { - override fun weigh(element: LookupElement, context: WeighingContext): Comparable { - val prefix = context.itemPattern(element) - return if (element.getLookupString() == prefix) 0 else 1 - } -} diff --git a/idea/src/org/jetbrains/jet/plugin/liveTemplates/JetLiveTemplateCompletionContributor.java b/idea/src/org/jetbrains/jet/plugin/liveTemplates/JetLiveTemplateCompletionContributor.java index 7e887d674b1..836ba09cf1d 100644 --- a/idea/src/org/jetbrains/jet/plugin/liveTemplates/JetLiveTemplateCompletionContributor.java +++ b/idea/src/org/jetbrains/jet/plugin/liveTemplates/JetLiveTemplateCompletionContributor.java @@ -21,45 +21,25 @@ import com.intellij.codeInsight.lookup.LookupElement; import com.intellij.codeInsight.template.TemplateContextType; import com.intellij.codeInsight.template.impl.*; import com.intellij.openapi.util.Ref; -import com.intellij.patterns.ElementPattern; import com.intellij.patterns.PlatformPatterns; -import com.intellij.psi.JavaTokenType; -import com.intellij.psi.PsiElement; import com.intellij.psi.PsiFile; import com.intellij.util.Consumer; import com.intellij.util.ProcessingContext; import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.NotNull; -import org.jetbrains.jet.lexer.JetToken; -import org.jetbrains.jet.lexer.JetTokens; import java.util.ArrayList; import java.util.List; import java.util.Set; -import static com.intellij.patterns.PsiJavaPatterns.elementType; -import static com.intellij.patterns.PsiJavaPatterns.psiElement; - public class JetLiveTemplateCompletionContributor extends CompletionContributor { - private static final ElementPattern AFTER_NUMBER_LITERAL = psiElement().afterLeafSkipping( - psiElement().withText(""), - psiElement().withElementType(elementType().oneOf(JetTokens.FLOAT_LITERAL, JetTokens.INTEGER_LITERAL))); - public JetLiveTemplateCompletionContributor() { extend(CompletionType.BASIC, PlatformPatterns.psiElement(), new CompletionProvider() { @Override protected void addCompletions(@NotNull CompletionParameters parameters, ProcessingContext context, @NotNull final CompletionResultSet result) { - if (AFTER_NUMBER_LITERAL.accepts(parameters.getPosition())) { - // First Kotlin completion contributors - stop here will stop all completion - result.stopHere(); - return; - } - - if (parameters.getInvocationCount() == 0) { - return; - } + if (parameters.getInvocationCount() == 0) return; PsiFile file = parameters.getPosition().getContainingFile(); int offset = parameters.getOffset(); diff --git a/idea/testData/completion/weighers/NamedParameters.kt b/idea/testData/completion/weighers/NamedParameters.kt index 815a2704cb1..4d6654a16bb 100644 --- a/idea/testData/completion/weighers/NamedParameters.kt +++ b/idea/testData/completion/weighers/NamedParameters.kt @@ -16,7 +16,7 @@ fun test(listParam: Int) { // ORDER: listParam // ORDER: listThisFileVal // ORDER: listImportedVal +// ORDER: listThisFileFun +// ORDER: listImportedFun // ORDER: listMatch // ORDER: listNew -// ORDER: listThisFileFun -// ORDER: listImportedFun \ No newline at end of file