CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/maven-com-github-javaparser--javaparser-core

A comprehensive Java parsing library providing complete support for parsing Java source code from Java 1.0 through Java 21 with advanced analysis functionalities.

Pending
Overview
Eval results
Files

symbol-resolution.mddocs/

Symbol Resolution and Type Analysis

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.

Capabilities

Symbol Resolution Configuration

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());
    }
}

Type Solving

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);

Resolved Declarations

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);
    }
}

Type Analysis

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); // true

Context and Navigation

Navigate 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);
}

Error Handling

/**
 * 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

docs

ast-navigation.md

configuration.md

index.md

parsing.md

printing.md

serialization.md

symbol-resolution.md

visitors.md

tile.json