update copyright
[fedora-idea.git] / java / java-impl / src / com / intellij / psi / formatter / java / BlockContainingJavaBlock.java
blob7bae1e7e45a9e13b1a685b6dd6a47bb20bc545e7
1 /*
2 * Copyright 2000-2009 JetBrains s.r.o.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
16 package com.intellij.psi.formatter.java;
18 import com.intellij.formatting.*;
19 import com.intellij.lang.ASTNode;
20 import com.intellij.psi.codeStyle.CodeStyleSettings;
21 import com.intellij.psi.formatter.FormatterUtil;
22 import com.intellij.psi.impl.source.tree.ElementType;
23 import com.intellij.psi.impl.source.tree.JavaDocElementType;
24 import com.intellij.psi.impl.source.tree.StdTokenSets;
25 import com.intellij.psi.tree.IElementType;
26 import org.jetbrains.annotations.NotNull;
28 import java.util.ArrayList;
29 import java.util.List;
31 public class BlockContainingJavaBlock extends AbstractJavaBlock{
33 private final static int BEFORE_FIRST = 0;
34 private final static int BEFORE_BLOCK = 1;
35 private final static int AFTER_ELSE = 2;
37 private final List<Indent> myIndentsBefore = new ArrayList<Indent>();
39 public BlockContainingJavaBlock(final ASTNode node, final Wrap wrap, final Alignment alignment, final Indent indent, CodeStyleSettings settings) {
40 super(node, wrap, alignment, indent, settings);
42 protected List<Block> buildChildren() {
43 final ArrayList<Block> result = new ArrayList<Block>();
44 Alignment childAlignment = createChildAlignment();
45 Wrap childWrap = createChildWrap();
47 buildChildren(result, childAlignment, childWrap);
49 return result;
53 private void buildChildren(final ArrayList<Block> result, final Alignment childAlignment, final Wrap childWrap) {
54 ASTNode child = myNode.getFirstChildNode();
56 int state = BEFORE_FIRST;
58 while (child != null) {
59 if (!FormatterUtil.containsWhiteSpacesOnly(child) && child.getTextLength() > 0){
60 final Indent indent = calcIndent(child, state);
61 myIndentsBefore.add(calcIndentBefore(child, state));
62 state = calcNewState(child, state);
63 child = processChild(result, child, childAlignment, childWrap, indent);
64 for (int i = myIndentsBefore.size(); i < result.size(); i++) {
65 myIndentsBefore.add(Indent.getContinuationIndent());
68 if (child != null) {
69 child = child.getTreeNext();
74 private int calcNewState(final ASTNode child, final int state) {
75 if (state == BEFORE_FIRST) {
76 if (child.getElementType() == ElementType.ELSE_KEYWORD) {
77 return AFTER_ELSE;
79 if (StdTokenSets.COMMENT_BIT_SET.contains(child.getElementType())) {
80 return BEFORE_FIRST;
82 if (child.getElementType() == ElementType.CATCH_SECTION) {
83 return BEFORE_FIRST;
85 } else if (state == BEFORE_BLOCK){
86 if (child.getElementType() == ElementType.ELSE_KEYWORD) {
87 return AFTER_ELSE;
89 if (child.getElementType() == ElementType.BLOCK_STATEMENT) {
90 return BEFORE_FIRST;
92 if (child.getElementType() == ElementType.CODE_BLOCK) {
93 return BEFORE_FIRST;
97 return BEFORE_BLOCK;
100 private Indent calcIndent(final ASTNode child, final int state) {
101 if (state == AFTER_ELSE && child.getElementType() == ElementType.IF_STATEMENT) {
102 if (!mySettings.SPECIAL_ELSE_IF_TREATMENT) {
103 return getCodeBlockInternalIndent(1);
104 } else {
105 return getCodeBlockExternalIndent();
108 if (isSimpleStatement(child)){
109 return createNormalIndent(1);
111 if (child.getElementType() == ElementType.ELSE_KEYWORD)
112 return Indent.getNoneIndent();
113 if (state == BEFORE_FIRST) {
114 return Indent.getNoneIndent();
116 else if (child.getElementType() == ElementType.WHILE_KEYWORD) {
117 return Indent.getNoneIndent();
119 else {
120 if (isPartOfCodeBlock(child)) {
121 return getCodeBlockExternalIndent();
123 else if (isSimpleStatement(child)){
124 return getCodeBlockInternalIndent(1);
126 else if (StdTokenSets.COMMENT_BIT_SET.contains(child.getElementType())) {
127 return getCodeBlockInternalIndent(1);
129 else {
130 return Indent.getContinuationIndent();
135 private Indent calcIndentBefore(final ASTNode child, final int state) {
136 if (state == AFTER_ELSE) {
137 if (!mySettings.SPECIAL_ELSE_IF_TREATMENT) {
138 return getCodeBlockInternalIndent(1);
139 } else {
140 return getCodeBlockExternalIndent();
143 if (state == BEFORE_BLOCK && (isSimpleStatement(child) || child.getElementType() == ElementType.BLOCK_STATEMENT)){
144 return getCodeBlockInternalIndent(0);
146 if (state == BEFORE_FIRST) {
147 return getCodeBlockExternalIndent();
149 if (child.getElementType() == ElementType.ELSE_KEYWORD)
150 return getCodeBlockExternalIndent();
152 return Indent.getContinuationIndent();
155 private boolean isSimpleStatement(final ASTNode child) {
156 if (child.getElementType() == ElementType.BLOCK_STATEMENT) return false;
157 if (!ElementType.STATEMENT_BIT_SET.contains(child.getElementType())) return false;
158 return isStatement(child, child.getTreeParent());
161 private boolean isPartOfCodeBlock(final ASTNode child) {
162 if (child == null) return false;
163 if (child.getElementType() == ElementType.BLOCK_STATEMENT) return true;
164 if (child.getElementType() == ElementType.CODE_BLOCK) return true;
166 if (FormatterUtil.containsWhiteSpacesOnly(child)) return isPartOfCodeBlock(child.getTreeNext());
167 if (child.getElementType() == ElementType.END_OF_LINE_COMMENT) return isPartOfCodeBlock(child.getTreeNext());
168 return child.getElementType() == JavaDocElementType.DOC_COMMENT;
171 protected Wrap getReservedWrap(final IElementType elementType) {
172 return null;
175 protected void setReservedWrap(final Wrap reservedWrap, final IElementType operationType) {
178 @NotNull
179 public ChildAttributes getChildAttributes(final int newChildIndex) {
180 if (isAfter(newChildIndex, new IElementType[]{JavaDocElementType.DOC_COMMENT})) {
181 return new ChildAttributes(Indent.getNoneIndent(), null);
184 if (myNode.getElementType() == ElementType.FOR_STATEMENT && mySettings.ALIGN_MULTILINE_FOR && isInsideForParens(newChildIndex)) {
185 Alignment prev = getUsedAlignment(newChildIndex);
186 if (prev != null) {
187 return new ChildAttributes(null, prev);
191 if (newChildIndex == 0) {
192 return new ChildAttributes(getCodeBlockExternalIndent(), null);
195 if (newChildIndex == getSubBlocks().size()) {
196 return new ChildAttributes(getCodeBlockChildExternalIndent(newChildIndex), null);
199 return new ChildAttributes(myIndentsBefore.get(newChildIndex), null);
203 private boolean isInsideForParens(final int newChildIndex) {
204 final List<Block> subBlocks = getSubBlocks();
205 for (int i = 0; i < newChildIndex; i++) {
206 if (i >= subBlocks.size()) return false;
207 final Block block = subBlocks.get(i);
208 if (block instanceof LeafBlock) {
209 if (((LeafBlock)block).getTreeNode().getElementType() == ElementType.RPARENTH) return false;
212 return true;