final void setNestedBlock(TemplateElement nestedBlock) { if (nestedBlock != null) { nestedBlock.parent = this; nestedBlock.index = 0; } this.nestedBlock = nestedBlock; }
private TemplateElement getLastLeaf() { TemplateElement te = this; while (!te.isLeaf() && !(te instanceof Macro) && !(te instanceof BlockAssignment)) { // A macro or macro invocation is treated as a leaf here for special reasons te = te.getLastChild(); } return te; }
TemplateElement prevTerminalNode() { TemplateElement prev = previousSibling(); if (prev != null) { return prev.getLastLeaf(); } else if (parent != null) { return parent.prevTerminalNode(); } return null; }
TemplateElement nextTerminalNode() { TemplateElement next = nextSibling(); if (next != null) { return next.getFirstLeaf(); } else if (parent != null) { return parent.nextTerminalNode(); } return null; }
/** Used for some backward compatibility hacks. */ MixedContent asMixedContent() { MixedContent mixedContent = new MixedContent(); if (count != 0) { TemplateElement first = buffer[0]; mixedContent.setChildren(this); mixedContent.setLocation(first.getTemplate(), first, getLast()); } return mixedContent; }
private static void insertDebugBreak(Template t, Breakpoint breakpoint) { TemplateElement te = findTemplateElement(t.getRootTreeNode(), breakpoint.getLine()); if (te == null) { return; } TemplateElement parent = (TemplateElement) te.getParent(); DebugBreak db = new DebugBreak(te); // TODO: Ensure there always is a parent by making sure // that the root element in the template is always a MixedContent // Also make sure it doesn't conflict with anyone's code. parent.setChildAt(parent.getIndex(te), db); }
private void removeDebugBreaks(TemplateElement te) { int count = te.getChildCount(); for (int i = 0; i < count; ++i) { TemplateElement child = (TemplateElement) te.getChildAt(i); while (child instanceof DebugBreak) { TemplateElement dbchild = (TemplateElement) child.getChildAt(0); te.setChildAt(i, dbchild); child = dbchild; } removeDebugBreaks(child); } }
/** Used for some backward compatibility hacks. */ TemplateElement asSingleElement() { if (count == 0) { return new TextBlock(CollectionUtils.EMPTY_CHAR_ARRAY, false); } else { TemplateElement first = buffer[0]; if (count == 1) { return first; } else { MixedContent mixedContent = new MixedContent(); mixedContent.setChildren(this); mixedContent.setLocation(first.getTemplate(), first, getLast()); return mixedContent; } } }
/** * @return an array of the {@link TemplateElement}s containing the given column and line numbers. */ List<TemplateElement> containingElements(int column, int line) { final ArrayList<TemplateElement> elements = new ArrayList<TemplateElement>(); TemplateElement element = rootElement; mainloop: while (element.contains(column, line)) { elements.add(element); for (Enumeration enumeration = element.children(); enumeration.hasMoreElements(); ) { TemplateElement elem = (TemplateElement) enumeration.nextElement(); if (elem.contains(column, line)) { element = elem; continue mainloop; } } break; } return elements.isEmpty() ? null : elements; }
public int getChildCount() { if (nestedBlock instanceof MixedContent) { return nestedBlock.getChildCount(); } if (nestedBlock != null) { return 1; } return regulatedChildCount; }
private void removeDebugBreak(Template t, Breakpoint breakpoint) { TemplateElement te = findTemplateElement(t.getRootTreeNode(), breakpoint.getLine()); if (te == null) { return; } DebugBreak db = null; while (te != null) { if (te instanceof DebugBreak) { db = (DebugBreak) te; break; } te = (TemplateElement) te.getParent(); } if (db == null) { return; } TemplateElement parent = (TemplateElement) db.getParent(); parent.setChildAt(parent.getIndex(db), (TemplateElement) db.getChildAt(0)); }
public void setChildAt(int index, TemplateElement element) { if (nestedBlock instanceof MixedContent) { nestedBlock.setChildAt(index, element); } else if (nestedBlock != null) { if (index == 0) { nestedBlock = element; element.index = 0; element.parent = this; } else { throw new IndexOutOfBoundsException("invalid index"); } } else if (regulatedChildBuffer != null) { regulatedChildBuffer[index] = element; element.index = index; element.parent = this; } else { throw new IndexOutOfBoundsException("element has no children"); } }
/** * Note: For element with {@code #nestedBlock}, this will hide the {@code #nestedBlock} when * that's a {@link MixedContent}. */ public Enumeration children() { if (nestedBlock instanceof MixedContent) { return nestedBlock.children(); } if (nestedBlock != null) { return Collections.enumeration(Collections.singletonList(nestedBlock)); } else if (regulatedChildBuffer != null) { return new _ArrayEnumeration(regulatedChildBuffer, regulatedChildCount); } return Collections.enumeration(Collections.EMPTY_LIST); }
/** * @return an array of the {@link TemplateElement}s containing the given column and line numbers. * @deprecated Should only be used internally, and might will be removed later. */ public TreePath containingElements(int column, int line) { final ArrayList elements = new ArrayList(); TemplateElement element = rootElement; mainloop: while (element.contains(column, line)) { elements.add(element); for (Enumeration enumeration = element.children(); enumeration.hasMoreElements(); ) { TemplateElement elem = (TemplateElement) enumeration.nextElement(); if (elem.contains(column, line)) { element = elem; continue mainloop; } } break; } if (elements.isEmpty()) { return null; } return new TreePath(elements.toArray()); }
final void addRegulatedChild(int index, TemplateElement nestedElement) { final int lRegulatedChildCount = regulatedChildCount; TemplateElement[] lRegulatedChildBuffer = regulatedChildBuffer; if (lRegulatedChildBuffer == null) { lRegulatedChildBuffer = new TemplateElement[INITIAL_REGULATED_CHILD_BUFFER_CAPACITY]; regulatedChildBuffer = lRegulatedChildBuffer; } else if (lRegulatedChildCount == lRegulatedChildBuffer.length) { setRegulatedChildBufferCapacity(lRegulatedChildCount != 0 ? lRegulatedChildCount * 2 : 1); lRegulatedChildBuffer = regulatedChildBuffer; } // At this point: nestedElements == this.nestedElements, and has sufficient capacity. for (int i = lRegulatedChildCount; i > index; i--) { TemplateElement movedElement = lRegulatedChildBuffer[i - 1]; movedElement.index = i; lRegulatedChildBuffer[i] = movedElement; } nestedElement.index = index; nestedElement.parent = this; lRegulatedChildBuffer[index] = nestedElement; regulatedChildCount = lRegulatedChildCount + 1; }
public int getIndex(TemplateElement node) { if (nestedBlock instanceof MixedContent) { return nestedBlock.getIndex(node); } if (nestedBlock != null) { if (node == nestedBlock) { return 0; } } else { for (int i = 0; i < regulatedChildCount; i++) { if (regulatedChildBuffer[i].equals(node)) { return i; } } } return -1; }
private static TemplateElement findTemplateElement(TemplateElement te, int line) { if (te.getBeginLine() > line || te.getEndLine() < line) { return null; } // Find the narrowest match List childMatches = new ArrayList(); for (Enumeration children = te.children(); children.hasMoreElements(); ) { TemplateElement child = (TemplateElement) children.nextElement(); TemplateElement childmatch = findTemplateElement(child, line); if (childmatch != null) { childMatches.add(childmatch); } } // find a match that exactly matches the begin/end line TemplateElement bestMatch = null; for (int i = 0; i < childMatches.size(); i++) { TemplateElement e = (TemplateElement) childMatches.get(i); if (bestMatch == null) { bestMatch = e; } if (e.getBeginLine() == line && e.getEndLine() > line) { bestMatch = e; } if (e.getBeginLine() == e.getEndLine() && e.getBeginLine() == line) { bestMatch = e; break; } } if (bestMatch != null) { return bestMatch; } // If no child provides narrower match, return this return te; }
public TemplateElement getChildAt(int index) { if (nestedBlock instanceof MixedContent) { return nestedBlock.getChildAt(index); } if (nestedBlock != null) { if (index == 0) { return nestedBlock; } throw new ArrayIndexOutOfBoundsException("invalid index"); } else if (regulatedChildCount != 0) { try { return regulatedChildBuffer[index]; } catch (ArrayIndexOutOfBoundsException e) { // nestedElements was a List earlier, so we emulate the same kind of exception throw new IndexOutOfBoundsException("Index: " + index + ", Size: " + regulatedChildCount); } } throw new ArrayIndexOutOfBoundsException("Template element has no children"); }
/** Dump the raw template in canonical form. */ public void dump(PrintStream ps) { ps.print(rootElement.getCanonicalForm()); }
/** Dump the raw template in canonical form. */ public void dump(Writer out) throws IOException { out.write(rootElement.getCanonicalForm()); }
/** * Walk the AST subtree rooted by this element, and do simplifications where possible, also remove * superfluous whitespace. * * @param stripWhitespace whether to remove superfluous whitespace * @return The element this element should be replaced with in the parent. If it's the same as * this element, no actual replacement will happen. Note that adjusting the {@link #parent} * and {@link #index} of the result is the duty of the caller, not of this method. */ TemplateElement postParseCleanup(boolean stripWhitespace) throws ParseException { int regulatedChildCount = this.regulatedChildCount; if (regulatedChildCount != 0) { for (int i = 0; i < regulatedChildCount; i++) { TemplateElement te = regulatedChildBuffer[i]; te = te.postParseCleanup(stripWhitespace); regulatedChildBuffer[i] = te; te.parent = this; te.index = i; } if (stripWhitespace) { for (int i = 0; i < regulatedChildCount; i++) { TemplateElement te = regulatedChildBuffer[i]; if (te.isIgnorable()) { regulatedChildCount--; for (int j = i; j < regulatedChildCount; j++) { final TemplateElement te2 = regulatedChildBuffer[j + 1]; regulatedChildBuffer[j] = te2; te2.index = j; } regulatedChildBuffer[regulatedChildCount] = null; this.regulatedChildCount = regulatedChildCount; i--; } } } if (regulatedChildCount < regulatedChildBuffer.length && regulatedChildCount <= regulatedChildBuffer.length * 3 / 4) { TemplateElement[] trimmedregulatedChildBuffer = new TemplateElement[regulatedChildCount]; for (int i = 0; i < regulatedChildCount; i++) { trimmedregulatedChildBuffer[i] = regulatedChildBuffer[i]; } regulatedChildBuffer = trimmedregulatedChildBuffer; } } else if (nestedBlock != null) { nestedBlock = nestedBlock.postParseCleanup(stripWhitespace); if (nestedBlock.isIgnorable()) { nestedBlock = null; } else { nestedBlock.parent = this; } } return this; }