/* * Copyright 2013 Guidewire Software, Inc. */ package gw.plugin.ij.formatting; import com.intellij.formatting.Alignment; import com.intellij.formatting.Block; import com.intellij.formatting.ChildAttributes; import com.intellij.formatting.Indent; import com.intellij.formatting.Spacing; import com.intellij.formatting.Wrap; 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 com.intellij.psi.tree.ILazyParseableElementType; import gw.plugin.ij.lang.parser.GosuElementTypes; import gw.plugin.ij.lang.psi.impl.statements.GosuStatementListImpl; import gw.plugin.ij.lang.psi.impl.statements.GosuVariableImpl; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.util.ArrayList; import java.util.List; public class GosuBlock extends GosuElementTypes implements Block { @NotNull protected final ASTNode myNode; @Nullable protected final Alignment myAlignment; @NotNull protected final Indent myIndent; @Nullable protected final Wrap myWrap; protected final CodeStyleSettings mySettings; protected List<Block> mySubBlocks; public GosuBlock(@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 = generateSubBlocks(); } return mySubBlocks; } @NotNull protected List<Block> generateSubBlocks() { final PsiElement nodePsi = myNode.getPsi(); final ArrayList<Block> blocks = new ArrayList<>(); ASTNode prevChildNode = null; for (ASTNode childNode : GosuIndentProcessor.getNonEmptyASTNodes(myNode.getChildren(null))) { final Indent childIndent = GosuIndentProcessor.getChildIndent(this, prevChildNode, childNode); final Alignment childAlignment = GosuIndentProcessor.getChildAlignment(this, prevChildNode, childNode, myAlignment); blocks.add(new GosuBlock(childNode, nodePsi instanceof GosuStatementListImpl ? null : childAlignment, childIndent, myWrap, mySettings)); prevChildNode = childNode; } return blocks; } @Nullable public Wrap getWrap() { return myWrap; } @Nullable public Indent getIndent() { return myIndent; } @Nullable public Alignment getAlignment() { return myAlignment; } @Nullable public Spacing getSpacing(@Nullable Block child1, @NotNull Block child2) { final GosuBlock gosuChild1 = (GosuBlock) child1; final GosuBlock gosuChild2 = (GosuBlock) child2; // FIXME-isd: do something... Seems like in IJ12 we can get null we are not expecting if (gosuChild1 == null) { return null; } Spacing spacing; if ((spacing = GosuWrappingAndBracesProcessor.getSpacing(gosuChild1, gosuChild2, mySettings)) != null || (spacing = GosuBlankLinesProcessor.getSpacing(gosuChild1, gosuChild2, mySettings)) != null || (spacing = GosuSpacingProcessor.getSpacing(gosuChild1, gosuChild2, mySettings)) != null) { return spacing; } return null; } @NotNull public ChildAttributes getChildAttributes(int newChildIndex) { return GosuIndentProcessor.getChildAttributes(this, newChildIndex); } public boolean isIncomplete() { return isIncomplete(myNode); } public boolean isIncomplete(@NotNull final ASTNode node) { if (node.getElementType() instanceof ILazyParseableElementType) { return false; } ASTNode lastChild = node.getLastChildNode(); while (lastChild != null && !(lastChild.getElementType() instanceof ILazyParseableElementType) && (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; } @NotNull @Override public String toString() { return myNode.getTextRange() + ": " + myNode; } }