KT-36860 Collect extensions from object on first completion

- This should not affect the performance of the completion, since all
object extensions are collected on the last step, when all main variants
are already collected
- Add more tests
- Also, disable completion of extensions from objects as callable
references (^KT-37395 Fixed)
- ^KT-36860 Fixed
This commit is contained in:
Roman Golyshev
2020-03-10 13:53:42 +03:00
committed by Roman Golyshev
parent 7dc9a2fc64
commit 90750483ee
30 changed files with 85 additions and 27 deletions
@@ -36,6 +36,7 @@ import org.jetbrains.kotlin.idea.project.TargetPlatformDetector
import org.jetbrains.kotlin.idea.references.KtSimpleNameReference.ShorteningMode.FORCED_SHORTENING
import org.jetbrains.kotlin.idea.references.mainReference
import org.jetbrains.kotlin.idea.stubindex.PackageIndexUtil
import org.jetbrains.kotlin.idea.util.CallType
import org.jetbrains.kotlin.idea.util.CallTypeAndReceiver
import org.jetbrains.kotlin.idea.util.getResolutionScope
import org.jetbrains.kotlin.lexer.KtTokens
@@ -332,8 +333,14 @@ class BasicCompletionSession(
}
}
if (configuration.staticMembers && prefix.isNotEmpty()) {
if (!receiverTypes.isNullOrEmpty()) {
if (!receiverTypes.isNullOrEmpty()) {
// N.B.: callable references to member extensions are forbidden
val shouldCompleteExtensionsFromObjects = when (callTypeAndReceiver.callType) {
CallType.DEFAULT, CallType.DOT, CallType.SAFE, CallType.INFIX -> true
else -> false
}
if (shouldCompleteExtensionsFromObjects) {
staticMembersCompletion.completeObjectMemberExtensionsFromIndices(
indicesHelper(false),
receiverTypes.map { it.type },
@@ -341,7 +348,9 @@ class BasicCompletionSession(
collector
)
}
}
if (configuration.staticMembers && prefix.isNotEmpty()) {
if (callTypeAndReceiver is CallTypeAndReceiver.DEFAULT) {
staticMembersCompletion.completeFromIndices(indicesHelper(false), collector)
}
@@ -11,6 +11,5 @@ fun usage(t: T) {
t.foo<caret>
}
// INVOCATION_COUNT: 2
// EXIST: { lookupString: "fooExtension", itemText: "fooExtension" }
// EXIST: { lookupString: "fooProperty", itemText: "fooProperty" }
@@ -0,0 +1,13 @@
class T
class A {
companion object {
infix fun T.fooExtension(i: Int) {}
}
}
fun usage(t: T) {
t foo<caret>
}
// EXIST: { lookupString: "fooExtension", itemText: "fooExtension" }
@@ -0,0 +1,15 @@
class T
class A {
companion object {
fun T.fooExtension() {}
val T.fooProperty get() = 10
}
}
fun usage(t: T) {
t.<caret>
}
// EXIST: { lookupString: "fooExtension", itemText: "fooExtension" }
// EXIST: { lookupString: "fooProperty", itemText: "fooProperty" }
@@ -0,0 +1,15 @@
class T
class A {
companion object {
fun T.fooExtension() {}
val T.fooProperty get() = 10
}
}
fun usage(t: T) {
t?.foo<caret>
}
// EXIST: { lookupString: "fooExtension", itemText: "fooExtension" }
// EXIST: { lookupString: "fooProperty", itemText: "fooProperty" }
@@ -11,6 +11,5 @@ fun T.usage() {
foo<caret>
}
// INVOCATION_COUNT: 2
// EXIST: { lookupString: "fooExtension", itemText: "fooExtension" }
// EXIST: { lookupString: "fooProperty", itemText: "fooProperty" }
@@ -21,7 +21,6 @@ fun usage(b: B) {
b.foo<caret>
}
// INVOCATION_COUNT: 2
// EXIST: { lookupString: "fooForAny", itemText: "fooForAny" }
// EXIST: { lookupString: "fooForT", itemText: "fooForT" }
@@ -21,7 +21,6 @@ fun B.usage() {
foo<caret>
}
// INVOCATION_COUNT: 2
// EXIST: { lookupString: "fooForAny", itemText: "fooForAny" }
// EXIST: { lookupString: "fooForT", itemText: "fooForT" }
@@ -30,7 +29,7 @@ fun B.usage() {
// EXIST: { lookupString: "fooForTGeneric", itemText: "fooForTGeneric" }
// EXIST: { lookupString: "fooForBGeneric", itemText: "fooForBGeneric" }
// EXIST: fooNoReceiver
// ABSENT: fooNoReceiver
// ABSENT: fooForC
// ABSENT: fooForCGeneric
@@ -17,7 +17,6 @@ class A {
}
}
// INVOCATION_COUNT: 2
// EXIST: { lookupString: "fooForA", itemText: "fooForA" }
// EXIST: { lookupString: "fooForB", itemText: "fooForB" }
// EXIST: { lookupString: "fooForT", itemText: "fooForT" }
@@ -9,6 +9,5 @@ fun usage(t: T) {
t.foo<caret>
}
// INVOCATION_COUNT: 2
// EXIST: { lookupString: "fooExtension", itemText: "fooExtension" }
// EXIST: { lookupString: "fooProperty", itemText: "fooProperty" }
@@ -9,6 +9,5 @@ fun T.usage() {
foo<caret>
}
// INVOCATION_COUNT: 2
// EXIST: { lookupString: "fooExtension", itemText: "fooExtension" }
// EXIST: { lookupString: "fooProperty", itemText: "fooProperty" }
@@ -14,6 +14,5 @@ fun T.usage() {
foo<caret>
}
// INVOCATION_COUNT: 2
// EXIST: { lookupString: "fooExtension", itemText: "fooExtension" }
// EXIST: { lookupString: "fooProperty", itemText: "fooProperty" }
@@ -8,5 +8,4 @@ fun usage(t: T) {
t.f<caret>
}
// INVOCATION_COUNT: 2
// ELEMENT: foo
@@ -10,5 +10,4 @@ fun usage(t: T) {
t.foo()<caret>
}
// INVOCATION_COUNT: 2
// ELEMENT: foo
@@ -8,5 +8,4 @@ fun T.usage() {
f<caret>
}
// INVOCATION_COUNT: 2
// ELEMENT: foo
@@ -10,5 +10,4 @@ fun T.usage() {
foo()<caret>
}
// INVOCATION_COUNT: 2
// ELEMENT: foo
@@ -12,5 +12,4 @@ fun usage(t: T) {
t.f<caret>
}
// INVOCATION_COUNT: 2
// ELEMENT: foo
@@ -14,5 +14,4 @@ fun usage(t: T) {
t.foo()<caret>
}
// INVOCATION_COUNT: 2
// ELEMENT: foo
@@ -12,5 +12,4 @@ fun T.usage() {
f<caret>
}
// INVOCATION_COUNT: 2
// ELEMENT: foo
@@ -14,5 +14,4 @@ fun T.usage() {
foo()<caret>
}
// INVOCATION_COUNT: 2
// ELEMENT: foo
@@ -10,5 +10,4 @@ fun usage(t: T) {
t.f<caret>
}
// INVOCATION_COUNT: 2
// ELEMENT: foo
@@ -12,5 +12,4 @@ fun usage(t: T) {
t.foo()<caret>
}
// INVOCATION_COUNT: 2
// ELEMENT: foo
@@ -10,5 +10,4 @@ fun T.usage() {
f<caret>
}
// INVOCATION_COUNT: 2
// ELEMENT: foo
@@ -12,5 +12,4 @@ fun T.usage() {
foo()<caret>
}
// INVOCATION_COUNT: 2
// ELEMENT: foo
@@ -8,5 +8,4 @@ fun usage(t: T) {
t.f<caret>
}
// INVOCATION_COUNT: 2
// ELEMENT: foo
@@ -10,5 +10,4 @@ fun usage(t: T) {
t.foo()<caret>
}
// INVOCATION_COUNT: 2
// ELEMENT: foo
@@ -8,5 +8,4 @@ fun T.usage() {
f<caret>
}
// INVOCATION_COUNT: 2
// ELEMENT: foo
@@ -10,5 +10,4 @@ fun T.usage() {
foo()<caret>
}
// INVOCATION_COUNT: 2
// ELEMENT: foo
@@ -1255,6 +1255,21 @@ public class JSBasicCompletionTestGenerated extends AbstractJSBasicCompletionTes
runTest("idea/idea-completion/testData/basic/common/extensionMethodInObject/CompanionObjectExplicitReceiver.kt");
}
@TestMetadata("CompanionObjectExplicitReceiverInfixExtension.kt")
public void testCompanionObjectExplicitReceiverInfixExtension() throws Exception {
runTest("idea/idea-completion/testData/basic/common/extensionMethodInObject/CompanionObjectExplicitReceiverInfixExtension.kt");
}
@TestMetadata("CompanionObjectExplicitReceiverNoPrefix.kt")
public void testCompanionObjectExplicitReceiverNoPrefix() throws Exception {
runTest("idea/idea-completion/testData/basic/common/extensionMethodInObject/CompanionObjectExplicitReceiverNoPrefix.kt");
}
@TestMetadata("CompanionObjectExplicitReceiverSafeAccess.kt")
public void testCompanionObjectExplicitReceiverSafeAccess() throws Exception {
runTest("idea/idea-completion/testData/basic/common/extensionMethodInObject/CompanionObjectExplicitReceiverSafeAccess.kt");
}
@TestMetadata("CompanionObjectImplicitReceiver.kt")
public void testCompanionObjectImplicitReceiver() throws Exception {
runTest("idea/idea-completion/testData/basic/common/extensionMethodInObject/CompanionObjectImplicitReceiver.kt");
@@ -1255,6 +1255,21 @@ public class JvmBasicCompletionTestGenerated extends AbstractJvmBasicCompletionT
runTest("idea/idea-completion/testData/basic/common/extensionMethodInObject/CompanionObjectExplicitReceiver.kt");
}
@TestMetadata("CompanionObjectExplicitReceiverInfixExtension.kt")
public void testCompanionObjectExplicitReceiverInfixExtension() throws Exception {
runTest("idea/idea-completion/testData/basic/common/extensionMethodInObject/CompanionObjectExplicitReceiverInfixExtension.kt");
}
@TestMetadata("CompanionObjectExplicitReceiverNoPrefix.kt")
public void testCompanionObjectExplicitReceiverNoPrefix() throws Exception {
runTest("idea/idea-completion/testData/basic/common/extensionMethodInObject/CompanionObjectExplicitReceiverNoPrefix.kt");
}
@TestMetadata("CompanionObjectExplicitReceiverSafeAccess.kt")
public void testCompanionObjectExplicitReceiverSafeAccess() throws Exception {
runTest("idea/idea-completion/testData/basic/common/extensionMethodInObject/CompanionObjectExplicitReceiverSafeAccess.kt");
}
@TestMetadata("CompanionObjectImplicitReceiver.kt")
public void testCompanionObjectImplicitReceiver() throws Exception {
runTest("idea/idea-completion/testData/basic/common/extensionMethodInObject/CompanionObjectImplicitReceiver.kt");