From 9f3a902ff399f3f838da5dc1e16c41642d3026b1 Mon Sep 17 00:00:00 2001 From: Denis Zharkov Date: Wed, 8 Aug 2018 16:53:18 +0700 Subject: [PATCH] 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 --- .../kotlin/resolve/calls/DslMarkerUtils.kt | 4 +- .../jetbrains/kotlin/idea/util/CallType.kt | 26 +++++++++--- .../idea/completion/DslMembersCompletion.kt | 3 +- .../DslCallsAnnotatedFunctionType.Data1.kt | 41 +++++++++++++++++++ .../basic/DslCallsAnnotatedFunctionType.kt | 20 +++++++++ .../BasicCompletionWeigherTestGenerated.java | 5 +++ .../autoImports/dslMarkersOnReceiver.after.kt | 13 ++++++ .../dslMarkersOnReceiver.before.Dependency.kt | 24 +++++++++++ .../dslMarkersOnReceiver.before.Main.kt | 11 +++++ .../QuickFixMultiFileTestGenerated.java | 5 +++ 10 files changed, 143 insertions(+), 9 deletions(-) create mode 100644 idea/idea-completion/testData/weighers/basic/DslCallsAnnotatedFunctionType.Data1.kt create mode 100644 idea/idea-completion/testData/weighers/basic/DslCallsAnnotatedFunctionType.kt create mode 100644 idea/testData/quickfix/autoImports/dslMarkersOnReceiver.after.kt create mode 100644 idea/testData/quickfix/autoImports/dslMarkersOnReceiver.before.Dependency.kt create mode 100644 idea/testData/quickfix/autoImports/dslMarkersOnReceiver.before.Main.kt diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/DslMarkerUtils.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/DslMarkerUtils.kt index c5d49ef61e8..7f8bb7f513b 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/DslMarkerUtils.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/DslMarkerUtils.kt @@ -25,7 +25,9 @@ object DslMarkerUtils { data class DslMarkersFromReceiver( val common: Set, val fromContainingFunctionType: Set - ) + ) { + fun all() = common + fromContainingFunctionType + } fun extractDslMarkerFqNames(receiver: ReceiverValue): DslMarkersFromReceiver { val errorLevel = extractDslMarkerFqNames(receiver.type) diff --git a/idea/ide-common/src/org/jetbrains/kotlin/idea/util/CallType.kt b/idea/ide-common/src/org/jetbrains/kotlin/idea/util/CallType.kt index a018331c56a..8c4658b1bd7 100644 --- a/idea/ide-common/src/org/jetbrains/kotlin/idea/util/CallType.kt +++ b/idea/ide-common/src/org/jetbrains/kotlin/idea/util/CallType.kt @@ -213,7 +213,17 @@ sealed class CallTypeAndReceiver.receiverTypes( bindingContext: BindingContext, @@ -305,9 +315,13 @@ fun CallTypeAndReceiver<*, *>.receiverTypesWithIndex( var receiverIndex = 0 fun addReceiverType(receiverValue: ReceiverValue, implicit: Boolean) { - val types = receiverValueTypes(receiverValue, dataFlowInfo, bindingContext, moduleDescriptor, stableSmartCastsOnly, languageVersionSettings, - resolutionFacade.frontendService()) - types.mapTo(result) { ReceiverType(it, receiverIndex, implicit) } + val types = receiverValueTypes( + receiverValue, dataFlowInfo, bindingContext, moduleDescriptor, stableSmartCastsOnly, languageVersionSettings, + resolutionFacade.frontendService() + ) + + types.mapTo(result) { type -> ReceiverType(type, receiverIndex, receiverValue.takeIf { implicit }) } + receiverIndex++ } if (withImplicitReceiversWhenExplicitPresent || expressionReceiver == null) { @@ -350,7 +364,7 @@ fun Collection.shadowedByDslMarkers(): Set { this .mapNotNull { receiver -> - val dslMarkers = DslMarkerUtils.extractDslMarkerFqNames(receiver.type) + val dslMarkers = receiver.extractDslMarkers() (receiver to dslMarkers).takeIf { dslMarkers.isNotEmpty() } } .forEach { (v, dslMarkers) -> dslMarkers.forEach { typesByDslScopes.getOrPut(it, { mutableListOf() }) += v } } @@ -359,4 +373,4 @@ fun Collection.shadowedByDslMarkers(): Set { typesByDslScopes.flatMapTo(shadowedDslReceivers) { (_, v) -> v.asSequence().drop(1).asIterable() } return shadowedDslReceivers -} \ No newline at end of file +} diff --git a/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/DslMembersCompletion.kt b/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/DslMembersCompletion.kt index bfa535c51e6..67889ef33db 100644 --- a/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/DslMembersCompletion.kt +++ b/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/DslMembersCompletion.kt @@ -24,8 +24,7 @@ class DslMembersCompletion( private val callTypeAndReceiver: CallTypeAndReceiver<*, *> ) { private val nearestReceiver = receiverTypes?.firstOrNull() - private val nearestReceiverMarkers = nearestReceiver?.takeIf { it.implicit } - ?.let { DslMarkerUtils.extractDslMarkerFqNames(it.type) }.orEmpty() + private val nearestReceiverMarkers = nearestReceiver?.takeIf { it.implicit }?.extractDslMarkers().orEmpty() private val factory = object : AbstractLookupElementFactory { override fun createLookupElement( diff --git a/idea/idea-completion/testData/weighers/basic/DslCallsAnnotatedFunctionType.Data1.kt b/idea/idea-completion/testData/weighers/basic/DslCallsAnnotatedFunctionType.Data1.kt new file mode 100644 index 00000000000..5d6d2ee1411 --- /dev/null +++ b/idea/idea-completion/testData/weighers/basic/DslCallsAnnotatedFunctionType.Data1.kt @@ -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() { + +} + diff --git a/idea/idea-completion/testData/weighers/basic/DslCallsAnnotatedFunctionType.kt b/idea/idea-completion/testData/weighers/basic/DslCallsAnnotatedFunctionType.kt new file mode 100644 index 00000000000..1fac007f663 --- /dev/null +++ b/idea/idea-completion/testData/weighers/basic/DslCallsAnnotatedFunctionType.kt @@ -0,0 +1,20 @@ +// RUNTIME +package test + +import bar.r +import bar.foo3 + +fun main() { + val foo5 = 3 + r { + foo + } +} + +// ORDER: foo2 +// ORDER: foo4 +// ORDER: fooloooooong +// ORDER: foo3 +// ORDER: foo5 +// ORDER: fooval +// ORDER: foo1 diff --git a/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/weighers/BasicCompletionWeigherTestGenerated.java b/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/weighers/BasicCompletionWeigherTestGenerated.java index 2c4722455e9..dc26bb9581e 100644 --- a/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/weighers/BasicCompletionWeigherTestGenerated.java +++ b/idea/idea-completion/tests/org/jetbrains/kotlin/idea/completion/test/weighers/BasicCompletionWeigherTestGenerated.java @@ -69,6 +69,11 @@ public class BasicCompletionWeigherTestGenerated extends AbstractBasicCompletion 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") public void testDslCallsWithMultipleReceivers() throws Exception { runTest("idea/idea-completion/testData/weighers/basic/DslCallsWithMultipleReceivers.kt"); diff --git a/idea/testData/quickfix/autoImports/dslMarkersOnReceiver.after.kt b/idea/testData/quickfix/autoImports/dslMarkersOnReceiver.after.kt new file mode 100644 index 00000000000..ba01b4ed61e --- /dev/null +++ b/idea/testData/quickfix/autoImports/dslMarkersOnReceiver.after.kt @@ -0,0 +1,13 @@ +import BExtSpace.aaa + +// "Import" "true" +// WITH_RUNTIME +// ERROR: Unresolved reference: aaa + +fun test() { + AAA().apply { + sub { + aaa() + } + } +} \ No newline at end of file diff --git a/idea/testData/quickfix/autoImports/dslMarkersOnReceiver.before.Dependency.kt b/idea/testData/quickfix/autoImports/dslMarkersOnReceiver.before.Dependency.kt new file mode 100644 index 00000000000..91c03ad1382 --- /dev/null +++ b/idea/testData/quickfix/autoImports/dslMarkersOnReceiver.before.Dependency.kt @@ -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() { + + } +} diff --git a/idea/testData/quickfix/autoImports/dslMarkersOnReceiver.before.Main.kt b/idea/testData/quickfix/autoImports/dslMarkersOnReceiver.before.Main.kt new file mode 100644 index 00000000000..49ffc4be76f --- /dev/null +++ b/idea/testData/quickfix/autoImports/dslMarkersOnReceiver.before.Main.kt @@ -0,0 +1,11 @@ +// "Import" "true" +// WITH_RUNTIME +// ERROR: Unresolved reference: aaa + +fun test() { + AAA().apply { + sub { + aaa() + } + } +} \ No newline at end of file diff --git a/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixMultiFileTestGenerated.java b/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixMultiFileTestGenerated.java index 4eb40ef214d..75f20b0589b 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixMultiFileTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixMultiFileTestGenerated.java @@ -459,6 +459,11 @@ public class QuickFixMultiFileTestGenerated extends AbstractQuickFixMultiFileTes 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") public void testExtensionFunctionImport() throws Exception { runTest("idea/testData/quickfix/autoImports/extensionFunctionImport.before.Main.kt");