Smart completion after "by" and "in": non-imported operators supported

This commit is contained in:
Valentin Kipyatkov
2016-03-24 16:42:05 +03:00
parent cda539d769
commit e8c35e16e0
13 changed files with 122 additions and 24 deletions
@@ -78,7 +78,7 @@ class BasicCompletionSession(
private val smartCompletion = expression?.let {
SmartCompletion(
it, resolutionFacade, bindingContext, moduleDescriptor, isVisibleFilter, prefixMatcher,
it, resolutionFacade, bindingContext, moduleDescriptor, isVisibleFilter, indicesHelper(false), prefixMatcher,
GlobalSearchScope.EMPTY_SCOPE, toFromOriginalFileMapper, callTypeAndReceiver,
isJvmModule, forBasicCompletion = true
)
@@ -82,7 +82,7 @@ private fun needExplicitParameterTypes(context: InsertionContext, placeholderRan
val resolutionFacade = file.getResolutionFacade()
val bindingContext = resolutionFacade.analyze(expression, BodyResolveMode.PARTIAL)
val expectedInfos = ExpectedInfos(bindingContext, resolutionFacade, useHeuristicSignatures = false).calculate(expression)
val expectedInfos = ExpectedInfos(bindingContext, resolutionFacade, indicesHelper = null, useHeuristicSignatures = false).calculate(expression)
val functionTypes = expectedInfos
.mapNotNull { it.fuzzyType?.type }
@@ -55,6 +55,7 @@ class SmartCompletion(
private val bindingContext: BindingContext,
private val moduleDescriptor: ModuleDescriptor,
private val visibilityFilter: (DeclarationDescriptor) -> Boolean,
private val indicesHelper: KotlinIndicesHelper,
private val prefixMatcher: PrefixMatcher,
private val inheritorSearchScope: GlobalSearchScope,
private val toFromOriginalFileMapper: ToFromOriginalFileMapper,
@@ -302,7 +303,7 @@ class SmartCompletion(
// if expected types are too general, try to use expected type from outer calls
var count = 0
while (true) {
val infos = ExpectedInfos(bindingContext, resolutionFacade, useOuterCallsExpectedTypeCount = count)
val infos = ExpectedInfos(bindingContext, resolutionFacade, indicesHelper, useOuterCallsExpectedTypeCount = count)
.calculate(expression)
if (count == 2 /* use two outer calls maximum */ || infos.none { it.fuzzyType?.isAlmostEverything() ?: false }) {
return if (forBasicCompletion)
@@ -59,7 +59,7 @@ class SmartCompletionSession(
private val smartCompletion by lazy(LazyThreadSafetyMode.NONE) {
expression?.let {
SmartCompletion(it, resolutionFacade, bindingContext, moduleDescriptor, isVisibleFilter,
SmartCompletion(it, resolutionFacade, bindingContext, moduleDescriptor, isVisibleFilter, indicesHelper(false),
prefixMatcher, originalSearchScope, toFromOriginalFileMapper,
callTypeAndReceiver, isJvmModule)
}
@@ -192,7 +192,7 @@ class SmartCompletionSession(
override fun getValueArgumentList() = throw UnsupportedOperationException()
}
val expectedInfos = ExpectedInfos(bindingContext, resolutionFacade)
val expectedInfos = ExpectedInfos(bindingContext, resolutionFacade, indicesHelper(false))
.calculateForArgument(dummyCall, dummyArgument)
collector.addElements(LambdaItems.collect(expectedInfos))
}
@@ -0,0 +1,8 @@
package dependency
interface X
interface Y : X
interface Z
operator fun X.contains(s: String): Boolean = true
fun Z.contains(s: String): Boolean = true
@@ -0,0 +1,11 @@
import dependency.X
import dependency.Y
import dependency.Z
fun foo(s: String, x: X, y: Y, z: Z) {
if (s in <caret>)
}
// EXIST: x
// EXIST: y
// ABSENT: z
@@ -0,0 +1,22 @@
package dependency
import kotlin.reflect.KProperty
import main.C
class X1 {
operator fun getValue(thisRef: C, property: KProperty<*>): String = ""
}
class X2 {
operator fun getValue(thisRef: String, property: KProperty<*>): String = ""
}
class X3 {
operator fun getValue(thisRef: Any, property: KProperty<*>): String = ""
}
class Y1
class Y2
class Y3
operator fun Y1.getValue(thisRef: C, property: KProperty<*>): String = ""
operator fun Y2.getValue(thisRef: String, property: KProperty<*>): String = ""
operator fun Y3.getValue(thisRef: Any, property: KProperty<*>): String = ""
@@ -0,0 +1,26 @@
package main
import dependency.X1
import dependency.X2
import dependency.X3
import dependency.Y1
import dependency.Y2
import dependency.Y3
fun createX1() = X1()
fun createX2() = X2()
fun createX3() = X3()
fun createY1() = Y1()
fun createY2() = Y2()
fun createY3() = Y3()
class C {
val property by <caret>
}
// EXIST: createX1
// ABSENT: createX2
// EXIST: createX3
// EXIST: createY1
// ABSENT: createY2
// EXIST: createY3
@@ -137,6 +137,18 @@ public class MultiFileSmartCompletionTestGenerated extends AbstractMultiFileSmar
doTest(fileName);
}
@TestMetadata("NotImportedContains")
public void testNotImportedContains() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/idea-completion/testData/smartMultiFile/NotImportedContains/");
doTest(fileName);
}
@TestMetadata("NotImportedGetValue")
public void testNotImportedGetValue() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/idea-completion/testData/smartMultiFile/NotImportedGetValue/");
doTest(fileName);
}
@TestMetadata("StaticMembers1")
public void testStaticMembers1() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/idea-completion/testData/smartMultiFile/StaticMembers1/");