diff options
author | Tor Norbye <tnorbye@google.com> | 2014-01-06 10:22:20 -0800 |
---|---|---|
committer | Tor Norbye <tnorbye@google.com> | 2014-01-06 10:22:24 -0800 |
commit | f2f7178ad6915927d918481b911e57a49785e4c4 (patch) | |
tree | c2b0f8906d38f5f1e2f5da853c67e09205816bf6 /java/java-impl/src | |
parent | 8668e1be0891658129cbc8f0965380f702c26755 (diff) | |
download | idea-f2f7178ad6915927d918481b911e57a49785e4c4.tar.gz |
Snapshot c11f3ac9bbde3f85d1f837ec3eb48a395ed7dd10 from idea/133.471 of git://git.jetbrains.org/idea/community.git
c11f3ac: faster xml properties indexing: don't process if no required namespace string present (cherry picked from commit 0845f9e) [r=Dmitry.Avdeev]
0be6c40: to get version sort copy of ClsStubBuilderFactory implementation array (cherry picked from commit c34b260) [r=Alexander.Podkhalusin]
8ed9df6: IDEA-116087 Warning when using new wrapper.gradleVersion construction (cherry picked from commit d3a81f0)
d33b33a: Gradle: fix check for gradle-related files (cherry picked from commit 140b618)
e8c50fa: Gradle: fix creation/sync of gradle wrapper files on project import
3fcf435: IDEA-99036 Changing breakpoint suspend policy from popup does not actually change the policy
033cdba: IDEA-116636 Android-Gradle facet is created when Gradle synchronization. related bug IDEA-116887 Gradle web artifacts do not contain compiled classes and JSP files (cherry picked from commit 64e7f51)
1f4d754: EA-52867 (null check)
3e2b5c5: proper processing of dom indices, 2 (cherry picked from commit e9d6759)
7061e85: proper processing of dom indices (cherry picked from commit e5401d6)
e04883d: proper implementation and usage of indices for DOMStubs
5fa6cf9: do not load/try to index inner classes content / delegate to ClsStubBuilder for inner class identification (cherry picked from commit a085c19) [r=Alexander.Podkhalusin]
3a8fd3f: - use all BinaryStubBuilders versions in stable order to calculate stub version - introduce version for ClassStubBuilderFactory and use all class stub builder factories in stable order to calculate version of ClassFileStubBuilder [r=Eugene.Zhuravlev, Alexander.Podkhalusin]
57e7213: IDEA-118436 Resource Bundle Editor converts UTF8 characters to ASCII even in UTF8 file
1dc12b4: IDEA-112730 PhpStorm goes crazy with collapsed comments and soft wraps until crash
eee52a9: IDEA-112730 PhpStorm goes crazy with collapsed comments and soft wraps until crash
c187921: IDEA-112730 PhpStorm goes crazy with collapsed comments and soft wraps until crash
2119489: ActionTestCase extracted from CoffeeScript and Puppet (cherry picked from commit be905df)
12e8b76: Overriding language in VariableInplaceRenamer. (CoffeeScript) (cherry picked from commit b459118)
c9069d1: IDEA-118587 IDEA may not exit with black window (cherry picked from commit a622b21)
6733c9e: WEB-9566 Debugger: optionally ignore certificate errors (cherry picked from commit af49f19)
da588bc: move CertificatesManager to platform (cherry picked from commit 6dc50e6)
f11ceb2: WEB-8262 Comment with line/block comment STILL doesn't work on HTML in ASP file (cherry picked from commit a83731c) [r=Rustam.Vyshnyakov]
8cfe207: WEB-849 "Comment with line comment" on empty line in <script> block generates HTML instead of JS comment (cherry picked from commit 73a14ec) [r=Rustam.Vyshnyakov]
36cf71c: WEB-6700 TODOs not recognized on multiple level language template (cherry picked from commit 9d00810) [r=Alexey.Gopachenko]
146d0c3: IDEA-118701 Multimodule project imported into IDEA via opening project file gets incorrect project name (cherry picked from commit 0912313)
25e5150: Bug fix: check not-null (cherry picked from commit 6b54183)
80932f6: IDEA-118601 New Module: Maven: click on "Create from archetype" reverts typed coordinates (cherry picked from commit d94c9a1)
a419509: IDEA-116593 improve choosing of Android and Java SDKs when creating new android-gradle project/module: choose only Android SDK location (if we don't know it) on first step, not build target; choose Java SDK (if there is no any) separately, set it as project sdk and as internal jdk for newly created android sdk entities (cherry picked from commit 2bf19b4)
e889183: Fixed IDEA-116006 Eclipse code style import: import the same xml does not pick up changes until manual synchronization (cherry picked from commit f6e9d9d)
fd2b92e: licenses missing licenses for libraries used by android
b5b25e5: Fixed IDEA-117788 Eclipse code style import: continuation indent is imported not multiplied to tab size (cherry picked from commit a9768ee)
074876e: remove all indexed state upon invalidateIndicesForFile (r=Eugene.Zhuravlev)
caa4032: EA-35422 - IOOBE: EditorImpl.offsetToLogicalLine (from debugger) (cherry picked from commit c21cd02) [r=Peter.Gromov]
b47b369: attach messages to root node if no running node found (cherry picked from commit 5c66005)
02cf0b4: [log] Flush & Close persistent enumerator on dispose()
f84ff13: better way to instantiate PersistentHashMap
36d590f: [git] Wrap the VcsException not to loose the cause
339dede: [log] IDEA-115407 Disable graph-only-actions if there is no graph
3773e2c: [log] IDEA-115568 Don't crash if the log is empty
cafe1a8: [log] IDEA-115901 Keep selection between refreshes and filtering
8169bbe: [log] rename type parameter to a more descriptive name
0548151: [log] remove pointless code
29f0909: [log] Don't use setFont(), instead supply value in getFont()
82f67f7: [log] IDEA-117816 small optimization in graph cell drawing
1acba78: IDEA-102942 Wrap always Chained methods calls over-format simple operations (cherry picked from commit 835ed38)
8ef13e9: IDEA-118613: catch all possible exceptions, that may be caused by corrupted storages
0654f14: IDEA-96131 Java: Braces placements don't work as expected for `Next Line` [CR-IC-3694] (cherry picked from commit 975cfe8)
ee689af: WEB-10387 Mocha console log statements are not correctly aligned to their encasing tests (cherry picked from commit 6018640)
b6b35e2: WEB-9517 Npm: Error loading package list (cherry picked from commit aa82d2a)
07d7344: test fix: explicit encoding is required
257ac80: cleanup
9b46832: IDEA-93034 SQL: MySQL: erasing the first backtick could erase the pair
6da1645: in case when some output and source roots intersect: do not stop rebuild if caches version is advanced (IDEA-118613)
631aea6: separate checks if compiler is enabled and compiler api is supported by compiler implementation
4ecc2a5: external build: added method to register output directory in source-to-output mapping instead of registering individual files to reduce occupied disk space (ZD-16651) [rev by Jeka]
f344db7: don't copy ui-designer runtime classes to output if only NetBeans *.form files are found (ZD-14954) [rev by Jeka]
88de860: standalone JPS build: propagate 'forceBuild' option to dependencies implicitly included into compile scope [rev by Jeka]
cbec9d7: [^Peter] EA-50899 - ISE: GrRegexImpl.createLiteralTextEscaper
3013e02: [^Peter] IDEA-117828 Groovy console: execute groovy code shortcut changed back
6ad8dbf: [^Peter] IDEA-117292 Groovy: checks for @Immutable class
8d2c8cf: EA-52292 fix (PHP template inside HTML comment case) (cherry picked from commit 41ccbd2)
1fc4a80: IDEA-118595
0f7f3a1: cleanup imports
09b3d12: style
efdd1aa: OutputSuppressed option added for HgCommandExecutor, style changed, unnecessary parameters removed (cherry picked from commit 4d55fdd)
12789c5: cosmetics: revision hash template changed to long. (cherry picked from commit f1c78e1)
57c3348: Parents revision hash template changed to long. (cherry picked from commit 32ab1db)
b70b45e: IDEA-118266 time measurements for all Mercurial commands added and log command debug output suppressed. (cherry picked from commit 75ec80e)
f44f8d8: [^maxmedvedev] gdsl: be prepared to multithreaded scripts (cherry picked from commit a240a44)
6121316: + "trie" (cherry picked from commit 669ae41)
3c8884d: IDEA-118552 Generated ANT scripts do not honour cross-compile settings
Change-Id: I18c031b09527bf8c7de6a529b546e66950a816d3
Diffstat (limited to 'java/java-impl/src')
-rw-r--r-- | java/java-impl/src/com/intellij/psi/formatter/java/AbstractJavaBlock.java | 175 | ||||
-rw-r--r-- | java/java-impl/src/com/intellij/psi/formatter/java/JavaSpacePropertyProcessor.java | 35 |
2 files changed, 128 insertions, 82 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 d392d7a7a481..d98165f3e7a8 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 @@ -712,67 +712,8 @@ public abstract class AbstractJavaBlock extends AbstractBlock implements JavaBlo @NotNull private Block createMethodCallExpressionBlock(@NotNull final ASTNode node, final Wrap blockWrap, final Alignment alignment) { final ArrayList<ASTNode> nodes = new ArrayList<ASTNode>(); - final ArrayList<Block> subBlocks = new ArrayList<Block>(); collectNodes(nodes, node); - - final Wrap wrap = Wrap.createWrap(getWrapType(mySettings.METHOD_CALL_CHAIN_WRAP), false); - - // We use this alignment object to align chained method calls to the first method invocation place if necessary (see IDEA-30369) - Alignment chainedCallsAlignment = createAlignment(mySettings.ALIGN_MULTILINE_CHAINED_METHODS, null); - - // We want to align chained method calls only if method target is explicitly specified, i.e. we don't want to align methods - // chain like 'recursive().recursive().recursive()' but want to align calls like 'foo.recursive().recursive().recursive()' - boolean callPointDefined = false; - List<ASTNode> lookAheadNodes = null; - boolean afterIdentifier = false; - - while (!nodes.isEmpty() || lookAheadNodes != null) { - final List<ASTNode> subNodes; - if (lookAheadNodes == null) { - subNodes = readToNextDot(nodes); - } - else { - subNodes = new ArrayList<ASTNode>(lookAheadNodes); - lookAheadNodes = null; - } - Alignment alignmentToUseForSubBlock = null; - - // 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(createSyntheticBlock(subNodes, wrap, alignmentToUseForSubBlock)); - continue; - } - - IElementType lastNodeType = subNodes.get(subNodes.size() - 1).getElementType(); - boolean currentSubBlockIsMethodCall = lastNodeType == JavaElementType.EXPRESSION_LIST; - - // Update information about chained method alignment point if necessary. I.e. we want to align only continuous method calls - // like 'foo.bar().bar().bar()' but not 'foo.bar().foo.bar()' - if (callPointDefined && !currentSubBlockIsMethodCall) { - chainedCallsAlignment = createAlignment(mySettings.ALIGN_MULTILINE_CHAINED_METHODS, null); - } - callPointDefined |= !currentSubBlockIsMethodCall; - - // We want to align method call only if call target is defined for the first chained method and current block is a method call. - if (callPointDefined && currentSubBlockIsMethodCall) { - alignmentToUseForSubBlock = chainedCallsAlignment; - } - else if (afterIdentifier && lastNodeType == JavaTokenType.IDENTIFIER) { - // Align method call to the last field access. Example: - // MyClass.staticField - // .foo(); - lookAheadNodes = readToNextDot(nodes); - if (!lookAheadNodes.isEmpty() && lookAheadNodes.get(lookAheadNodes.size() - 1).getElementType() == JavaElementType.EXPRESSION_LIST) { - alignmentToUseForSubBlock = chainedCallsAlignment; - } - } - afterIdentifier = lastNodeType == JavaTokenType.IDENTIFIER; - subBlocks.add(createSyntheticBlock(subNodes, wrap, alignmentToUseForSubBlock)); - } - - return new SyntheticCodeBlock(subBlocks, alignment, mySettings, - Indent.getContinuationWithoutFirstIndent(myIndentSettings.USE_RELATIVE_INDENTS), blockWrap); + return new ChainMethodCallsBlockBuilder(alignment, blockWrap).build(nodes); } @NotNull @@ -802,19 +743,6 @@ public abstract class AbstractJavaBlock extends AbstractBlock implements JavaBlo return result; } - @NotNull - private static List<ASTNode> readToNextDot(@NotNull List<ASTNode> nodes) { - final ArrayList<ASTNode> result = new ArrayList<ASTNode>(); - result.add(nodes.remove(0)); - for (Iterator<ASTNode> iterator = nodes.iterator(); iterator.hasNext();) { - ASTNode node = iterator.next(); - if (node.getElementType() == JavaTokenType.DOT) break; - result.add(node); - iterator.remove(); - } - return result; - } - private static void collectNodes(@NotNull List<ASTNode> nodes, @NotNull ASTNode node) { ASTNode child = node.getFirstChildNode(); while (child != null) { @@ -1504,4 +1432,105 @@ public abstract class AbstractJavaBlock extends AbstractBlock implements JavaBlo result.setChildAttributes(new ChildAttributes(getCodeBlockInternalIndent(childrenIndent), null)); return result; } + + private class ChainMethodCallsBlockBuilder { + private Wrap blockWrap; + private Alignment blockAlignment; + + private Wrap myWrap; + private Alignment myChainedCallsAlignment; + + public ChainMethodCallsBlockBuilder(Alignment alignment, Wrap wrap) { + blockWrap = wrap; + blockAlignment = alignment; + } + + public Block build(List<ASTNode> nodes) { + myWrap = getNewWrap(); + myChainedCallsAlignment = getNewAlignment(); + + List<Block> blocks = buildBlocksFrom(nodes); + Indent indent = Indent.getContinuationWithoutFirstIndent(myIndentSettings.USE_RELATIVE_INDENTS); + + return new SyntheticCodeBlock(blocks, blockAlignment, mySettings, indent, blockWrap); + } + + private List<Block> buildBlocksFrom(List<ASTNode> nodes) { + List<ChainedCallChunk> methodCall = splitMethodCallOnChunksByDots(nodes); + Wrap wrapToUse = null; + Alignment alignmentToUse = null; + + List<Block> blocks = new ArrayList<Block>(); + + for (ChainedCallChunk currentCallChunk : methodCall) { + if (isMethodCall(currentCallChunk)) { + wrapToUse = myWrap; + alignmentToUse = shouldAlignMethod(currentCallChunk, methodCall) ? myChainedCallsAlignment : null; + } + else if (wrapToUse != null) { + wrapToUse = null; + alignmentToUse = null; + + myChainedCallsAlignment = getNewAlignment(); + myWrap = getNewWrap(); + } + + blocks.add(createSyntheticBlock(currentCallChunk.nodes, wrapToUse, alignmentToUse)); + } + + return blocks; + } + + private boolean shouldAlignMethod(ChainedCallChunk currentMethodChunk, List<ChainedCallChunk> methodCall) { + return mySettings.ALIGN_MULTILINE_CHAINED_METHODS + && !currentMethodChunk.isEmpty() + && !chunkIsFirstInChainMethodCall(currentMethodChunk, methodCall); + } + + private boolean chunkIsFirstInChainMethodCall(@NotNull ChainedCallChunk callChunk, @NotNull List<ChainedCallChunk> methodCall) { + return !methodCall.isEmpty() && callChunk == methodCall.get(0); + } + + @NotNull + private List<ChainedCallChunk> splitMethodCallOnChunksByDots(@NotNull List<ASTNode> nodes) { + List<ChainedCallChunk> result = new ArrayList<ChainedCallChunk>(); + + List<ASTNode> current = new ArrayList<ASTNode>(); + for (ASTNode node : nodes) { + if (node.getElementType() == JavaTokenType.DOT) { + result.add(new ChainedCallChunk(current)); + current = new ArrayList<ASTNode>(); + } + current.add(node); + } + + result.add(new ChainedCallChunk(current)); + return result; + } + + private Alignment getNewAlignment() { + return createAlignment(mySettings.ALIGN_MULTILINE_CHAINED_METHODS, null); + } + + private Wrap getNewWrap() { + return Wrap.createWrap(getWrapType(mySettings.METHOD_CALL_CHAIN_WRAP), false); + } + + private boolean isMethodCall(@NotNull ChainedCallChunk callChunk) { + List<ASTNode> nodes = callChunk.nodes; + return !nodes.isEmpty() && nodes.get(nodes.size() - 1).getElementType() == JavaElementType.EXPRESSION_LIST; + } + } + + private static class ChainedCallChunk { + @NotNull final List<ASTNode> nodes; + + ChainedCallChunk(@NotNull List<ASTNode> nodes) { + this.nodes = nodes; + } + + boolean isEmpty() { + return nodes.isEmpty(); + } + } } diff --git a/java/java-impl/src/com/intellij/psi/formatter/java/JavaSpacePropertyProcessor.java b/java/java-impl/src/com/intellij/psi/formatter/java/JavaSpacePropertyProcessor.java index 8f090b072d16..eed6d597e476 100644 --- a/java/java-impl/src/com/intellij/psi/formatter/java/JavaSpacePropertyProcessor.java +++ b/java/java-impl/src/com/intellij/psi/formatter/java/JavaSpacePropertyProcessor.java @@ -840,8 +840,14 @@ public class JavaSpacePropertyProcessor extends JavaElementVisitor { } else { if (myChild2.getElementType() == JavaElementType.BLOCK_STATEMENT || myChild2.getElementType() == JavaElementType.CODE_BLOCK) { - myResult = getSpaceBeforeLBrace(mySettings.SPACE_BEFORE_ELSE_LBRACE, mySettings.BRACE_STYLE, null, - mySettings.KEEP_SIMPLE_BLOCKS_IN_ONE_LINE, true); + PsiElement branch = statement.getElseBranch(); + boolean shouldKeepInOneLine = mySettings.KEEP_SIMPLE_BLOCKS_IN_ONE_LINE + && branch != null + && !branch.textContains('\n'); + + myResult = getSpaceBeforeLBrace(mySettings.SPACE_BEFORE_ELSE_LBRACE, + mySettings.BRACE_STYLE, + null, shouldKeepInOneLine, true); } else { createSpacingBeforeElementInsideControlStatement(); @@ -849,10 +855,19 @@ public class JavaSpacePropertyProcessor extends JavaElementVisitor { } } else if (myChild2.getElementType() == JavaElementType.BLOCK_STATEMENT || myChild2.getElementType() == JavaElementType.CODE_BLOCK) { - boolean space = myRole2 == ChildRole.ELSE_BRANCH ? mySettings.SPACE_BEFORE_ELSE_LBRACE : mySettings.SPACE_BEFORE_IF_LBRACE; + boolean space = myRole2 == ChildRole.ELSE_BRANCH ? mySettings.SPACE_BEFORE_ELSE_LBRACE + : mySettings.SPACE_BEFORE_IF_LBRACE; + + PsiElement branch = myRole2 == ChildRole.ELSE_BRANCH ? statement.getElseBranch() + : statement.getThenBranch(); + + boolean shouldKeepInOneLine = mySettings.KEEP_SIMPLE_BLOCKS_IN_ONE_LINE + && branch != null + && !branch.textContains('\n'); + myResult = getSpaceBeforeLBrace(space, mySettings.BRACE_STYLE, new TextRange(myParent.getTextRange().getStartOffset(), myChild1.getTextRange().getEndOffset()), - mySettings.KEEP_SIMPLE_BLOCKS_IN_ONE_LINE, true); + shouldKeepInOneLine, true); } else if (myRole2 == ChildRole.LPARENTH) { createSpaceInCode(mySettings.SPACE_BEFORE_IF_PARENTHESES); @@ -909,7 +924,7 @@ public class JavaSpacePropertyProcessor extends JavaElementVisitor { else if (braceStyle == CommonCodeStyleSettings.END_OF_LINE || braceStyle == CommonCodeStyleSettings.NEXT_LINE_IF_WRAPPED) { return createNonLFSpace(space, null, false); } - else if (braceStyle == CommonCodeStyleSettings.NEXT_LINE && !mySettings.KEEP_SIMPLE_METHODS_IN_ONE_LINE) { + else if (braceStyle == CommonCodeStyleSettings.NEXT_LINE) { space = (keepOneLine && spaceBeforeLbrace) ? 1 : 0; return Spacing.createSpacing(space, 0, keepOneLine ? 0 : 1, false, mySettings.KEEP_BLANK_LINES_IN_CODE); } @@ -917,9 +932,7 @@ public class JavaSpacePropertyProcessor extends JavaElementVisitor { TextRange dependencyRangeToUse = dependantRange == null || useParentBlockAsDependencyAllTheTime ? myParent.getTextRange() : dependantRange; - return Spacing.createDependentLFSpacing( - space, space, dependencyRangeToUse, mySettings.KEEP_LINE_BREAKS, mySettings.KEEP_BLANK_LINES_IN_CODE - ); + return Spacing.createDependentLFSpacing(space, space, dependencyRangeToUse, mySettings.KEEP_LINE_BREAKS, mySettings.KEEP_BLANK_LINES_IN_CODE); } else { return Spacing.createSpacing(0, 0, 1, false, mySettings.KEEP_BLANK_LINES_IN_CODE); @@ -1043,8 +1056,12 @@ public class JavaSpacePropertyProcessor extends JavaElementVisitor { ASTNode dependencyEndAnchor = mySettings.METHOD_BRACE_STYLE == CommonCodeStyleSettings.NEXT_LINE ? myChild2 : myChild1; int dependencyEnd = dependencyEndAnchor.getTextRange().getEndOffset(); + boolean keepInOneLine = mySettings.KEEP_SIMPLE_METHODS_IN_ONE_LINE + && method.getBody() != null + && !method.getBody().textContains('\n'); + myResult = getSpaceBeforeLBrace(mySettings.SPACE_BEFORE_METHOD_LBRACE, mySettings.METHOD_BRACE_STYLE, - new TextRange(dependencyStart, dependencyEnd), mySettings.KEEP_SIMPLE_METHODS_IN_ONE_LINE, + new TextRange(dependencyStart, dependencyEnd), keepInOneLine, useParentBlockAsDependencyAllTheTime); } else if (myRole1 == ChildRole.MODIFIER_LIST) { |