Initial upgrade to Platform/JDT 3.4.1
[phpeclipse.git] / net.sourceforge.phpeclipse / src / net / sourceforge / phpdt / core / dom / PostfixExpression.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.HashMap;
16 import java.util.List;
17 import java.util.Map;
18
19 /**
20  * Postfix expression AST node type.
21  *
22  * <pre>
23  * PostfixExpression:
24  *    Expression PostfixOperator
25  * </pre>
26  * 
27  * @since 2.0
28  * @noinstantiate This class is not intended to be instantiated by clients.
29  */
30 public class PostfixExpression extends Expression {
31
32         /**
33          * Postfix operators (typesafe enumeration).
34          * <pre>
35          * PostfixOperator:
36          *    <b><code>++</code></b>  <code>INCREMENT</code>
37          *    <b><code>--</code></b>  <code>DECREMENT</code>
38          * </pre>
39          */
40         public static class Operator {
41         
42                 /**
43                  * The token for the operator.
44                  */
45                 private String token;
46                 
47                 /**
48                  * Creates a new postfix operator with the given token.
49                  * <p>
50                  * Note: this constructor is private. The only instances
51                  * ever created are the ones for the standard operators.
52                  * </p>
53                  * 
54                  * @param token the character sequence for the operator
55                  */
56                 private Operator(String token) {
57                         this.token = token;
58                 }
59                 
60                 /**
61                  * Returns the character sequence for the operator.
62                  * 
63                  * @return the character sequence for the operator
64                  */
65                 public String toString() {
66                         return token;
67                 }
68                 
69                 /** Postfix increment "++" operator. */
70                 public static final Operator INCREMENT = new Operator("++");//$NON-NLS-1$
71                 /** Postfix decrement "--" operator. */
72                 public static final Operator DECREMENT = new Operator("--");//$NON-NLS-1$
73                 
74                 /**
75                  * Map from token to operator (key type: <code>String</code>;
76                  * value type: <code>Operator</code>).
77                  */
78                 private static final Map CODES;
79                 static {
80                         CODES = new HashMap(20);
81                         Operator[] ops = {
82                                         INCREMENT,
83                                         DECREMENT,
84                                 };
85                         for (int i = 0; i < ops.length; i++) {
86                                 CODES.put(ops[i].toString(), ops[i]);
87                         }
88                 }
89
90                 /**
91                  * Returns the postfix operator corresponding to the given string,
92                  * or <code>null</code> if none.
93                  * <p>
94                  * <code>toOperator</code> is the converse of <code>toString</code>:
95                  * that is, <code>Operator.toOperator(op.toString()) == op</code> for 
96                  * all operators <code>op</code>.
97                  * </p>
98                  * 
99                  * @param token the character sequence for the operator
100                  * @return the postfix operator, or <code>null</code> if none
101                  */
102                 public static Operator toOperator(String token) {
103                         return (Operator) CODES.get(token);
104                 }
105         }
106         
107         /**
108          * The "operator" structural property of this node type.
109          * @since 3.0
110          */
111         public static final SimplePropertyDescriptor OPERATOR_PROPERTY = 
112                 new SimplePropertyDescriptor(PostfixExpression.class, "operator", PostfixExpression.Operator.class, MANDATORY); //$NON-NLS-1$
113         
114         /**
115          * The "operand" structural property of this node type.
116          * @since 3.0
117          */
118         public static final ChildPropertyDescriptor OPERAND_PROPERTY = 
119                 new ChildPropertyDescriptor(PostfixExpression.class, "operand", Expression.class, MANDATORY, CYCLE_RISK); //$NON-NLS-1$
120
121         /**
122          * A list of property descriptors (element type: 
123          * {@link StructuralPropertyDescriptor}),
124          * or null if uninitialized.
125          */
126         private static final List PROPERTY_DESCRIPTORS;
127         
128         static {
129                 List propertyList = new ArrayList(3);
130                 createPropertyList(PostfixExpression.class, propertyList);
131                 addProperty(OPERAND_PROPERTY, propertyList);
132                 addProperty(OPERATOR_PROPERTY, propertyList);
133                 PROPERTY_DESCRIPTORS = reapPropertyList(propertyList);
134         }
135
136         /**
137          * Returns a list of structural property descriptors for this node type.
138          * Clients must not modify the result.
139          * 
140          * @param apiLevel the API level; one of the
141          * <code>AST.JLS*</code> constants
142
143          * @return a list of property descriptors (element type: 
144          * {@link StructuralPropertyDescriptor})
145          * @since 3.0
146          */
147         public static List propertyDescriptors(int apiLevel) {
148                 return PROPERTY_DESCRIPTORS;
149         }
150                         
151         /**
152          * The operator; defaults to an unspecified postfix operator.
153          */
154         private PostfixExpression.Operator operator = 
155                 PostfixExpression.Operator.INCREMENT;
156
157         /**
158          * The operand; lazily initialized; defaults to an unspecified,
159          * but legal, simple name.
160          */
161         private Expression operand = null;
162
163         /**
164          * Creates a new AST node for an postfix expression owned by the given 
165          * AST. By default, the node has unspecified (but legal) operator and 
166          * operand.
167          * 
168          * @param ast the AST that is to own this node
169          */
170         PostfixExpression(AST ast) {
171                 super(ast);
172         }
173
174         /* (omit javadoc for this method)
175          * Method declared on ASTNode.
176          */
177         final List internalStructuralPropertiesForType(int apiLevel) {
178                 return propertyDescriptors(apiLevel);
179         }
180         
181         /* (omit javadoc for this method)
182          * Method declared on ASTNode.
183          */
184         final Object internalGetSetObjectProperty(SimplePropertyDescriptor property, boolean get, Object value) {
185                 if (property == OPERATOR_PROPERTY) {
186                         if (get) {
187                                 return getOperator();
188                         } else {
189                                 setOperator((Operator) value);
190                                 return null;
191                         }
192                 }
193                 // allow default implementation to flag the error
194                 return super.internalGetSetObjectProperty(property, get, value);
195         }
196
197         /* (omit javadoc for this method)
198          * Method declared on ASTNode.
199          */
200         final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) {
201                 if (property == OPERAND_PROPERTY) {
202                         if (get) {
203                                 return getOperand();
204                         } else {
205                                 setOperand((Expression) child);
206                                 return null;
207                         }
208                 }
209                 // allow default implementation to flag the error
210                 return super.internalGetSetChildProperty(property, get, child);
211         }
212         
213         /* (omit javadoc for this method)
214          * Method declared on ASTNode.
215          */
216         final int getNodeType0() {
217                 return POSTFIX_EXPRESSION;
218         }
219
220         /* (omit javadoc for this method)
221          * Method declared on ASTNode.
222          */
223         ASTNode clone0(AST target) {
224                 PostfixExpression result = new PostfixExpression(target);
225                 result.setSourceRange(this.getStartPosition(), this.getLength());
226                 result.setOperator(getOperator());
227                 result.setOperand((Expression) getOperand().clone(target));
228                 return result;
229         }
230
231         /* (omit javadoc for this method)
232          * Method declared on ASTNode.
233          */
234         final boolean subtreeMatch0(ASTMatcher matcher, Object other) {
235                 // dispatch to correct overloaded match method
236                 return matcher.match(this, other);
237         }
238
239         /* (omit javadoc for this method)
240          * Method declared on ASTNode.
241          */
242         void accept0(ASTVisitor visitor) {
243                 boolean visitChildren = visitor.visit(this);
244                 if (visitChildren) {
245                         acceptChild(visitor, getOperand());
246                 }
247                 visitor.endVisit(this);
248         }
249         
250         /**
251          * Returns the operator of this postfix expression.
252          * 
253          * @return the operator
254          */ 
255         public PostfixExpression.Operator getOperator() {
256                 return this.operator;
257         }
258
259         /**
260          * Sets the operator of this postfix expression.
261          * 
262          * @param operator the operator
263          * @exception IllegalArgumentException if the argument is incorrect
264          */ 
265         public void setOperator(PostfixExpression.Operator operator) {
266                 if (operator == null) {
267                         throw new IllegalArgumentException();
268                 }
269                 preValueChange(OPERATOR_PROPERTY);
270                 this.operator = operator;
271                 postValueChange(OPERATOR_PROPERTY);
272         }
273
274         /**
275          * Returns the operand of this postfix expression.
276          * 
277          * @return the operand expression node
278          */ 
279         public Expression getOperand() {
280                 if (this.operand  == null) {
281                         // lazy init must be thread-safe for readers
282                         synchronized (this) {
283                                 if (this.operand == null) {
284                                         preLazyInit();
285                                         this.operand= new SimpleName(this.ast);
286                                         postLazyInit(this.operand, OPERAND_PROPERTY);
287                                 }
288                         }
289                 }
290                 return this.operand;
291         }
292                 
293         /**
294          * Sets the operand of this postfix expression.
295          * 
296          * @param expression the operand expression node
297          * @exception IllegalArgumentException if:
298          * <ul>
299          * <li>the node belongs to a different AST</li>
300          * <li>the node already has a parent</li>
301          * <li>a cycle in would be created</li>
302          * </ul>
303          */ 
304         public void setOperand(Expression expression) {
305                 if (expression == null) {
306                         throw new IllegalArgumentException();
307                 }
308                 ASTNode oldChild = this.operand;
309                 preReplaceChild(oldChild, expression, OPERAND_PROPERTY);
310                 this.operand = expression;
311                 postReplaceChild(oldChild, expression, OPERAND_PROPERTY);
312         }
313
314         /* (omit javadoc for this method)
315          * Method declared on ASTNode.
316          */
317         int memSize() {
318                 // treat Operator as free
319                 return BASE_NODE_SIZE + 2 * 4;
320         }
321         
322         /* (omit javadoc for this method)
323          * Method declared on ASTNode.
324          */
325         int treeSize() {
326                 return 
327                         memSize()
328                         + (this.operand == null ? 0 : getOperand().treeSize());
329         }
330 }