blob: bb9ccf7252aade1c4351cf8d315e9957a089d764 [file] [log] [blame]
/*
* Copyright 2012, the Dart project authors.
*
* Licensed under the Eclipse Public License v1.0 (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at
*
* http://www.eclipse.org/legal/epl-v10.html
*
* Unless required by applicable law or agreed to in writing, software distributed under the License
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
* or implied. See the License for the specific language governing permissions and limitations under
* the License.
*/
package com.google.dart.engine.ast;
import com.google.dart.engine.scanner.Token;
import com.google.dart.engine.utilities.translation.DartOmit;
import java.util.AbstractList;
import java.util.Collection;
/**
* Instances of the class {@code NodeList} represent a list of AST nodes that have a common parent.
*
* @coverage dart.engine.ast
*/
@DartOmit
public class NodeList<E extends AstNode> extends AbstractList<E> {
/**
* Create an empty list with the given owner. This is a convenience method that allows the
* compiler to determine the correct value of the type argument {@link #E} without needing to
* explicitly specify it.
*
* @param owner the node that is the parent of each of the elements in the list
* @return the list that was created
*/
public static <E extends AstNode> NodeList<E> create(AstNode owner) {
return new NodeList<E>(owner);
}
/**
* The node that is the parent of each of the elements in the list.
*/
private final AstNode owner;
/**
* The elements contained in the list.
*/
private AstNode[] elements = AstNode.EMPTY_ARRAY;
/**
* Initialize a newly created list of nodes to be empty.
*
* @param owner the node that is the parent of each of the elements in the list
*/
public NodeList(AstNode owner) {
this.owner = owner;
}
/**
* Use the given visitor to visit each of the nodes in this list.
*
* @param visitor the visitor to be used to visit the elements of this list
*/
public void accept(AstVisitor<?> visitor) {
for (AstNode element : elements) {
element.accept(visitor);
}
}
@Override
public void add(int index, E node) {
int length = elements.length;
if (index < 0 || index > length) {
throw new IndexOutOfBoundsException("Index: " + index + ", Size: " + elements.length);
}
owner.becomeParentOf(node);
if (length == 0) {
elements = new AstNode[] {node};
} else {
AstNode[] newElements = new AstNode[length + 1];
System.arraycopy(elements, 0, newElements, 0, index);
newElements[index] = node;
System.arraycopy(elements, index, newElements, index + 1, length - index);
elements = newElements;
}
}
@Override
public boolean addAll(Collection<? extends E> nodes) {
if (nodes != null && !nodes.isEmpty()) {
int oldCount = elements.length;
int newCount = nodes.size();
AstNode[] newElements = new AstNode[oldCount + newCount];
System.arraycopy(elements, 0, newElements, 0, oldCount);
int index = oldCount;
for (E node : nodes) {
owner.becomeParentOf(node);
newElements[index++] = node;
}
elements = newElements;
return true;
}
return false;
}
@Override
@SuppressWarnings("unchecked")
public E get(int index) {
if (index < 0 || index >= elements.length) {
throw new IndexOutOfBoundsException("Index: " + index + ", Size: " + elements.length);
}
return (E) elements[index];
}
/**
* Return the first token included in this node's source range.
*
* @return the first token included in this node's source range
*/
public Token getBeginToken() {
if (elements.length == 0) {
return null;
}
return elements[0].getBeginToken();
}
/**
* Return the last token included in this node list's source range.
*
* @return the last token included in this node list's source range
*/
public Token getEndToken() {
if (elements.length == 0) {
return null;
}
return elements[elements.length - 1].getEndToken();
}
/**
* Return the node that is the parent of each of the elements in the list.
*
* @return the node that is the parent of each of the elements in the list
*/
public AstNode getOwner() {
return owner;
}
@Override
public int indexOf(Object o) {
for (int i = 0; i < elements.length; i++) {
if (elements[i] == o) {
return i;
}
}
return -1;
}
@Override
@SuppressWarnings("unchecked")
public E remove(int index) {
if (index < 0 || index >= elements.length) {
throw new IndexOutOfBoundsException("Index: " + index + ", Size: " + elements.length);
}
E removedNode = (E) elements[index];
int length = elements.length;
if (length == 1) {
elements = AstNode.EMPTY_ARRAY;
return removedNode;
}
AstNode[] newElements = new AstNode[length - 1];
System.arraycopy(elements, 0, newElements, 0, index);
System.arraycopy(elements, index + 1, newElements, index, length - index - 1);
elements = newElements;
return removedNode;
}
@Override
@SuppressWarnings("unchecked")
public E set(int index, E node) {
if (index < 0 || index >= elements.length) {
throw new IndexOutOfBoundsException("Index: " + index + ", Size: " + elements.length);
}
E replacedNode = (E) elements[index];
owner.becomeParentOf(node);
elements[index] = node;
return replacedNode;
}
@Override
public int size() {
return elements.length;
}
}