/** * Returns the innermost enclosing function, or {@code null} if not in a function. Begins the * search with this node's parent. * * @return the {@link FunctionNode} enclosing this node, else {@code null} */ public FunctionNode getEnclosingFunction() { AstNode parent = this.getParent(); while (parent != null && !(parent instanceof FunctionNode)) { parent = parent.getParent(); } return (FunctionNode) parent; }
/** * Returns the innermost enclosing {@link Scope} node, or {@code null} if we're not nested in a * scope. Begins the search with this node's parent. Note that this is not the same as the * defining scope for a {@link Name}. * * @return the {@link Scope} enclosing this node, else {@code null} */ public Scope getEnclosingScope() { AstNode parent = this.getParent(); while (parent != null && !(parent instanceof Scope)) { parent = parent.getParent(); } return (Scope) parent; }
/** * Returns the root of the tree containing this node. * * @return the {@link AstRoot} at the root of this node's parent chain, or {@code null} if the * topmost parent is not an {@code AstRoot}. */ public AstRoot getAstRoot() { AstNode parent = this; // this node could be the AstRoot while (parent != null && !(parent instanceof AstRoot)) { parent = parent.getParent(); } return (AstRoot) parent; }
/** * Adds a child or function to the end of the block. Sets the parent of the child to this node, * and fixes up the start position of the child to be relative to this node. Sets the length of * this node to include the new child. * * @param kid the child * @throws IllegalArgumentException if kid is {@code null} */ public void addChild(AstNode kid) { assertNotNull(kid); int end = kid.getPosition() + kid.getLength(); setLength(end - this.getPosition()); addChildToBack(kid); kid.setParent(this); }
/** * Returns the absolute document position of the node. Computes it by adding the node's relative * position to the relative positions of all its parents. */ public int getAbsolutePosition() { int pos = position; AstNode parent = this.parent; while (parent != null) { pos += parent.getPosition(); parent = parent.getParent(); } return pos; }
/** * Visits this node, the target, and each argument. If there is a trailing initializer node, * visits that last. */ @Override public void visit(NodeVisitor v) { if (v.visit(this)) { target.visit(v); for (AstNode arg : getArguments()) { arg.visit(v); } if (initializer != null) { initializer.visit(v); } } }
/** * Permits AST nodes to be sorted based on start position and length. This makes it easy to sort * Comment and Error nodes into a set of other AST nodes: just put them all into a {@link * java.util.SortedSet}, for instance. * * @param other another node * @return -1 if this node's start position is less than {@code other}'s start position. If tied, * -1 if this node's length is less than {@code other}'s length. If the lengths are equal, * sorts abitrarily on hashcode unless the nodes are the same per {@link #equals}. */ public int compareTo(AstNode other) { if (this.equals(other)) return 0; int abs1 = this.getAbsolutePosition(); int abs2 = other.getAbsolutePosition(); if (abs1 < abs2) return -1; if (abs2 < abs1) return 1; int len1 = this.getLength(); int len2 = other.getLength(); if (len1 < len2) return -1; if (len2 < len1) return 1; return this.hashCode() - other.hashCode(); }
/** * Prints a comma-separated item list into a {@link StringBuilder}. * * @param items a list to print * @param sb a {@link StringBuilder} into which to print */ protected <T extends AstNode> void printList(List<T> items, StringBuilder sb) { int max = items.size(); int count = 0; for (AstNode item : items) { sb.append(item.toSource(0)); if (count++ < max - 1) { sb.append(", "); } else if (item instanceof EmptyExpression) { sb.append(","); } } }
public boolean visit(AstNode node) { int tt = node.getType(); String name = Token.typeToName(tt); buffer.append(node.getAbsolutePosition()).append("\t"); buffer.append(makeIndent(node.depth())); buffer.append(name).append(" "); buffer.append(node.getPosition()).append(" "); buffer.append(node.getLength()); if (tt == Token.NAME) { buffer.append(" ").append(((Name) node).getIdentifier()); } buffer.append("\n"); return true; // process kids }
/** * Sets the node parent. This method automatically adjusts the current node's start position to be * relative to the new parent. * * @param parent the new parent. Can be {@code null}. */ public void setParent(AstNode parent) { if (parent == this.parent) { return; } // Convert position back to absolute. if (this.parent != null) { setRelative(-this.parent.getPosition()); } this.parent = parent; if (parent != null) { setRelative(parent.getPosition()); } }
/** * Return the line number recorded for this node. If no line number was recorded, searches the * parent chain. * * @return the nearest line number, or -1 if none was found */ @Override public int getLineno() { if (lineno != -1) return lineno; if (parent != null) return parent.getLineno(); return -1; }
/** * Returns the depth of this node. The root is depth 0, its children are depth 1, and so on. * * @return the node depth in the tree */ public int depth() { return parent == null ? 0 : 1 + parent.depth(); }