Copyright (c) 2000, 2014 IBM Corporation and others. This program and the accompanying materials are made available under the terms of the Eclipse Public License 2.0 which accompanies this distribution, and is available at https://www.eclipse.org/legal/epl-2.0/ SPDX-License-Identifier: EPL-2.0 Contributors: IBM Corporation - initial API and implementation
/******************************************************************************* * Copyright (c) 2000, 2014 IBM Corporation and others. * * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 * which accompanies this distribution, and is available at * https://www.eclipse.org/legal/epl-2.0/ * * SPDX-License-Identifier: EPL-2.0 * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/
package org.eclipse.jdt.core.dom; import java.util.ArrayList; import java.util.List;
Type node for an array type.

In JLS8 and later, array types are represented by a base element type (which cannot be an array type) and a list of dimensions, each of which may have a list of annotations.

ArrayType: 
   Type Dimension { Dimension }
In JLS4 and before, array types were expressed in a recursive manner, one dimension at a time:
ArrayType:
   Type [ ]
This structure became untenable with the advent of type-use annotations, because in the language model, the base type binds with array dimensions from right to left, whereas a recursive structure binds from left to right (inside out).

Example:
int @A[] @B[] @C[] is an @A-array of
int      @B[] @C[], but such a component type is not representable by nested ArrayTypes with contiguous source ranges.

Since:2.0
@noinstantiateThis class is not intended to be instantiated by clients.
/** * Type node for an array type. * <p> * In JLS8 and later, array types are represented by a base element type (which cannot * be an array type) and a list of dimensions, each of which may have a list of annotations. * </p> * <pre> * ArrayType: * Type Dimension <b>{</b> Dimension <b>}</b> * </pre> * * In JLS4 and before, array types were expressed in a recursive manner, one dimension at a time: * <pre> * ArrayType: * Type <b>[</b> <b>]</b></pre> * * This structure became untenable with the advent of type-use annotations, * because in the language model, the base type binds with array dimensions from right to left, * whereas a recursive structure binds from left to right (inside out). * <p> * Example:<br> * <code><u>int @A[] @B[] @C[]</u></code> * is an <u><code>@A</code></u>-array of<br> * <code><u>int </u>&nbsp;&nbsp;&nbsp;&nbsp;<u> @B[] @C[]</u></code>, * but such a component type is not representable by nested <code>ArrayType</code>s with contiguous source ranges. * * @since 2.0 * @noinstantiate This class is not intended to be instantiated by clients. */
@SuppressWarnings({"rawtypes", "unchecked"}) public class ArrayType extends Type {
The "componentType" structural property of this node type (child type: Type).
Deprecated:In the JLS8 API, this property is replaced by ELEMENT_TYPE_PROPERTY and DIMENSIONS_PROPERTY.
Since:3.0
/** * The "componentType" structural property of this node type (child type: {@link Type}). * @deprecated In the JLS8 API, this property is replaced by {@link #ELEMENT_TYPE_PROPERTY} and {@link #DIMENSIONS_PROPERTY}. * @since 3.0 */
public static final ChildPropertyDescriptor COMPONENT_TYPE_PROPERTY = new ChildPropertyDescriptor(ArrayType.class, "componentType", Type.class, MANDATORY, CYCLE_RISK); //$NON-NLS-1$
The "elementType" structural property of this node type (child type: Type) (added in JLS8 API). Cannot be an array type.
Since:3.10
/** * The "elementType" structural property of this node type (child type: {@link Type}) (added in JLS8 API). * Cannot be an array type. * @since 3.10 */
public static final ChildPropertyDescriptor ELEMENT_TYPE_PROPERTY = new ChildPropertyDescriptor(ArrayType.class, "elementType", Type.class, MANDATORY, CYCLE_RISK); //$NON-NLS-1$
The "dimensions" structural property of this node type (element type: Dimension) (added in JLS8 API).
Since:3.10
/** * The "dimensions" structural property of this node type (element type: {@link Dimension}) (added in JLS8 API). * @since 3.10 */
public static final ChildListPropertyDescriptor DIMENSIONS_PROPERTY = new ChildListPropertyDescriptor(ArrayType.class, "dimensions", Dimension.class, CYCLE_RISK); //$NON-NLS-1$
A list of property descriptors (element type: StructuralPropertyDescriptor), or null if uninitialized.
/** * A list of property descriptors (element type: * {@link StructuralPropertyDescriptor}), * or null if uninitialized. */
private static final List PROPERTY_DESCRIPTORS;
A list of property descriptors (element type: StructuralPropertyDescriptor), or null if uninitialized.
Since:3.10
/** * A list of property descriptors (element type: * {@link StructuralPropertyDescriptor}), * or null if uninitialized. * @since 3.10 */
private static final List PROPERTY_DESCRIPTORS_8_0; static { List propertyList = new ArrayList(2); createPropertyList(ArrayType.class, propertyList); addProperty(COMPONENT_TYPE_PROPERTY, propertyList); PROPERTY_DESCRIPTORS = reapPropertyList(propertyList); propertyList = new ArrayList(3); createPropertyList(ArrayType.class, propertyList); addProperty(ELEMENT_TYPE_PROPERTY, propertyList); addProperty(DIMENSIONS_PROPERTY, propertyList); PROPERTY_DESCRIPTORS_8_0 = reapPropertyList(propertyList); }
Returns a list of structural property descriptors for this node type. Clients must not modify the result.
Params:
  • apiLevel – the API level; one of the AST.JLS* constants
Returns:a list of property descriptors (element type: StructuralPropertyDescriptor)
Since:3.0
/** * Returns a list of structural property descriptors for this node type. * Clients must not modify the result. * * @param apiLevel the API level; one of the * <code>AST.JLS*</code> constants * @return a list of property descriptors (element type: * {@link StructuralPropertyDescriptor}) * @since 3.0 */
public static List propertyDescriptors(int apiLevel) { switch (apiLevel) { case AST.JLS2_INTERNAL : case AST.JLS3_INTERNAL : case AST.JLS4_INTERNAL: return PROPERTY_DESCRIPTORS; default : return PROPERTY_DESCRIPTORS_8_0; } }
The element type (before JLS8: component type); lazily initialized; defaults to a simple type with an unspecified, but legal, name.
/** * The element type (before JLS8: component type); lazily initialized; defaults to a simple type with * an unspecified, but legal, name. */
private Type type = null;
List of dimensions this node has with optional annotations (element type: Dimension). Null before JLS8. Added in JLS8; defaults to a list with one element (see constructor).
Since:3.10
/** * List of dimensions this node has with optional annotations * (element type: {@link Dimension}). * Null before JLS8. Added in JLS8; defaults to a list with one element * (see constructor). * * @since 3.10 */
private ASTNode.NodeList dimensions = null;
Creates a new unparented node for an array type owned by the given AST. By default, a 1-dimensional array of an unspecified simple type.

N.B. This constructor is package-private.

Params:
  • ast – the AST that is to own this node
/** * Creates a new unparented node for an array type owned by the given AST. * By default, a 1-dimensional array of an unspecified simple type. * <p> * N.B. This constructor is package-private. * </p> * * @param ast the AST that is to own this node */
ArrayType(AST ast) { super(ast); if (ast.apiLevel >= AST.JLS8_INTERNAL) { this.dimensions = new ASTNode.NodeList(DIMENSIONS_PROPERTY); // single dimension array is the default this.dimensions().add(this.ast.newDimension()); } }
Creates a new unparented node for an array type owned by the given AST.

N.B. This constructor is package-private.

Params:
  • ast – the AST that is to own this node
  • dimensions – no of dimensions - can be zero
Since:3.10
/** * Creates a new unparented node for an array type owned by the given AST. * <p> * N.B. This constructor is package-private. * </p> * * @param ast the AST that is to own this node * @param dimensions no of dimensions - can be zero * * @since 3.10 */
ArrayType(AST ast, int dimensions) { super(ast); unsupportedIn2_3_4(); this.dimensions = new ASTNode.NodeList(DIMENSIONS_PROPERTY); for (int i = 0; i < dimensions; ++i) { this.dimensions().add(this.ast.newDimension()); } } @Override final List internalStructuralPropertiesForType(int apiLevel) { return propertyDescriptors(apiLevel); } @Override final List internalGetChildListProperty(ChildListPropertyDescriptor property) { if (property == DIMENSIONS_PROPERTY) { return dimensions(); } // allow default implementation to flag the error return super.internalGetChildListProperty(property); } @Override final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) { if (property == COMPONENT_TYPE_PROPERTY) { if (get) { return getComponentType(); } else { setComponentType((Type) child); return null; } } else if (property == ELEMENT_TYPE_PROPERTY) { if (get) { return getElementType(); } else { setElementType((Type) child); return null; } } // allow default implementation to flag the error return super.internalGetSetChildProperty(property, get, child); } @Override final int getNodeType0() { return ARRAY_TYPE; } @Override ASTNode clone0(AST target) { ArrayType result; if (this.ast.apiLevel < AST.JLS8_INTERNAL) { result = new ArrayType(target); result.setComponentType((Type) getComponentType().clone(target)); } else { result = new ArrayType(target, 0); result.setElementType((Type) getElementType().clone(target)); result.dimensions().addAll( ASTNode.copySubtrees(target, dimensions())); } result.setSourceRange(getStartPosition(), getLength()); return result; } @Override final boolean subtreeMatch0(ASTMatcher matcher, Object other) { // dispatch to correct overloaded match method return matcher.match(this, other); } @Override void accept0(ASTVisitor visitor) { boolean visitChildren = visitor.visit(this); if (visitChildren) { // visit children in normal left to right reading order if (this.ast.apiLevel < AST.JLS8_INTERNAL) { acceptChild(visitor, getComponentType()); } else { acceptChild(visitor, getElementType()); acceptChildren(visitor, this.dimensions); } } visitor.endVisit(this); }
Returns the component type of this array type. The component type may be another array type.
Throws:
See Also:
Returns:the component type node
Deprecated:In the JLS8 API, the recursive structure is not valid.
/** * Returns the component type of this array type. The component type * may be another array type. * * @return the component type node * @exception UnsupportedOperationException if this operation is used in * an AST later than JLS4 * @see #dimensions() * @deprecated In the JLS8 API, the recursive structure is not valid. */
public Type getComponentType() { supportedOnlyIn2_3_4(); return internalGetType(COMPONENT_TYPE_PROPERTY); } private Type internalGetType(ChildPropertyDescriptor property) { if (this.type == null) { // lazy init must be thread-safe for readers synchronized (this) { if (this.type == null) { preLazyInit(); this.type = new SimpleType(this.ast); postLazyInit(this.type, property); } } } return this.type; }
Sets the component type of this array type. The component type may be another array type.
Params:
  • componentType – the component type
Throws:
Deprecated:In the JLS8 API, the recursive structure is not valid.
/** * Sets the component type of this array type. The component type * may be another array type. * * @param componentType the component type * @exception IllegalArgumentException if: * <ul> * <li>the node belongs to a different AST</li> * <li>the node already has a parent</li> * <li>a cycle in would be created</li> * </ul> * @exception UnsupportedOperationException if this operation is used in * an AST later than JLS4 * @deprecated In the JLS8 API, the recursive structure is not valid. */
public void setComponentType(Type componentType) { supportedOnlyIn2_3_4(); if (componentType == null) { throw new IllegalArgumentException(); } internalSetType(componentType, COMPONENT_TYPE_PROPERTY); } private void internalSetType(Type componentType, ChildPropertyDescriptor property) { ASTNode oldChild = this.type; preReplaceChild(oldChild, componentType, property); this.type = componentType; postReplaceChild(oldChild, componentType, property); }
Returns the element type of this array type. The element type is never an array type.

In JLS4 and earlier, this is a convenience method that descends a chain of nested array types until it reaches a non-array type.

Returns:the element type node
/** * Returns the element type of this array type. The element type is * never an array type. * <p> * In JLS4 and earlier, this is a convenience method that descends a chain of nested array types * until it reaches a non-array type. * </p> * * @return the element type node */
public Type getElementType() { if (this.ast.apiLevel() < AST.JLS8_INTERNAL) { Type t = getComponentType(); while (t.isArrayType()) { t = ((ArrayType) t).getComponentType(); } return t; } return internalGetType(ELEMENT_TYPE_PROPERTY); }
Sets the element type of the array.
Params:
  • type – the new type
Throws:
Since:3.10
/** * Sets the element type of the array. * * @param type the new type * @exception IllegalArgumentException if: * <ul> * <li>the node belongs to a different AST</li> * <li>the node already has a parent</li> * <li>the node is an array type</li> * </ul> * @exception UnsupportedOperationException if this operation is used below JLS8 * @since 3.10 */
public void setElementType(Type type) { unsupportedIn2_3_4(); if (type == null || type instanceof ArrayType) { throw new IllegalArgumentException(); } internalSetType(type, ELEMENT_TYPE_PROPERTY); }
Returns the number of dimensions in this array type.

In JLS8 and later, this is a convenience method that returns dimensions().size().

In JLS4 and earlier, this is a convenience method that descends a chain of nested array types until it reaches a non-array type.

Returns:the number of dimensions (always positive)
/** * Returns the number of dimensions in this array type. * <p> * In JLS8 and later, this is a convenience method that returns <code>dimensions().size()</code>. * </p> * <p> * In JLS4 and earlier, this is a convenience method that descends a chain of nested array types * until it reaches a non-array type. * </p> * * @return the number of dimensions (always positive) */
public int getDimensions() { if (this.ast.apiLevel() >= AST.JLS8_INTERNAL) { return dimensions().size(); } Type t = getComponentType(); int dimension = 1; // always include this array type while (t.isArrayType()) { dimension++; t = ((ArrayType) t).getComponentType(); } return dimension; }
Returns the live ordered list of dimensions with optional annotations (added in JLS8 API).

For the array type to be plausible, the list should contain at least one element.

Throws:
Returns:the live list of dimensions with optional annotations (element type: Dimension)
Since:3.10
/** * Returns the live ordered list of dimensions with optional annotations (added in JLS8 API). * <p> * For the array type to be plausible, the list should contain at least one element. * </p> * * @return the live list of dimensions with optional annotations (element type: {@link Dimension}) * @exception UnsupportedOperationException if this operation is used below JLS8 * @since 3.10 */
public List dimensions() { // more efficient than just calling unsupportedIn2_3_4() to check if (this.dimensions == null) { unsupportedIn2_3_4(); } return this.dimensions; } @Override int memSize() { return BASE_NODE_SIZE + 2 * 4; } @Override int treeSize() { return memSize() + (this.type == null ? 0 : (this.ast.apiLevel() < AST.JLS8_INTERNAL ? getComponentType().treeSize() : getElementType().treeSize()) + (this.dimensions == null ? 0 : this.dimensions.listSize())); } }