From 40022e8f7a799cbb374bc1c2acdf8b08e9fac3ad Mon Sep 17 00:00:00 2001 From: Valentin Kipyatkov Date: Mon, 25 Apr 2016 18:59:12 +0300 Subject: [PATCH] KT-12068 Special completion item for "[]" get-operator access #KT-12068 Fixed --- .../kotlin/idea/completion/CompletionUtils.kt | 1 + .../idea/completion/LookupElementFactory.kt | 28 +++++++++++++++++++ .../basic/common/getOperator/Extension.kt | 11 ++++++++ .../common/getOperator/NotForSafeCall.kt | 5 ++++ .../basic/common/getOperator/Simple.kt | 5 ++++ .../testData/handlers/basic/GetOperator.kt | 5 ++++ .../handlers/basic/GetOperator.kt.after | 5 ++++ .../testData/smart/GetOperator.kt | 5 ++++ .../test/JSBasicCompletionTestGenerated.java | 27 ++++++++++++++++++ .../test/JvmBasicCompletionTestGenerated.java | 27 ++++++++++++++++++ .../test/JvmSmartCompletionTestGenerated.java | 6 ++++ .../BasicCompletionHandlerTestGenerated.java | 6 ++++ 12 files changed, 131 insertions(+) create mode 100644 idea/idea-completion/testData/basic/common/getOperator/Extension.kt create mode 100644 idea/idea-completion/testData/basic/common/getOperator/NotForSafeCall.kt create mode 100644 idea/idea-completion/testData/basic/common/getOperator/Simple.kt create mode 100644 idea/idea-completion/testData/handlers/basic/GetOperator.kt create mode 100644 idea/idea-completion/testData/handlers/basic/GetOperator.kt.after create mode 100644 idea/idea-completion/testData/smart/GetOperator.kt diff --git a/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/CompletionUtils.kt b/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/CompletionUtils.kt index 506ee65a17f..7db88c67024 100644 --- a/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/CompletionUtils.kt +++ b/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/CompletionUtils.kt @@ -67,6 +67,7 @@ tailrec fun LookupElement.getUserDataDeep(key: Key): T? { enum class ItemPriority { SUPER_METHOD_WITH_ARGUMENTS, FROM_UNRESOLVED_NAME_SUGGESTION, + GET_OPERATOR, DEFAULT, IMPLEMENT, OVERRIDE, diff --git a/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/LookupElementFactory.kt b/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/LookupElementFactory.kt index baaa030b27a..a22336f9ac8 100644 --- a/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/LookupElementFactory.kt +++ b/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/LookupElementFactory.kt @@ -16,6 +16,7 @@ package org.jetbrains.kotlin.idea.completion +import com.intellij.codeInsight.AutoPopupController import com.intellij.codeInsight.completion.InsertionContext import com.intellij.codeInsight.lookup.LookupElement import com.intellij.codeInsight.lookup.LookupElementDecorator @@ -27,6 +28,7 @@ import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.idea.completion.handlers.GenerateLambdaInfo import org.jetbrains.kotlin.idea.completion.handlers.KotlinFunctionInsertHandler import org.jetbrains.kotlin.idea.completion.handlers.lambdaPresentation +import org.jetbrains.kotlin.idea.core.moveCaret import org.jetbrains.kotlin.idea.util.CallType import org.jetbrains.kotlin.idea.util.toFuzzyType import org.jetbrains.kotlin.renderer.DescriptorRenderer @@ -42,6 +44,7 @@ import org.jetbrains.kotlin.synthetic.SyntheticJavaPropertyDescriptor import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.TypeUtils import org.jetbrains.kotlin.types.typeUtil.isSubtypeOf +import org.jetbrains.kotlin.util.OperatorNameConventions import org.jetbrains.kotlin.utils.addIfNotNull interface AbstractLookupElementFactory { @@ -100,6 +103,31 @@ class LookupElementFactory( } } + // special "[]" item for get-operator + if (callType == CallType.DOT && descriptor is FunctionDescriptor && descriptor.isOperator() && descriptor.name == OperatorNameConventions.GET) { + val baseLookupElement = createLookupElement(descriptor, useReceiverTypes) + val lookupElement = object : LookupElementDecorator(baseLookupElement) { + override fun getLookupString() = "[]" + override fun getAllLookupStrings() = setOf(lookupString) + + override fun renderElement(presentation: LookupElementPresentation) { + super.renderElement(presentation) + presentation.itemText = lookupString + } + + override fun handleInsert(context: InsertionContext) { + val startOffset = context.startOffset + assert(context.document.charsSequence[startOffset - 1] == '.') + context.document.deleteString(startOffset - 1, startOffset) + context.editor.moveCaret(startOffset) + + AutoPopupController.getInstance(context.project)?.autoPopupParameterInfo(context.editor, null) + } + } + lookupElement.assignPriority(ItemPriority.GET_OPERATOR) + result.add(lookupElement) + } + return result.map(standardLookupElementsPostProcessor) } diff --git a/idea/idea-completion/testData/basic/common/getOperator/Extension.kt b/idea/idea-completion/testData/basic/common/getOperator/Extension.kt new file mode 100644 index 00000000000..cdbad3cdd50 --- /dev/null +++ b/idea/idea-completion/testData/basic/common/getOperator/Extension.kt @@ -0,0 +1,11 @@ +package p + +class C + +operator fun C.get(p: Int): Int = 0 + +fun foo(c: C) { + c. +} + +// EXIST: { lookupString: "[]", itemText: "[]", tailText: "(p: Int) for C in p", typeText: "Int", attributes: "bold" } diff --git a/idea/idea-completion/testData/basic/common/getOperator/NotForSafeCall.kt b/idea/idea-completion/testData/basic/common/getOperator/NotForSafeCall.kt new file mode 100644 index 00000000000..2ea65531e39 --- /dev/null +++ b/idea/idea-completion/testData/basic/common/getOperator/NotForSafeCall.kt @@ -0,0 +1,5 @@ +fun some(list: List?) { + list?. +} + +// ABSENT: "[]" diff --git a/idea/idea-completion/testData/basic/common/getOperator/Simple.kt b/idea/idea-completion/testData/basic/common/getOperator/Simple.kt new file mode 100644 index 00000000000..995d05f6991 --- /dev/null +++ b/idea/idea-completion/testData/basic/common/getOperator/Simple.kt @@ -0,0 +1,5 @@ +fun some(list: List) { + list. +} + +// EXIST: { lookupString: "[]", itemText: "[]", tailText: "(index: Int)", typeText: "String", attributes: "bold" } diff --git a/idea/idea-completion/testData/handlers/basic/GetOperator.kt b/idea/idea-completion/testData/handlers/basic/GetOperator.kt new file mode 100644 index 00000000000..9a31855cb43 --- /dev/null +++ b/idea/idea-completion/testData/handlers/basic/GetOperator.kt @@ -0,0 +1,5 @@ +fun some(list: List) { + list. +} + +// ELEMENT: "[]" \ No newline at end of file diff --git a/idea/idea-completion/testData/handlers/basic/GetOperator.kt.after b/idea/idea-completion/testData/handlers/basic/GetOperator.kt.after new file mode 100644 index 00000000000..2bd5c382d0f --- /dev/null +++ b/idea/idea-completion/testData/handlers/basic/GetOperator.kt.after @@ -0,0 +1,5 @@ +fun some(list: List) { + list[] +} + +// ELEMENT: "[]" \ No newline at end of file diff --git a/idea/idea-completion/testData/smart/GetOperator.kt b/idea/idea-completion/testData/smart/GetOperator.kt new file mode 100644 index 00000000000..1d1e9665dcd --- /dev/null +++ b/idea/idea-completion/testData/smart/GetOperator.kt @@ -0,0 +1,5 @@ +fun some(list: List): String { + return list. +} + +// EXIST: { lookupString: "[]", itemText: "[]", tailText: "(index: Int)", typeText: "String", attributes: "bold" } diff --git a/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/JSBasicCompletionTestGenerated.java b/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/JSBasicCompletionTestGenerated.java index 2f7f765f740..9e856fbea74 100644 --- a/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/JSBasicCompletionTestGenerated.java +++ b/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/JSBasicCompletionTestGenerated.java @@ -1519,6 +1519,33 @@ public class JSBasicCompletionTestGenerated extends AbstractJSBasicCompletionTes } } + @TestMetadata("idea/idea-completion/testData/basic/common/getOperator") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class GetOperator extends AbstractJSBasicCompletionTest { + public void testAllFilesPresentInGetOperator() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/idea-completion/testData/basic/common/getOperator"), Pattern.compile("^(.+)\\.kt$"), true); + } + + @TestMetadata("Extension.kt") + public void testExtension() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/getOperator/Extension.kt"); + doTest(fileName); + } + + @TestMetadata("NotForSafeCall.kt") + public void testNotForSafeCall() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/getOperator/NotForSafeCall.kt"); + doTest(fileName); + } + + @TestMetadata("Simple.kt") + public void testSimple() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/getOperator/Simple.kt"); + doTest(fileName); + } + } + @TestMetadata("idea/idea-completion/testData/basic/common/highOrderFunctions") @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class) diff --git a/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/JvmBasicCompletionTestGenerated.java b/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/JvmBasicCompletionTestGenerated.java index e263a8325cb..e5ab8cf7efa 100644 --- a/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/JvmBasicCompletionTestGenerated.java +++ b/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/JvmBasicCompletionTestGenerated.java @@ -1519,6 +1519,33 @@ public class JvmBasicCompletionTestGenerated extends AbstractJvmBasicCompletionT } } + @TestMetadata("idea/idea-completion/testData/basic/common/getOperator") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class GetOperator extends AbstractJvmBasicCompletionTest { + public void testAllFilesPresentInGetOperator() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/idea-completion/testData/basic/common/getOperator"), Pattern.compile("^(.+)\\.kt$"), true); + } + + @TestMetadata("Extension.kt") + public void testExtension() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/getOperator/Extension.kt"); + doTest(fileName); + } + + @TestMetadata("NotForSafeCall.kt") + public void testNotForSafeCall() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/getOperator/NotForSafeCall.kt"); + doTest(fileName); + } + + @TestMetadata("Simple.kt") + public void testSimple() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/getOperator/Simple.kt"); + doTest(fileName); + } + } + @TestMetadata("idea/idea-completion/testData/basic/common/highOrderFunctions") @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class) diff --git a/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/JvmSmartCompletionTestGenerated.java b/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/JvmSmartCompletionTestGenerated.java index 9b261d0db4d..d2b3a05bc2a 100644 --- a/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/JvmSmartCompletionTestGenerated.java +++ b/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/JvmSmartCompletionTestGenerated.java @@ -149,6 +149,12 @@ public class JvmSmartCompletionTestGenerated extends AbstractJvmSmartCompletionT doTest(fileName); } + @TestMetadata("GetOperator.kt") + public void testGetOperator() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/idea-completion/testData/smart/GetOperator.kt"); + doTest(fileName); + } + @TestMetadata("GroupBySubstitutor.kt") public void testGroupBySubstitutor() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("idea/idea-completion/testData/smart/GroupBySubstitutor.kt"); diff --git a/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/handlers/BasicCompletionHandlerTestGenerated.java b/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/handlers/BasicCompletionHandlerTestGenerated.java index 65a448eb412..86ee21ba160 100644 --- a/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/handlers/BasicCompletionHandlerTestGenerated.java +++ b/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/handlers/BasicCompletionHandlerTestGenerated.java @@ -119,6 +119,12 @@ public class BasicCompletionHandlerTestGenerated extends AbstractBasicCompletion doTest(fileName); } + @TestMetadata("GetOperator.kt") + public void testGetOperator() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/idea-completion/testData/handlers/basic/GetOperator.kt"); + doTest(fileName); + } + @TestMetadata("InterfaceNameBeforeRunBug.kt") public void testInterfaceNameBeforeRunBug() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("idea/idea-completion/testData/handlers/basic/InterfaceNameBeforeRunBug.kt");