0
# AST Navigation and Manipulation
1
2
JavaParser provides a comprehensive Abstract Syntax Tree (AST) model with over 100 node types representing all Java language constructs. The AST supports navigation, search, modification, and observation of changes.
3
4
## Capabilities
5
6
### Base Node Functionality
7
8
All AST nodes extend the abstract Node class, providing common functionality for traversal, search, and manipulation.
9
10
```java { .api }
11
/**
12
* Base class for all AST nodes
13
*/
14
public abstract class Node implements Cloneable, HasParentNode<Node>, Visitable, NodeWithRange<Node>, NodeWithTokenRange<Node> {
15
16
/**
17
* Accept a generic visitor that returns a value
18
* @param v The visitor to accept
19
* @param arg Argument passed to visitor methods
20
* @return Value returned by visitor
21
*/
22
public <R, A> R accept(GenericVisitor<R, A> v, A arg);
23
24
/**
25
* Accept a void visitor for side effects
26
* @param v The visitor to accept
27
* @param arg Argument passed to visitor methods
28
*/
29
public <A> void accept(VoidVisitor<A> v, A arg);
30
31
/**
32
* Find all descendant nodes of a specific type
33
* @param clazz Class of nodes to find
34
* @return List of nodes matching the type
35
*/
36
public <T extends Node> List<T> findAll(Class<T> clazz);
37
38
/**
39
* Find first descendant node of a specific type
40
* @param clazz Class of node to find
41
* @return Optional containing first match, empty if none found
42
*/
43
public <T extends Node> Optional<T> findFirst(Class<T> clazz);
44
45
/**
46
* Get parent node
47
* @return Optional containing parent, empty if this is root
48
*/
49
public Optional<Node> getParentNode();
50
51
/**
52
* Replace this node with another node
53
* @param node Replacement node
54
* @return true if replacement was successful
55
*/
56
public boolean replace(Node node);
57
58
/**
59
* Remove this node from its parent
60
* @return true if removal was successful
61
*/
62
public boolean remove();
63
64
/**
65
* Create deep copy of this node
66
* @return Cloned node
67
*/
68
public Node clone();
69
70
/**
71
* Get range of this node in source code
72
* @return Optional containing range, empty if not available
73
*/
74
public Optional<Range> getRange();
75
76
/**
77
* Set data associated with this node
78
* @param key Data key
79
* @param value Data value
80
*/
81
public <T> void setData(DataKey<T> key, T value);
82
83
/**
84
* Get data associated with this node
85
* @param key Data key
86
* @return Data value
87
* @throws IllegalStateException if key is not found
88
*/
89
public <T> T getData(DataKey<T> key);
90
91
/**
92
* Find data associated with this node
93
* @param key Data key
94
* @return Optional containing data value, empty if not found
95
*/
96
public <T> Optional<T> findData(DataKey<T> key);
97
98
/**
99
* Get token range of this node in source code
100
* @return Optional containing token range, empty if not available
101
*/
102
public Optional<TokenRange> getTokenRange();
103
104
/**
105
* Stream all descendant nodes
106
* @return Stream of all descendant nodes
107
*/
108
public Stream<Node> stream();
109
110
/**
111
* Stream descendant nodes with specific traversal strategy
112
* @param traversal Tree traversal strategy
113
* @return Stream of nodes using specified traversal
114
*/
115
public Stream<Node> stream(TreeTraversal traversal);
116
117
/**
118
* Walk the AST tree and apply consumer to each node
119
* @param consumer Function to apply to each node
120
*/
121
public void walk(Consumer<Node> consumer);
122
123
/**
124
* Walk the AST tree with specific traversal and apply consumer
125
* @param traversal Tree traversal strategy
126
* @param consumer Function to apply to each node
127
*/
128
public void walk(TreeTraversal traversal, Consumer<Node> consumer);
129
130
/**
131
* Find all descendant nodes matching predicate
132
* @param clazz Class of nodes to find
133
* @param predicate Condition to match
134
* @return List of matching nodes
135
*/
136
public <T extends Node> List<T> findAll(Class<T> clazz, Predicate<T> predicate);
137
138
/**
139
* Find first descendant node matching predicate
140
* @param clazz Class of node to find
141
* @param predicate Condition to match
142
* @return Optional containing first match, empty if none found
143
*/
144
public <T extends Node> Optional<T> findFirst(Class<T> clazz, Predicate<T> predicate);
145
146
/**
147
* Check if this node contains data for the given key
148
* @param key Data key to check
149
* @return true if data exists for key
150
*/
151
public boolean containsData(DataKey<?> key);
152
153
/**
154
* Remove data associated with key
155
* @param key Data key to remove
156
*/
157
public void removeData(DataKey<?> key);
158
159
/**
160
* Get all data keys associated with this node
161
* @return Set of data keys
162
*/
163
public Set<DataKey<?>> getDataKeys();
164
165
/**
166
* Find the root node of the AST
167
* @return Root node of the tree
168
*/
169
public Node findRootNode();
170
171
/**
172
* Find the CompilationUnit containing this node
173
* @return Optional containing CompilationUnit, empty if not found
174
*/
175
public Optional<CompilationUnit> findCompilationUnit();
176
}
177
```
178
179
**Usage Examples:**
180
181
```java
182
CompilationUnit cu = StaticJavaParser.parse(code);
183
184
// Find all method declarations
185
List<MethodDeclaration> methods = cu.findAll(MethodDeclaration.class);
186
187
// Find first class declaration
188
Optional<ClassOrInterfaceDeclaration> firstClass =
189
cu.findFirst(ClassOrInterfaceDeclaration.class);
190
191
// Navigate parent-child relationships
192
for (MethodDeclaration method : methods) {
193
Optional<Node> parent = method.getParentNode();
194
if (parent.isPresent() && parent.get() instanceof ClassOrInterfaceDeclaration) {
195
ClassOrInterfaceDeclaration owner = (ClassOrInterfaceDeclaration) parent.get();
196
System.out.println("Method " + method.getNameAsString() +
197
" belongs to class " + owner.getNameAsString());
198
}
199
}
200
201
// Clone nodes
202
MethodDeclaration originalMethod = methods.get(0);
203
MethodDeclaration clonedMethod = originalMethod.clone();
204
```
205
206
### CompilationUnit - Root AST Node
207
208
The CompilationUnit represents a complete Java source file and serves as the root of the AST.
209
210
```java { .api }
211
/**
212
* Root AST node representing a Java source file
213
*/
214
public class CompilationUnit extends Node {
215
216
/**
217
* Get all type declarations (classes, interfaces, enums, annotations)
218
* @return NodeList of type declarations
219
*/
220
public NodeList<TypeDeclaration<?>> getTypes();
221
222
/**
223
* Get all import declarations
224
* @return NodeList of import declarations
225
*/
226
public NodeList<ImportDeclaration> getImports();
227
228
/**
229
* Get package declaration
230
* @return Optional containing package declaration, empty if default package
231
*/
232
public Optional<PackageDeclaration> getPackageDeclaration();
233
234
/**
235
* Get primary type declaration (usually first public type)
236
* @return Optional containing primary type
237
*/
238
public Optional<TypeDeclaration<?>> getPrimaryType();
239
240
/**
241
* Get primary type name
242
* @return Optional containing primary type name
243
*/
244
public Optional<String> getPrimaryTypeName();
245
246
/**
247
* Get module declaration
248
* @return Optional containing module declaration, empty if not a module
249
*/
250
public Optional<ModuleDeclaration> getModule();
251
252
/**
253
* Set module declaration
254
* @param module Module declaration to set
255
* @return This CompilationUnit for chaining
256
*/
257
public CompilationUnit setModule(ModuleDeclaration module);
258
259
/**
260
* Set module by name
261
* @param name Module name
262
* @return This CompilationUnit for chaining
263
*/
264
public CompilationUnit setModule(String name);
265
266
/**
267
* Remove module declaration
268
* @return This CompilationUnit for chaining
269
*/
270
public CompilationUnit removeModule();
271
272
/**
273
* Get class declaration by name
274
* @param className Name of class to find
275
* @return Optional containing class declaration
276
*/
277
public Optional<ClassOrInterfaceDeclaration> getClassByName(String className);
278
279
/**
280
* Get interface declaration by name
281
* @param interfaceName Name of interface to find
282
* @return Optional containing interface declaration
283
*/
284
public Optional<ClassOrInterfaceDeclaration> getInterfaceByName(String interfaceName);
285
286
/**
287
* Get enum declaration by name
288
* @param enumName Name of enum to find
289
* @return Optional containing enum declaration
290
*/
291
public Optional<EnumDeclaration> getEnumByName(String enumName);
292
293
/**
294
* Get annotation declaration by name
295
* @param annotationName Name of annotation to find
296
* @return Optional containing annotation declaration
297
*/
298
public Optional<AnnotationDeclaration> getAnnotationDeclarationByName(String annotationName);
299
300
/**
301
* Get record declaration by name (Java 14+)
302
* @param recordName Name of record to find
303
* @return Optional containing record declaration
304
*/
305
public Optional<RecordDeclaration> getRecordByName(String recordName);
306
307
/**
308
* Add a new class to this compilation unit
309
* @param name Class name
310
* @return Created ClassOrInterfaceDeclaration
311
*/
312
public ClassOrInterfaceDeclaration addClass(String name);
313
314
/**
315
* Add a new interface to this compilation unit
316
* @param name Interface name
317
* @return Created ClassOrInterfaceDeclaration
318
*/
319
public ClassOrInterfaceDeclaration addInterface(String name);
320
321
/**
322
* Add a new enum to this compilation unit
323
* @param name Enum name
324
* @return Created EnumDeclaration
325
*/
326
public EnumDeclaration addEnum(String name);
327
328
/**
329
* Set package declaration
330
* @param packageDeclaration Package declaration to set
331
* @return This CompilationUnit for chaining
332
*/
333
public CompilationUnit setPackageDeclaration(PackageDeclaration packageDeclaration);
334
335
/**
336
* Set package name
337
* @param name Package name
338
* @return This CompilationUnit for chaining
339
*/
340
public CompilationUnit setPackageDeclaration(String name);
341
342
/**
343
* Add import declaration
344
* @param importDeclaration Import to add
345
* @return This CompilationUnit for chaining
346
*/
347
public CompilationUnit addImport(ImportDeclaration importDeclaration);
348
349
/**
350
* Add import by name
351
* @param name Import name (e.g., "java.util.List")
352
* @return This CompilationUnit for chaining
353
*/
354
public CompilationUnit addImport(String name);
355
356
/**
357
* Add static import
358
* @param name Static import name
359
* @return This CompilationUnit for chaining
360
*/
361
public CompilationUnit addStaticImport(String name);
362
}
363
```
364
365
**Usage Examples:**
366
367
```java
368
CompilationUnit cu = StaticJavaParser.parse(sourceCode);
369
370
// Access package and imports
371
Optional<PackageDeclaration> pkg = cu.getPackageDeclaration();
372
NodeList<ImportDeclaration> imports = cu.getImports();
373
374
// Get all types
375
NodeList<TypeDeclaration<?>> types = cu.getTypes();
376
for (TypeDeclaration<?> type : types) {
377
System.out.println("Found type: " + type.getNameAsString());
378
}
379
380
// Modify compilation unit
381
CompilationUnit newCu = new CompilationUnit();
382
newCu.setPackageDeclaration("com.example");
383
newCu.addImport("java.util.List");
384
newCu.addImport("java.util.ArrayList");
385
386
ClassOrInterfaceDeclaration newClass = newCu.addClass("MyClass");
387
newClass.addField("String", "name").setPrivate(true);
388
```
389
390
### Observable NodeList
391
392
JavaParser uses NodeList, an observable list implementation, for collections of AST nodes.
393
394
```java { .api }
395
/**
396
* Observable list for AST nodes
397
*/
398
public class NodeList<T> extends ArrayList<T> implements Observable {
399
400
/**
401
* Create empty node list
402
*/
403
public NodeList();
404
405
/**
406
* Create node list from collection
407
* @param collection Initial elements
408
*/
409
public NodeList(Collection<? extends T> collection);
410
411
/**
412
* Register observer for changes
413
* @param observer Observer to register
414
*/
415
public void register(AstObserver observer);
416
417
/**
418
* Unregister observer
419
* @param observer Observer to unregister
420
*/
421
public void unregister(AstObserver observer);
422
423
// Standard List interface methods...
424
// All methods fire change notifications to observers
425
}
426
```
427
428
### AST Node Search and Filtering
429
430
Advanced search capabilities for finding specific nodes in the AST.
431
432
```java { .api }
433
/**
434
* Find nodes matching a predicate
435
* @param predicate Condition to match
436
* @return List of matching nodes
437
*/
438
public <T> List<T> findAll(Class<T> clazz, Predicate<T> predicate);
439
440
/**
441
* Check if any descendant nodes match condition
442
* @param predicate Condition to check
443
* @return true if any nodes match
444
*/
445
public boolean containsData(Predicate<Node> predicate);
446
447
/**
448
* Walk the AST tree and collect results
449
* @param visitor Function to apply to each node
450
* @return Stream of results
451
*/
452
public <T> Stream<T> walk(Function<Node, Stream<T>> visitor);
453
```
454
455
**Usage Examples:**
456
457
```java
458
// Find all public methods
459
List<MethodDeclaration> publicMethods = cu.findAll(MethodDeclaration.class,
460
method -> method.isPublic());
461
462
// Find methods with specific name
463
List<MethodDeclaration> getMethods = cu.findAll(MethodDeclaration.class,
464
method -> method.getNameAsString().startsWith("get"));
465
466
// Find all string literals
467
List<StringLiteralExpr> strings = cu.findAll(StringLiteralExpr.class);
468
469
// Check for specific patterns
470
boolean hasMainMethod = cu.findAll(MethodDeclaration.class).stream()
471
.anyMatch(method -> method.getNameAsString().equals("main")
472
&& method.isStatic()
473
&& method.isPublic());
474
```
475
476
### AST Modification
477
478
Modify AST nodes by adding, removing, or replacing elements.
479
480
```java { .api }
481
// Add new elements to classes
482
ClassOrInterfaceDeclaration clazz = cu.findFirst(ClassOrInterfaceDeclaration.class).get();
483
484
// Add field
485
FieldDeclaration field = clazz.addField(String.class, "newField");
486
field.setPrivate(true);
487
488
// Add method
489
MethodDeclaration method = clazz.addMethod("getValue", Modifier.Keyword.PUBLIC);
490
method.setType("String");
491
method.setBody(StaticJavaParser.parseBlock("{ return this.value; }"));
492
493
// Add constructor
494
ConstructorDeclaration constructor = clazz.addConstructor(Modifier.Keyword.PUBLIC);
495
constructor.addParameter("String", "value");
496
constructor.setBody(StaticJavaParser.parseBlock("{ this.value = value; }"));
497
498
// Remove elements
499
field.remove(); // Remove from parent
500
method.replace(newMethod); // Replace with new method
501
```
502
503
## Key AST Node Types
504
505
```java { .api }
506
// Type declarations
507
public class ClassOrInterfaceDeclaration extends TypeDeclaration<ClassOrInterfaceDeclaration> {
508
public boolean isInterface();
509
public NodeList<ClassOrInterfaceType> getExtendedTypes();
510
public NodeList<ClassOrInterfaceType> getImplementedTypes();
511
}
512
513
public class MethodDeclaration extends CallableDeclaration<MethodDeclaration> {
514
public Type getType();
515
public NodeList<Parameter> getParameters();
516
public Optional<BlockStmt> getBody();
517
}
518
519
public class FieldDeclaration extends BodyDeclaration<FieldDeclaration> {
520
public NodeList<VariableDeclarator> getVariables();
521
}
522
523
// Expressions
524
public abstract class Expression extends Node {
525
public boolean isAssignExpr();
526
public boolean isBinaryExpr();
527
public boolean isMethodCallExpr();
528
// ... type checking methods for all expression types
529
}
530
531
// Statements
532
public abstract class Statement extends Node {
533
public boolean isBlockStmt();
534
public boolean isIfStmt();
535
public boolean isForStmt();
536
// ... type checking methods for all statement types
537
}
538
```