From ab0db9b789503d091f7c15bf7d7b4bcf751494d7 Mon Sep 17 00:00:00 2001 From: Yaroslav Lepenkin Date: Wed, 20 Jul 2016 17:30:11 +0300 Subject: [PATCH] [java-formatter] chained method calls - align on enter press by dot --- .../formatter/java/SyntheticCodeBlock.java | 50 ++++++++++++++++++- .../formatter/java/JavaEnterActionTest.java | 29 +++++++++++ 2 files changed, 78 insertions(+), 1 deletion(-) diff --git a/java/java-impl/src/com/intellij/psi/formatter/java/SyntheticCodeBlock.java b/java/java-impl/src/com/intellij/psi/formatter/java/SyntheticCodeBlock.java index 30f1960119e3..e1eb9c546eeb 100644 --- a/java/java-impl/src/com/intellij/psi/formatter/java/SyntheticCodeBlock.java +++ b/java/java-impl/src/com/intellij/psi/formatter/java/SyntheticCodeBlock.java @@ -19,12 +19,14 @@ import com.intellij.formatting.*; import com.intellij.lang.ASTNode; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.util.TextRange; +import com.intellij.psi.JavaTokenType; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiFile; import com.intellij.psi.codeStyle.CommonCodeStyleSettings; import com.intellij.psi.codeStyle.JavaCodeStyleSettings; import com.intellij.psi.formatter.common.AbstractBlock; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import java.util.ArrayList; import java.util.List; @@ -56,7 +58,7 @@ public class SyntheticCodeBlock implements Block, JavaBlock{ if (subBlocks.isEmpty()) { LOG.assertTrue(false); } - mySubBlocks = new ArrayList(subBlocks); + mySubBlocks = new ArrayList<>(subBlocks); myAlignment = alignment; mySettings = settings; myWrap = wrap; @@ -145,10 +147,56 @@ public class SyntheticCodeBlock implements Block, JavaBlock{ Block block = mySubBlocks.get(newChildIndex); alignment = block.getAlignment(); } + else if (mySubBlocks.size() == newChildIndex) { + if (isRParenth(getRightMostBlock())) { + alignment = getDotAlignment(); + } + } + return new ChildAttributes(getIndent(), alignment); } } + private static boolean isRParenth(Block sibling) { + if (sibling instanceof LeafBlock) { + ASTNode node = ((LeafBlock)sibling).getNode(); + return node != null && node.getElementType() == JavaTokenType.RPARENTH; + } + return false; + } + + @Nullable + private Alignment getDotAlignment() { + if (mySubBlocks.size() > 1) { + Block block = mySubBlocks.get(1); + if (isDotFirst(block)) { + return block.getAlignment(); + } + } + return null; + } + + private static boolean isDotFirst(final Block block) { + Block current = block; + while (!current.getSubBlocks().isEmpty()) { + current = block.getSubBlocks().get(0); + } + ASTNode node = current instanceof LeafBlock ? ((LeafBlock)current).getNode() : null; + return node != null && node.getElementType() == JavaTokenType.DOT; + } + + @Nullable + private Block getRightMostBlock() { + Block rightMost = null; + List subBlocks = getSubBlocks(); + while (!subBlocks.isEmpty()) { + int lastIndex = subBlocks.size() - 1; + rightMost = subBlocks.get(lastIndex); + subBlocks = rightMost.getSubBlocks(); + } + return rightMost; + } + @Override public boolean isIncomplete() { if (myIsIncomplete) return true; diff --git a/java/java-tests/testSrc/com/intellij/psi/formatter/java/JavaEnterActionTest.java b/java/java-tests/testSrc/com/intellij/psi/formatter/java/JavaEnterActionTest.java index af65e34e8fa3..b0a9cdae52d8 100644 --- a/java/java-tests/testSrc/com/intellij/psi/formatter/java/JavaEnterActionTest.java +++ b/java/java-tests/testSrc/com/intellij/psi/formatter/java/JavaEnterActionTest.java @@ -169,4 +169,33 @@ public class JavaEnterActionTest extends AbstractEnterActionTestCase { " }\n" + "}"); } + + public void testEnter_AfterLastChainedCall() throws IOException { + CodeStyleSettings settings = getCodeStyleSettings(); + CommonCodeStyleSettings javaCommon = settings.getCommonSettings(JavaLanguage.INSTANCE); + javaCommon.ALIGN_MULTILINE_CHAINED_METHODS = true; + setCodeStyleSettings(settings); + + doTextTest("java", + "class T {\n" + + " public void main() {\n" + + " ActionBarPullToRefresh.from(getActivity())\n" + + " .theseChildrenArePullable(eventsListView)\n" + + " .listener(this)\n" + + " .useViewDelegate(StickyListHeadersListView.class, new AbsListViewDelegate())\n" + + " }\n" + + "}", + "class T {\n" + + " public void main() {\n" + + " ActionBarPullToRefresh.from(getActivity())\n" + + " .theseChildrenArePullable(eventsListView)\n" + + " .listener(this)\n" + + " .useViewDelegate(StickyListHeadersListView.class, new AbsListViewDelegate())\n" + + " \n" + + " }\n" + + "}"); + } + + + } \ No newline at end of file