Inline: do more precise check before adding this@Labeled #KT-30762 Fixed
This commit is contained in:
@@ -99,7 +99,7 @@ class CodeInliner<TCallElement : KtElement>(
|
|||||||
|
|
||||||
receiver?.mark(RECEIVER_VALUE_KEY)
|
receiver?.mark(RECEIVER_VALUE_KEY)
|
||||||
|
|
||||||
for (thisExpression in codeToInline.collectDescendantsOfType<KtThisExpression>()) {
|
codeToInline.collectDescendantsOfType<KtThisExpression> { !it[CodeToInline.SIDE_RECEIVER_USAGE_KEY] }.forEach { thisExpression ->
|
||||||
// for this@ClassName we have only option to keep it as is (although it's sometimes incorrect but we have no other options)
|
// for this@ClassName we have only option to keep it as is (although it's sometimes incorrect but we have no other options)
|
||||||
if (thisExpression.labelQualifier == null && receiver != null) {
|
if (thisExpression.labelQualifier == null && receiver != null) {
|
||||||
codeToInline.replaceExpression(thisExpression, receiver)
|
codeToInline.replaceExpression(thisExpression, receiver)
|
||||||
|
|||||||
@@ -41,5 +41,6 @@ class CodeToInline(
|
|||||||
companion object {
|
companion object {
|
||||||
val PARAMETER_USAGE_KEY: Key<Name> = Key("PARAMETER_USAGE")
|
val PARAMETER_USAGE_KEY: Key<Name> = Key("PARAMETER_USAGE")
|
||||||
val TYPE_PARAMETER_USAGE_KEY: Key<Name> = Key("TYPE_PARAMETER_USAGE")
|
val TYPE_PARAMETER_USAGE_KEY: Key<Name> = Key("TYPE_PARAMETER_USAGE")
|
||||||
|
val SIDE_RECEIVER_USAGE_KEY: Key<Unit> = Key("SIDE_RECEIVER_USAGE")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,10 +16,7 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.idea.codeInliner
|
package org.jetbrains.kotlin.idea.codeInliner
|
||||||
|
|
||||||
import org.jetbrains.kotlin.descriptors.CallableDescriptor
|
import org.jetbrains.kotlin.descriptors.*
|
||||||
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
|
|
||||||
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor
|
|
||||||
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
|
|
||||||
import org.jetbrains.kotlin.diagnostics.Errors
|
import org.jetbrains.kotlin.diagnostics.Errors
|
||||||
import org.jetbrains.kotlin.idea.caches.resolve.getResolutionFacade
|
import org.jetbrains.kotlin.idea.caches.resolve.getResolutionFacade
|
||||||
import org.jetbrains.kotlin.idea.core.asExpression
|
import org.jetbrains.kotlin.idea.core.asExpression
|
||||||
@@ -41,6 +38,7 @@ import org.jetbrains.kotlin.resolve.descriptorUtil.isExtension
|
|||||||
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
|
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
|
||||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ImplicitReceiver
|
import org.jetbrains.kotlin.resolve.scopes.receivers.ImplicitReceiver
|
||||||
import org.jetbrains.kotlin.types.ErrorUtils
|
import org.jetbrains.kotlin.types.ErrorUtils
|
||||||
|
import org.jetbrains.kotlin.types.KotlinType
|
||||||
import org.jetbrains.kotlin.utils.sure
|
import org.jetbrains.kotlin.utils.sure
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
@@ -153,7 +151,9 @@ class CodeToInlineBuilder(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun processReferences(codeToInline: MutableCodeToInline, bindingContext: BindingContext, reformat: Boolean) {
|
private fun processReferences(codeToInline: MutableCodeToInline, bindingContext: BindingContext, reformat: Boolean) {
|
||||||
val receiversToAdd = ArrayList<Pair<KtExpression, KtExpression>>()
|
val receiversToAdd = ArrayList<Triple<KtExpression, KtExpression, KotlinType>>()
|
||||||
|
val targetDispatchReceiverType = targetCallable.dispatchReceiverParameter?.value?.type
|
||||||
|
val targetExtensionReceiverType = targetCallable.extensionReceiverParameter?.value?.type
|
||||||
|
|
||||||
codeToInline.forEachDescendantOfType<KtSimpleNameExpression> { expression ->
|
codeToInline.forEachDescendantOfType<KtSimpleNameExpression> { expression ->
|
||||||
val target = bindingContext[BindingContext.REFERENCE_TARGET, expression] ?: return@forEachDescendantOfType
|
val target = bindingContext[BindingContext.REFERENCE_TARGET, expression] ?: return@forEachDescendantOfType
|
||||||
@@ -180,7 +180,7 @@ class CodeToInlineBuilder(
|
|||||||
val resolutionScope = expression.getResolutionScope(bindingContext, resolutionFacade)
|
val resolutionScope = expression.getResolutionScope(bindingContext, resolutionFacade)
|
||||||
val receiverExpression = receiver.asExpression(resolutionScope, psiFactory)
|
val receiverExpression = receiver.asExpression(resolutionScope, psiFactory)
|
||||||
if (receiverExpression != null) {
|
if (receiverExpression != null) {
|
||||||
receiversToAdd.add(expression to receiverExpression)
|
receiversToAdd.add(Triple(expression, receiverExpression, receiver.type))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -188,15 +188,18 @@ class CodeToInlineBuilder(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// add receivers in reverse order because arguments of a call were processed after the callee's name
|
// add receivers in reverse order because arguments of a call were processed after the callee's name
|
||||||
for ((expr, receiverExpression) in receiversToAdd.asReversed()) {
|
for ((expr, receiverExpression, receiverType) in receiversToAdd.asReversed()) {
|
||||||
val expressionToReplace = expr.parent as? KtCallExpression ?: expr
|
val expressionToReplace = expr.parent as? KtCallExpression ?: expr
|
||||||
codeToInline.replaceExpression(
|
val replaced = codeToInline.replaceExpression(
|
||||||
expressionToReplace,
|
expressionToReplace,
|
||||||
psiFactory.createExpressionByPattern(
|
psiFactory.createExpressionByPattern(
|
||||||
"$0.$1", receiverExpression, expressionToReplace,
|
"$0.$1", receiverExpression, expressionToReplace,
|
||||||
reformat = reformat
|
reformat = reformat
|
||||||
)
|
)
|
||||||
)
|
) as? KtQualifiedExpression
|
||||||
|
if (receiverType != targetDispatchReceiverType && receiverType != targetExtensionReceiverType) {
|
||||||
|
replaced?.receiverExpression?.putCopyableUserData(CodeToInline.SIDE_RECEIVER_USAGE_KEY, Unit)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
interface MySeq<T> {
|
||||||
|
fun yield(arg: T)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun <T> mySeq(f: MySeq<T>.() -> Unit): MySeq<T> = null!!
|
||||||
|
|
||||||
|
class Test {
|
||||||
|
fun repro() = mySeq<Int> {
|
||||||
|
inner()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun <caret>inner() = mySeq<Double> {
|
||||||
|
yield(1.0)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
interface MySeq<T> {
|
||||||
|
fun yield(arg: T)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun <T> mySeq(f: MySeq<T>.() -> Unit): MySeq<T> = null!!
|
||||||
|
|
||||||
|
class Test {
|
||||||
|
fun repro() = mySeq<Int> {
|
||||||
|
mySeq<Double> {
|
||||||
|
yield(1.0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
+1
-1
@@ -11,7 +11,7 @@ internal object Bar {
|
|||||||
@JvmStatic fun main(args: Array<String>) {
|
@JvmStatic fun main(args: Array<String>) {
|
||||||
bar(object : Runnable {
|
bar(object : Runnable {
|
||||||
override fun run() {
|
override fun run() {
|
||||||
Foo.doRun()
|
doRun()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun doRun() {
|
private fun doRun() {
|
||||||
|
|||||||
+5
@@ -86,6 +86,11 @@ public class InlineTestGenerated extends AbstractInlineTest {
|
|||||||
runTest("idea/testData/refactoring/inline/function/ReturnNotInTheEnd.kt");
|
runTest("idea/testData/refactoring/inline/function/ReturnNotInTheEnd.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("Sequence.kt")
|
||||||
|
public void testSequence() throws Exception {
|
||||||
|
runTest("idea/testData/refactoring/inline/function/Sequence.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("UnitReturnType.kt")
|
@TestMetadata("UnitReturnType.kt")
|
||||||
public void testUnitReturnType() throws Exception {
|
public void testUnitReturnType() throws Exception {
|
||||||
runTest("idea/testData/refactoring/inline/function/UnitReturnType.kt");
|
runTest("idea/testData/refactoring/inline/function/UnitReturnType.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user