Fixed not working item in completion list for infix call

This commit is contained in:
Valentin Kipyatkov
2015-05-06 19:48:56 +03:00
parent 2adf0a3e9a
commit a036a6435b
6 changed files with 56 additions and 18 deletions
@@ -127,27 +127,35 @@ abstract class CompletionSessionBase(protected val configuration: CompletionSess
protected val referenceVariantsHelper: ReferenceVariantsHelper = ReferenceVariantsHelper(bindingContext) { isVisibleDescriptor(it) } protected val referenceVariantsHelper: ReferenceVariantsHelper = ReferenceVariantsHelper(bindingContext) { isVisibleDescriptor(it) }
protected val receiversData: ReferenceVariantsHelper.ReceiversData? = reference?.let { referenceVariantsHelper.getReferenceVariantsReceivers(it.expression) }
protected val lookupElementFactory: LookupElementFactory = run { protected val lookupElementFactory: LookupElementFactory = run {
val receiverTypes = if (reference != null) { if (receiversData != null) {
val expression = reference.expression
val (receivers, callType) = referenceVariantsHelper.getReferenceVariantsReceivers(expression)
val dataFlowInfo = bindingContext.getDataFlowInfo(expression) val dataFlowInfo = bindingContext.getDataFlowInfo(expression)
var receiverTypes = receivers.flatMap {
var receiverTypes = receiversData.receivers.flatMap {
SmartCastUtils.getSmartCastVariantsWithLessSpecificExcluded(it, bindingContext, moduleDescriptor, dataFlowInfo) SmartCastUtils.getSmartCastVariantsWithLessSpecificExcluded(it, bindingContext, moduleDescriptor, dataFlowInfo)
} }
if (callType == CallType.SAFE) {
if (receiversData.callType == CallType.SAFE) {
receiverTypes = receiverTypes.map { it.makeNotNullable() } receiverTypes = receiverTypes.map { it.makeNotNullable() }
} }
receiverTypes
LookupElementFactory(receiverTypes)
} }
else { else {
listOf() LookupElementFactory(emptyList())
} }
LookupElementFactory(receiverTypes)
} }
protected val collector: LookupElementsCollector = LookupElementsCollector( private val collectorContext = if (expression?.getParent() is JetSimpleNameStringTemplateEntry)
prefixMatcher, parameters, resolutionFacade, lookupElementFactory, inDescriptor, expression?.getParent() is JetSimpleNameStringTemplateEntry) LookupElementsCollector.Context.STRING_TEMPLATE_AFTER_DOLLAR
else if (receiversData?.callType == CallType.INFIX)
LookupElementsCollector.Context.INFIX_CALL
else
LookupElementsCollector.Context.NORMAL
protected val collector: LookupElementsCollector = LookupElementsCollector(prefixMatcher, parameters, resolutionFacade, lookupElementFactory, inDescriptor, collectorContext)
protected val project: Project = position.getProject() protected val project: Project = position.getProject()
@@ -29,6 +29,7 @@ import org.jetbrains.kotlin.idea.caches.resolve.ResolutionFacade
import org.jetbrains.kotlin.idea.completion.handlers.CastReceiverInsertHandler import org.jetbrains.kotlin.idea.completion.handlers.CastReceiverInsertHandler
import org.jetbrains.kotlin.idea.completion.handlers.WithTailInsertHandler import org.jetbrains.kotlin.idea.completion.handlers.WithTailInsertHandler
import org.jetbrains.kotlin.idea.util.FuzzyType import org.jetbrains.kotlin.idea.util.FuzzyType
import org.jetbrains.kotlin.idea.util.fuzzyReturnType
import org.jetbrains.kotlin.idea.util.getImplicitReceiversWithInstance import org.jetbrains.kotlin.idea.util.getImplicitReceiversWithInstance
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.*
@@ -39,8 +39,14 @@ class LookupElementsCollector(
private val resolutionFacade: ResolutionFacade, private val resolutionFacade: ResolutionFacade,
private val lookupElementFactory: LookupElementFactory, private val lookupElementFactory: LookupElementFactory,
private val inDescriptor: DeclarationDescriptor?, private val inDescriptor: DeclarationDescriptor?,
private val surroundCallsWithBraces: Boolean private val context: LookupElementsCollector.Context
) { ) {
public enum class Context {
NORMAL
STRING_TEMPLATE_AFTER_DOLLAR
INFIX_CALL
}
private val elements = ArrayList<LookupElement>() private val elements = ArrayList<LookupElement>()
public fun flushToResultSet(resultSet: CompletionResultSet) { public fun flushToResultSet(resultSet: CompletionResultSet) {
@@ -63,7 +69,7 @@ class LookupElementsCollector(
} }
} }
public fun addDescriptorElements(descriptor: DeclarationDescriptor, suppressAutoInsertion: Boolean, withReceiverCast: Boolean) { private fun addDescriptorElements(descriptor: DeclarationDescriptor, suppressAutoInsertion: Boolean, withReceiverCast: Boolean) {
run { run {
var lookupElement = lookupElementFactory.createLookupElement(resolutionFacade, descriptor, true) var lookupElement = lookupElementFactory.createLookupElement(resolutionFacade, descriptor, true)
@@ -71,7 +77,7 @@ class LookupElementsCollector(
lookupElement = lookupElement.withReceiverCast() lookupElement = lookupElement.withReceiverCast()
} }
if (surroundCallsWithBraces && (descriptor is FunctionDescriptor || descriptor is ClassifierDescriptor)) { if (context == Context.STRING_TEMPLATE_AFTER_DOLLAR && (descriptor is FunctionDescriptor || descriptor is ClassifierDescriptor)) {
lookupElement = lookupElement.withBracesSurrounding() lookupElement = lookupElement.withBracesSurrounding()
} }
@@ -84,7 +90,7 @@ class LookupElementsCollector(
} }
// add special item for function with one argument of function type with more than one parameter // add special item for function with one argument of function type with more than one parameter
if (descriptor is FunctionDescriptor) { if (context != Context.INFIX_CALL && descriptor is FunctionDescriptor) {
val parameters = descriptor.getValueParameters() val parameters = descriptor.getValueParameters()
if (parameters.size() == 1) { if (parameters.size() == 1) {
val parameterType = parameters.get(0).getType() val parameterType = parameters.get(0).getType()
@@ -108,7 +114,7 @@ class LookupElementsCollector(
} }
} }
if (surroundCallsWithBraces) { if (context == Context.STRING_TEMPLATE_AFTER_DOLLAR) {
lookupElement = lookupElement.withBracesSurrounding() lookupElement = lookupElement.withBracesSurrounding()
} }
@@ -121,10 +127,10 @@ class LookupElementsCollector(
if (descriptor is PropertyDescriptor) { if (descriptor is PropertyDescriptor) {
var lookupElement = lookupElementFactory.createBackingFieldLookupElement(descriptor, inDescriptor, resolutionFacade) var lookupElement = lookupElementFactory.createBackingFieldLookupElement(descriptor, inDescriptor, resolutionFacade)
if (lookupElement != null) { if (lookupElement != null) {
if (surroundCallsWithBraces) { if (context == Context.STRING_TEMPLATE_AFTER_DOLLAR) {
lookupElement = lookupElement!!.withBracesSurrounding() lookupElement = lookupElement.withBracesSurrounding()
} }
addElement(lookupElement!!) addElement(lookupElement)
} }
} }
} }
@@ -0,0 +1,11 @@
// checks that no special item "ext1 { String, Int -> ... }" created for infix call
fun Int.ext1(handler: (String, Int) -> Unit){}
fun Int.ext2(c: Char){}
fun foo() {
val pair = 1 ext<caret>
}
// EXIST: ext1
// EXIST: ext2
// NUMBER: 2
@@ -631,6 +631,12 @@ public class JSBasicCompletionTestGenerated extends AbstractJSBasicCompletionTes
doTest(fileName); doTest(fileName);
} }
@TestMetadata("InfixCallNoSpecialLambdaArgumentItem.kt")
public void testInfixCallNoSpecialLambdaArgumentItem() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/InfixCallNoSpecialLambdaArgumentItem.kt");
doTest(fileName);
}
@TestMetadata("InsideAnonymousClass.kt") @TestMetadata("InsideAnonymousClass.kt")
public void testInsideAnonymousClass() throws Exception { public void testInsideAnonymousClass() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/InsideAnonymousClass.kt"); String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/InsideAnonymousClass.kt");
@@ -631,6 +631,12 @@ public class JvmBasicCompletionTestGenerated extends AbstractJvmBasicCompletionT
doTest(fileName); doTest(fileName);
} }
@TestMetadata("InfixCallNoSpecialLambdaArgumentItem.kt")
public void testInfixCallNoSpecialLambdaArgumentItem() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/InfixCallNoSpecialLambdaArgumentItem.kt");
doTest(fileName);
}
@TestMetadata("InsideAnonymousClass.kt") @TestMetadata("InsideAnonymousClass.kt")
public void testInsideAnonymousClass() throws Exception { public void testInsideAnonymousClass() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/InsideAnonymousClass.kt"); String fileName = JetTestUtils.navigationMetadata("idea/idea-completion/testData/basic/common/InsideAnonymousClass.kt");