KT-30996: Use the last receiver to complete dsl methods

- change `detectReceiverTypes` return type to `List` instead of `Collection`
  - it reflects that receiver types are actually ordered
  - did not propagate signature changes to all possible places because it creates too much noise in git history
- ^KT-30996 Fixed
This commit is contained in:
Roman Golyshev
2019-09-05 11:59:55 +03:00
committed by Roman Golyshev
parent b2d2ba5811
commit b422485440
6 changed files with 37 additions and 6 deletions
@@ -249,7 +249,7 @@ fun CallTypeAndReceiver<*, *>.receiverTypes(
moduleDescriptor: ModuleDescriptor,
resolutionFacade: ResolutionFacade,
stableSmartCastsOnly: Boolean
): Collection<KotlinType>? {
): List<KotlinType>? {
return receiverTypesWithIndex(bindingContext, contextElement, moduleDescriptor, resolutionFacade, stableSmartCastsOnly)?.map { it.type }
}
@@ -260,7 +260,7 @@ fun CallTypeAndReceiver<*, *>.receiverTypesWithIndex(
resolutionFacade: ResolutionFacade,
stableSmartCastsOnly: Boolean,
withImplicitReceiversWhenExplicitPresent: Boolean = false
): Collection<ReceiverType>? {
): List<ReceiverType>? {
val languageVersionSettings = resolutionFacade.frontendService<LanguageVersionSettings>()
val receiverExpression: KtExpression?
@@ -417,7 +417,7 @@ abstract class CompletionSession(
bindingContext: BindingContext,
nameExpression: KtSimpleNameExpression,
callTypeAndReceiver: CallTypeAndReceiver<*, *>
): Collection<ReceiverType>? {
): List<ReceiverType>? {
var receiverTypes = callTypeAndReceiver.receiverTypesWithIndex(
bindingContext, nameExpression, moduleDescriptor, resolutionFacade,
stableSmartCastsOnly = true, /* we don't include smart cast receiver types for "unstable" receiver value to mark members grayed */
@@ -11,17 +11,23 @@ import org.jetbrains.kotlin.idea.util.CallTypeAndReceiver
import org.jetbrains.kotlin.idea.util.ReceiverType
import org.jetbrains.kotlin.psi.KtModifierListOwner
import org.jetbrains.kotlin.psi.psiUtil.collectAnnotationEntriesFromStubOrPsi
import org.jetbrains.kotlin.resolve.calls.DslMarkerUtils
class DslMembersCompletion(
private val prefixMatcher: PrefixMatcher,
private val elementFactory: LookupElementFactory,
receiverTypes: Collection<ReceiverType>?,
receiverTypes: List<ReceiverType>?,
private val collector: LookupElementsCollector,
private val indicesHelper: KotlinIndicesHelper,
private val callTypeAndReceiver: CallTypeAndReceiver<*, *>
) {
private val nearestReceiver = receiverTypes?.firstOrNull()
/**
* It is stated that `two implicit receivers of the same DSL are not accessible in the same scope`,
* that's why we need only the last one of the receivers to provide the completion (see [DslMarker]).
*
* When the last receiver is not a part of DSL, [nearestReceiverMarkers] will be empty, and dsl
* members would not be suggested in the autocompletion (see KT-30996).
*/
private val nearestReceiver = receiverTypes?.lastOrNull()
private val nearestReceiverMarkers = nearestReceiver?.takeIf { it.implicit }?.extractDslMarkers().orEmpty()
fun completeDslFunctions() {
@@ -0,0 +1,15 @@
@DslMarker
annotation class MyDSL
@MyDSL
class HTML
@MyDSL
fun HTML.foo() { }
fun HTML.test() {
val x = 1
x.<caret>
}
// ABSENT: foo
@@ -1175,6 +1175,11 @@ public class JSBasicCompletionTestGenerated extends AbstractJSBasicCompletionTes
runTest("idea/idea-completion/testData/basic/common/dslMarker/container.kt");
}
@TestMetadata("noDslCompletionForNonDslReciever.kt")
public void testNoDslCompletionForNonDslReciever() throws Exception {
runTest("idea/idea-completion/testData/basic/common/dslMarker/noDslCompletionForNonDslReciever.kt");
}
@TestMetadata("root.kt")
public void testRoot() throws Exception {
runTest("idea/idea-completion/testData/basic/common/dslMarker/root.kt");
@@ -1175,6 +1175,11 @@ public class JvmBasicCompletionTestGenerated extends AbstractJvmBasicCompletionT
runTest("idea/idea-completion/testData/basic/common/dslMarker/container.kt");
}
@TestMetadata("noDslCompletionForNonDslReciever.kt")
public void testNoDslCompletionForNonDslReciever() throws Exception {
runTest("idea/idea-completion/testData/basic/common/dslMarker/noDslCompletionForNonDslReciever.kt");
}
@TestMetadata("root.kt")
public void testRoot() throws Exception {
runTest("idea/idea-completion/testData/basic/common/dslMarker/root.kt");