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)
|
||||
|
||||
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)
|
||||
if (thisExpression.labelQualifier == null && receiver != null) {
|
||||
codeToInline.replaceExpression(thisExpression, receiver)
|
||||
|
||||
@@ -41,5 +41,6 @@ class CodeToInline(
|
||||
companion object {
|
||||
val PARAMETER_USAGE_KEY: Key<Name> = Key("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
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.CallableDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.diagnostics.Errors
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.getResolutionFacade
|
||||
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.scopes.receivers.ImplicitReceiver
|
||||
import org.jetbrains.kotlin.types.ErrorUtils
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.utils.sure
|
||||
import java.util.*
|
||||
|
||||
@@ -153,7 +151,9 @@ class CodeToInlineBuilder(
|
||||
}
|
||||
|
||||
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 ->
|
||||
val target = bindingContext[BindingContext.REFERENCE_TARGET, expression] ?: return@forEachDescendantOfType
|
||||
@@ -180,7 +180,7 @@ class CodeToInlineBuilder(
|
||||
val resolutionScope = expression.getResolutionScope(bindingContext, resolutionFacade)
|
||||
val receiverExpression = receiver.asExpression(resolutionScope, psiFactory)
|
||||
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
|
||||
for ((expr, receiverExpression) in receiversToAdd.asReversed()) {
|
||||
for ((expr, receiverExpression, receiverType) in receiversToAdd.asReversed()) {
|
||||
val expressionToReplace = expr.parent as? KtCallExpression ?: expr
|
||||
codeToInline.replaceExpression(
|
||||
val replaced = codeToInline.replaceExpression(
|
||||
expressionToReplace,
|
||||
psiFactory.createExpressionByPattern(
|
||||
"$0.$1", receiverExpression, expressionToReplace,
|
||||
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>) {
|
||||
bar(object : Runnable {
|
||||
override fun run() {
|
||||
Foo.doRun()
|
||||
doRun()
|
||||
}
|
||||
|
||||
private fun doRun() {
|
||||
|
||||
+5
@@ -86,6 +86,11 @@ public class InlineTestGenerated extends AbstractInlineTest {
|
||||
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")
|
||||
public void testUnitReturnType() throws Exception {
|
||||
runTest("idea/testData/refactoring/inline/function/UnitReturnType.kt");
|
||||
|
||||
Reference in New Issue
Block a user