EclipseJDT Source Viewer

Home|eclipse_jdt/src/org/eclipse/jdt/core/dom/InfixExpression.java
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
15package org.eclipse.jdt.core.dom;
16
17import java.util.ArrayList;
18import java.util.HashMap;
19import java.util.List;
20import java.util.Map;
21
22/**
23 * Infix expression AST node type.
24 * <pre>
25 * InfixExpression:
26 *    Expression InfixOperator Expression { InfixOperator Expression }
27 * </pre>
28 *
29 * @since 2.0
30 * @noinstantiate This class is not intended to be instantiated by clients.
31 */
32@SuppressWarnings({ "rawtypes""unchecked" })
33public class InfixExpression extends Expression {
34
35    /**
36      * Infix operators (typesafe enumeration).
37      * <pre>
38     * InfixOperator:<code>
39     *    <b>*</b>    TIMES
40     *    <b>/</b>  DIVIDE
41     *    <b>%</b>  REMAINDER
42     *    <b>+</b>  PLUS
43     *    <b>-</b>  MINUS
44     *    <b>&lt;&lt;</b>  LEFT_SHIFT
45     *    <b>&gt;&gt;</b>  RIGHT_SHIFT_SIGNED
46     *    <b>&gt;&gt;&gt;</b>  RIGHT_SHIFT_UNSIGNED
47     *    <b>&lt;</b>  LESS
48     *    <b>&gt;</b>  GREATER
49     *    <b>&lt;=</b>  LESS_EQUALS
50     *    <b>&gt;=</b>  GREATER_EQUALS
51     *    <b>==</b>  EQUALS
52     *    <b>!=</b>  NOT_EQUALS
53     *    <b>^</b>  XOR
54     *    <b>&amp;</b>  AND
55     *    <b>|</b>  OR
56     *    <b>&amp;&amp;</b>  CONDITIONAL_AND
57     *    <b>||</b>  CONDITIONAL_OR</code>
58     * </pre>
59     */
60    public static class Operator {
61
62        /**
63         * The token for the operator.
64         */
65        private String token;
66
67        /**
68         * Creates a new infix operator with the given token.
69         * <p>
70         * Note: this constructor is private. The only instances
71         * ever created are the ones for the standard operators.
72         * </p>
73         *
74         * @param token the character sequence for the operator
75         */
76        private Operator(String token) {
77            this.token = token;
78        }
79
80        /**
81         * Returns the character sequence for the operator.
82         *
83         * @return the character sequence for the operator
84         */
85        @Override
86        public String toString() {
87            return this.token;
88        }
89
90        /** Multiplication "*" operator. */
91        public static final Operator TIMES = new Operator("*");//$NON-NLS-1$
92        /** Division "/" operator. */
93        public static final Operator DIVIDE = new Operator("/");//$NON-NLS-1$
94        /** Remainder "%" operator. */
95        public static final Operator REMAINDER = new Operator("%");//$NON-NLS-1$
96        /** Addition (or string concatenation) "+" operator. */
97        public static final Operator PLUS = new Operator("+");//$NON-NLS-1$
98        /** Subtraction "-" operator. */
99        public static final Operator MINUS = new Operator("-");//$NON-NLS-1$
100        /** Left shift "&lt;&lt;" operator. */
101        public static final Operator LEFT_SHIFT = new Operator("<<");//$NON-NLS-1$
102        /** Signed right shift "&gt;&gt;" operator. */
103        public static final Operator RIGHT_SHIFT_SIGNED = new Operator(">>");//$NON-NLS-1$
104        /** Unsigned right shift "&gt;&gt;&gt;" operator. */
105        public static final Operator RIGHT_SHIFT_UNSIGNED =
106            new Operator(">>>");//$NON-NLS-1$
107        /** Less than "&lt;" operator. */
108        public static final Operator LESS = new Operator("<");//$NON-NLS-1$
109        /** Greater than "&gt;" operator. */
110        public static final Operator GREATER = new Operator(">");//$NON-NLS-1$
111        /** Less than or equals "&lt;=" operator. */
112        public static final Operator LESS_EQUALS = new Operator("<=");//$NON-NLS-1$
113        /** Greater than or equals "&gt=;" operator. */
114        public static final Operator GREATER_EQUALS = new Operator(">=");//$NON-NLS-1$
115        /** Equals "==" operator. */
116        public static final Operator EQUALS = new Operator("==");//$NON-NLS-1$
117        /** Not equals "!=" operator. */
118        public static final Operator NOT_EQUALS = new Operator("!=");//$NON-NLS-1$
119        /** Exclusive OR "^" operator. */
120        public static final Operator XOR = new Operator("^");//$NON-NLS-1$
121        /** Inclusive OR "|" operator. */
122        public static final Operator OR = new Operator("|");//$NON-NLS-1$
123        /** AND "&amp;" operator. */
124        public static final Operator AND = new Operator("&");//$NON-NLS-1$
125        /** Conditional OR "||" operator. */
126        public static final Operator CONDITIONAL_OR = new Operator("||");//$NON-NLS-1$
127        /** Conditional AND "&amp;&amp;" operator. */
128        public static final Operator CONDITIONAL_AND = new Operator("&&");//$NON-NLS-1$
129
130        /**
131         * Map from token to operator (key type: <code>String</code>;
132         * value type: <code>Operator</code>).
133         */
134        private static final Map CODES;
135        static {
136            CODES = new HashMap(20);
137            Operator[] ops = {
138                    TIMES,
139                    DIVIDE,
140                    REMAINDER,
141                    PLUS,
142                    MINUS,
143                    LEFT_SHIFT,
144                    RIGHT_SHIFT_SIGNED,
145                    RIGHT_SHIFT_UNSIGNED,
146                    LESS,
147                    GREATER,
148                    LESS_EQUALS,
149                    GREATER_EQUALS,
150                    EQUALS,
151                    NOT_EQUALS,
152                    XOR,
153                    OR,
154                    AND,
155                    CONDITIONAL_OR,
156                    CONDITIONAL_AND,
157                };
158            for (int i = 0i < ops.lengthi++) {
159                CODES.put(ops[i].toString(), ops[i]);
160            }
161        }
162
163        /**
164         * Returns the infix operator corresponding to the given string,
165         * or <code>null</code> if none.
166         * <p>
167         * <code>toOperator</code> is the converse of <code>toString</code>:
168         * that is, <code>Operator.toOperator(op.toString()) == op</code> for
169         * all operators <code>op</code>.
170         * </p>
171         *
172         * @param token the character sequence for the operator
173         * @return the infix operator, or <code>null</code> if none
174         */
175        public static Operator toOperator(String token) {
176            return (OperatorCODES.get(token);
177        }
178
179    }
180
181    /**
182     * The "leftOperand" structural property of this node type (child type: {@link Expression}).
183     * @since 3.0
184     */
185    public static final ChildPropertyDescriptor LEFT_OPERAND_PROPERTY =
186        new ChildPropertyDescriptor(InfixExpression.class"leftOperand"Expression.classMANDATORYCYCLE_RISK); //$NON-NLS-1$
187
188    /**
189     * The "operator" structural property of this node type (type: {@link InfixExpression.Operator}).
190     * @since 3.0
191     */
192    public static final SimplePropertyDescriptor OPERATOR_PROPERTY =
193        new SimplePropertyDescriptor(InfixExpression.class"operator"InfixExpression.Operator.class, MANDATORY); //$NON-NLS-1$
194
195    /**
196     * The "rightOperand" structural property of this node type (child type: {@link Expression}).
197     * @since 3.0
198     */
199    public static final ChildPropertyDescriptor RIGHT_OPERAND_PROPERTY =
200        new ChildPropertyDescriptor(InfixExpression.class"rightOperand"Expression.classMANDATORYCYCLE_RISK); //$NON-NLS-1$
201
202    /**
203     * The "extendedOperands" structural property of this node type (element type: {@link Expression}).
204     * @since 3.0
205     */
206    public static final ChildListPropertyDescriptor EXTENDED_OPERANDS_PROPERTY =
207        new ChildListPropertyDescriptor(InfixExpression.class"extendedOperands"Expression.classCYCLE_RISK); //$NON-NLS-1$
208
209    /**
210     * A list of property descriptors (element type:
211     * {@link StructuralPropertyDescriptor}),
212     * or null if uninitialized.
213     */
214    private static final List PROPERTY_DESCRIPTORS;
215
216    static {
217        List properyList = new ArrayList(5);
218        createPropertyList(InfixExpression.classproperyList);
219        addProperty(LEFT_OPERAND_PROPERTYproperyList);
220        addProperty(OPERATOR_PROPERTYproperyList);
221        addProperty(RIGHT_OPERAND_PROPERTYproperyList);
222        addProperty(EXTENDED_OPERANDS_PROPERTYproperyList);
223        PROPERTY_DESCRIPTORS = reapPropertyList(properyList);
224    }
225
226    /**
227     * Returns a list of structural property descriptors for this node type.
228     * Clients must not modify the result.
229     *
230     * @param apiLevel the API level; one of the
231     * <code>AST.JLS*</code> constants
232
233     * @return a list of property descriptors (element type:
234     * {@link StructuralPropertyDescriptor})
235     * @since 3.0
236     */
237    public static List propertyDescriptors(int apiLevel) {
238        return PROPERTY_DESCRIPTORS;
239    }
240
241    /**
242     * The infix operator; defaults to InfixExpression.Operator.PLUS.
243     */
244    private InfixExpression.Operator operator = InfixExpression.Operator.PLUS;
245
246    /**
247     * The left operand; lazily initialized; defaults to an unspecified,
248     * but legal, simple name.
249     */
250    private Expression leftOperand = null;
251
252    /**
253     * The right operand; lazily initialized; defaults to an unspecified,
254     * but legal, simple name.
255     */
256    private Expression rightOperand = null;
257
258    /**
259     * The list of extended operand expressions (element type:
260     * {@link Expression}). Lazily initialized; defaults to an empty list.
261     */
262    private ASTNode.NodeList extendedOperands = null;
263
264    /**
265     * Creates a new AST node for an infix expression owned by the given
266     * AST. By default, the node has unspecified (but legal) operator,
267     * left and right operands, and an empty list of additional operands.
268     *
269     * @param ast the AST that is to own this node
270     */
271    InfixExpression(AST ast) {
272        super(ast);
273    }
274
275    @Override
276    final List internalStructuralPropertiesForType(int apiLevel) {
277        return propertyDescriptors(apiLevel);
278    }
279
280    @Override
281    final Object internalGetSetObjectProperty(SimplePropertyDescriptor propertyboolean getObject value) {
282        if (property == OPERATOR_PROPERTY) {
283            if (get) {
284                return getOperator();
285            } else {
286                setOperator((Operatorvalue);
287                return null;
288            }
289        }
290        // allow default implementation to flag the error
291        return super.internalGetSetObjectProperty(propertygetvalue);
292    }
293
294    @Override
295    final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor propertyboolean getASTNode child) {
296        if (property == LEFT_OPERAND_PROPERTY) {
297            if (get) {
298                return getLeftOperand();
299            } else {
300                setLeftOperand((Expressionchild);
301                return null;
302            }
303        }
304        if (property == RIGHT_OPERAND_PROPERTY) {
305            if (get) {
306                return getRightOperand();
307            } else {
308                setRightOperand((Expressionchild);
309                return null;
310            }
311        }
312        // allow default implementation to flag the error
313        return super.internalGetSetChildProperty(propertygetchild);
314    }
315
316    @Override
317    final List internalGetChildListProperty(ChildListPropertyDescriptor property) {
318        if (property == EXTENDED_OPERANDS_PROPERTY) {
319            return extendedOperands();
320        }
321        // allow default implementation to flag the error
322        return super.internalGetChildListProperty(property);
323    }
324
325    @Override
326    final int getNodeType0() {
327        return INFIX_EXPRESSION;
328    }
329
330    @Override
331    ASTNode clone0(AST target) {
332        InfixExpression result = new InfixExpression(target);
333        result.setSourceRange(getStartPosition(), getLength());
334        result.setOperator(getOperator());
335        result.setLeftOperand((ExpressiongetLeftOperand().clone(target));
336        result.setRightOperand((ExpressiongetRightOperand().clone(target));
337        if (this.extendedOperands != null) {
338            // be careful not to trigger lazy creation of list
339            result.extendedOperands().addAll(
340                ASTNode.copySubtrees(targetextendedOperands()));
341        }
342        return result;
343    }
344
345    @Override
346    final boolean subtreeMatch0(ASTMatcher matcherObject other) {
347        // dispatch to correct overloaded match method
348        return matcher.match(this, other);
349    }
350
351    @Override
352    void accept0(ASTVisitor visitor) {
353        boolean visitChildren = visitor.visit(this);
354        if (visitChildren) {
355            // visit children in normal left to right reading order
356            acceptChild(visitorgetLeftOperand());
357            acceptChild(visitorgetRightOperand());
358            if (this.extendedOperands != null) {
359                // be careful not to trigger lazy creation of list
360                acceptChildren(visitor, this.extendedOperands);
361            }
362        }
363        visitor.endVisit(this);
364    }
365
366    /**
367     * Returns the operator of this infix expression.
368     *
369     * @return the infix operator
370     */
371    public InfixExpression.Operator getOperator() {
372        return this.operator;
373    }
374
375    /**
376     * Sets the operator of this infix expression.
377     *
378     * @param operator the infix operator
379     * @exception IllegalArgumentException if the argument is incorrect
380     */
381    public void setOperator(InfixExpression.Operator operator) {
382        if (operator == null) {
383            throw new IllegalArgumentException();
384        }
385        preValueChange(OPERATOR_PROPERTY);
386        this.operator = operator;
387        postValueChange(OPERATOR_PROPERTY);
388    }
389
390    /**
391     * Returns the left operand of this infix expression.
392     *
393     * @return the left operand node
394     */
395    public Expression getLeftOperand() {
396        if (this.leftOperand  == null) {
397            // lazy init must be thread-safe for readers
398            synchronized (this) {
399                if (this.leftOperand == null) {
400                    preLazyInit();
401                    this.leftOperand= new SimpleName(this.ast);
402                    postLazyInit(this.leftOperandLEFT_OPERAND_PROPERTY);
403                }
404            }
405        }
406        return this.leftOperand;
407    }
408
409    /**
410     * Sets the left operand of this infix expression.
411     *
412     * @param expression the left operand node
413     * @exception IllegalArgumentException if:
414     * <ul>
415     * <li>the node belongs to a different AST</li>
416     * <li>the node already has a parent</li>
417     * <li>a cycle in would be created</li>
418     * </ul>
419     */
420    public void setLeftOperand(Expression expression) {
421        if (expression == null) {
422            throw new IllegalArgumentException();
423        }
424        ASTNode oldChild = this.leftOperand;
425        preReplaceChild(oldChildexpressionLEFT_OPERAND_PROPERTY);
426        this.leftOperand = expression;
427        postReplaceChild(oldChildexpressionLEFT_OPERAND_PROPERTY);
428    }
429
430    /**
431     * Returns the right operand of this infix expression.
432     *
433     * @return the right operand node
434     */
435    public Expression getRightOperand() {
436        if (this.rightOperand  == null) {
437            // lazy init must be thread-safe for readers
438            synchronized (this) {
439                if (this.rightOperand  == null) {
440                    preLazyInit();
441                    this.rightOperand= new SimpleName(this.ast);
442                    postLazyInit(this.rightOperandRIGHT_OPERAND_PROPERTY);
443                }
444            }
445        }
446        return this.rightOperand;
447    }
448
449    /**
450     * Sets the right operand of this infix expression.
451     *
452     * @param expression the right operand node
453     * @exception IllegalArgumentException if:
454     * <ul>
455     * <li>the node belongs to a different AST</li>
456     * <li>the node already has a parent</li>
457     * <li>a cycle in would be created</li>
458     * </ul>
459     */
460    public void setRightOperand(Expression expression) {
461        if (expression == null) {
462            throw new IllegalArgumentException();
463        }
464        ASTNode oldChild = this.rightOperand;
465        preReplaceChild(oldChildexpressionRIGHT_OPERAND_PROPERTY);
466        this.rightOperand = expression;
467        postReplaceChild(oldChildexpressionRIGHT_OPERAND_PROPERTY);
468    }
469
470    /**
471     * Returns where there are any extended operands.
472     *
473     * @return <code>true</code> if there are one or more extended operands,
474     *    and <code>false</code> if there are no extended operands
475     */
476    public boolean hasExtendedOperands() {
477        return
478            (this.extendedOperands != null) && this.extendedOperands.size() > 0;
479    }
480
481    /**
482     * Returns the live list of extended operands.
483     * <p>
484     * The extended operands is the preferred way of representing deeply nested
485     * expressions of the form <code>L op R op R2 op R3...</code> where
486     * the same operator appears between all the operands (the most
487     * common case being lengthy string concatenation expressions). Using
488     * the extended operands keeps the trees from getting too deep; this
489     * decreases the risk is running out of thread stack space at runtime
490     * when traversing such trees.
491     * ((a + b) + c) + d would be translated to:
492     *     leftOperand: a
493     *     rightOperand: b
494     *     extendedOperands: {c, d}
495     *     operator: +
496     * </p>
497     *
498     * @return the live list of extended operands
499     *   (element type: {@link Expression})
500     */
501    public List extendedOperands() {
502        if (this.extendedOperands == null) {
503            // lazily initialize
504            this.extendedOperands = new ASTNode.NodeList(EXTENDED_OPERANDS_PROPERTY);
505        }
506        return this.extendedOperands;
507    }
508
509    @Override
510    int memSize() {
511        // treat Operator as free
512        return BASE_NODE_SIZE + 4 * 4;
513    }
514
515    @Override
516    int treeSize() {
517        return
518            memSize()
519            + (this.leftOperand == null ? 0 : getLeftOperand().treeSize())
520            + (this.rightOperand == null ? 0 : getRightOperand().treeSize())
521            + (this.extendedOperands == null ? 0 : this.extendedOperands.listSize());
522    }
523}
524
MembersX
InfixExpression:Operator:RIGHT_SHIFT_SIGNED
InfixExpression:internalGetSetObjectProperty
InfixExpression:Block:properyList
InfixExpression:getRightOperand
InfixExpression:Operator:LESS
InfixExpression:Operator:REMAINDER
InfixExpression:Operator:CODES
InfixExpression:Operator:PLUS
InfixExpression:setRightOperand:Block:oldChild
InfixExpression:Operator:GREATER
InfixExpression:Operator:EQUALS
InfixExpression:Operator:CONDITIONAL_OR
InfixExpression:setLeftOperand:Block:oldChild
InfixExpression:operator
InfixExpression:accept0:Block:visitChildren
InfixExpression:treeSize
InfixExpression:Operator:OR
InfixExpression:extendedOperands
InfixExpression:PROPERTY_DESCRIPTORS
InfixExpression:setOperator
InfixExpression:EXTENDED_OPERANDS_PROPERTY
InfixExpression:internalGetChildListProperty
InfixExpression:clone0:Block:result
InfixExpression:Operator:MINUS
InfixExpression:Operator:NOT_EQUALS
InfixExpression:Operator:DIVIDE
InfixExpression:RIGHT_OPERAND_PROPERTY
InfixExpression:Operator:AND
InfixExpression:Operator:TIMES
InfixExpression:setRightOperand
InfixExpression:internalStructuralPropertiesForType
InfixExpression:Operator:toString
InfixExpression:Operator:LESS_EQUALS
InfixExpression:Operator:XOR
InfixExpression:Operator:CONDITIONAL_AND
InfixExpression:memSize
InfixExpression:accept0
InfixExpression:getLeftOperand
InfixExpression:LEFT_OPERAND_PROPERTY
InfixExpression:clone0
InfixExpression:leftOperand
InfixExpression:rightOperand
InfixExpression:Operator:LEFT_SHIFT
InfixExpression:Operator:token
InfixExpression:Operator:GREATER_EQUALS
InfixExpression:InfixExpression
InfixExpression:propertyDescriptors
InfixExpression:Operator:toOperator
InfixExpression:Operator:RIGHT_SHIFT_UNSIGNED
InfixExpression:OPERATOR_PROPERTY
InfixExpression:getOperator
InfixExpression:Operator:Block:ops
InfixExpression:setLeftOperand
InfixExpression:hasExtendedOperands
InfixExpression:internalGetSetChildProperty
InfixExpression:getNodeType0
InfixExpression:Operator:Operator
InfixExpression:subtreeMatch0
Members
X