Object to lambda intention is inapplicable when reference to this is used
#KT-10202 In Progress
This commit is contained in:
@@ -33,6 +33,7 @@ import org.jetbrains.kotlin.idea.util.ShortenReferences
|
||||
import org.jetbrains.kotlin.lexer.KtTokens
|
||||
import org.jetbrains.kotlin.load.java.sam.SingleAbstractMethodUtils
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.psi.psiUtil.collectDescendantsOfType
|
||||
import org.jetbrains.kotlin.psi.psiUtil.contentRange
|
||||
import org.jetbrains.kotlin.psi.psiUtil.endOffset
|
||||
import org.jetbrains.kotlin.psi.psiUtil.startOffset
|
||||
@@ -60,8 +61,20 @@ class ObjectLiteralToLambdaIntention : SelfTargetingRangeIntention<KtObjectLiter
|
||||
if (!singleFunction.hasBody()) return null
|
||||
if (singleFunction.valueParameters.any { it.name == null }) return null
|
||||
|
||||
val bodyExpression = singleFunction.bodyExpression!!
|
||||
|
||||
// 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
|
||||
}
|
||||
}
|
||||
|
||||
// Recursive call, skip labels
|
||||
if (ReferencesSearch.search(singleFunction, LocalSearchScope(singleFunction.bodyExpression!!)).any { it.element !is KtLabelReferenceExpression }) {
|
||||
if (ReferencesSearch.search(singleFunction, LocalSearchScope(bodyExpression)).any { it.element !is KtLabelReferenceExpression }) {
|
||||
return null
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
// WITH_RUNTIME
|
||||
|
||||
class Test {
|
||||
fun foo() {
|
||||
bar(object : Runnable {
|
||||
override fun run() {
|
||||
println(this)
|
||||
}
|
||||
})
|
||||
|
||||
// Applicable
|
||||
bar(<caret>object : Runnable {
|
||||
override fun run() {
|
||||
println(this@Test)
|
||||
}
|
||||
})
|
||||
|
||||
// Applicable
|
||||
bar(object : Runnable {
|
||||
override fun run() {
|
||||
bar(object : Runnable {
|
||||
override fun run() {
|
||||
println(this)
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
private fun bar(b: Runnable) {
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
// WITH_RUNTIME
|
||||
|
||||
class Test {
|
||||
fun foo() {
|
||||
bar(object : Runnable {
|
||||
override fun run() {
|
||||
println(this)
|
||||
}
|
||||
})
|
||||
|
||||
// Applicable
|
||||
bar(Runnable { println(this@Test) })
|
||||
|
||||
// Applicable
|
||||
bar(object : Runnable {
|
||||
override fun run() {
|
||||
bar(object : Runnable {
|
||||
override fun run() {
|
||||
println(this)
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
private fun bar(b: Runnable) {
|
||||
|
||||
}
|
||||
}
|
||||
@@ -150,4 +150,20 @@
|
||||
<problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">Convert object literal to lambda</problem_class>
|
||||
<description>Convert to lambda</description>
|
||||
</problem>
|
||||
<problem>
|
||||
<file>ThisReference.kt</file>
|
||||
<line>12</line>
|
||||
<module>light_idea_test_case</module>
|
||||
<entry_point TYPE="file" FQNAME="ThisReference.kt" />
|
||||
<problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">Convert object literal to lambda</problem_class>
|
||||
<description>Convert to lambda</description>
|
||||
</problem>
|
||||
<problem>
|
||||
<file>ThisReference.kt</file>
|
||||
<line>19</line>
|
||||
<module>light_idea_test_case</module>
|
||||
<entry_point TYPE="file" FQNAME="ThisReference.kt" />
|
||||
<problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">Convert object literal to lambda</problem_class>
|
||||
<description>Convert to lambda</description>
|
||||
</problem>
|
||||
</problems>
|
||||
@@ -6600,6 +6600,12 @@ public class IntentionTestGenerated extends AbstractIntentionTest {
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("ThisReference.kt")
|
||||
public void testThisReference() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/objectLiteralToLambda/ThisReference.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("TwoFunctions.kt")
|
||||
public void testTwoFunctions() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/objectLiteralToLambda/TwoFunctions.kt");
|
||||
|
||||
Reference in New Issue
Block a user