update copyright
[fedora-idea.git] / xml / impl / src / com / intellij / psi / formatter / xml / AbstractSyntheticBlock.java
blob6566f77fbfec6afce664d0047d1f5ac4a99dae76
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.xml;
18 import com.intellij.formatting.*;
19 import com.intellij.lang.ASTNode;
20 import com.intellij.openapi.diagnostic.Logger;
21 import com.intellij.openapi.util.TextRange;
22 import com.intellij.psi.formatter.common.AbstractBlock;
23 import com.intellij.psi.impl.source.SourceTreeToPsiMap;
24 import com.intellij.psi.tree.IElementType;
25 import com.intellij.psi.xml.XmlElementType;
26 import com.intellij.psi.xml.XmlTag;
28 import java.util.List;
31 public abstract class AbstractSyntheticBlock implements Block{
32 protected final Indent myIndent;
33 protected final XmlFormattingPolicy myXmlFormattingPolicy;
34 protected final ASTNode myEndTreeNode;
35 protected final ASTNode myStartTreeNode;
36 private final XmlTag myTag;
38 public AbstractSyntheticBlock(List<Block> subBlocks, Block parent, XmlFormattingPolicy policy, Indent indent) {
39 myEndTreeNode = getLastNode(subBlocks);
40 myStartTreeNode = getFirstNode(subBlocks);
41 myIndent = indent;
42 myXmlFormattingPolicy = policy;
43 myTag = ((AbstractXmlBlock)parent).getTag();
46 private static final Logger LOG = Logger.getInstance("#com.intellij.psi.formatter.xml.AbstractSyntheticBlock");
48 private ASTNode getFirstNode(final List<Block> subBlocks) {
49 LOG.assertTrue(!subBlocks.isEmpty());
50 final Block firstBlock = subBlocks.get(0);
51 if (firstBlock instanceof AbstractBlock) {
52 return ((AbstractBlock)firstBlock).getNode();
53 } else {
54 return getFirstNode(firstBlock.getSubBlocks());
58 private ASTNode getLastNode(final List<Block> subBlocks) {
59 LOG.assertTrue(!subBlocks.isEmpty());
60 final Block lastBlock = subBlocks.get(subBlocks.size() - 1);
61 if (lastBlock instanceof AbstractBlock) {
62 return ((AbstractBlock)lastBlock).getNode();
63 } else {
64 return getLastNode(lastBlock.getSubBlocks());
68 private boolean isEndOfTag() {
69 return myEndTreeNode.getElementType() == XmlElementType.XML_TAG_END;
72 public Wrap getWrap() {
73 return null;
76 public Indent getIndent() {
77 return myIndent;
80 public Alignment getAlignment() {
81 return null;
84 protected static boolean isXmlTagName(final IElementType type1, final IElementType type2) {
85 if (type1 == XmlElementType.XML_NAME && type2 == XmlElementType.XML_TAG_END) return true;
86 if (type1 == XmlElementType.XML_NAME && type2 == XmlElementType.XML_EMPTY_ELEMENT_END) return true;
87 if (type1 == XmlElementType.XML_ATTRIBUTE && type2 == XmlElementType.XML_EMPTY_ELEMENT_END) return true;
88 return type1 == XmlElementType.XML_ATTRIBUTE && type2 == XmlElementType.XML_TAG_END;
91 public boolean endsWithText() {
92 return myEndTreeNode.getElementType() == XmlElementType.XML_TEXT || myEndTreeNode.getElementType() == XmlElementType.XML_DATA_CHARACTERS;
95 public boolean isTagDescription() {
96 final ASTNode startTreeNode = myStartTreeNode;
97 return isTagDescription(startTreeNode);
100 private static boolean isTagDescription(final ASTNode startTreeNode) {
101 return startTreeNode.getElementType() == XmlElementType.XML_START_TAG_START || startTreeNode.getElementType() == XmlElementType.XML_END_TAG_START;
104 public boolean startsWithText() {
105 return myStartTreeNode.getElementType() == XmlElementType.XML_TEXT || myStartTreeNode.getElementType() == XmlElementType.XML_DATA_CHARACTERS;
108 public boolean endsWithTextElement() {
109 if (endsWithText()) return true;
110 if (isEndOfTag() && myXmlFormattingPolicy.isTextElement(getTag())) return true;
111 return isTextTag(myEndTreeNode);
114 protected XmlTag getTag() {
115 return myTag;
118 public boolean startsWithTextElement() {
119 if (startsWithText()) return true;
120 if (isStartOfTag() && myXmlFormattingPolicy.isTextElement(getTag())) return true;
121 return isTextTag(myStartTreeNode);
124 private boolean isTextTag(final ASTNode treeNode) {
125 return isXmlTag(treeNode) && myXmlFormattingPolicy.isTextElement((XmlTag)SourceTreeToPsiMap.treeElementToPsi(treeNode));
128 private boolean isXmlTag(final ASTNode treeNode) {
129 return (treeNode.getPsi() instanceof XmlTag);
132 private boolean isStartOfTag() {
133 return isTagDescription(myStartTreeNode);
136 protected static TextRange calculateTextRange(final List<Block> subBlocks) {
137 return new TextRange(subBlocks.get(0).getTextRange().getStartOffset(),
138 subBlocks.get(subBlocks.size()- 1).getTextRange().getEndOffset());
141 public boolean isIncomplete() {
142 return getSubBlocks().get(getSubBlocks().size() - 1).isIncomplete();
145 public boolean startsWithTag() {
146 return isXmlTag(myStartTreeNode);
149 public XmlTag getStartTag() {
150 return (XmlTag)myStartTreeNode.getPsi();
154 public boolean endsWithTag() {
155 return isXmlTag(myEndTreeNode);
158 public boolean isJspTextBlock() {
159 return false;
162 public boolean isJspxTextBlock() {
163 return false;
166 public boolean isLeaf() {
167 return false;
170 public boolean startsWithCDATA() {
171 return isCDATA(myStartTreeNode.getFirstChildNode());
174 private boolean isCDATA(final ASTNode node) {
175 return node != null && node.getElementType() == XmlElementType.XML_CDATA;
178 public boolean endsWithCDATA() {
179 return isCDATA(myStartTreeNode.getLastChildNode());
182 public boolean insertLineFeedAfter() {
183 final List<Block> subBlocks = getSubBlocks();
184 final Block lastBlock = subBlocks.get(subBlocks.size() - 1);
185 if (lastBlock instanceof XmlTagBlock) {
186 return insertLineFeedAfter(((XmlTagBlock)lastBlock).getTag());
188 if (endsWithText()) {
189 return insertLineFeedAfter(myTag);
191 return false;
194 protected boolean insertLineFeedAfter(final XmlTag tag) {
195 return myXmlFormattingPolicy.getWrappingTypeForTagBegin(tag) == WrapType.ALWAYS;