Parameter name completion: no insertion on just typing

This commit is contained in:
Valentin Kipyatkov
2015-06-17 21:26:57 +03:00
parent c0126b08c3
commit 22ad1389f5
10 changed files with 65 additions and 11 deletions
@@ -351,6 +351,10 @@ class BasicCompletionSession(configuration: CompletionSessionConfiguration,
override fun doComplete() { override fun doComplete() {
assert(parameters.getCompletionType() == CompletionType.BASIC) assert(parameters.getCompletionType() == CompletionType.BASIC)
if (completionKind == CompletionKind.PARAMETER_NAME || completionKind == CompletionKind.ANNOTATION_TYPES_OR_PARAMETER_NAME) {
collector.suppressItemSelectionByCharsOnTyping = true
}
if (completionKind != CompletionKind.NAMED_ARGUMENTS_ONLY) { if (completionKind != CompletionKind.NAMED_ARGUMENTS_ONLY) {
collector.addDescriptorElements(referenceVariants, suppressAutoInsertion = false) collector.addDescriptorElements(referenceVariants, suppressAutoInsertion = false)
@@ -32,7 +32,9 @@ import org.jetbrains.kotlin.psi.psiUtil.prevLeaf
public class KotlinCompletionCharFilter() : CharFilter() { public class KotlinCompletionCharFilter() : CharFilter() {
companion object { companion object {
public val ACCEPT_OPENING_BRACE: Key<Boolean> = Key("KotlinCompletionCharFilter.ACCEPT_OPENNING_BRACE") public val ACCEPT_OPENING_BRACE: Key<Unit> = Key("KotlinCompletionCharFilter.ACCEPT_OPENNING_BRACE")
public val SUPPRESS_ITEM_SELECTION_BY_CHARS_ON_TYPING: Key<Unit> = Key("KotlinCompletionCharFilter.SUPPRESS_ITEM_SELECTION_BY_CHARS_ON_TYPING")
public val JUST_TYPING_PREFIX: Key<String> = Key("KotlinCompletionCharFilter.JUST_TYPING_PREFIX") public val JUST_TYPING_PREFIX: Key<String> = Key("KotlinCompletionCharFilter.JUST_TYPING_PREFIX")
} }
@@ -49,8 +51,11 @@ public class KotlinCompletionCharFilter() : CharFilter() {
return CharFilter.Result.ADD_TO_PREFIX return CharFilter.Result.ADD_TO_PREFIX
} }
// do not accept items by special chars in the very beginning of function literal where name of the first parameter can be val currentItem = lookup.getCurrentItem()
if (isAutopopup && !lookup.isSelectionTouched() && isInFunctionLiteralStart(completionParameters.getPosition())) {
// do not accept items by special chars in some special positions such as in the very beginning of function literal where name of the first parameter can be
if (isAutopopup && !lookup.isSelectionTouched()
&& (currentItem?.getUserData(SUPPRESS_ITEM_SELECTION_BY_CHARS_ON_TYPING) != null || isInFunctionLiteralStart(completionParameters.getPosition()))) {
return Result.HIDE_LOOKUP return Result.HIDE_LOOKUP
} }
@@ -58,7 +63,6 @@ public class KotlinCompletionCharFilter() : CharFilter() {
return CharFilter.Result.ADD_TO_PREFIX return CharFilter.Result.ADD_TO_PREFIX
} }
val currentItem = lookup.getCurrentItem()
if (!lookup.isSelectionTouched()) { if (!lookup.isSelectionTouched()) {
currentItem?.putUserData(JUST_TYPING_PREFIX, lookup.itemPattern(currentItem)) currentItem?.putUserData(JUST_TYPING_PREFIX, lookup.itemPattern(currentItem))
} }
@@ -75,7 +79,7 @@ public class KotlinCompletionCharFilter() : CharFilter() {
} }
'{' -> { '{' -> {
if (currentItem != null && currentItem.getUserData(ACCEPT_OPENING_BRACE) ?: false) if (currentItem != null && currentItem.getUserData(ACCEPT_OPENING_BRACE) != null)
Result.SELECT_ITEM_AND_FINISH_LOOKUP Result.SELECT_ITEM_AND_FINISH_LOOKUP
else else
Result.HIDE_LOOKUP Result.HIDE_LOOKUP
@@ -207,7 +207,7 @@ public class LookupElementFactory(
element = element.withInsertHandler(insertHandler) element = element.withInsertHandler(insertHandler)
if (insertHandler is KotlinFunctionInsertHandler && insertHandler.lambdaInfo != null) { if (insertHandler is KotlinFunctionInsertHandler && insertHandler.lambdaInfo != null) {
element.putUserData<Boolean>(KotlinCompletionCharFilter.ACCEPT_OPENING_BRACE, true) element.putUserData(KotlinCompletionCharFilter.ACCEPT_OPENING_BRACE, Unit)
} }
return element return element
@@ -42,8 +42,8 @@ class LookupElementsCollector(
private val context: LookupElementsCollector.Context private val context: LookupElementsCollector.Context
) { ) {
public enum class Context { public enum class Context {
NORMAL NORMAL,
STRING_TEMPLATE_AFTER_DOLLAR STRING_TEMPLATE_AFTER_DOLLAR,
INFIX_CALL INFIX_CALL
} }
@@ -60,6 +60,8 @@ class LookupElementsCollector(
public var isResultEmpty: Boolean = true public var isResultEmpty: Boolean = true
private set private set
public var suppressItemSelectionByCharsOnTyping: Boolean = false
public fun addDescriptorElements(descriptors: Iterable<DeclarationDescriptor>, public fun addDescriptorElements(descriptors: Iterable<DeclarationDescriptor>,
suppressAutoInsertion: Boolean, // auto-insertion suppression is used for elements that require adding an import suppressAutoInsertion: Boolean, // auto-insertion suppression is used for elements that require adding an import
withReceiverCast: Boolean = false withReceiverCast: Boolean = false
@@ -137,7 +139,7 @@ class LookupElementsCollector(
public fun addElement(element: LookupElement) { public fun addElement(element: LookupElement) {
if (prefixMatcher.prefixMatches(element)) { if (prefixMatcher.prefixMatches(element)) {
elements.add(object: LookupElementDecorator<LookupElement>(element) { val decorated = object : LookupElementDecorator<LookupElement>(element) {
override fun handleInsert(context: InsertionContext) { override fun handleInsert(context: InsertionContext) {
getDelegate().handleInsert(context) getDelegate().handleInsert(context)
@@ -155,7 +157,11 @@ class LookupElementsCollector(
} }
} }
}) }
if (suppressItemSelectionByCharsOnTyping) {
decorated.putUserData(KotlinCompletionCharFilter.SUPPRESS_ITEM_SELECTION_BY_CHARS_ON_TYPING, Unit)
}
elements.add(decorated)
} }
} }
@@ -200,7 +200,7 @@ class TypeInstantiationItems(
lookupElement = lookupElement.keepOldArgumentListOnTab() lookupElement = lookupElement.keepOldArgumentListOnTab()
} }
if (baseInsertHandler.lambdaInfo != null) { if (baseInsertHandler.lambdaInfo != null) {
lookupElement.putUserData(KotlinCompletionCharFilter.ACCEPT_OPENING_BRACE, true) lookupElement.putUserData(KotlinCompletionCharFilter.ACCEPT_OPENING_BRACE, Unit)
} }
lookupElement = lookupElement.assignSmartCompletionPriority(SmartCompletionItemPriority.INSTANTIATION) lookupElement = lookupElement.assignSmartCompletionPriority(SmartCompletionItemPriority.INSTANTIATION)
} }
@@ -0,0 +1,7 @@
class FooBar
fun f(foo<caret>)
// ELEMENT: *
// INVOCATION_COUNT: 0
// CHAR: ':'
@@ -0,0 +1,7 @@
class FooBar
fun f(foo:<caret>)
// ELEMENT: *
// INVOCATION_COUNT: 0
// CHAR: ':'
@@ -0,0 +1,7 @@
class FooBar
fun f(foo<caret>)
// ELEMENT: *
// INVOCATION_COUNT: 0
// CHAR: ' '
@@ -0,0 +1,7 @@
class FooBar
fun f(foo <caret>)
// ELEMENT: *
// INVOCATION_COUNT: 0
// CHAR: ' '
@@ -265,6 +265,18 @@ public class BasicCompletionHandlerTestGenerated extends AbstractBasicCompletion
doTest(fileName); doTest(fileName);
} }
@TestMetadata("NoInsertionOnTypingColon.kt")
public void testNoInsertionOnTypingColon() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/handlers/basic/parameterNameAndType/NoInsertionOnTypingColon.kt");
doTest(fileName);
}
@TestMetadata("NoInsertionOnTypingSpace.kt")
public void testNoInsertionOnTypingSpace() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/handlers/basic/parameterNameAndType/NoInsertionOnTypingSpace.kt");
doTest(fileName);
}
@TestMetadata("Simple.kt") @TestMetadata("Simple.kt")
public void testSimple() throws Exception { public void testSimple() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/handlers/basic/parameterNameAndType/Simple.kt"); String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/handlers/basic/parameterNameAndType/Simple.kt");