From e8e51d1db4e37fcb8a2ec5c4b83798e19f8c780f Mon Sep 17 00:00:00 2001 From: Toshiaki Kameyama Date: Thu, 1 Nov 2018 10:13:28 +0900 Subject: [PATCH] Safe cast with return: fix false negative on lambda last statement #KT-27906 Fixed --- .../inspections/SafeCastWithReturnInspection.kt | 7 ++++++- .../safeCastWithReturn/lambdaLastStatement.kt | 7 +++++++ .../safeCastWithReturn/lambdaLastStatement2.kt | 6 ++++++ .../lambdaLastStatement2.kt.after | 6 ++++++ .../safeCastWithReturn/lambdaLastStatement3.kt | 6 ++++++ .../lambdaLastStatement3.kt.after | 6 ++++++ .../inspections/LocalInspectionTestGenerated.java | 15 +++++++++++++++ 7 files changed, 52 insertions(+), 1 deletion(-) create mode 100644 idea/testData/inspectionsLocal/safeCastWithReturn/lambdaLastStatement.kt create mode 100644 idea/testData/inspectionsLocal/safeCastWithReturn/lambdaLastStatement2.kt create mode 100644 idea/testData/inspectionsLocal/safeCastWithReturn/lambdaLastStatement2.kt.after create mode 100644 idea/testData/inspectionsLocal/safeCastWithReturn/lambdaLastStatement3.kt create mode 100644 idea/testData/inspectionsLocal/safeCastWithReturn/lambdaLastStatement3.kt.after diff --git a/idea/src/org/jetbrains/kotlin/idea/inspections/SafeCastWithReturnInspection.kt b/idea/src/org/jetbrains/kotlin/idea/inspections/SafeCastWithReturnInspection.kt index db6ce95fff4..2381dd39eb3 100644 --- a/idea/src/org/jetbrains/kotlin/idea/inspections/SafeCastWithReturnInspection.kt +++ b/idea/src/org/jetbrains/kotlin/idea/inspections/SafeCastWithReturnInspection.kt @@ -30,7 +30,12 @@ class SafeCastWithReturnInspection : AbstractKotlinInspection() { if (KtPsiUtil.deparenthesize(parent.right) !is KtReturnExpression) return val context = expression.analyze(BodyResolveMode.PARTIAL_WITH_DIAGNOSTICS) - if (context[BindingContext.USED_AS_EXPRESSION, parent] == true) return + if (context[BindingContext.USED_AS_EXPRESSION, parent] == true) { + val lambda = expression.getStrictParentOfType() ?: return + if (lambda.functionLiteral.bodyExpression?.statements?.lastOrNull() != parent) return + val call = lambda.getStrictParentOfType() ?: return + if (context[BindingContext.USED_AS_EXPRESSION, call] == true) return + } if (context.diagnostics.forElement(expression.operationReference).any { it.factory == Errors.CAST_NEVER_SUCCEEDS }) return holder.registerProblem( diff --git a/idea/testData/inspectionsLocal/safeCastWithReturn/lambdaLastStatement.kt b/idea/testData/inspectionsLocal/safeCastWithReturn/lambdaLastStatement.kt new file mode 100644 index 00000000000..ca2e1b731f0 --- /dev/null +++ b/idea/testData/inspectionsLocal/safeCastWithReturn/lambdaLastStatement.kt @@ -0,0 +1,7 @@ +// PROBLEM: none +// WITH_RUNTIME +fun test(x: Any) { + val s = run { + x as? String ?: return + } +} \ No newline at end of file diff --git a/idea/testData/inspectionsLocal/safeCastWithReturn/lambdaLastStatement2.kt b/idea/testData/inspectionsLocal/safeCastWithReturn/lambdaLastStatement2.kt new file mode 100644 index 00000000000..dc697b94706 --- /dev/null +++ b/idea/testData/inspectionsLocal/safeCastWithReturn/lambdaLastStatement2.kt @@ -0,0 +1,6 @@ +// WITH_RUNTIME +fun test(x: Any) { + run { + x as? String ?: return + } +} \ No newline at end of file diff --git a/idea/testData/inspectionsLocal/safeCastWithReturn/lambdaLastStatement2.kt.after b/idea/testData/inspectionsLocal/safeCastWithReturn/lambdaLastStatement2.kt.after new file mode 100644 index 00000000000..8e6c6f628e1 --- /dev/null +++ b/idea/testData/inspectionsLocal/safeCastWithReturn/lambdaLastStatement2.kt.after @@ -0,0 +1,6 @@ +// WITH_RUNTIME +fun test(x: Any) { + run { + if (x !is String) return + } +} \ No newline at end of file diff --git a/idea/testData/inspectionsLocal/safeCastWithReturn/lambdaLastStatement3.kt b/idea/testData/inspectionsLocal/safeCastWithReturn/lambdaLastStatement3.kt new file mode 100644 index 00000000000..35c9a95e20a --- /dev/null +++ b/idea/testData/inspectionsLocal/safeCastWithReturn/lambdaLastStatement3.kt @@ -0,0 +1,6 @@ +// WITH_RUNTIME +fun test(x: Any) { + run { + x as? String ?: return@run + } +} \ No newline at end of file diff --git a/idea/testData/inspectionsLocal/safeCastWithReturn/lambdaLastStatement3.kt.after b/idea/testData/inspectionsLocal/safeCastWithReturn/lambdaLastStatement3.kt.after new file mode 100644 index 00000000000..1e06da38818 --- /dev/null +++ b/idea/testData/inspectionsLocal/safeCastWithReturn/lambdaLastStatement3.kt.after @@ -0,0 +1,6 @@ +// WITH_RUNTIME +fun test(x: Any) { + run { + if (x !is String) return@run + } +} \ No newline at end of file diff --git a/idea/tests/org/jetbrains/kotlin/idea/inspections/LocalInspectionTestGenerated.java b/idea/tests/org/jetbrains/kotlin/idea/inspections/LocalInspectionTestGenerated.java index 292ee595071..3c5037c88de 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/inspections/LocalInspectionTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/idea/inspections/LocalInspectionTestGenerated.java @@ -5593,6 +5593,21 @@ public class LocalInspectionTestGenerated extends AbstractLocalInspectionTest { runTest("idea/testData/inspectionsLocal/safeCastWithReturn/labeledReturn.kt"); } + @TestMetadata("lambdaLastStatement.kt") + public void testLambdaLastStatement() throws Exception { + runTest("idea/testData/inspectionsLocal/safeCastWithReturn/lambdaLastStatement.kt"); + } + + @TestMetadata("lambdaLastStatement2.kt") + public void testLambdaLastStatement2() throws Exception { + runTest("idea/testData/inspectionsLocal/safeCastWithReturn/lambdaLastStatement2.kt"); + } + + @TestMetadata("lambdaLastStatement3.kt") + public void testLambdaLastStatement3() throws Exception { + runTest("idea/testData/inspectionsLocal/safeCastWithReturn/lambdaLastStatement3.kt"); + } + @TestMetadata("simple.kt") public void testSimple() throws Exception { runTest("idea/testData/inspectionsLocal/safeCastWithReturn/simple.kt");