diff --git a/java/java-impl/src/com/intellij/psi/formatter/java/CallChunkBlockBuilder.java b/java/java-impl/src/com/intellij/psi/formatter/java/CallChunkBlockBuilder.java index aea151296d87..1789537db91d 100644 --- a/java/java-impl/src/com/intellij/psi/formatter/java/CallChunkBlockBuilder.java +++ b/java/java-impl/src/com/intellij/psi/formatter/java/CallChunkBlockBuilder.java @@ -21,9 +21,6 @@ import com.intellij.lang.ASTNode; import com.intellij.psi.JavaTokenType; import com.intellij.psi.codeStyle.CommonCodeStyleSettings; import com.intellij.psi.codeStyle.JavaCodeStyleSettings; -import com.intellij.util.CollectionsKt; -import com.siyeh.ig.psiutils.CollectionUtils; -import org.apache.commons.collections.ListUtils; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -61,6 +58,7 @@ public class CallChunkBlockBuilder { } return new SyntheticCodeBlock(subBlocks, alignment, mySettings, myJavaSettings, Indent.getContinuationIndent(myIndentSettings.USE_RELATIVE_INDENTS), wrap); } + // Support for groovy style dot placement final ASTNode lastNode = subNodes.get(subNodes.size() - 1); if (lastNode.getElementType() == JavaTokenType.DOT) { @@ -69,16 +67,20 @@ public class CallChunkBlockBuilder { if (!subNodes.isEmpty()) { subBlocks.add(create(subNodes, wrap, null)); } - Block block = newJavaBlock(lastNode, mySettings, myJavaSettings, Indent.getNoneIndent(), Wrap.createWrap(WrapType.ALWAYS, true), strategy, myFormattingMode); + Block block = + newJavaBlock(lastNode, mySettings, myJavaSettings, Indent.getNoneIndent(), Wrap.createWrap(WrapType.NONE, true), strategy, + myFormattingMode); subBlocks.add(block); - SyntheticCodeBlock syntheticCodeBlock = new SyntheticCodeBlock(subBlocks, alignment, mySettings, myJavaSettings, - Indent.getContinuationIndent(myIndentSettings.USE_RELATIVE_INDENTS), Wrap.createWrap(WrapType.NONE, false)); - return syntheticCodeBlock; + return new SyntheticCodeBlock(subBlocks, alignment, mySettings, myJavaSettings, + Indent.getContinuationWithoutFirstIndent(myIndentSettings.USE_RELATIVE_INDENTS), wrap); } List blocks = createJavaBlocks(subNodes); + + // Last line not contains '.', but needs to be wrapped + final Wrap finalWrap = myJavaSettings.PLACE_DOT_ON_NEXT_LINE ? null : wrap; return new SyntheticCodeBlock(blocks, alignment, mySettings, myJavaSettings, Indent.getContinuationWithoutFirstIndent(myIndentSettings.USE_RELATIVE_INDENTS), - null); + finalWrap); } @NotNull diff --git a/java/java-impl/src/com/intellij/psi/formatter/java/ChainMethodCallsBlockBuilder.java b/java/java-impl/src/com/intellij/psi/formatter/java/ChainMethodCallsBlockBuilder.java index 3331bdf3f356..69a13181304e 100644 --- a/java/java-impl/src/com/intellij/psi/formatter/java/ChainMethodCallsBlockBuilder.java +++ b/java/java-impl/src/com/intellij/psi/formatter/java/ChainMethodCallsBlockBuilder.java @@ -130,40 +130,39 @@ class ChainMethodCallsBlockBuilder { private List splitMethodCallOnChunksByDots(@NotNull List nodes) { List result = new ArrayList<>(); + List current = new ArrayList<>(); if (myJavaSettings.PLACE_DOT_ON_NEXT_LINE) { - List current = new ArrayList<>(); for (ASTNode node : nodes) { - if (node.getElementType() == JavaTokenType.DOT || node.getPsi() instanceof PsiComment) { - if (!current.isEmpty()) { - result.add(new ChainedCallChunk(current)); - } + if (tryAddToResult(node, current, result)) { current = new ArrayList<>(); } current.add(node); } - - if (!current.isEmpty()) { - result.add(new ChainedCallChunk(current)); - } } else { - List current = new ArrayList<>(); for (ASTNode node : nodes) { current.add(node); - if (node.getElementType() == JavaTokenType.DOT || node.getPsi() instanceof PsiComment) { - if (!current.isEmpty()) { - result.add(new ChainedCallChunk(current)); - } + if (tryAddToResult(node, current, result)) { current = new ArrayList<>(); } } + } + if (!current.isEmpty()) { + result.add(new ChainedCallChunk(current)); + } + return result; + } + /** + * @return true if current list should be finished + */ + private static boolean tryAddToResult(ASTNode node, List current, List result) { + if (node.getElementType() == JavaTokenType.DOT || node.getPsi() instanceof PsiComment) { if (!current.isEmpty()) { result.add(new ChainedCallChunk(current)); } + return true; } - - - return result; + return false; } private Alignment createCallChunkAlignment(int chunkIndex, @NotNull List methodCall) { diff --git a/java/java-tests/testSrc/com/intellij/java/psi/formatter/java/JavaFormatterWrapTest.java b/java/java-tests/testSrc/com/intellij/java/psi/formatter/java/JavaFormatterWrapTest.java index f0990d052d06..d0a64277b95d 100644 --- a/java/java-tests/testSrc/com/intellij/java/psi/formatter/java/JavaFormatterWrapTest.java +++ b/java/java-tests/testSrc/com/intellij/java/psi/formatter/java/JavaFormatterWrapTest.java @@ -937,9 +937,8 @@ public class JavaFormatterWrapTest extends AbstractJavaFormatterTest { } public void testDotPlacement() { - //getSettings().WRAP_LONG_LINES = true; - //getSettings().WRAP_COMMENTS = true; - //getSettings().RIGHT_MARGIN = 50; + getSettings().METHOD_CALL_CHAIN_WRAP = CommonCodeStyleSettings.WRAP_ALWAYS; + getSettings().KEEP_LINE_BREAKS = false; getJavaSettings().PLACE_DOT_ON_NEXT_LINE = false; @@ -962,17 +961,28 @@ public class JavaFormatterWrapTest extends AbstractJavaFormatterTest { " }\n" + "}\n", - "public class Main {\n" + - "\n" + - " /**\n" + - " * {@link #authenticationCompleted(android.app.Activity,\n" + - " * int, int, android.content.Intent)}\n" + - " *\n" + - " * @param args\n" + - " */\n" + - " public static void main(String[] args) {\n" + + "public class Chains {\n" + + " static Chains get() {\n" + + " return null;\n" + " }\n" + - "}" + "\n " + + " Chains foo() {\n" + + " return null;\n" + + " }\n" + + "\n " + + " Chains bar() {\n" + + " return null;\n" + + " }\n" + + "\n " + + " public static void main(String[] args) {\n" + + " get().\n" + + " bar().\n" + + " foo().\n" + + " bar().\n" + + " bar().\n" + + " foo();\n" + + " }\n" + + "}\n" ); } }