From c6fbff80c0704b0b4573de7b6411110d29307284 Mon Sep 17 00:00:00 2001 From: Tagir Valeev Date: Thu, 2 Nov 2023 14:50:57 +0100 Subject: [PATCH] [java-refactoring] Inline variable: improve behavior in the presence of compilation errors 1. Properly forward the AnalysisCancelledException 2. Allow inlining of never overwritten variable in the presence of syntax errors Fixes IDEA-336815 "Inline variable" misleading error message when compile-errors are present GitOrigin-RevId: 7510d497fce2dcd4bef38482cfadf162d47cc2c0 --- .../inline/InlineLocalHandler.java | 20 +++++++++++++++---- .../inlineLocal/CompilationError.java | 11 ++++++++++ .../inlineLocal/CompilationError.java.after | 11 ++++++++++ .../CompilationErrorAssignment.java | 12 +++++++++++ .../refactoring/inline/InlineLocalTest.java | 9 +++++++++ 5 files changed, 59 insertions(+), 4 deletions(-) create mode 100644 java/java-tests/testData/refactoring/inlineLocal/CompilationError.java create mode 100644 java/java-tests/testData/refactoring/inlineLocal/CompilationError.java.after create mode 100644 java/java-tests/testData/refactoring/inlineLocal/CompilationErrorAssignment.java diff --git a/java/java-impl-refactorings/src/com/intellij/refactoring/inline/InlineLocalHandler.java b/java/java-impl-refactorings/src/com/intellij/refactoring/inline/InlineLocalHandler.java index 9ebcf8a9a9a0..21e3a70ddfc8 100644 --- a/java/java-impl-refactorings/src/com/intellij/refactoring/inline/InlineLocalHandler.java +++ b/java/java-impl-refactorings/src/com/intellij/refactoring/inline/InlineLocalHandler.java @@ -199,14 +199,26 @@ public class InlineLocalHandler extends JavaInlineActionHandler { } List refsToInlineList = new ArrayList<>(); + boolean simpleInlining = false; if (mode == InlineMode.INLINE_ONE) { refsToInlineList.add(refExpr); } else { - try { - Collections.addAll(refsToInlineList, DefUseUtil.getRefs(containerBlock, local, defToInline)); + if (defToInline == local.getInitializer()) { + // Do not rely on ref-def analysis in a simple case when we inline an initializer and there are no subsequent writes. + // This allows inlining in the presense of syntax errors. + List refs = VariableAccessUtils.getVariableReferences(local, containerBlock); + if (!ContainerUtil.exists(refs, ref -> PsiUtil.isAccessedForWriting(ref))) { + simpleInlining = true; + refsToInlineList.addAll(refs); + } } - catch (RuntimeException e) { - return processWrappedAnalysisCanceledException(e); + if (!simpleInlining) { + try { + Collections.addAll(refsToInlineList, DefUseUtil.getRefs(containerBlock, local, defToInline, true)); + } + catch (RuntimeException e) { + return processWrappedAnalysisCanceledException(e); + } } for (PsiElement innerClassUsage : innerClassUses.innerClassUsages()) { if (!refsToInlineList.contains(innerClassUsage)) { diff --git a/java/java-tests/testData/refactoring/inlineLocal/CompilationError.java b/java/java-tests/testData/refactoring/inlineLocal/CompilationError.java new file mode 100644 index 000000000000..7eeee5dd2db9 --- /dev/null +++ b/java/java-tests/testData/refactoring/inlineLocal/CompilationError.java @@ -0,0 +1,11 @@ +public class CompilationError { + + public void test() { + public static void main(String[] args) { + int inlineMe = 3; // inline + int dd = 4 + inlineMe; + + "Error". + } + } +} \ No newline at end of file diff --git a/java/java-tests/testData/refactoring/inlineLocal/CompilationError.java.after b/java/java-tests/testData/refactoring/inlineLocal/CompilationError.java.after new file mode 100644 index 000000000000..758e6487d9df --- /dev/null +++ b/java/java-tests/testData/refactoring/inlineLocal/CompilationError.java.after @@ -0,0 +1,11 @@ +public class CompilationError { + + public void test() { + public static void main(String[] args) { + // inline + int dd = 4 + 3; + + "Error". + } + } +} \ No newline at end of file diff --git a/java/java-tests/testData/refactoring/inlineLocal/CompilationErrorAssignment.java b/java/java-tests/testData/refactoring/inlineLocal/CompilationErrorAssignment.java new file mode 100644 index 000000000000..a31db76a2fbb --- /dev/null +++ b/java/java-tests/testData/refactoring/inlineLocal/CompilationErrorAssignment.java @@ -0,0 +1,12 @@ +public class CompilationError { + + public void test() { + public static void main(String[] args) { + int inlineMe = 2; + inlineMe = 3; // inline + int dd = 4 + inlineMe; + + "Error". + } + } +} \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/java/refactoring/inline/InlineLocalTest.java b/java/java-tests/testSrc/com/intellij/java/refactoring/inline/InlineLocalTest.java index 809dc040425f..a2a7b89f521c 100644 --- a/java/java-tests/testSrc/com/intellij/java/refactoring/inline/InlineLocalTest.java +++ b/java/java-tests/testSrc/com/intellij/java/refactoring/inline/InlineLocalTest.java @@ -342,6 +342,15 @@ public class InlineLocalTest extends LightJavaCodeInsightTestCase { public void testUnusedReassignmentInLoop() { doTest(); } + + public void testCompilationError() { + doTest(); + } + + public void testCompilationErrorAssignment() { + doTest("Cannot perform refactoring.\n" + + "Code contains syntax errors. Cannot perform necessary analysis."); + } public void testEolComment() { doTest();