package org.jetbrains.plugins.clojure.formatter; import com.intellij.formatting.*; import com.intellij.lang.ASTNode; import com.intellij.openapi.util.TextRange; import com.intellij.psi.PsiComment; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiErrorElement; import com.intellij.psi.PsiWhiteSpace; import com.intellij.psi.codeStyle.CodeStyleSettings; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.plugins.clojure.formatter.processors.ClojureSpacingProcessor; import org.jetbrains.plugins.clojure.parser.ClojureElementTypes; import org.jetbrains.plugins.clojure.psi.api.ClojureFile; import java.util.List; /** * @author ilyas */ public class ClojureBlock implements Block, ClojureElementTypes{ final protected ASTNode myNode; final protected Alignment myAlignment; final protected Indent myIndent; final protected Wrap myWrap; final protected CodeStyleSettings mySettings; final Alignment childAlignment = Alignment.createAlignment(); protected List<Block> mySubBlocks = null; public ClojureBlock(@NotNull final ASTNode node, @Nullable final Alignment alignment, @NotNull final Indent indent, @Nullable final Wrap wrap, final CodeStyleSettings settings) { myNode = node; myAlignment = alignment; myIndent = indent; myWrap = wrap; mySettings = settings; } @NotNull public ASTNode getNode() { return myNode; } @NotNull public CodeStyleSettings getSettings() { return mySettings; } @NotNull public TextRange getTextRange() { return myNode.getTextRange(); } @NotNull public List<Block> getSubBlocks() { if (mySubBlocks == null) { mySubBlocks = new ClojureBlockGenerator().generateSubBlocks(myNode, myWrap, mySettings, this); } return mySubBlocks; } @Nullable public Wrap getWrap() { return myWrap; } @Nullable public Indent getIndent() { return myIndent; } @Nullable public Alignment getAlignment() { return myAlignment; } public Spacing getSpacing(Block child1, Block child2) { return ClojureSpacingProcessor.getSpacing(child1, child2); } @NotNull public ChildAttributes getChildAttributes(final int newChildIndex) { return getAttributesByParent(); } private ChildAttributes getAttributesByParent() { ASTNode astNode = getNode(); final PsiElement psiParent = astNode.getPsi(); if (psiParent instanceof ClojureFile) { return new ChildAttributes(Indent.getNoneIndent(), null); } if (LIST_LIKE_FORMS.contains(astNode.getElementType())) { return new ChildAttributes(Indent.getNormalIndent(), childAlignment); } return new ChildAttributes(Indent.getNoneIndent(), null); } public boolean isIncomplete() { return isIncomplete(myNode); } /** * @param node Tree node * @return true if node is incomplete */ public boolean isIncomplete(@NotNull final ASTNode node) { ASTNode lastChild = node.getLastChildNode(); while (lastChild != null && (lastChild.getPsi() instanceof PsiWhiteSpace || lastChild.getPsi() instanceof PsiComment)) { lastChild = lastChild.getTreePrev(); } return lastChild != null && (lastChild.getPsi() instanceof PsiErrorElement || isIncomplete(lastChild)); } public boolean isLeaf() { return myNode.getFirstChildNode() == null; } }