/** * Replace a node with the contents of a list. * * <p>Technically this will always work, but it really only makes sense if the replaced node is an * element of a list to begin with. */ public static void replaceWithContents(ASTNode<?> node, ast.List<?> source) { ASTNode<?> parent = node.getParent(); int index = parent.getIndexOfChild(node); node.getParent().removeChild(index); for (Object element : source) { parent.insertChild((ASTNode<?>) element, index++); } }
private DrawingTree layoutBinary(String name, ASTNode child1, ASTNode child2) { DrawingTree dt = layoutCaption(name); DrawingTree d1 = (DrawingTree) child1.accept(this); DrawingTree d2 = (DrawingTree) child2.accept(this); dt.setChildren(new DrawingTree[] {d1, d2}); attachParent(dt, join(dt)); return dt; }
/** * Pretty-prints the AST to source code. * * @return Pretty-printed AST (source code) */ public final String prettyPrint() { assert (astnode != null); rebuildAST(); astnode.flushCaches(); if (LOG.isDebugEnabled()) { System.out.println(dumpTree()); } return astnode.prettyPrint(); }
/* * (non-Javadoc) * * @see de.fosd.jdime.common.Artifact#initializeChildren() */ @Override public final void initializeChildren() { assert (astnode != null); ArtifactList<ASTNodeArtifact> children = new ArtifactList<>(); for (int i = 0; i < astnode.getNumChildNoTransform(); i++) { ASTNodeArtifact child = new ASTNodeArtifact(astnode.getChild(i)); child.setParent(this); child.setRevision(getRevision()); children.add(child); } setChildren(children); }
private DrawingTree layoutQuintenary( String name, ASTNode child1, ASTNode child2, ASTNode child3, ASTNode child4, ASTNode child5) { DrawingTree dt = layoutCaption(name); DrawingTree d1 = (DrawingTree) child1.accept(this); DrawingTree d2 = (DrawingTree) child2.accept(this); DrawingTree d3 = (DrawingTree) child3.accept(this); DrawingTree d4 = (DrawingTree) child4.accept(this); DrawingTree d5 = (DrawingTree) child5.accept(this); dt.setChildren(new DrawingTree[] {d1, d2, d3, d4, d5}); attachParent(dt, join(dt)); return dt; }
private DrawingTree layoutNary(String name, ListNode childNodes) { if (childNodes.getSize() == 0) return layoutNullary("Empty" + name); DrawingTree dt = layoutCaption(name); DrawingTree[] childTrees = new DrawingTree[childNodes.getSize()]; int i = 0; for (ASTNode childNode : childNodes) { childTrees[i] = (DrawingTree) childNode.accept(this); i++; } dt.setChildren(childTrees); attachParent(dt, join(dt)); return dt; }
/** Rebuild the encapsulated ASTNode tree top down. This should be only called at the root node */ public final void rebuildAST() { if (isConflict()) { astnode.isConflict = true; astnode.jdimeId = getId(); if (left != null) { left.rebuildAST(); astnode.left = left.astnode; } if (right != null) { right.rebuildAST(); astnode.right = right.astnode; } } ASTNode<?>[] newchildren = new ASTNode[getNumChildren()]; for (int i = 0; i < getNumChildren(); i++) { ASTNodeArtifact child = getChild(i); newchildren[i] = child.astnode; newchildren[i].setParent(astnode); child.rebuildAST(); } astnode.jdimeChanges = hasChanges(); astnode.jdimeId = getId(); astnode.setChildren(newchildren); assert (isConflict() || getNumChildren() == astnode.getNumChildNoTransform()); }
@Override public final int compareTo(final ASTNodeArtifact o) { if (hasUniqueLabels()) { return astnode.dumpString().compareTo(o.astnode.dumpString()); } else { throw new RuntimeException("This artifact is not comparable."); } }
/** * Returns whether a node matches another node. * * @param other node to compare with. * @return true if the node matches another node. */ @Override public final boolean matches(final ASTNodeArtifact other) { assert (astnode != null); assert (other != null); assert (other.astnode != null); if (LOG.isDebugEnabled()) { LOG.debug("match(" + getId() + ", " + other.getId() + ")"); } if ((ImportDecl.class.isAssignableFrom(astnode.getClass()) || Literal.class.isAssignableFrom(astnode.getClass())) && other.astnode.getClass().equals(astnode.getClass())) { if (LOG.isDebugEnabled()) { LOG.debug( "Try Matching (prettyPrint): {" + astnode.prettyPrint() + "} and {" + other.astnode.prettyPrint() + "}"); } return astnode.prettyPrint().equals(other.astnode.prettyPrint()); } if (LOG.isDebugEnabled()) { LOG.debug( "Try Matching (dumpString): {" + astnode.dumpString() + "} and {" + other.astnode.dumpString() + "}"); } return astnode.dumpString().equals(other.astnode.dumpString()); }
/** * Returns whether declaration order is significant for this node. * * @return whether declaration order is significant for this node */ @Override public final boolean isOrdered() { return !ConstructorDecl.class.isAssignableFrom(astnode.getClass()) && !MethodDecl.class.isAssignableFrom(astnode.getClass()) && !InterfaceDecl.class.isAssignableFrom(astnode.getClass()) && !FieldDecl.class.isAssignableFrom(astnode.getClass()) && !FieldDeclaration.class.isAssignableFrom(astnode.getClass()) && !ImportDecl.class.isAssignableFrom(astnode.getClass()); }
// This is the default node case. We recurse on the children from left to right, // so we're traversing the AST depth-first. @Override public void caseASTNode(ASTNode node) { for (int i = 0; i < node.getNumChild(); ++i) { node.getChild(i).analyze(this); } }
public static void instrument(ASTNode<?> node) { node.analyze(new ProfileAssignments()); }
/** * Returns the AST in dot-format. * * @param includeNumbers include node number in label if true * @return AST in dot-format. */ public final String dumpGraphvizTree(final boolean includeNumbers, int virtualcount) { assert (astnode != null); StringBuilder sb = new StringBuilder(); if (isConflict()) { // insert virtual node String conflictId = "\"c" + virtualcount + "\""; sb.append(conflictId); sb.append("[label=\"Conflict\", fillcolor = red, style = filled]") .append(System.lineSeparator()); // left alternative sb.append(left.dumpGraphvizTree(includeNumbers, virtualcount)); sb.append(conflictId) .append("->") .append(getGraphvizId(left)) .append("[label=\"") .append(left.getRevision()) .append("\"]") .append(";") .append(System.lineSeparator()); // right alternative sb.append(right.dumpGraphvizTree(includeNumbers, virtualcount)); sb.append(conflictId) .append("->") .append(getGraphvizId(right)) .append("[label=\"") .append(right.getRevision()) .append("\"]") .append(";") .append(System.lineSeparator()); } else { sb.append(getGraphvizId(this)).append("[label=\""); // node label if (includeNumbers) { sb.append("(").append(getNumber()).append(") "); } sb.append(astnode.dumpString()); sb.append("\""); if (hasMatches()) { sb.append(", fillcolor = green, style = filled"); } sb.append("];"); sb.append(System.lineSeparator()); // children for (ASTNodeArtifact child : getChildren()) { String childId = getGraphvizId(child); if (child.isConflict()) { virtualcount++; childId = "\"c" + virtualcount + "\""; } sb.append(child.dumpGraphvizTree(includeNumbers, virtualcount)); // edge sb.append(getGraphvizId(this)) .append("->") .append(childId) .append(";") .append(System.lineSeparator()); } } return sb.toString(); }
/** Removes the given subtree, i.e. disconnects it from its parent. */ public static void remove(ASTNode<?> node) { node.getParent().removeChild(node.getParent().getIndexOfChild(node)); }
/** Replaces a subtree with another, correctly updating parent/child links. */ public static void replace(ASTNode<?> oldNode, ASTNode<?> newNode) { oldNode.getParent().setChild(newNode, oldNode.getParent().getIndexOfChild(oldNode)); newNode.setStartPosition(oldNode.getStartLine(), oldNode.getStartColumn()); newNode.setEndPosition(oldNode.getEndLine(), oldNode.getEndColumn()); }
/* * (non-Javadoc) * * @see de.fosd.jdime.common.Artifact#toString() */ @Override public final String toString() { assert (astnode != null); return astnode.dumpString(); }
/* * (non-Javadoc) * * @see de.fosd.jdime.common.Artifact#hashCode() */ @Override public final int hashCode() { return astnode.dumpString().hashCode(); }
@Override public final boolean hasUniqueLabels() { return ImportDecl.class.isAssignableFrom(astnode.getClass()) || Literal.class.isAssignableFrom(astnode.getClass()); }