KT-12068 Special completion item for "[]" get-operator access
#KT-12068 Fixed
This commit is contained in:
@@ -67,6 +67,7 @@ tailrec fun <T : Any> LookupElement.getUserDataDeep(key: Key<T>): T? {
|
|||||||
enum class ItemPriority {
|
enum class ItemPriority {
|
||||||
SUPER_METHOD_WITH_ARGUMENTS,
|
SUPER_METHOD_WITH_ARGUMENTS,
|
||||||
FROM_UNRESOLVED_NAME_SUGGESTION,
|
FROM_UNRESOLVED_NAME_SUGGESTION,
|
||||||
|
GET_OPERATOR,
|
||||||
DEFAULT,
|
DEFAULT,
|
||||||
IMPLEMENT,
|
IMPLEMENT,
|
||||||
OVERRIDE,
|
OVERRIDE,
|
||||||
|
|||||||
@@ -16,6 +16,7 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.idea.completion
|
package org.jetbrains.kotlin.idea.completion
|
||||||
|
|
||||||
|
import com.intellij.codeInsight.AutoPopupController
|
||||||
import com.intellij.codeInsight.completion.InsertionContext
|
import com.intellij.codeInsight.completion.InsertionContext
|
||||||
import com.intellij.codeInsight.lookup.LookupElement
|
import com.intellij.codeInsight.lookup.LookupElement
|
||||||
import com.intellij.codeInsight.lookup.LookupElementDecorator
|
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.GenerateLambdaInfo
|
||||||
import org.jetbrains.kotlin.idea.completion.handlers.KotlinFunctionInsertHandler
|
import org.jetbrains.kotlin.idea.completion.handlers.KotlinFunctionInsertHandler
|
||||||
import org.jetbrains.kotlin.idea.completion.handlers.lambdaPresentation
|
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.CallType
|
||||||
import org.jetbrains.kotlin.idea.util.toFuzzyType
|
import org.jetbrains.kotlin.idea.util.toFuzzyType
|
||||||
import org.jetbrains.kotlin.renderer.DescriptorRenderer
|
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.KotlinType
|
||||||
import org.jetbrains.kotlin.types.TypeUtils
|
import org.jetbrains.kotlin.types.TypeUtils
|
||||||
import org.jetbrains.kotlin.types.typeUtil.isSubtypeOf
|
import org.jetbrains.kotlin.types.typeUtil.isSubtypeOf
|
||||||
|
import org.jetbrains.kotlin.util.OperatorNameConventions
|
||||||
import org.jetbrains.kotlin.utils.addIfNotNull
|
import org.jetbrains.kotlin.utils.addIfNotNull
|
||||||
|
|
||||||
interface AbstractLookupElementFactory {
|
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)
|
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: "[]"
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
fun some(list: List<String>): String {
|
||||||
|
return list.<caret>
|
||||||
|
}
|
||||||
|
|
||||||
|
// EXIST: { lookupString: "[]", itemText: "[]", tailText: "(index: Int)", typeText: "String", attributes: "bold" }
|
||||||
+27
@@ -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")
|
@TestMetadata("idea/idea-completion/testData/basic/common/highOrderFunctions")
|
||||||
@TestDataPath("$PROJECT_ROOT")
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
@RunWith(JUnit3RunnerWithInners.class)
|
@RunWith(JUnit3RunnerWithInners.class)
|
||||||
|
|||||||
+27
@@ -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")
|
@TestMetadata("idea/idea-completion/testData/basic/common/highOrderFunctions")
|
||||||
@TestDataPath("$PROJECT_ROOT")
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
@RunWith(JUnit3RunnerWithInners.class)
|
@RunWith(JUnit3RunnerWithInners.class)
|
||||||
|
|||||||
+6
@@ -149,6 +149,12 @@ public class JvmSmartCompletionTestGenerated extends AbstractJvmSmartCompletionT
|
|||||||
doTest(fileName);
|
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")
|
@TestMetadata("GroupBySubstitutor.kt")
|
||||||
public void testGroupBySubstitutor() throws Exception {
|
public void testGroupBySubstitutor() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("idea/idea-completion/testData/smart/GroupBySubstitutor.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("idea/idea-completion/testData/smart/GroupBySubstitutor.kt");
|
||||||
|
|||||||
+6
@@ -119,6 +119,12 @@ public class BasicCompletionHandlerTestGenerated extends AbstractBasicCompletion
|
|||||||
doTest(fileName);
|
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")
|
@TestMetadata("InterfaceNameBeforeRunBug.kt")
|
||||||
public void testInterfaceNameBeforeRunBug() throws Exception {
|
public void testInterfaceNameBeforeRunBug() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("idea/idea-completion/testData/handlers/basic/InterfaceNameBeforeRunBug.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("idea/idea-completion/testData/handlers/basic/InterfaceNameBeforeRunBug.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user