/** * There is a possible case that 'implements' section is incomplete (e.g. ends with comma). We may * want to align lbrace to the comma then. * * @param alignment block alignment * @param baseNode base AST node * @return alignment strategy to use for the given node */ private static AlignmentStrategy getAlignmentStrategy( Alignment alignment, ASTNode baseNode, @NotNull CommonCodeStyleSettings settings) { if (baseNode.getElementType() != JavaElementType.CLASS || !settings.ALIGN_MULTILINE_EXTENDS_LIST) { return AlignmentStrategy.wrap(alignment); } for (ASTNode node = baseNode.getLastChildNode(); node != null; node = FormatterUtil.getPreviousNonWhitespaceSibling(node)) { if (node.getElementType() != JavaElementType.IMPLEMENTS_LIST) { continue; } ASTNode lastChildNode = node.getLastChildNode(); if (lastChildNode != null && lastChildNode.getElementType() == TokenType.ERROR_ELEMENT) { Alignment alignmentToUse = alignment; if (alignment == null) { alignmentToUse = Alignment.createAlignment(); } return AlignmentStrategy.wrap( alignmentToUse, false, JavaTokenType.LBRACE, JavaElementType.JAVA_CODE_REFERENCE, node.getElementType()); } break; } return AlignmentStrategy.wrap(alignment); }
@Override public boolean shouldCreateStub(ASTNode node) { // @see getNameIdentifier(ElixirAlias) boolean shouldCreateStub = false; ASTNode parent = node.getTreeParent(); IElementType parentElementType = parent.getElementType(); if (parentElementType == ElixirTypes.ACCESS_EXPRESSION) { ASTNode grandParent = parent.getTreeParent(); IElementType grandParentElementType = grandParent.getElementType(); if (grandParentElementType == ElixirTypes.NO_PARENTHESES_ONE_ARGUMENT) { ASTNode greatGrandParent = grandParent.getTreeParent(); IElementType greatGrandParentElementType = greatGrandParent.getElementType(); if (greatGrandParentElementType == ElixirTypes.UNMATCHED_UNQUALIFIED_NO_PARENTHESES_CALL && greatGrandParent.getFirstChildNode().getText().equals("defmodule")) { IElementType greatGrandParentLastChildElementType = greatGrandParent.getLastChildNode().getElementType(); if (greatGrandParentLastChildElementType == ElixirTypes.DO_BLOCK) { shouldCreateStub = true; } } } } return shouldCreateStub; }
/** * Tries to find node that is direct or indirect previous node of the given node. * * <p>E.g. there is a possible use-case: * * <pre> * n1 * / \ * n21 n22 * | | * n31 n32 * </pre> * * Let's assume that target node is <code>'n32'</code>. 'n31' is assumed to be returned from this * method then. * * <p><b>Note:</b> current method avoids going too deep if found node type is the same as start * node type * * @return direct or indirect previous node of the given one having target type if possible; * <code>null</code> otherwise */ private static boolean findPreviousNode( AlignmentInColumnsConfig config, ASTNode from, IElementType targetType, boolean processFrom, boolean processParent, NodeProcessor processor) { if (from == null) return false; for (ASTNode prev = processFrom ? from : from.getTreePrev(); prev != null; prev = prev.getTreePrev()) { IElementType prevType = prev.getElementType(); if (prevType == targetType) { if (processor.targetTypeFound(prev)) return true; } else if (config.getWhiteSpaceTokenTypes().contains(prevType)) { if (processor.whitespaceFound(prev)) return true; } if (findPreviousNode(config, prev.getLastChildNode(), targetType, true, false, processor)) return true; } if (processParent) { for (ASTNode parent = from.getTreeParent(); parent != null; parent = parent.getTreeParent()) { if (findPreviousNode(config, parent, targetType, false, false, processor)) return true; } } return false; }
public static boolean isIncomplete(@Nullable ASTNode node) { ASTNode lastChild = node == null ? null : node.getLastChildNode(); while (lastChild != null && lastChild.getElementType() == TokenType.WHITE_SPACE) { lastChild = lastChild.getTreePrev(); } if (lastChild == null) return false; if (lastChild.getElementType() == TokenType.ERROR_ELEMENT) return true; return isIncomplete(lastChild); }
@Nullable public static ASTNode getPreviousLeaf( @Nullable ASTNode node, @NotNull IElementType... typesToIgnore) { ASTNode prev = getPrevious(node, typesToIgnore); if (prev == null) { return null; } ASTNode result = prev; ASTNode lastChild = prev.getLastChildNode(); while (lastChild != null) { result = lastChild; lastChild = lastChild.getLastChildNode(); } for (IElementType type : typesToIgnore) { if (result.getElementType() == type) { return getPreviousLeaf(result, typesToIgnore); } } return result; }
@Nullable static XmlToken findEndTagName(@Nullable final PsiErrorElement element) { if (element == null) return null; final ASTNode astNode = element.getNode(); if (astNode == null) return null; ASTNode current = astNode.getLastChildNode(); ASTNode prev = current; while (current != null) { final IElementType elementType = prev.getElementType(); if ((elementType == XmlElementType.XML_NAME || elementType == XmlElementType.XML_TAG_NAME) && current.getElementType() == XmlElementType.XML_END_TAG_START) { return (XmlToken) prev.getPsi(); } prev = current; current = current.getTreePrev(); } return null; }