diff --git a/idea/src/org/jetbrains/kotlin/idea/quickfix/QuickFixRegistrar.kt b/idea/src/org/jetbrains/kotlin/idea/quickfix/QuickFixRegistrar.kt index 646a2f80247..29d13253479 100644 --- a/idea/src/org/jetbrains/kotlin/idea/quickfix/QuickFixRegistrar.kt +++ b/idea/src/org/jetbrains/kotlin/idea/quickfix/QuickFixRegistrar.kt @@ -229,6 +229,7 @@ class QuickFixRegistrar : QuickFixContributor { UNSAFE_INFIX_CALL.registerFactory(ReplaceInfixOrOperatorCallFix) UNSAFE_CALL.registerFactory(ReplaceInfixOrOperatorCallFix) // [] only UNSAFE_IMPLICIT_INVOKE_CALL.registerFactory(ReplaceInfixOrOperatorCallFix) + UNSAFE_CALL.registerFactory(ReplaceWithSafeCallForScopeFunctionFix) AMBIGUOUS_ANONYMOUS_TYPE_INFERRED.registerActions(SpecifyTypeExplicitlyFix()) PROPERTY_WITH_NO_TYPE_NO_INITIALIZER.registerActions(SpecifyTypeExplicitlyFix()) diff --git a/idea/src/org/jetbrains/kotlin/idea/quickfix/ReplaceCallFix.kt b/idea/src/org/jetbrains/kotlin/idea/quickfix/ReplaceCallFix.kt index 486895883d0..419f4219138 100644 --- a/idea/src/org/jetbrains/kotlin/idea/quickfix/ReplaceCallFix.kt +++ b/idea/src/org/jetbrains/kotlin/idea/quickfix/ReplaceCallFix.kt @@ -24,8 +24,11 @@ import org.jetbrains.kotlin.diagnostics.Diagnostic import org.jetbrains.kotlin.idea.caches.resolve.analyze import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.psiUtil.getParentOfType +import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType +import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall import org.jetbrains.kotlin.resolve.calls.resolvedCallUtil.getImplicitReceiverValue +import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameUnsafe abstract class ReplaceCallFix( expression: KtQualifiedExpression, @@ -81,6 +84,55 @@ class ReplaceWithSafeCallFix(expression: KtDotQualifiedExpression): ReplaceCallF } } +class ReplaceWithSafeCallForScopeFunctionFix(expression: KtDotQualifiedExpression) : ReplaceCallFix(expression, "?.") { + + override fun getText() = "Replace scope function with safe (?.) call" + + companion object : KotlinSingleIntentionActionFactory() { + override fun createAction(diagnostic: Diagnostic): KotlinQuickFixAction? { + val element = diagnostic.psiElement + val scopeFunctionLiteral = element.getStrictParentOfType() ?: return null + val scopeCallExpression = scopeFunctionLiteral.getStrictParentOfType() ?: return null + val scopeDotQualifiedExpression = scopeCallExpression.getStrictParentOfType() ?: return null + + val context = scopeCallExpression.analyze() + val scopeFunctionLiteralDescriptor = context[BindingContext.FUNCTION, scopeFunctionLiteral] ?: return null + val scopeFunctionKind = scopeCallExpression.scopeFunctionKind(context) ?: return null + + val internalReceiver = (element.parent as? KtDotQualifiedExpression)?.receiverExpression + val internalReceiverDescriptor = internalReceiver.getResolvedCall(context)?.candidateDescriptor + val internalResolvedCall = (element.getParentOfType(strict = false))?.getResolvedCall(context) + ?: return null + + when (scopeFunctionKind) { + ScopeFunctionKind.WITH_PARAMETER -> { + if (internalReceiverDescriptor != scopeFunctionLiteralDescriptor.valueParameters.singleOrNull()) { + return null + } + } + ScopeFunctionKind.WITH_RECEIVER -> { + if (internalReceiverDescriptor != scopeFunctionLiteralDescriptor.extensionReceiverParameter && + internalResolvedCall.getImplicitReceiverValue() == null) { + return null + } + } + } + + return ReplaceWithSafeCallForScopeFunctionFix(scopeDotQualifiedExpression) + } + + private fun KtCallExpression.scopeFunctionKind(context: BindingContext): ScopeFunctionKind? { + val methodName = getResolvedCall(context)?.resultingDescriptor?.fqNameUnsafe?.asString() + return ScopeFunctionKind.values().firstOrNull { kind -> kind.names.contains(methodName) } + } + + private enum class ScopeFunctionKind(vararg val names: String) { + WITH_PARAMETER("kotlin.let", "kotlin.also"), + WITH_RECEIVER("kotlin.apply", "kotlin.run") + } + } +} + class ReplaceWithDotCallFix(expression: KtSafeQualifiedExpression): ReplaceCallFix(expression, "."), CleanupFix { override fun getText() = "Replace with dot call" diff --git a/idea/testData/quickfix/replaceWithSafeCallForScopeFunction/also.kt b/idea/testData/quickfix/replaceWithSafeCallForScopeFunction/also.kt new file mode 100644 index 00000000000..dd96734f15b --- /dev/null +++ b/idea/testData/quickfix/replaceWithSafeCallForScopeFunction/also.kt @@ -0,0 +1,7 @@ +// "Replace scope function with safe (?.) call" "true" +// WITH_RUNTIME +fun foo(a: String?) { + a.also { + it.length + } +} \ No newline at end of file diff --git a/idea/testData/quickfix/replaceWithSafeCallForScopeFunction/also.kt.after b/idea/testData/quickfix/replaceWithSafeCallForScopeFunction/also.kt.after new file mode 100644 index 00000000000..665ffaba0f8 --- /dev/null +++ b/idea/testData/quickfix/replaceWithSafeCallForScopeFunction/also.kt.after @@ -0,0 +1,7 @@ +// "Replace scope function with safe (?.) call" "true" +// WITH_RUNTIME +fun foo(a: String?) { + a?.also { + it.length + } +} \ No newline at end of file diff --git a/idea/testData/quickfix/replaceWithSafeCallForScopeFunction/applyWithFake.kt b/idea/testData/quickfix/replaceWithSafeCallForScopeFunction/applyWithFake.kt new file mode 100644 index 00000000000..8d4084f314b --- /dev/null +++ b/idea/testData/quickfix/replaceWithSafeCallForScopeFunction/applyWithFake.kt @@ -0,0 +1,13 @@ +// "Replace scope function with safe (?.) call" "false" +// WITH_RUNTIME +// ACTION: Add non-null asserted (!!) call +// ACTION: Introduce local variable +// ACTION: Replace with safe (?.) call +// ACTION: Surround with null check +// ERROR: Only safe (?.) or non-null asserted (!!.) calls are allowed on a nullable receiver of type String? + +fun foo(a: String?, b: String?) { + a.apply { -> + b.length + } +} \ No newline at end of file diff --git a/idea/testData/quickfix/replaceWithSafeCallForScopeFunction/applyWithThis.kt b/idea/testData/quickfix/replaceWithSafeCallForScopeFunction/applyWithThis.kt new file mode 100644 index 00000000000..be29156e5e7 --- /dev/null +++ b/idea/testData/quickfix/replaceWithSafeCallForScopeFunction/applyWithThis.kt @@ -0,0 +1,7 @@ +// "Replace scope function with safe (?.) call" "true" +// WITH_RUNTIME +fun foo(a: String?) { + a.apply { + this.length + } +} \ No newline at end of file diff --git a/idea/testData/quickfix/replaceWithSafeCallForScopeFunction/applyWithThis.kt.after b/idea/testData/quickfix/replaceWithSafeCallForScopeFunction/applyWithThis.kt.after new file mode 100644 index 00000000000..6aec8a092f5 --- /dev/null +++ b/idea/testData/quickfix/replaceWithSafeCallForScopeFunction/applyWithThis.kt.after @@ -0,0 +1,7 @@ +// "Replace scope function with safe (?.) call" "true" +// WITH_RUNTIME +fun foo(a: String?) { + a?.apply { + this.length + } +} \ No newline at end of file diff --git a/idea/testData/quickfix/replaceWithSafeCallForScopeFunction/applyWithThisAndArrow.kt b/idea/testData/quickfix/replaceWithSafeCallForScopeFunction/applyWithThisAndArrow.kt new file mode 100644 index 00000000000..fdc11aa7789 --- /dev/null +++ b/idea/testData/quickfix/replaceWithSafeCallForScopeFunction/applyWithThisAndArrow.kt @@ -0,0 +1,7 @@ +// "Replace scope function with safe (?.) call" "true" +// WITH_RUNTIME +fun foo(a: String?) { + a.apply { -> + this.length + } +} \ No newline at end of file diff --git a/idea/testData/quickfix/replaceWithSafeCallForScopeFunction/applyWithThisAndArrow.kt.after b/idea/testData/quickfix/replaceWithSafeCallForScopeFunction/applyWithThisAndArrow.kt.after new file mode 100644 index 00000000000..87d2d2cfbaa --- /dev/null +++ b/idea/testData/quickfix/replaceWithSafeCallForScopeFunction/applyWithThisAndArrow.kt.after @@ -0,0 +1,7 @@ +// "Replace scope function with safe (?.) call" "true" +// WITH_RUNTIME +fun foo(a: String?) { + a?.apply { -> + this.length + } +} \ No newline at end of file diff --git a/idea/testData/quickfix/replaceWithSafeCallForScopeFunction/applyWithThisLabeled.kt b/idea/testData/quickfix/replaceWithSafeCallForScopeFunction/applyWithThisLabeled.kt new file mode 100644 index 00000000000..7c6c29e98da --- /dev/null +++ b/idea/testData/quickfix/replaceWithSafeCallForScopeFunction/applyWithThisLabeled.kt @@ -0,0 +1,7 @@ +// "Replace scope function with safe (?.) call" "true" +// WITH_RUNTIME +fun foo(a: String?) { + a.apply { + this@apply.length + } +} \ No newline at end of file diff --git a/idea/testData/quickfix/replaceWithSafeCallForScopeFunction/applyWithThisLabeled.kt.after b/idea/testData/quickfix/replaceWithSafeCallForScopeFunction/applyWithThisLabeled.kt.after new file mode 100644 index 00000000000..d0a9d5b5897 --- /dev/null +++ b/idea/testData/quickfix/replaceWithSafeCallForScopeFunction/applyWithThisLabeled.kt.after @@ -0,0 +1,7 @@ +// "Replace scope function with safe (?.) call" "true" +// WITH_RUNTIME +fun foo(a: String?) { + a?.apply { + this@apply.length + } +} \ No newline at end of file diff --git a/idea/testData/quickfix/replaceWithSafeCallForScopeFunction/applyWithThisLabeledFake.kt b/idea/testData/quickfix/replaceWithSafeCallForScopeFunction/applyWithThisLabeledFake.kt new file mode 100644 index 00000000000..f4c40401f60 --- /dev/null +++ b/idea/testData/quickfix/replaceWithSafeCallForScopeFunction/applyWithThisLabeledFake.kt @@ -0,0 +1,14 @@ +// "Replace scope function with safe (?.) call" "false" +// WITH_RUNTIME +// ACTION: Introduce local variable +// ACTION: Add non-null asserted (!!) call +// ACTION: Replace with safe (?.) call +// ERROR: Only safe (?.) or non-null asserted (!!.) calls are allowed on a nullable receiver of type My? + +class My(val prop: Int) + +fun My?.foo(a: String?) { + a.apply { + this@foo.prop + } +} \ No newline at end of file diff --git a/idea/testData/quickfix/replaceWithSafeCallForScopeFunction/applyWithoutThis.kt b/idea/testData/quickfix/replaceWithSafeCallForScopeFunction/applyWithoutThis.kt new file mode 100644 index 00000000000..1cee0c9657f --- /dev/null +++ b/idea/testData/quickfix/replaceWithSafeCallForScopeFunction/applyWithoutThis.kt @@ -0,0 +1,7 @@ +// "Replace scope function with safe (?.) call" "true" +// WITH_RUNTIME +fun foo(a: String?) { + a.apply { + length + } +} \ No newline at end of file diff --git a/idea/testData/quickfix/replaceWithSafeCallForScopeFunction/applyWithoutThis.kt.after b/idea/testData/quickfix/replaceWithSafeCallForScopeFunction/applyWithoutThis.kt.after new file mode 100644 index 00000000000..a8d98c4f878 --- /dev/null +++ b/idea/testData/quickfix/replaceWithSafeCallForScopeFunction/applyWithoutThis.kt.after @@ -0,0 +1,7 @@ +// "Replace scope function with safe (?.) call" "true" +// WITH_RUNTIME +fun foo(a: String?) { + a?.apply { + length + } +} \ No newline at end of file diff --git a/idea/testData/quickfix/replaceWithSafeCallForScopeFunction/applyWithoutThisMethodCall.kt b/idea/testData/quickfix/replaceWithSafeCallForScopeFunction/applyWithoutThisMethodCall.kt new file mode 100644 index 00000000000..29d7a395737 --- /dev/null +++ b/idea/testData/quickfix/replaceWithSafeCallForScopeFunction/applyWithoutThisMethodCall.kt @@ -0,0 +1,7 @@ +// "Replace scope function with safe (?.) call" "true" +// WITH_RUNTIME +fun foo(a: String?) { + a.apply { + toLowerCase() + } +} \ No newline at end of file diff --git a/idea/testData/quickfix/replaceWithSafeCallForScopeFunction/applyWithoutThisMethodCall.kt.after b/idea/testData/quickfix/replaceWithSafeCallForScopeFunction/applyWithoutThisMethodCall.kt.after new file mode 100644 index 00000000000..93e02f96bd0 --- /dev/null +++ b/idea/testData/quickfix/replaceWithSafeCallForScopeFunction/applyWithoutThisMethodCall.kt.after @@ -0,0 +1,7 @@ +// "Replace scope function with safe (?.) call" "true" +// WITH_RUNTIME +fun foo(a: String?) { + a?.apply { + toLowerCase() + } +} \ No newline at end of file diff --git a/idea/testData/quickfix/replaceWithSafeCallForScopeFunction/let.kt b/idea/testData/quickfix/replaceWithSafeCallForScopeFunction/let.kt new file mode 100644 index 00000000000..61262c3bf6b --- /dev/null +++ b/idea/testData/quickfix/replaceWithSafeCallForScopeFunction/let.kt @@ -0,0 +1,7 @@ +// "Replace scope function with safe (?.) call" "true" +// WITH_RUNTIME +fun foo(a: String?) { + a.let { + it.length + } +} \ No newline at end of file diff --git a/idea/testData/quickfix/replaceWithSafeCallForScopeFunction/let.kt.after b/idea/testData/quickfix/replaceWithSafeCallForScopeFunction/let.kt.after new file mode 100644 index 00000000000..1e01ce6852b --- /dev/null +++ b/idea/testData/quickfix/replaceWithSafeCallForScopeFunction/let.kt.after @@ -0,0 +1,7 @@ +// "Replace scope function with safe (?.) call" "true" +// WITH_RUNTIME +fun foo(a: String?) { + a?.let { + it.length + } +} \ No newline at end of file diff --git a/idea/testData/quickfix/replaceWithSafeCallForScopeFunction/letWithParam.kt b/idea/testData/quickfix/replaceWithSafeCallForScopeFunction/letWithParam.kt new file mode 100644 index 00000000000..07f3ab39a59 --- /dev/null +++ b/idea/testData/quickfix/replaceWithSafeCallForScopeFunction/letWithParam.kt @@ -0,0 +1,7 @@ +// "Replace scope function with safe (?.) call" "true" +// WITH_RUNTIME +fun foo(a: String?) { + a.let { s -> + s.length + } +} \ No newline at end of file diff --git a/idea/testData/quickfix/replaceWithSafeCallForScopeFunction/letWithParam.kt.after b/idea/testData/quickfix/replaceWithSafeCallForScopeFunction/letWithParam.kt.after new file mode 100644 index 00000000000..8f3e6c675e8 --- /dev/null +++ b/idea/testData/quickfix/replaceWithSafeCallForScopeFunction/letWithParam.kt.after @@ -0,0 +1,7 @@ +// "Replace scope function with safe (?.) call" "true" +// WITH_RUNTIME +fun foo(a: String?) { + a?.let { s -> + s.length + } +} \ No newline at end of file diff --git a/idea/testData/quickfix/replaceWithSafeCallForScopeFunction/letWithWrongImplicitThis.kt b/idea/testData/quickfix/replaceWithSafeCallForScopeFunction/letWithWrongImplicitThis.kt new file mode 100644 index 00000000000..fd37a156781 --- /dev/null +++ b/idea/testData/quickfix/replaceWithSafeCallForScopeFunction/letWithWrongImplicitThis.kt @@ -0,0 +1,13 @@ +// "Replace scope function with safe (?.) call" "false" +// WITH_RUNTIME +// ACTION: Add non-null asserted (!!) call +// ACTION: Introduce local variable +// ACTION: Move lambda argument into parentheses +// ACTION: Replace with safe (this?.) call +// ERROR: Only safe (?.) or non-null asserted (!!.) calls are allowed on a nullable receiver of type String? + +fun String?.foo(a: String?) { + a.let { s -> + length + } +} \ No newline at end of file diff --git a/idea/testData/quickfix/replaceWithSafeCallForScopeFunction/letWithWrongParam.kt b/idea/testData/quickfix/replaceWithSafeCallForScopeFunction/letWithWrongParam.kt new file mode 100644 index 00000000000..234d86249d3 --- /dev/null +++ b/idea/testData/quickfix/replaceWithSafeCallForScopeFunction/letWithWrongParam.kt @@ -0,0 +1,13 @@ +// "Replace scope function with safe (?.) call" "false" +// WITH_RUNTIME +// ACTION: Add non-null asserted (!!) call +// ACTION: Introduce local variable +// ACTION: Replace with safe (?.) call +// ACTION: Surround with null check +// ERROR: Only safe (?.) or non-null asserted (!!.) calls are allowed on a nullable receiver of type String? + +fun foo(a: String?, b: String?) { + a.let { s -> + b.length + } +} \ No newline at end of file diff --git a/idea/testData/quickfix/replaceWithSafeCallForScopeFunction/notInsideScope.kt b/idea/testData/quickfix/replaceWithSafeCallForScopeFunction/notInsideScope.kt new file mode 100644 index 00000000000..4a459a0736b --- /dev/null +++ b/idea/testData/quickfix/replaceWithSafeCallForScopeFunction/notInsideScope.kt @@ -0,0 +1,10 @@ +// "Replace scope function with safe (?.) call" "false" +// ACTION: Add non-null asserted (!!) call +// ACTION: Introduce local variable +// ACTION: Replace with safe (?.) call +// ACTION: Surround with null check +// ERROR: Only safe (?.) or non-null asserted (!!.) calls are allowed on a nullable receiver of type String? +// WITH_RUNTIME +fun foo(a: String?) { + a.length +} \ No newline at end of file diff --git a/idea/testData/quickfix/replaceWithSafeCallForScopeFunction/run.kt b/idea/testData/quickfix/replaceWithSafeCallForScopeFunction/run.kt new file mode 100644 index 00000000000..e1675f73c45 --- /dev/null +++ b/idea/testData/quickfix/replaceWithSafeCallForScopeFunction/run.kt @@ -0,0 +1,7 @@ +// "Replace scope function with safe (?.) call" "true" +// WITH_RUNTIME +fun foo(a: String?) { + a.run { + length + } +} \ No newline at end of file diff --git a/idea/testData/quickfix/replaceWithSafeCallForScopeFunction/run.kt.after b/idea/testData/quickfix/replaceWithSafeCallForScopeFunction/run.kt.after new file mode 100644 index 00000000000..d1dcd84e1b8 --- /dev/null +++ b/idea/testData/quickfix/replaceWithSafeCallForScopeFunction/run.kt.after @@ -0,0 +1,7 @@ +// "Replace scope function with safe (?.) call" "true" +// WITH_RUNTIME +fun foo(a: String?) { + a?.run { + length + } +} \ No newline at end of file diff --git a/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixTestGenerated.java b/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixTestGenerated.java index d9a3d33b0bf..c0dc733186c 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixTestGenerated.java @@ -8763,6 +8763,99 @@ public class QuickFixTestGenerated extends AbstractQuickFixTest { } } + @TestMetadata("idea/testData/quickfix/replaceWithSafeCallForScopeFunction") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class ReplaceWithSafeCallForScopeFunction extends AbstractQuickFixTest { + public void testAllFilesPresentInReplaceWithSafeCallForScopeFunction() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/quickfix/replaceWithSafeCallForScopeFunction"), Pattern.compile("^([\\w\\-_]+)\\.kt$"), TargetBackend.ANY, true); + } + + @TestMetadata("also.kt") + public void testAlso() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/quickfix/replaceWithSafeCallForScopeFunction/also.kt"); + doTest(fileName); + } + + @TestMetadata("applyWithFake.kt") + public void testApplyWithFake() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/quickfix/replaceWithSafeCallForScopeFunction/applyWithFake.kt"); + doTest(fileName); + } + + @TestMetadata("applyWithThis.kt") + public void testApplyWithThis() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/quickfix/replaceWithSafeCallForScopeFunction/applyWithThis.kt"); + doTest(fileName); + } + + @TestMetadata("applyWithThisAndArrow.kt") + public void testApplyWithThisAndArrow() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/quickfix/replaceWithSafeCallForScopeFunction/applyWithThisAndArrow.kt"); + doTest(fileName); + } + + @TestMetadata("applyWithThisLabeled.kt") + public void testApplyWithThisLabeled() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/quickfix/replaceWithSafeCallForScopeFunction/applyWithThisLabeled.kt"); + doTest(fileName); + } + + @TestMetadata("applyWithThisLabeledFake.kt") + public void testApplyWithThisLabeledFake() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/quickfix/replaceWithSafeCallForScopeFunction/applyWithThisLabeledFake.kt"); + doTest(fileName); + } + + @TestMetadata("applyWithoutThis.kt") + public void testApplyWithoutThis() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/quickfix/replaceWithSafeCallForScopeFunction/applyWithoutThis.kt"); + doTest(fileName); + } + + @TestMetadata("applyWithoutThisMethodCall.kt") + public void testApplyWithoutThisMethodCall() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/quickfix/replaceWithSafeCallForScopeFunction/applyWithoutThisMethodCall.kt"); + doTest(fileName); + } + + @TestMetadata("let.kt") + public void testLet() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/quickfix/replaceWithSafeCallForScopeFunction/let.kt"); + doTest(fileName); + } + + @TestMetadata("letWithParam.kt") + public void testLetWithParam() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/quickfix/replaceWithSafeCallForScopeFunction/letWithParam.kt"); + doTest(fileName); + } + + @TestMetadata("letWithWrongImplicitThis.kt") + public void testLetWithWrongImplicitThis() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/quickfix/replaceWithSafeCallForScopeFunction/letWithWrongImplicitThis.kt"); + doTest(fileName); + } + + @TestMetadata("letWithWrongParam.kt") + public void testLetWithWrongParam() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/quickfix/replaceWithSafeCallForScopeFunction/letWithWrongParam.kt"); + doTest(fileName); + } + + @TestMetadata("notInsideScope.kt") + public void testNotInsideScope() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/quickfix/replaceWithSafeCallForScopeFunction/notInsideScope.kt"); + doTest(fileName); + } + + @TestMetadata("run.kt") + public void testRun() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/quickfix/replaceWithSafeCallForScopeFunction/run.kt"); + doTest(fileName); + } + } + @TestMetadata("idea/testData/quickfix/simplifyComparison") @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class)