c4cfe6eaedcd2d08bdc0209e38db7107643e0a25
[phpeclipse.git] / net.sourceforge.phpeclipse / src / net / sourceforge / phpdt / core / dom / TypeDeclarationStatement.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  * Local type declaration statement AST node type.
19  * <p>
20  * This kind of node is used to convert a type declaration
21  * node into a statement node by wrapping it.
22  * </p>
23  * For JLS2:
24  * <pre>
25  * TypeDeclarationStatement:
26  *    TypeDeclaration
27  * </pre>
28  * For JLS3, the kinds of type declarations grew to include enum declarations:
29  * <pre>
30  * TypeDeclarationStatement:
31  *    TypeDeclaration
32  *    EnumDeclaration
33  * </pre>
34  * Although allowed at the AST, not all arrangements of AST nodes are meaningful;
35  * in particular, only class and enum declarations are meaningful in the context of 
36  * a block.
37  * 
38  * @since 2.0
39  * @noinstantiate This class is not intended to be instantiated by clients.
40  */
41 public class TypeDeclarationStatement extends Statement {
42         
43         /**
44          * The "typeDeclaration" structural property of this node type (JLS2 API only).
45          * @since 3.0
46          */
47         public static final ChildPropertyDescriptor TYPE_DECLARATION_PROPERTY = 
48                 new ChildPropertyDescriptor(TypeDeclarationStatement.class, "typeDeclaration", TypeDeclaration.class, MANDATORY, CYCLE_RISK); //$NON-NLS-1$
49
50         /**
51          * The "declaration" structural property of this node type (added in JLS3 API).
52          * @since 3.1
53          */
54         public static final ChildPropertyDescriptor DECLARATION_PROPERTY = 
55                 new ChildPropertyDescriptor(TypeDeclarationStatement.class, "declaration", AbstractTypeDeclaration.class, MANDATORY, CYCLE_RISK); //$NON-NLS-1$
56
57         /**
58          * A list of property descriptors (element type: 
59          * {@link StructuralPropertyDescriptor}),
60          * or null if uninitialized.
61          * @since 3.0
62          */
63         private static final List PROPERTY_DESCRIPTORS_2_0;
64         
65         /**
66          * A list of property descriptors (element type: 
67          * {@link StructuralPropertyDescriptor}),
68          * or null if uninitialized.
69          * @since 3.1
70          */
71         private static final List PROPERTY_DESCRIPTORS_3_0;
72         
73         static {
74                 List propertyList = new ArrayList(2);
75                 createPropertyList(TypeDeclarationStatement.class, propertyList);
76                 addProperty(TYPE_DECLARATION_PROPERTY, propertyList);
77                 PROPERTY_DESCRIPTORS_2_0 = reapPropertyList(propertyList);
78                 
79                 propertyList = new ArrayList(2);
80                 createPropertyList(TypeDeclarationStatement.class, propertyList);
81                 addProperty(DECLARATION_PROPERTY, propertyList);
82                 PROPERTY_DESCRIPTORS_3_0 = reapPropertyList(propertyList);
83         }
84
85         /**
86          * Returns a list of structural property descriptors for this node type.
87          * Clients must not modify the result.
88          * 
89          * @param apiLevel the API level; one of the
90          * <code>AST.JLS*</code> constants
91
92          * @return a list of property descriptors (element type: 
93          * {@link StructuralPropertyDescriptor})
94          * @since 3.0
95          */
96         public static List propertyDescriptors(int apiLevel) {
97                 if (apiLevel == AST.JLS2_INTERNAL) {
98                         return PROPERTY_DESCRIPTORS_2_0;
99                 } else {
100                         return PROPERTY_DESCRIPTORS_3_0;
101                 }
102         }
103                         
104         /**
105          * The type declaration; lazily initialized; defaults to a unspecified, 
106          * but legal, type declaration. In JLS2, corresponds to TYPE_DECLARATION_PROPERTY.
107      * After JLS2, corresponds to DECLARATION_PROPERTY.
108      * @see #typeDeclProperty
109          */
110         private AbstractTypeDeclaration typeDecl = null;
111     
112     /**
113      * The child property stored on the <code>typeDecl</code> instance variable.
114      * In JLS2, corresponds to TYPE_DECLARATION_PROPERTY. After JLS2, corresponds to 
115      * DECLARATION_PROPERTY.
116      * 
117      * @return the property corresponding to the <code>typeDecl</code> instance variable;
118      * never <code>null</code>
119      */
120     private ChildPropertyDescriptor typeDeclProperty () {
121         if (getAST().apiLevel() == AST.JLS2_INTERNAL) {
122             return TYPE_DECLARATION_PROPERTY;
123         } else {
124             return DECLARATION_PROPERTY;
125         }
126     }
127
128
129         /**
130          * Creates a new unparented local type declaration statement node owned 
131          * by the given AST. By default, the local type declaration is an
132          * unspecified, but legal, type declaration.
133          * <p>
134          * N.B. This constructor is package-private.
135          * </p>
136          * 
137          * @param ast the AST that is to own this node
138          */
139         TypeDeclarationStatement(AST ast) {
140                 super(ast);
141         }
142
143         /* (omit javadoc for this method)
144          * Method declared on ASTNode.
145          * @since 3.0
146          */
147         final List internalStructuralPropertiesForType(int apiLevel) {
148                 return propertyDescriptors(apiLevel);
149         }
150         
151         /* (omit javadoc for this method)
152          * Method declared on ASTNode.
153          */
154         final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) {
155                 if (property == TYPE_DECLARATION_PROPERTY) {
156                         if (get) {
157                                 return getTypeDeclaration();
158                         } else {
159                                 setTypeDeclaration((TypeDeclaration) child);
160                                 return null;
161                         }
162                 }
163                 if (property == DECLARATION_PROPERTY) {
164                         if (get) {
165                                 return getDeclaration();
166                         } else {
167                                 setDeclaration((AbstractTypeDeclaration) child);
168                                 return null;
169                         }
170                 }
171                 // allow default implementation to flag the error
172                 return super.internalGetSetChildProperty(property, get, child);
173         }
174         
175         /* (omit javadoc for this method)
176          * Method declared on ASTNode.
177          */
178         final int getNodeType0() {
179                 return TYPE_DECLARATION_STATEMENT;
180         }
181
182         /* (omit javadoc for this method)
183          * Method declared on ASTNode.
184          */
185         ASTNode clone0(AST target) {
186                 TypeDeclarationStatement result = 
187                         new TypeDeclarationStatement(target);
188                 result.setSourceRange(this.getStartPosition(), this.getLength());
189                 result.copyLeadingComment(this);
190                 result.setDeclaration(
191                         (AbstractTypeDeclaration) getDeclaration().clone(target));
192                 return result;
193         }
194         
195         /* (omit javadoc for this method)
196          * Method declared on ASTNode.
197          */
198         final boolean subtreeMatch0(ASTMatcher matcher, Object other) {
199                 // dispatch to correct overloaded match method
200                 return matcher.match(this, other);
201         }
202
203         /* (omit javadoc for this method)
204          * Method declared on ASTNode.
205          */
206         void accept0(ASTVisitor visitor) {
207                 boolean visitChildren = visitor.visit(this);
208                 if (visitChildren) {
209                         acceptChild(visitor, getDeclaration());
210                 }
211                 visitor.endVisit(this);
212         }
213         
214         /**
215          * Returns the abstract type declaration of this local type declaration
216          * statement (added in JLS3 API).
217          * 
218          * @return the type declaration node
219          * @since 3.1
220          */ 
221         public AbstractTypeDeclaration getDeclaration() {
222                 if (this.typeDecl == null) {
223                         // lazy init must be thread-safe for readers
224                         synchronized (this) {
225                                 if (this.typeDecl == null) {
226                                         preLazyInit();
227                                         this.typeDecl = new TypeDeclaration(this.ast);
228                                         postLazyInit(this.typeDecl, typeDeclProperty());
229                                 }
230                         }
231                 }
232                 return this.typeDecl;
233         }
234                 
235         /**
236          * Sets the abstract type declaration of this local type declaration
237          * statement (added in JLS3 API).
238          * 
239          * @param decl the type declaration node
240          * @exception IllegalArgumentException if:
241          * <ul>
242          * <li>the node belongs to a different AST</li>
243          * <li>the node already has a parent</li>
244          * <li>a cycle in would be created</li>
245          * </ul>
246          * @since 3.1
247          */ 
248         public void setDeclaration(AbstractTypeDeclaration decl) {
249                 if (decl == null) {
250                         throw new IllegalArgumentException();
251                 }
252                 // a TypeDeclarationStatement may occur inside an 
253                 // TypeDeclaration - must check cycles
254                 ASTNode oldChild = this.typeDecl;
255                 ChildPropertyDescriptor typeDeclProperty = typeDeclProperty();
256                 preReplaceChild(oldChild, decl, typeDeclProperty);
257                 this.typeDecl= decl;
258                 postReplaceChild(oldChild, decl, typeDeclProperty);
259         }
260         
261         /**
262          * Returns the type declaration of this local type declaration
263          * statement (JLS2 API only).
264          * 
265          * @return the type declaration node
266          * @exception UnsupportedOperationException if this operation is used in
267          * an AST later than JLS2
268          * @deprecated In the JLS3 API, this method is replaced by 
269          * {@link #getDeclaration()}, which returns <code>AbstractTypeDeclaration</code>
270          * instead of <code>TypeDeclaration</code>.
271          */ 
272         public TypeDeclaration getTypeDeclaration() {
273                 return internalGetTypeDeclaration();
274         }
275         
276         /**
277          * Internal synonym for deprecated method. Used to avoid
278          * deprecation warnings.
279          * @since 3.1
280          */
281         /*package*/ final TypeDeclaration internalGetTypeDeclaration() {
282                 supportedOnlyIn2();
283                 return (TypeDeclaration) getDeclaration();
284         }
285                 
286         /**
287          * Sets the type declaration of this local type declaration
288          * statement (JLS2 API only).
289          * 
290          * @param decl the type declaration node
291          * @exception IllegalArgumentException if:
292          * <ul>
293          * <li>the node belongs to a different AST</li>
294          * <li>the node already has a parent</li>
295          * <li>a cycle in would be created</li>
296          * </ul>
297          * @exception UnsupportedOperationException if this operation is used in
298          * an AST later than JLS2
299      * @deprecated In the JLS3 API, this method is replaced by 
300      * {@link #setDeclaration(AbstractTypeDeclaration)} which takes
301      * <code>AbstractTypeDeclaration</code> instead of
302      * <code>TypeDeclaration</code>.
303          */ 
304         public void setTypeDeclaration(TypeDeclaration decl) {
305                 internalSetTypeDeclaration(decl);
306         }
307         
308         /**
309          * Internal synonym for deprecated method. Used to avoid
310          * deprecation warnings.
311          * @since 3.1
312          */
313         /*package*/ final void internalSetTypeDeclaration(TypeDeclaration decl) {
314             supportedOnlyIn2();
315                 // forward to non-deprecated replacement method
316                 setDeclaration(decl);
317         }
318         
319         /**
320          * Resolves and returns the binding for the class or interface declared in
321          * this type declaration statement.
322          * <p>
323          * Note that bindings are generally unavailable unless requested when the
324          * AST is being built.
325          * </p>
326          * 
327          * @return the binding, or <code>null</code> if the binding cannot be 
328          *    resolved
329          */     
330         public ITypeBinding resolveBinding() {
331                 // forward request to the wrapped type declaration
332                 AbstractTypeDeclaration d = getDeclaration();
333                 if (d instanceof TypeDeclaration) {
334                         return ((TypeDeclaration) d).resolveBinding();
335                 } else if (d instanceof AnnotationTypeDeclaration) {
336                         return ((AnnotationTypeDeclaration) d).resolveBinding();
337                 } else {
338                         // shouldn't happen
339                         return null;
340                 }
341         }
342         
343         /* (omit javadoc for this method)
344          * Method declared on ASTNode.
345          */
346         int memSize() {
347                 return super.memSize() + 1 * 4;
348         }
349         
350         /* (omit javadoc for this method)
351          * Method declared on ASTNode.
352          */
353         int treeSize() {
354                 return
355                         memSize()
356                         + (this.typeDecl == null ? 0 : getDeclaration().treeSize());
357         }
358 }
359