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.List; |
19 | |
20 | |
21 | /** |
22 | * AST node for a qualified name. A qualified name is defined recursively |
23 | * as a simple name preceded by a name, which qualifies it. Expressing it this |
24 | * way means that the qualifier and the simple name get their own AST nodes. |
25 | * <pre> |
26 | * QualifiedName: |
27 | * Name <b>.</b> SimpleName |
28 | * </pre> |
29 | * <p> |
30 | * See <code>FieldAccess</code> for guidelines on handling other expressions |
31 | * that resemble qualified names. |
32 | * </p> |
33 | * |
34 | * @see FieldAccess |
35 | * @since 2.0 |
36 | * @noinstantiate This class is not intended to be instantiated by clients. |
37 | */ |
38 | @SuppressWarnings("rawtypes") |
39 | public class QualifiedName extends Name { |
40 | |
41 | /** |
42 | * The "qualifier" structural property of this node type (child type: {@link Name}). |
43 | * @since 3.0 |
44 | */ |
45 | public static final ChildPropertyDescriptor QUALIFIER_PROPERTY = |
46 | new ChildPropertyDescriptor(QualifiedName.class, "qualifier", Name.class, MANDATORY, CYCLE_RISK); //$NON-NLS-1$ |
47 | |
48 | /** |
49 | * The "name" structural property of this node type (child type: {@link SimpleName}). |
50 | * @since 3.0 |
51 | */ |
52 | public static final ChildPropertyDescriptor NAME_PROPERTY = |
53 | new ChildPropertyDescriptor(QualifiedName.class, "name", SimpleName.class, MANDATORY, NO_CYCLE_RISK); //$NON-NLS-1$ |
54 | |
55 | /** |
56 | * A list of property descriptors (element type: |
57 | * {@link StructuralPropertyDescriptor}), |
58 | * or null if uninitialized. |
59 | */ |
60 | private static final List PROPERTY_DESCRIPTORS; |
61 | |
62 | static { |
63 | List propertyList = new ArrayList(3); |
64 | createPropertyList(QualifiedName.class, propertyList); |
65 | addProperty(QUALIFIER_PROPERTY, propertyList); |
66 | addProperty(NAME_PROPERTY, propertyList); |
67 | PROPERTY_DESCRIPTORS = reapPropertyList(propertyList); |
68 | } |
69 | |
70 | /** |
71 | * Returns a list of structural property descriptors for this node type. |
72 | * Clients must not modify the result. |
73 | * |
74 | * @param apiLevel the API level; one of the |
75 | * <code>AST.JLS*</code> constants |
76 | * @return a list of property descriptors (element type: |
77 | * {@link StructuralPropertyDescriptor}) |
78 | * @since 3.0 |
79 | */ |
80 | public static List propertyDescriptors(int apiLevel) { |
81 | return PROPERTY_DESCRIPTORS; |
82 | } |
83 | |
84 | /** |
85 | * The identifier; lazily initialized; defaults to a unspecified, legal |
86 | * Java identifier. |
87 | */ |
88 | private Name qualifier = null; |
89 | |
90 | /** |
91 | * The name being qualified; lazily initialized; defaults to a unspecified, |
92 | * legal Java identifier. |
93 | */ |
94 | private SimpleName name = null; |
95 | |
96 | /** |
97 | * Creates a new AST node for a qualified name owned by the given AST. |
98 | * <p> |
99 | * N.B. This constructor is package-private; all subclasses must be |
100 | * declared in the same package; clients are unable to declare |
101 | * additional subclasses. |
102 | * </p> |
103 | * |
104 | * @param ast the AST that is to own this node |
105 | */ |
106 | QualifiedName(AST ast) { |
107 | super(ast); |
108 | } |
109 | |
110 | @Override |
111 | final List internalStructuralPropertiesForType(int apiLevel) { |
112 | return propertyDescriptors(apiLevel); |
113 | } |
114 | |
115 | @Override |
116 | final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) { |
117 | if (property == QUALIFIER_PROPERTY) { |
118 | if (get) { |
119 | return getQualifier(); |
120 | } else { |
121 | setQualifier((Name) child); |
122 | return null; |
123 | } |
124 | } |
125 | if (property == NAME_PROPERTY) { |
126 | if (get) { |
127 | return getName(); |
128 | } else { |
129 | setName((SimpleName) child); |
130 | return null; |
131 | } |
132 | } |
133 | // allow default implementation to flag the error |
134 | return super.internalGetSetChildProperty(property, get, child); |
135 | } |
136 | |
137 | @Override |
138 | final int getNodeType0() { |
139 | return QUALIFIED_NAME; |
140 | } |
141 | |
142 | @Override |
143 | ASTNode clone0(AST target) { |
144 | QualifiedName result = new QualifiedName(target); |
145 | result.setSourceRange(getStartPosition(), getLength()); |
146 | result.setQualifier((Name) getQualifier().clone(target)); |
147 | result.setName((SimpleName) getName().clone(target)); |
148 | return result; |
149 | } |
150 | |
151 | @Override |
152 | final boolean subtreeMatch0(ASTMatcher matcher, Object other) { |
153 | // dispatch to correct overloaded match method |
154 | return matcher.match(this, other); |
155 | } |
156 | |
157 | @Override |
158 | void accept0(ASTVisitor visitor) { |
159 | boolean visitChildren = visitor.visit(this); |
160 | if (visitChildren) { |
161 | // visit children in normal left to right reading order |
162 | acceptChild(visitor, getQualifier()); |
163 | acceptChild(visitor, getName()); |
164 | } |
165 | visitor.endVisit(this); |
166 | } |
167 | |
168 | /** |
169 | * Returns the qualifier part of this qualified name. |
170 | * |
171 | * @return the qualifier part of this qualified name |
172 | */ |
173 | public Name getQualifier() { |
174 | if (this.qualifier == null) { |
175 | // lazy init must be thread-safe for readers |
176 | synchronized (this) { |
177 | if (this.qualifier == null) { |
178 | preLazyInit(); |
179 | this.qualifier = new SimpleName(this.ast); |
180 | postLazyInit(this.qualifier, QUALIFIER_PROPERTY); |
181 | } |
182 | } |
183 | } |
184 | return this.qualifier; |
185 | } |
186 | |
187 | /** |
188 | * Sets the qualifier of this qualified name to the given name. |
189 | * |
190 | * @param qualifier the qualifier of this qualified name |
191 | * @exception IllegalArgumentException if: |
192 | * <ul> |
193 | * <li>the node belongs to a different AST</li> |
194 | * <li>the node already has a parent</li> |
195 | * <li>a cycle in would be created</li> |
196 | * </ul> |
197 | */ |
198 | public void setQualifier(Name qualifier) { |
199 | if (qualifier == null) { |
200 | throw new IllegalArgumentException(); |
201 | } |
202 | ASTNode oldChild = this.qualifier; |
203 | preReplaceChild(oldChild, qualifier, QUALIFIER_PROPERTY); |
204 | this.qualifier = qualifier; |
205 | postReplaceChild(oldChild, qualifier, QUALIFIER_PROPERTY); |
206 | } |
207 | |
208 | /** |
209 | * Returns the name part of this qualified name. |
210 | * |
211 | * @return the name being qualified |
212 | */ |
213 | public SimpleName getName() { |
214 | if (this.name == null) { |
215 | // lazy init must be thread-safe for readers |
216 | synchronized (this) { |
217 | if (this.name == null) { |
218 | preLazyInit(); |
219 | this.name = new SimpleName(this.ast); |
220 | postLazyInit(this.name, NAME_PROPERTY); |
221 | } |
222 | } |
223 | } |
224 | return this.name; |
225 | } |
226 | |
227 | /** |
228 | * Sets the name part of this qualified name to the given simple name. |
229 | * |
230 | * @param name the identifier of this qualified name |
231 | * @exception IllegalArgumentException if: |
232 | * <ul> |
233 | * <li>the node belongs to a different AST</li> |
234 | * <li>the node already has a parent</li> |
235 | * </ul> |
236 | */ |
237 | public void setName(SimpleName name) { |
238 | if (name == null) { |
239 | throw new IllegalArgumentException(); |
240 | } |
241 | ASTNode oldChild = this.name; |
242 | preReplaceChild(oldChild, name, NAME_PROPERTY); |
243 | this.name = name; |
244 | postReplaceChild(oldChild, name, NAME_PROPERTY); |
245 | } |
246 | |
247 | @Override |
248 | void appendName(StringBuffer buffer) { |
249 | getQualifier().appendName(buffer); |
250 | buffer.append('.'); |
251 | getName().appendName(buffer); |
252 | } |
253 | |
254 | @Override |
255 | int memSize() { |
256 | return BASE_NAME_NODE_SIZE + 3 * 4; |
257 | } |
258 | |
259 | @Override |
260 | int treeSize() { |
261 | return |
262 | memSize() |
263 | + (this.name == null ? 0 : getName().treeSize()) |
264 | + (this.qualifier == null ? 0 : getQualifier().treeSize()); |
265 | } |
266 | } |
267 | |
268 |
Members