Don't apply "object->lambda" if 'this' is used inside #KT-15250 Fixed
This commit is contained in:
@@ -21,6 +21,7 @@ import com.intellij.openapi.util.TextRange
|
||||
import com.intellij.psi.PsiComment
|
||||
import com.intellij.psi.search.LocalSearchScope
|
||||
import com.intellij.psi.search.searches.ReferencesSearch
|
||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.Modality
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.analyze
|
||||
@@ -38,7 +39,10 @@ import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.psi.psiUtil.*
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
import org.jetbrains.kotlin.resolve.calls.callUtil.getCalleeExpressionIfAny
|
||||
import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall
|
||||
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ImplicitClassReceiver
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
|
||||
class ObjectLiteralToLambdaInspection : IntentionBasedInspection<KtObjectLiteralExpression>(ObjectLiteralToLambdaIntention::class)
|
||||
@@ -61,22 +65,30 @@ class ObjectLiteralToLambdaIntention : SelfTargetingRangeIntention<KtObjectLiter
|
||||
if (singleFunction.valueParameters.any { it.name == null }) return null
|
||||
|
||||
val bodyExpression = singleFunction.bodyExpression!!
|
||||
val context = bodyExpression.analyze()
|
||||
val containingDeclaration = functionDescriptor.containingDeclaration
|
||||
|
||||
// this-reference
|
||||
val thisReferences = bodyExpression.collectDescendantsOfType<KtThisExpression> { it !is KtClassOrObject }
|
||||
for (thisReference in thisReferences) {
|
||||
val context = thisReference.analyze(BodyResolveMode.PARTIAL)
|
||||
val thisDescriptor = context[BindingContext.REFERENCE_TARGET, thisReference.instanceReference]
|
||||
if (thisDescriptor == functionDescriptor.containingDeclaration) {
|
||||
return null
|
||||
}
|
||||
}
|
||||
if (bodyExpression.anyDescendantOfType<KtThisExpression> { thisReference ->
|
||||
context[BindingContext.REFERENCE_TARGET, thisReference.instanceReference] == containingDeclaration
|
||||
}) return null
|
||||
|
||||
// Recursive call, skip labels
|
||||
if (ReferencesSearch.search(singleFunction, LocalSearchScope(bodyExpression)).any { it.element !is KtLabelReferenceExpression }) {
|
||||
return null
|
||||
}
|
||||
|
||||
fun ReceiverValue?.isImplicitClassFor(descriptor: DeclarationDescriptor) =
|
||||
this is ImplicitClassReceiver && classDescriptor == descriptor
|
||||
|
||||
if (bodyExpression.anyDescendantOfType<KtExpression> { expression ->
|
||||
val resolvedCall = expression.getResolvedCall(context)
|
||||
resolvedCall?.let {
|
||||
it.dispatchReceiver.isImplicitClassFor(containingDeclaration) ||
|
||||
it.extensionReceiver.isImplicitClassFor(containingDeclaration)
|
||||
} ?: false
|
||||
}) return null
|
||||
|
||||
return TextRange(element.objectDeclaration.getObjectKeyword()!!.startOffset, baseTypeRef.endOffset)
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
// IS_APPLICABLE: false
|
||||
// WITH_RUNTIME
|
||||
|
||||
fun foo() {
|
||||
<caret>object : Runnable {
|
||||
override fun run() {
|
||||
this.hashCode()
|
||||
}
|
||||
}.run()
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
// IS_APPLICABLE: false
|
||||
// WITH_RUNTIME
|
||||
|
||||
fun foo() {
|
||||
<caret>object : Runnable {
|
||||
override fun run() {
|
||||
hashCode()
|
||||
}
|
||||
}.run()
|
||||
}
|
||||
@@ -11418,6 +11418,12 @@ public class IntentionTestGenerated extends AbstractIntentionTest {
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("ExplicitThis.kt")
|
||||
public void testExplicitThis() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/objectLiteralToLambda/ExplicitThis.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("ExpressionBody.kt")
|
||||
public void testExpressionBody() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/objectLiteralToLambda/ExpressionBody.kt");
|
||||
@@ -11430,6 +11436,12 @@ public class IntentionTestGenerated extends AbstractIntentionTest {
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("ImplicitThis.kt")
|
||||
public void testImplicitThis() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/objectLiteralToLambda/ImplicitThis.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("MultipleBases.kt")
|
||||
public void testMultipleBases() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/objectLiteralToLambda/MultipleBases.kt");
|
||||
|
||||
Reference in New Issue
Block a user