From 13e414c73d07148e7a0b9cbcbb09265769f2a4a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Fournier?= Date: Sun, 26 Apr 2020 18:28:47 +0200 Subject: [PATCH] Add insertChild --- .../pmd/lang/apex/ast/AbstractApexNode.java | 8 ++++ .../pmd/lang/apex/ast/ApexTreeBuilder.java | 21 +++------ .../pmd/lang/ast/impl/AbstractNode.java | 45 +++++++++++++++++-- 3 files changed, 56 insertions(+), 18 deletions(-) diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/AbstractApexNode.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/AbstractApexNode.java index 19424788e6..ca89400aa6 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/AbstractApexNode.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/AbstractApexNode.java @@ -22,6 +22,14 @@ abstract class AbstractApexNode extends AbstractNodeWithTextC this.node = node; } + protected void addChild(AbstractApexNode child, int index) { + super.addChild(child, index); + } + + protected void insertChild(AbstractApexNode child, int index) { + super.insertChild(child, index); + } + /* package */ void calculateLineNumbers(SourceCodePositioner positioner, int startOffset, int endOffset) { // end column will be interpreted as inclusive, while endOffset/endIndex // is exclusive diff --git a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ApexTreeBuilder.java b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ApexTreeBuilder.java index 013f3543dd..9229ad18bc 100644 --- a/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ApexTreeBuilder.java +++ b/pmd-apex/src/main/java/net/sourceforge/pmd/lang/apex/ast/ApexTreeBuilder.java @@ -16,7 +16,6 @@ import org.antlr.runtime.ANTLRStringStream; import org.antlr.runtime.Token; import net.sourceforge.pmd.lang.apex.ApexParserOptions; -import net.sourceforge.pmd.lang.ast.Node; import net.sourceforge.pmd.lang.ast.SourceCodePositioner; import apex.jorje.data.Location; @@ -283,8 +282,7 @@ final class ApexTreeBuilder extends AstVisitor { // Append to parent AbstractApexNode parent = nodes.isEmpty() ? null : nodes.peek(); if (parent != null) { - parent.jjtAddChild(node, parent.getNumChildren()); - node.setParent(parent); + parent.addChild(node, parent.getNumChildren()); } // Build the children... @@ -304,27 +302,20 @@ final class ApexTreeBuilder extends AstVisitor { private void addFormalComments() { for (ApexDocTokenLocation tokenLocation : apexDocTokenLocations) { - ApexNode parent = tokenLocation.nearestNode; + AbstractApexNode parent = tokenLocation.nearestNode; if (parent != null) { ASTFormalComment comment = new ASTFormalComment(tokenLocation.token); comment.calculateLineNumbers(sourceCodePositioner, tokenLocation.index, tokenLocation.index + tokenLocation.token.getText().length()); - // move existing nodes so that we can insert the comment as the first node - for (int i = parent.getNumChildren(); i > 0; i--) { - parent.jjtAddChild(parent.getChild(i - 1), i); - } - - parent.jjtAddChild(comment, 0); - comment.setParent(parent); + parent.insertChild(comment, 0); } } } private void buildFormalComment(AstNode node) { if (parents.peek() == node) { - ApexNode parent = (ApexNode) nodes.peek(); - assignApexDocTokenToNode(node, parent); + assignApexDocTokenToNode(node, nodes.peek()); } } @@ -337,7 +328,7 @@ final class ApexTreeBuilder extends AstVisitor { * @param jorjeNode the original node * @param node the potential parent node, to which the comment could belong */ - private void assignApexDocTokenToNode(AstNode jorjeNode, ApexNode node) { + private void assignApexDocTokenToNode(AstNode jorjeNode, AbstractApexNode node) { Location loc = jorjeNode.getLoc(); if (!Locations.isReal(loc)) { // Synthetic nodes such as "" don't have a location in the @@ -411,7 +402,7 @@ final class ApexTreeBuilder extends AstVisitor { private static class ApexDocTokenLocation { int index; Token token; - ApexNode nearestNode; + AbstractApexNode nearestNode; int nearestNodeDistance; ApexDocTokenLocation(int index, Token token) { diff --git a/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/impl/AbstractNode.java b/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/impl/AbstractNode.java index 32ddcd6891..339f230848 100644 --- a/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/impl/AbstractNode.java +++ b/pmd-core/src/main/java/net/sourceforge/pmd/lang/ast/impl/AbstractNode.java @@ -67,24 +67,63 @@ public abstract class AbstractNode> implements GenericN } /** - * This method tells the node to add its argument to the node's list of children. - * Note that it is more efficient to add children in reverse (from right to left), - * because the array is resized only once. + * Set the child at the given index to the given node. This resizes + * the children array to be able to contain the given index. Implementations + * must take care that this does not leave any "holes" in the array. + * This method throws if there is already a child at the given index. + * + *

Note that it is more efficient to add children in reverse + * (from right to left), because the array is resized only the + * first time. + * + *

This method also calls {@link #setParent(AbstractNode)}. * * @param child The child to add * @param index The index to which the child will be added */ protected void addChild(final AbstractNode child, final int index) { + assert index >= 0 : "Invalid index " + index; + assert index >= children.length || children[index] == null : "There is already a child at index " + index; + if (index >= children.length) { final Node[] newChildren = new Node[index + 1]; System.arraycopy(children, 0, newChildren, 0, children.length); children = newChildren; } + children[index] = child; child.setChildIndex(index); child.setParent(this); } + /** + * Insert a child at the given index, shifting all the following + * children to the right. + * + * @param child New child + * @param index Index (must be 0 <= index <= getNumChildren()), ie + * you can insert a node beyond the end, because that + * would leave holes in the array + */ + protected void insertChild(final AbstractNode child, final int index) { + assert index >= 0 && index <= children.length + : "Invalid index for insertion into array of length " + children.length + ": " + index; + + Node[] newChildren = new Node[index + 1]; + if (index != 0) { + System.arraycopy(children, 0, newChildren, 0, index); + } + if (index != children.length) { + System.arraycopy(children, index, newChildren, index + 1, children.length - index); + } + newChildren[index] = child; + child.setParent(this); + + for (int i = index; i < newChildren.length; i++) { + ((AbstractNode) newChildren[i]).setChildIndex(i); + } + this.children = newChildren; + } @SafeVarargs