KT-12068 Special completion item for "[]" get-operator access

#KT-12068 Fixed
This commit is contained in:
Valentin Kipyatkov
2016-04-25 18:59:12 +03:00
parent deb75b3f18
commit 40022e8f7a
12 changed files with 131 additions and 0 deletions
@@ -67,6 +67,7 @@ tailrec fun <T : Any> LookupElement.getUserDataDeep(key: Key<T>): T? {
enum class ItemPriority {
SUPER_METHOD_WITH_ARGUMENTS,
FROM_UNRESOLVED_NAME_SUGGESTION,
GET_OPERATOR,
DEFAULT,
IMPLEMENT,
OVERRIDE,
@@ -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<LookupElement>(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)
}
@@ -0,0 +1,11 @@
package p
class C
operator fun C.get(p: Int): Int = 0
fun foo(c: C) {
c.<caret>
}
// EXIST: { lookupString: "[]", itemText: "[]", tailText: "(p: Int) for C in p", typeText: "Int", attributes: "bold" }
@@ -0,0 +1,5 @@
fun some(list: List<String>?) {
list?.<caret>
}
// ABSENT: "[]"
@@ -0,0 +1,5 @@
fun some(list: List<String>) {
list.<caret>
}
// EXIST: { lookupString: "[]", itemText: "[]", tailText: "(index: Int)", typeText: "String", attributes: "bold" }
@@ -0,0 +1,5 @@
fun some(list: List<String>) {
list.<caret>
}
// ELEMENT: "[]"
@@ -0,0 +1,5 @@
fun some(list: List<String>) {
list[<caret>]
}
// ELEMENT: "[]"
+5
View File
@@ -0,0 +1,5 @@
fun some(list: List<String>): String {
return list.<caret>
}
// EXIST: { lookupString: "[]", itemText: "[]", tailText: "(index: Int)", typeText: "String", attributes: "bold" }
@@ -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)
@@ -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)
@@ -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");
@@ -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");