diff --git a/idea/src/org/jetbrains/kotlin/idea/inspections/RedundantSamConstructorInspection.kt b/idea/src/org/jetbrains/kotlin/idea/inspections/RedundantSamConstructorInspection.kt index 142b4e294ce..bd42b2ef1c3 100644 --- a/idea/src/org/jetbrains/kotlin/idea/inspections/RedundantSamConstructorInspection.kt +++ b/idea/src/org/jetbrains/kotlin/idea/inspections/RedundantSamConstructorInspection.kt @@ -31,6 +31,7 @@ import org.jetbrains.kotlin.load.java.descriptors.SamAdapterDescriptor import org.jetbrains.kotlin.load.java.descriptors.SamConstructorDescriptor import org.jetbrains.kotlin.load.java.sam.SingleAbstractMethodUtils import org.jetbrains.kotlin.psi.* +import org.jetbrains.kotlin.psi.psiUtil.anyDescendantOfType import org.jetbrains.kotlin.psi.psiUtil.getElementTextWithContext import org.jetbrains.kotlin.psi.psiUtil.getQualifiedExpressionForSelectorOrThis import org.jetbrains.kotlin.resolve.BindingContext @@ -167,6 +168,8 @@ public class RedundantSamConstructorInspection : AbstractKotlinInspection() { if (samConstructorCallArguments.isEmpty()) return emptyList() + if (samConstructorCallArguments.any { hasLabeledReturnPreventingConversion(it.toCallExpression()!!) }) return emptyList() + val originalFunctionDescriptor = functionResolvedCall.resultingDescriptor.original as? FunctionDescriptor ?: return emptyList() val containingClass = originalFunctionDescriptor.containingDeclaration as? ClassDescriptor ?: return emptyList() @@ -226,5 +229,11 @@ public class RedundantSamConstructorInspection : AbstractKotlinInspection() { return parametersWithSamTypeCount == samConstructorsCount } + + private fun hasLabeledReturnPreventingConversion(samConstructorCall: KtCallExpression): Boolean { + val argument = samConstructorCall.samConstructorValueArgument()!! + val samConstructorName = (samConstructorCall.calleeExpression as KtSimpleNameExpression).getReferencedNameAsName() + return argument.anyDescendantOfType { it.getLabelNameAsName() == samConstructorName } + } } } \ No newline at end of file diff --git a/idea/testData/inspections/redundantSamConstructor/nonApplicable.kt b/idea/testData/inspections/redundantSamConstructor/nonApplicable.kt index 58262ad8af0..1bfcc2e1d11 100644 --- a/idea/testData/inspections/redundantSamConstructor/nonApplicable.kt +++ b/idea/testData/inspections/redundantSamConstructor/nonApplicable.kt @@ -2,11 +2,21 @@ package redundantSamConstructor import a.* -fun testNonApplicableAmbiguity() { +fun testNonApplicableAmbiguity(p: Int) { GenericClassCantBeReplaced.staticFun1(JFunction0 { "" }) GenericClassCantBeReplaced.staticFun2(JFunction0 { "" }, JFunction0 { "" }) val klass = GenericClassCantBeReplaced() klass.memberFun1(JFunction0 { "" }) klass.memberFun2(JFunction0 { "" }, JFunction0 { "" }) + + MyJavaClass.staticFun1(Runnable { + if (p > 0) return@Runnable + print(1) + }) + + MyJavaClass.staticFun2(Runnable { }, Runnable { + if (p > 0) return@Runnable + print(1) + }) } \ No newline at end of file diff --git a/idea/testData/intentions/objectLiteralToLambda/SamAdapterNeededBecauseOfLabeledReturn.kt b/idea/testData/intentions/objectLiteralToLambda/SamAdapterNeededBecauseOfLabeledReturn.kt new file mode 100644 index 00000000000..cb9a0a477a7 --- /dev/null +++ b/idea/testData/intentions/objectLiteralToLambda/SamAdapterNeededBecauseOfLabeledReturn.kt @@ -0,0 +1,12 @@ +// WITH_RUNTIME + +import javax.swing.SwingUtilities + +fun bar(p: Int) { + SwingUtilities.invokeLater(object: Runnable { + override fun run() { + if (p < 0) return + throw UnsupportedOperationException() + } + }) +} \ No newline at end of file diff --git a/idea/testData/intentions/objectLiteralToLambda/SamAdapterNeededBecauseOfLabeledReturn.kt.after b/idea/testData/intentions/objectLiteralToLambda/SamAdapterNeededBecauseOfLabeledReturn.kt.after new file mode 100644 index 00000000000..688d0a8cd5c --- /dev/null +++ b/idea/testData/intentions/objectLiteralToLambda/SamAdapterNeededBecauseOfLabeledReturn.kt.after @@ -0,0 +1,10 @@ +// WITH_RUNTIME + +import javax.swing.SwingUtilities + +fun bar(p: Int) { + SwingUtilities.invokeLater(Runnable { + if (p < 0) return@Runnable + throw UnsupportedOperationException() + }) +} \ No newline at end of file diff --git a/idea/testData/intentions/objectLiteralToLambda/inspectionData/expected.xml b/idea/testData/intentions/objectLiteralToLambda/inspectionData/expected.xml index 1085a009e29..31d96c362c4 100644 --- a/idea/testData/intentions/objectLiteralToLambda/inspectionData/expected.xml +++ b/idea/testData/intentions/objectLiteralToLambda/inspectionData/expected.xml @@ -133,4 +133,13 @@ Convert object literal to lambda Convert to lambda + + + SamAdapterNeededBecauseOfLabeledReturn.kt + 6 + light_idea_test_case + + Convert object literal to lambda + Convert to lambda + \ No newline at end of file diff --git a/idea/tests/org/jetbrains/kotlin/idea/intentions/IntentionTestGenerated.java b/idea/tests/org/jetbrains/kotlin/idea/intentions/IntentionTestGenerated.java index 1a932897553..8e1fa283ea3 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/intentions/IntentionTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/idea/intentions/IntentionTestGenerated.java @@ -5943,6 +5943,12 @@ public class IntentionTestGenerated extends AbstractIntentionTest { doTest(fileName); } + @TestMetadata("SamAdapterNeededBecauseOfLabeledReturn.kt") + public void testSamAdapterNeededBecauseOfLabeledReturn() throws Exception { + String fileName = JetTestUtils.navigationMetadata("idea/testData/intentions/objectLiteralToLambda/SamAdapterNeededBecauseOfLabeledReturn.kt"); + doTest(fileName); + } + @TestMetadata("Simple.kt") public void testSimple() throws Exception { String fileName = JetTestUtils.navigationMetadata("idea/testData/intentions/objectLiteralToLambda/Simple.kt");