1 | /******************************************************************************* |
---|---|
2 | * Copyright (c) 2019, 2021 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 | * Contributors: |
11 | * IBM Corporation - initial API and implementation |
12 | *******************************************************************************/ |
13 | |
14 | package org.eclipse.jdt.core.dom; |
15 | |
16 | import java.util.ArrayList; |
17 | import java.util.Iterator; |
18 | import java.util.List; |
19 | |
20 | /** |
21 | * Record declaration AST node type (added in JLS16 API). |
22 | * |
23 | * <pre> |
24 | * RecordDeclaration: |
25 | * [ Javadoc ] { ExtendedModifier } <b>record</b> Identifier |
26 | * [ <b><</b> TypeParameter <b>></b> ] |
27 | * <b>(</b> |
28 | * [ FormalParameter { <b>,</b> FormalParameter } ] |
29 | * <b>)</b> { Dimension } |
30 | * [ <b>implements</b> Type { <b>,</b> Type } ] |
31 | * [ <b>;</b> { RecordBodyDeclaration | <b>;</b> } ] |
32 | * </pre> |
33 | * The {@link #bodyDeclarations()} list holds the class body declarations |
34 | * that appear after the semicolon. |
35 | * <p> |
36 | * When a Javadoc comment is present, the source |
37 | * range begins with the first character of the "/**" comment delimiter. |
38 | * When there is no Javadoc comment, the source range begins with the first |
39 | * character of the first modifier or annotation (if present), or the |
40 | * first character of the "record" keyword (if no |
41 | * modifiers or annotations). The source range extends through the last |
42 | * character of the "}" token following the body declarations. |
43 | * </p> |
44 | * |
45 | * @since 3.26 |
46 | */ |
47 | @SuppressWarnings({ "rawtypes", "unchecked" }) |
48 | public class RecordDeclaration extends AbstractTypeDeclaration { |
49 | |
50 | /** |
51 | * The "javadoc" structural property of this node type (child type: {@link Javadoc}). |
52 | */ |
53 | public static final ChildPropertyDescriptor JAVADOC_PROPERTY = |
54 | internalJavadocPropertyFactory(RecordDeclaration.class); |
55 | |
56 | /** |
57 | * The "modifiers" structural property of this node type (element type: {@link IExtendedModifier}). |
58 | */ |
59 | public static final ChildListPropertyDescriptor MODIFIERS2_PROPERTY = |
60 | internalModifiers2PropertyFactory(RecordDeclaration.class); |
61 | |
62 | /** |
63 | * The "name" structural property of this node type (child type: {@link SimpleName}). |
64 | */ |
65 | public static final ChildPropertyDescriptor NAME_PROPERTY = |
66 | internalNamePropertyFactory(RecordDeclaration.class); |
67 | |
68 | |
69 | /** |
70 | * The "superInterfaceTypes" structural property of this node type (element type: {@link Type}). |
71 | */ |
72 | public static final ChildListPropertyDescriptor SUPER_INTERFACE_TYPES_PROPERTY = |
73 | new ChildListPropertyDescriptor(RecordDeclaration.class, "superInterfaceTypes", Type.class, NO_CYCLE_RISK); //$NON-NLS-1$ |
74 | |
75 | /** |
76 | * The "typeParameters" structural property of this node type (element type: {@link TypeParameter}). |
77 | */ |
78 | public static final ChildListPropertyDescriptor TYPE_PARAMETERS_PROPERTY = |
79 | new ChildListPropertyDescriptor(RecordDeclaration.class, "typeParameters", TypeParameter.class, NO_CYCLE_RISK); //$NON-NLS-1$ |
80 | |
81 | /** |
82 | * The "recordComponents" structural property of this node type (element type: {@link SingleVariableDeclaration}). |
83 | */ |
84 | public static final ChildListPropertyDescriptor RECORD_COMPONENTS_PROPERTY = |
85 | new ChildListPropertyDescriptor(RecordDeclaration.class, "recordComponents", SingleVariableDeclaration.class, NO_CYCLE_RISK); //$NON-NLS-1$ |
86 | |
87 | /** |
88 | * The "bodyDeclarations" structural property of this node type (element type: {@link BodyDeclaration}). |
89 | */ |
90 | public static final ChildListPropertyDescriptor BODY_DECLARATIONS_PROPERTY = |
91 | internalBodyDeclarationPropertyFactory(RecordDeclaration.class); |
92 | |
93 | |
94 | /** |
95 | * A character index into the original restricted identifier source string, |
96 | * or <code>-1</code> if no restricted identifier source position information is available |
97 | * for this node; <code>-1</code> by default. |
98 | */ |
99 | private int restrictedIdentifierStartPosition = -1; |
100 | |
101 | /** |
102 | * @param restrictedIdentifierStartPosition |
103 | * @since 3.26 |
104 | */ |
105 | public void setRestrictedIdentifierStartPosition(int restrictedIdentifierStartPosition) { |
106 | if (restrictedIdentifierStartPosition < 0) { |
107 | throw new IllegalArgumentException(); |
108 | } |
109 | // restrictedIdentifierStartPosition is not considered a structural property |
110 | // but we protect it nevertheless |
111 | checkModifiable(); |
112 | this.restrictedIdentifierStartPosition= restrictedIdentifierStartPosition; |
113 | } |
114 | |
115 | /** |
116 | * @return restrictedIdentifierStartPosition |
117 | * @since 3.26 |
118 | */ |
119 | public int getRestrictedIdentifierStartPosition() { |
120 | return this.restrictedIdentifierStartPosition; |
121 | } |
122 | |
123 | /** |
124 | * A list of property descriptors (element type: |
125 | * {@link StructuralPropertyDescriptor}), |
126 | * or null if uninitialized. |
127 | */ |
128 | private static final List PROPERTY_DESCRIPTORS; |
129 | |
130 | static { |
131 | |
132 | ArrayList propertyList = new ArrayList(8); |
133 | createPropertyList(RecordDeclaration.class, propertyList); |
134 | addProperty(JAVADOC_PROPERTY, propertyList); |
135 | addProperty(MODIFIERS2_PROPERTY, propertyList); |
136 | addProperty(NAME_PROPERTY, propertyList); |
137 | addProperty(TYPE_PARAMETERS_PROPERTY, propertyList); |
138 | addProperty(RECORD_COMPONENTS_PROPERTY, propertyList); |
139 | addProperty(SUPER_INTERFACE_TYPES_PROPERTY, propertyList); |
140 | addProperty(BODY_DECLARATIONS_PROPERTY, propertyList); |
141 | |
142 | PROPERTY_DESCRIPTORS = reapPropertyList(propertyList); |
143 | } |
144 | |
145 | /** |
146 | * Returns a list of structural property descriptors for this node type. |
147 | * Clients must not modify the result. |
148 | * |
149 | * @param apiLevel the API level; one of the |
150 | * <code>AST.JLS*</code> constants |
151 | |
152 | * @return a list of property descriptors (element type: |
153 | * {@link StructuralPropertyDescriptor}) |
154 | * @since 3.26 |
155 | */ |
156 | public static List propertyDescriptors(int apiLevel) { |
157 | return PROPERTY_DESCRIPTORS; |
158 | } |
159 | |
160 | /** |
161 | * The type parameters (element type: {@link TypeParameter}). |
162 | * defaults to an empty list |
163 | */ |
164 | private ASTNode.NodeList typeParameters = new ASTNode.NodeList(TYPE_PARAMETERS_PROPERTY); |
165 | |
166 | |
167 | /** |
168 | * The superinterface types (element type: {@link Type}). |
169 | * defaults to an empty list |
170 | * (see constructor). |
171 | */ |
172 | private ASTNode.NodeList superInterfaceTypes = new ASTNode.NodeList(SUPER_INTERFACE_TYPES_PROPERTY); |
173 | |
174 | /** |
175 | * The parameters (element type: {@link SingleVariableDeclaration}). |
176 | * defaults to an empty list |
177 | * (see constructor). |
178 | */ |
179 | private ASTNode.NodeList recordComponents = new ASTNode.NodeList(RECORD_COMPONENTS_PROPERTY); |
180 | |
181 | |
182 | /** |
183 | * Creates a new AST node for a type declaration owned by the given |
184 | * AST. By default, the type declaration is for a class of an |
185 | * unspecified, but legal, name; no modifiers; no javadoc; |
186 | * no type parameters; no superinterfaces; and an empty list |
187 | * of body declarations. |
188 | * <p> |
189 | * N.B. This constructor is package-private; all subclasses must be |
190 | * declared in the same package; clients are unable to declare |
191 | * additional subclasses. |
192 | * </p> |
193 | * |
194 | * @param ast the AST that is to own this node |
195 | * @exception UnsupportedOperationException if this operation is used below JLS16 |
196 | */ |
197 | RecordDeclaration(AST ast) { |
198 | super(ast); |
199 | unsupportedBelow16(); |
200 | } |
201 | |
202 | @Override |
203 | final List internalStructuralPropertiesForType(int apiLevel) { |
204 | return propertyDescriptors(apiLevel); |
205 | } |
206 | |
207 | @Override |
208 | final ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) { |
209 | if (property == JAVADOC_PROPERTY) { |
210 | if (get) { |
211 | return getJavadoc(); |
212 | } else { |
213 | setJavadoc((Javadoc) child); |
214 | return null; |
215 | } |
216 | } |
217 | if (property == NAME_PROPERTY) { |
218 | if (get) { |
219 | return getName(); |
220 | } else { |
221 | setName((SimpleName) child); |
222 | return null; |
223 | } |
224 | } |
225 | // allow default implementation to flag the error |
226 | return super.internalGetSetChildProperty(property, get, child); |
227 | } |
228 | |
229 | @Override |
230 | final List internalGetChildListProperty(ChildListPropertyDescriptor property) { |
231 | if (property == MODIFIERS2_PROPERTY) { |
232 | return modifiers(); |
233 | } |
234 | if (property == TYPE_PARAMETERS_PROPERTY) { |
235 | return typeParameters(); |
236 | } |
237 | if (property == RECORD_COMPONENTS_PROPERTY) { |
238 | return recordComponents(); |
239 | } |
240 | if (property == SUPER_INTERFACE_TYPES_PROPERTY) { |
241 | return superInterfaceTypes(); |
242 | } |
243 | if (property == BODY_DECLARATIONS_PROPERTY) { |
244 | return bodyDeclarations(); |
245 | } |
246 | // allow default implementation to flag the error |
247 | return super.internalGetChildListProperty(property); |
248 | } |
249 | |
250 | @Override |
251 | final ChildPropertyDescriptor internalJavadocProperty() { |
252 | return JAVADOC_PROPERTY; |
253 | } |
254 | |
255 | @Override |
256 | final ChildListPropertyDescriptor internalModifiers2Property() { |
257 | return MODIFIERS2_PROPERTY; |
258 | } |
259 | |
260 | @Override |
261 | final ChildPropertyDescriptor internalNameProperty() { |
262 | return NAME_PROPERTY; |
263 | } |
264 | |
265 | @Override |
266 | final ChildListPropertyDescriptor internalBodyDeclarationsProperty() { |
267 | return BODY_DECLARATIONS_PROPERTY; |
268 | } |
269 | |
270 | @Override |
271 | final int getNodeType0() { |
272 | return RECORD_DECLARATION; |
273 | } |
274 | |
275 | @Override |
276 | ASTNode clone0(AST target) { |
277 | RecordDeclaration result = new RecordDeclaration(target); |
278 | result.restrictedIdentifierStartPosition = getRestrictedIdentifierStartPosition(); |
279 | result.setSourceRange(getStartPosition(), getLength()); |
280 | result.setJavadoc( |
281 | (Javadoc) ASTNode.copySubtree(target, getJavadoc())); |
282 | result.setName((SimpleName) getName().clone(target)); |
283 | result.modifiers().addAll(ASTNode.copySubtrees(target, modifiers())); |
284 | result.typeParameters().addAll( |
285 | ASTNode.copySubtrees(target, typeParameters())); |
286 | result.recordComponents().addAll( |
287 | ASTNode.copySubtrees(target, recordComponents())); |
288 | result.superInterfaceTypes().addAll( |
289 | ASTNode.copySubtrees(target, superInterfaceTypes())); |
290 | result.bodyDeclarations().addAll( |
291 | ASTNode.copySubtrees(target, bodyDeclarations())); |
292 | return result; |
293 | } |
294 | |
295 | @Override |
296 | final boolean subtreeMatch0(ASTMatcher matcher, Object other) { |
297 | // dispatch to correct overloaded match method |
298 | return matcher.match(this, other); |
299 | } |
300 | |
301 | @Override |
302 | void accept0(ASTVisitor visitor) { |
303 | boolean visitChildren = visitor.visit(this); |
304 | if (visitChildren) { |
305 | // visit children in normal left to right reading order |
306 | acceptChild(visitor, getJavadoc()); |
307 | acceptChildren(visitor, this.modifiers); |
308 | acceptChild(visitor, getName()); |
309 | acceptChildren(visitor, this.typeParameters); |
310 | acceptChildren(visitor, this.recordComponents); |
311 | acceptChildren(visitor, this.superInterfaceTypes); |
312 | acceptChildren(visitor, this.bodyDeclarations); |
313 | } |
314 | visitor.endVisit(this); |
315 | } |
316 | |
317 | /** |
318 | * Returns the live ordered list of type parameters of this type |
319 | * declaration (added in JLS3 API). This list is non-empty for parameterized types. |
320 | * |
321 | * @return the live list of type parameters |
322 | * (element type: {@link TypeParameter}) |
323 | * @since 3.26 |
324 | */ |
325 | public List typeParameters() { |
326 | return this.typeParameters; |
327 | } |
328 | |
329 | |
330 | /** |
331 | * Returns the live ordered list of superinterfaces of this type |
332 | * declaration (added in JLS3 API). For a class declaration, these are the interfaces |
333 | * that this class implements; for an interface declaration, |
334 | * these are the interfaces that this interface extends. |
335 | * |
336 | * @return the live list of interface types |
337 | * (element type: {@link Type}) |
338 | * @since 3.26 |
339 | */ |
340 | public List superInterfaceTypes() { |
341 | return this.superInterfaceTypes; |
342 | } |
343 | |
344 | /** |
345 | * Returns the live ordered list of recordComponents of record declaration. |
346 | * |
347 | * @return the live list of recordComponents |
348 | * (element type: {@link SingleVariableDeclaration}) |
349 | * @since 3.26 |
350 | */ |
351 | public List recordComponents() { |
352 | return this.recordComponents; |
353 | } |
354 | |
355 | /** |
356 | * Returns the ordered list of field declarations of this type |
357 | * declaration. For a class declaration, these are the |
358 | * field declarations; for an interface declaration, these are |
359 | * the constant declarations. |
360 | * <p> |
361 | * This convenience method returns this node's body declarations |
362 | * with non-fields filtered out. Unlike <code>bodyDeclarations</code>, |
363 | * this method does not return a live result. |
364 | * </p> |
365 | * |
366 | * @return the (possibly empty) list of field declarations |
367 | * @since 3.26 |
368 | */ |
369 | public FieldDeclaration[] getFields() { |
370 | List bd = bodyDeclarations(); |
371 | int fieldCount = 0; |
372 | for (Iterator it = bd.listIterator(); it.hasNext(); ) { |
373 | if (it.next() instanceof FieldDeclaration) { |
374 | fieldCount++; |
375 | } |
376 | } |
377 | FieldDeclaration[] fields = new FieldDeclaration[fieldCount]; |
378 | int next = 0; |
379 | for (Iterator it = bd.listIterator(); it.hasNext(); ) { |
380 | Object decl = it.next(); |
381 | if (decl instanceof FieldDeclaration) { |
382 | fields[next++] = (FieldDeclaration) decl; |
383 | } |
384 | } |
385 | return fields; |
386 | } |
387 | |
388 | /** |
389 | * Returns the ordered list of method declarations of this type |
390 | * declaration. |
391 | * <p> |
392 | * This convenience method returns this node's body declarations |
393 | * with non-methods filtered out. Unlike <code>bodyDeclarations</code>, |
394 | * this method does not return a live result. |
395 | * </p> |
396 | * |
397 | * @return the (possibly empty) list of method (and constructor) |
398 | * declarations |
399 | * @since 3.26 |
400 | */ |
401 | public MethodDeclaration[] getMethods() { |
402 | List bd = bodyDeclarations(); |
403 | int methodCount = 0; |
404 | for (Iterator it = bd.listIterator(); it.hasNext(); ) { |
405 | if (it.next() instanceof MethodDeclaration) { |
406 | methodCount++; |
407 | } |
408 | } |
409 | MethodDeclaration[] methods = new MethodDeclaration[methodCount]; |
410 | int next = 0; |
411 | for (Iterator it = bd.listIterator(); it.hasNext(); ) { |
412 | Object decl = it.next(); |
413 | if (decl instanceof MethodDeclaration) { |
414 | methods[next++] = (MethodDeclaration) decl; |
415 | } |
416 | } |
417 | return methods; |
418 | } |
419 | |
420 | @Override |
421 | ITypeBinding internalResolveBinding() { |
422 | return this.ast.getBindingResolver().resolveType(this); |
423 | } |
424 | |
425 | @Override |
426 | int memSize() { |
427 | return super.memSize() + 4 * 4; |
428 | } |
429 | |
430 | @Override |
431 | int treeSize() { |
432 | return memSize() |
433 | + (this.optionalDocComment == null ? 0 : getJavadoc().treeSize()) |
434 | + (this.modifiers == null ? 0 : this.modifiers.listSize()) |
435 | + (this.typeName == null ? 0 : getName().treeSize()) |
436 | + (this.typeParameters == null ? 0 : this.typeParameters.listSize()) |
437 | + (this.superInterfaceTypes == null ? 0 : this.superInterfaceTypes.listSize()) |
438 | + (this.recordComponents == null ? 0 : this.recordComponents.listSize()) |
439 | + this.bodyDeclarations.listSize(); |
440 | } |
441 | |
442 | @Override |
443 | SimplePropertyDescriptor internalModifiersProperty() { |
444 | // node type does not exist before JLS 16 |
445 | return null; |
446 | } |
447 | |
448 | } |
449 | |
450 |
Members