EclipseJDT Source Viewer

Home|eclipse_jdt/src/org/eclipse/jdt/core/dom/FieldAccess.java
1/*******************************************************************************
2 * Copyright (c) 2000, 2019 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.List;
19
20/**
21 * Field access expression AST node type.
22 *
23 * <pre>
24 * FieldAccess:
25 *         Expression <b>.</b> Identifier
26 * </pre>
27 *
28 * <p>
29 * Note that there are several kinds of expressions that resemble field access
30 * expressions: qualified names, this expressions, and super field access
31 * expressions. The following guidelines help with correct usage:
32 * </p>
33 * <ul>
34 *   <li>An expression like "foo.this" can only be represented as a this
35 *   expression (<code>ThisExpression</code>) containing a simple name.
36 *   "this" is a keyword, and therefore invalid as an identifier.</li>
37 *   <li>An expression like "this.foo" can only be represented as a field
38 *   access expression (<code>FieldAccess</code>) containing a this expression
39 *   and a simple name. Again, this is because "this" is a keyword, and
40 *   therefore invalid as an identifier.</li>
41 *   <li>An expression with "super" can only be represented as a super field
42 *   access expression (<code>SuperFieldAccess</code>). "super" is a also
43 *   keyword, and therefore invalid as an identifier.</li>
44 *   <li>An expression like "foo.bar" can be represented either as a
45 *   qualified name (<code>QualifiedName</code>) or as a field access
46 *   expression (<code>FieldAccess</code>) containing simple names. Either
47 *   is acceptable, and there is no way to choose between them without
48 *   information about what the names resolve to
49 *   (<code>ASTParser</code> may return either).</li>
50 *   <li>Other expressions ending in an identifier, such as "foo().bar" can
51 *   only be represented as field access expressions
52 *   (<code>FieldAccess</code>).</li>
53 * </ul>
54 *
55 * @see QualifiedName
56 * @see ThisExpression
57 * @see SuperFieldAccess
58 * @since 2.0
59 * @noinstantiate This class is not intended to be instantiated by clients.
60 */
61@SuppressWarnings("rawtypes")
62public class FieldAccess extends Expression {
63
64    /**
65     * The "expression" structural property of this node type (child type: {@link Expression}).
66     * @since 3.0
67     */
68    public static final ChildPropertyDescriptor EXPRESSION_PROPERTY =
69        new ChildPropertyDescriptor(FieldAccess.class"expression"Expression.classMANDATORYCYCLE_RISK); //$NON-NLS-1$
70
71    /**
72     * The "name" structural property of this node type (child type: {@link SimpleName}).
73     * @since 3.0
74     */
75    public static final ChildPropertyDescriptor NAME_PROPERTY =
76        new ChildPropertyDescriptor(FieldAccess.class"name"SimpleName.classMANDATORYNO_CYCLE_RISK); //$NON-NLS-1$
77
78    /**
79     * A list of property descriptors (element type:
80     * {@link StructuralPropertyDescriptor}),
81     * or null if uninitialized.
82     */
83    private static final List PROPERTY_DESCRIPTORS;
84
85    static {
86        List properyList = new ArrayList(3);
87        createPropertyList(FieldAccess.classproperyList);
88        addProperty(EXPRESSION_PROPERTYproperyList);
89        addProperty(NAME_PROPERTYproperyList);
90        PROPERTY_DESCRIPTORS = reapPropertyList(properyList);
91    }
92
93    /**
94     * Returns a list of structural property descriptors for this node type.
95     * Clients must not modify the result.
96     *
97     * @param apiLevel the API level; one of the
98     * <code>AST.JLS*</code> constants
99
100     * @return a list of property descriptors (element type:
101     * {@link StructuralPropertyDescriptor})
102     * @since 3.0
103     */
104    public static List propertyDescriptors(int apiLevel) {
105        return PROPERTY_DESCRIPTORS;
106    }
107
108    /**
109     * The expression; lazily initialized; defaults to an unspecified,
110     * but legal, simple name.
111     */
112    private Expression expression = null;
113
114    /**
115     * The field; lazily initialized; defaults to an unspecified,
116     * but legal, simple field name.
117     */
118    private SimpleName fieldName = null;
119
120    /**
121     * Creates a new unparented node for a field access expression owned by the
122     * given AST. By default, the expression and field are both unspecified,
123     * but legal, names.
124     * <p>
125     * N.B. This constructor is package-private.
126     * </p>
127     *
128     * @param ast the AST that is to own this node
129     */
130    FieldAccess(AST ast) {
131        super(ast);
132    }
133
134    @Override
135    final List internalStructuralPropertiesForType(int apiLevel) {
136        return propertyDescriptors(apiLevel);
137    }
138
139    @Override
140    final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor propertyboolean getASTNode child) {
141        if (property == EXPRESSION_PROPERTY) {
142            if (get) {
143                return getExpression();
144            } else {
145                setExpression((Expressionchild);
146                return null;
147            }
148        }
149        if (property == NAME_PROPERTY) {
150            if (get) {
151                return getName();
152            } else {
153                setName((SimpleNamechild);
154                return null;
155            }
156        }
157        // allow default implementation to flag the error
158        return super.internalGetSetChildProperty(propertygetchild);
159    }
160
161    @Override
162    final int getNodeType0() {
163        return FIELD_ACCESS;
164    }
165
166    @Override
167    ASTNode clone0(AST target) {
168        FieldAccess result = new FieldAccess(target);
169        result.setSourceRange(getStartPosition(), getLength());
170        result.setExpression((ExpressiongetExpression().clone(target));
171        result.setName((SimpleNamegetName().clone(target));
172        return result;
173    }
174
175    @Override
176    final boolean subtreeMatch0(ASTMatcher matcherObject other) {
177        // dispatch to correct overloaded match method
178        return matcher.match(this, other);
179    }
180
181    @Override
182    void accept0(ASTVisitor visitor) {
183        boolean visitChildren = visitor.visit(this);
184        if (visitChildren) {
185            // visit children in normal left to right reading order
186            acceptChild(visitorgetExpression());
187            acceptChild(visitorgetName());
188        }
189        visitor.endVisit(this);
190    }
191
192    /**
193     * Returns the expression of this field access expression.
194     *
195     * @return the expression node
196     */
197    public Expression getExpression() {
198        if (this.expression == null) {
199            // lazy init must be thread-safe for readers
200            synchronized (this) {
201                if (this.expression == null) {
202                    preLazyInit();
203                    this.expression = new SimpleName(this.ast);
204                    postLazyInit(this.expressionEXPRESSION_PROPERTY);
205                }
206            }
207        }
208        return this.expression;
209    }
210
211    /**
212     * Sets the expression of this field access expression.
213     *
214     * @param expression the new expression
215     * @exception IllegalArgumentException if:
216     * <ul>
217     * <li>the node belongs to a different AST</li>
218     * <li>the node already has a parent</li>
219     * <li>a cycle in would be created</li>
220     * </ul>
221     */
222    public void setExpression(Expression expression) {
223        if (expression == null) {
224            throw new IllegalArgumentException();
225        }
226        ASTNode oldChild = this.expression;
227        preReplaceChild(oldChildexpressionEXPRESSION_PROPERTY);
228        this.expression = expression;
229        postReplaceChild(oldChildexpressionEXPRESSION_PROPERTY);
230    }
231
232    /**
233     * Returns the name of the field accessed in this field access expression.
234     *
235     * @return the field name
236     */
237    public SimpleName getName() {
238        if (this.fieldName == null) {
239            // lazy init must be thread-safe for readers
240            synchronized (this) {
241                if (this.fieldName == null) {
242                    preLazyInit();
243                    this.fieldName = new SimpleName(this.ast);
244                    postLazyInit(this.fieldNameNAME_PROPERTY);
245                }
246            }
247        }
248        return this.fieldName;
249    }
250
251    /**
252     * Sets the name of the field accessed in this field access expression.
253     *
254     * @param fieldName the field name
255     * @exception IllegalArgumentException if:
256     * <ul>
257     * <li>the node belongs to a different AST</li>
258     * <li>the node already has a parent</li>
259     * </ul>
260     */
261    public void setName(SimpleName fieldName) {
262        if (fieldName == null) {
263            throw new IllegalArgumentException();
264        }
265        ASTNode oldChild = this.fieldName;
266        preReplaceChild(oldChildfieldNameNAME_PROPERTY);
267        this.fieldName = fieldName;
268        postReplaceChild(oldChildfieldNameNAME_PROPERTY);
269    }
270
271    @Override
272    int memSize() {
273        // treat Code as free
274        return BASE_NODE_SIZE + 2 * 4;
275    }
276
277    /**
278     * Resolves and returns the binding for the field accessed by this
279     * expression.
280     * <p>
281     * Note that bindings are generally unavailable unless requested when the
282     * AST is being built.
283     * </p>
284     *
285     * @return the variable binding, or <code>null</code> if the binding cannot
286     * be resolved
287     * @since 3.0
288     */
289    public IVariableBinding resolveFieldBinding() {
290        return this.ast.getBindingResolver().resolveField(this);
291    }
292
293    @Override
294    int treeSize() {
295        return
296            memSize()
297            + (this.expression == null ? 0 : getExpression().treeSize())
298            + (this.fieldName == null ? 0 : getName().treeSize());
299    }
300}
301
302
MembersX
FieldAccess:NAME_PROPERTY
FieldAccess:fieldName
FieldAccess:setName:Block:oldChild
FieldAccess:getExpression
FieldAccess:FieldAccess
FieldAccess:internalStructuralPropertiesForType
FieldAccess:EXPRESSION_PROPERTY
FieldAccess:accept0
FieldAccess:subtreeMatch0
FieldAccess:internalGetSetChildProperty
FieldAccess:expression
FieldAccess:propertyDescriptors
FieldAccess:Block:properyList
FieldAccess:getName
FieldAccess:setName
FieldAccess:getNodeType0
FieldAccess:setExpression
FieldAccess:clone0
FieldAccess:PROPERTY_DESCRIPTORS
FieldAccess:accept0:Block:visitChildren
FieldAccess:memSize
FieldAccess:clone0:Block:result
FieldAccess:setExpression:Block:oldChild
FieldAccess:treeSize
FieldAccess:resolveFieldBinding
Members
X