7c13752535ce5147af00976288b18829a5d53fcb
[phpeclipse.git] / net.sourceforge.phpeclipse / src / net / sourceforge / phpdt / core / dom / Assignment.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  * Assignment expression AST node type.
21  *
22  * <pre>
23  * Assignment:
24  *    Expression AssignmentOperator Expression
25  * </pre>
26  * 
27  * @since 2.0
28  * @noinstantiate This class is not intended to be instantiated by clients.
29  */
30 public class Assignment extends Expression {
31                 
32         /**
33          * Assignment operators (typesafe enumeration).
34          * <pre>
35          * AssignmentOperator:<code>
36          *    <b>=</b> ASSIGN
37          *    <b>+=</b> PLUS_ASSIGN
38          *    <b>-=</b> MINUS_ASSIGN
39          *    <b>*=</b> TIMES_ASSIGN
40          *    <b>/=</b> DIVIDE_ASSIGN
41          *    <b>&amp;=</b> BIT_AND_ASSIGN
42          *    <b>|=</b> BIT_OR_ASSIGN
43          *    <b>^=</b> BIT_XOR_ASSIGN
44          *    <b>%=</b> REMAINDER_ASSIGN
45          *    <b>&lt;&lt;=</b> LEFT_SHIFT_ASSIGN
46          *    <b>&gt;&gt;=</b> RIGHT_SHIFT_SIGNED_ASSIGN
47          *    <b>&gt;&gt;&gt;=</b> RIGHT_SHIFT_UNSIGNED_ASSIGN</code>
48          * </pre>
49          */
50         public static class Operator {
51         
52                 /**
53                  * The name of the operator
54                  */
55                 private String op;
56                 
57                 /**
58                  * Creates a new assignment operator with the given name.
59                  * <p>
60                  * Note: this constructor is private. The only instances
61                  * ever created are the ones for the standard operators.
62                  * </p>
63                  * 
64                  * @param op the character sequence for the operator
65                  */
66                 private Operator(String op) {
67                         this.op = op;
68                 }
69                 
70                 /**
71                  * Returns the character sequence for the operator.
72                  * 
73                  * @return the character sequence for the operator
74                  */
75                 public String toString() {
76                         return op;
77                 }
78                 
79                 /** = operator. */
80                 public static final Operator ASSIGN = new Operator("=");//$NON-NLS-1$
81                 /** += operator. */
82                 public static final Operator PLUS_ASSIGN = new Operator("+=");//$NON-NLS-1$
83                 /** -= operator. */
84                 public static final Operator MINUS_ASSIGN = new Operator("-=");//$NON-NLS-1$
85                 /** *= operator. */
86                 public static final Operator TIMES_ASSIGN = new Operator("*=");//$NON-NLS-1$
87                 /** /= operator. */
88                 public static final Operator DIVIDE_ASSIGN = new Operator("/=");//$NON-NLS-1$
89                 /** &amp;= operator. */
90                 public static final Operator BIT_AND_ASSIGN = new Operator("&=");//$NON-NLS-1$
91                 /** |= operator. */
92                 public static final Operator BIT_OR_ASSIGN = new Operator("|=");//$NON-NLS-1$
93                 /** ^= operator. */
94                 public static final Operator BIT_XOR_ASSIGN = new Operator("^=");//$NON-NLS-1$
95                 /** %= operator. */
96                 public static final Operator REMAINDER_ASSIGN = new Operator("%=");//$NON-NLS-1$
97                 /** &lt;&lt;== operator. */
98                 public static final Operator LEFT_SHIFT_ASSIGN =
99                         new Operator("<<=");//$NON-NLS-1$
100                 /** &gt;&gt;= operator. */
101                 public static final Operator RIGHT_SHIFT_SIGNED_ASSIGN =
102                         new Operator(">>=");//$NON-NLS-1$
103                 /** &gt;&gt;&gt;= operator. */
104                 public static final Operator RIGHT_SHIFT_UNSIGNED_ASSIGN =
105                         new Operator(">>>=");//$NON-NLS-1$
106                 
107                 /**
108                  * Returns the assignment operator corresponding to the given string,
109                  * or <code>null</code> if none.
110                  * <p>
111                  * <code>toOperator</code> is the converse of <code>toString</code>:
112                  * that is, <code>Operator.toOperator(op.toString()) == op</code> for all 
113                  * operators <code>op</code>.
114                  * </p>
115                  * 
116                  * @param token the character sequence for the operator
117                  * @return the assignment operator, or <code>null</code> if none
118                  */
119                 public static Operator toOperator(String token) {
120                         return (Operator) CODES.get(token);
121                 }
122                 
123                 /**
124                  * Map from token to operator (key type: <code>String</code>;
125                  * value type: <code>Operator</code>).
126                  */
127                 private static final Map CODES;
128                 static {
129                         CODES = new HashMap(20);
130                         Operator[] ops = {
131                                         ASSIGN,
132                                         PLUS_ASSIGN,
133                                         MINUS_ASSIGN,
134                                         TIMES_ASSIGN,
135                                         DIVIDE_ASSIGN,
136                                         BIT_AND_ASSIGN,
137                                         BIT_OR_ASSIGN,
138                                         BIT_XOR_ASSIGN,
139                                         REMAINDER_ASSIGN,
140                                         LEFT_SHIFT_ASSIGN,
141                                         RIGHT_SHIFT_SIGNED_ASSIGN,
142                                         RIGHT_SHIFT_UNSIGNED_ASSIGN
143                                 };
144                         for (int i = 0; i < ops.length; i++) {
145                                 CODES.put(ops[i].toString(), ops[i]);
146                         }
147                 }
148         }
149         
150         /**
151          * The "leftHandSide" structural property of this node type.
152          * @since 3.0
153          */
154         public static final ChildPropertyDescriptor LEFT_HAND_SIDE_PROPERTY = 
155                 new ChildPropertyDescriptor(Assignment.class, "leftHandSide", Expression.class, MANDATORY, CYCLE_RISK); //$NON-NLS-1$
156
157         /**
158          * The "operator" structural property of this node type.
159          * @since 3.0
160          */
161         public static final SimplePropertyDescriptor OPERATOR_PROPERTY = 
162                 new SimplePropertyDescriptor(Assignment.class, "operator", Assignment.Operator.class, MANDATORY); //$NON-NLS-1$
163         
164         /**
165          * The "rightHandSide" structural property of this node type.
166          * @since 3.0
167          */
168         public static final ChildPropertyDescriptor RIGHT_HAND_SIDE_PROPERTY = 
169                 new ChildPropertyDescriptor(Assignment.class, "rightHandSide", Expression.class, MANDATORY, CYCLE_RISK); //$NON-NLS-1$
170
171         /**
172          * A list of property descriptors (element type: 
173          * {@link StructuralPropertyDescriptor}),
174          * or null if uninitialized.
175          */
176         private static final List PROPERTY_DESCRIPTORS;
177         
178         static {
179                 List properyList = new ArrayList(4);
180                 createPropertyList(Assignment.class, properyList);
181                 addProperty(LEFT_HAND_SIDE_PROPERTY, properyList);
182                 addProperty(OPERATOR_PROPERTY, properyList);
183                 addProperty(RIGHT_HAND_SIDE_PROPERTY, properyList);
184                 PROPERTY_DESCRIPTORS = reapPropertyList(properyList);
185         }
186
187         /**
188          * Returns a list of structural property descriptors for this node type.
189          * Clients must not modify the result.
190          * 
191          * @param apiLevel the API level; one of the
192          * <code>AST.JLS*</code> constants
193
194          * @return a list of property descriptors (element type: 
195          * {@link StructuralPropertyDescriptor})
196          * @since 3.0
197          */
198         public static List propertyDescriptors(int apiLevel) {
199                 return PROPERTY_DESCRIPTORS;
200         }
201                         
202         /**
203          * The assignment operator; defaults to Assignment.Operator.ASSIGN
204          */
205         private Assignment.Operator assignmentOperator = Assignment.Operator.ASSIGN;
206
207         /**
208          * The left hand side; lazily initialized; defaults to an unspecified,
209          * but legal, simple name.
210          */
211         private Expression leftHandSide = null;
212
213         /**
214          * The right hand side; lazily initialized; defaults to an unspecified,
215          * but legal, simple name.
216          */
217         private Expression rightHandSide = null;
218
219         /**
220          * Creates a new AST node for an assignment expression owned by the given 
221          * AST. By default, the node has an assignment operator, and unspecified
222          * left and right hand sides.
223          * 
224          * @param ast the AST that is to own this node
225          */
226         Assignment(AST ast) {
227                 super(ast);
228         }
229
230         /* (omit javadoc for this method)
231          * Method declared on ASTNode.
232          */
233         final List internalStructuralPropertiesForType(int apiLevel) {
234                 return propertyDescriptors(apiLevel);
235         }
236         
237         /* (omit javadoc for this method)
238          * Method declared on ASTNode.
239          */
240         final Object internalGetSetObjectProperty(SimplePropertyDescriptor property, boolean get, Object value) {
241                 if (property == OPERATOR_PROPERTY) {
242                         if (get) {
243                                 return getOperator();
244                         } else {
245                                 setOperator((Operator) value);
246                                 return null;
247                         }
248                 }
249                 // allow default implementation to flag the error
250                 return super.internalGetSetObjectProperty(property, get, value);
251         }
252
253         /* (omit javadoc for this method)
254          * Method declared on ASTNode.
255          */
256         final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) {
257                 if (property == LEFT_HAND_SIDE_PROPERTY) {
258                         if (get) {
259                                 return getLeftHandSide();
260                         } else {
261                                 setLeftHandSide((Expression) child);
262                                 return null;
263                         }
264                 }
265                 if (property == RIGHT_HAND_SIDE_PROPERTY) {
266                         if (get) {
267                                 return getRightHandSide();
268                         } else {
269                                 setRightHandSide((Expression) child);
270                                 return null;
271                         }
272                 }
273                 // allow default implementation to flag the error
274                 return super.internalGetSetChildProperty(property, get, child);
275         }
276
277         /* (omit javadoc for this method)
278          * Method declared on ASTNode.
279          */
280         final int getNodeType0() {
281                 return ASSIGNMENT;
282         }
283
284         /* (omit javadoc for this method)
285          * Method declared on ASTNode.
286          */
287         ASTNode clone0(AST target) {
288                 Assignment result = new Assignment(target);
289                 result.setSourceRange(this.getStartPosition(), this.getLength());
290                 result.setOperator(getOperator());
291                 result.setLeftHandSide((Expression) getLeftHandSide().clone(target));
292                 result.setRightHandSide((Expression) getRightHandSide().clone(target));
293                 return result;
294         }
295
296         /* (omit javadoc for this method)
297          * Method declared on ASTNode.
298          */
299         final boolean subtreeMatch0(ASTMatcher matcher, Object other) {
300                 // dispatch to correct overloaded match method
301                 return matcher.match(this, other);
302         }
303
304         /* (omit javadoc for this method)
305          * Method declared on ASTNode.
306          */
307         void accept0(ASTVisitor visitor) {
308                 boolean visitChildren = visitor.visit(this);
309                 if (visitChildren) {
310                         // visit children in normal left to right reading order
311                         acceptChild(visitor, getLeftHandSide());
312                         acceptChild(visitor, getRightHandSide());
313                 }
314                 visitor.endVisit(this);
315         }
316         
317         /**
318          * Returns the operator of this assignment expression.
319          * 
320          * @return the assignment operator
321          */ 
322         public Assignment.Operator getOperator() {
323                 return this.assignmentOperator;
324         }
325
326         /**
327          * Sets the operator of this assignment expression.
328          * 
329          * @param assignmentOperator the assignment operator
330          * @exception IllegalArgumentException if the argument is incorrect
331          */ 
332         public void setOperator(Assignment.Operator assignmentOperator) {
333                 if (assignmentOperator == null) {
334                         throw new IllegalArgumentException();
335                 }
336                 preValueChange(OPERATOR_PROPERTY);
337                 this.assignmentOperator = assignmentOperator;
338                 postValueChange(OPERATOR_PROPERTY);
339         }
340
341         /**
342          * Returns the left hand side of this assignment expression.
343          * 
344          * @return the left hand side node
345          */ 
346         public Expression getLeftHandSide() {
347                 if (this.leftHandSide  == null) {
348                         // lazy init must be thread-safe for readers
349                         synchronized (this) {
350                                 if (this.leftHandSide == null) {
351                                         preLazyInit();
352                                         this.leftHandSide= new SimpleName(this.ast);
353                                         postLazyInit(this.leftHandSide, LEFT_HAND_SIDE_PROPERTY);
354                                 }
355                         }
356                 }
357                 return this.leftHandSide;
358         }
359                 
360         /**
361          * Sets the left hand side of this assignment expression.
362          * 
363          * @param expression the left hand side node
364          * @exception IllegalArgumentException if:
365          * <ul>
366          * <li>the node belongs to a different AST</li>
367          * <li>the node already has a parent</li>
368          * <li>a cycle in would be created</li>
369          * </ul>
370          */ 
371         public void setLeftHandSide(Expression expression) {
372                 if (expression == null) {
373                         throw new IllegalArgumentException();
374                 }
375                 // an Assignment may occur inside a Expression - must check cycles
376                 ASTNode oldChild = this.leftHandSide;
377                 preReplaceChild(oldChild, expression, LEFT_HAND_SIDE_PROPERTY);
378                 this.leftHandSide = expression;
379                 postReplaceChild(oldChild, expression, LEFT_HAND_SIDE_PROPERTY);
380         }
381
382         /**
383          * Returns the right hand side of this assignment expression.
384          * 
385          * @return the right hand side node
386          */ 
387         public Expression getRightHandSide() {
388                 if (this.rightHandSide  == null) {
389                         // lazy init must be thread-safe for readers
390                         synchronized (this) {
391                                 if (this.rightHandSide == null) {
392                                         preLazyInit();
393                                         this.rightHandSide= new SimpleName(this.ast);
394                                         postLazyInit(this.rightHandSide, RIGHT_HAND_SIDE_PROPERTY);
395                                 }
396                         }
397                 }
398                 return this.rightHandSide;
399         }
400                 
401         /**
402          * Sets the right hand side of this assignment expression.
403          * 
404          * @param expression the right hand side node
405          * @exception IllegalArgumentException if:
406          * <ul>
407          * <li>the node belongs to a different AST</li>
408          * <li>the node already has a parent</li>
409          * <li>a cycle in would be created</li>
410          * </ul>
411          */ 
412         public void setRightHandSide(Expression expression) {
413                 if (expression == null) {
414                         throw new IllegalArgumentException();
415                 }
416                 // an Assignment may occur inside a Expression - must check cycles
417                 ASTNode oldChild = this.rightHandSide;
418                 preReplaceChild(oldChild, expression, RIGHT_HAND_SIDE_PROPERTY);
419                 this.rightHandSide = expression;
420                 postReplaceChild(oldChild, expression, RIGHT_HAND_SIDE_PROPERTY);
421         }
422
423         /* (omit javadoc for this method)
424          * Method declared on ASTNode.
425          */
426         int memSize() {
427                 // treat Code as free
428                 return BASE_NODE_SIZE + 3 * 4;
429         }
430         
431         /* (omit javadoc for this method)
432          * Method declared on ASTNode.
433          */
434         int treeSize() {
435                 return 
436                         memSize()
437                         + (this.leftHandSide == null ? 0 : getLeftHandSide().treeSize())
438                         + (this.rightHandSide == null ? 0 : getRightHandSide().treeSize());
439         }
440 }
441