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:
committed by
Roman Golyshev
parent
7dc9a2fc64
commit
90750483ee
+11
-2
@@ -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.KtSimpleNameReference.ShorteningMode.FORCED_SHORTENING
|
||||||
import org.jetbrains.kotlin.idea.references.mainReference
|
import org.jetbrains.kotlin.idea.references.mainReference
|
||||||
import org.jetbrains.kotlin.idea.stubindex.PackageIndexUtil
|
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.CallTypeAndReceiver
|
||||||
import org.jetbrains.kotlin.idea.util.getResolutionScope
|
import org.jetbrains.kotlin.idea.util.getResolutionScope
|
||||||
import org.jetbrains.kotlin.lexer.KtTokens
|
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(
|
staticMembersCompletion.completeObjectMemberExtensionsFromIndices(
|
||||||
indicesHelper(false),
|
indicesHelper(false),
|
||||||
receiverTypes.map { it.type },
|
receiverTypes.map { it.type },
|
||||||
@@ -341,7 +348,9 @@ class BasicCompletionSession(
|
|||||||
collector
|
collector
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (configuration.staticMembers && prefix.isNotEmpty()) {
|
||||||
if (callTypeAndReceiver is CallTypeAndReceiver.DEFAULT) {
|
if (callTypeAndReceiver is CallTypeAndReceiver.DEFAULT) {
|
||||||
staticMembersCompletion.completeFromIndices(indicesHelper(false), collector)
|
staticMembersCompletion.completeFromIndices(indicesHelper(false), collector)
|
||||||
}
|
}
|
||||||
|
|||||||
-1
@@ -11,6 +11,5 @@ fun usage(t: T) {
|
|||||||
t.foo<caret>
|
t.foo<caret>
|
||||||
}
|
}
|
||||||
|
|
||||||
// INVOCATION_COUNT: 2
|
|
||||||
// EXIST: { lookupString: "fooExtension", itemText: "fooExtension" }
|
// EXIST: { lookupString: "fooExtension", itemText: "fooExtension" }
|
||||||
// EXIST: { lookupString: "fooProperty", itemText: "fooProperty" }
|
// EXIST: { lookupString: "fooProperty", itemText: "fooProperty" }
|
||||||
+13
@@ -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" }
|
||||||
+15
@@ -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" }
|
||||||
+15
@@ -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" }
|
||||||
-1
@@ -11,6 +11,5 @@ fun T.usage() {
|
|||||||
foo<caret>
|
foo<caret>
|
||||||
}
|
}
|
||||||
|
|
||||||
// INVOCATION_COUNT: 2
|
|
||||||
// EXIST: { lookupString: "fooExtension", itemText: "fooExtension" }
|
// EXIST: { lookupString: "fooExtension", itemText: "fooExtension" }
|
||||||
// EXIST: { lookupString: "fooProperty", itemText: "fooProperty" }
|
// EXIST: { lookupString: "fooProperty", itemText: "fooProperty" }
|
||||||
Vendored
-1
@@ -21,7 +21,6 @@ fun usage(b: B) {
|
|||||||
b.foo<caret>
|
b.foo<caret>
|
||||||
}
|
}
|
||||||
|
|
||||||
// INVOCATION_COUNT: 2
|
|
||||||
// EXIST: { lookupString: "fooForAny", itemText: "fooForAny" }
|
// EXIST: { lookupString: "fooForAny", itemText: "fooForAny" }
|
||||||
|
|
||||||
// EXIST: { lookupString: "fooForT", itemText: "fooForT" }
|
// EXIST: { lookupString: "fooForT", itemText: "fooForT" }
|
||||||
|
|||||||
Vendored
+1
-2
@@ -21,7 +21,6 @@ fun B.usage() {
|
|||||||
foo<caret>
|
foo<caret>
|
||||||
}
|
}
|
||||||
|
|
||||||
// INVOCATION_COUNT: 2
|
|
||||||
// EXIST: { lookupString: "fooForAny", itemText: "fooForAny" }
|
// EXIST: { lookupString: "fooForAny", itemText: "fooForAny" }
|
||||||
|
|
||||||
// EXIST: { lookupString: "fooForT", itemText: "fooForT" }
|
// EXIST: { lookupString: "fooForT", itemText: "fooForT" }
|
||||||
@@ -30,7 +29,7 @@ fun B.usage() {
|
|||||||
// EXIST: { lookupString: "fooForTGeneric", itemText: "fooForTGeneric" }
|
// EXIST: { lookupString: "fooForTGeneric", itemText: "fooForTGeneric" }
|
||||||
// EXIST: { lookupString: "fooForBGeneric", itemText: "fooForBGeneric" }
|
// EXIST: { lookupString: "fooForBGeneric", itemText: "fooForBGeneric" }
|
||||||
|
|
||||||
// EXIST: fooNoReceiver
|
// ABSENT: fooNoReceiver
|
||||||
|
|
||||||
// ABSENT: fooForC
|
// ABSENT: fooForC
|
||||||
// ABSENT: fooForCGeneric
|
// ABSENT: fooForCGeneric
|
||||||
|
|||||||
Vendored
-1
@@ -17,7 +17,6 @@ class A {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// INVOCATION_COUNT: 2
|
|
||||||
// EXIST: { lookupString: "fooForA", itemText: "fooForA" }
|
// EXIST: { lookupString: "fooForA", itemText: "fooForA" }
|
||||||
// EXIST: { lookupString: "fooForB", itemText: "fooForB" }
|
// EXIST: { lookupString: "fooForB", itemText: "fooForB" }
|
||||||
// EXIST: { lookupString: "fooForT", itemText: "fooForT" }
|
// EXIST: { lookupString: "fooForT", itemText: "fooForT" }
|
||||||
|
|||||||
Vendored
-1
@@ -9,6 +9,5 @@ fun usage(t: T) {
|
|||||||
t.foo<caret>
|
t.foo<caret>
|
||||||
}
|
}
|
||||||
|
|
||||||
// INVOCATION_COUNT: 2
|
|
||||||
// EXIST: { lookupString: "fooExtension", itemText: "fooExtension" }
|
// EXIST: { lookupString: "fooExtension", itemText: "fooExtension" }
|
||||||
// EXIST: { lookupString: "fooProperty", itemText: "fooProperty" }
|
// EXIST: { lookupString: "fooProperty", itemText: "fooProperty" }
|
||||||
Vendored
-1
@@ -9,6 +9,5 @@ fun T.usage() {
|
|||||||
foo<caret>
|
foo<caret>
|
||||||
}
|
}
|
||||||
|
|
||||||
// INVOCATION_COUNT: 2
|
|
||||||
// EXIST: { lookupString: "fooExtension", itemText: "fooExtension" }
|
// EXIST: { lookupString: "fooExtension", itemText: "fooExtension" }
|
||||||
// EXIST: { lookupString: "fooProperty", itemText: "fooProperty" }
|
// EXIST: { lookupString: "fooProperty", itemText: "fooProperty" }
|
||||||
Vendored
-1
@@ -14,6 +14,5 @@ fun T.usage() {
|
|||||||
foo<caret>
|
foo<caret>
|
||||||
}
|
}
|
||||||
|
|
||||||
// INVOCATION_COUNT: 2
|
|
||||||
// EXIST: { lookupString: "fooExtension", itemText: "fooExtension" }
|
// EXIST: { lookupString: "fooExtension", itemText: "fooExtension" }
|
||||||
// EXIST: { lookupString: "fooProperty", itemText: "fooProperty" }
|
// EXIST: { lookupString: "fooProperty", itemText: "fooProperty" }
|
||||||
-1
@@ -8,5 +8,4 @@ fun usage(t: T) {
|
|||||||
t.f<caret>
|
t.f<caret>
|
||||||
}
|
}
|
||||||
|
|
||||||
// INVOCATION_COUNT: 2
|
|
||||||
// ELEMENT: foo
|
// ELEMENT: foo
|
||||||
-1
@@ -10,5 +10,4 @@ fun usage(t: T) {
|
|||||||
t.foo()<caret>
|
t.foo()<caret>
|
||||||
}
|
}
|
||||||
|
|
||||||
// INVOCATION_COUNT: 2
|
|
||||||
// ELEMENT: foo
|
// ELEMENT: foo
|
||||||
-1
@@ -8,5 +8,4 @@ fun T.usage() {
|
|||||||
f<caret>
|
f<caret>
|
||||||
}
|
}
|
||||||
|
|
||||||
// INVOCATION_COUNT: 2
|
|
||||||
// ELEMENT: foo
|
// ELEMENT: foo
|
||||||
-1
@@ -10,5 +10,4 @@ fun T.usage() {
|
|||||||
foo()<caret>
|
foo()<caret>
|
||||||
}
|
}
|
||||||
|
|
||||||
// INVOCATION_COUNT: 2
|
|
||||||
// ELEMENT: foo
|
// ELEMENT: foo
|
||||||
-1
@@ -12,5 +12,4 @@ fun usage(t: T) {
|
|||||||
t.f<caret>
|
t.f<caret>
|
||||||
}
|
}
|
||||||
|
|
||||||
// INVOCATION_COUNT: 2
|
|
||||||
// ELEMENT: foo
|
// ELEMENT: foo
|
||||||
-1
@@ -14,5 +14,4 @@ fun usage(t: T) {
|
|||||||
t.foo()<caret>
|
t.foo()<caret>
|
||||||
}
|
}
|
||||||
|
|
||||||
// INVOCATION_COUNT: 2
|
|
||||||
// ELEMENT: foo
|
// ELEMENT: foo
|
||||||
-1
@@ -12,5 +12,4 @@ fun T.usage() {
|
|||||||
f<caret>
|
f<caret>
|
||||||
}
|
}
|
||||||
|
|
||||||
// INVOCATION_COUNT: 2
|
|
||||||
// ELEMENT: foo
|
// ELEMENT: foo
|
||||||
-1
@@ -14,5 +14,4 @@ fun T.usage() {
|
|||||||
foo()<caret>
|
foo()<caret>
|
||||||
}
|
}
|
||||||
|
|
||||||
// INVOCATION_COUNT: 2
|
|
||||||
// ELEMENT: foo
|
// ELEMENT: foo
|
||||||
-1
@@ -10,5 +10,4 @@ fun usage(t: T) {
|
|||||||
t.f<caret>
|
t.f<caret>
|
||||||
}
|
}
|
||||||
|
|
||||||
// INVOCATION_COUNT: 2
|
|
||||||
// ELEMENT: foo
|
// ELEMENT: foo
|
||||||
-1
@@ -12,5 +12,4 @@ fun usage(t: T) {
|
|||||||
t.foo()<caret>
|
t.foo()<caret>
|
||||||
}
|
}
|
||||||
|
|
||||||
// INVOCATION_COUNT: 2
|
|
||||||
// ELEMENT: foo
|
// ELEMENT: foo
|
||||||
-1
@@ -10,5 +10,4 @@ fun T.usage() {
|
|||||||
f<caret>
|
f<caret>
|
||||||
}
|
}
|
||||||
|
|
||||||
// INVOCATION_COUNT: 2
|
|
||||||
// ELEMENT: foo
|
// ELEMENT: foo
|
||||||
-1
@@ -12,5 +12,4 @@ fun T.usage() {
|
|||||||
foo()<caret>
|
foo()<caret>
|
||||||
}
|
}
|
||||||
|
|
||||||
// INVOCATION_COUNT: 2
|
|
||||||
// ELEMENT: foo
|
// ELEMENT: foo
|
||||||
-1
@@ -8,5 +8,4 @@ fun usage(t: T) {
|
|||||||
t.f<caret>
|
t.f<caret>
|
||||||
}
|
}
|
||||||
|
|
||||||
// INVOCATION_COUNT: 2
|
|
||||||
// ELEMENT: foo
|
// ELEMENT: foo
|
||||||
-1
@@ -10,5 +10,4 @@ fun usage(t: T) {
|
|||||||
t.foo()<caret>
|
t.foo()<caret>
|
||||||
}
|
}
|
||||||
|
|
||||||
// INVOCATION_COUNT: 2
|
|
||||||
// ELEMENT: foo
|
// ELEMENT: foo
|
||||||
-1
@@ -8,5 +8,4 @@ fun T.usage() {
|
|||||||
f<caret>
|
f<caret>
|
||||||
}
|
}
|
||||||
|
|
||||||
// INVOCATION_COUNT: 2
|
|
||||||
// ELEMENT: foo
|
// ELEMENT: foo
|
||||||
-1
@@ -10,5 +10,4 @@ fun T.usage() {
|
|||||||
foo()<caret>
|
foo()<caret>
|
||||||
}
|
}
|
||||||
|
|
||||||
// INVOCATION_COUNT: 2
|
|
||||||
// ELEMENT: foo
|
// ELEMENT: foo
|
||||||
+15
@@ -1255,6 +1255,21 @@ public class JSBasicCompletionTestGenerated extends AbstractJSBasicCompletionTes
|
|||||||
runTest("idea/idea-completion/testData/basic/common/extensionMethodInObject/CompanionObjectExplicitReceiver.kt");
|
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")
|
@TestMetadata("CompanionObjectImplicitReceiver.kt")
|
||||||
public void testCompanionObjectImplicitReceiver() throws Exception {
|
public void testCompanionObjectImplicitReceiver() throws Exception {
|
||||||
runTest("idea/idea-completion/testData/basic/common/extensionMethodInObject/CompanionObjectImplicitReceiver.kt");
|
runTest("idea/idea-completion/testData/basic/common/extensionMethodInObject/CompanionObjectImplicitReceiver.kt");
|
||||||
|
|||||||
+15
@@ -1255,6 +1255,21 @@ public class JvmBasicCompletionTestGenerated extends AbstractJvmBasicCompletionT
|
|||||||
runTest("idea/idea-completion/testData/basic/common/extensionMethodInObject/CompanionObjectExplicitReceiver.kt");
|
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")
|
@TestMetadata("CompanionObjectImplicitReceiver.kt")
|
||||||
public void testCompanionObjectImplicitReceiver() throws Exception {
|
public void testCompanionObjectImplicitReceiver() throws Exception {
|
||||||
runTest("idea/idea-completion/testData/basic/common/extensionMethodInObject/CompanionObjectImplicitReceiver.kt");
|
runTest("idea/idea-completion/testData/basic/common/extensionMethodInObject/CompanionObjectImplicitReceiver.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user