1 /*******************************************************************************
2 * Copyright (c) 2003, 2008 IBM Corporation and others.
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Eclipse Public License v1.0
5 * which accompanies this distribution, and is available at
6 * http://www.eclipse.org/legal/epl-v10.html
9 * IBM Corporation - initial API and implementation
10 *******************************************************************************/
12 package net.sourceforge.phpdt.core.dom;
14 import java.util.ArrayList;
15 import java.util.List;
18 * Type node for a wildcard type (added in JLS3 API).
21 * <b>?</b> [ ( <b>extends</b> | <b>super</b>) Type ]
24 * Not all node arrangements will represent legal Java constructs. In particular,
25 * it is nonsense if a wildcard type node appears anywhere other than as an
26 * argument of a <code>ParameterizedType</code> node.
30 * @noinstantiate This class is not intended to be instantiated by clients.
32 public class WildcardType extends Type {
35 * The "bound" structural property of this node type.
37 public static final ChildPropertyDescriptor BOUND_PROPERTY =
38 new ChildPropertyDescriptor(WildcardType.class, "bound", Type.class, OPTIONAL, CYCLE_RISK); //$NON-NLS-1$
41 * The "upperBound" structural property of this node type.
43 public static final SimplePropertyDescriptor UPPER_BOUND_PROPERTY =
44 new SimplePropertyDescriptor(WildcardType.class, "upperBound", boolean.class, MANDATORY); //$NON-NLS-1$
47 * A list of property descriptors (element type:
48 * {@link StructuralPropertyDescriptor}),
49 * or null if uninitialized.
51 private static final List PROPERTY_DESCRIPTORS;
54 List propertyList = new ArrayList(3);
55 createPropertyList(WildcardType.class, propertyList);
56 addProperty(BOUND_PROPERTY, propertyList);
57 addProperty(UPPER_BOUND_PROPERTY, propertyList);
58 PROPERTY_DESCRIPTORS = reapPropertyList(propertyList);
62 * Returns a list of structural property descriptors for this node type.
63 * Clients must not modify the result.
65 * @param apiLevel the API level; one of the
66 * <code>AST.JLS*</code> constants
68 * @return a list of property descriptors (element type:
69 * {@link StructuralPropertyDescriptor})
71 public static List propertyDescriptors(int apiLevel) {
72 return PROPERTY_DESCRIPTORS;
76 * The optional type bound node; <code>null</code> if none;
79 private Type optionalBound = null;
82 * Indicates whether the wildcard bound is an upper bound
83 * ("extends") as opposed to a lower bound ("super").
84 * Defaults to <code>true</code> initially.
86 private boolean isUpperBound = true;
89 * Creates a new unparented node for a wildcard type owned by the
90 * given AST. By default, no upper bound.
92 * N.B. This constructor is package-private.
95 * @param ast the AST that is to own this node
97 WildcardType(AST ast) {
102 /* (omit javadoc for this method)
103 * Method declared on ASTNode.
105 final List internalStructuralPropertiesForType(int apiLevel) {
106 return propertyDescriptors(apiLevel);
109 /* (omit javadoc for this method)
110 * Method declared on ASTNode.
112 final boolean internalGetSetBooleanProperty(SimplePropertyDescriptor property, boolean get, boolean value) {
113 if (property == UPPER_BOUND_PROPERTY) {
115 return isUpperBound();
117 setUpperBound(value);
121 // allow default implementation to flag the error
122 return super.internalGetSetBooleanProperty(property, get, value);
125 /* (omit javadoc for this method)
126 * Method declared on ASTNode.
128 final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) {
129 if (property == BOUND_PROPERTY) {
133 setBound((Type) child);
137 // allow default implementation to flag the error
138 return super.internalGetSetChildProperty(property, get, child);
141 /* (omit javadoc for this method)
142 * Method declared on ASTNode.
144 final int getNodeType0() {
145 return WILDCARD_TYPE;
148 /* (omit javadoc for this method)
149 * Method declared on ASTNode.
151 ASTNode clone0(AST target) {
152 WildcardType result = new WildcardType(target);
153 result.setSourceRange(this.getStartPosition(), this.getLength());
154 result.setBound((Type) ASTNode.copySubtree(target, getBound()), isUpperBound());
158 /* (omit javadoc for this method)
159 * Method declared on ASTNode.
161 final boolean subtreeMatch0(ASTMatcher matcher, Object other) {
162 // dispatch to correct overloaded match method
163 return matcher.match(this, other);
166 /* (omit javadoc for this method)
167 * Method declared on ASTNode.
169 void accept0(ASTVisitor visitor) {
170 boolean visitChildren = visitor.visit(this);
172 // visit children in normal left to right reading order
173 acceptChild(visitor, getBound());
175 visitor.endVisit(this);
179 * Returns whether this wildcard type is an upper bound
180 * ("extends") as opposed to a lower bound ("super").
182 * Note that this property is irrelevant for wildcards
183 * that do not have a bound.
186 * @return <code>true</code> if an upper bound,
187 * and <code>false</code> if a lower bound
188 * @see #setBound(Type)
190 public boolean isUpperBound() {
191 return this.isUpperBound;
195 * Returns the bound of this wildcard type if it has one.
196 * If {@link #isUpperBound isUpperBound} returns true, this
197 * is an upper bound ("? extends B"); if it returns false, this
198 * is a lower bound ("? super B").
200 * @return the bound of this wildcard type, or <code>null</code>
202 * @see #setBound(Type)
204 public Type getBound() {
205 return this.optionalBound;
209 * Sets the bound of this wildcard type to the given type and
210 * marks it as an upper or a lower bound. The method is
211 * equivalent to calling <code>setBound(type); setUpperBound(isUpperBound)</code>.
213 * @param type the new bound of this wildcard type, or <code>null</code>
215 * @param isUpperBound <code>true</code> for an upper bound ("? extends B"),
216 * and <code>false</code> for a lower bound ("? super B")
217 * @exception IllegalArgumentException if:
219 * <li>the node belongs to a different AST</li>
220 * <li>the node already has a parent</li>
223 * @see #isUpperBound()
225 public void setBound(Type type, boolean isUpperBound) {
227 setUpperBound(isUpperBound);
231 * Sets the bound of this wildcard type to the given type.
233 * @param type the new bound of this wildcard type, or <code>null</code>
235 * @exception IllegalArgumentException if:
237 * <li>the node belongs to a different AST</li>
238 * <li>the node already has a parent</li>
242 public void setBound(Type type) {
243 ASTNode oldChild = this.optionalBound;
244 preReplaceChild(oldChild, type, BOUND_PROPERTY);
245 this.optionalBound = type;
246 postReplaceChild(oldChild, type, BOUND_PROPERTY);
250 * Sets whether this wildcard type is an upper bound
251 * ("extends") as opposed to a lower bound ("super").
253 * @param isUpperBound <code>true</code> if an upper bound,
254 * and <code>false</code> if a lower bound
255 * @see #isUpperBound()
257 public void setUpperBound(boolean isUpperBound) {
258 preValueChange(UPPER_BOUND_PROPERTY);
259 this.isUpperBound = isUpperBound;
260 postValueChange(UPPER_BOUND_PROPERTY);
263 /* (omit javadoc for this method)
264 * Method declared on ASTNode.
267 return BASE_NODE_SIZE + 2 * 4;
270 /* (omit javadoc for this method)
271 * Method declared on ASTNode.
276 + (this.optionalBound == null ? 0 : getBound().treeSize());