1 | /******************************************************************************* |
---|---|
2 | * Copyright (c) 2000, 2022 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.AbstractList; |
18 | import java.util.ArrayList; |
19 | import java.util.Collections; |
20 | import java.util.HashMap; |
21 | import java.util.Iterator; |
22 | import java.util.List; |
23 | import java.util.Map; |
24 | |
25 | import org.eclipse.jdt.internal.core.dom.NaiveASTFlattener; |
26 | |
27 | /** |
28 | * Abstract superclass of all Abstract Syntax Tree (AST) node types. |
29 | * <p> |
30 | * An AST node represents a Java source code construct, such |
31 | * as a name, type, expression, statement, or declaration. |
32 | * </p> |
33 | * <p> |
34 | * Each AST node belongs to a unique AST instance, called the owning AST. |
35 | * The children of an AST node always have the same owner as their parent node. |
36 | * If a node from one AST is to be added to a different AST, the subtree must |
37 | * be cloned first to ensure that the added nodes have the correct owning AST. |
38 | * </p> |
39 | * <p> |
40 | * When an AST node is part of an AST, it has a unique parent node. |
41 | * Clients can navigate upwards, from child to parent, as well as downwards, |
42 | * from parent to child. Newly created nodes are unparented. When an |
43 | * unparented node is set as a child of a node (using a |
44 | * <code>set<i>CHILD</i></code> method), its parent link is set automatically |
45 | * and the parent link of the former child is set to <code>null</code>. |
46 | * For nodes with properties that include a list of children (for example, |
47 | * <code>Block</code> whose <code>statements</code> property is a list |
48 | * of statements), adding or removing an element to/for the list property |
49 | * automatically updates the parent links. These lists support the |
50 | * <code>List.set</code> method; however, the constraint that the same |
51 | * node cannot appear more than once means that this method cannot be used |
52 | * to swap elements without first removing the node. |
53 | * </p> |
54 | * <p> |
55 | * ASTs must not contain cycles. All operations that could create a cycle |
56 | * detect this possibility and fail. |
57 | * </p> |
58 | * <p> |
59 | * ASTs do not contain "holes" (missing subtrees). If a node is required to |
60 | * have a certain property, a syntactically plausible initial value is |
61 | * always supplied. |
62 | * </p> |
63 | * <p> |
64 | * The hierarchy of AST node types has some convenient groupings marked |
65 | * by abstract superclasses: |
66 | * <ul> |
67 | * <li>expressions - <code>Expression</code></li> |
68 | * <li>names - <code>Name</code> (a sub-kind of expression)</li> |
69 | * <li>statements - <code>Statement</code></li> |
70 | * <li>types - <code>Type</code></li> |
71 | * <li>type body declarations - <code>BodyDeclaration</code></li> |
72 | * </ul> |
73 | * <p> |
74 | * Abstract syntax trees may be hand constructed by clients, using the |
75 | * <code>new<i>TYPE</i></code> factory methods (see <code>AST</code>) to |
76 | * create new nodes, and the various <code>set<i>CHILD</i></code> methods |
77 | * to connect them together. |
78 | * </p> |
79 | * <p> |
80 | * The class {@link ASTParser} parses a string |
81 | * containing a Java source code and returns an abstract syntax tree |
82 | * for it. The resulting nodes carry source ranges relating the node back to |
83 | * the original source characters. The source range covers the construct |
84 | * as a whole. |
85 | * </p> |
86 | * <p> |
87 | * Each AST node carries bit flags, which may convey additional information about |
88 | * the node. For instance, the parser uses a flag to indicate a syntax error. |
89 | * Newly created nodes have no flags set. |
90 | * </p> |
91 | * <p> |
92 | * Each AST node is capable of carrying an open-ended collection of |
93 | * client-defined properties. Newly created nodes have none. |
94 | * <code>getProperty</code> and <code>setProperty</code> are used to access |
95 | * these properties. |
96 | * </p> |
97 | * <p> |
98 | * AST nodes are thread-safe for readers provided there are no active writers. |
99 | * If one thread is modifying an AST, including creating new nodes or cloning |
100 | * existing ones, it is <b>not</b> safe for another thread to read, visit, |
101 | * write, create, or clone <em>any</em> of the nodes on the same AST. |
102 | * When synchronization is required, consider using the common AST |
103 | * object that owns the node; that is, use |
104 | * <code>synchronize (node.getAST()) {...}</code>. |
105 | * </p> |
106 | * <p> |
107 | * ASTs also support the visitor pattern; see the class <code>ASTVisitor</code> |
108 | * for details. The <code>NodeFinder</code> class can be used to find a specific |
109 | * node inside a tree. |
110 | * </p> |
111 | * <p> |
112 | * Compilation units created by <code>ASTParser</code> from a |
113 | * source document can be serialized after arbitrary modifications |
114 | * with minimal loss of original formatting. See |
115 | * {@link CompilationUnit#recordModifications()} for details. |
116 | * See also {@link org.eclipse.jdt.core.dom.rewrite.ASTRewrite} for |
117 | * an alternative way to describe and serialize changes to a |
118 | * read-only AST. |
119 | * </p> |
120 | * |
121 | * @see ASTParser |
122 | * @see ASTVisitor |
123 | * @see NodeFinder |
124 | * @since 2.0 |
125 | * @noextend This class is not intended to be subclassed by clients. |
126 | */ |
127 | @SuppressWarnings({ "rawtypes", "unchecked" }) |
128 | public abstract class ASTNode { |
129 | /* |
130 | * ATTENTION: When doing anything to the ASTNode hierarchy, do not try to |
131 | * reinvent the wheel. |
132 | * |
133 | * Look out for precedents with |
134 | * - the same structural property type |
135 | * - for child node properties: the same optionality (can be null / lazy initialization blurbs and impl.) |
136 | * - the same declaring node type kind (abstract supertype or concrete type) |
137 | * - a similar history (added in JLSx API, below JLSx only, replaced by {@link #xx}) |
138 | * ..., and copy what was done there. Most of the code and |
139 | * Javadoc in this package should look like it was created by a code generator. |
140 | * |
141 | * In subclasses of ASTNode, order properties by order of occurrence in source. |
142 | * In general classes that list all AST node types, order alphabetically. |
143 | */ |
144 | |
145 | /* |
146 | * INSTRUCTIONS FOR ADDING NEW CONCRETE AST NODE TYPES |
147 | * |
148 | * There are several things that need to be changed when a |
149 | * new concrete AST node type (call it "FooBar") is added: |
150 | * |
151 | * 1. Create the FooBar AST node type class. |
152 | * The most effective way to do this is to copy a similar |
153 | * existing concrete node class to get a template that |
154 | * includes all the framework methods that must be implemented. |
155 | * |
156 | * 2. Add node type constant ASTNode.FOO_BAR. |
157 | * Node constants are numbered consecutively. Add the |
158 | * constant after the existing ones. |
159 | * |
160 | * 3. Add entry to ASTNode.nodeClassForType(int). |
161 | * |
162 | * 4. Add AST.newFooBar() factory method. |
163 | * |
164 | * 5. Add ASTVisitor.visit(FooBar) and endVisit(FooBar) methods. Same for DefaultASTVisitor. |
165 | * |
166 | * 6. Add ASTMatcher.match(FooBar,Object) method. |
167 | * |
168 | * 7. Ensure that SimpleName.isDeclaration() covers FooBar |
169 | * nodes if required. |
170 | * |
171 | * 8. Add NaiveASTFlattener.visit(FooBar) method to illustrate |
172 | * how these nodes should be serialized. |
173 | * |
174 | * 9. Update the AST test suites (ASTVisitorTest, etc.) |
175 | * |
176 | * The next steps are to update AST.parse* to start generating |
177 | * the new type of nodes, and ASTRewrite to serialize them back out. |
178 | */ |
179 | |
180 | /* |
181 | * INSTRUCTIONS FOR ADDING A NEW PROPERTY TO AN AST NODE TYPE |
182 | * |
183 | * For concrete node types, use e.g. properties of SimpleName or ClassInstanceCreation |
184 | * as templates: |
185 | * |
186 | * 1. Copy/paste the field, property descriptor, and getter/setter. |
187 | * |
188 | * 2. Adjust everything to the new property name and type. In the field's |
189 | * Javadoc, properly document default value, initialization, and applicable |
190 | * API levels. |
191 | * |
192 | * 3. Add/remove @since tags as necessary. |
193 | * |
194 | * 4. Search for references to the members in the template, and add similar |
195 | * references in corresponding places for the new property. |
196 | * |
197 | * |
198 | * For abstract node types, use AbstractTypeDeclaration as a template: |
199 | * |
200 | * 1. Same steps as above, but take extra care to copy and adjust the |
201 | * *internal*() methods as well. |
202 | * |
203 | * 2. Search for references to the members in the template, and add similar |
204 | * references in corresponding places for the new property (e.g. property |
205 | * descriptor in each leaf type). |
206 | */ |
207 | |
208 | /* |
209 | * INSTRUCTIONS FOR REPLACING/DEPRECATING A PROPERTY OF AN AST NODE |
210 | * |
211 | * To replace a simple property with a child list property, see e.g. how |
212 | * SingleVariableDeclaration replaced MODIFIERS_PROPERTY with |
213 | * MODIFIERS2_PROPERTY. |
214 | * |
215 | * 1. Reuse the old property id. |
216 | * |
217 | * 2. Deprecate all references to the old property, except for the old |
218 | * getter, which should compute the value from the new property in |
219 | * later API levels. |
220 | * |
221 | * To completely replace a property, see how ClassInstanceCreation replaced |
222 | * NAME_PROPERTY with TYPE_PROPERTY. |
223 | */ |
224 | |
225 | /** |
226 | * Node type constant indicating a node of type |
227 | * <code>AnonymousClassDeclaration</code>. |
228 | * @see AnonymousClassDeclaration |
229 | */ |
230 | public static final int ANONYMOUS_CLASS_DECLARATION = 1; |
231 | |
232 | /** |
233 | * Node type constant indicating a node of type |
234 | * <code>ArrayAccess</code>. |
235 | * @see ArrayAccess |
236 | */ |
237 | public static final int ARRAY_ACCESS = 2; |
238 | |
239 | /** |
240 | * Node type constant indicating a node of type |
241 | * <code>ArrayCreation</code>. |
242 | * @see ArrayCreation |
243 | */ |
244 | public static final int ARRAY_CREATION = 3; |
245 | |
246 | /** |
247 | * Node type constant indicating a node of type |
248 | * <code>ArrayInitializer</code>. |
249 | * @see ArrayInitializer |
250 | */ |
251 | public static final int ARRAY_INITIALIZER = 4; |
252 | |
253 | /** |
254 | * Node type constant indicating a node of type |
255 | * <code>ArrayType</code>. |
256 | * @see ArrayType |
257 | */ |
258 | public static final int ARRAY_TYPE = 5; |
259 | |
260 | /** |
261 | * Node type constant indicating a node of type |
262 | * <code>AssertStatement</code>. |
263 | * @see AssertStatement |
264 | */ |
265 | public static final int ASSERT_STATEMENT = 6; |
266 | |
267 | /** |
268 | * Node type constant indicating a node of type |
269 | * <code>Assignment</code>. |
270 | * @see Assignment |
271 | */ |
272 | public static final int ASSIGNMENT = 7; |
273 | |
274 | /** |
275 | * Node type constant indicating a node of type |
276 | * <code>Block</code>. |
277 | * @see Block |
278 | */ |
279 | public static final int BLOCK = 8; |
280 | |
281 | /** |
282 | * Node type constant indicating a node of type |
283 | * <code>BooleanLiteral</code>. |
284 | * @see BooleanLiteral |
285 | */ |
286 | public static final int BOOLEAN_LITERAL = 9; |
287 | |
288 | /** |
289 | * Node type constant indicating a node of type |
290 | * <code>BreakStatement</code>. |
291 | * @see BreakStatement |
292 | */ |
293 | public static final int BREAK_STATEMENT = 10; |
294 | |
295 | /** |
296 | * Node type constant indicating a node of type |
297 | * <code>CastExpression</code>. |
298 | * @see CastExpression |
299 | */ |
300 | public static final int CAST_EXPRESSION = 11; |
301 | |
302 | /** |
303 | * Node type constant indicating a node of type |
304 | * <code>CatchClause</code>. |
305 | * @see CatchClause |
306 | */ |
307 | public static final int CATCH_CLAUSE = 12; |
308 | |
309 | /** |
310 | * Node type constant indicating a node of type |
311 | * <code>CharacterLiteral</code>. |
312 | * @see CharacterLiteral |
313 | */ |
314 | public static final int CHARACTER_LITERAL = 13; |
315 | |
316 | /** |
317 | * Node type constant indicating a node of type |
318 | * <code>ClassInstanceCreation</code>. |
319 | * @see ClassInstanceCreation |
320 | */ |
321 | public static final int CLASS_INSTANCE_CREATION = 14; |
322 | |
323 | /** |
324 | * Node type constant indicating a node of type |
325 | * <code>CompilationUnit</code>. |
326 | * @see CompilationUnit |
327 | */ |
328 | public static final int COMPILATION_UNIT = 15; |
329 | |
330 | /** |
331 | * Node type constant indicating a node of type |
332 | * <code>ConditionalExpression</code>. |
333 | * @see ConditionalExpression |
334 | */ |
335 | public static final int CONDITIONAL_EXPRESSION = 16; |
336 | |
337 | /** |
338 | * Node type constant indicating a node of type |
339 | * <code>ConstructorInvocation</code>. |
340 | * @see ConstructorInvocation |
341 | */ |
342 | public static final int CONSTRUCTOR_INVOCATION = 17; |
343 | |
344 | /** |
345 | * Node type constant indicating a node of type |
346 | * <code>ContinueStatement</code>. |
347 | * @see ContinueStatement |
348 | */ |
349 | public static final int CONTINUE_STATEMENT = 18; |
350 | |
351 | /** |
352 | * Node type constant indicating a node of type |
353 | * <code>DoStatement</code>. |
354 | * @see DoStatement |
355 | */ |
356 | public static final int DO_STATEMENT = 19; |
357 | |
358 | /** |
359 | * Node type constant indicating a node of type |
360 | * <code>EmptyStatement</code>. |
361 | * @see EmptyStatement |
362 | */ |
363 | public static final int EMPTY_STATEMENT = 20; |
364 | |
365 | /** |
366 | * Node type constant indicating a node of type |
367 | * <code>ExpressionStatement</code>. |
368 | * @see ExpressionStatement |
369 | */ |
370 | public static final int EXPRESSION_STATEMENT = 21; |
371 | |
372 | /** |
373 | * Node type constant indicating a node of type |
374 | * <code>FieldAccess</code>. |
375 | * @see FieldAccess |
376 | */ |
377 | public static final int FIELD_ACCESS = 22; |
378 | |
379 | /** |
380 | * Node type constant indicating a node of type |
381 | * <code>FieldDeclaration</code>. |
382 | * @see FieldDeclaration |
383 | */ |
384 | public static final int FIELD_DECLARATION = 23; |
385 | |
386 | /** |
387 | * Node type constant indicating a node of type |
388 | * <code>ForStatement</code>. |
389 | * @see ForStatement |
390 | */ |
391 | public static final int FOR_STATEMENT = 24; |
392 | |
393 | /** |
394 | * Node type constant indicating a node of type |
395 | * <code>IfStatement</code>. |
396 | * @see IfStatement |
397 | */ |
398 | public static final int IF_STATEMENT = 25; |
399 | |
400 | /** |
401 | * Node type constant indicating a node of type |
402 | * <code>ImportDeclaration</code>. |
403 | * @see ImportDeclaration |
404 | */ |
405 | public static final int IMPORT_DECLARATION = 26; |
406 | |
407 | /** |
408 | * Node type constant indicating a node of type |
409 | * <code>InfixExpression</code>. |
410 | * @see InfixExpression |
411 | */ |
412 | public static final int INFIX_EXPRESSION = 27; |
413 | |
414 | /** |
415 | * Node type constant indicating a node of type |
416 | * <code>Initializer</code>. |
417 | * @see Initializer |
418 | */ |
419 | public static final int INITIALIZER = 28; |
420 | |
421 | /** |
422 | * Node type constant indicating a node of type |
423 | * <code>Javadoc</code>. |
424 | * @see Javadoc |
425 | */ |
426 | public static final int JAVADOC = 29; |
427 | |
428 | /** |
429 | * Node type constant indicating a node of type |
430 | * <code>LabeledStatement</code>. |
431 | * @see LabeledStatement |
432 | */ |
433 | public static final int LABELED_STATEMENT = 30; |
434 | |
435 | /** |
436 | * Node type constant indicating a node of type |
437 | * <code>MethodDeclaration</code>. |
438 | * @see MethodDeclaration |
439 | */ |
440 | public static final int METHOD_DECLARATION = 31; |
441 | |
442 | /** |
443 | * Node type constant indicating a node of type |
444 | * <code>MethodInvocation</code>. |
445 | * @see MethodInvocation |
446 | */ |
447 | public static final int METHOD_INVOCATION = 32; |
448 | |
449 | /** |
450 | * Node type constant indicating a node of type |
451 | * <code>NullLiteral</code>. |
452 | * @see NullLiteral |
453 | */ |
454 | public static final int NULL_LITERAL = 33; |
455 | |
456 | /** |
457 | * Node type constant indicating a node of type |
458 | * <code>NumberLiteral</code>. |
459 | * @see NumberLiteral |
460 | */ |
461 | public static final int NUMBER_LITERAL = 34; |
462 | |
463 | /** |
464 | * Node type constant indicating a node of type |
465 | * <code>PackageDeclaration</code>. |
466 | * @see PackageDeclaration |
467 | */ |
468 | public static final int PACKAGE_DECLARATION = 35; |
469 | |
470 | /** |
471 | * Node type constant indicating a node of type |
472 | * <code>ParenthesizedExpression</code>. |
473 | * @see ParenthesizedExpression |
474 | */ |
475 | public static final int PARENTHESIZED_EXPRESSION = 36; |
476 | |
477 | /** |
478 | * Node type constant indicating a node of type |
479 | * <code>PostfixExpression</code>. |
480 | * @see PostfixExpression |
481 | */ |
482 | public static final int POSTFIX_EXPRESSION = 37; |
483 | |
484 | /** |
485 | * Node type constant indicating a node of type |
486 | * <code>PrefixExpression</code>. |
487 | * @see PrefixExpression |
488 | */ |
489 | public static final int PREFIX_EXPRESSION = 38; |
490 | |
491 | /** |
492 | * Node type constant indicating a node of type |
493 | * <code>PrimitiveType</code>. |
494 | * @see PrimitiveType |
495 | */ |
496 | public static final int PRIMITIVE_TYPE = 39; |
497 | |
498 | /** |
499 | * Node type constant indicating a node of type |
500 | * <code>QualifiedName</code>. |
501 | * @see QualifiedName |
502 | */ |
503 | public static final int QUALIFIED_NAME = 40; |
504 | |
505 | /** |
506 | * Node type constant indicating a node of type |
507 | * <code>ReturnStatement</code>. |
508 | * @see ReturnStatement |
509 | */ |
510 | public static final int RETURN_STATEMENT = 41; |
511 | |
512 | /** |
513 | * Node type constant indicating a node of type |
514 | * <code>SimpleName</code>. |
515 | * @see SimpleName |
516 | */ |
517 | public static final int SIMPLE_NAME = 42; |
518 | |
519 | /** |
520 | * Node type constant indicating a node of type |
521 | * <code>SimpleType</code>. |
522 | * @see SimpleType |
523 | */ |
524 | public static final int SIMPLE_TYPE = 43; |
525 | |
526 | /** |
527 | * Node type constant indicating a node of type |
528 | * <code>SingleVariableDeclaration</code>. |
529 | * @see SingleVariableDeclaration |
530 | */ |
531 | public static final int SINGLE_VARIABLE_DECLARATION = 44; |
532 | |
533 | /** |
534 | * Node type constant indicating a node of type |
535 | * <code>StringLiteral</code>. |
536 | * @see StringLiteral |
537 | */ |
538 | public static final int STRING_LITERAL = 45; |
539 | |
540 | /** |
541 | * Node type constant indicating a node of type |
542 | * <code>SuperConstructorInvocation</code>. |
543 | * @see SuperConstructorInvocation |
544 | */ |
545 | public static final int SUPER_CONSTRUCTOR_INVOCATION = 46; |
546 | |
547 | /** |
548 | * Node type constant indicating a node of type |
549 | * <code>SuperFieldAccess</code>. |
550 | * @see SuperFieldAccess |
551 | */ |
552 | public static final int SUPER_FIELD_ACCESS = 47; |
553 | |
554 | /** |
555 | * Node type constant indicating a node of type |
556 | * <code>SuperMethodInvocation</code>. |
557 | * @see SuperMethodInvocation |
558 | */ |
559 | public static final int SUPER_METHOD_INVOCATION = 48; |
560 | |
561 | /** |
562 | * Node type constant indicating a node of type |
563 | * <code>SwitchCase</code>. |
564 | * @see SwitchCase |
565 | */ |
566 | public static final int SWITCH_CASE = 49; |
567 | |
568 | /** |
569 | * Node type constant indicating a node of type |
570 | * <code>SwitchStatement</code>. |
571 | * @see SwitchStatement |
572 | */ |
573 | public static final int SWITCH_STATEMENT = 50; |
574 | |
575 | /** |
576 | * Node type constant indicating a node of type |
577 | * <code>SynchronizedStatement</code>. |
578 | * @see SynchronizedStatement |
579 | */ |
580 | public static final int SYNCHRONIZED_STATEMENT = 51; |
581 | |
582 | /** |
583 | * Node type constant indicating a node of type |
584 | * <code>ThisExpression</code>. |
585 | * @see ThisExpression |
586 | */ |
587 | public static final int THIS_EXPRESSION = 52; |
588 | |
589 | /** |
590 | * Node type constant indicating a node of type |
591 | * <code>ThrowStatement</code>. |
592 | * @see ThrowStatement |
593 | */ |
594 | public static final int THROW_STATEMENT = 53; |
595 | |
596 | /** |
597 | * Node type constant indicating a node of type |
598 | * <code>TryStatement</code>. |
599 | * @see TryStatement |
600 | */ |
601 | public static final int TRY_STATEMENT = 54; |
602 | |
603 | /** |
604 | * Node type constant indicating a node of type |
605 | * <code>TypeDeclaration</code>. |
606 | * @see TypeDeclaration |
607 | */ |
608 | public static final int TYPE_DECLARATION = 55; |
609 | |
610 | /** |
611 | * Node type constant indicating a node of type |
612 | * <code>TypeDeclarationStatement</code>. |
613 | * @see TypeDeclarationStatement |
614 | */ |
615 | public static final int TYPE_DECLARATION_STATEMENT = 56; |
616 | |
617 | /** |
618 | * Node type constant indicating a node of type |
619 | * <code>TypeLiteral</code>. |
620 | * @see TypeLiteral |
621 | */ |
622 | public static final int TYPE_LITERAL = 57; |
623 | |
624 | /** |
625 | * Node type constant indicating a node of type |
626 | * <code>VariableDeclarationExpression</code>. |
627 | * @see VariableDeclarationExpression |
628 | */ |
629 | public static final int VARIABLE_DECLARATION_EXPRESSION = 58; |
630 | |
631 | /** |
632 | * Node type constant indicating a node of type |
633 | * <code>VariableDeclarationFragment</code>. |
634 | * @see VariableDeclarationFragment |
635 | */ |
636 | public static final int VARIABLE_DECLARATION_FRAGMENT = 59; |
637 | |
638 | /** |
639 | * Node type constant indicating a node of type |
640 | * <code>VariableDeclarationStatement</code>. |
641 | * @see VariableDeclarationStatement |
642 | */ |
643 | public static final int VARIABLE_DECLARATION_STATEMENT = 60; |
644 | |
645 | /** |
646 | * Node type constant indicating a node of type |
647 | * <code>WhileStatement</code>. |
648 | * @see WhileStatement |
649 | */ |
650 | public static final int WHILE_STATEMENT = 61; |
651 | |
652 | /** |
653 | * Node type constant indicating a node of type |
654 | * <code>InstanceofExpression</code>. |
655 | * @see InstanceofExpression |
656 | */ |
657 | public static final int INSTANCEOF_EXPRESSION = 62; |
658 | |
659 | /** |
660 | * Node type constant indicating a node of type |
661 | * <code>LineComment</code>. |
662 | * @see LineComment |
663 | * @since 3.0 |
664 | */ |
665 | public static final int LINE_COMMENT = 63; |
666 | |
667 | /** |
668 | * Node type constant indicating a node of type |
669 | * <code>BlockComment</code>. |
670 | * @see BlockComment |
671 | * @since 3.0 |
672 | */ |
673 | public static final int BLOCK_COMMENT = 64; |
674 | |
675 | /** |
676 | * Node type constant indicating a node of type |
677 | * <code>TagElement</code>. |
678 | * @see TagElement |
679 | * @since 3.0 |
680 | */ |
681 | public static final int TAG_ELEMENT = 65; |
682 | |
683 | /** |
684 | * Node type constant indicating a node of type |
685 | * <code>TextElement</code>. |
686 | * @see TextElement |
687 | * @since 3.0 |
688 | */ |
689 | public static final int TEXT_ELEMENT = 66; |
690 | |
691 | /** |
692 | * Node type constant indicating a node of type |
693 | * <code>MemberRef</code>. |
694 | * @see MemberRef |
695 | * @since 3.0 |
696 | */ |
697 | public static final int MEMBER_REF = 67; |
698 | |
699 | /** |
700 | * Node type constant indicating a node of type |
701 | * <code>MethodRef</code>. |
702 | * @see MethodRef |
703 | * @since 3.0 |
704 | */ |
705 | public static final int METHOD_REF = 68; |
706 | |
707 | /** |
708 | * Node type constant indicating a node of type |
709 | * <code>MethodRefParameter</code>. |
710 | * @see MethodRefParameter |
711 | * @since 3.0 |
712 | */ |
713 | public static final int METHOD_REF_PARAMETER = 69; |
714 | |
715 | /** |
716 | * Node type constant indicating a node of type |
717 | * <code>EnhancedForStatement</code>. |
718 | * @see EnhancedForStatement |
719 | * @since 3.1 |
720 | */ |
721 | public static final int ENHANCED_FOR_STATEMENT = 70; |
722 | |
723 | /** |
724 | * Node type constant indicating a node of type |
725 | * <code>EnumDeclaration</code>. |
726 | * @see EnumDeclaration |
727 | * @since 3.1 |
728 | */ |
729 | public static final int ENUM_DECLARATION = 71; |
730 | |
731 | /** |
732 | * Node type constant indicating a node of type |
733 | * <code>EnumConstantDeclaration</code>. |
734 | * @see EnumConstantDeclaration |
735 | * @since 3.1 |
736 | */ |
737 | public static final int ENUM_CONSTANT_DECLARATION = 72; |
738 | |
739 | /** |
740 | * Node type constant indicating a node of type |
741 | * <code>TypeParameter</code>. |
742 | * @see TypeParameter |
743 | * @since 3.1 |
744 | */ |
745 | public static final int TYPE_PARAMETER = 73; |
746 | |
747 | /** |
748 | * Node type constant indicating a node of type |
749 | * <code>ParameterizedType</code>. |
750 | * @see ParameterizedType |
751 | * @since 3.1 |
752 | */ |
753 | public static final int PARAMETERIZED_TYPE = 74; |
754 | |
755 | /** |
756 | * Node type constant indicating a node of type |
757 | * <code>QualifiedType</code>. |
758 | * @see QualifiedType |
759 | * @since 3.1 |
760 | */ |
761 | public static final int QUALIFIED_TYPE = 75; |
762 | |
763 | /** |
764 | * Node type constant indicating a node of type |
765 | * <code>WildcardType</code>. |
766 | * @see WildcardType |
767 | * @since 3.1 |
768 | */ |
769 | public static final int WILDCARD_TYPE = 76; |
770 | |
771 | /** |
772 | * Node type constant indicating a node of type |
773 | * <code>NormalAnnotation</code>. |
774 | * @see NormalAnnotation |
775 | * @since 3.1 |
776 | */ |
777 | public static final int NORMAL_ANNOTATION = 77; |
778 | |
779 | /** |
780 | * Node type constant indicating a node of type |
781 | * <code>MarkerAnnotation</code>. |
782 | * @see MarkerAnnotation |
783 | * @since 3.1 |
784 | */ |
785 | public static final int MARKER_ANNOTATION = 78; |
786 | |
787 | /** |
788 | * Node type constant indicating a node of type |
789 | * <code>SingleMemberAnnotation</code>. |
790 | * @see SingleMemberAnnotation |
791 | * @since 3.1 |
792 | */ |
793 | public static final int SINGLE_MEMBER_ANNOTATION = 79; |
794 | |
795 | /** |
796 | * Node type constant indicating a node of type |
797 | * <code>MemberValuePair</code>. |
798 | * @see MemberValuePair |
799 | * @since 3.1 |
800 | */ |
801 | public static final int MEMBER_VALUE_PAIR = 80; |
802 | |
803 | /** |
804 | * Node type constant indicating a node of type |
805 | * <code>AnnotationTypeDeclaration</code>. |
806 | * @see AnnotationTypeDeclaration |
807 | * @since 3.1 |
808 | */ |
809 | public static final int ANNOTATION_TYPE_DECLARATION = 81; |
810 | |
811 | /** |
812 | * Node type constant indicating a node of type |
813 | * <code>AnnotationTypeMemberDeclaration</code>. |
814 | * @see AnnotationTypeMemberDeclaration |
815 | * @since 3.1 |
816 | */ |
817 | public static final int ANNOTATION_TYPE_MEMBER_DECLARATION = 82; |
818 | |
819 | /** |
820 | * Node type constant indicating a node of type |
821 | * <code>Modifier</code>. |
822 | * @see Modifier |
823 | * @since 3.1 |
824 | */ |
825 | public static final int MODIFIER = 83; |
826 | |
827 | /** |
828 | * Node type constant indicating a node of type |
829 | * <code>UnionType</code>. |
830 | * @see UnionType |
831 | * @since 3.7.1 |
832 | */ |
833 | public static final int UNION_TYPE = 84; |
834 | |
835 | /** |
836 | * Node type constant indicating a node of type |
837 | * <code>Dimension</code>. |
838 | * |
839 | * @see Dimension |
840 | * @since 3.10 |
841 | */ |
842 | public static final int DIMENSION = 85; |
843 | |
844 | /** |
845 | * Node type constant indicating a node of type |
846 | * <code>LambdaExpression</code>. |
847 | * @see LambdaExpression |
848 | * @since 3.10 |
849 | */ |
850 | public static final int LAMBDA_EXPRESSION = 86; |
851 | |
852 | /** |
853 | * Node type constant indicating a node of type |
854 | * <code>IntersectionType</code>. |
855 | * |
856 | * @see IntersectionType |
857 | * @since 3.10 |
858 | */ |
859 | public static final int INTERSECTION_TYPE = 87; |
860 | |
861 | /** |
862 | * Node type constant indicating a node of type |
863 | * <code>NameQualifiedType</code>. |
864 | * @see NameQualifiedType |
865 | * @since 3.10 |
866 | */ |
867 | public static final int NAME_QUALIFIED_TYPE = 88; |
868 | |
869 | /** |
870 | * Node type constant indicating a node of type |
871 | * <code>CreationReference</code>. |
872 | * @see CreationReference |
873 | * @since 3.10 |
874 | */ |
875 | public static final int CREATION_REFERENCE = 89; |
876 | |
877 | /** |
878 | * Node type constant indicating a node of type |
879 | * <code>ExpressionMethodReference</code>. |
880 | * @see ExpressionMethodReference |
881 | * @since 3.10 |
882 | */ |
883 | public static final int EXPRESSION_METHOD_REFERENCE = 90; |
884 | |
885 | /** |
886 | * Node type constant indicating a node of type |
887 | * <code>SuperMethhodReference</code>. |
888 | * @see SuperMethodReference |
889 | * @since 3.10 |
890 | */ |
891 | public static final int SUPER_METHOD_REFERENCE = 91; |
892 | |
893 | /** |
894 | * Node type constant indicating a node of type |
895 | * <code>TypeMethodReference</code>. |
896 | * @see TypeMethodReference |
897 | * @since 3.10 |
898 | */ |
899 | public static final int TYPE_METHOD_REFERENCE = 92; |
900 | |
901 | /** |
902 | * Node type constant indicating a node of type |
903 | * <code>ModuleDeclaration</code>. |
904 | * @see ModuleDeclaration |
905 | * @since 3.14 |
906 | */ |
907 | public static final int MODULE_DECLARATION = 93; |
908 | |
909 | /** |
910 | * Node type constant indicating a node of type |
911 | * <code>RequiresDirective</code>. |
912 | * @see RequiresDirective |
913 | * @since 3.14 |
914 | */ |
915 | public static final int REQUIRES_DIRECTIVE = 94; |
916 | |
917 | /** |
918 | * Node type constant indicating a node of type |
919 | * <code>ExportsDirective</code>. |
920 | * @see ExportsDirective |
921 | * @since 3.14 |
922 | */ |
923 | public static final int EXPORTS_DIRECTIVE = 95; |
924 | |
925 | /** |
926 | * Node type constant indicating a node of type |
927 | * <code>OpensDirective</code>. |
928 | * @see OpensDirective |
929 | * @since 3.14 |
930 | */ |
931 | public static final int OPENS_DIRECTIVE = 96; |
932 | |
933 | /** |
934 | * Node type constant indicating a node of type |
935 | * <code>UsesDirective</code>. |
936 | * @see UsesDirective |
937 | * @since 3.14 |
938 | */ |
939 | public static final int USES_DIRECTIVE = 97; |
940 | |
941 | /** |
942 | * Node type constant indicating a node of type |
943 | * <code>ProvidesDirective</code>. |
944 | * @see ProvidesDirective |
945 | * @since 3.14 |
946 | */ |
947 | public static final int PROVIDES_DIRECTIVE = 98; |
948 | |
949 | /** |
950 | * Node type constant indicating a node of type |
951 | * <code>ModuleModifier</code>. |
952 | * @see ModuleModifier |
953 | * @since 3.14 |
954 | */ |
955 | public static final int MODULE_MODIFIER = 99; |
956 | |
957 | /** |
958 | * Node type constant indicating a node of type |
959 | * <code>SwitchExpression</code>. |
960 | * @see SwitchExpression |
961 | * @since 3.18 |
962 | */ |
963 | public static final int SWITCH_EXPRESSION = 100; |
964 | |
965 | /** |
966 | * Node type constant indicating a node of type |
967 | * <code>YieldStatement</code>. |
968 | * @see YieldStatement |
969 | * @since 3.20 |
970 | */ |
971 | public static final int YIELD_STATEMENT = 101; |
972 | |
973 | /** |
974 | * Node type constant indicating a node of type |
975 | * <code>TextBlock</code>. |
976 | * @see TextBlock |
977 | * @since 3.20 |
978 | */ |
979 | public static final int TEXT_BLOCK = 102; |
980 | |
981 | /** |
982 | * Node type constant indicating a node of type |
983 | * <code>RecordDeclaration</code>. |
984 | * @see RecordDeclaration |
985 | * @since 3.22 |
986 | */ |
987 | public static final int RECORD_DECLARATION = 103; |
988 | |
989 | /** |
990 | * Node type constant indicating a node of type |
991 | * <code>PatternInstanceofExpression</code>. |
992 | * @see PatternInstanceofExpression |
993 | * @since 3.26 |
994 | */ |
995 | public static final int PATTERN_INSTANCEOF_EXPRESSION = 104; |
996 | |
997 | /** |
998 | * Node type constant indicating a node of type |
999 | * <code>ModuleQualifiedName</code>. |
1000 | * @see ModuleQualifiedName |
1001 | * @since 3.24 |
1002 | */ |
1003 | public static final int MODULE_QUALIFIED_NAME = 105; |
1004 | |
1005 | |
1006 | /** |
1007 | * Node type constant indicating a node of type |
1008 | * <code>TypePattern</code>. |
1009 | * @see TypePattern |
1010 | * @since 3.28 |
1011 | */ |
1012 | public static final int TYPE_PATTERN = 106; |
1013 | |
1014 | /** |
1015 | * Node type constant indicating a node of type |
1016 | * <code>GuardedPattern</code>. |
1017 | * @see GuardedPattern |
1018 | * @since 3.28 |
1019 | */ |
1020 | public static final int GUARDED_PATTERN = 107; |
1021 | |
1022 | /** |
1023 | * Node type constant indicating a node of type |
1024 | * <code>NullPattern</code>. |
1025 | * @see NullPattern |
1026 | * @since 3.28 |
1027 | */ |
1028 | public static final int NULL_PATTERN = 108; |
1029 | |
1030 | /** |
1031 | * Node type constant indicating a node of type |
1032 | * <code>CaseDefaultExpression</code>. |
1033 | * @see CaseDefaultExpression |
1034 | * @since 3.28 |
1035 | */ |
1036 | public static final int CASE_DEFAULT_EXPRESSION = 109; |
1037 | |
1038 | /** |
1039 | * Node type constant indicating a node of type |
1040 | * <code>TagProperty</code>. |
1041 | * @see TagProperty |
1042 | * @since 3.30 |
1043 | */ |
1044 | public static final int TAG_PROPERTY = 110; |
1045 | |
1046 | /** |
1047 | * Node type constant indicating a node of type |
1048 | * <code>JavaDocRegion</code>. |
1049 | * @see JavaDocRegion |
1050 | * @since 3.30 |
1051 | */ |
1052 | public static final int JAVADOC_REGION = 111; |
1053 | |
1054 | |
1055 | /** |
1056 | * Returns the node class for the corresponding node type. |
1057 | * |
1058 | * @param nodeType AST node type |
1059 | * @return the corresponding <code>ASTNode</code> subclass |
1060 | * @exception IllegalArgumentException if <code>nodeType</code> is |
1061 | * not a legal AST node type |
1062 | * @see #getNodeType() |
1063 | * @since 3.0 |
1064 | */ |
1065 | public static Class nodeClassForType(int nodeType) { |
1066 | switch (nodeType) { |
1067 | case ANNOTATION_TYPE_DECLARATION : |
1068 | return AnnotationTypeDeclaration.class; |
1069 | case ANNOTATION_TYPE_MEMBER_DECLARATION : |
1070 | return AnnotationTypeMemberDeclaration.class; |
1071 | case ANONYMOUS_CLASS_DECLARATION : |
1072 | return AnonymousClassDeclaration.class; |
1073 | case ARRAY_ACCESS : |
1074 | return ArrayAccess.class; |
1075 | case ARRAY_CREATION : |
1076 | return ArrayCreation.class; |
1077 | case ARRAY_INITIALIZER : |
1078 | return ArrayInitializer.class; |
1079 | case ARRAY_TYPE : |
1080 | return ArrayType.class; |
1081 | case ASSERT_STATEMENT : |
1082 | return AssertStatement.class; |
1083 | case ASSIGNMENT : |
1084 | return Assignment.class; |
1085 | case BLOCK : |
1086 | return Block.class; |
1087 | case BLOCK_COMMENT : |
1088 | return BlockComment.class; |
1089 | case BOOLEAN_LITERAL : |
1090 | return BooleanLiteral.class; |
1091 | case BREAK_STATEMENT : |
1092 | return BreakStatement.class; |
1093 | case CASE_DEFAULT_EXPRESSION : |
1094 | return CaseDefaultExpression.class; |
1095 | case CAST_EXPRESSION : |
1096 | return CastExpression.class; |
1097 | case CATCH_CLAUSE : |
1098 | return CatchClause.class; |
1099 | case CHARACTER_LITERAL : |
1100 | return CharacterLiteral.class; |
1101 | case CLASS_INSTANCE_CREATION : |
1102 | return ClassInstanceCreation.class; |
1103 | case COMPILATION_UNIT : |
1104 | return CompilationUnit.class; |
1105 | case CONDITIONAL_EXPRESSION : |
1106 | return ConditionalExpression.class; |
1107 | case CONSTRUCTOR_INVOCATION : |
1108 | return ConstructorInvocation.class; |
1109 | case CONTINUE_STATEMENT : |
1110 | return ContinueStatement.class; |
1111 | case CREATION_REFERENCE : |
1112 | return CreationReference.class; |
1113 | case DIMENSION: |
1114 | return Dimension.class; |
1115 | case DO_STATEMENT : |
1116 | return DoStatement.class; |
1117 | case EMPTY_STATEMENT : |
1118 | return EmptyStatement.class; |
1119 | case ENHANCED_FOR_STATEMENT : |
1120 | return EnhancedForStatement.class; |
1121 | case ENUM_CONSTANT_DECLARATION : |
1122 | return EnumConstantDeclaration.class; |
1123 | case ENUM_DECLARATION : |
1124 | return EnumDeclaration.class; |
1125 | case EXPORTS_DIRECTIVE : |
1126 | return ExportsDirective.class; |
1127 | case EXPRESSION_METHOD_REFERENCE : |
1128 | return ExpressionMethodReference.class; |
1129 | case EXPRESSION_STATEMENT : |
1130 | return ExpressionStatement.class; |
1131 | case FIELD_ACCESS : |
1132 | return FieldAccess.class; |
1133 | case FIELD_DECLARATION : |
1134 | return FieldDeclaration.class; |
1135 | case FOR_STATEMENT : |
1136 | return ForStatement.class; |
1137 | case GUARDED_PATTERN : |
1138 | return GuardedPattern.class; |
1139 | case IF_STATEMENT : |
1140 | return IfStatement.class; |
1141 | case IMPORT_DECLARATION : |
1142 | return ImportDeclaration.class; |
1143 | case INFIX_EXPRESSION : |
1144 | return InfixExpression.class; |
1145 | case INITIALIZER : |
1146 | return Initializer.class; |
1147 | case INSTANCEOF_EXPRESSION : |
1148 | return InstanceofExpression.class; |
1149 | case INTERSECTION_TYPE: |
1150 | return IntersectionType.class; |
1151 | case JAVADOC : |
1152 | return Javadoc.class; |
1153 | case JAVADOC_REGION : |
1154 | return JavaDocRegion.class; |
1155 | case LABELED_STATEMENT : |
1156 | return LabeledStatement.class; |
1157 | case LAMBDA_EXPRESSION : |
1158 | return LambdaExpression.class; |
1159 | case LINE_COMMENT : |
1160 | return LineComment.class; |
1161 | case MARKER_ANNOTATION : |
1162 | return MarkerAnnotation.class; |
1163 | case MEMBER_REF : |
1164 | return MemberRef.class; |
1165 | case MEMBER_VALUE_PAIR : |
1166 | return MemberValuePair.class; |
1167 | case METHOD_DECLARATION : |
1168 | return MethodDeclaration.class; |
1169 | case METHOD_INVOCATION : |
1170 | return MethodInvocation.class; |
1171 | case METHOD_REF : |
1172 | return MethodRef.class; |
1173 | case METHOD_REF_PARAMETER : |
1174 | return MethodRefParameter.class; |
1175 | case MODIFIER : |
1176 | return Modifier.class; |
1177 | case MODULE_DECLARATION : |
1178 | return ModuleDeclaration.class; |
1179 | case MODULE_MODIFIER : |
1180 | return ModuleModifier.class; |
1181 | case MODULE_QUALIFIED_NAME : |
1182 | return ModuleQualifiedName.class; |
1183 | case NAME_QUALIFIED_TYPE : |
1184 | return NameQualifiedType.class; |
1185 | case NORMAL_ANNOTATION : |
1186 | return NormalAnnotation.class; |
1187 | case NULL_LITERAL : |
1188 | return NullLiteral.class; |
1189 | case NULL_PATTERN : |
1190 | return NullPattern.class; |
1191 | case NUMBER_LITERAL : |
1192 | return NumberLiteral.class; |
1193 | case OPENS_DIRECTIVE : |
1194 | return OpensDirective.class; |
1195 | case PACKAGE_DECLARATION : |
1196 | return PackageDeclaration.class; |
1197 | case PARAMETERIZED_TYPE : |
1198 | return ParameterizedType.class; |
1199 | case PARENTHESIZED_EXPRESSION : |
1200 | return ParenthesizedExpression.class; |
1201 | case PATTERN_INSTANCEOF_EXPRESSION : |
1202 | return PatternInstanceofExpression.class; |
1203 | case POSTFIX_EXPRESSION : |
1204 | return PostfixExpression.class; |
1205 | case PREFIX_EXPRESSION : |
1206 | return PrefixExpression.class; |
1207 | case PRIMITIVE_TYPE : |
1208 | return PrimitiveType.class; |
1209 | case PROVIDES_DIRECTIVE : |
1210 | return ProvidesDirective.class; |
1211 | case QUALIFIED_NAME : |
1212 | return QualifiedName.class; |
1213 | case QUALIFIED_TYPE : |
1214 | return QualifiedType.class; |
1215 | case RECORD_DECLARATION : |
1216 | return RecordDeclaration.class; |
1217 | case REQUIRES_DIRECTIVE : |
1218 | return RequiresDirective.class; |
1219 | case RETURN_STATEMENT : |
1220 | return ReturnStatement.class; |
1221 | case SIMPLE_NAME : |
1222 | return SimpleName.class; |
1223 | case SIMPLE_TYPE : |
1224 | return SimpleType.class; |
1225 | case SINGLE_MEMBER_ANNOTATION : |
1226 | return SingleMemberAnnotation.class; |
1227 | case SINGLE_VARIABLE_DECLARATION : |
1228 | return SingleVariableDeclaration.class; |
1229 | case STRING_LITERAL : |
1230 | return StringLiteral.class; |
1231 | case SUPER_CONSTRUCTOR_INVOCATION : |
1232 | return SuperConstructorInvocation.class; |
1233 | case SUPER_FIELD_ACCESS : |
1234 | return SuperFieldAccess.class; |
1235 | case SUPER_METHOD_INVOCATION : |
1236 | return SuperMethodInvocation.class; |
1237 | case SUPER_METHOD_REFERENCE : |
1238 | return SuperMethodReference.class; |
1239 | case SWITCH_CASE: |
1240 | return SwitchCase.class; |
1241 | case SWITCH_STATEMENT : |
1242 | return SwitchStatement.class; |
1243 | case SWITCH_EXPRESSION : |
1244 | return SwitchExpression.class; |
1245 | case SYNCHRONIZED_STATEMENT : |
1246 | return SynchronizedStatement.class; |
1247 | case TAG_ELEMENT : |
1248 | return TagElement.class; |
1249 | case TAG_PROPERTY : |
1250 | return TagProperty.class; |
1251 | case TEXT_BLOCK : |
1252 | return TextBlock.class; |
1253 | case TEXT_ELEMENT : |
1254 | return TextElement.class; |
1255 | case THIS_EXPRESSION : |
1256 | return ThisExpression.class; |
1257 | case THROW_STATEMENT : |
1258 | return ThrowStatement.class; |
1259 | case TRY_STATEMENT : |
1260 | return TryStatement.class; |
1261 | case TYPE_DECLARATION : |
1262 | return TypeDeclaration.class; |
1263 | case TYPE_DECLARATION_STATEMENT : |
1264 | return TypeDeclarationStatement.class; |
1265 | case TYPE_METHOD_REFERENCE : |
1266 | return TypeMethodReference.class; |
1267 | case TYPE_LITERAL : |
1268 | return TypeLiteral.class; |
1269 | case TYPE_PARAMETER : |
1270 | return TypeParameter.class; |
1271 | case TYPE_PATTERN : |
1272 | return TypePattern.class; |
1273 | case UNION_TYPE : |
1274 | return UnionType.class; |
1275 | case USES_DIRECTIVE : |
1276 | return UsesDirective.class; |
1277 | case VARIABLE_DECLARATION_EXPRESSION : |
1278 | return VariableDeclarationExpression.class; |
1279 | case VARIABLE_DECLARATION_FRAGMENT : |
1280 | return VariableDeclarationFragment.class; |
1281 | case VARIABLE_DECLARATION_STATEMENT : |
1282 | return VariableDeclarationStatement.class; |
1283 | case WHILE_STATEMENT : |
1284 | return WhileStatement.class; |
1285 | case WILDCARD_TYPE : |
1286 | return WildcardType.class; |
1287 | case YIELD_STATEMENT : |
1288 | return YieldStatement.class; |
1289 | } |
1290 | throw new IllegalArgumentException(); |
1291 | } |
1292 | |
1293 | /** |
1294 | * Owning AST. |
1295 | * <p> |
1296 | * N.B. This is a private field, but declared as package-visible |
1297 | * for more efficient access from inner classes. |
1298 | * </p> |
1299 | */ |
1300 | final AST ast; |
1301 | |
1302 | /** |
1303 | * Parent AST node, or <code>null</code> if this node is a root. |
1304 | * Initially <code>null</code>. |
1305 | */ |
1306 | private ASTNode parent = null; |
1307 | |
1308 | /** |
1309 | * An unmodifiable empty map (used to implement <code>properties()</code>). |
1310 | */ |
1311 | private static final Map UNMODIFIABLE_EMPTY_MAP |
1312 | = Collections.unmodifiableMap(new HashMap(1)); |
1313 | |
1314 | /** |
1315 | * Primary field used in representing node properties efficiently. |
1316 | * If <code>null</code>, this node has no properties. |
1317 | * If a {@link String}, this is the name of this node's sole property, |
1318 | * and <code>property2</code> contains its value. |
1319 | * If a {@link Map}, this is the table of property name-value |
1320 | * mappings; <code>property2</code>, if non-null is its unmodifiable |
1321 | * equivalent. |
1322 | * Initially <code>null</code>. |
1323 | * |
1324 | * @see #property2 |
1325 | */ |
1326 | private Object property1 = null; |
1327 | |
1328 | /** |
1329 | * Auxiliary field used in representing node properties efficiently. |
1330 | * |
1331 | * @see #property1 |
1332 | */ |
1333 | private Object property2 = null; |
1334 | |
1335 | /** |
1336 | * A character index into the original source string, |
1337 | * or <code>-1</code> if no source position information is available |
1338 | * for this node; <code>-1</code> by default. |
1339 | */ |
1340 | private int startPosition = -1; |
1341 | |
1342 | /** |
1343 | * A character length, or <code>0</code> if no source position |
1344 | * information is recorded for this node; <code>0</code> by default. |
1345 | */ |
1346 | private int length = 0; |
1347 | |
1348 | /** |
1349 | * Flag constant (bit mask, value 1) indicating that there is something |
1350 | * not quite right with this AST node. |
1351 | * <p> |
1352 | * The standard parser (<code>ASTParser</code>) sets this |
1353 | * flag on a node to indicate a syntax error detected in the vicinity. |
1354 | * </p> |
1355 | */ |
1356 | public static final int MALFORMED = 1; |
1357 | |
1358 | /** |
1359 | * Flag constant (bit mask, value 2) indicating that this is a node |
1360 | * that was created by the parser (as opposed to one created by another |
1361 | * party). |
1362 | * <p> |
1363 | * The standard parser (<code>ASTParser</code>) sets this |
1364 | * flag on the nodes it creates. |
1365 | * </p> |
1366 | * @since 3.0 |
1367 | */ |
1368 | public static final int ORIGINAL = 2; |
1369 | |
1370 | /** |
1371 | * Flag constant (bit mask, value 4) indicating that this node |
1372 | * is unmodifiable. When a node is marked unmodifiable, the |
1373 | * following operations result in a runtime exception: |
1374 | * <ul> |
1375 | * <li>Change a simple property of this node.</li> |
1376 | * <li>Add or remove a child node from this node.</li> |
1377 | * <li>Parent (or reparent) this node.</li> |
1378 | * </ul> |
1379 | * <p> |
1380 | * The standard parser (<code>ASTParser</code>) does not set |
1381 | * this flag on the nodes it creates. However, clients may set |
1382 | * this flag on a node to prevent further modification of the |
1383 | * its structural properties. |
1384 | * </p> |
1385 | * @since 3.0 |
1386 | */ |
1387 | public static final int PROTECT = 4; |
1388 | |
1389 | /** |
1390 | * Flag constant (bit mask, value 8) indicating that this node |
1391 | * or a part of this node is recovered from source that contains |
1392 | * a syntax error detected in the vicinity. |
1393 | * <p> |
1394 | * The standard parser (<code>ASTParser</code>) sets this |
1395 | * flag on a node to indicate a recovered node. |
1396 | * </p> |
1397 | * @since 3.2 |
1398 | */ |
1399 | public static final int RECOVERED = 8; |
1400 | |
1401 | /** |
1402 | * int containing the node type in the top 16 bits and |
1403 | * flags in the bottom 16 bits; none set by default. |
1404 | * <p> |
1405 | * N.B. This is a private field, but declared as package-visible |
1406 | * for more efficient access from inner classes. |
1407 | * </p> |
1408 | * |
1409 | * @see #MALFORMED |
1410 | */ |
1411 | int typeAndFlags = 0; |
1412 | |
1413 | /** |
1414 | * Property of parent in which this node is a child, or <code>null</code> |
1415 | * if this node is a root. Initially <code>null</code>. |
1416 | * |
1417 | * @see #getLocationInParent |
1418 | * @since 3.0 |
1419 | */ |
1420 | private StructuralPropertyDescriptor location = null; |
1421 | |
1422 | /** Internal convenience constant indicating that there is definite risk of cycles. |
1423 | * @see ChildPropertyDescriptor#cycleRisk() |
1424 | * @see ChildListPropertyDescriptor#cycleRisk() |
1425 | * @since 3.0 |
1426 | */ |
1427 | static final boolean CYCLE_RISK = true; |
1428 | |
1429 | /** Internal convenience constant indicating that there is no risk of cycles. |
1430 | * @see ChildPropertyDescriptor#cycleRisk() |
1431 | * @see ChildListPropertyDescriptor#cycleRisk() |
1432 | * @since 3.0 |
1433 | */ |
1434 | static final boolean NO_CYCLE_RISK = false; |
1435 | |
1436 | /** Internal convenience constant indicating that a structural property is mandatory. |
1437 | * @since 3.0 |
1438 | */ |
1439 | static final boolean MANDATORY = true; |
1440 | |
1441 | /** Internal convenience constant indicating that a structural property is optional. |
1442 | * @since 3.0 |
1443 | */ |
1444 | static final boolean OPTIONAL = false; |
1445 | |
1446 | /** |
1447 | * A specialized implementation of a list of ASTNodes. The |
1448 | * implementation is based on an ArrayList. |
1449 | */ |
1450 | class NodeList extends AbstractList { |
1451 | |
1452 | /** |
1453 | * The underlying list in which the nodes of this list are |
1454 | * stored (element type: {@link ASTNode}). |
1455 | * <p> |
1456 | * Be stingy on storage - assume that list will be empty. |
1457 | * </p> |
1458 | * <p> |
1459 | * This field declared default visibility (rather than private) |
1460 | * so that accesses from <code>NodeList.Cursor</code> do not require |
1461 | * a synthetic accessor method. |
1462 | * </p> |
1463 | */ |
1464 | ArrayList store = new ArrayList(0); |
1465 | |
1466 | /** |
1467 | * The property descriptor for this list. |
1468 | */ |
1469 | ChildListPropertyDescriptor propertyDescriptor; |
1470 | |
1471 | /** |
1472 | * A cursor for iterating over the elements of the list. |
1473 | * Does not lose its position if the list is changed during |
1474 | * the iteration. |
1475 | */ |
1476 | class Cursor implements Iterator { |
1477 | /** |
1478 | * The position of the cursor between elements. If the value |
1479 | * is N, then the cursor sits between the element at positions |
1480 | * N-1 and N. Initially just before the first element of the |
1481 | * list. |
1482 | */ |
1483 | private int position = 0; |
1484 | |
1485 | @Override |
1486 | public boolean hasNext() { |
1487 | return this.position < NodeList.this.store.size(); |
1488 | } |
1489 | |
1490 | @Override |
1491 | public Object next() { |
1492 | Object result = NodeList.this.store.get(this.position); |
1493 | this.position++; |
1494 | return result; |
1495 | } |
1496 | |
1497 | @Override |
1498 | public void remove() { |
1499 | throw new UnsupportedOperationException(); |
1500 | } |
1501 | |
1502 | /** |
1503 | * Adjusts this cursor to accommodate an add/remove at the given |
1504 | * index. |
1505 | * |
1506 | * @param index the position at which the element was added |
1507 | * or removed |
1508 | * @param delta +1 for add, and -1 for remove |
1509 | */ |
1510 | void update(int index, int delta) { |
1511 | if (this.position > index) { |
1512 | // the cursor has passed the added or removed element |
1513 | this.position += delta; |
1514 | } |
1515 | } |
1516 | } |
1517 | |
1518 | /** |
1519 | * A list of currently active cursors (element type: |
1520 | * {@link Cursor}), or <code>null</code> if there are no |
1521 | * active cursors. |
1522 | * <p> |
1523 | * It is important for storage considerations to maintain the |
1524 | * null-means-empty invariant; otherwise, every NodeList instance |
1525 | * will waste a lot of space. A cursor is needed only for the duration |
1526 | * of a visit to the child nodes. Under normal circumstances, only a |
1527 | * single cursor is needed; multiple cursors are only required if there |
1528 | * are multiple visits going on at the same time. |
1529 | * </p> |
1530 | */ |
1531 | private List cursors = null; |
1532 | |
1533 | /** |
1534 | * Creates a new empty list of nodes owned by this node. |
1535 | * This node will be the common parent of all nodes added to |
1536 | * this list. |
1537 | * |
1538 | * @param property the property descriptor |
1539 | * @since 3.0 |
1540 | */ |
1541 | NodeList(ChildListPropertyDescriptor property) { |
1542 | super(); |
1543 | this.propertyDescriptor = property; |
1544 | } |
1545 | |
1546 | @Override |
1547 | public int size() { |
1548 | return this.store.size(); |
1549 | } |
1550 | |
1551 | @Override |
1552 | public Object get(int index) { |
1553 | return this.store.get(index); |
1554 | } |
1555 | |
1556 | @Override |
1557 | public Object set(int index, Object element) { |
1558 | if (element == null) { |
1559 | throw new IllegalArgumentException(); |
1560 | } |
1561 | if ((ASTNode.this.typeAndFlags & PROTECT) != 0) { |
1562 | // this node is protected => cannot gain or lose children |
1563 | throw new IllegalArgumentException("AST node cannot be modified"); //$NON-NLS-1$ |
1564 | } |
1565 | // delink old child from parent, and link new child to parent |
1566 | ASTNode newChild = (ASTNode) element; |
1567 | ASTNode oldChild = (ASTNode) this.store.get(index); |
1568 | if (oldChild == newChild) { |
1569 | return oldChild; |
1570 | } |
1571 | if ((oldChild.typeAndFlags & PROTECT) != 0) { |
1572 | // old child is protected => cannot be unparented |
1573 | throw new IllegalArgumentException("AST node cannot be modified"); //$NON-NLS-1$ |
1574 | } |
1575 | ASTNode.checkNewChild(ASTNode.this, newChild, this.propertyDescriptor.cycleRisk, this.propertyDescriptor.elementType); |
1576 | ASTNode.this.ast.preReplaceChildEvent(ASTNode.this, oldChild, newChild, this.propertyDescriptor); |
1577 | |
1578 | Object result = this.store.set(index, newChild); |
1579 | // n.b. setParent will call ast.modifying() |
1580 | oldChild.setParent(null, null); |
1581 | newChild.setParent(ASTNode.this, this.propertyDescriptor); |
1582 | ASTNode.this.ast.postReplaceChildEvent(ASTNode.this, oldChild, newChild, this.propertyDescriptor); |
1583 | return result; |
1584 | } |
1585 | |
1586 | @Override |
1587 | public void add(int index, Object element) { |
1588 | if (element == null) { |
1589 | throw new IllegalArgumentException(); |
1590 | } |
1591 | if ((ASTNode.this.typeAndFlags & PROTECT) != 0) { |
1592 | // this node is protected => cannot gain or lose children |
1593 | throw new IllegalArgumentException("AST node cannot be modified"); //$NON-NLS-1$ |
1594 | } |
1595 | // link new child to parent |
1596 | ASTNode newChild = (ASTNode) element; |
1597 | ASTNode.checkNewChild(ASTNode.this, newChild, this.propertyDescriptor.cycleRisk, this.propertyDescriptor.elementType); |
1598 | ASTNode.this.ast.preAddChildEvent(ASTNode.this, newChild, this.propertyDescriptor); |
1599 | |
1600 | |
1601 | this.store.add(index, element); |
1602 | updateCursors(index, +1); |
1603 | // n.b. setParent will call ast.modifying() |
1604 | newChild.setParent(ASTNode.this, this.propertyDescriptor); |
1605 | ASTNode.this.ast.postAddChildEvent(ASTNode.this, newChild, this.propertyDescriptor); |
1606 | } |
1607 | |
1608 | @Override |
1609 | public Object remove(int index) { |
1610 | if ((ASTNode.this.typeAndFlags & PROTECT) != 0) { |
1611 | // this node is protected => cannot gain or lose children |
1612 | throw new IllegalArgumentException("AST node cannot be modified"); //$NON-NLS-1$ |
1613 | } |
1614 | // delink old child from parent |
1615 | ASTNode oldChild = (ASTNode) this.store.get(index); |
1616 | if ((oldChild.typeAndFlags & PROTECT) != 0) { |
1617 | // old child is protected => cannot be unparented |
1618 | throw new IllegalArgumentException("AST node cannot be modified"); //$NON-NLS-1$ |
1619 | } |
1620 | |
1621 | ASTNode.this.ast.preRemoveChildEvent(ASTNode.this, oldChild, this.propertyDescriptor); |
1622 | // n.b. setParent will call ast.modifying() |
1623 | oldChild.setParent(null, null); |
1624 | Object result = this.store.remove(index); |
1625 | updateCursors(index, -1); |
1626 | ASTNode.this.ast.postRemoveChildEvent(ASTNode.this, oldChild, this.propertyDescriptor); |
1627 | return result; |
1628 | |
1629 | } |
1630 | |
1631 | /** |
1632 | * Allocate a cursor to use for a visit. The client must call |
1633 | * <code>releaseCursor</code> when done. |
1634 | * <p> |
1635 | * This method is internally synchronized on this NodeList. |
1636 | * It is thread-safe to create a cursor. |
1637 | * </p> |
1638 | * |
1639 | * @return a new cursor positioned before the first element |
1640 | * of the list |
1641 | */ |
1642 | Cursor newCursor() { |
1643 | synchronized (this) { |
1644 | // serialize cursor management on this NodeList |
1645 | if (this.cursors == null) { |
1646 | // convert null to empty list |
1647 | this.cursors = new ArrayList(1); |
1648 | } |
1649 | Cursor result = new Cursor(); |
1650 | this.cursors.add(result); |
1651 | return result; |
1652 | } |
1653 | } |
1654 | |
1655 | /** |
1656 | * Releases the given cursor at the end of a visit. |
1657 | * <p> |
1658 | * This method is internally synchronized on this NodeList. |
1659 | * It is thread-safe to release a cursor. |
1660 | * </p> |
1661 | * |
1662 | * @param cursor the cursor |
1663 | */ |
1664 | void releaseCursor(Cursor cursor) { |
1665 | synchronized (this) { |
1666 | // serialize cursor management on this NodeList |
1667 | this.cursors.remove(cursor); |
1668 | if (this.cursors.isEmpty()) { |
1669 | // important: convert empty list back to null |
1670 | // otherwise the node will hang on to needless junk |
1671 | this.cursors = null; |
1672 | } |
1673 | } |
1674 | } |
1675 | |
1676 | /** |
1677 | * Adjusts all cursors to accommodate an add/remove at the given |
1678 | * index. |
1679 | * <p> |
1680 | * This method is only used when the list is being modified. |
1681 | * The AST is not thread-safe if any of the clients are modifying it. |
1682 | * </p> |
1683 | * |
1684 | * @param index the position at which the element was added |
1685 | * or removed |
1686 | * @param delta +1 for add, and -1 for remove |
1687 | */ |
1688 | private synchronized void updateCursors(int index, int delta) { |
1689 | if (this.cursors == null) { |
1690 | // there are no cursors to worry about |
1691 | return; |
1692 | } |
1693 | for (Iterator it = this.cursors.iterator(); it.hasNext(); ) { |
1694 | Cursor c = (Cursor) it.next(); |
1695 | c.update(index, delta); |
1696 | } |
1697 | } |
1698 | |
1699 | /** |
1700 | * Returns an estimate of the memory footprint of this node list |
1701 | * instance in bytes. |
1702 | * <ul> |
1703 | * <li>1 object header for the NodeList instance</li> |
1704 | * <li>5 4-byte fields of the NodeList instance</li> |
1705 | * <li>0 for cursors since null unless walk in progress</li> |
1706 | * <li>1 object header for the ArrayList instance</li> |
1707 | * <li>2 4-byte fields of the ArrayList instance</li> |
1708 | * <li>1 object header for an Object[] instance</li> |
1709 | * <li>4 bytes in array for each element</li> |
1710 | * </ul> |
1711 | * |
1712 | * @return the size of this node list in bytes |
1713 | */ |
1714 | int memSize() { |
1715 | int result = HEADERS + 5 * 4; |
1716 | result += HEADERS + 2 * 4; |
1717 | result += HEADERS + 4 * size(); |
1718 | return result; |
1719 | } |
1720 | |
1721 | /** |
1722 | * Returns an estimate of the memory footprint in bytes of this node |
1723 | * list and all its subtrees. |
1724 | * |
1725 | * @return the size of this list of subtrees in bytes |
1726 | */ |
1727 | int listSize() { |
1728 | int result = memSize(); |
1729 | for (Iterator it = iterator(); it.hasNext(); ) { |
1730 | ASTNode child = (ASTNode) it.next(); |
1731 | result += child.treeSize(); |
1732 | } |
1733 | return result; |
1734 | } |
1735 | } |
1736 | |
1737 | /** |
1738 | * Creates a new AST node owned by the given AST. Once established, |
1739 | * the relationship between an AST node and its owning AST does not change |
1740 | * over the lifetime of the node. The new node has no parent node, |
1741 | * and no properties. |
1742 | * <p> |
1743 | * N.B. This constructor is package-private; all subclasses my be |
1744 | * declared in the same package; clients are unable to declare |
1745 | * additional subclasses. |
1746 | * </p> |
1747 | * |
1748 | * @param ast the AST that is to own this node |
1749 | */ |
1750 | ASTNode(AST ast) { |
1751 | if (ast == null) { |
1752 | throw new IllegalArgumentException(); |
1753 | } |
1754 | |
1755 | this.ast = ast; |
1756 | setNodeType(getNodeType0()); |
1757 | setFlags(ast.getDefaultNodeFlag()); |
1758 | // setFlags calls modifying(); |
1759 | } |
1760 | |
1761 | /** |
1762 | * Returns this node's AST. |
1763 | * <p> |
1764 | * Note that the relationship between an AST node and its owing AST does |
1765 | * not change over the lifetime of a node. |
1766 | * </p> |
1767 | * |
1768 | * @return the AST that owns this node |
1769 | */ |
1770 | public final AST getAST() { |
1771 | return this.ast; |
1772 | } |
1773 | |
1774 | /** |
1775 | * Returns this node's parent node, or <code>null</code> if this is the |
1776 | * root node. |
1777 | * <p> |
1778 | * Note that the relationship between an AST node and its parent node |
1779 | * may change over the lifetime of a node. |
1780 | * </p> |
1781 | * |
1782 | * @return the parent of this node, or <code>null</code> if none |
1783 | */ |
1784 | public final ASTNode getParent() { |
1785 | return this.parent; |
1786 | } |
1787 | |
1788 | /** |
1789 | * Returns the location of this node within its parent, |
1790 | * or <code>null</code> if this is a root node. |
1791 | * <pre> |
1792 | * ASTNode node = ...; |
1793 | * ASTNode parent = node.getParent(); |
1794 | * StructuralPropertyDescriptor location = node.getLocationInParent(); |
1795 | * assert (parent != null) == (location != null); |
1796 | * if ((location != null) && location.isChildProperty()) |
1797 | * assert parent.getStructuralProperty(location) == node; |
1798 | * if ((location != null) && location.isChildListProperty()) |
1799 | * assert ((List) parent.getStructuralProperty(location)).contains(node); |
1800 | * </pre> |
1801 | * <p> |
1802 | * Note that the relationship between an AST node and its parent node |
1803 | * may change over the lifetime of a node. |
1804 | * </p> |
1805 | * |
1806 | * @return the location of this node in its parent, |
1807 | * or <code>null</code> if this node has no parent |
1808 | * @since 3.0 |
1809 | */ |
1810 | public final StructuralPropertyDescriptor getLocationInParent() { |
1811 | return this.location; |
1812 | } |
1813 | |
1814 | /** |
1815 | * Returns the root node at or above this node; returns this node if |
1816 | * it is a root. |
1817 | * |
1818 | * @return the root node at or above this node |
1819 | */ |
1820 | public final ASTNode getRoot() { |
1821 | ASTNode candidate = this; |
1822 | while (true) { |
1823 | ASTNode p = candidate.getParent(); |
1824 | if (p == null) { |
1825 | // candidate has no parent - that's the guy |
1826 | return candidate; |
1827 | } |
1828 | candidate = p; |
1829 | } |
1830 | } |
1831 | |
1832 | /** |
1833 | * Returns the value of the given structural property for this node. The value |
1834 | * returned depends on the kind of property: |
1835 | * <ul> |
1836 | * <li>{@link SimplePropertyDescriptor} - the value of the given simple property, |
1837 | * or <code>null</code> if none; primitive values are "boxed"</li> |
1838 | * <li>{@link ChildPropertyDescriptor} - the child node (type <code>ASTNode</code>), |
1839 | * or <code>null</code> if none</li> |
1840 | * <li>{@link ChildListPropertyDescriptor} - the list (element type: {@link ASTNode})</li> |
1841 | * </ul> |
1842 | * |
1843 | * @param property the property |
1844 | * @return the value, or <code>null</code> if none |
1845 | * @exception RuntimeException if this node does not have the given property |
1846 | * @since 3.0 |
1847 | */ |
1848 | public final Object getStructuralProperty(StructuralPropertyDescriptor property) { |
1849 | if (property instanceof SimplePropertyDescriptor) { |
1850 | SimplePropertyDescriptor p = (SimplePropertyDescriptor) property; |
1851 | if (p.getValueType() == int.class) { |
1852 | int result = internalGetSetIntProperty(p, true, 0); |
1853 | return Integer.valueOf(result); |
1854 | } else if (p.getValueType() == boolean.class) { |
1855 | boolean result = internalGetSetBooleanProperty(p, true, false); |
1856 | return Boolean.valueOf(result); |
1857 | } else { |
1858 | return internalGetSetObjectProperty(p, true, null); |
1859 | } |
1860 | } |
1861 | if (property instanceof ChildPropertyDescriptor) { |
1862 | return internalGetSetChildProperty((ChildPropertyDescriptor) property, true, null); |
1863 | } |
1864 | if (property instanceof ChildListPropertyDescriptor) { |
1865 | return internalGetChildListProperty((ChildListPropertyDescriptor) property); |
1866 | } |
1867 | throw new IllegalArgumentException(); |
1868 | } |
1869 | |
1870 | /** |
1871 | * Sets the value of the given structural property for this node. The value |
1872 | * passed depends on the kind of property: |
1873 | * <ul> |
1874 | * <li>{@link SimplePropertyDescriptor} - the new value of the given simple property, |
1875 | * or <code>null</code> if none; primitive values are "boxed"</li> |
1876 | * <li>{@link ChildPropertyDescriptor} - the new child node (type <code>ASTNode</code>), |
1877 | * or <code>null</code> if none</li> |
1878 | * <li>{@link ChildListPropertyDescriptor} - not allowed</li> |
1879 | * </ul> |
1880 | * |
1881 | * @param property the property |
1882 | * @param value the property value |
1883 | * @exception RuntimeException if this node does not have the |
1884 | * given property, or if the given property cannot be set |
1885 | * @since 3.0 |
1886 | */ |
1887 | public final void setStructuralProperty(StructuralPropertyDescriptor property, Object value) { |
1888 | if (property instanceof SimplePropertyDescriptor) { |
1889 | SimplePropertyDescriptor p = (SimplePropertyDescriptor) property; |
1890 | if (p.getValueType() == int.class) { |
1891 | int arg = ((Integer) value).intValue(); |
1892 | internalGetSetIntProperty(p, false, arg); |
1893 | return; |
1894 | } else if (p.getValueType() == boolean.class) { |
1895 | boolean arg = ((Boolean) value).booleanValue(); |
1896 | internalGetSetBooleanProperty(p, false, arg); |
1897 | return; |
1898 | } else { |
1899 | if (value == null && p.isMandatory()) { |
1900 | throw new IllegalArgumentException(); |
1901 | } |
1902 | internalGetSetObjectProperty(p, false, value); |
1903 | return; |
1904 | } |
1905 | } |
1906 | if (property instanceof ChildPropertyDescriptor) { |
1907 | ChildPropertyDescriptor p = (ChildPropertyDescriptor) property; |
1908 | ASTNode child = (ASTNode) value; |
1909 | if (child == null && p.isMandatory()) { |
1910 | throw new IllegalArgumentException(); |
1911 | } |
1912 | internalGetSetChildProperty(p, false, child); |
1913 | return; |
1914 | } |
1915 | if (property instanceof ChildListPropertyDescriptor) { |
1916 | throw new IllegalArgumentException("Cannot set the list of child list property"); //$NON-NLS-1$ |
1917 | } |
1918 | } |
1919 | |
1920 | /** |
1921 | * Sets the value of the given int-valued property for this node. |
1922 | * The default implementation of this method throws an exception explaining |
1923 | * that this node does not have such a property. This method should be |
1924 | * extended in subclasses that have at least one simple property whose value |
1925 | * type is int. |
1926 | * |
1927 | * @param property the property |
1928 | * @param get <code>true</code> for a get operation, and |
1929 | * <code>false</code> for a set operation |
1930 | * @param value the new property value; ignored for get operations |
1931 | * @return the value; always returns |
1932 | * <code>0</code> for set operations |
1933 | * @exception RuntimeException if this node does not have the |
1934 | * given property, or if the given value cannot be set as specified |
1935 | * @since 3.0 |
1936 | */ |
1937 | int internalGetSetIntProperty(SimplePropertyDescriptor property, boolean get, int value) { |
1938 | throw new RuntimeException("Node does not have this property"); //$NON-NLS-1$ |
1939 | } |
1940 | |
1941 | /** |
1942 | * Sets the value of the given boolean-valued property for this node. |
1943 | * The default implementation of this method throws an exception explaining |
1944 | * that this node does not have such a property. This method should be |
1945 | * extended in subclasses that have at least one simple property whose value |
1946 | * type is boolean. |
1947 | * |
1948 | * @param property the property |
1949 | * @param get <code>true</code> for a get operation, and |
1950 | * <code>false</code> for a set operation |
1951 | * @param value the new property value; ignored for get operations |
1952 | * @return the value; always returns |
1953 | * <code>false</code> for set operations |
1954 | * @exception RuntimeException if this node does not have the |
1955 | * given property, or if the given value cannot be set as specified |
1956 | * @since 3.0 |
1957 | */ |
1958 | boolean internalGetSetBooleanProperty(SimplePropertyDescriptor property, boolean get, boolean value) { |
1959 | throw new RuntimeException("Node does not have this property"); //$NON-NLS-1$ |
1960 | } |
1961 | |
1962 | /** |
1963 | * Sets the value of the given property for this node. |
1964 | * The default implementation of this method throws an exception explaining |
1965 | * that this node does not have such a property. This method should be |
1966 | * extended in subclasses that have at least one simple property whose value |
1967 | * type is a reference type. |
1968 | * |
1969 | * @param property the property |
1970 | * @param get <code>true</code> for a get operation, and |
1971 | * <code>false</code> for a set operation |
1972 | * @param value the new property value, or <code>null</code> if none; |
1973 | * ignored for get operations |
1974 | * @return the value, or <code>null</code> if none; always returns |
1975 | * <code>null</code> for set operations |
1976 | * @exception RuntimeException if this node does not have the |
1977 | * given property, or if the given value cannot be set as specified |
1978 | * @since 3.0 |
1979 | */ |
1980 | Object internalGetSetObjectProperty(SimplePropertyDescriptor property, boolean get, Object value) { |
1981 | throw new RuntimeException("Node does not have this property"); //$NON-NLS-1$ |
1982 | } |
1983 | |
1984 | /** |
1985 | * Sets the child value of the given property for this node. |
1986 | * The default implementation of this method throws an exception explaining |
1987 | * that this node does not have such a property. This method should be |
1988 | * extended in subclasses that have at least one child property. |
1989 | * |
1990 | * @param property the property |
1991 | * @param get <code>true</code> for a get operation, and |
1992 | * <code>false</code> for a set operation |
1993 | * @param child the new child value, or <code>null</code> if none; |
1994 | * always <code>null</code> for get operations |
1995 | * @return the child, or <code>null</code> if none; always returns |
1996 | * <code>null</code> for set operations |
1997 | * @exception RuntimeException if this node does not have the |
1998 | * given property, or if the given child cannot be set as specified |
1999 | * @since 3.0 |
2000 | */ |
2001 | ASTNode internalGetSetChildProperty(ChildPropertyDescriptor property, boolean get, ASTNode child) { |
2002 | throw new RuntimeException("Node does not have this property"); //$NON-NLS-1$ |
2003 | } |
2004 | |
2005 | /** |
2006 | * Returns the list value of the given property for this node. |
2007 | * The default implementation of this method throws an exception explaining |
2008 | * that this node does not have such a property. This method should be |
2009 | * extended in subclasses that have at least one child list property. |
2010 | * |
2011 | * @param property the property |
2012 | * @return the list (element type: {@link ASTNode}) |
2013 | * @exception RuntimeException if the given node does not have the |
2014 | * given property |
2015 | * @since 3.0 |
2016 | */ |
2017 | List internalGetChildListProperty(ChildListPropertyDescriptor property) { |
2018 | throw new RuntimeException("Node does not have this property"); //$NON-NLS-1$ |
2019 | } |
2020 | |
2021 | /** |
2022 | * Returns a list of structural property descriptors for nodes of the |
2023 | * same type as this node. Clients must not modify the result. |
2024 | * <p> |
2025 | * Note that property descriptors are a meta-level mechanism |
2026 | * for manipulating ASTNodes in a generic way. They are |
2027 | * unrelated to <code>get/setProperty</code>. |
2028 | * </p> |
2029 | * |
2030 | * @return a list of property descriptors (element type: |
2031 | * {@link StructuralPropertyDescriptor}) |
2032 | * @since 3.0 |
2033 | */ |
2034 | public final List structuralPropertiesForType() { |
2035 | return internalStructuralPropertiesForType(this.ast.apiLevel, this.ast.isPreviewEnabled()); |
2036 | } |
2037 | |
2038 | /** |
2039 | * Returns a list of property descriptors for this node type. |
2040 | * Clients must not modify the result. This abstract method |
2041 | * must be implemented in each concrete AST node type. |
2042 | * <p> |
2043 | * N.B. This method is package-private, so that the implementations |
2044 | * of this method in each of the concrete AST node types do not |
2045 | * clutter up the API doc. |
2046 | * </p> |
2047 | * |
2048 | * @param apiLevel the API level; one of the <code>AST.JLS*</code> constants |
2049 | * @return a list of property descriptors (element type: |
2050 | * {@link StructuralPropertyDescriptor}) |
2051 | * @since 3.0 |
2052 | */ |
2053 | abstract List internalStructuralPropertiesForType(int apiLevel); |
2054 | |
2055 | |
2056 | /** |
2057 | * Returns a list of property descriptors for this node type. |
2058 | * Clients must not modify the result. This abstract method |
2059 | * must be implemented in each concrete AST node type. |
2060 | * <p> |
2061 | * N.B. This method is package-private, so that the implementations |
2062 | * of this method in each of the concrete AST node types do not |
2063 | * clutter up the API doc. |
2064 | * </p> |
2065 | * |
2066 | * @param apiLevel the API level; one of the <code>AST.JLS*</code> constants |
2067 | * @param previewEnabled the previewEnabled flag |
2068 | * @return a list of property descriptors (element type: |
2069 | * {@link StructuralPropertyDescriptor}) |
2070 | * @since 3.19 |
2071 | */ |
2072 | List internalStructuralPropertiesForType(int apiLevel, boolean previewEnabled) { |
2073 | return internalStructuralPropertiesForType(apiLevel); |
2074 | } |
2075 | |
2076 | /** |
2077 | * Internal helper method that starts the building a list of |
2078 | * property descriptors for the given node type. |
2079 | * |
2080 | * @param nodeClass the class for a concrete node type with n properties |
2081 | * @param propertyList empty list, with capacity for n+1 elements |
2082 | */ |
2083 | static void createPropertyList(Class nodeClass, List propertyList) { |
2084 | // stuff nodeClass at head of list for future ref |
2085 | propertyList.add(nodeClass); |
2086 | } |
2087 | |
2088 | /** |
2089 | * Internal helper method that adding a property descriptor. |
2090 | * |
2091 | * @param property the structural property descriptor |
2092 | * @param propertyList list beginning with the AST node class |
2093 | * followed by accumulated structural property descriptors |
2094 | */ |
2095 | static void addProperty(StructuralPropertyDescriptor property, List propertyList) { |
2096 | Class nodeClass = (Class) propertyList.get(0); |
2097 | if (property.getNodeClass() != nodeClass) { |
2098 | // easily made cut-and-paste mistake |
2099 | throw new RuntimeException("Structural property descriptor has wrong node class!"); //$NON-NLS-1$ |
2100 | } |
2101 | propertyList.add(property); |
2102 | } |
2103 | |
2104 | /** |
2105 | * Internal helper method that completes the building of |
2106 | * a node type's structural property descriptor list. |
2107 | * |
2108 | * @param propertyList list beginning with the AST node class |
2109 | * followed by accumulated structural property descriptors |
2110 | * @return unmodifiable list of structural property descriptors |
2111 | * (element type: {@link StructuralPropertyDescriptor}) |
2112 | */ |
2113 | static List reapPropertyList(List propertyList) { |
2114 | propertyList.remove(0); // remove nodeClass |
2115 | // compact |
2116 | ArrayList a = new ArrayList(propertyList.size()); |
2117 | a.addAll(propertyList); |
2118 | return Collections.unmodifiableList(a); |
2119 | } |
2120 | |
2121 | /** |
2122 | * Checks that this AST operation is not used when |
2123 | * building JLS2 level ASTs. |
2124 | * <p> |
2125 | * Use this method to prevent access to new properties that have been added in JLS3. |
2126 | * </p> |
2127 | * |
2128 | * @exception UnsupportedOperationException if this operation is used in a JLS2 AST |
2129 | * @since 3.0 |
2130 | */ |
2131 | final void unsupportedIn2() { |
2132 | if (this.ast.apiLevel == AST.JLS2_INTERNAL) { |
2133 | throw new UnsupportedOperationException("Operation not supported in JLS2 AST"); //$NON-NLS-1$ |
2134 | } |
2135 | } |
2136 | |
2137 | /** |
2138 | * Checks that this AST operation is not used when |
2139 | * building JLS2 or JLS3 level ASTs. |
2140 | * <p> |
2141 | * Use this method to prevent access to new properties that have been added in JLS4. |
2142 | * </p> |
2143 | * |
2144 | * @exception UnsupportedOperationException if this operation is used in a JLS2 or JLS3 AST |
2145 | * @since 3.7 |
2146 | */ |
2147 | final void unsupportedIn2_3() { |
2148 | if (this.ast.apiLevel <= AST.JLS3_INTERNAL) { |
2149 | throw new UnsupportedOperationException("Operation only supported in JLS4 and later AST"); //$NON-NLS-1$ |
2150 | } |
2151 | } |
2152 | |
2153 | /** |
2154 | * Checks that this AST operation is not used when |
2155 | * building JLS2 or JLS3 or JLS4 level ASTs. |
2156 | * <p> |
2157 | * Use this method to prevent access to new properties that have been added in JLS8. |
2158 | * </p> |
2159 | * |
2160 | * @exception UnsupportedOperationException if this operation is used below JLS8 |
2161 | * @since 3.10 |
2162 | */ |
2163 | final void unsupportedIn2_3_4() { |
2164 | if (this.ast.apiLevel < AST.JLS8_INTERNAL) { |
2165 | throw new UnsupportedOperationException("Operation only supported in JLS8 and later AST"); //$NON-NLS-1$ |
2166 | } |
2167 | } |
2168 | |
2169 | /** |
2170 | * Checks that this AST operation is not used when |
2171 | * building JLS2, JLS3, JLS4 or JLS8 level ASTs. |
2172 | * <p> |
2173 | * Use this method to prevent access to new properties that have been added in JLS9. |
2174 | * </p> |
2175 | * |
2176 | * @exception UnsupportedOperationException if this operation is used below JLS9 |
2177 | * @since 3.14 |
2178 | */ |
2179 | final void unsupportedBelow9() { |
2180 | if (this.ast.apiLevel < AST.JLS9_INTERNAL) { |
2181 | throw new UnsupportedOperationException("Operation only supported in JLS9 and later AST"); //$NON-NLS-1$ |
2182 | } |
2183 | } |
2184 | /** |
2185 | * Checks that this AST operation is not used when |
2186 | * building JLS2, JLS3, JLS4, JLS8 or JLS9 level ASTs. |
2187 | * <p> |
2188 | * Use this method to prevent access to new properties that have been added in JLS10 |
2189 | * </p> |
2190 | * |
2191 | * @exception UnsupportedOperationException if this operation is used below JLS10 |
2192 | * @since 3.14 |
2193 | */ |
2194 | final void unsupportedBelow10() { |
2195 | if (this.ast.apiLevel < AST.JLS10_INTERNAL) { |
2196 | throw new UnsupportedOperationException("Operation only supported in ASTs with level JLS10 and above"); //$NON-NLS-1$ |
2197 | } |
2198 | } |
2199 | /** |
2200 | * Checks that this AST operation is not used when |
2201 | * building JLS2, JLS3, JLS4, JLS8, JLS9 or JLS10 level ASTs. |
2202 | * <p> |
2203 | * Use this method to prevent access to new properties that have been added in JLS11 |
2204 | * </p> |
2205 | * |
2206 | * @exception UnsupportedOperationException if this operation is used below JLS11 |
2207 | * @since 3.14 |
2208 | */ |
2209 | final void unsupportedBelow11() { |
2210 | if (this.ast.apiLevel < AST.JLS11_INTERNAL) { |
2211 | throw new UnsupportedOperationException("Operation only supported in ASTs with level JLS11 and above"); //$NON-NLS-1$ |
2212 | } |
2213 | } |
2214 | |
2215 | /** |
2216 | * Checks that this AST operation is not used when |
2217 | * building JLS2, JLS3, JLS4, JLS8, JLS9,JLS10 or JLS11 level ASTs. |
2218 | * <p> |
2219 | * Use this method to prevent access to new properties that have been added in JLS12 |
2220 | * </p> |
2221 | * |
2222 | * @exception UnsupportedOperationException if this operation is used below JLS12 |
2223 | * @deprecated |
2224 | * @since 3.16 |
2225 | */ |
2226 | final void unsupportedBelow12() { |
2227 | if (this.ast.apiLevel < AST.JLS12_INTERNAL) { |
2228 | throw new UnsupportedOperationException("Operation only supported in ASTs with level JLS12 and above"); //$NON-NLS-1$ |
2229 | } |
2230 | } |
2231 | |
2232 | /** |
2233 | * Checks that this AST operation is not used when |
2234 | * building JLS2, JLS3, JLS4, JLS8, JLS9, JLS10, JLS11, JLS12 or JSL13 level ASTs. |
2235 | * <p> |
2236 | * Use this method to prevent access to new properties that have been added in JLS14 |
2237 | * </p> |
2238 | * |
2239 | * @exception UnsupportedOperationException if this operation is used below JLS14 |
2240 | * @since 3.22 |
2241 | */ |
2242 | final void unsupportedBelow14() { |
2243 | if (this.ast.apiLevel < AST.JLS14_INTERNAL) { |
2244 | throw new UnsupportedOperationException("Operation only supported in ASTs with level JLS14 and above"); //$NON-NLS-1$ |
2245 | } |
2246 | } |
2247 | |
2248 | /** |
2249 | * Checks that this AST operation is not used when |
2250 | * building JLS2, JLS3, JLS4, JLS8, JLS9, JLS10, JLS11, JLS12, JLS13 or JSL14 level ASTs. |
2251 | * <p> |
2252 | * Use this method to prevent access to new properties that have been added in JLS15 |
2253 | * </p> |
2254 | * |
2255 | * @exception UnsupportedOperationException if this operation is used below JLS15 |
2256 | * @since 3.22 |
2257 | */ |
2258 | final void unsupportedBelow15() { |
2259 | if (this.ast.apiLevel < AST.JLS15_INTERNAL) { |
2260 | throw new UnsupportedOperationException("Operation only supported in ASTs with level JLS15 and above"); //$NON-NLS-1$ |
2261 | } |
2262 | } |
2263 | |
2264 | /** |
2265 | * Checks that this AST operation is not used when |
2266 | * building JLS2, JLS3, JLS4, JLS8, JLS9, JLS10, JLS11, JLS12, JLS13, JSL14 or JSL15 level ASTs. |
2267 | * <p> |
2268 | * Use this method to prevent access to new properties that have been added in JLS16 |
2269 | * </p> |
2270 | * |
2271 | * @exception UnsupportedOperationException if this operation is used below JLS16 |
2272 | * @since 3.26 |
2273 | */ |
2274 | final void unsupportedBelow16() { |
2275 | if (this.ast.apiLevel < AST.JLS16_INTERNAL) { |
2276 | throw new UnsupportedOperationException("Operation only supported in ASTs with level JLS16 and above"); //$NON-NLS-1$ |
2277 | } |
2278 | } |
2279 | |
2280 | /** |
2281 | * Checks that this AST operation is not used when |
2282 | * building JLS2, JLS3, JLS4, JLS8, JLS9, JLS10, JLS11, JLS12, JLS13, JSL14, JSL15 or JLS16 level ASTs. |
2283 | * <p> |
2284 | * Use this method to prevent access to new properties that have been added in JLS17 |
2285 | * </p> |
2286 | * |
2287 | * @exception UnsupportedOperationException if this operation is used below JLS17 |
2288 | * @since 3.27 |
2289 | */ |
2290 | final void unsupportedBelow17() { |
2291 | if (this.ast.apiLevel < AST.JLS17_INTERNAL) { |
2292 | throw new UnsupportedOperationException("Operation only supported in ASTs with level JLS17 and above"); //$NON-NLS-1$ |
2293 | } |
2294 | } |
2295 | |
2296 | /** |
2297 | * Checks that this AST operation is not used when |
2298 | * building JLS2, JLS3, JLS4, JLS8, JLS9, JLS10, JLS11, JLS12, JLS13, JSL14, JSL15, JLS16 or JLS17 level ASTs. |
2299 | * <p> |
2300 | * Use this method to prevent access to new properties that have been added in JLS18 |
2301 | * </p> |
2302 | * |
2303 | * @exception UnsupportedOperationException if this operation is used below JLS18 |
2304 | * @since 3.30 |
2305 | */ |
2306 | final void unsupportedBelow18() { |
2307 | if (this.ast.apiLevel < AST.JLS18_INTERNAL) { |
2308 | throw new UnsupportedOperationException("Operation only supported in ASTs with level JLS17 and above"); //$NON-NLS-1$ |
2309 | } |
2310 | } |
2311 | |
2312 | |
2313 | /** |
2314 | * Checks that this AST operation is not used when |
2315 | * building ASTs without previewEnabled flag. |
2316 | * <p> |
2317 | * Use this method to prevent access to new properties that have been added with preview feature |
2318 | * </p> |
2319 | * |
2320 | * @exception UnsupportedOperationException if this operation is used with previewEnabled flag as false |
2321 | * @since 3.19 |
2322 | */ |
2323 | final void unsupportedWithoutPreviewError() { |
2324 | if (!this.ast.isPreviewEnabled()) { |
2325 | throw new UnsupportedOperationException("Operation only supported in ASTs with previewEnabled flag as true"); //$NON-NLS-1$ |
2326 | } |
2327 | } |
2328 | |
2329 | /** |
2330 | * Checks that this AST operation is only used when |
2331 | * building JLS2 level ASTs. |
2332 | * <p> |
2333 | * Use this method to prevent access to deprecated properties (deprecated in JLS3). |
2334 | * </p> |
2335 | * |
2336 | * @exception UnsupportedOperationException if this operation is used in an AST later than JLS2 |
2337 | * @since 3.0 |
2338 | */ |
2339 | // In API Javadocs, add: * @deprecated In the JLS3 API, this method is replaced by {@link #replacement()}. |
2340 | final void supportedOnlyIn2() { |
2341 | if (this.ast.apiLevel != AST.JLS2_INTERNAL) { |
2342 | throw new UnsupportedOperationException("Operation only supported in JLS2 AST"); //$NON-NLS-1$ |
2343 | } |
2344 | } |
2345 | |
2346 | /** |
2347 | * Checks that this AST operation is only used when |
2348 | * building JLS2, JLS3 or JLS4 level ASTs. |
2349 | * <p> |
2350 | * Use this method to prevent access to deprecated properties (deprecated in JLS8). |
2351 | * </p> |
2352 | * |
2353 | * @exception UnsupportedOperationException if this operation is used in an AST later than JLS4 |
2354 | * @since 3.10 |
2355 | */ |
2356 | // In API Javadocs, add: * @deprecated In the JLS8 API, this method is replaced by {@link #replacement()}. |
2357 | final void supportedOnlyIn2_3_4() { |
2358 | if (this.ast.apiLevel >= AST.JLS8_INTERNAL) { |
2359 | throw new UnsupportedOperationException("Operation only supported in JLS2, JLS3 and JLS4 ASTs"); //$NON-NLS-1$ |
2360 | } |
2361 | } |
2362 | |
2363 | /** |
2364 | * Checks that this AST operation is only used when |
2365 | * building JLS12 level ASTs. |
2366 | * <p> |
2367 | * Use this method to prevent access to properties available only in JLS12. |
2368 | * </p> |
2369 | * |
2370 | * @exception UnsupportedOperationException if this operation is is not used in JLS12 |
2371 | * @since 3.20 |
2372 | */ |
2373 | // In API Javadocs, add: * @deprecated In the JLS13 API, this method is replaced by {@link #replacement()}. |
2374 | final void supportedOnlyIn12() { |
2375 | if (this.ast.apiLevel != AST.JLS12_INTERNAL) { |
2376 | throw new UnsupportedOperationException("Operation only supported in JLS12 AST"); //$NON-NLS-1$ |
2377 | } |
2378 | } |
2379 | |
2380 | /** |
2381 | * Checks that this AST operation is only used when |
2382 | * building JLS13 level ASTs. |
2383 | * <p> |
2384 | * Use this method to prevent access to new properties available only in JLS13. |
2385 | * </p> |
2386 | * |
2387 | * @exception UnsupportedOperationException if this operation is not used in JLS13 |
2388 | * @since 3.20 |
2389 | */ |
2390 | final void supportedOnlyIn13() { |
2391 | if (this.ast.apiLevel != AST.JLS13_INTERNAL) { |
2392 | throw new UnsupportedOperationException("Operation only supported in JLS13 AST"); //$NON-NLS-1$ |
2393 | } |
2394 | } |
2395 | |
2396 | /** |
2397 | * Checks that this AST operation is only used when |
2398 | * building JLS14 level ASTs. |
2399 | * <p> |
2400 | * Use this method to prevent access to new properties available only in JLS14. |
2401 | * </p> |
2402 | * |
2403 | * @exception UnsupportedOperationException if this operation is not used in JLS14 |
2404 | * @since 3.20 |
2405 | */ |
2406 | final void supportedOnlyIn14() { |
2407 | if (this.ast.apiLevel != AST.JLS14_INTERNAL) { |
2408 | throw new UnsupportedOperationException("Operation only supported in JLS14 AST"); //$NON-NLS-1$ |
2409 | } |
2410 | } |
2411 | |
2412 | /** |
2413 | * Checks that this AST operation is only used when |
2414 | * building JLS15 level ASTs. |
2415 | * <p> |
2416 | * Use this method to prevent access to new properties available only in JLS15. |
2417 | * </p> |
2418 | * |
2419 | * @exception UnsupportedOperationException if this operation is not used in JLS15 |
2420 | * @since 3.22 |
2421 | */ |
2422 | final void supportedOnlyIn15() { |
2423 | if (this.ast.apiLevel != AST.JLS15_INTERNAL) { |
2424 | throw new UnsupportedOperationException("Operation only supported in JLS15 AST"); //$NON-NLS-1$ |
2425 | } |
2426 | } |
2427 | |
2428 | /** |
2429 | * Checks that this AST operation is only used when |
2430 | * building JLS16 level ASTs. |
2431 | * <p> |
2432 | * Use this method to prevent access to new properties available only in JLS15. |
2433 | * </p> |
2434 | * |
2435 | * @exception UnsupportedOperationException if this operation is not used in JLS15 |
2436 | * @since 3.26 |
2437 | */ |
2438 | final void supportedOnlyIn16() { |
2439 | if (this.ast.apiLevel != AST.JLS16_INTERNAL) { |
2440 | throw new UnsupportedOperationException("Operation only supported in JLS16 AST"); //$NON-NLS-1$ |
2441 | } |
2442 | } |
2443 | |
2444 | /** |
2445 | * Checks that this AST operation is only used when |
2446 | * building JLS17 level ASTs. |
2447 | * <p> |
2448 | * Use this method to prevent access to new properties available only in JLS17. |
2449 | * </p> |
2450 | * |
2451 | * @exception UnsupportedOperationException if this operation is not used in JLS17 |
2452 | * @since 3.27 |
2453 | */ |
2454 | final void supportedOnlyIn17() { |
2455 | if (this.ast.apiLevel != AST.JLS17_INTERNAL) { |
2456 | throw new UnsupportedOperationException("Operation only supported in JLS17 AST"); //$NON-NLS-1$ |
2457 | } |
2458 | } |
2459 | /** |
2460 | * Checks that this AST operation is only used when |
2461 | * building JLS18 level ASTs. |
2462 | * <p> |
2463 | * Use this method to prevent access to new properties available only in JLS18. |
2464 | * </p> |
2465 | * |
2466 | * @exception UnsupportedOperationException if this operation is not used in JLS18 |
2467 | * @since 3.30 |
2468 | */ |
2469 | final void supportedOnlyIn18() { |
2470 | if (this.ast.apiLevel != AST.JLS18_INTERNAL) { |
2471 | throw new UnsupportedOperationException("Operation only supported in JLS17 AST"); //$NON-NLS-1$ |
2472 | } |
2473 | } |
2474 | |
2475 | /** |
2476 | * Sets or clears this node's parent node and location. |
2477 | * <p> |
2478 | * Note that this method is package-private. The pointer from a node |
2479 | * to its parent is set implicitly as a side effect of inserting or |
2480 | * removing the node as a child of another node. This method calls |
2481 | * <code>ast.modifying()</code>. |
2482 | * </p> |
2483 | * |
2484 | * @param parent the new parent of this node, or <code>null</code> if none |
2485 | * @param property the location of this node in its parent, |
2486 | * or <code>null</code> if <code>parent</code> is <code>null</code> |
2487 | * @see #getLocationInParent |
2488 | * @see #getParent |
2489 | * @since 3.0 |
2490 | */ |
2491 | final void setParent(ASTNode parent, StructuralPropertyDescriptor property) { |
2492 | this.ast.modifying(); |
2493 | this.parent = parent; |
2494 | this.location = property; |
2495 | } |
2496 | |
2497 | /** |
2498 | * Removes this node from its parent. Has no effect if this node |
2499 | * is unparented. If this node appears as an element of a child list |
2500 | * property of its parent, then this node is removed from the |
2501 | * list using <code>List.remove</code>. |
2502 | * If this node appears as the value of a child property of its |
2503 | * parent, then this node is detached from its parent |
2504 | * by passing <code>null</code> to the appropriate setter method; |
2505 | * this operation fails if this node is in a mandatory property. |
2506 | * |
2507 | * @since 3.0 |
2508 | */ |
2509 | public final void delete() { |
2510 | StructuralPropertyDescriptor p = getLocationInParent(); |
2511 | if (p == null) { |
2512 | // node is unparented |
2513 | return; |
2514 | } |
2515 | if (p.isChildProperty()) { |
2516 | getParent().setStructuralProperty(this.location, null); |
2517 | return; |
2518 | } |
2519 | if (p.isChildListProperty()) { |
2520 | List l = (List) getParent().getStructuralProperty(this.location); |
2521 | l.remove(this); |
2522 | } |
2523 | } |
2524 | |
2525 | /** |
2526 | * Checks whether the given new child node is a node |
2527 | * in a different AST from its parent-to-be, whether it is |
2528 | * already has a parent, whether adding it to its |
2529 | * parent-to-be would create a cycle, and whether the child is of |
2530 | * the right type. The parent-to-be is the enclosing instance. |
2531 | * |
2532 | * @param node the parent-to-be node |
2533 | * @param newChild the new child of the parent |
2534 | * @param cycleCheck <code>true</code> if cycles are possible and need |
2535 | * to be checked, <code>false</code> if cycles are impossible and do |
2536 | * not need to be checked |
2537 | * @param nodeType a type constraint on child nodes, or <code>null</code> |
2538 | * if no special check is required |
2539 | * @exception IllegalArgumentException if: |
2540 | * <ul> |
2541 | * <li>the child is null</li> |
2542 | * <li>the node belongs to a different AST</li> |
2543 | * <li>the child has the incorrect node type</li> |
2544 | * <li>the node already has a parent</li> |
2545 | * <li>a cycle in would be created</li> |
2546 | * </ul> |
2547 | */ |
2548 | static void checkNewChild(ASTNode node, ASTNode newChild, |
2549 | boolean cycleCheck, Class nodeType) { |
2550 | if (newChild.ast != node.ast) { |
2551 | // new child is from a different AST |
2552 | throw new IllegalArgumentException(); |
2553 | } |
2554 | if (newChild.getParent() != null) { |
2555 | // new child currently has a different parent |
2556 | throw new IllegalArgumentException(); |
2557 | } |
2558 | if (cycleCheck && newChild == node.getRoot()) { |
2559 | // inserting new child would create a cycle |
2560 | throw new IllegalArgumentException(); |
2561 | } |
2562 | Class childClass = newChild.getClass(); |
2563 | if (nodeType != null && !nodeType.isAssignableFrom(childClass)) { |
2564 | // new child is not of the right type |
2565 | throw new ClassCastException(childClass + " is not an instance of " + nodeType); //$NON-NLS-1$ |
2566 | } |
2567 | if ((newChild.typeAndFlags & PROTECT) != 0) { |
2568 | // new child node is protected => cannot be parented |
2569 | throw new IllegalArgumentException("AST node cannot be modified"); //$NON-NLS-1$ |
2570 | } |
2571 | } |
2572 | |
2573 | /** |
2574 | * Prelude portion of the "3 step program" for replacing the |
2575 | * old child of this node with another node. |
2576 | * Here is the code pattern found in all AST node subclasses: |
2577 | * <pre> |
2578 | * ASTNode oldChild = this.foo; |
2579 | * preReplaceChild(oldChild, newFoo, FOO_PROPERTY); |
2580 | * this.foo = newFoo; |
2581 | * postReplaceChild(oldChild, newFoo, FOO_PROPERTY); |
2582 | * </pre> |
2583 | * The first part (preReplaceChild) does all the precondition checks, |
2584 | * reports pre-delete events, and changes parent links. |
2585 | * The old child is delinked from its parent (making it a root node), |
2586 | * and the new child node is linked to its parent. The new child node |
2587 | * must be a root node in the same AST as its new parent, and must not |
2588 | * be an ancestor of this node. All three nodes must be |
2589 | * modifiable (not PROTECTED). The replace operation must fail |
2590 | * atomically; so it is crucial that all precondition checks |
2591 | * be done before any linking and delinking happens. |
2592 | * The final part (postReplaceChild )reports post-add events. |
2593 | * <p> |
2594 | * This method calls <code>ast.modifying()</code> for the nodes affected. |
2595 | * </p> |
2596 | * |
2597 | * @param oldChild the old child of this node, or <code>null</code> if |
2598 | * there was no old child to replace |
2599 | * @param newChild the new child of this node, or <code>null</code> if |
2600 | * there is no replacement child |
2601 | * @param property the property descriptor of this node describing |
2602 | * the relationship between node and child |
2603 | * @exception RuntimeException if: |
2604 | * <ul> |
2605 | * <li>the node belongs to a different AST</li> |
2606 | * <li>the node already has a parent</li> |
2607 | * <li>a cycle in would be created</li> |
2608 | * <li>any of the nodes involved are unmodifiable</li> |
2609 | * </ul> |
2610 | * @since 3.0 |
2611 | */ |
2612 | final void preReplaceChild(ASTNode oldChild, ASTNode newChild, ChildPropertyDescriptor property) { |
2613 | if ((this.typeAndFlags & PROTECT) != 0) { |
2614 | // this node is protected => cannot gain or lose children |
2615 | throw new IllegalArgumentException("AST node cannot be modified"); //$NON-NLS-1$ |
2616 | } |
2617 | if (newChild != null) { |
2618 | checkNewChild(this, newChild, property.cycleRisk, null); |
2619 | } |
2620 | // delink old child from parent |
2621 | if (oldChild != null) { |
2622 | if ((oldChild.typeAndFlags & PROTECT) != 0) { |
2623 | // old child node is protected => cannot be unparented |
2624 | throw new IllegalArgumentException("AST node cannot be modified"); //$NON-NLS-1$ |
2625 | } |
2626 | if (newChild != null) { |
2627 | this.ast.preReplaceChildEvent(this, oldChild, newChild, property); |
2628 | } else { |
2629 | this.ast.preRemoveChildEvent(this, oldChild, property); |
2630 | } |
2631 | oldChild.setParent(null, null); |
2632 | } else { |
2633 | if(newChild != null) { |
2634 | this.ast.preAddChildEvent(this, newChild, property); |
2635 | } |
2636 | } |
2637 | // link new child to parent |
2638 | if (newChild != null) { |
2639 | newChild.setParent(this, property); |
2640 | // cannot notify postAddChildEvent until parent is linked to child too |
2641 | } |
2642 | } |
2643 | |
2644 | /** |
2645 | * Postlude portion of the "3 step program" for replacing the |
2646 | * old child of this node with another node. |
2647 | * See {@link #preReplaceChild(ASTNode, ASTNode, ChildPropertyDescriptor)} |
2648 | * for details. |
2649 | * @since 3.0 |
2650 | */ |
2651 | final void postReplaceChild(ASTNode oldChild, ASTNode newChild, ChildPropertyDescriptor property) { |
2652 | // link new child to parent |
2653 | if (newChild != null) { |
2654 | if (oldChild != null) { |
2655 | this.ast.postReplaceChildEvent(this, oldChild, newChild, property); |
2656 | } else { |
2657 | this.ast.postAddChildEvent(this, newChild, property); |
2658 | } |
2659 | } else { |
2660 | this.ast.postRemoveChildEvent(this, oldChild, property); |
2661 | } |
2662 | } |
2663 | |
2664 | /** |
2665 | * Prelude portion of the "3 step program" for changing the |
2666 | * value of a simple property of this node. |
2667 | * Here is the code pattern found in all AST node subclasses: |
2668 | * <pre> |
2669 | * preValueChange(FOO_PROPERTY); |
2670 | * this.foo = newFoo; |
2671 | * postValueChange(FOO_PROPERTY); |
2672 | * </pre> |
2673 | * The first part (preValueChange) does the precondition check |
2674 | * to make sure the node is modifiable (not PROTECTED). |
2675 | * The change operation must fail atomically; so it is crucial |
2676 | * that the precondition checks are done before the field is |
2677 | * hammered. The final part (postValueChange)reports post-change |
2678 | * events. |
2679 | * <p> |
2680 | * This method calls <code>ast.modifying()</code> for the node affected. |
2681 | * </p> |
2682 | * |
2683 | * @param property the property descriptor of this node |
2684 | * @exception RuntimeException if: |
2685 | * <ul> |
2686 | * <li>this node is unmodifiable</li> |
2687 | * </ul> |
2688 | * @since 3.0 |
2689 | */ |
2690 | final void preValueChange(SimplePropertyDescriptor property) { |
2691 | if ((this.typeAndFlags & PROTECT) != 0) { |
2692 | // this node is protected => cannot change value of properties |
2693 | throw new IllegalArgumentException("AST node cannot be modified"); //$NON-NLS-1$ |
2694 | } |
2695 | this.ast.preValueChangeEvent(this, property); |
2696 | this.ast.modifying(); |
2697 | } |
2698 | |
2699 | /** |
2700 | * Postlude portion of the "3 step program" for replacing the |
2701 | * old child of this node with another node. |
2702 | * See {@link #preValueChange(SimplePropertyDescriptor)} for details. |
2703 | * @since 3.0 |
2704 | */ |
2705 | final void postValueChange(SimplePropertyDescriptor property) { |
2706 | this.ast.postValueChangeEvent(this, property); |
2707 | } |
2708 | |
2709 | /** |
2710 | * Ensures that this node is modifiable (that is, not marked PROTECTED). |
2711 | * If successful, calls ast.modifying(). |
2712 | * @exception RuntimeException is not modifiable |
2713 | */ |
2714 | final void checkModifiable() { |
2715 | if ((this.typeAndFlags & PROTECT) != 0) { |
2716 | throw new IllegalArgumentException("AST node cannot be modified"); //$NON-NLS-1$ |
2717 | } |
2718 | this.ast.modifying(); |
2719 | } |
2720 | |
2721 | /** |
2722 | * Begin lazy initialization of this node. |
2723 | * Here is the code pattern found in all AST |
2724 | * node subclasses: |
2725 | * <pre> |
2726 | * if (this.foo == null) { |
2727 | * // lazy init must be thread-safe for readers |
2728 | * synchronized (this) { |
2729 | * if (this.foo == null) { |
2730 | * preLazyInit(); |
2731 | * this.foo = ...; // code to create new node |
2732 | * postLazyInit(this.foo, FOO_PROPERTY); |
2733 | * } |
2734 | * } |
2735 | * } |
2736 | * </pre> |
2737 | * @since 3.0 |
2738 | */ |
2739 | final void preLazyInit() { |
2740 | // IMPORTANT: this method is called by readers |
2741 | // ASTNode.this is locked at this point |
2742 | this.ast.disableEvents(); |
2743 | // will turn events back on in postLasyInit |
2744 | } |
2745 | |
2746 | /** |
2747 | * End lazy initialization of this node. |
2748 | * |
2749 | * @param newChild the new child of this node, or <code>null</code> if |
2750 | * there is no replacement child |
2751 | * @param property the property descriptor of this node describing |
2752 | * the relationship between node and child |
2753 | * @since 3.0 |
2754 | */ |
2755 | final void postLazyInit(ASTNode newChild, ChildPropertyDescriptor property) { |
2756 | // IMPORTANT: this method is called by readers |
2757 | // ASTNode.this is locked at this point |
2758 | // newChild is brand new (so no chance of concurrent access) |
2759 | newChild.setParent(this, property); |
2760 | // turn events back on (they were turned off in corresponding preLazyInit) |
2761 | this.ast.reenableEvents(); |
2762 | } |
2763 | |
2764 | /** |
2765 | * Returns the value of the named property of this node, or <code>null</code> if none. |
2766 | * |
2767 | * @param propertyName the property name |
2768 | * @return the property value, or <code>null</code> if none |
2769 | * @see #setProperty(String,Object) |
2770 | */ |
2771 | public final Object getProperty(String propertyName) { |
2772 | if (propertyName == null) { |
2773 | throw new IllegalArgumentException(); |
2774 | } |
2775 | if (this.property1 == null) { |
2776 | // node has no properties at all |
2777 | return null; |
2778 | } |
2779 | if (this.property1 instanceof String) { |
2780 | // node has only a single property |
2781 | if (propertyName.equals(this.property1)) { |
2782 | return this.property2; |
2783 | } else { |
2784 | return null; |
2785 | } |
2786 | } |
2787 | // otherwise node has table of properties |
2788 | Map m = (Map) this.property1; |
2789 | return m.get(propertyName); |
2790 | } |
2791 | |
2792 | /** |
2793 | * Sets the named property of this node to the given value, |
2794 | * or to <code>null</code> to clear it. |
2795 | * <p> |
2796 | * Clients should employ property names that are sufficiently unique |
2797 | * to avoid inadvertent conflicts with other clients that might also be |
2798 | * setting properties on the same node. |
2799 | * </p> |
2800 | * <p> |
2801 | * Note that modifying a property is not considered a modification to the |
2802 | * AST itself. This is to allow clients to decorate existing nodes with |
2803 | * their own properties without jeopardizing certain things (like the |
2804 | * validity of bindings), which rely on the underlying tree remaining static. |
2805 | * </p> |
2806 | * |
2807 | * @param propertyName the property name |
2808 | * @param data the new property value, or <code>null</code> if none |
2809 | * @see #getProperty(String) |
2810 | * @throws IllegalArgumentException if the given property name is <code>null</code> |
2811 | */ |
2812 | public final void setProperty(String propertyName, Object data) { |
2813 | if (propertyName == null) { |
2814 | throw new IllegalArgumentException(); |
2815 | } |
2816 | // N.B. DO NOT CALL ast.modifying(); |
2817 | |
2818 | if (this.property1 == null) { |
2819 | // node has no properties at all |
2820 | if (data == null) { |
2821 | // we already know this |
2822 | return; |
2823 | } |
2824 | // node gets its fist property |
2825 | this.property1 = propertyName; |
2826 | this.property2 = data; |
2827 | return; |
2828 | } |
2829 | |
2830 | if (this.property1 instanceof String) { |
2831 | // node has only a single property |
2832 | if (propertyName.equals(this.property1)) { |
2833 | // we're in luck |
2834 | if (data == null) { |
2835 | // just deleted last property |
2836 | this.property1 = null; |
2837 | this.property2 = null; |
2838 | } else { |
2839 | this.property2 = data; |
2840 | } |
2841 | return; |
2842 | } |
2843 | if (data == null) { |
2844 | // we already know this |
2845 | return; |
2846 | } |
2847 | // node already has one property - getting its second |
2848 | // convert to more flexible representation |
2849 | Map m = new HashMap(3); |
2850 | m.put(this.property1, this.property2); |
2851 | m.put(propertyName, data); |
2852 | this.property1 = m; |
2853 | this.property2 = null; |
2854 | return; |
2855 | } |
2856 | |
2857 | // node has two or more properties |
2858 | Map m = (Map) this.property1; |
2859 | if (data == null) { |
2860 | m.remove(propertyName); |
2861 | // check for just one property left |
2862 | if (m.size() == 1) { |
2863 | // convert to more efficient representation |
2864 | Map.Entry[] entries = (Map.Entry[]) m.entrySet().toArray(new Map.Entry[1]); |
2865 | this.property1 = entries[0].getKey(); |
2866 | this.property2 = entries[0].getValue(); |
2867 | } |
2868 | return; |
2869 | } else { |
2870 | m.put(propertyName, data); |
2871 | // still has two or more properties |
2872 | return; |
2873 | } |
2874 | } |
2875 | |
2876 | /** |
2877 | * Returns an unmodifiable table of the properties of this node with |
2878 | * non-<code>null</code> values. |
2879 | * |
2880 | * @return the table of property values keyed by property name |
2881 | * (key type: <code>String</code>; value type: <code>Object</code>) |
2882 | */ |
2883 | public final Map properties() { |
2884 | if (this.property1 == null) { |
2885 | // node has no properties at all |
2886 | return UNMODIFIABLE_EMPTY_MAP; |
2887 | } |
2888 | if (this.property1 instanceof String) { |
2889 | // node has a single property |
2890 | return Collections.singletonMap(this.property1, this.property2); |
2891 | } |
2892 | |
2893 | // node has two or more properties |
2894 | if (this.property2 == null) { |
2895 | this.property2 = Collections.unmodifiableMap((Map) this.property1); |
2896 | } |
2897 | // property2 is unmodifiable wrapper for map in property1 |
2898 | return (Map) this.property2; |
2899 | } |
2900 | |
2901 | /** |
2902 | * Returns the flags associated with this node. |
2903 | * <p> |
2904 | * No flags are associated with newly created nodes. |
2905 | * </p> |
2906 | * <p> |
2907 | * The flags are the bitwise-or of individual flags. |
2908 | * The following flags are currently defined: |
2909 | * <ul> |
2910 | * <li>{@link #MALFORMED} - indicates node is syntactically |
2911 | * malformed</li> |
2912 | * <li>{@link #ORIGINAL} - indicates original node |
2913 | * created by ASTParser</li> |
2914 | * <li>{@link #PROTECT} - indicates node is protected |
2915 | * from further modification</li> |
2916 | * <li>{@link #RECOVERED} - indicates node or a part of this node |
2917 | * is recovered from source that contains a syntax error</li> |
2918 | * </ul> |
2919 | * Other bit positions are reserved for future use. |
2920 | * |
2921 | * @return the bitwise-or of individual flags |
2922 | * @see #setFlags(int) |
2923 | */ |
2924 | public final int getFlags() { |
2925 | return this.typeAndFlags & 0xFFFF; |
2926 | } |
2927 | |
2928 | /** |
2929 | * Sets the flags associated with this node to the given value. |
2930 | * <p> |
2931 | * The flags are the bitwise-or of individual flags. |
2932 | * The following flags are currently defined: |
2933 | * <ul> |
2934 | * <li>{@link #MALFORMED} - indicates node is syntactically |
2935 | * malformed</li> |
2936 | * <li>{@link #ORIGINAL} - indicates original node |
2937 | * created by ASTParser</li> |
2938 | * <li>{@link #PROTECT} - indicates node is protected |
2939 | * from further modification</li> |
2940 | * <li>{@link #RECOVERED} - indicates node or a part of this node |
2941 | * is recovered from source that contains a syntax error</li> |
2942 | * </ul> |
2943 | * Other bit positions are reserved for future use. |
2944 | * <p> |
2945 | * Note that the flags are <em>not</em> considered a structural |
2946 | * property of the node, and can be changed even if the |
2947 | * node is marked as protected. |
2948 | * </p> |
2949 | * |
2950 | * @param flags the bitwise-or of individual flags |
2951 | * @see #getFlags() |
2952 | */ |
2953 | public final void setFlags(int flags) { |
2954 | this.ast.modifying(); |
2955 | int old = this.typeAndFlags & 0xFFFF0000; |
2956 | this.typeAndFlags = old | (flags & 0xFFFF); |
2957 | } |
2958 | |
2959 | /** |
2960 | * Returns an integer value identifying the type of this concrete AST node. |
2961 | * The values are small positive integers, suitable for use in switch statements. |
2962 | * <p> |
2963 | * For each concrete node type there is a unique node type constant (name |
2964 | * and value). The unique node type constant for a concrete node type such as |
2965 | * <code>CastExpression</code> is <code>ASTNode.CAST_EXPRESSION</code>. |
2966 | * </p> |
2967 | * |
2968 | * @return one of the node type constants |
2969 | */ |
2970 | public final int getNodeType() { |
2971 | return this.typeAndFlags >>> 16; |
2972 | } |
2973 | |
2974 | /** |
2975 | * Sets the integer value identifying the type of this concrete AST node. |
2976 | * The values are small positive integers, suitable for use in switch statements. |
2977 | * |
2978 | * @param nodeType one of the node type constants |
2979 | */ |
2980 | private void setNodeType(int nodeType) { |
2981 | int old = this.typeAndFlags & 0xFFFF0000; |
2982 | this.typeAndFlags = old | (nodeType << 16); |
2983 | } |
2984 | |
2985 | /** |
2986 | * Returns an integer value identifying the type of this concrete AST node. |
2987 | * <p> |
2988 | * This internal method is implemented in each of the |
2989 | * concrete node subclasses. |
2990 | * </p> |
2991 | * |
2992 | * @return one of the node type constants |
2993 | */ |
2994 | abstract int getNodeType0(); |
2995 | |
2996 | /** |
2997 | * The <code>ASTNode</code> implementation of this <code>Object</code> |
2998 | * method uses object identity (==). Use <code>subtreeMatch</code> to |
2999 | * compare two subtrees for equality. |
3000 | * |
3001 | * @param obj {@inheritDoc} |
3002 | * @return {@inheritDoc} |
3003 | * @see #subtreeMatch(ASTMatcher matcher, Object other) |
3004 | */ |
3005 | @Override |
3006 | public final boolean equals(Object obj) { |
3007 | return this == obj; // equivalent to Object.equals |
3008 | } |
3009 | |
3010 | /* |
3011 | * (non-Javadoc) |
3012 | * This makes it consistent with the fact that a equals methods has been provided. |
3013 | * @see java.lang.Object#hashCode() |
3014 | */ |
3015 | @Override |
3016 | public final int hashCode() { |
3017 | return super.hashCode(); |
3018 | } |
3019 | |
3020 | /** |
3021 | * Returns whether the subtree rooted at the given node matches the |
3022 | * given other object as decided by the given matcher. |
3023 | * |
3024 | * @param matcher the matcher |
3025 | * @param other the other object, or <code>null</code> |
3026 | * @return <code>true</code> if the subtree matches, or |
3027 | * <code>false</code> if they do not match |
3028 | */ |
3029 | public final boolean subtreeMatch(ASTMatcher matcher, Object other) { |
3030 | return subtreeMatch0(matcher, other); |
3031 | } |
3032 | |
3033 | /** |
3034 | * Returns whether the subtree rooted at the given node matches the |
3035 | * given other object as decided by the given matcher. |
3036 | * <p> |
3037 | * This internal method is implemented in each of the |
3038 | * concrete node subclasses. |
3039 | * </p> |
3040 | * |
3041 | * @param matcher the matcher |
3042 | * @param other the other object, or <code>null</code> |
3043 | * @return <code>true</code> if the subtree matches, or |
3044 | * <code>false</code> if they do not match |
3045 | */ |
3046 | abstract boolean subtreeMatch0(ASTMatcher matcher, Object other); |
3047 | |
3048 | /** |
3049 | * Returns a deep copy of the subtree of AST nodes rooted at the |
3050 | * given node. The resulting nodes are owned by the given AST, |
3051 | * which may be different from the ASTs of the given node. |
3052 | * Even if the given node has a parent, the result node will be unparented. |
3053 | * <p> |
3054 | * Source range information on the original nodes is automatically copied to the new |
3055 | * nodes. Client properties (<code>properties</code>) are not carried over. |
3056 | * </p> |
3057 | * <p> |
3058 | * The node's <code>AST</code> and the target <code>AST</code> must support |
3059 | * the same API level. |
3060 | * </p> |
3061 | * |
3062 | * @param target the AST that is to own the nodes in the result |
3063 | * @param node the node to copy, or <code>null</code> if none |
3064 | * @return the copied node, or <code>null</code> if <code>node</code> |
3065 | * is <code>null</code> |
3066 | */ |
3067 | public static ASTNode copySubtree(AST target, ASTNode node) { |
3068 | if (node == null) { |
3069 | return null; |
3070 | } |
3071 | if (target == null) { |
3072 | throw new IllegalArgumentException(); |
3073 | } |
3074 | if (target.apiLevel() != node.getAST().apiLevel()) { |
3075 | throw new UnsupportedOperationException(); |
3076 | } |
3077 | ASTNode newNode = node.clone(target); |
3078 | return newNode; |
3079 | } |
3080 | |
3081 | /** |
3082 | * Returns a deep copy of the subtrees of AST nodes rooted at the |
3083 | * given list of nodes. The resulting nodes are owned by the given AST, |
3084 | * which may be different from the ASTs of the nodes in the list. |
3085 | * Even if the nodes in the list have parents, the nodes in the result |
3086 | * will be unparented. |
3087 | * <p> |
3088 | * Source range information on the original nodes is automatically copied to the new |
3089 | * nodes. Client properties (<code>properties</code>) are not carried over. |
3090 | * </p> |
3091 | * |
3092 | * @param target the AST that is to own the nodes in the result |
3093 | * @param nodes the list of nodes to copy |
3094 | * (element type: {@link ASTNode}) |
3095 | * @return the list of copied subtrees |
3096 | * (element type: {@link ASTNode}) |
3097 | */ |
3098 | public static List copySubtrees(AST target, List nodes) { |
3099 | List result = new ArrayList(nodes.size()); |
3100 | for (Iterator it = nodes.iterator(); it.hasNext(); ) { |
3101 | ASTNode oldNode = (ASTNode) it.next(); |
3102 | ASTNode newNode = oldNode.clone(target); |
3103 | result.add(newNode); |
3104 | } |
3105 | return result; |
3106 | } |
3107 | |
3108 | /** |
3109 | * Returns a deep copy of the subtree of AST nodes rooted at this node. |
3110 | * The resulting nodes are owned by the given AST, which may be different |
3111 | * from the AST of this node. Even if this node has a parent, the |
3112 | * result node will be unparented. |
3113 | * <p> |
3114 | * This method reports pre- and post-clone events, and dispatches |
3115 | * to <code>clone0(AST)</code> which is reimplemented in node subclasses. |
3116 | * </p> |
3117 | * |
3118 | * @param target the AST that is to own the nodes in the result |
3119 | * @return the root node of the copies subtree |
3120 | */ |
3121 | final ASTNode clone(AST target) { |
3122 | this.ast.preCloneNodeEvent(this); |
3123 | ASTNode c = clone0(target); |
3124 | this.ast.postCloneNodeEvent(this, c); |
3125 | return c; |
3126 | } |
3127 | |
3128 | /** |
3129 | * Returns a deep copy of the subtree of AST nodes rooted at this node. |
3130 | * The resulting nodes are owned by the given AST, which may be different |
3131 | * from the AST of this node. Even if this node has a parent, the |
3132 | * result node will be unparented. |
3133 | * <p> |
3134 | * This method must be implemented in subclasses. |
3135 | * </p> |
3136 | * <p> |
3137 | * General template for implementation on each concrete ASTNode class: |
3138 | * <pre> |
3139 | * <code> |
3140 | * ConcreteNodeType result = new ConcreteNodeType(target); |
3141 | * result.setSourceRange(getStartPosition(), getLength()); |
3142 | * result.setChildProperty( |
3143 | * (ChildPropertyType) ASTNode.copySubtree(target, getChildProperty())); |
3144 | * result.setSimpleProperty(isSimpleProperty()); |
3145 | * result.childrenProperty().addAll( |
3146 | * ASTNode.copySubtrees(target, childrenProperty())); |
3147 | * return result; |
3148 | * </code> |
3149 | * </pre> |
3150 | * </p> |
3151 | * <p> |
3152 | * This method does not report pre- and post-clone events. |
3153 | * All callers should instead call <code>clone(AST)</code> |
3154 | * to ensure that pre- and post-clone events are reported. |
3155 | * </p> |
3156 | * <p> |
3157 | * N.B. This method is package-private, so that the implementations |
3158 | * of this method in each of the concrete AST node types do not |
3159 | * clutter up the API doc. |
3160 | * </p> |
3161 | * |
3162 | * @param target the AST that is to own the nodes in the result |
3163 | * @return the root node of the copies subtree |
3164 | */ |
3165 | abstract ASTNode clone0(AST target); |
3166 | |
3167 | /** |
3168 | * Accepts the given visitor on a visit of the current node. |
3169 | * |
3170 | * @param visitor the visitor object |
3171 | * @exception IllegalArgumentException if the visitor is null |
3172 | */ |
3173 | public final void accept(ASTVisitor visitor) { |
3174 | if (visitor == null) { |
3175 | throw new IllegalArgumentException(); |
3176 | } |
3177 | // begin with the generic pre-visit |
3178 | if (visitor.preVisit2(this)) { |
3179 | // dynamic dispatch to internal method for type-specific visit/endVisit |
3180 | accept0(visitor); |
3181 | } |
3182 | // end with the generic post-visit |
3183 | visitor.postVisit(this); |
3184 | } |
3185 | |
3186 | /** |
3187 | * Accepts the given visitor on a type-specific visit of the current node. |
3188 | * This method must be implemented in all concrete AST node types. |
3189 | * <p> |
3190 | * General template for implementation on each concrete ASTNode class: |
3191 | * <pre> |
3192 | * <code> |
3193 | * boolean visitChildren = visitor.visit(this); |
3194 | * if (visitChildren) { |
3195 | * // visit children in normal left to right reading order |
3196 | * acceptChild(visitor, getProperty1()); |
3197 | * acceptChildren(visitor, this.rawListProperty); |
3198 | * acceptChild(visitor, getProperty2()); |
3199 | * } |
3200 | * visitor.endVisit(this); |
3201 | * </code> |
3202 | * </pre> |
3203 | * Note that the caller (<code>accept</code>) take cares of invoking |
3204 | * <code>visitor.preVisit(this)</code> and <code>visitor.postVisit(this)</code>. |
3205 | * </p> |
3206 | * |
3207 | * @param visitor the visitor object |
3208 | */ |
3209 | abstract void accept0(ASTVisitor visitor); |
3210 | |
3211 | /** |
3212 | * Accepts the given visitor on a visit of the current node. |
3213 | * <p> |
3214 | * This method should be used by the concrete implementations of |
3215 | * <code>accept0</code> to traverse optional properties. Equivalent |
3216 | * to <code>child.accept(visitor)</code> if <code>child</code> |
3217 | * is not <code>null</code>. |
3218 | * </p> |
3219 | * |
3220 | * @param visitor the visitor object |
3221 | * @param child the child AST node to dispatch too, or <code>null</code> |
3222 | * if none |
3223 | */ |
3224 | final void acceptChild(ASTVisitor visitor, ASTNode child) { |
3225 | if (child == null) { |
3226 | return; |
3227 | } |
3228 | child.accept(visitor); |
3229 | } |
3230 | |
3231 | /** |
3232 | * Accepts the given visitor on a visit of the given live list of |
3233 | * child nodes. |
3234 | * <p> |
3235 | * This method must be used by the concrete implementations of |
3236 | * <code>accept</code> to traverse list-values properties; it |
3237 | * encapsulates the proper handling of on-the-fly changes to the list. |
3238 | * </p> |
3239 | * |
3240 | * @param visitor the visitor object |
3241 | * @param children the child AST node to dispatch too, or <code>null</code> |
3242 | * if none |
3243 | */ |
3244 | final void acceptChildren(ASTVisitor visitor, ASTNode.NodeList children) { |
3245 | // use a cursor to keep track of where we are up to |
3246 | // (the list may be changing under foot) |
3247 | NodeList.Cursor cursor = children.newCursor(); |
3248 | try { |
3249 | while (cursor.hasNext()) { |
3250 | ASTNode child = (ASTNode) cursor.next(); |
3251 | child.accept(visitor); |
3252 | } |
3253 | } finally { |
3254 | children.releaseCursor(cursor); |
3255 | } |
3256 | } |
3257 | |
3258 | /** |
3259 | * Returns the character index into the original source file indicating |
3260 | * where the source fragment corresponding to this node begins. |
3261 | * <p> |
3262 | * The parser supplies useful well-defined source ranges to the nodes it creates. |
3263 | * See {@link ASTParser#setKind(int)} for details |
3264 | * on precisely where source ranges begin and end. |
3265 | * </p> |
3266 | * |
3267 | * @return the 0-based character index, or <code>-1</code> |
3268 | * if no source position information is recorded for this node |
3269 | * @see #getLength() |
3270 | * @see ASTParser |
3271 | */ |
3272 | public final int getStartPosition() { |
3273 | return this.startPosition; |
3274 | } |
3275 | |
3276 | /** |
3277 | * Returns the length in characters of the original source file indicating |
3278 | * where the source fragment corresponding to this node ends. |
3279 | * <p> |
3280 | * The parser supplies useful well-defined source ranges to the nodes it creates. |
3281 | * See {@link ASTParser#setKind(int)} methods for details |
3282 | * on precisely where source ranges begin and end. |
3283 | * </p> |
3284 | * |
3285 | * @return a (possibly 0) length, or <code>0</code> |
3286 | * if no source position information is recorded for this node |
3287 | * @see #getStartPosition() |
3288 | * @see ASTParser |
3289 | */ |
3290 | public final int getLength() { |
3291 | return this.length; |
3292 | } |
3293 | |
3294 | /** |
3295 | * Sets the source range of the original source file where the source |
3296 | * fragment corresponding to this node was found. |
3297 | * <p> |
3298 | * See {@link ASTParser#setKind(int)} for details |
3299 | * on precisely where source ranges are supposed to begin and end. |
3300 | * </p> |
3301 | * |
3302 | * @param startPosition a 0-based character index, |
3303 | * or <code>-1</code> if no source position information is |
3304 | * available for this node |
3305 | * @param length a (possibly 0) length, |
3306 | * or <code>0</code> if no source position information is recorded |
3307 | * for this node |
3308 | * @see #getStartPosition() |
3309 | * @see #getLength() |
3310 | * @see ASTParser |
3311 | */ |
3312 | public final void setSourceRange(int startPosition, int length) { |
3313 | if (startPosition >= 0 && length < 0) { |
3314 | throw new IllegalArgumentException(); |
3315 | } |
3316 | if (startPosition < 0 && length != 0) { |
3317 | throw new IllegalArgumentException(); |
3318 | } |
3319 | // source positions are not considered a structural property |
3320 | // but we protect them nevertheless |
3321 | checkModifiable(); |
3322 | this.startPosition = startPosition; |
3323 | this.length = length; |
3324 | } |
3325 | |
3326 | /** |
3327 | * Returns a string representation of this node suitable for debugging |
3328 | * purposes only. |
3329 | * |
3330 | * @return a debug string |
3331 | */ |
3332 | @Override |
3333 | public final String toString() { |
3334 | StringBuffer buffer = new StringBuffer(); |
3335 | int p = buffer.length(); |
3336 | try { |
3337 | appendDebugString(buffer); |
3338 | } catch (RuntimeException e) { |
3339 | // since debugger sometimes call toString methods, problems can easily happen when |
3340 | // toString is called on an instance that is being initialized |
3341 | buffer.setLength(p); |
3342 | buffer.append("!"); //$NON-NLS-1$ |
3343 | buffer.append(standardToString()); |
3344 | } |
3345 | return buffer.toString(); |
3346 | } |
3347 | |
3348 | /** |
3349 | * Returns the string representation of this node produced by the standard |
3350 | * <code>Object.toString</code> method. |
3351 | * |
3352 | * @return a debug string |
3353 | */ |
3354 | final String standardToString() { |
3355 | return super.toString(); |
3356 | } |
3357 | |
3358 | /** |
3359 | * Appends a debug representation of this node to the given string buffer. |
3360 | * <p> |
3361 | * The <code>ASTNode</code> implementation of this method prints out the entire |
3362 | * subtree. Subclasses may override to provide a more succinct representation. |
3363 | * </p> |
3364 | * |
3365 | * @param buffer the string buffer to append to |
3366 | */ |
3367 | void appendDebugString(StringBuffer buffer) { |
3368 | // print the subtree by default |
3369 | appendPrintString(buffer); |
3370 | } |
3371 | |
3372 | /** |
3373 | * Appends a standard Java source code representation of this subtree to the given |
3374 | * string buffer. |
3375 | * |
3376 | * @param buffer the string buffer to append to |
3377 | */ |
3378 | final void appendPrintString(StringBuffer buffer) { |
3379 | NaiveASTFlattener printer = new NaiveASTFlattener(); |
3380 | accept(printer); |
3381 | buffer.append(printer.getResult()); |
3382 | } |
3383 | |
3384 | /** |
3385 | * Estimate of size of an object header in bytes. |
3386 | */ |
3387 | static final int HEADERS = 12; |
3388 | |
3389 | /** |
3390 | * Approximate base size of an AST node instance in bytes, |
3391 | * including object header and instance fields. |
3392 | * That is, HEADERS + (# instance vars in ASTNode)*4. |
3393 | */ |
3394 | static final int BASE_NODE_SIZE = HEADERS + 7 * 4; |
3395 | |
3396 | /** |
3397 | * Returns an estimate of the memory footprint, in bytes, |
3398 | * of the given string. |
3399 | * |
3400 | * @param string the string to measure, or <code>null</code> |
3401 | * @return the size of this string object in bytes, or |
3402 | * 0 if the string is <code>null</code> |
3403 | * @since 3.0 |
3404 | */ |
3405 | static int stringSize(String string) { |
3406 | int size = 0; |
3407 | if (string != null) { |
3408 | // Strings usually have 4 instance fields, one of which is a char[] |
3409 | size += HEADERS + 4 * 4; |
3410 | // char[] has 2 bytes per character |
3411 | size += HEADERS + 2 * string.length(); |
3412 | } |
3413 | return size; |
3414 | } |
3415 | |
3416 | /** |
3417 | * Returns an estimate of the memory footprint in bytes of the entire |
3418 | * subtree rooted at this node. |
3419 | * |
3420 | * @return the size of this subtree in bytes |
3421 | */ |
3422 | public final int subtreeBytes() { |
3423 | return treeSize(); |
3424 | } |
3425 | |
3426 | /** |
3427 | * Returns an estimate of the memory footprint in bytes of the entire |
3428 | * subtree rooted at this node. |
3429 | * <p> |
3430 | * N.B. This method is package-private, so that the implementations |
3431 | * of this method in each of the concrete AST node types do not |
3432 | * clutter up the API doc. |
3433 | * </p> |
3434 | * |
3435 | * @return the size of this subtree in bytes |
3436 | */ |
3437 | abstract int treeSize(); |
3438 | |
3439 | /** |
3440 | * Returns an estimate of the memory footprint of this node in bytes. |
3441 | * The estimate does not include the space occupied by child nodes. |
3442 | * |
3443 | * @return the size of this node in bytes |
3444 | */ |
3445 | abstract int memSize(); |
3446 | } |
3447 |
Members