| /* |
| * 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; |
| } |
| } |