A comprehensive Java parsing library providing complete support for parsing Java source code from Java 1.0 through Java 21 with advanced analysis functionalities.
—
JavaParser implements the visitor pattern to provide flexible and efficient traversal of AST nodes. The visitor pattern allows you to define operations on AST nodes without modifying the node classes themselves.
The GenericVisitor interface allows visitors that return values of type R and accept arguments of type A.
/**
* Generic visitor interface for AST traversal with return values
* @param <R> Return type of visit methods
* @param <A> Argument type passed to visit methods
*/
public interface GenericVisitor<R, A> {
// Compilation unit and imports
R visit(CompilationUnit n, A arg);
R visit(PackageDeclaration n, A arg);
R visit(ImportDeclaration n, A arg);
// Type declarations
R visit(ClassOrInterfaceDeclaration n, A arg);
R visit(EnumDeclaration n, A arg);
R visit(AnnotationDeclaration n, A arg);
R visit(RecordDeclaration n, A arg);
// Members
R visit(MethodDeclaration n, A arg);
R visit(ConstructorDeclaration n, A arg);
R visit(FieldDeclaration n, A arg);
R visit(EnumConstantDeclaration n, A arg);
R visit(AnnotationMemberDeclaration n, A arg);
R visit(InitializerDeclaration n, A arg);
R visit(Parameter n, A arg);
// Expressions
R visit(ArrayAccessExpr n, A arg);
R visit(ArrayCreationExpr n, A arg);
R visit(ArrayInitializerExpr n, A arg);
R visit(AssignExpr n, A arg);
R visit(BinaryExpr n, A arg);
R visit(BooleanLiteralExpr n, A arg);
R visit(CastExpr n, A arg);
R visit(CharLiteralExpr n, A arg);
R visit(ClassExpr n, A arg);
R visit(ConditionalExpr n, A arg);
R visit(DoubleLiteralExpr n, A arg);
R visit(EnclosedExpr n, A arg);
R visit(FieldAccessExpr n, A arg);
R visit(InstanceOfExpr n, A arg);
R visit(IntegerLiteralExpr n, A arg);
R visit(LambdaExpr n, A arg);
R visit(LongLiteralExpr n, A arg);
R visit(MethodCallExpr n, A arg);
R visit(MethodReferenceExpr n, A arg);
R visit(NameExpr n, A arg);
R visit(NullLiteralExpr n, A arg);
R visit(ObjectCreationExpr n, A arg);
R visit(StringLiteralExpr n, A arg);
R visit(SuperExpr n, A arg);
R visit(ThisExpr n, A arg);
R visit(UnaryExpr n, A arg);
R visit(VariableDeclarationExpr n, A arg);
// Statements
R visit(AssertStmt n, A arg);
R visit(BlockStmt n, A arg);
R visit(BreakStmt n, A arg);
R visit(ContinueStmt n, A arg);
R visit(DoStmt n, A arg);
R visit(ExpressionStmt n, A arg);
R visit(ForEachStmt n, A arg);
R visit(ForStmt n, A arg);
R visit(IfStmt n, A arg);
R visit(LabeledStmt n, A arg);
R visit(ReturnStmt n, A arg);
R visit(SwitchStmt n, A arg);
R visit(SynchronizedStmt n, A arg);
R visit(ThrowStmt n, A arg);
R visit(TryStmt n, A arg);
R visit(WhileStmt n, A arg);
// Types
R visit(ArrayType n, A arg);
R visit(ClassOrInterfaceType n, A arg);
R visit(IntersectionType n, A arg);
R visit(PrimitiveType n, A arg);
R visit(TypeParameter n, A arg);
R visit(UnionType n, A arg);
R visit(VoidType n, A arg);
R visit(WildcardType n, A arg);
// Modern Java language features (Java 9+)
R visit(ModuleDeclaration n, A arg);
R visit(ModuleExportsDirective n, A arg);
R visit(ModuleOpensDirective n, A arg);
R visit(ModuleProvidesDirective n, A arg);
R visit(ModuleRequiresDirective n, A arg);
R visit(ModuleUsesDirective n, A arg);
// Records (Java 14+)
R visit(RecordDeclaration n, A arg);
R visit(CompactConstructorDeclaration n, A arg);
// Pattern matching and newer expressions (Java 14+)
R visit(SwitchExpr n, A arg);
R visit(YieldStmt n, A arg);
R visit(TextBlockLiteralExpr n, A arg);
R visit(TypePatternExpr n, A arg);
R visit(RecordPatternExpr n, A arg);
// Additional statement types
R visit(LocalClassDeclarationStmt n, A arg);
R visit(LocalRecordDeclarationStmt n, A arg);
R visit(SwitchEntry n, A arg);
R visit(UnparsableStmt n, A arg);
// Additional type and modifier support
R visit(VarType n, A arg);
R visit(ReceiverParameter n, A arg);
R visit(Modifier n, A arg);
R visit(ArrayCreationLevel n, A arg)
}The VoidVisitor interface is for visitors that perform side effects without returning values.
/**
* Void visitor interface for AST traversal with side effects only
* @param <A> Argument type passed to visit methods
*/
public interface VoidVisitor<A> {
// Same visit method signatures as GenericVisitor but returning void
void visit(CompilationUnit n, A arg);
void visit(ClassOrInterfaceDeclaration n, A arg);
void visit(MethodDeclaration n, A arg);
void visit(FieldDeclaration n, A arg);
// ... all other visit methods returning void
}JavaParser provides adapter classes that implement default behavior for all visit methods, allowing you to override only the methods you need.
/**
* Adapter providing default implementations for GenericVisitor
* @param <R> Return type
* @param <A> Argument type
*/
public abstract class GenericVisitorAdapter<R, A> implements GenericVisitor<R, A> {
/**
* Default visit behavior - visits all child nodes and returns null
* Override specific visit methods to provide custom behavior
*/
// Default implementations for all visit methods...
}
/**
* Adapter providing default implementations for VoidVisitor
* @param <A> Argument type
*/
public abstract class VoidVisitorAdapter<A> implements VoidVisitor<A> {
/**
* Default visit behavior - visits all child nodes
* Override specific visit methods to provide custom behavior
*/
// Default implementations for all visit methods...
}Usage Examples:
import com.github.javaparser.ast.visitor.VoidVisitorAdapter;
import com.github.javaparser.ast.body.MethodDeclaration;
import com.github.javaparser.ast.body.FieldDeclaration;
// Count methods and fields
CompilationUnit cu = StaticJavaParser.parse(code);
cu.accept(new VoidVisitorAdapter<Void>() {
private int methodCount = 0;
private int fieldCount = 0;
@Override
public void visit(MethodDeclaration n, Void arg) {
methodCount++;
System.out.println("Found method: " + n.getNameAsString());
super.visit(n, arg); // Continue traversal
}
@Override
public void visit(FieldDeclaration n, Void arg) {
fieldCount++;
n.getVariables().forEach(var ->
System.out.println("Found field: " + var.getNameAsString()));
super.visit(n, arg);
}
}, null);JavaParser includes several built-in visitor implementations for common tasks.
/**
* Visitor for modifying AST nodes during traversal
* @param <A> Argument type
*/
public class ModifierVisitor<A> implements GenericVisitor<Visitable, A> {
/**
* Visit and potentially modify nodes
* Return the same node to keep it, return a different node to replace it,
* return null to remove it
*/
// Implementation allows modification during traversal
}
/**
* Visitor for deep cloning AST nodes
*/
public class CloneVisitor implements GenericVisitor<Visitable, Object> {
/**
* Creates deep copies of visited nodes
* @param n Node to clone
* @param arg Clone context
* @return Cloned node
*/
// Implementation for deep cloning
}
/**
* Visitor for comparing AST nodes for equality
*/
public class EqualsVisitor implements GenericVisitor<Boolean, Visitable> {
/**
* Compare two AST nodes for structural equality
* @param n First node
* @param other Second node to compare against
* @return true if nodes are structurally equal
*/
// Implementation for equality comparison
}
/**
* Visitor for computing hash codes of AST nodes
*/
public class HashCodeVisitor implements GenericVisitor<Integer, Void> {
/**
* Compute hash code for AST node
* @param n Node to hash
* @param arg Not used
* @return Hash code of the node
*/
// Implementation for hash code computation
}Usage Examples:
// Clone an AST node
Node original = cu.findFirst(ClassOrInterfaceDeclaration.class).get();
Node cloned = original.accept(new CloneVisitor(), null);
// Compare two nodes for equality
boolean equal = original.accept(new EqualsVisitor(), cloned);
// Modify AST during traversal
cu.accept(new ModifierVisitor<Void>() {
@Override
public Visitable visit(MethodDeclaration n, Void arg) {
// Make all methods public
n.setPublic(true);
return super.visit(n, arg);
}
@Override
public Visitable visit(FieldDeclaration n, Void arg) {
// Remove private fields
if (n.isPrivate()) {
return null; // Remove this node
}
return super.visit(n, arg);
}
}, null);Create custom visitors by extending the adapter classes and overriding specific visit methods.
/**
* Example: Collect all method names in a class
*/
public class MethodNameCollector extends VoidVisitorAdapter<List<String>> {
@Override
public void visit(MethodDeclaration n, List<String> collector) {
collector.add(n.getNameAsString());
super.visit(n, collector); // Continue to child nodes
}
}
/**
* Example: Calculate complexity metrics
*/
public class ComplexityCalculator extends GenericVisitorAdapter<Integer, Void> {
@Override
public Integer visit(IfStmt n, Void arg) {
int complexity = 1; // Base complexity for if statement
complexity += visit(n.getThenStmt(), arg);
if (n.getElseStmt().isPresent()) {
complexity += visit(n.getElseStmt().get(), arg);
}
return complexity;
}
@Override
public Integer visit(ForStmt n, Void arg) {
int complexity = 1; // Base complexity for loop
complexity += visit(n.getBody(), arg);
return complexity;
}
// Override other control flow visit methods...
}Usage Examples:
// Use custom visitors
CompilationUnit cu = StaticJavaParser.parse(code);
// Collect method names
List<String> methodNames = new ArrayList<>();
cu.accept(new MethodNameCollector(), methodNames);
System.out.println("Methods found: " + methodNames);
// Calculate complexity
Integer complexity = cu.accept(new ComplexityCalculator(), null);
System.out.println("Cyclomatic complexity: " + complexity);Pass context information through visitor traversal using the argument parameter.
/**
* Context class for tracking traversal state
*/
public class VisitorContext {
private String currentClassName;
private int depth;
private Map<String, Object> properties;
// Context management methods
public void enterClass(String name) { this.currentClassName = name; }
public void exitClass() { this.currentClassName = null; }
public void incrementDepth() { depth++; }
public void decrementDepth() { depth--; }
}Usage Examples:
// Visitor with context tracking
cu.accept(new VoidVisitorAdapter<VisitorContext>() {
@Override
public void visit(ClassOrInterfaceDeclaration n, VisitorContext ctx) {
ctx.enterClass(n.getNameAsString());
System.out.println("Entering class: " + n.getNameAsString() +
" at depth " + ctx.getDepth());
super.visit(n, ctx); // Visit children
ctx.exitClass();
System.out.println("Exiting class: " + n.getNameAsString());
}
@Override
public void visit(MethodDeclaration n, VisitorContext ctx) {
System.out.println("Method " + n.getNameAsString() +
" in class " + ctx.getCurrentClassName());
super.visit(n, ctx);
}
}, new VisitorContext());The visitor pattern in JavaParser provides several advantages:
Install with Tessl CLI
npx tessl i tessl/maven-com-github-javaparser--javaparser-core