df92ea218f3bbb3749c232e7041f0a1a30a8c4b0
[phpeclipse.git] / net.sourceforge.phpeclipse / src / net / sourceforge / phpdt / core / dom / ClassInstanceCreation.java
1 /*******************************************************************************
2  * Copyright (c) 2000, 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
7  *
8  * Contributors:
9  *     IBM Corporation - initial API and implementation
10  *******************************************************************************/
11
12 package net.sourceforge.phpdt.core.dom;
13
14 import java.util.ArrayList;
15 import java.util.List;
16
17 /**
18  * Class instance creation expression AST node type.
19  * For JLS2:
20  * <pre>
21  * ClassInstanceCreation:
22  *        [ Expression <b>.</b> ] <b>new</b> Name
23  *            <b>(</b> [ Expression { <b>,</b> Expression } ] <b>)</b>
24  *            [ AnonymousClassDeclaration ]
25  * </pre>
26  * For JLS3, type arguments are added
27  * and the type name is generalized to a type so that parameterized
28  * types can be instantiated:
29  * <pre>
30  * ClassInstanceCreation:
31  *        [ Expression <b>.</b> ]
32  *            <b>new</b> [ <b>&lt;</b> Type { <b>,</b> Type } <b>&gt;</b> ]
33  *            Type <b>(</b> [ Expression { <b>,</b> Expression } ] <b>)</b>
34  *            [ AnonymousClassDeclaration ]
35  * </pre>
36  * <p>
37  * Not all node arragements will represent legal Java constructs. In particular,
38  * it is nonsense if the type is a primitive type or an array type (primitive
39  * types cannot be instantiated, and array creations must be represented with
40  * <code>ArrayCreation</code> nodes). The normal use is when the type is a
41  * simple, qualified, or parameterized type.
42  * </p>
43  * <p>
44  * A type like "A.B" can be represented either of two ways:
45  * <ol>
46  * <li>
47  * <code>QualifiedType(SimpleType(SimpleName("A")),SimpleName("B"))</code>
48  * </li>
49  * <li>
50  * <code>SimpleType(QualifiedName(SimpleName("A"),SimpleName("B")))</code>
51  * </li>
52  * </ol>
53  * The first form is preferred when "A" is known to be a type (as opposed
54  * to a package). However, a parser cannot always determine this. Clients
55  * should be prepared to handle either rather than make assumptions.
56  * (Note also that the first form became possible as of JLS3; only the second
57  * form existed in JLS2.)
58  * </p>
59  * 
60  * @since 2.0
61  * @noinstantiate This class is not intended to be instantiated by clients.
62  */
63 public class ClassInstanceCreation extends Expression {
64
65         /**
66          * The "typeArguments" structural property of this node type (added in JLS3 API).
67          * @since 3.1
68          */
69         public static final ChildListPropertyDescriptor TYPE_ARGUMENTS_PROPERTY = 
70                 new ChildListPropertyDescriptor(ClassInstanceCreation.class, "typeArguments", Type.class, NO_CYCLE_RISK); //$NON-NLS-1$
71         
72         /**
73          * The "expression" structural property of this node type.
74          * @since 3.0
75          */
76         public static final ChildPropertyDescriptor EXPRESSION_PROPERTY = 
77                 new ChildPropertyDescriptor(ClassInstanceCreation.class, "expression", Expression.class, OPTIONAL, CYCLE_RISK); //$NON-NLS-1$
78
79         /**
80          * The "name" structural property of this node type (JLS2 API only).
81          * @since 3.0
82          */
83         public static final ChildPropertyDescriptor NAME_PROPERTY = 
84                 new ChildPropertyDescriptor(ClassInstanceCreation.class, "name", Name.class, MANDATORY, NO_CYCLE_RISK); //$NON-NLS-1$
85
86         /**
87          * The "type" structural property of this node type (added in JLS3 API).
88          * @since 3.1
89          */
90         public static final ChildPropertyDescriptor TYPE_PROPERTY = 
91                 new ChildPropertyDescriptor(ClassInstanceCreation.class, "type", Type.class, MANDATORY, NO_CYCLE_RISK); //$NON-NLS-1$
92
93         /**
94          * The "arguments" structural property of this node type.
95          * @since 3.0
96          */
97         public static final ChildListPropertyDescriptor ARGUMENTS_PROPERTY = 
98                 new ChildListPropertyDescriptor(ClassInstanceCreation.class, "arguments", Expression.class, CYCLE_RISK); //$NON-NLS-1$
99         
100         /**
101          * The "anonymousClassDeclaration" structural property of this node type.
102          * @since 3.0
103          */
104         public static final ChildPropertyDescriptor ANONYMOUS_CLASS_DECLARATION_PROPERTY = 
105                 new ChildPropertyDescriptor(ClassInstanceCreation.class, "anonymousClassDeclaration", AnonymousClassDeclaration.class, OPTIONAL, CYCLE_RISK); //$NON-NLS-1$
106         
107         /**
108          * A list of property descriptors (element type: 
109          * {@link StructuralPropertyDescriptor}),
110          * or null if uninitialized.
111          * @since 3.0
112          */
113         private static final List PROPERTY_DESCRIPTORS_2_0;
114         
115         /**
116          * A list of property descriptors (element type: 
117          * {@link StructuralPropertyDescriptor}),
118          * or null if uninitialized.
119          * @since 3.1
120          */
121         private static final List PROPERTY_DESCRIPTORS_3_0;
122         
123         static {
124                 List properyList = new ArrayList(5);
125                 createPropertyList(ClassInstanceCreation.class, properyList);
126                 addProperty(EXPRESSION_PROPERTY, properyList);
127                 addProperty(NAME_PROPERTY, properyList);
128                 addProperty(ARGUMENTS_PROPERTY, properyList);
129                 addProperty(ANONYMOUS_CLASS_DECLARATION_PROPERTY, properyList);
130                 PROPERTY_DESCRIPTORS_2_0 = reapPropertyList(properyList);
131                 
132                 properyList = new ArrayList(6);
133                 createPropertyList(ClassInstanceCreation.class, properyList);
134                 addProperty(EXPRESSION_PROPERTY, properyList);
135                 addProperty(TYPE_ARGUMENTS_PROPERTY, properyList);
136                 addProperty(TYPE_PROPERTY, properyList);
137                 addProperty(ARGUMENTS_PROPERTY, properyList);
138                 addProperty(ANONYMOUS_CLASS_DECLARATION_PROPERTY, properyList);
139                 PROPERTY_DESCRIPTORS_3_0 = reapPropertyList(properyList);
140         }
141
142         /**
143          * Returns a list of structural property descriptors for this node type.
144          * Clients must not modify the result.
145          * 
146          * @param apiLevel the API level; one of the
147          * <code>AST.JLS*</code> constants
148
149          * @return a list of property descriptors (element type: 
150          * {@link StructuralPropertyDescriptor})
151          * @since 3.0
152          */
153         public static List propertyDescriptors(int apiLevel) {
154                 if (apiLevel == AST.JLS2_INTERNAL) {
155                         return PROPERTY_DESCRIPTORS_2_0;
156                 } else {
157                         return PROPERTY_DESCRIPTORS_3_0;
158                 }
159         }
160                         
161         /**
162          * The optional expression; <code>null</code> for none; defaults to none.
163          */
164         private Expression optionalExpression = null;
165         
166         /**
167          * The type arguments (element type: <code>Type</code>). 
168          * Null in JLS2. Added in JLS3; defaults to an empty list
169          * (see constructor).
170          * @since 3.1
171          */
172         private ASTNode.NodeList typeArguments = null;
173
174         /**
175          * The type name; lazily initialized; defaults to a unspecified,
176          * legal type name. Not used in JLS3.
177          */
178         private Name typeName = null;
179         
180         /**
181          * The type; lazily initialized; defaults to a unspecified type.
182          * @since 3.0
183          */
184         private Type type = null;
185         
186         /**
187          * The list of argument expressions (element type: 
188          * <code>Expression</code>). Defaults to an empty list.
189          */
190         private ASTNode.NodeList arguments =
191                 new ASTNode.NodeList(ARGUMENTS_PROPERTY);
192                 
193         /**
194          * The optional anonymous class declaration; <code>null</code> for none; 
195          * defaults to none.
196          */
197         private AnonymousClassDeclaration optionalAnonymousClassDeclaration = null;
198         
199         /**
200          * Creates a new AST node for a class instance creation expression owned 
201          * by the given AST. By default, there is no qualifying expression,
202          * an empty list of type parameters, an unspecified type, an empty
203      * list of arguments, and does not declare an anonymous class.
204          * <p>
205          * N.B. This constructor is package-private; all subclasses must be 
206          * declared in the same package; clients are unable to declare 
207          * additional subclasses.
208          * </p>
209          * 
210          * @param ast the AST that is to own this node
211          */
212         ClassInstanceCreation (AST ast) {
213                 super(ast);
214                 if (ast.apiLevel >= AST.JLS3) {
215                         this.typeArguments = new ASTNode.NodeList(TYPE_ARGUMENTS_PROPERTY);
216                 }
217         }
218
219         /* (omit javadoc for this method)
220          * Method declared on ASTNode.
221          * @since 3.0
222          */
223         final List internalStructuralPropertiesForType(int apiLevel) {
224                 return propertyDescriptors(apiLevel);
225         }
226         
227
228         /* (omit javadoc for this method)
229          * Method declared on ASTNode.
230          */
231         final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) {
232                 if (property == EXPRESSION_PROPERTY) {
233                         if (get) {
234                                 return getExpression();
235                         } else {
236                                 setExpression((Expression) child);
237                                 return null;
238                         }
239                 }
240                 if (property == NAME_PROPERTY) {
241                         if (get) {
242                                 return getName();
243                         } else {
244                                 setName((Name) child);
245                                 return null;
246                         }
247                 }
248                 if (property == TYPE_PROPERTY) {
249                         if (get) {
250                                 return getType();
251                         } else {
252                                 setType((Type) child);
253                                 return null;
254                         }
255                 }
256                 if (property == ANONYMOUS_CLASS_DECLARATION_PROPERTY) {
257                         if (get) {
258                                 return getAnonymousClassDeclaration();
259                         } else {
260                                 setAnonymousClassDeclaration((AnonymousClassDeclaration) child);
261                                 return null;
262                         }
263                 }
264                 // allow default implementation to flag the error
265                 return super.internalGetSetChildProperty(property, get, child);
266         }
267         
268         /* (omit javadoc for this method)
269          * Method declared on ASTNode.
270          */
271         final List internalGetChildListProperty(ChildListPropertyDescriptor property) {
272                 if (property == ARGUMENTS_PROPERTY) {
273                         return arguments();
274                 }
275                 if (property == TYPE_ARGUMENTS_PROPERTY) {
276                         return typeArguments();
277                 }
278                 // allow default implementation to flag the error
279                 return super.internalGetChildListProperty(property);
280         }
281         
282         /* (omit javadoc for this method)
283          * Method declared on ASTNode.
284          */
285         final int getNodeType0() {
286                 return CLASS_INSTANCE_CREATION;
287         }
288
289         /* (omit javadoc for this method)
290          * Method declared on ASTNode.
291          */
292         ASTNode clone0(AST target) {
293                 ClassInstanceCreation result = new ClassInstanceCreation(target);
294                 result.setSourceRange(this.getStartPosition(), this.getLength());
295                 result.setExpression(
296                         (Expression) ASTNode.copySubtree(target, getExpression()));
297                 if (this.ast.apiLevel == AST.JLS2_INTERNAL) {
298                         result.setName((Name) getName().clone(target));
299                 }
300                 if (this.ast.apiLevel >= AST.JLS3) {
301                         result.typeArguments().addAll(ASTNode.copySubtrees(target, typeArguments()));
302                         result.setType((Type) getType().clone(target));
303                 }
304                 result.arguments().addAll(ASTNode.copySubtrees(target, arguments()));
305                 result.setAnonymousClassDeclaration(
306                         (AnonymousClassDeclaration) 
307                            ASTNode.copySubtree(target, getAnonymousClassDeclaration()));
308                 return result;
309         }
310
311         /* (omit javadoc for this method)
312          * Method declared on ASTNode.
313          */
314         final boolean subtreeMatch0(ASTMatcher matcher, Object other) {
315                 // dispatch to correct overloaded match method
316                 return matcher.match(this, other);
317         }
318
319         /* (omit javadoc for this method)
320          * Method declared on ASTNode.
321          */
322         void accept0(ASTVisitor visitor) {
323                 boolean visitChildren = visitor.visit(this);
324                 if (visitChildren) {
325                         // visit children in normal left to right reading order
326                         acceptChild(visitor, getExpression());
327                         if (this.ast.apiLevel == AST.JLS2_INTERNAL) {
328                                 acceptChild(visitor, getName());
329                         }
330                         if (this.ast.apiLevel >= AST.JLS3) {
331                                 acceptChildren(visitor, this.typeArguments);
332                                 acceptChild(visitor, getType());
333                         }
334                         acceptChildren(visitor, this.arguments);
335                         acceptChild(visitor, getAnonymousClassDeclaration());
336                 }
337                 visitor.endVisit(this);
338         }
339         
340         /**
341          * Returns the expression of this class instance creation expression, or 
342          * <code>null</code> if there is none.
343          * 
344          * @return the expression node, or <code>null</code> if there is none
345          */ 
346         public Expression getExpression() {
347                 return this.optionalExpression;
348         }
349         
350         /**
351          * Sets or clears the expression of this class instance creation expression.
352          * 
353          * @param expression the expression node, or <code>null</code> if 
354          *    there is none
355          * @exception IllegalArgumentException if:
356          * <ul>
357          * <li>the node belongs to a different AST</li>
358          * <li>the node already has a parent</li>
359          * <li>a cycle in would be created</li>
360          * </ul>
361          */ 
362         public void setExpression(Expression expression) {
363                 // a ClassInstanceCreation may occur inside an Expression
364                 // must check cycles
365                 ASTNode oldChild = this.optionalExpression;
366                 preReplaceChild(oldChild, expression, EXPRESSION_PROPERTY);
367                 this.optionalExpression = expression;
368                 postReplaceChild(oldChild, expression, EXPRESSION_PROPERTY);
369         }
370
371         /**
372          * Returns the live ordered list of type arguments of this class
373          * instance creation (added in JLS3 API).
374          * 
375          * @return the live list of type arguments
376          *    (element type: <code>Type</code>)
377          * @exception UnsupportedOperationException if this operation is used in
378          * a JLS2 AST
379          * @since 3.1
380          */ 
381         public List typeArguments() {
382                 // more efficient than just calling unsupportedIn2() to check
383                 if (this.typeArguments == null) {
384                         unsupportedIn2();
385                 }
386                 return this.typeArguments;
387         }
388         
389     /**
390          * Returns the name of the type instantiated in this class instance 
391          * creation expression (JLS2 API only).
392          * 
393          * @return the type name node
394          * @exception UnsupportedOperationException if this operation is used in
395          * an AST later than JLS2
396          * @deprecated In the JLS3 API, this method is replaced by
397          * {@link #getType()}, which returns a <code>Type</code> instead of a
398          * <code>Name</code>.
399          */ 
400         public Name getName() {
401                 return internalGetName();
402         }
403
404         /**
405          * Internal synonym for deprecated method. Used to avoid
406          * deprecation warnings.
407          * @since 3.1
408          */
409         /*package*/ Name internalGetName() {
410             supportedOnlyIn2();
411                 if (this.typeName == null) {
412                         // lazy init must be thread-safe for readers
413                         synchronized (this) {
414                                 if (this.typeName == null) {
415                                         preLazyInit();
416                                         this.typeName = new SimpleName(this.ast);
417                                         postLazyInit(this.typeName, NAME_PROPERTY);
418                                 }
419                         }
420                 }
421                 return typeName;
422         }
423         
424         /**
425          * Sets the name of the type instantiated in this class instance 
426          * creation expression (JLS2 API only).
427          * 
428          * @param name the new type name
429          * @exception IllegalArgumentException if:
430          * <ul>
431          * <li>the node belongs to a different AST</li>
432          * <li>the node already has a parent</li>`
433          * </ul>
434          * @exception UnsupportedOperationException if this operation is used in
435          * an AST later than JLS2
436          * @deprecated In the JLS3 API, this method is replaced by 
437          * {@link #setType(Type)}, which expects a <code>Type</code> instead of
438          * a <code>Name</code>.
439          */ 
440         public void setName(Name name) {
441                 internalSetName(name);
442         }
443
444         /**
445          * Internal synonym for deprecated method. Used to avoid
446          * deprecation warnings.
447          * @since 3.1
448          */
449         /*package*/ void internalSetName(Name name) {
450             supportedOnlyIn2();
451                 if (name == null) {
452                         throw new IllegalArgumentException();
453                 }
454                 ASTNode oldChild = this.typeName;
455                 preReplaceChild(oldChild, name, NAME_PROPERTY);
456                 this.typeName = name;
457                 postReplaceChild(oldChild, name, NAME_PROPERTY);
458         }
459
460         /**
461          * Returns the type instantiated in this class instance creation
462          * expression (added in JLS3 API).
463          * 
464          * @return the type node
465          * @exception UnsupportedOperationException if this operation is used in
466          * a JLS2 AST
467          * @since 3.1
468          */ 
469         public Type getType() {
470             unsupportedIn2();
471                 if (this.type == null) {
472                         // lazy init must be thread-safe for readers
473                         synchronized (this) {
474                                 if (this.type == null) {
475                                         preLazyInit();
476                                         this.type = new SimpleType(this.ast);
477                                         postLazyInit(this.type, TYPE_PROPERTY);
478                                 }
479                         }
480                 }
481                 return this.type;
482         }
483         
484         /**
485          * Sets the type instantiated in this class instance creation
486          * expression (added in JLS3 API).
487          * 
488          * @param type the new type
489          * @exception IllegalArgumentException if:
490          * <ul>
491          * <li>the node belongs to a different AST</li>
492          * <li>the node already has a parent</li>`
493          * </ul>
494          * @exception UnsupportedOperationException if this operation is used in
495          * a JLS2 AST
496          * @since 3.1
497          */ 
498         public void setType(Type type) {
499             unsupportedIn2();
500                 if (type == null) {
501                         throw new IllegalArgumentException();
502                 }
503                 ASTNode oldChild = this.type;
504                 preReplaceChild(oldChild, type, TYPE_PROPERTY);
505                 this.type = type;
506                 postReplaceChild(oldChild, type, TYPE_PROPERTY);
507         }
508
509         /**
510          * Returns the live ordered list of argument expressions in this class
511          * instance creation expression.
512          * 
513          * @return the live list of argument expressions (possibly empty)
514          *    (element type: <code>Expression</code>)
515          */ 
516         public List arguments() {
517                 return this.arguments;
518         }
519         
520         /**
521          * Returns the anonymous class declaration introduced by this
522          * class instance creation expression, if it has one.
523          * 
524          * @return the anonymous class declaration, or <code>null</code> if none
525          */ 
526         public AnonymousClassDeclaration getAnonymousClassDeclaration() {
527                 return this.optionalAnonymousClassDeclaration;
528         }
529         
530         /**
531          * Sets whether this class instance creation expression declares
532          * an anonymous class (that is, has class body declarations).
533          * 
534          * @param decl the anonymous class declaration, or <code>null</code> 
535          *    if none
536          */ 
537         public void setAnonymousClassDeclaration(AnonymousClassDeclaration decl) {
538                 ASTNode oldChild = this.optionalAnonymousClassDeclaration;
539                 preReplaceChild(oldChild, decl, ANONYMOUS_CLASS_DECLARATION_PROPERTY);
540                 this.optionalAnonymousClassDeclaration = decl;
541                 postReplaceChild(oldChild, decl, ANONYMOUS_CLASS_DECLARATION_PROPERTY);
542         }
543
544         /**
545          * Resolves and returns the binding for the constructor invoked by this
546          * expression. For anonymous classes, the binding is that of the anonymous
547          * constructor.
548          * <p>
549          * Note that bindings are generally unavailable unless requested when the
550          * AST is being built.
551          * </p>
552          * 
553          * @return the constructor binding, or <code>null</code> if the binding
554          *    cannot be resolved
555          */     
556         public IMethodBinding resolveConstructorBinding() {
557                 return this.ast.getBindingResolver().resolveConstructor(this);
558         }
559
560         /* (omit javadoc for this method)
561          * Method declared on ASTNode.
562          */
563         int memSize() {
564                 // treat Code as free
565                 return BASE_NODE_SIZE + 6 * 4;
566         }
567         
568         /* (omit javadoc for this method)
569          * Method declared on ASTNode.
570          */
571         int treeSize() {
572                 // n.b. type == null for ast.API_LEVEL == JLS2
573                 // n.b. typeArguments == null for ast.API_LEVEL == JLS2
574                 // n.b. typeName == null for ast.API_LEVEL >= JLS3
575                 return 
576                         memSize()
577                         + (this.typeName == null ? 0 : getName().treeSize())
578                         + (this.type == null ? 0 : getType().treeSize())
579                         + (this.optionalExpression == null ? 0 : getExpression().treeSize())
580                         + (this.typeArguments == null ? 0 : this.typeArguments.listSize())
581                         + (this.arguments == null ? 0 : this.arguments.listSize())
582                         + (this.optionalAnonymousClassDeclaration == null ? 0 : getAnonymousClassDeclaration().treeSize());
583         }
584 }
585