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 | * Package declaration AST node type. |
22 | * <pre> |
23 | * PackageDeclaration: |
24 | * [ Javadoc ] { Annotation } <b>package</b> Name <b>;</b> |
25 | * </pre> |
26 | * Note that the standard AST parser only recognizes a Javadoc comment |
27 | * immediately preceding the package declaration when it occurs in the |
28 | * special <code>package-info.java</code> compilation unit (JLS3 7.4.1.1). |
29 | * The Javadoc comment in that file contains the package description. |
30 | * |
31 | * @since 2.0 |
32 | * @noinstantiate This class is not intended to be instantiated by clients. |
33 | */ |
34 | @SuppressWarnings({"rawtypes", "unchecked"}) |
35 | public class PackageDeclaration extends ASTNode { |
36 | |
37 | /** |
38 | * The "javadoc" structural property of this node type (child type: {@link Javadoc}) (added in JLS3 API). |
39 | * @since 3.0 |
40 | */ |
41 | public static final ChildPropertyDescriptor JAVADOC_PROPERTY = |
42 | new ChildPropertyDescriptor(PackageDeclaration.class, "javadoc", Javadoc.class, OPTIONAL, NO_CYCLE_RISK); //$NON-NLS-1$ |
43 | |
44 | /** |
45 | * The "annotations" structural property of this node type (element type: {@link Annotation}) (added in JLS3 API). |
46 | * @since 3.1 |
47 | */ |
48 | public static final ChildListPropertyDescriptor ANNOTATIONS_PROPERTY = |
49 | new ChildListPropertyDescriptor(PackageDeclaration.class, "annotations", Annotation.class, CYCLE_RISK); //$NON-NLS-1$ |
50 | |
51 | /** |
52 | * The "name" structural property of this node type (child type: {@link Name}). |
53 | * @since 3.0 |
54 | */ |
55 | public static final ChildPropertyDescriptor NAME_PROPERTY = |
56 | new ChildPropertyDescriptor(PackageDeclaration.class, "name", Name.class, MANDATORY, NO_CYCLE_RISK); //$NON-NLS-1$ |
57 | |
58 | /** |
59 | * A list of property descriptors (element type: |
60 | * {@link StructuralPropertyDescriptor}), |
61 | * or null if uninitialized. |
62 | * @since 3.0 |
63 | */ |
64 | private static final List PROPERTY_DESCRIPTORS_2_0; |
65 | |
66 | /** |
67 | * A list of property descriptors (element type: |
68 | * {@link StructuralPropertyDescriptor}), |
69 | * or null if uninitialized. |
70 | * @since 3.1 |
71 | */ |
72 | private static final List PROPERTY_DESCRIPTORS_3_0; |
73 | |
74 | static { |
75 | List propertyList = new ArrayList(2); |
76 | createPropertyList(PackageDeclaration.class, propertyList); |
77 | addProperty(NAME_PROPERTY, propertyList); |
78 | PROPERTY_DESCRIPTORS_2_0 = reapPropertyList(propertyList); |
79 | |
80 | propertyList = new ArrayList(4); |
81 | createPropertyList(PackageDeclaration.class, propertyList); |
82 | addProperty(JAVADOC_PROPERTY, propertyList); |
83 | addProperty(ANNOTATIONS_PROPERTY, propertyList); |
84 | addProperty(NAME_PROPERTY, propertyList); |
85 | PROPERTY_DESCRIPTORS_3_0 = reapPropertyList(propertyList); |
86 | } |
87 | |
88 | /** |
89 | * Returns a list of structural property descriptors for this node type. |
90 | * Clients must not modify the result. |
91 | * |
92 | * @param apiLevel the API level; one of the |
93 | * <code>AST.JLS*</code> constants |
94 | |
95 | * @return a list of property descriptors (element type: |
96 | * {@link StructuralPropertyDescriptor}) |
97 | * @since 3.0 |
98 | */ |
99 | public static List propertyDescriptors(int apiLevel) { |
100 | if (apiLevel == AST.JLS2_INTERNAL) { |
101 | return PROPERTY_DESCRIPTORS_2_0; |
102 | } else { |
103 | return PROPERTY_DESCRIPTORS_3_0; |
104 | } |
105 | } |
106 | |
107 | /** |
108 | * The doc comment, or <code>null</code> if none. |
109 | * Defaults to none. |
110 | * @since 3.0 |
111 | */ |
112 | Javadoc optionalDocComment = null; |
113 | |
114 | /** |
115 | * The annotations (element type: {@link Annotation}). |
116 | * Null in JLS2. Added in JLS3; defaults to an empty list |
117 | * (see constructor). |
118 | * @since 3.1 |
119 | */ |
120 | private ASTNode.NodeList annotations = null; |
121 | |
122 | /** |
123 | * The package name; lazily initialized; defaults to a unspecified, |
124 | * legal Java package identifier. |
125 | */ |
126 | private Name packageName = null; |
127 | |
128 | /** |
129 | * Creates a new AST node for a package declaration owned by the |
130 | * given AST. The package declaration initially has an unspecified, |
131 | * but legal, Java identifier; and an empty list of annotations. |
132 | * <p> |
133 | * N.B. This constructor is package-private; all subclasses must be |
134 | * declared in the same package; clients are unable to declare |
135 | * additional subclasses. |
136 | * </p> |
137 | * |
138 | * @param ast the AST that is to own this node |
139 | */ |
140 | PackageDeclaration(AST ast) { |
141 | super(ast); |
142 | if (ast.apiLevel >= AST.JLS3_INTERNAL) { |
143 | this.annotations = new ASTNode.NodeList(ANNOTATIONS_PROPERTY); |
144 | } |
145 | } |
146 | |
147 | @Override |
148 | final List internalStructuralPropertiesForType(int apiLevel) { |
149 | return propertyDescriptors(apiLevel); |
150 | } |
151 | |
152 | @Override |
153 | final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) { |
154 | if (property == JAVADOC_PROPERTY) { |
155 | if (get) { |
156 | return getJavadoc(); |
157 | } else { |
158 | setJavadoc((Javadoc) child); |
159 | return null; |
160 | } |
161 | } |
162 | if (property == NAME_PROPERTY) { |
163 | if (get) { |
164 | return getName(); |
165 | } else { |
166 | setName((Name) child); |
167 | return null; |
168 | } |
169 | } |
170 | // allow default implementation to flag the error |
171 | return super.internalGetSetChildProperty(property, get, child); |
172 | } |
173 | |
174 | @Override |
175 | final List internalGetChildListProperty(ChildListPropertyDescriptor property) { |
176 | if (property == ANNOTATIONS_PROPERTY) { |
177 | return annotations(); |
178 | } |
179 | // allow default implementation to flag the error |
180 | return super.internalGetChildListProperty(property); |
181 | } |
182 | |
183 | @Override |
184 | final int getNodeType0() { |
185 | return PACKAGE_DECLARATION; |
186 | } |
187 | |
188 | @Override |
189 | ASTNode clone0(AST target) { |
190 | PackageDeclaration result = new PackageDeclaration(target); |
191 | result.setSourceRange(getStartPosition(), getLength()); |
192 | if (this.ast.apiLevel >= AST.JLS3_INTERNAL) { |
193 | result.setJavadoc((Javadoc) ASTNode.copySubtree(target, getJavadoc())); |
194 | result.annotations().addAll(ASTNode.copySubtrees(target, annotations())); |
195 | } |
196 | result.setName((Name) getName().clone(target)); |
197 | return result; |
198 | } |
199 | |
200 | @Override |
201 | final boolean subtreeMatch0(ASTMatcher matcher, Object other) { |
202 | // dispatch to correct overloaded match method |
203 | return matcher.match(this, other); |
204 | } |
205 | |
206 | @Override |
207 | void accept0(ASTVisitor visitor) { |
208 | boolean visitChildren = visitor.visit(this); |
209 | if (visitChildren) { |
210 | if (this.ast.apiLevel >= AST.JLS3_INTERNAL) { |
211 | acceptChild(visitor, getJavadoc()); |
212 | acceptChildren(visitor, this.annotations); |
213 | } |
214 | acceptChild(visitor, getName()); |
215 | } |
216 | visitor.endVisit(this); |
217 | } |
218 | |
219 | /** |
220 | * Returns the live ordered list of annotations of this |
221 | * package declaration (added in JLS3 API). |
222 | * |
223 | * @return the live list of annotations |
224 | * (element type: {@link Annotation}) |
225 | * @exception UnsupportedOperationException if this operation is used in |
226 | * a JLS2 AST |
227 | * @since 3.1 |
228 | */ |
229 | public List annotations() { |
230 | // more efficient than just calling unsupportedIn2() to check |
231 | if (this.annotations == null) { |
232 | unsupportedIn2(); |
233 | } |
234 | return this.annotations; |
235 | } |
236 | |
237 | /** |
238 | * Returns the doc comment node (added in JLS3 API). |
239 | * |
240 | * @return the doc comment node, or <code>null</code> if none |
241 | * @exception UnsupportedOperationException if this operation is used in |
242 | * a JLS2 AST |
243 | * @since 3.0 |
244 | */ |
245 | public Javadoc getJavadoc() { |
246 | // more efficient than just calling unsupportedIn2() to check |
247 | if (this.annotations == null) { |
248 | unsupportedIn2(); |
249 | } |
250 | return this.optionalDocComment; |
251 | } |
252 | |
253 | /** |
254 | * Sets or clears the doc comment node (added in JLS3 API). |
255 | * |
256 | * @param docComment the doc comment node, or <code>null</code> if none |
257 | * @exception IllegalArgumentException if the doc comment string is invalid |
258 | * @exception UnsupportedOperationException if this operation is used in |
259 | * a JLS2 AST |
260 | * @since 3.0 |
261 | */ |
262 | public void setJavadoc(Javadoc docComment) { |
263 | // more efficient than just calling unsupportedIn2() to check |
264 | if (this.annotations == null) { |
265 | unsupportedIn2(); |
266 | } |
267 | ASTNode oldChild = this.optionalDocComment; |
268 | preReplaceChild(oldChild, docComment, JAVADOC_PROPERTY); |
269 | this.optionalDocComment = docComment; |
270 | postReplaceChild(oldChild, docComment, JAVADOC_PROPERTY); |
271 | } |
272 | |
273 | /** |
274 | * Returns the package name of this package declaration. |
275 | * |
276 | * @return the package name node |
277 | */ |
278 | public Name getName() { |
279 | if (this.packageName == null) { |
280 | // lazy init must be thread-safe for readers |
281 | synchronized (this) { |
282 | if (this.packageName == null) { |
283 | preLazyInit(); |
284 | this.packageName = new SimpleName(this.ast); |
285 | postLazyInit(this.packageName, NAME_PROPERTY); |
286 | } |
287 | } |
288 | } |
289 | return this.packageName; |
290 | } |
291 | |
292 | /** |
293 | * Sets the package name of this package declaration to the given name. |
294 | * |
295 | * @param name the new package name |
296 | * @exception IllegalArgumentException if`: |
297 | * <ul> |
298 | * <li>the node belongs to a different AST</li> |
299 | * <li>the node already has a parent</li> |
300 | * </ul> |
301 | */ |
302 | public void setName(Name name) { |
303 | if (name == null) { |
304 | throw new IllegalArgumentException(); |
305 | } |
306 | ASTNode oldChild = this.packageName; |
307 | preReplaceChild(oldChild, name, NAME_PROPERTY); |
308 | this.packageName = name; |
309 | postReplaceChild(oldChild, name, NAME_PROPERTY); |
310 | } |
311 | |
312 | /** |
313 | * Resolves and returns the binding for the package declared in this package |
314 | * declaration. |
315 | * <p> |
316 | * Note that bindings are generally unavailable unless requested when the |
317 | * AST is being built. |
318 | * </p> |
319 | * |
320 | * @return the binding, or <code>null</code> if the binding cannot be |
321 | * resolved |
322 | */ |
323 | public IPackageBinding resolveBinding() { |
324 | return this.ast.getBindingResolver().resolvePackage(this); |
325 | } |
326 | |
327 | @Override |
328 | int memSize() { |
329 | return BASE_NODE_SIZE + 3 * 4; |
330 | } |
331 | |
332 | @Override |
333 | int treeSize() { |
334 | return |
335 | memSize() |
336 | + (this.optionalDocComment == null ? 0 : getJavadoc().treeSize()) |
337 | + (this.annotations == null ? 0 : this.annotations.listSize()) |
338 | + (this.packageName == null ? 0 : getName().treeSize()); |
339 | } |
340 | } |
341 | |
342 |
Members