Take into account refined applicability of dsl-marker in IDE
After the previous change, when being applied to a function type with receiver it's assumed to work just as it's applied to receiver type Thus, it's necessary to fix relevant IDE features relied on DSL markers #KT-23255 Fixed
This commit is contained in:
@@ -25,7 +25,9 @@ object DslMarkerUtils {
|
|||||||
data class DslMarkersFromReceiver(
|
data class DslMarkersFromReceiver(
|
||||||
val common: Set<FqName>,
|
val common: Set<FqName>,
|
||||||
val fromContainingFunctionType: Set<FqName>
|
val fromContainingFunctionType: Set<FqName>
|
||||||
)
|
) {
|
||||||
|
fun all() = common + fromContainingFunctionType
|
||||||
|
}
|
||||||
|
|
||||||
fun extractDslMarkerFqNames(receiver: ReceiverValue): DslMarkersFromReceiver {
|
fun extractDslMarkerFqNames(receiver: ReceiverValue): DslMarkersFromReceiver {
|
||||||
val errorLevel = extractDslMarkerFqNames(receiver.type)
|
val errorLevel = extractDslMarkerFqNames(receiver.type)
|
||||||
|
|||||||
@@ -213,7 +213,17 @@ sealed class CallTypeAndReceiver<TReceiver : KtElement?, out TCallType : CallTyp
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
data class ReceiverType(val type: KotlinType, val receiverIndex: Int, val implicit: Boolean = false)
|
data class ReceiverType(
|
||||||
|
val type: KotlinType,
|
||||||
|
val receiverIndex: Int,
|
||||||
|
val implicitValue: ReceiverValue? = null
|
||||||
|
) {
|
||||||
|
val implicit: Boolean get() = implicitValue != null
|
||||||
|
|
||||||
|
fun extractDslMarkers() =
|
||||||
|
implicitValue?.let(DslMarkerUtils::extractDslMarkerFqNames)?.all()
|
||||||
|
?: DslMarkerUtils.extractDslMarkerFqNames(type)
|
||||||
|
}
|
||||||
|
|
||||||
fun CallTypeAndReceiver<*, *>.receiverTypes(
|
fun CallTypeAndReceiver<*, *>.receiverTypes(
|
||||||
bindingContext: BindingContext,
|
bindingContext: BindingContext,
|
||||||
@@ -305,9 +315,13 @@ fun CallTypeAndReceiver<*, *>.receiverTypesWithIndex(
|
|||||||
var receiverIndex = 0
|
var receiverIndex = 0
|
||||||
|
|
||||||
fun addReceiverType(receiverValue: ReceiverValue, implicit: Boolean) {
|
fun addReceiverType(receiverValue: ReceiverValue, implicit: Boolean) {
|
||||||
val types = receiverValueTypes(receiverValue, dataFlowInfo, bindingContext, moduleDescriptor, stableSmartCastsOnly, languageVersionSettings,
|
val types = receiverValueTypes(
|
||||||
resolutionFacade.frontendService<DataFlowValueFactory>())
|
receiverValue, dataFlowInfo, bindingContext, moduleDescriptor, stableSmartCastsOnly, languageVersionSettings,
|
||||||
types.mapTo(result) { ReceiverType(it, receiverIndex, implicit) }
|
resolutionFacade.frontendService<DataFlowValueFactory>()
|
||||||
|
)
|
||||||
|
|
||||||
|
types.mapTo(result) { type -> ReceiverType(type, receiverIndex, receiverValue.takeIf { implicit }) }
|
||||||
|
|
||||||
receiverIndex++
|
receiverIndex++
|
||||||
}
|
}
|
||||||
if (withImplicitReceiversWhenExplicitPresent || expressionReceiver == null) {
|
if (withImplicitReceiversWhenExplicitPresent || expressionReceiver == null) {
|
||||||
@@ -350,7 +364,7 @@ fun Collection<ReceiverType>.shadowedByDslMarkers(): Set<ReceiverType> {
|
|||||||
|
|
||||||
this
|
this
|
||||||
.mapNotNull { receiver ->
|
.mapNotNull { receiver ->
|
||||||
val dslMarkers = DslMarkerUtils.extractDslMarkerFqNames(receiver.type)
|
val dslMarkers = receiver.extractDslMarkers()
|
||||||
(receiver to dslMarkers).takeIf { dslMarkers.isNotEmpty() }
|
(receiver to dslMarkers).takeIf { dslMarkers.isNotEmpty() }
|
||||||
}
|
}
|
||||||
.forEach { (v, dslMarkers) -> dslMarkers.forEach { typesByDslScopes.getOrPut(it, { mutableListOf() }) += v } }
|
.forEach { (v, dslMarkers) -> dslMarkers.forEach { typesByDslScopes.getOrPut(it, { mutableListOf() }) += v } }
|
||||||
@@ -359,4 +373,4 @@ fun Collection<ReceiverType>.shadowedByDslMarkers(): Set<ReceiverType> {
|
|||||||
typesByDslScopes.flatMapTo(shadowedDslReceivers) { (_, v) -> v.asSequence().drop(1).asIterable() }
|
typesByDslScopes.flatMapTo(shadowedDslReceivers) { (_, v) -> v.asSequence().drop(1).asIterable() }
|
||||||
|
|
||||||
return shadowedDslReceivers
|
return shadowedDslReceivers
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-2
@@ -24,8 +24,7 @@ class DslMembersCompletion(
|
|||||||
private val callTypeAndReceiver: CallTypeAndReceiver<*, *>
|
private val callTypeAndReceiver: CallTypeAndReceiver<*, *>
|
||||||
) {
|
) {
|
||||||
private val nearestReceiver = receiverTypes?.firstOrNull()
|
private val nearestReceiver = receiverTypes?.firstOrNull()
|
||||||
private val nearestReceiverMarkers = nearestReceiver?.takeIf { it.implicit }
|
private val nearestReceiverMarkers = nearestReceiver?.takeIf { it.implicit }?.extractDslMarkers().orEmpty()
|
||||||
?.let { DslMarkerUtils.extractDslMarkerFqNames(it.type) }.orEmpty()
|
|
||||||
|
|
||||||
private val factory = object : AbstractLookupElementFactory {
|
private val factory = object : AbstractLookupElementFactory {
|
||||||
override fun createLookupElement(
|
override fun createLookupElement(
|
||||||
|
|||||||
+41
@@ -0,0 +1,41 @@
|
|||||||
|
package bar
|
||||||
|
|
||||||
|
@DslMarker
|
||||||
|
annotation class Dsl
|
||||||
|
|
||||||
|
|
||||||
|
class R
|
||||||
|
|
||||||
|
fun r(body: @Dsl R.() -> Unit) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
fun foo1(i: Int) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
fun foo3() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Dsl
|
||||||
|
fun R.foo2() {}
|
||||||
|
|
||||||
|
@Dsl
|
||||||
|
fun R.foo4() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Dsl
|
||||||
|
fun R.fooloooooong() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
val R.fooval
|
||||||
|
get() = Unit
|
||||||
|
|
||||||
|
@Dsl
|
||||||
|
fun R.SomethingSomethingFooSomething() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
+20
@@ -0,0 +1,20 @@
|
|||||||
|
// RUNTIME
|
||||||
|
package test
|
||||||
|
|
||||||
|
import bar.r
|
||||||
|
import bar.foo3
|
||||||
|
|
||||||
|
fun main() {
|
||||||
|
val foo5 = 3
|
||||||
|
r {
|
||||||
|
foo<caret>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ORDER: foo2
|
||||||
|
// ORDER: foo4
|
||||||
|
// ORDER: fooloooooong
|
||||||
|
// ORDER: foo3
|
||||||
|
// ORDER: foo5
|
||||||
|
// ORDER: fooval
|
||||||
|
// ORDER: foo1
|
||||||
+5
@@ -69,6 +69,11 @@ public class BasicCompletionWeigherTestGenerated extends AbstractBasicCompletion
|
|||||||
runTest("idea/idea-completion/testData/weighers/basic/DslCalls.kt");
|
runTest("idea/idea-completion/testData/weighers/basic/DslCalls.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("DslCallsAnnotatedFunctionType.kt")
|
||||||
|
public void testDslCallsAnnotatedFunctionType() throws Exception {
|
||||||
|
runTest("idea/idea-completion/testData/weighers/basic/DslCallsAnnotatedFunctionType.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("DslCallsWithMultipleReceivers.kt")
|
@TestMetadata("DslCallsWithMultipleReceivers.kt")
|
||||||
public void testDslCallsWithMultipleReceivers() throws Exception {
|
public void testDslCallsWithMultipleReceivers() throws Exception {
|
||||||
runTest("idea/idea-completion/testData/weighers/basic/DslCallsWithMultipleReceivers.kt");
|
runTest("idea/idea-completion/testData/weighers/basic/DslCallsWithMultipleReceivers.kt");
|
||||||
|
|||||||
@@ -0,0 +1,13 @@
|
|||||||
|
import BExtSpace.aaa
|
||||||
|
|
||||||
|
// "Import" "true"
|
||||||
|
// WITH_RUNTIME
|
||||||
|
// ERROR: Unresolved reference: aaa
|
||||||
|
|
||||||
|
fun test() {
|
||||||
|
AAA().apply {
|
||||||
|
sub {
|
||||||
|
aaa<caret>()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
|
||||||
|
@DslMarker
|
||||||
|
annotation class DSL
|
||||||
|
|
||||||
|
@DSL
|
||||||
|
class AAA {
|
||||||
|
fun sub(l: @DSL BBB.() -> Unit) {
|
||||||
|
l(BBB())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class BBB
|
||||||
|
|
||||||
|
object AExtSpace {
|
||||||
|
fun AAA.aaa() {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
object BExtSpace {
|
||||||
|
fun BBB.aaa() {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
// "Import" "true"
|
||||||
|
// WITH_RUNTIME
|
||||||
|
// ERROR: Unresolved reference: aaa
|
||||||
|
|
||||||
|
fun test() {
|
||||||
|
AAA().apply {
|
||||||
|
sub {
|
||||||
|
aaa<caret>()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+5
@@ -459,6 +459,11 @@ public class QuickFixMultiFileTestGenerated extends AbstractQuickFixMultiFileTes
|
|||||||
runTest("idea/testData/quickfix/autoImports/dslMarkers.before.Main.kt");
|
runTest("idea/testData/quickfix/autoImports/dslMarkers.before.Main.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("dslMarkersOnReceiver.before.Main.kt")
|
||||||
|
public void testDslMarkersOnReceiver() throws Exception {
|
||||||
|
runTest("idea/testData/quickfix/autoImports/dslMarkersOnReceiver.before.Main.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("extensionFunctionImport.before.Main.kt")
|
@TestMetadata("extensionFunctionImport.before.Main.kt")
|
||||||
public void testExtensionFunctionImport() throws Exception {
|
public void testExtensionFunctionImport() throws Exception {
|
||||||
runTest("idea/testData/quickfix/autoImports/extensionFunctionImport.before.Main.kt");
|
runTest("idea/testData/quickfix/autoImports/extensionFunctionImport.before.Main.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user