From 5e393060227ac2455a06876df4d968b390cea6da Mon Sep 17 00:00:00 2001 From: "Denis.Zhdanov" Date: Tue, 10 Jan 2012 18:04:48 +0400 Subject: [PATCH] IDEA-79486 Java formatter: Correct processing of anonymous classes as method call arguments --- .../psi/formatter/java/AbstractJavaBlock.java | 137 ++++++++++-------- .../psi/formatter/java/CodeBlockBlock.java | 25 +++- .../psi/formatter/java/JavaFormatterUtil.java | 118 +-------------- .../psi/formatter/java/SimpleJavaBlock.java | 13 +- .../java/JavaFormatterIndentationTest.java | 30 +++- .../formatting/InitialInfoBuilder.java | 6 +- 6 files changed, 135 insertions(+), 194 deletions(-) diff --git a/java/java-impl/src/com/intellij/psi/formatter/java/AbstractJavaBlock.java b/java/java-impl/src/com/intellij/psi/formatter/java/AbstractJavaBlock.java index 381a8b41f3dd..09f977933bac 100644 --- a/java/java-impl/src/com/intellij/psi/formatter/java/AbstractJavaBlock.java +++ b/java/java-impl/src/com/intellij/psi/formatter/java/AbstractJavaBlock.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2012 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -45,7 +45,7 @@ import org.jetbrains.annotations.Nullable; import java.util.*; -import static com.intellij.psi.formatter.java.JavaFormatterUtil.isFirstAmongOthersAnonymousClassMethodCallArguments; +import static com.intellij.psi.formatter.java.JavaFormatterUtil.hasAnonymousClassesArguments; import static java.util.Arrays.asList; public abstract class AbstractJavaBlock extends AbstractBlock implements JavaBlock, ReservedWrapsProvider { @@ -130,8 +130,8 @@ public abstract class AbstractJavaBlock extends AbstractBlock implements JavaBlo public static Block createJavaBlock(final ASTNode child, final CommonCodeStyleSettings settings, - final Indent indent, - Wrap wrap, + @Nullable final Indent indent, + @Nullable Wrap wrap, Alignment alignment) { return createJavaBlock(child, settings, indent, wrap, AlignmentStrategy.wrap(alignment)); } @@ -139,7 +139,7 @@ public abstract class AbstractJavaBlock extends AbstractBlock implements JavaBlo public static Block createJavaBlock(final ASTNode child, final CommonCodeStyleSettings settings, final Indent indent, - Wrap wrap, + @Nullable Wrap wrap, @NotNull AlignmentStrategy alignmentStrategy) { return createJavaBlock(child, settings, indent, wrap, alignmentStrategy, -1); } @@ -388,8 +388,9 @@ public abstract class AbstractJavaBlock extends AbstractBlock implements JavaBlo } } - protected Alignment chooseAlignment(Alignment alignment, Alignment alignment2, ASTNode child) { - if (preferesSlaveAlignment(child)) { + @Nullable + protected Alignment chooseAlignment(@Nullable Alignment alignment, @Nullable Alignment alignment2, ASTNode child) { + if (preferSlaveAlignment(child)) { return alignment2; } else { @@ -397,7 +398,7 @@ public abstract class AbstractJavaBlock extends AbstractBlock implements JavaBlo } } - private boolean preferesSlaveAlignment(final ASTNode child) { + private boolean preferSlaveAlignment(final ASTNode child) { final IElementType nodeType = myNode.getElementType(); if (nodeType == JavaElementType.CONDITIONAL_EXPRESSION) { @@ -433,7 +434,7 @@ public abstract class AbstractJavaBlock extends AbstractBlock implements JavaBlo protected ASTNode processChild(final List result, ASTNode child, AlignmentStrategy alignmentStrategy, - final Wrap defaultWrap, + @Nullable final Wrap defaultWrap, final Indent childIndent) { return processChild(result, child, alignmentStrategy, defaultWrap, childIndent, -1); } @@ -724,7 +725,7 @@ public abstract class AbstractJavaBlock extends AbstractBlock implements JavaBlo // Just create a no-aligned sub-block if we don't need to bother with it's alignment (either due to end-user // setup or sub-block state). if (chainedCallsAlignment == null || subNodes.isEmpty()) { - subBlocks.add(createSynthBlock(subNodes, wrap, alignmentToUseForSubBlock)); + subBlocks.add(createSyntheticBlock(subNodes, wrap, alignmentToUseForSubBlock)); continue; } @@ -742,21 +743,21 @@ public abstract class AbstractJavaBlock extends AbstractBlock implements JavaBlo if (callPointDefined && currentSubBlockIsMethodCall) { alignmentToUseForSubBlock = chainedCallsAlignment; } - subBlocks.add(createSynthBlock(subNodes, wrap, alignmentToUseForSubBlock)); + subBlocks.add(createSyntheticBlock(subNodes, wrap, alignmentToUseForSubBlock)); } return new SyntheticCodeBlock(subBlocks, alignment, mySettings, Indent.getContinuationWithoutFirstIndent(myIndentSettings.USE_RELATIVE_INDENTS), blockWrap); } - private Block createSynthBlock(final ArrayList subNodes, final Wrap wrap, final Alignment alignment) { + private Block createSyntheticBlock(final ArrayList subNodes, final Wrap wrap, @Nullable final Alignment alignment) { final ArrayList subBlocks = new ArrayList(); final ASTNode firstNode = subNodes.get(0); if (firstNode.getElementType() == JavaTokenType.DOT) { subBlocks.add(createJavaBlock(firstNode, getSettings(), Indent.getNoneIndent(), null, AlignmentStrategy.getNullStrategy())); subNodes.remove(0); if (!subNodes.isEmpty()) { - subBlocks.add(createSynthBlock(subNodes, wrap, null)); + subBlocks.add(createSyntheticBlock(subNodes, wrap, null)); } return new SyntheticCodeBlock(subBlocks, alignment, mySettings, Indent.getContinuationIndent(myIndentSettings.USE_RELATIVE_INDENTS), wrap); @@ -837,7 +838,7 @@ public abstract class AbstractJavaBlock extends AbstractBlock implements JavaBlo } if (nodeType == JavaElementType.CLASS) { // There is a possible case that current document state is invalid from language syntax point of view, e.g. the user starts - // typing field definition and re-formatting is triggered by 'auto insert javadocs' processing. Example: + // typing field definition and re-formatting is triggered by 'auto insert javadoc' processing. Example: // class Test { // @NotNull Object // } @@ -945,12 +946,6 @@ public abstract class AbstractJavaBlock extends AbstractBlock implements JavaBlo } return null; } - - else if (nodeType == JavaElementType.ANONYMOUS_CLASS && role == ChildRole.RBRACE - && isFirstAmongOthersAnonymousClassMethodCallArguments(myNode)) - { - return myAlignment; - } else { return defaultAlignment; @@ -1004,11 +999,14 @@ public abstract class AbstractJavaBlock extends AbstractBlock implements JavaBlo } */ - private static Alignment createAlignment(final boolean alignOption, final Alignment defaultAlignment) { + + @Nullable + private static Alignment createAlignment(final boolean alignOption, @Nullable final Alignment defaultAlignment) { return alignOption ? createAlignmentOrDefault(null, defaultAlignment) : defaultAlignment; } - private static Alignment createAlignment(Alignment base, final boolean alignOption, final Alignment defaultAlignment) { + @Nullable + private static Alignment createAlignment(Alignment base, final boolean alignOption, @Nullable final Alignment defaultAlignment) { return alignOption ? createAlignmentOrDefault(base, defaultAlignment) : defaultAlignment; } @@ -1068,6 +1066,14 @@ public abstract class AbstractJavaBlock extends AbstractBlock implements JavaBlo || methodCandidate.getElementType() == JavaElementType.METHOD_CALL_EXPRESSION); } Alignment bracketAlignment = methodParametersBlock && mySettings.ALIGN_MULTILINE_METHOD_BRACKETS ? Alignment.createAlignment() : null; + AlignmentStrategy anonymousClassStrategy = doAlign ? alignmentStrategy + : AlignmentStrategy.wrap(Alignment.createAlignment(), + false, + JavaTokenType.NEW_KEYWORD, + JavaElementType.NEW_EXPRESSION, + JavaTokenType.RBRACE); + setChildIndent(internalIndent); + setChildAlignment(alignmentStrategy.getAlignment(null)); boolean isAfterIncomplete = false; @@ -1088,8 +1094,10 @@ public abstract class AbstractJavaBlock extends AbstractBlock implements JavaBlo } else { final IElementType elementType = child.getElementType(); - Indent indentToUse = shouldEnforceIndentToChildren(child) ? internalIndentEnforcedToChildren : internalIndent; - processChild(result, child, alignmentStrategy.getAlignment(elementType), wrappingStrategy.getWrap(elementType), indentToUse); + final boolean enforceIndent = shouldEnforceIndentToChildren(child); + Indent indentToUse = enforceIndent ? internalIndentEnforcedToChildren : internalIndent; + AlignmentStrategy alignmentStrategyToUse = canUseAnonymousClassAlignment(child) ? anonymousClassStrategy : alignmentStrategy; + processChild(result, child, alignmentStrategyToUse.getAlignment(elementType), wrappingStrategy.getWrap(elementType), indentToUse); if (to == null) {//process only one statement return child; } @@ -1103,26 +1111,48 @@ public abstract class AbstractJavaBlock extends AbstractBlock implements JavaBlo return prev; } - private boolean shouldEnforceIndentToChildren(@NotNull ASTNode node) { - // Don't enforce indent if given node is the last argument, i.e. prefer the code below - // void test() { - // foo("test", new Runnable() { - // public void run() { - // } - // }); - // } - // to this one: - // void test() { - // foo("test", new Runnable() { - // public void run() { - // } - // }); - // } - ASTNode rBrace = myNode.getLastChildNode(); - if (node == FormatterUtil.getPreviousNonWhitespaceSibling(rBrace)) { + private static boolean canUseAnonymousClassAlignment(@NotNull ASTNode child) { + // The general idea is to handle situations like below: + // test(new Runnable() { + // public void run() { + // } + // }, new Runnable() { + // public void run() { + // } + // } + // ); + // I.e. we want to align subsequent anonymous class argument to the previous one if it's not preceded by another argument + // at the same line, e.g.: + // test("this is a long argument", new Runnable() { + // public void run() { + // } + // }, new Runnable() { + // public void run() { + // } + // } + // ); + if (!isAnonymousClass(child)) { return false; } + for (ASTNode node = child.getTreePrev(); node != null; node = node.getTreePrev()) { + if (node.getElementType() == TokenType.WHITE_SPACE) { + if (StringUtil.countNewLines(node.getChars()) > 0) { + return false; + } + } + else if (node.getElementType() == JavaTokenType.LPARENTH) { + // First method call argument. + return true; + } + else if (node.getElementType() != JavaTokenType.COMMA && !isAnonymousClass(node)) { + return false; + } + } + return true; + } + + private boolean shouldEnforceIndentToChildren(@NotNull ASTNode node) { // Filter only anonymous class instances as method call arguments if (myNode.getElementType() != JavaElementType.EXPRESSION_LIST) { return false; @@ -1131,7 +1161,7 @@ public abstract class AbstractJavaBlock extends AbstractBlock implements JavaBlo if (parent == null || parent.getElementType() != JavaElementType.METHOD_CALL_EXPRESSION) { return false; } - if (!isAnonymousClass(node)) { + if (!isAnonymousClass(node) || !hasAnonymousClassesArguments((PsiExpressionList)myNode.getPsi(), 2)) { return false; } @@ -1140,24 +1170,8 @@ public abstract class AbstractJavaBlock extends AbstractBlock implements JavaBlo if (prev == null || (StringUtil.containsLineBreak(prev.getChars()) && prev.getElementType() != TokenType.WHITE_SPACE)) { return false; } - - final PsiElement psi = myNode.getPsi(); - if (!(psi instanceof PsiExpressionList)) { - return false; - } - PsiExpressionList expressionList = (PsiExpressionList)psi; - for (PsiExpression expression : expressionList.getExpressions()) { - final ASTNode argumentNode = expression.getNode(); - if (argumentNode == node) { - continue; - } - - if (isAnonymousClass(argumentNode)) { - return true; - } - } - return false; + return true; } private static boolean isAnonymousClass(@Nullable ASTNode node) { @@ -1194,7 +1208,8 @@ public abstract class AbstractJavaBlock extends AbstractBlock implements JavaBlo myChildIndent = internalIndent; } - private static Alignment createAlignmentOrDefault(Alignment base, final Alignment defaultAlignment) { + @Nullable + private static Alignment createAlignmentOrDefault(@Nullable Alignment base, @Nullable final Alignment defaultAlignment) { if (defaultAlignment == null) { return base == null ? Alignment.createAlignment() : Alignment.createChildAlignment(base); } @@ -1385,7 +1400,7 @@ public abstract class AbstractJavaBlock extends AbstractBlock implements JavaBlo @Nullable protected ASTNode composeCodeBlock(final ArrayList result, ASTNode child, final Indent indent, final int childrenIndent, - final Wrap childWrap) { + @Nullable final Wrap childWrap) { final ArrayList localResult = new ArrayList(); processChild(localResult, child, AlignmentStrategy.getNullStrategy(), null, Indent.getNoneIndent()); child = child.getTreeNext(); diff --git a/java/java-impl/src/com/intellij/psi/formatter/java/CodeBlockBlock.java b/java/java-impl/src/com/intellij/psi/formatter/java/CodeBlockBlock.java index 7744b6bef7f8..3b039580ae0c 100644 --- a/java/java-impl/src/com/intellij/psi/formatter/java/CodeBlockBlock.java +++ b/java/java-impl/src/com/intellij/psi/formatter/java/CodeBlockBlock.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2012 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -18,6 +18,7 @@ package com.intellij.psi.formatter.java; import com.intellij.formatting.*; import com.intellij.formatting.alignment.AlignmentStrategy; import com.intellij.lang.ASTNode; +import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.JavaTokenType; import com.intellij.psi.TokenType; import com.intellij.psi.codeStyle.CommonCodeStyleSettings; @@ -128,7 +129,7 @@ public class CodeBlockBlock extends AbstractJavaBlock { child = composeCodeBlock(result, child, indent, myChildrenIndent, childWrap); } else { - child = processChild(result, child, childAlignment, childWrap, indent); + child = processChild(result, child, chooseAlignment(child, childAlignment), childWrap, indent); } } if (child != null) { @@ -137,6 +138,26 @@ public class CodeBlockBlock extends AbstractJavaBlock { } } + @Nullable + private Alignment chooseAlignment(@NotNull ASTNode child, @Nullable Alignment defaultAlignment) { + if (defaultAlignment != null) { + return defaultAlignment; + } + // Take special care about anonymous classes. + if (child.getElementType() != JavaTokenType.RBRACE) { + return defaultAlignment; + } + final ASTNode parent = child.getTreeParent(); + if (parent == null || parent.getElementType() != JavaElementType.ANONYMOUS_CLASS) { + return defaultAlignment; + } + final ASTNode whiteSpaceCandidate = parent.getTreePrev(); + if (whiteSpaceCandidate == null || whiteSpaceCandidate.getElementType() != TokenType.WHITE_SPACE) { + return defaultAlignment; + } + return StringUtil.countNewLines(whiteSpaceCandidate.getChars()) > 0 ? myAlignment : defaultAlignment; + } + @Nullable private ASTNode processCaseAndStatementAfter(final ArrayList result, ASTNode child, diff --git a/java/java-impl/src/com/intellij/psi/formatter/java/JavaFormatterUtil.java b/java/java-impl/src/com/intellij/psi/formatter/java/JavaFormatterUtil.java index 78eab71dbd89..2f6c7f9b6a54 100644 --- a/java/java-impl/src/com/intellij/psi/formatter/java/JavaFormatterUtil.java +++ b/java/java-impl/src/com/intellij/psi/formatter/java/JavaFormatterUtil.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2011 JetBrains s.r.o. + * Copyright 2000-2012 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -19,9 +19,7 @@ import com.intellij.lang.ASTNode; import com.intellij.psi.PsiExpression; import com.intellij.psi.PsiExpressionList; import com.intellij.psi.PsiPolyadicExpression; -import com.intellij.psi.formatter.FormatterUtil; import com.intellij.psi.impl.source.tree.JavaElementType; -import com.intellij.psi.impl.source.tree.JavaJspElementType; import com.intellij.psi.tree.IElementType; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -47,10 +45,10 @@ public class JavaFormatterUtil { } /** - * Allows to answer if given node wraps assignement operation. + * Allows to answer if given node wraps assignment operation. * * @param node node to check - * @return true if given node wraps assignement operation; false otherwise + * @return true if given node wraps assignment operation; false otherwise */ public static boolean isAssignment(ASTNode node) { return ASSIGNMENT_ELEMENT_TYPES.contains(node.getElementType()); @@ -77,116 +75,6 @@ public class JavaFormatterUtil { return expression1.getOperationTokenType() == expression2.getOperationTokenType(); } - public static boolean isFirstMethodCallArgument(@NotNull ASTNode node) { - ASTNode firstArgCandidate = node; - ASTNode expressionList = node.getTreeParent(); - if (expressionList == null) { - return false; - } - - if (expressionList.getElementType() != JavaElementType.EXPRESSION_LIST - && expressionList.getElementType() == JavaElementType.NEW_EXPRESSION) - { - firstArgCandidate = expressionList; - expressionList = expressionList.getTreeParent(); - } - - if (expressionList == null || expressionList.getElementType() != JavaElementType.EXPRESSION_LIST) { - return false; - } - - ASTNode methodCallExpression = expressionList.getTreeParent(); - if (methodCallExpression == null || methodCallExpression.getElementType() != JavaElementType.METHOD_CALL_EXPRESSION) { - return false; - } - - ASTNode lbrace = expressionList.getFirstChildNode(); - ASTNode firstArg = lbrace.getTreeNext(); - if (firstArg != null && JavaJspElementType.WHITE_SPACE_BIT_SET.contains(firstArg.getElementType())) { - firstArg = firstArg.getTreeNext(); - } - - return firstArg == firstArgCandidate; - } - - /** - * Allows to check if given node references anonymous class instance used as a method call argument. The most important thing - * is that that method call expression should have other anonymous classes as well. - *

- * Examples - *

-   *   test(new Runnable() {         <-- true is returned for this node
-   *          public void run() {
-   *          }
-   *        },
-   *        new Runnable() {          <-- false is returned for this node
-   *          public void run() {
-   *          }
-   *        }
-   *    );
-   *
-   *    test(1234, "text", new Runnable() {         <-- true is returned for this node because there are no other anonymous
-   *          public void run() {                          class objects at method call expression before it
-   *          }
-   *        },
-   *        new Runnable() {                        <-- false is returned for this node
-   *          public void run() {
-   *          }
-   *        }
-   *    );
-   *
-   *    test(1234, "text", new Runnable() {         <-- false is returned for this node because there are no other anonymous
-   *        public void run() {                            class objects at method call expression after it
-   *        }
-   *    });
-   * 
- * - * @param node node to process - * @return - */ - public static boolean isFirstAmongOthersAnonymousClassMethodCallArguments(@NotNull ASTNode node) { - ASTNode expressionList = node.getTreeParent(); - ASTNode firstAnonymousClassCandidate = node; - if (expressionList == null) { - return false; - } - - if (expressionList.getElementType() != JavaElementType.EXPRESSION_LIST - && expressionList.getElementType() == JavaElementType.NEW_EXPRESSION) - { - firstAnonymousClassCandidate = expressionList; - expressionList = expressionList.getTreeParent(); - } - - if (expressionList == null || expressionList.getElementType() != JavaElementType.EXPRESSION_LIST) { - return false; - } - - ASTNode methodCallExpression = expressionList.getTreeParent(); - if (methodCallExpression == null || methodCallExpression.getElementType() != JavaElementType.METHOD_CALL_EXPRESSION) { - return false; - } - - ASTNode lbrace = expressionList.getFirstChildNode(); - boolean firstAnonymousClass = false; - for (ASTNode arg = lbrace.getTreeNext(); arg != null; arg = FormatterUtil.getNextNonWhitespaceSibling(arg)) { - if (!isAnonymousClass(arg)) { - continue; - } - if (firstAnonymousClass) { - // Other anonymous class is found at the method call expression after the target one. - return true; - } - else if (arg != firstAnonymousClassCandidate) { - return false; - } - else { - firstAnonymousClass = true; - } - } - return false; - } - /** * Allows to check if given expression list has given number of anonymous classes. * diff --git a/java/java-impl/src/com/intellij/psi/formatter/java/SimpleJavaBlock.java b/java/java-impl/src/com/intellij/psi/formatter/java/SimpleJavaBlock.java index c90b8fceb50a..6ebf67bf0ff5 100644 --- a/java/java-impl/src/com/intellij/psi/formatter/java/SimpleJavaBlock.java +++ b/java/java-impl/src/com/intellij/psi/formatter/java/SimpleJavaBlock.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2012 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -22,7 +22,6 @@ import com.intellij.openapi.util.TextRange; import com.intellij.psi.PsiFile; import com.intellij.psi.codeStyle.CommonCodeStyleSettings; import com.intellij.psi.formatter.FormatterUtil; -import com.intellij.psi.impl.source.tree.ElementType; import com.intellij.psi.impl.source.tree.JavaDocElementType; import com.intellij.psi.impl.source.tree.JavaElementType; import com.intellij.psi.impl.source.tree.StdTokenSets; @@ -75,10 +74,11 @@ public class SimpleJavaBlock extends AbstractJavaBlock { if (astNode != child && child != null) { offset = child.getTextRange().getStartOffset(); } - if (indent != null && !(myNode.getPsi() instanceof PsiFile) && child != null && child.getElementType() != ElementType.MODIFIER_LIST) { + if (indent != null + && !(myNode.getPsi() instanceof PsiFile) && child != null && child.getElementType() != JavaElementType.MODIFIER_LIST) + { indent = Indent.getContinuationIndent(myIndentSettings.USE_RELATIVE_INDENTS); } - //indent = FormatterEx.getInstance().getContinuationIndent(); } if (child != null) { offset += child.getTextLength(); @@ -101,7 +101,7 @@ public class SimpleJavaBlock extends AbstractJavaBlock { @Override @NotNull public ChildAttributes getChildAttributes(final int newChildIndex) { - if (myNode.getElementType() == ElementType.CONDITIONAL_EXPRESSION && mySettings.ALIGN_MULTILINE_TERNARY_OPERATION) { + if (myNode.getElementType() == JavaElementType.CONDITIONAL_EXPRESSION && mySettings.ALIGN_MULTILINE_TERNARY_OPERATION) { final Alignment usedAlignment = getUsedAlignment(newChildIndex); if (usedAlignment != null) { return new ChildAttributes(null, usedAlignment); @@ -129,8 +129,5 @@ public class SimpleJavaBlock extends AbstractJavaBlock { public void setStartOffset(final int startOffset) { myStartOffset = startOffset; - //if (startOffset != -1 && startOffset != myNode.getTextRange().getStartOffset()) { - // assert false; - //} } } diff --git a/java/java-tests/testSrc/com/intellij/psi/formatter/java/JavaFormatterIndentationTest.java b/java/java-tests/testSrc/com/intellij/psi/formatter/java/JavaFormatterIndentationTest.java index 6788a72b3d50..da9e5839507c 100644 --- a/java/java-tests/testSrc/com/intellij/psi/formatter/java/JavaFormatterIndentationTest.java +++ b/java/java-tests/testSrc/com/intellij/psi/formatter/java/JavaFormatterIndentationTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2010 JetBrains s.r.o. + * Copyright 2000-2012 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -358,10 +358,10 @@ public class JavaFormatterIndentationTest extends AbstractJavaFormatterTest { "}\n" + "});", "foo(new Runnable() {\n" + - " @Override\n" + - " public void run() {\n" + - " }\n" + - " },\n" + + " @Override\n" + + " public void run() {\n" + + " }\n" + + " },\n" + " new Runnable() {\n" + " @Override\n" + " public void run() {\n" + @@ -435,6 +435,26 @@ public class JavaFormatterIndentationTest extends AbstractJavaFormatterTest { "}, 1, 2);" ); } + + public void testAnonymousClassesOnSameLineAtMethodCallExpression() throws Exception { + doMethodTest( + "foo(new Runnable() {\n" + + " public void run() {\n" + + " }\n" + + " }, new Runnable() {\n" + + " public void run() {\n" + + " }\n" + + " });", + "foo(new Runnable() {\n" + + " public void run() {\n" + + " }\n" + + " }, new Runnable() {\n" + + " public void run() {\n" + + " }\n" + + " }\n" + + ");" + ); + } public void testPackagePrivateAnnotation() { // Inspired by IDEA-67294 diff --git a/platform/lang-impl/src/com/intellij/formatting/InitialInfoBuilder.java b/platform/lang-impl/src/com/intellij/formatting/InitialInfoBuilder.java index fcad8fc511e8..9c955e6c803f 100644 --- a/platform/lang-impl/src/com/intellij/formatting/InitialInfoBuilder.java +++ b/platform/lang-impl/src/com/intellij/formatting/InitialInfoBuilder.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2011 JetBrains s.r.o. + * Copyright 2000-2012 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -371,7 +371,7 @@ class InitialInfoBuilder { final FormattingDocumentModelImpl modelImpl = (FormattingDocumentModelImpl)model; buffer.append("Psi Tree:\n"); final PsiFile file = modelImpl.getFile(); - final PsiFile[] roots = file.getPsiRoots(); + final List roots = file.getViewProvider().getAllFiles(); for (PsiFile root : roots) { buffer.append("Root "); DebugUtil.treeToBuffer(buffer, root.getNode(), 0, false, true, true, true); @@ -383,7 +383,7 @@ class InitialInfoBuilder { } /** - * We want to wrap {@link Block code blocks} sequentially, hence, need to store a processing state and continure from the point + * We want to wrap {@link Block code blocks} sequentially, hence, need to store a processing state and continue from the point * where we stopped the processing last time. *

* Current class defines common contract for the state required for such a processing.