ca91ad26e4c287672ec1d1034448b95be996e3d0
[idea/javafx-plugin.git] / src / org / jetbrains / javafx / formatter / JavaFxFormattingBlock.java
1 package org.jetbrains.javafx.formatter;
2
3 import com.intellij.formatting.*;
4 import com.intellij.lang.ASTNode;
5 import com.intellij.lang.FileASTNode;
6 import com.intellij.psi.formatter.FormatterUtil;
7 import com.intellij.psi.formatter.common.AbstractBlock;
8 import com.intellij.psi.impl.source.tree.LeafElement;
9 import com.intellij.psi.tree.IElementType;
10 import com.intellij.psi.tree.TokenSet;
11 import org.jetbrains.annotations.NotNull;
12 import org.jetbrains.annotations.Nullable;
13 import org.jetbrains.javafx.lang.lexer.JavaFxTokenTypes;
14 import org.jetbrains.javafx.lang.parser.JavaFxElementTypes;
15
16 import java.util.ArrayList;
17 import java.util.List;
18
19 /**
20  * Created by IntelliJ IDEA.
21  *
22  * @author Alexey.Ivanov
23  */
24 public class JavaFxFormattingBlock extends AbstractBlock {
25   protected final Indent myIndent;
26   protected final Indent myChildIndent;
27
28   public JavaFxFormattingBlock(final FileASTNode node) {
29     this(node, Indent.getAbsoluteNoneIndent(), Indent.getNoneIndent());
30   }
31
32   public JavaFxFormattingBlock(final ASTNode node, final Indent indent, final Indent childIndent) {
33     this(node, null, null, indent, childIndent);
34   }
35
36   protected JavaFxFormattingBlock(@NotNull final ASTNode node,
37                                   @Nullable final Wrap wrap,
38                                   @Nullable final Alignment alignment,
39                                   final Indent indent,
40                                   final Indent childIndent) {
41     super(node, wrap, alignment);
42     myIndent = indent;
43     myChildIndent = childIndent;
44   }
45
46   @Override
47   protected List<Block> buildChildren() {
48     if (isLeaf()) {
49       return EMPTY;
50     }
51
52     final List<Block> result = new ArrayList<Block>();
53     ASTNode child = myNode.getFirstChildNode();
54     while (child != null) {
55       if (!FormatterUtil.containsWhiteSpacesOnly(child) && child.getTextLength() > 0) {
56         processChild(result, child);
57       }
58       child = child.getTreeNext();
59     }
60     return result;
61   }
62
63   private void processChild(final List<Block> blocks, final ASTNode node) {
64     final IElementType type = node.getElementType();
65     final Indent childIndent = calcIndent(node, type);
66
67     if (type == JavaFxElementTypes.BLOCK_EXPRESSION ||
68         type == JavaFxElementTypes.OBJECT_LITERAL ||
69         type == JavaFxElementTypes.SEQUENCE_LITERAL) {
70       blocks.add(new JavaFxBlockFormattingBlock(node, childIndent, Indent.getNormalIndent(false)));
71     }
72     else {
73       blocks.add(new JavaFxFormattingBlock(node, childIndent, Indent.getNoneIndent()));
74     }
75   }
76
77   protected Indent calcIndent(final ASTNode child, final IElementType childType) {
78     return (childType == JavaFxTokenTypes.LBRACE || childType == JavaFxTokenTypes.RBRACE) ? Indent.getNoneIndent() : myChildIndent;
79   }
80
81   @Override
82   public Spacing getSpacing(final Block child1, final Block child2) {
83     return null;
84   }
85
86   @Override
87   public boolean isLeaf() {
88     return (myNode instanceof LeafElement);
89   }
90
91   @Override
92   protected Indent getChildIndent() {
93     return myChildIndent;
94   }
95
96   @Override
97   public Indent getIndent() {
98     return myIndent;
99   }
100
101   private static class JavaFxBlockFormattingBlock extends JavaFxFormattingBlock {
102     private static final TokenSet BRACES =
103       TokenSet.create(JavaFxTokenTypes.LBRACE, JavaFxTokenTypes.RBRACE, JavaFxTokenTypes.LBRACK, JavaFxTokenTypes.RBRACK);
104     private boolean myInsideBraces;
105
106     public JavaFxBlockFormattingBlock(final ASTNode node, final Indent indent, final Indent childIndent) {
107       super(node, indent, childIndent);
108     }
109
110     @Override
111     protected Indent calcIndent(final ASTNode child, final IElementType childType) {
112       if (isBrace(childType)) {
113         myInsideBraces = (childType == JavaFxTokenTypes.LBRACE || childType == JavaFxTokenTypes.LBRACK);
114         return Indent.getNoneIndent();
115       }
116       return myInsideBraces ? myChildIndent : Indent.getNoneIndent();
117     }
118
119     private boolean isBrace(final IElementType childType) {
120       return BRACES.contains(childType);
121     }
122   }
123 }