From 55c9701fc8de547d8abd9c5fa60ba9903d1e1dec Mon Sep 17 00:00:00 2001 From: Mikhail Pyltsin Date: Wed, 3 Apr 2024 19:58:22 +0200 Subject: [PATCH] [java-completion] IJ-CR-129761 IDEA-349764 Suggest a full catch section - catch sections are added automatically GitOrigin-RevId: 75aed0b2281ffa0e412b1eaecf90caf406ba0182 --- .../completion/CatchLookupElement.java | 26 +++--- .../normal/EmptyTryCatch_after.java | 8 +- .../ManyUnhandledCheckedExceptions_after.java | 88 +++++++++---------- ...dCheckedExceptionsWithAllCaught_after.java | 16 ++-- ...ndledCheckedExceptionsWithCatch_after.java | 14 +-- ...ledCheckedExceptionsWithDefault_after.java | 14 +-- ...ckedExceptionsWithExistedImport_after.java | 10 +-- ...dledCheckedExceptionsWithImport_after.java | 10 +-- ...ledCheckedExceptionsWithParents_after.java | 14 +-- ...dExceptionsWithRuntimeException_after.java | 14 +-- .../UnhandledCheckedExceptions_after.java | 12 +-- .../UnhandledRuntimeExceptions_after.java | 12 +-- .../NormalCatchSectionCompletionTest.java | 17 +++- .../completion/NormalCompletionTest.java | 4 +- 14 files changed, 138 insertions(+), 121 deletions(-) diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/CatchLookupElement.java b/java/java-impl/src/com/intellij/codeInsight/completion/CatchLookupElement.java index a5f97cfeb2c7..cdbb5b20bb17 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/CatchLookupElement.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/CatchLookupElement.java @@ -2,13 +2,14 @@ package com.intellij.codeInsight.completion; import com.intellij.codeInsight.ExceptionUtil; -import com.intellij.codeInsight.editorActions.smartEnter.JavaSmartEnterProcessor; +import com.intellij.codeInsight.generation.surroundWith.SurroundWithUtil; import com.intellij.codeInsight.lookup.LookupElement; import com.intellij.codeInsight.lookup.LookupElementPresentation; import com.intellij.codeInsight.lookup.LookupItem; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.project.DumbService; import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.TextRange; import com.intellij.psi.*; import com.intellij.psi.codeStyle.CodeStyleManager; import com.intellij.psi.codeStyle.JavaCodeStyleManager; @@ -71,11 +72,20 @@ final class CatchLookupElement extends LookupItem { if (element != null) { JavaCodeStyleManager codeStyleManager = JavaCodeStyleManager.getInstance(project); PsiElement finalElement = element; - DumbService.getInstance(project) - .runWithAlternativeResolveEnabled(() -> codeStyleManager.shortenClassReferences(finalElement)); + element = DumbService.getInstance(project) + .computeWithAlternativeResolveEnabled(() -> codeStyleManager.shortenClassReferences(finalElement)); } PsiDocumentManager.getInstance(project).commitDocument(editor.getDocument()); - new JavaSmartEnterProcessor().process(project, editor, context.getFile()); + + if (element instanceof PsiCatchSection catchSection) { + catchSection = (PsiCatchSection)CodeStyleManager.getInstance(project).reformat(catchSection); + PsiCodeBlock catchBlock = catchSection.getCatchBlock(); + if (catchBlock != null) { + TextRange rangeToSelect = SurroundWithUtil.getRangeToSelect(catchBlock); + context.getEditor().getSelectionModel().setSelection(rangeToSelect.getStartOffset(), rangeToSelect.getEndOffset()); + editor.getCaretModel().moveToOffset(rangeToSelect.getEndOffset()); + } + } } @NotNull @@ -141,13 +151,7 @@ final class CatchLookupElement extends LookupItem { String name = new VariableNameGenerator(tryStatement, VariableKind.PARAMETER).byName("e", "ex", "exc").generate(false); PsiCatchSection catchSection = factory.createCatchSection(exceptionType, name, tryStatement); - catchSection = (PsiCatchSection)CodeStyleManager.getInstance(project).reformat(catchSection); - PsiJavaToken rParenth = catchSection.getRParenth(); - if (rParenth == null) { - return List.of(); - } - int offset = rParenth.getTextRangeInParent().getEndOffset(); - String catchSectionText = catchSection.getText().substring(0, offset); + String catchSectionText = catchSection.getText(); lookupElements.add(new CatchLookupElement(catchSection, catchSectionText)); if (lookupElements.size() >= MAX_LOOKUP_SIZE) { break; diff --git a/java/java-tests/testData/codeInsight/completion/normal/EmptyTryCatch_after.java b/java/java-tests/testData/codeInsight/completion/normal/EmptyTryCatch_after.java index 6f0c1bb97599..8d403f525ceb 100644 --- a/java/java-tests/testData/codeInsight/completion/normal/EmptyTryCatch_after.java +++ b/java/java-tests/testData/codeInsight/completion/normal/EmptyTryCatch_after.java @@ -1,8 +1,8 @@ class X{ public void test() { - try { - } catch (Exception e) { - - } + try { + } catch (Exception e) { + throw new RuntimeException(e); + } } } diff --git a/java/java-tests/testData/codeInsight/completion/normal/ManyUnhandledCheckedExceptions_after.java b/java/java-tests/testData/codeInsight/completion/normal/ManyUnhandledCheckedExceptions_after.java index 30f43a5c9f23..aea4657c98d0 100644 --- a/java/java-tests/testData/codeInsight/completion/normal/ManyUnhandledCheckedExceptions_after.java +++ b/java/java-tests/testData/codeInsight/completion/normal/ManyUnhandledCheckedExceptions_after.java @@ -4,50 +4,50 @@ class X{ class CheckedException2 extends Exception { } public void test() { - try { - method1(); - method1(); - method1(); - method1(); - method1(); - method1(); - method1(); - method1(); - method1(); - method1(); - method1(); - method1(); - method1(); - method1(); - method1(); - method1(); - method1(); - method1(); - method1(); - method1(); - method1(); - method1(); - method1(); - method1(); - method1(); - method1(); - method1(); - method1(); - method1(); - method1(); - method1(); - method1(); - method1(); - method1(); - method1(); - method1(); - method1(); - method1(); - method1(); - throw new CheckedException2(); - } catch (Exception e) { - - } + try { + method1(); + method1(); + method1(); + method1(); + method1(); + method1(); + method1(); + method1(); + method1(); + method1(); + method1(); + method1(); + method1(); + method1(); + method1(); + method1(); + method1(); + method1(); + method1(); + method1(); + method1(); + method1(); + method1(); + method1(); + method1(); + method1(); + method1(); + method1(); + method1(); + method1(); + method1(); + method1(); + method1(); + method1(); + method1(); + method1(); + method1(); + method1(); + method1(); + throw new CheckedException2(); + } catch (Exception e) { + throw new RuntimeException(e); + } } private void method1() throws CheckedException1{ diff --git a/java/java-tests/testData/codeInsight/completion/normal/UnhandledCheckedExceptionsWithAllCaught_after.java b/java/java-tests/testData/codeInsight/completion/normal/UnhandledCheckedExceptionsWithAllCaught_after.java index e1732098aef4..234c092c794b 100644 --- a/java/java-tests/testData/codeInsight/completion/normal/UnhandledCheckedExceptionsWithAllCaught_after.java +++ b/java/java-tests/testData/codeInsight/completion/normal/UnhandledCheckedExceptionsWithAllCaught_after.java @@ -4,14 +4,14 @@ class X{ class CheckedException2 extends Exception { } public void test() { - try { - method1(); - throw new CheckedException2(); - } catch (CheckedException1 e) { - } catch (CheckedException2 e) { - } catch (Exception e) { - - } + try { + method1(); + throw new CheckedException2(); + } catch(CheckedException1 e) { + } catch(CheckedException2 e) { + } catch (Exception e) { + throw new RuntimeException(e); + } } private void method1() throws CheckedException1{ diff --git a/java/java-tests/testData/codeInsight/completion/normal/UnhandledCheckedExceptionsWithCatch_after.java b/java/java-tests/testData/codeInsight/completion/normal/UnhandledCheckedExceptionsWithCatch_after.java index d4d4dcc0603a..a52fb7ecd0ca 100644 --- a/java/java-tests/testData/codeInsight/completion/normal/UnhandledCheckedExceptionsWithCatch_after.java +++ b/java/java-tests/testData/codeInsight/completion/normal/UnhandledCheckedExceptionsWithCatch_after.java @@ -4,13 +4,13 @@ class X{ class CheckedException2 extends Exception { } public void test() { - try { - method1(); - throw new CheckedException2(); - } catch (CheckedException2 e) { - } catch (CheckedException1 e) { - - } + try { + method1(); + throw new CheckedException2(); + } catch(CheckedException2 e) { + } catch (CheckedException1 e) { + throw new RuntimeException(e); + } } private void method1() throws CheckedException1{ diff --git a/java/java-tests/testData/codeInsight/completion/normal/UnhandledCheckedExceptionsWithDefault_after.java b/java/java-tests/testData/codeInsight/completion/normal/UnhandledCheckedExceptionsWithDefault_after.java index cd576d3adb5c..2d2cd1af6e13 100644 --- a/java/java-tests/testData/codeInsight/completion/normal/UnhandledCheckedExceptionsWithDefault_after.java +++ b/java/java-tests/testData/codeInsight/completion/normal/UnhandledCheckedExceptionsWithDefault_after.java @@ -6,13 +6,13 @@ class X{ class CheckedException3 extends Exception { } public void test() { - try { - method1(); - throw new CheckedException2(); - throw new CheckedException3(); - } catch (Exception e) { - - } + try { + method1(); + throw new CheckedException2(); + throw new CheckedException3(); + } catch (Exception e) { + throw new RuntimeException(e); + } } private void method1() throws CheckedException1{ diff --git a/java/java-tests/testData/codeInsight/completion/normal/UnhandledCheckedExceptionsWithExistedImport_after.java b/java/java-tests/testData/codeInsight/completion/normal/UnhandledCheckedExceptionsWithExistedImport_after.java index 22fe8914163d..ef8aa762a07f 100644 --- a/java/java-tests/testData/codeInsight/completion/normal/UnhandledCheckedExceptionsWithExistedImport_after.java +++ b/java/java-tests/testData/codeInsight/completion/normal/UnhandledCheckedExceptionsWithExistedImport_after.java @@ -4,10 +4,10 @@ import com.test2.Test; class X{ public void test() { - try { - Test.test(); - } catch (TestException e) { - - } + try { + Test.test(); + } catch (TestException e) { + throw new RuntimeException(e); + } } } diff --git a/java/java-tests/testData/codeInsight/completion/normal/UnhandledCheckedExceptionsWithImport_after.java b/java/java-tests/testData/codeInsight/completion/normal/UnhandledCheckedExceptionsWithImport_after.java index 22fe8914163d..ef8aa762a07f 100644 --- a/java/java-tests/testData/codeInsight/completion/normal/UnhandledCheckedExceptionsWithImport_after.java +++ b/java/java-tests/testData/codeInsight/completion/normal/UnhandledCheckedExceptionsWithImport_after.java @@ -4,10 +4,10 @@ import com.test2.Test; class X{ public void test() { - try { - Test.test(); - } catch (TestException e) { - - } + try { + Test.test(); + } catch (TestException e) { + throw new RuntimeException(e); + } } } diff --git a/java/java-tests/testData/codeInsight/completion/normal/UnhandledCheckedExceptionsWithParents_after.java b/java/java-tests/testData/codeInsight/completion/normal/UnhandledCheckedExceptionsWithParents_after.java index e2fc32db180b..832c6ee8c386 100644 --- a/java/java-tests/testData/codeInsight/completion/normal/UnhandledCheckedExceptionsWithParents_after.java +++ b/java/java-tests/testData/codeInsight/completion/normal/UnhandledCheckedExceptionsWithParents_after.java @@ -6,13 +6,13 @@ class X{ class CheckedException2 extends CheckedException { } public void test() { - try { - method1(); - throw new CheckedException2(); - } catch (CheckedException e) { - } catch (Exception e) { - - } + try { + method1(); + throw new CheckedException2(); + } catch(CheckedException e) { + } catch (Exception e) { + throw new RuntimeException(e); + } } private void method1() throws CheckedException1{ diff --git a/java/java-tests/testData/codeInsight/completion/normal/UnhandledCheckedExceptionsWithRuntimeException_after.java b/java/java-tests/testData/codeInsight/completion/normal/UnhandledCheckedExceptionsWithRuntimeException_after.java index ca2d2ddceef1..93c1d4e97ce9 100644 --- a/java/java-tests/testData/codeInsight/completion/normal/UnhandledCheckedExceptionsWithRuntimeException_after.java +++ b/java/java-tests/testData/codeInsight/completion/normal/UnhandledCheckedExceptionsWithRuntimeException_after.java @@ -4,13 +4,13 @@ class X{ class CheckedException2 extends Exception { } public void test() { - try { - method1(); - throw new CheckedException2(); - throw new RuntimeException(); - } catch (CheckedException1 e) { - - } + try { + method1(); + throw new CheckedException2(); + throw new RuntimeException(); + } catch (CheckedException1 e) { + throw new RuntimeException(e); + } } private void method1() throws CheckedException1{ diff --git a/java/java-tests/testData/codeInsight/completion/normal/UnhandledCheckedExceptions_after.java b/java/java-tests/testData/codeInsight/completion/normal/UnhandledCheckedExceptions_after.java index a932c7d773ac..10b3bbe8962a 100644 --- a/java/java-tests/testData/codeInsight/completion/normal/UnhandledCheckedExceptions_after.java +++ b/java/java-tests/testData/codeInsight/completion/normal/UnhandledCheckedExceptions_after.java @@ -4,12 +4,12 @@ class X{ class CheckedException2 extends Exception { } public void test() { - try { - method1(); - throw new CheckedException2(); - } catch (CheckedException1 e) { - - } + try { + method1(); + throw new CheckedException2(); + } catch (CheckedException1 e) { + throw new RuntimeException(e); + } } private void method1() throws CheckedException1{ diff --git a/java/java-tests/testData/codeInsight/completion/normal/UnhandledRuntimeExceptions_after.java b/java/java-tests/testData/codeInsight/completion/normal/UnhandledRuntimeExceptions_after.java index 80e5fe674734..c4c1bf58a00e 100644 --- a/java/java-tests/testData/codeInsight/completion/normal/UnhandledRuntimeExceptions_after.java +++ b/java/java-tests/testData/codeInsight/completion/normal/UnhandledRuntimeExceptions_after.java @@ -4,12 +4,12 @@ class X{ class CheckedException2 extends RuntimeException { } public void test() { - try { - method1(); - throw new CheckedException2(); - } catch (CheckedException1 e) { - - } + try { + method1(); + throw new CheckedException2(); + } catch (CheckedException1 e) { + throw new RuntimeException(e); + } } private void method1() throws CheckedException1{ diff --git a/java/java-tests/testSrc/com/intellij/java/codeInsight/completion/NormalCatchSectionCompletionTest.java b/java/java-tests/testSrc/com/intellij/java/codeInsight/completion/NormalCatchSectionCompletionTest.java index 75e4971ee856..a52703e755eb 100644 --- a/java/java-tests/testSrc/com/intellij/java/codeInsight/completion/NormalCatchSectionCompletionTest.java +++ b/java/java-tests/testSrc/com/intellij/java/codeInsight/completion/NormalCatchSectionCompletionTest.java @@ -7,6 +7,7 @@ import com.intellij.testFramework.LightProjectDescriptor; import com.intellij.testFramework.NeedsIndex; import org.jetbrains.annotations.NotNull; +import java.util.Arrays; import java.util.List; @SuppressWarnings("RedundantThrows") @@ -53,7 +54,7 @@ public class NormalCatchSectionCompletionTest extends NormalCompletionTestCase { configure(); - assertEquals(List.of("catch", "catch (TestException e)"), myFixture.getLookupElementStrings()); + checkRenderedItems(List.of("catch", "catch (TestException e)")); LookupElement element = myItems[1]; LookupElementPresentation presentation = renderElement(element); @@ -81,7 +82,7 @@ public class NormalCatchSectionCompletionTest extends NormalCompletionTestCase { configure(); - assertEquals(List.of("catch", "catch (com.test.TestException e)"), myFixture.getLookupElementStrings()); + checkRenderedItems(List.of("catch", "catch (TestException e)")); LookupElement element = myItems[1]; LookupElementPresentation presentation = renderElement(element); @@ -118,10 +119,20 @@ public class NormalCatchSectionCompletionTest extends NormalCompletionTestCase { private void simpleTestCatchSection(@NotNull List catches) { configure(); - assertEquals(catches, myFixture.getLookupElementStrings()); + checkRenderedItems(catches); selectItem(myItems[1]); checkResult(); } + + private void checkRenderedItems(@NotNull List catches) { + List renderedItems = Arrays.stream(myItems).map(t -> { + LookupElementPresentation presentation = new LookupElementPresentation(); + t.renderElement(presentation); + return (presentation.getItemText() != null ? presentation.getItemText() : "") + + (presentation.getTailText() != null ? presentation.getTailText() : ""); + }).toList(); + assertEquals(catches, renderedItems); + } } diff --git a/java/java-tests/testSrc/com/intellij/java/codeInsight/completion/NormalCompletionTest.java b/java/java-tests/testSrc/com/intellij/java/codeInsight/completion/NormalCompletionTest.java index de11fd36bb1a..6b987c6ef8ce 100644 --- a/java/java-tests/testSrc/com/intellij/java/codeInsight/completion/NormalCompletionTest.java +++ b/java/java-tests/testSrc/com/intellij/java/codeInsight/completion/NormalCompletionTest.java @@ -2505,7 +2505,9 @@ public class NormalCompletionTest extends NormalCompletionTestCase { myFixture.configureByText("Test.java", "class X{X() {try {}}}"); myFixture.completeBasic(); assertEquals(myFixture.getLookupElementStrings(), - List.of("catch", "finally", "catch (Exception e)", "catch (RuntimeException e)")); + List.of("catch", "finally", + "catch (Exception e) {\n throw new RuntimeException(e);\n}", + "catch (RuntimeException e) {\n throw new RuntimeException(e);\n}")); } @NeedsIndex.ForStandardLibrary