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