From bc9a1a4ba21657b4c48dd757c00b4b649de27524 Mon Sep 17 00:00:00 2001 From: Tagir Valeev Date: Fri, 23 Aug 2019 18:40:35 +0700 Subject: [PATCH] JoinLinesHandler: separate processing of raw handlers; disable formatting for PSI handlers GitOrigin-RevId: 59f8fe15c8ca883f02f968ac08a5aa490d4686b2 --- .../NestedIfJoinLinesHandler.java | 22 ++-- .../joinLines/CallChainLineBreak_after.java | 3 +- .../codeInsight/joinLines/ConvertMixed.java | 17 +++ .../joinLines/ConvertMixed_after.java | 5 + .../joinLines/IfChainSelection.java | 4 +- .../joinLines/WrongWrapping_after.java | 2 +- .../java/codeInsight/JoinLinesTest.java | 1 + .../editorActions/JoinLinesHandler.java | 118 ++++++++++++------ 8 files changed, 119 insertions(+), 53 deletions(-) create mode 100644 java/java-tests/testData/codeInsight/joinLines/ConvertMixed.java create mode 100644 java/java-tests/testData/codeInsight/joinLines/ConvertMixed_after.java diff --git a/java/java-impl/src/com/intellij/codeInsight/editorActions/NestedIfJoinLinesHandler.java b/java/java-impl/src/com/intellij/codeInsight/editorActions/NestedIfJoinLinesHandler.java index 064b18fe977a..729de70c3e2a 100644 --- a/java/java-impl/src/com/intellij/codeInsight/editorActions/NestedIfJoinLinesHandler.java +++ b/java/java-impl/src/com/intellij/codeInsight/editorActions/NestedIfJoinLinesHandler.java @@ -4,11 +4,12 @@ package com.intellij.codeInsight.editorActions; import com.intellij.openapi.editor.Document; import com.intellij.psi.*; import com.intellij.psi.util.PsiTreeUtil; -import com.siyeh.ig.psiutils.CommentTracker; import com.siyeh.ig.psiutils.ControlFlowUtils; import com.siyeh.ig.psiutils.ParenthesesUtils; import org.jetbrains.annotations.NotNull; +import java.util.Objects; + import static com.intellij.util.ObjectUtils.tryCast; /** @@ -52,13 +53,20 @@ public class NestedIfJoinLinesHandler implements JoinLinesHandlerDelegate { if (outerCondition == null) return CANNOT_JOIN; PsiExpression innerCondition = innerIf.getCondition(); if (innerCondition == null) return CANNOT_JOIN; + PsiJavaToken lParenth = outerIf.getLParenth(); + PsiJavaToken rParenth = innerIf.getRParenth(); + if (lParenth == null || rParenth == null) return CANNOT_JOIN; - CommentTracker ct = new CommentTracker(); - String childConditionText = ParenthesesUtils.getText(ct.markUnchanged(innerCondition), ParenthesesUtils.OR_PRECEDENCE); - String parentConditionText = ParenthesesUtils.getText(ct.markUnchanged(outerCondition), ParenthesesUtils.OR_PRECEDENCE); + String childConditionText = ParenthesesUtils.getText(innerCondition, ParenthesesUtils.OR_PRECEDENCE); + String parentConditionText = ParenthesesUtils.getText(outerCondition, ParenthesesUtils.OR_PRECEDENCE); - PsiElement newCondition = ct.replace(outerCondition, parentConditionText + "&&" + childConditionText); - ct.replaceAndRestoreComments(outerIf.getThenBranch(), innerIf.getThenBranch()); - return newCondition.getTextRange().getStartOffset() + parentConditionText.length() + 1; + PsiElementFactory factory = JavaPsiFacade.getElementFactory(psiFile.getProject()); + String condition = parentConditionText + " && " + childConditionText; + String resultText = outerIf.getText().substring(0, lParenth.getTextRangeInParent().getEndOffset()) + + condition + innerIf.getText().substring(rParenth.getTextRangeInParent().getStartOffset()); + PsiStatement statement = factory.createStatementFromText(resultText, outerIf); + PsiIfStatement result = (PsiIfStatement)outerIf.replace(statement); + return Objects.requireNonNull(result.getCondition()).getTextRange().getStartOffset() + + parentConditionText.length() + 2; } } diff --git a/java/java-tests/testData/codeInsight/joinLines/CallChainLineBreak_after.java b/java/java-tests/testData/codeInsight/joinLines/CallChainLineBreak_after.java index 336ae54c7a33..c2ca45bed378 100644 --- a/java/java-tests/testData/codeInsight/joinLines/CallChainLineBreak_after.java +++ b/java/java-tests/testData/codeInsight/joinLines/CallChainLineBreak_after.java @@ -1,7 +1,6 @@ class Foo { void test() { StringBuilder sb = new StringBuilder(); - sb.append("long-long-long-long-long-long-long-long-long-long-long-long-long-long-long") - .append("long-long-long-long-long-long-long-long-long-long-long-long-long-long-long"); + sb.append("long-long-long-long-long-long-long-long-long-long-long-long-long-long-long").append("long-long-long-long-long-long-long-long-long-long-long-long-long-long-long"); } } \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/joinLines/ConvertMixed.java b/java/java-tests/testData/codeInsight/joinLines/ConvertMixed.java new file mode 100644 index 000000000000..30b1ff879ac7 --- /dev/null +++ b/java/java-tests/testData/codeInsight/joinLines/ConvertMixed.java @@ -0,0 +1,17 @@ +class A { + void test() { + /* hello + one + two + three + */ + int foo; + foo = 5; + int bar = 0; + bar = 6; + int baz; /* goodbye + one + two + three */ + } +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/joinLines/ConvertMixed_after.java b/java/java-tests/testData/codeInsight/joinLines/ConvertMixed_after.java new file mode 100644 index 000000000000..ca736c5b3db3 --- /dev/null +++ b/java/java-tests/testData/codeInsight/joinLines/ConvertMixed_after.java @@ -0,0 +1,5 @@ +class A { + void test() { + /* hello one two three */int foo = 5;int bar = 6;int baz; /* goodbye one two three */ + } +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/joinLines/IfChainSelection.java b/java/java-tests/testData/codeInsight/joinLines/IfChainSelection.java index 4b70f5a32251..c491d0a1c902 100644 --- a/java/java-tests/testData/codeInsight/joinLines/IfChainSelection.java +++ b/java/java-tests/testData/codeInsight/joinLines/IfChainSelection.java @@ -3,8 +3,8 @@ class Foo { int a = 2; int b = 2; - if (a == b){ - if (a > b){ + if (a == b) { + if (a > b) { System.out.println(); } } diff --git a/java/java-tests/testData/codeInsight/joinLines/WrongWrapping_after.java b/java/java-tests/testData/codeInsight/joinLines/WrongWrapping_after.java index b59f38f9f7b4..c03f501ebec0 100644 --- a/java/java-tests/testData/codeInsight/joinLines/WrongWrapping_after.java +++ b/java/java-tests/testData/codeInsight/joinLines/WrongWrapping_after.java @@ -3,7 +3,7 @@ import java.awt.*; class Foo { void foo (){ - ButtonWithExtension button = new ButtonWithExtension("", "", "", ""); + ButtonWithExtension button = new ButtonWithExtension("", "", "", ""); } private abstract class MyActionButton extends JComponent{ diff --git a/java/java-tests/testSrc/com/intellij/java/codeInsight/JoinLinesTest.java b/java/java-tests/testSrc/com/intellij/java/codeInsight/JoinLinesTest.java index d547eb2d5237..b462d7f100b6 100644 --- a/java/java-tests/testSrc/com/intellij/java/codeInsight/JoinLinesTest.java +++ b/java/java-tests/testSrc/com/intellij/java/codeInsight/JoinLinesTest.java @@ -246,6 +246,7 @@ public class JoinLinesTest extends LightJavaCodeInsightTestCase { public void testConvertComment() { doTest();} public void testConvertComment2() { doTest();} public void testConvertManyEndOfLineComments() { doTest();} + public void testConvertMixed() { doTest();} public void testJoiningMethodCallWhenItDoesntFit() { CommonCodeStyleSettings settings = getJavaSettings(); diff --git a/platform/lang-impl/src/com/intellij/codeInsight/editorActions/JoinLinesHandler.java b/platform/lang-impl/src/com/intellij/codeInsight/editorActions/JoinLinesHandler.java index 6ad5bd6ad376..46bf50d002f8 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/editorActions/JoinLinesHandler.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/editorActions/JoinLinesHandler.java @@ -14,6 +14,7 @@ import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.editor.*; import com.intellij.openapi.editor.actionSystem.EditorActionHandler; import com.intellij.openapi.editor.ex.DocumentEx; +import com.intellij.openapi.progress.ProgressIndicator; import com.intellij.openapi.progress.ProgressManager; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Ref; @@ -98,13 +99,16 @@ public class JoinLinesHandler extends EditorActionHandler { try { convertEndComments(psiFile, doc, line, lineCount); ProgressManager.checkCanceled(); + int newEndLine = processRawJoiners(doc, docManager, psiFile, line, lineCount, caretRestoreOffset, indicator); + int newCount = newEndLine - line; int count = 0; - while (count < lineCount) { + while (count < newCount) { indicator.checkCanceled(); - indicator.setFraction(((double)count) / lineCount); + indicator.setFraction(((double)count) / newCount * 0.7 + 0.3); int beforeLines = doc.getLineCount(); ProgressManager.getInstance().executeNonCancelableSection( - () -> doJoinTwoLines(doc, project, docManager, psiFile, line, caretRestoreOffset)); + () -> CodeStyleManager.getInstance(project).performActionWithFormatterDisabled( + (Runnable)(() -> doJoinTwoLines(doc, project, docManager, psiFile, line, caretRestoreOffset)))); int afterLines = doc.getLineCount(); // Single Join two lines procedure could join more than two (e.g. if it removes braces) count += Math.max(beforeLines - afterLines, 1); @@ -118,6 +122,52 @@ public class JoinLinesHandler extends EditorActionHandler { }); } + private static int processRawJoiners(@NotNull DocumentEx doc, + @NotNull PsiDocumentManager docManager, + @NotNull PsiFile psiFile, + int startLine, + int lineCount, + Ref caretRestoreOffset, + ProgressIndicator indicator) { + int count = 0; + List list = JoinLinesHandlerDelegate.EP_NAME.getExtensionList(); + int beforeLines = doc.getLineCount(); + CharSequence text = doc.getCharsSequence(); + while (count < lineCount) { + indicator.checkCanceled(); + indicator.setFraction(((double)count) / lineCount * 0.3); + JoinLinesOffsets offsets = new JoinLinesOffsets(doc, startLine); + + TextRange limits = findStartAndEnd(text, offsets.lastNonSpaceOffsetInStartLine, offsets.firstNonSpaceOffsetInNextLine); + int start = limits.getStartOffset(); + int end = limits.getEndOffset(); + int rc = CANNOT_JOIN; + for (JoinLinesHandlerDelegate delegate : list) { + if (delegate instanceof JoinRawLinesHandlerDelegate) { + rc = ((JoinRawLinesHandlerDelegate)delegate).tryJoinRawLines(doc, psiFile, start, end); + if (rc != CANNOT_JOIN) { + caretRestoreOffset.set(checkOffset(rc, delegate, doc)); + break; + } + } + } + if (rc == CANNOT_JOIN) { + startLine++; + count++; + } + else { + docManager.doPostponedOperationsAndUnblockDocument(doc); + docManager.commitDocument(doc); + int afterLines = doc.getLineCount(); + // Single Join two lines procedure could join more than two (e.g. if it removes braces) + count += Math.max(beforeLines - afterLines, 1); + beforeLines = afterLines; + text = doc.getCharsSequence(); + } + } + return startLine; + } + private static void positionCaret(Editor editor, Caret caret, int caretRestoreOffset) { if (caret.hasSelection()) { caret.moveToOffset(caret.getSelectionEnd()); @@ -141,50 +191,36 @@ public class JoinLinesHandler extends EditorActionHandler { docManager.doPostponedOperationsAndUnblockDocument(doc); docManager.commitDocument(doc); - CharSequence text = doc.getCharsSequence(); JoinLinesOffsets offsets = new JoinLinesOffsets(doc, startLine); - TextRange limits = findStartAndEnd(text, offsets.lastNonSpaceOffsetInStartLine, offsets.firstNonSpaceOffsetInNextLine); - int start = limits.getStartOffset(); - int end = limits.getEndOffset(); - // run raw joiners - int rc = -1; - for (JoinLinesHandlerDelegate delegate: JoinLinesHandlerDelegate.EP_NAME.getExtensionList()) { - if (delegate instanceof JoinRawLinesHandlerDelegate) { - rc = ((JoinRawLinesHandlerDelegate)delegate).tryJoinRawLines(doc, psiFile, start, end); - if (rc != CANNOT_JOIN) { - caretRestoreOffset.set(checkOffset(rc, delegate, doc)); - break; - } - } - } - if (rc == CANNOT_JOIN) { // remove indents and newline, run non-raw joiners - if (offsets.lastNonSpaceOffsetInStartLine == doc.getLineStartOffset(startLine)) { - doc.deleteString(doc.getLineStartOffset(startLine), offsets.firstNonSpaceOffsetInNextLine); - - docManager.commitDocument(doc); - int indent = - CodeStyleManager.getInstance(project).adjustLineIndent(psiFile, startLine == 0 ? 0 : doc.getLineStartOffset(startLine)); - - if (caretRestoreOffset.get() == CANNOT_JOIN) { - caretRestoreOffset.set(indent); - } - - return; - } - - doc.deleteString(offsets.lineEndOffset, offsets.lineEndOffset + doc.getLineSeparatorLength(startLine)); - - text = doc.getCharsSequence(); - limits = findStartAndEnd(text, offsets.lineEndOffset - 1, offsets.lineEndOffset); - start = limits.getStartOffset(); end = limits.getEndOffset(); + // remove indents and newline, run non-raw joiners + if (offsets.lastNonSpaceOffsetInStartLine == doc.getLineStartOffset(startLine)) { + doc.deleteString(doc.getLineStartOffset(startLine), offsets.firstNonSpaceOffsetInNextLine); docManager.commitDocument(doc); + int indent = + CodeStyleManager.getInstance(project).adjustLineIndent(psiFile, startLine == 0 ? 0 : doc.getLineStartOffset(startLine)); - for(JoinLinesHandlerDelegate delegate: JoinLinesHandlerDelegate.EP_NAME.getExtensionList()) { - rc = checkOffset(delegate.tryJoinLines(doc, psiFile, start, end), delegate, doc); - if (rc != CANNOT_JOIN) break; + if (caretRestoreOffset.get() == CANNOT_JOIN) { + caretRestoreOffset.set(indent); } + + return; + } + + doc.deleteString(offsets.lineEndOffset, offsets.lineEndOffset + doc.getLineSeparatorLength(startLine)); + + CharSequence text = doc.getCharsSequence(); + TextRange limits = findStartAndEnd(text, offsets.lineEndOffset - 1, offsets.lineEndOffset); + int start = limits.getStartOffset(); + int end = limits.getEndOffset(); + + docManager.commitDocument(doc); + + int rc = CANNOT_JOIN; + for (JoinLinesHandlerDelegate delegate : JoinLinesHandlerDelegate.EP_NAME.getExtensionList()) { + rc = checkOffset(delegate.tryJoinLines(doc, psiFile, start, end), delegate, doc); + if (rc != CANNOT_JOIN) break; } if (rc != CANNOT_JOIN) {