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 provides advanced symbol resolution capabilities for resolving references to their declarations and performing comprehensive type analysis. This enables sophisticated code analysis, refactoring tools, and IDE-like features.
Enable symbol resolution by configuring a SymbolResolver in the ParserConfiguration.
/**
* Interface for resolving symbols to their declarations
*/
public interface SymbolResolver {
/**
* Resolve a node to its declaration
* @param node Node to resolve
* @param resultClass Expected type of resolved declaration
* @return Resolved declaration
* @throws UnsolvedSymbolException if symbol cannot be resolved
*/
<T> T resolveDeclaration(Node node, Class<T> resultClass);
/**
* Resolve a reference expression to its declaration
* @param nameExpr Name expression to resolve
* @return Resolved value declaration
*/
ResolvedValueDeclaration resolveDeclaration(NameExpr nameExpr);
/**
* Resolve a method call to its declaration
* @param methodCallExpr Method call expression to resolve
* @return Resolved method declaration
*/
ResolvedMethodDeclaration resolveDeclaration(MethodCallExpr methodCallExpr);
/**
* Resolve a type to its declaration
* @param type Type to resolve
* @return Resolved type declaration
*/
ResolvedReferenceTypeDeclaration resolveDeclaration(ClassOrInterfaceType type);
}
/**
* Configure parser with symbol resolution
*/
public class ParserConfiguration {
/**
* Set symbol resolver for type analysis
* @param symbolResolver Symbol resolver implementation
* @return This configuration for chaining
*/
public ParserConfiguration setSymbolResolver(SymbolResolver symbolResolver);
}Usage Examples:
import com.github.javaparser.symbolsolver.JavaSymbolSolver;
import com.github.javaparser.symbolsolver.resolution.typesolvers.CombinedTypeSolver;
import com.github.javaparser.symbolsolver.resolution.typesolvers.ReflectionTypeSolver;
import com.github.javaparser.symbolsolver.resolution.typesolvers.JavaParserTypeSolver;
// Configure symbol resolution
CombinedTypeSolver typeSolver = new CombinedTypeSolver();
typeSolver.add(new ReflectionTypeSolver()); // For JDK classes
typeSolver.add(new JavaParserTypeSolver(new File("src/main/java"))); // For project classes
JavaSymbolSolver symbolResolver = new JavaSymbolSolver(typeSolver);
ParserConfiguration config = new ParserConfiguration()
.setSymbolResolver(symbolResolver);
// Parse with symbol resolution enabled
JavaParser parser = new JavaParser(config);
CompilationUnit cu = parser.parse(code).getResult().get();
// Now you can resolve symbols
for (NameExpr nameExpr : cu.findAll(NameExpr.class)) {
try {
ResolvedValueDeclaration resolved = nameExpr.resolve();
System.out.println("Resolved: " + resolved.getName() + " -> " + resolved.getType());
} catch (UnsolvedSymbolException e) {
System.out.println("Could not resolve: " + nameExpr.getNameAsString());
}
}TypeSolver implementations provide the foundation for symbol resolution by locating type definitions.
/**
* Interface for solving/locating type declarations
*/
public interface TypeSolver {
/**
* Try to solve a type by name
* @param name Fully qualified or simple type name
* @return SymbolReference to the type declaration
*/
SymbolReference<ResolvedReferenceTypeDeclaration> tryToSolveType(String name);
/**
* Get parent type solver if this is a chained solver
* @return Parent type solver or null
*/
TypeSolver getParent();
/**
* Set parent type solver for chaining
* @param parent Parent type solver
*/
void setParent(TypeSolver parent);
}
/**
* Combined type solver that chains multiple solvers
*/
public class CombinedTypeSolver implements TypeSolver {
/**
* Create empty combined solver
*/
public CombinedTypeSolver();
/**
* Create with initial solvers
* @param solvers Initial type solvers
*/
public CombinedTypeSolver(TypeSolver... solvers);
/**
* Add a type solver to the chain
* @param typeSolver Type solver to add
*/
public void add(TypeSolver typeSolver);
}
/**
* Reflection-based type solver for JDK and classpath classes
*/
public class ReflectionTypeSolver implements TypeSolver {
/**
* Create reflection solver for current JRE
*/
public ReflectionTypeSolver();
/**
* Create reflection solver with explicit classloader
* @param classLoader ClassLoader to use for type resolution
*/
public ReflectionTypeSolver(ClassLoader classLoader);
/**
* Create reflection solver with filtering
* @param exploreJDK true to include JDK classes
*/
public ReflectionTypeSolver(boolean exploreJDK);
}
/**
* JavaParser-based type solver for source code
*/
public class JavaParserTypeSolver implements TypeSolver {
/**
* Create solver for source directory
* @param srcDir Source root directory
*/
public JavaParserTypeSolver(File srcDir);
/**
* Create solver for source directory with parser configuration
* @param srcDir Source root directory
* @param parserConfiguration Parser configuration to use
*/
public JavaParserTypeSolver(File srcDir, ParserConfiguration parserConfiguration);
}Usage Examples:
// Set up comprehensive type resolution
CombinedTypeSolver typeSolver = new CombinedTypeSolver();
// Add JDK classes
typeSolver.add(new ReflectionTypeSolver());
// Add project source code
typeSolver.add(new JavaParserTypeSolver(new File("src/main/java")));
typeSolver.add(new JavaParserTypeSolver(new File("src/test/java")));
// Add JAR dependencies
typeSolver.add(new JarTypeSolver(new File("lib/dependency.jar")));
// Use in symbol resolver
JavaSymbolSolver symbolResolver = new JavaSymbolSolver(typeSolver);Symbol resolution produces resolved declaration objects that provide detailed type information.
/**
* Base interface for resolved declarations
*/
public interface ResolvedDeclaration {
/**
* Get declaration name
* @return Name of the declaration
*/
String getName();
/**
* Check if this is a field declaration
* @return true if this is a field
*/
default boolean isField() { return false; }
/**
* Check if this is a parameter declaration
* @return true if this is a parameter
*/
default boolean isParameter() { return false; }
/**
* Check if this is a variable declaration
* @return true if this is a variable
*/
default boolean isVariable() { return false; }
/**
* Check if this is a method declaration
* @return true if this is a method
*/
default boolean isMethod() { return false; }
/**
* Check if this is a type declaration
* @return true if this is a type
*/
default boolean isType() { return false; }
}
/**
* Resolved value declaration (fields, parameters, variables)
*/
public interface ResolvedValueDeclaration extends ResolvedDeclaration {
/**
* Get the type of this value
* @return Resolved type
*/
ResolvedType getType();
}
/**
* Resolved method declaration
*/
public interface ResolvedMethodDeclaration extends ResolvedDeclaration {
/**
* Get return type
* @return Resolved return type
*/
ResolvedType getReturnType();
/**
* Get method parameters
* @return List of resolved parameters
*/
List<ResolvedParameterDeclaration> getParams();
/**
* Get number of parameters
* @return Parameter count
*/
int getNumberOfParams();
/**
* Get parameter at index
* @param i Parameter index
* @return Resolved parameter declaration
*/
ResolvedParameterDeclaration getParam(int i);
/**
* Check if method is static
* @return true if static
*/
boolean isStatic();
/**
* Get declaring type
* @return Type that declares this method
*/
ResolvedReferenceTypeDeclaration declaringType();
}
/**
* Resolved type declaration (classes, interfaces, enums)
*/
public interface ResolvedTypeDeclaration extends ResolvedDeclaration {
/**
* Get qualified name
* @return Fully qualified name
*/
String getQualifiedName();
/**
* Get package name
* @return Package name
*/
String getPackageName();
/**
* Get class name without package
* @return Simple class name
*/
String getClassName();
/**
* Check if this is a class
* @return true if this is a class
*/
default boolean isClass() { return false; }
/**
* Check if this is an interface
* @return true if this is an interface
*/
default boolean isInterface() { return false; }
/**
* Check if this is an enum
* @return true if this is an enum
*/
default boolean isEnum() { return false; }
}Usage Examples:
// Resolve method calls
for (MethodCallExpr methodCall : cu.findAll(MethodCallExpr.class)) {
try {
ResolvedMethodDeclaration resolved = methodCall.resolve();
System.out.println("Method: " + resolved.getQualifiedSignature());
System.out.println("Return type: " + resolved.getReturnType());
System.out.println("Declaring class: " + resolved.declaringType().getQualifiedName());
for (int i = 0; i < resolved.getNumberOfParams(); i++) {
ResolvedParameterDeclaration param = resolved.getParam(i);
System.out.println("Param " + i + ": " + param.getType());
}
} catch (UnsolvedSymbolException e) {
System.out.println("Could not resolve method: " + methodCall);
}
}
// Resolve field access
for (FieldAccessExpr fieldAccess : cu.findAll(FieldAccessExpr.class)) {
try {
ResolvedValueDeclaration resolved = fieldAccess.resolve();
System.out.println("Field: " + resolved.getName());
System.out.println("Type: " + resolved.getType());
} catch (UnsolvedSymbolException e) {
System.out.println("Could not resolve field: " + fieldAccess);
}
}Analyze and work with resolved types for comprehensive type information.
/**
* Base interface for resolved types
*/
public interface ResolvedType {
/**
* Get type description
* @return Human-readable type description
*/
String describe();
/**
* Check if this is a reference type
* @return true if reference type
*/
boolean isReferenceType();
/**
* Check if this is a primitive type
* @return true if primitive type
*/
boolean isPrimitive();
/**
* Check if this is an array type
* @return true if array type
*/
boolean isArray();
/**
* Check if this is assignable to another type
* @param other Target type
* @return true if assignable
*/
boolean isAssignableBy(ResolvedType other);
}
/**
* Resolved reference type (classes, interfaces)
*/
public interface ResolvedReferenceType extends ResolvedType {
/**
* Get type declaration
* @return Type declaration
*/
ResolvedReferenceTypeDeclaration getTypeDeclaration();
/**
* Get type parameters
* @return List of type parameters
*/
List<ResolvedType> getTypeParametersMap();
/**
* Check if this type is assignable to another
* @param other Target type
* @return true if assignable
*/
boolean isAssignableBy(ResolvedType other);
}
/**
* Resolved primitive type
*/
public interface ResolvedPrimitiveType extends ResolvedType {
/**
* Get primitive type kind
* @return Primitive type
*/
ResolvedPrimitiveType.Primitive getType();
public enum Primitive {
BOOLEAN, CHAR, BYTE, SHORT, INT, LONG, FLOAT, DOUBLE
}
}Usage Examples:
// Analyze expression types
for (Expression expr : cu.findAll(Expression.class)) {
try {
ResolvedType type = expr.calculateResolvedType();
System.out.println("Expression: " + expr);
System.out.println("Type: " + type.describe());
if (type.isPrimitive()) {
ResolvedPrimitiveType primitive = type.asPrimitive();
System.out.println("Primitive: " + primitive.getType());
} else if (type.isReferenceType()) {
ResolvedReferenceType refType = type.asReferenceType();
System.out.println("Class: " + refType.getQualifiedName());
}
} catch (UnsolvedSymbolException e) {
System.out.println("Could not resolve type for: " + expr);
}
}
// Check type compatibility
ResolvedType stringType = ...; // resolved String type
ResolvedType objectType = ...; // resolved Object type
boolean assignable = objectType.isAssignableBy(stringType); // trueNavigate the symbol resolution context and access scope information.
/**
* Resolution context for symbol lookup
*/
public class Context {
/**
* Solve symbol in this context
* @param name Symbol name to resolve
* @return Symbol reference
*/
public SymbolReference<? extends ResolvedValueDeclaration> solveSymbol(String name);
/**
* Solve method in this context
* @param name Method name
* @param argumentTypes Argument types
* @return Method reference
*/
public SymbolReference<ResolvedMethodDeclaration> solveMethod(
String name, List<ResolvedType> argumentTypes);
/**
* Get parent context
* @return Parent context or null
*/
public Context getParent();
}
/**
* Utility for navigating symbol resolution
*/
public class Navigator {
/**
* Get local variables in scope at a node
* @param node AST node
* @return List of local variables
*/
public static List<ResolvedValueDeclaration> getLocalVariables(Node node);
/**
* Find method declarations in a type
* @param type Type to search
* @param name Method name
* @return List of matching methods
*/
public static List<ResolvedMethodDeclaration> findMethods(
ResolvedReferenceTypeDeclaration type, String name);
}/**
* Exception thrown when symbol cannot be resolved
*/
public class UnsolvedSymbolException extends RuntimeException {
/**
* Get the unresolved symbol name
* @return Symbol name
*/
public String getName();
/**
* Get context where resolution failed
* @return Resolution context
*/
public Context getContext();
}
/**
* Exception for method resolution ambiguity
*/
public class MethodAmbiguityException extends RuntimeException {
/**
* Get candidate methods
* @return List of candidate methods
*/
public List<ResolvedMethodDeclaration> getCandidates();
}Install with Tessl CLI
npx tessl i tessl/maven-com-github-javaparser--javaparser-core