From 2683b257288d148573d848f078fc06783055ff54 Mon Sep 17 00:00:00 2001 From: Toshiaki Kameyama Date: Fri, 9 Nov 2018 10:59:35 +0900 Subject: [PATCH] "Change type" quick fix: fix false negative in 'when' branch #KT-8820 Fixed --- .../idea/core/quickfix/QuickFixUtil.java | 29 +++++++++++++++---- idea/testData/quickfix/typeMismatch/when.kt | 7 +++++ .../quickfix/typeMismatch/when.kt.after | 7 +++++ idea/testData/quickfix/typeMismatch/when2.kt | 11 +++++++ .../quickfix/typeMismatch/when2.kt.after | 11 +++++++ idea/testData/quickfix/typeMismatch/when3.kt | 7 +++++ .../quickfix/typeMismatch/when3.kt.after | 7 +++++ .../idea/quickfix/QuickFixTestGenerated.java | 15 ++++++++++ 8 files changed, 88 insertions(+), 6 deletions(-) create mode 100644 idea/testData/quickfix/typeMismatch/when.kt create mode 100644 idea/testData/quickfix/typeMismatch/when.kt.after create mode 100644 idea/testData/quickfix/typeMismatch/when2.kt create mode 100644 idea/testData/quickfix/typeMismatch/when2.kt.after create mode 100644 idea/testData/quickfix/typeMismatch/when3.kt create mode 100644 idea/testData/quickfix/typeMismatch/when3.kt.after diff --git a/idea/ide-common/src/org/jetbrains/kotlin/idea/core/quickfix/QuickFixUtil.java b/idea/ide-common/src/org/jetbrains/kotlin/idea/core/quickfix/QuickFixUtil.java index 0652d891a57..bcb126eb00e 100644 --- a/idea/ide-common/src/org/jetbrains/kotlin/idea/core/quickfix/QuickFixUtil.java +++ b/idea/ide-common/src/org/jetbrains/kotlin/idea/core/quickfix/QuickFixUtil.java @@ -105,9 +105,9 @@ public class QuickFixUtil { return declaration instanceof KtParameter ? (KtParameter) declaration : null; } - private static boolean equalOrLastInThenOrElse(KtExpression thenOrElse, KtExpression expression) { - if (thenOrElse == expression) return true; - return thenOrElse instanceof KtBlockExpression && expression.getParent() == thenOrElse && + private static boolean equalOrLastInBlock(KtExpression block, KtExpression expression) { + if (block == expression) return true; + return block instanceof KtBlockExpression && expression.getParent() == block && PsiTreeUtil.getNextSiblingOfType(expression, KtExpression.class) == null; } @@ -115,13 +115,30 @@ public class QuickFixUtil { public static KtIfExpression getParentIfForBranch(@Nullable KtExpression expression) { KtIfExpression ifExpression = PsiTreeUtil.getParentOfType(expression, KtIfExpression.class, true); if (ifExpression == null) return null; - if (equalOrLastInThenOrElse(ifExpression.getThen(), expression) - || equalOrLastInThenOrElse(ifExpression.getElse(), expression)) { + if (equalOrLastInBlock(ifExpression.getThen(), expression) + || equalOrLastInBlock(ifExpression.getElse(), expression)) { return ifExpression; } return null; } + @Nullable + private static KtWhenExpression getParentWhenForBranch(@Nullable KtExpression expression) { + KtWhenEntry whenEntry = PsiTreeUtil.getParentOfType(expression, KtWhenEntry.class, true); + if (whenEntry == null) return null; + KtExpression whenEntryExpression = whenEntry.getExpression(); + if (whenEntryExpression == null) return null; + if (!equalOrLastInBlock(whenEntryExpression, expression)) return null; + return PsiTreeUtil.getParentOfType(whenEntry, KtWhenExpression.class, true); + } + + @Nullable + private static KtExpression getParentForBranch(@Nullable KtExpression expression) { + KtExpression parent = getParentIfForBranch(expression); + if (parent != null) return parent; + return getParentWhenForBranch(expression); + } + // Returns true iff parent's value always or sometimes is evaluable to child's value, e.g. // parent = (x), child = x; // parent = if (...) x else y, child = x; @@ -141,7 +158,7 @@ public class QuickFixUtil { child = (KtExpression) childParent; continue; } - child = getParentIfForBranch(child); + child = getParentForBranch(child); if (child == null) return false; } return true; diff --git a/idea/testData/quickfix/typeMismatch/when.kt b/idea/testData/quickfix/typeMismatch/when.kt new file mode 100644 index 00000000000..6b58ca42f2e --- /dev/null +++ b/idea/testData/quickfix/typeMismatch/when.kt @@ -0,0 +1,7 @@ +// "Change return type of enclosing function 'test' to 'String'" "true" +fun test(i: Int) { + return when (i) { + 0 -> "" + else -> "" + } +} \ No newline at end of file diff --git a/idea/testData/quickfix/typeMismatch/when.kt.after b/idea/testData/quickfix/typeMismatch/when.kt.after new file mode 100644 index 00000000000..2be4539163f --- /dev/null +++ b/idea/testData/quickfix/typeMismatch/when.kt.after @@ -0,0 +1,7 @@ +// "Change return type of enclosing function 'test' to 'String'" "true" +fun test(i: Int): String { + return when (i) { + 0 -> "" + else -> "" + } +} \ No newline at end of file diff --git a/idea/testData/quickfix/typeMismatch/when2.kt b/idea/testData/quickfix/typeMismatch/when2.kt new file mode 100644 index 00000000000..e27697525eb --- /dev/null +++ b/idea/testData/quickfix/typeMismatch/when2.kt @@ -0,0 +1,11 @@ +// "Change return type of enclosing function 'test' to 'String'" "true" +fun test(i: Int) { + return when (i) { + 0 -> { + "" + } + else -> { + "" + } + } +} \ No newline at end of file diff --git a/idea/testData/quickfix/typeMismatch/when2.kt.after b/idea/testData/quickfix/typeMismatch/when2.kt.after new file mode 100644 index 00000000000..04905802f65 --- /dev/null +++ b/idea/testData/quickfix/typeMismatch/when2.kt.after @@ -0,0 +1,11 @@ +// "Change return type of enclosing function 'test' to 'String'" "true" +fun test(i: Int): String { + return when (i) { + 0 -> { + "" + } + else -> { + "" + } + } +} \ No newline at end of file diff --git a/idea/testData/quickfix/typeMismatch/when3.kt b/idea/testData/quickfix/typeMismatch/when3.kt new file mode 100644 index 00000000000..97b2262c323 --- /dev/null +++ b/idea/testData/quickfix/typeMismatch/when3.kt @@ -0,0 +1,7 @@ +// "Change type of 's' to 'String'" "true" +fun test(i: Int) { + val s: Int = when (i) { + 0 -> "" + else -> "" + } +} \ No newline at end of file diff --git a/idea/testData/quickfix/typeMismatch/when3.kt.after b/idea/testData/quickfix/typeMismatch/when3.kt.after new file mode 100644 index 00000000000..0a97b2708cb --- /dev/null +++ b/idea/testData/quickfix/typeMismatch/when3.kt.after @@ -0,0 +1,7 @@ +// "Change type of 's' to 'String'" "true" +fun test(i: Int) { + val s: String = when (i) { + 0 -> "" + else -> "" + } +} \ 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 14458e1d635..9531364d793 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixTestGenerated.java @@ -11843,6 +11843,21 @@ public class QuickFixTestGenerated extends AbstractQuickFixTest { runTest("idea/testData/quickfix/typeMismatch/unresolvableTypeParams.kt"); } + @TestMetadata("when.kt") + public void testWhen() throws Exception { + runTest("idea/testData/quickfix/typeMismatch/when.kt"); + } + + @TestMetadata("when2.kt") + public void testWhen2() throws Exception { + runTest("idea/testData/quickfix/typeMismatch/when2.kt"); + } + + @TestMetadata("when3.kt") + public void testWhen3() throws Exception { + runTest("idea/testData/quickfix/typeMismatch/when3.kt"); + } + @TestMetadata("idea/testData/quickfix/typeMismatch/casts") @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class)