Fix invalidated element access exception in ObjectLiteralToLambdaIntention

#KT-36149 fixed
#KT-36152 fixed
This commit is contained in:
Ilya Kirillov
2020-02-14 10:02:36 +03:00
parent 6b913da698
commit 85be0450ba
7 changed files with 117 additions and 4 deletions
@@ -150,14 +150,14 @@ class ObjectLiteralToLambdaIntention : SelfTargetingRangeIntention<KtObjectLiter
}
val replaced = runWriteAction { element.replaced(newExpression) }
val callee = replaced.getCalleeExpressionIfAny()!! as KtNameReferenceExpression
val pointerToReplaced = replaced.createSmartPointer()
val callee = replaced.callee
val callExpression = callee.parent as KtCallExpression
val functionLiteral = callExpression.lambdaArguments.single().getLambdaExpression()!!
val returnLabel = callee.getReferencedNameAsName()
runWriteAction {
returnSaver.restore(functionLiteral, returnLabel)
commentSaver.restore(replaced, forceAdjustIndent = true/* by some reason lambda body is sometimes not properly indented */)
}
val parentCall = ((replaced.parent as? KtValueArgument)
?.parent as? KtValueArgumentList)
@@ -165,15 +165,27 @@ class ObjectLiteralToLambdaIntention : SelfTargetingRangeIntention<KtObjectLiter
if (parentCall != null && RedundantSamConstructorInspection.samConstructorCallsToBeConverted(parentCall)
.singleOrNull() == callExpression
) {
runWriteAction {
commentSaver.restore(replaced, forceAdjustIndent = true/* by some reason lambda body is sometimes not properly indented */)
}
RedundantSamConstructorInspection.replaceSamConstructorCall(callExpression)
if (parentCall.canMoveLambdaOutsideParentheses()) runWriteAction {
parentCall.moveFunctionLiteralOutsideParentheses()
}
} else {
val endOffset = (callee.parent as? KtCallExpression)?.typeArgumentList?.endOffset ?: callee.endOffset
ShortenReferences.DEFAULT.process(replaced.containingKtFile, replaced.startOffset, endOffset)
runWriteAction {
commentSaver.restore(replaced, forceAdjustIndent = true/* by some reason lambda body is sometimes not properly indented */)
}
pointerToReplaced.element?.let { replacedByPointer ->
val endOffset = (replacedByPointer.callee.parent as? KtCallExpression)?.typeArgumentList?.endOffset
?: replacedByPointer.callee.endOffset
ShortenReferences.DEFAULT.process(replacedByPointer.containingKtFile, replacedByPointer.startOffset, endOffset)
}
}
}
private val KtExpression.callee
get() = getCalleeExpressionIfAny() as KtNameReferenceExpression
}
private data class Data(
+28
View File
@@ -0,0 +1,28 @@
// Stubbed from Android Activity
class Activity {
public final void runOnUiThread(Runnable action) {
action.run();
}
}
public class Foo {
private Activity activity;
public void foo() {
synchronized (this) {
activity.runOnUiThread(new Runnable() {
public void run() {
}
});
}
}
public void bar() {
synchronized (this) {
activity.runOnUiThread(new Runnable() {
public void run() {
}
});
}
}
}
+21
View File
@@ -0,0 +1,21 @@
// Stubbed from Android Activity
internal class Activity {
fun runOnUiThread(action: Runnable) {
action.run()
}
}
class Foo {
private val activity: Activity? = null
fun foo() {
synchronized(this) {
activity!!.runOnUiThread(Runnable { })
}
}
fun bar() {
synchronized(this) {
activity!!.runOnUiThread(Runnable { })
}
}
}
@@ -0,0 +1,15 @@
// Stubbed class from 'androidx.preference:preference:1.1.0'
public class Preference {
public interface OnPreferenceClickListener {
boolean onPreferenceClick(Preference preference);
}
@SuppressWarnings("unused")
public OnPreferenceClickListener getOnPreferenceClickListener() {
return null;
}
public void setOnPreferenceClickListener(OnPreferenceClickListener onPreferenceClickListener) {
}
}
+15
View File
@@ -0,0 +1,15 @@
public class Foo {
public void foo(Preference l, Preference pm) {
l.setOnPreferenceClickListener((p) -> true);
pm.setOnPreferenceClickListener(new OnPreferenceClickListener() {
public boolean onPreferenceClick(Preference preference) {
return true;
}
});
}
private void bar(Preference l) {
l.setOnPreferenceClickListener((p) -> true);
}
}
+12
View File
@@ -0,0 +1,12 @@
import Preference.OnPreferenceClickListener
class Foo {
fun foo(l: Preference, pm: Preference) {
l.onPreferenceClickListener = OnPreferenceClickListener { p: Preference? -> true }
pm.onPreferenceClickListener = OnPreferenceClickListener { true }
}
private fun bar(l: Preference) {
l.onPreferenceClickListener = OnPreferenceClickListener { p: Preference? -> true }
}
}
@@ -4061,6 +4061,16 @@ public class NewJavaToKotlinConverterSingleFileTestGenerated extends AbstractNew
KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("nj2k/testData/newJ2k/objectLiteral"), Pattern.compile("^([^\\.]+)\\.java$"), null, true);
}
@TestMetadata("kt-36149.java")
public void testKt_36149() throws Exception {
runTest("nj2k/testData/newJ2k/objectLiteral/kt-36149.java");
}
@TestMetadata("kt-36152.java")
public void testKt_36152() throws Exception {
runTest("nj2k/testData/newJ2k/objectLiteral/kt-36152.java");
}
@TestMetadata("MyFrame.java")
public void testMyFrame() throws Exception {
runTest("nj2k/testData/newJ2k/objectLiteral/MyFrame.java");