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.formatting.templateLanguages;
18 import com.intellij.formatting.*;
19 import com.intellij.lang.ASTNode;
20 import com.intellij.openapi.util.TextRange;
21 import com.intellij.psi.codeStyle.CodeStyleSettings;
22 import com.intellij.psi.formatter.FormatterUtil;
23 import com.intellij.psi.formatter.common.AbstractBlock;
24 import com.intellij.psi.tree.IElementType;
25 import org.jetbrains.annotations.NotNull;
26 import org.jetbrains.annotations.Nullable;
28 import java.util.ArrayList;
29 import java.util.List;
32 * @author Alexey Chmutov
36 public abstract class TemplateLanguageBlock extends AbstractBlock implements BlockWithParent {
37 private final TemplateLanguageBlockFactory myBlockFactory;
38 private final CodeStyleSettings mySettings;
39 protected List<DataLanguageBlockWrapper> myForeignChildren;
40 private boolean myChildrenBuilt = false;
41 private BlockWithParent myParent;
43 protected TemplateLanguageBlock(@NotNull TemplateLanguageBlockFactory blockFactory, @NotNull CodeStyleSettings settings,
44 @NotNull ASTNode node, @Nullable List<DataLanguageBlockWrapper> foreignChildren) {
45 this(node, null, null, blockFactory, settings, foreignChildren);
48 protected TemplateLanguageBlock(@NotNull ASTNode node, @Nullable Wrap wrap, @Nullable Alignment alignment,
49 @NotNull TemplateLanguageBlockFactory blockFactory,
50 @NotNull CodeStyleSettings settings,
51 @Nullable List<DataLanguageBlockWrapper> foreignChildren) {
52 super(node, wrap, alignment);
53 myBlockFactory = blockFactory;
54 myForeignChildren = foreignChildren;
55 mySettings = settings;
58 protected List<Block> buildChildren() {
59 myChildrenBuilt = true;
63 final ArrayList<TemplateLanguageBlock> tlChildren = new ArrayList<TemplateLanguageBlock>(5);
64 for (ASTNode childNode = getNode().getFirstChildNode(); childNode != null; childNode = childNode.getTreeNext()) {
65 if (FormatterUtil.containsWhiteSpacesOnly(childNode)) continue;
66 if (shouldBuildBlockFor(childNode)) {
67 final TemplateLanguageBlock childBlock = myBlockFactory
68 .createTemplateLanguageBlock(childNode, createChildWrap(childNode), createChildAlignment(childNode), null, mySettings);
69 childBlock.setParent(this);
70 tlChildren.add(childBlock);
73 final List<Block> children = (List<Block>)(myForeignChildren == null ? tlChildren : BlockUtil.mergeBlocks(tlChildren, myForeignChildren));
74 //BlockUtil.printBlocks(getTextRange(), children);
75 return BlockUtil.setParent(children, this);
78 protected boolean shouldBuildBlockFor(ASTNode childNode) {
79 return childNode.getElementType() != getTemplateTextElementType() || noForeignChildren();
82 private boolean noForeignChildren() {
83 return (myForeignChildren == null || myForeignChildren.isEmpty());
86 void addForeignChild(@NotNull DataLanguageBlockWrapper foreignChild) {
87 initForeignChildren();
88 myForeignChildren.add(foreignChild);
91 void addForeignChildren(List<DataLanguageBlockWrapper> foreignChildren) {
92 initForeignChildren();
93 myForeignChildren.addAll(foreignChildren);
96 private void initForeignChildren() {
97 assert !myChildrenBuilt;
98 if (myForeignChildren == null) {
99 myForeignChildren = new ArrayList<DataLanguageBlockWrapper>(5);
104 public Spacing getSpacing(Block child1, Block child2) {
105 if (child1 instanceof DataLanguageBlockWrapper && child2 instanceof DataLanguageBlockWrapper) {
106 return ((DataLanguageBlockWrapper)child1).getRightHandSpacing((DataLanguageBlockWrapper)child2);
111 public boolean isLeaf() {
112 return noForeignChildren() && getNode().getFirstChildNode() == null;
115 protected abstract IElementType getTemplateTextElementType();
117 public BlockWithParent getParent() {
121 public void setParent(BlockWithParent newParent) {
122 myParent = newParent;
126 * Checks if DataLanguageBlockFragmentWrapper must be created for the given text range.
127 * @param range The range to check.
128 * @return True by default.
130 public boolean isRequiredRange(TextRange range) {
134 protected Wrap createChildWrap(ASTNode child) {
135 return Wrap.createWrap(Wrap.NONE, false);
138 protected Alignment createChildAlignment(ASTNode child) {
142 public CodeStyleSettings getSettings() {