Skip to content

Java API

Java is the most complete CLDK analysis. JavaAnalysis gives you a typed symbol table, a call graph, subclass and interface queries, and comments. COCOA builds on these calls.

CLDK.java(project_path=...) returns a JavaAnalysis object backed by the codeanalyzer-java backend, which uses WALA. It builds the symbol table, the call graph, the subclass and interface relationships, and the comments. In CLDK 2.0 the backend is the optional extra cldk[java], and its wheel carries the jar and its own JVM. Caching is on by default under <project>/.codeanalyzer.

flowchart LR
    P[Java project] --> A["CLDK.java(project_path)"]
    A --> S[Symbol table]
    A --> CG[Call graph]
    A --> H[Subclasses & interfaces]
    A --> CM[Comments]

Analysis levels. analysis_level controls how much CLDK computes. AnalysisLevel.symbol_table, the default, populates classes, methods, and fields. AnalysisLevel.call_graph adds the call graph that get_call_graph, get_callers, and get_callees need. CLDK 2.0 adds AnalysisLevel.program_dependency_graph and AnalysisLevel.system_dependency_graph for dataflow. See Dataflow graphs. If you need call relationships, set the level when you build the analysis:

from cldk import CLDK
from cldk.analysis import AnalysisLevel
analysis = CLDK.java(
project_path="commons-cli",
analysis_level=AnalysisLevel.call_graph,
)

To run against a read-only Neo4j backend instead of the in-process backend, pass a Neo4jConnectionConfig as backend=:

from cldk import CLDK
from cldk.analysis import AnalysisLevel
from cldk.analysis.commons.backend_config import Neo4jConnectionConfig
analysis = CLDK.java(
project_path="commons-cli",
analysis_level=AnalysisLevel.call_graph,
backend=Neo4jConnectionConfig(
uri="bolt://localhost:7687",
username="neo4j",
password="password",
database="neo4j",
application_name="commons-cli",
),
)

Using Apache Commons CLI as the sample project.

# Every file -> its compilation unit (classes, methods, fields).
symbol_table = analysis.get_symbol_table()
print(len(analysis.get_classes()), "classes")
# 23 classes
import networkx as nx
cg = analysis.get_call_graph() # networkx.DiGraph, caller -> callee
print(cg) # DiGraph with N nodes / M edges
callers = analysis.get_callers(
target_class_name="org.apache.commons.cli.OptionBuilder",
target_method_declaration="create(String)",
)
# -> dict of caller method signatures + call-site locations

See the common tasks guide for more snippets, and the cocoa, the Code Context Agent plugin, for exposing these calls to an agent.

The full generated reference for the Java analysis API and data models follows.

Source on GitHub cldk 2.0.0rc8

API reference generated from cldk 2.0.0rc8.

Java analysis facade module.

This module provides the JavaAnalysis class, which serves as the primary high-level interface for performing static analysis on Java projects. It combines Tree-sitter-based parsing with the CodeAnalyzer backend to provide comprehensive code analysis capabilities.

The analysis operates on a project directory (cross-file call graphs, class hierarchies, the symbol table). The 1.x single-file source_code mode was removed in 2.0 (spec leg 3, J-10): pass the project directory, or hand a source string to TreesitterJava directly.

Key capabilities include

  • Symbol table extraction (classes, methods, fields, imports)
  • Call graph construction and traversal
  • Class hierarchy and inheritance analysis
  • Method parameter and signature analysis
  • Comment and Javadoc extraction
  • CRUD operation detection for enterprise applications
  • Entry point identification (main methods, REST endpoints)

The analysis is powered by

  • Tree-sitter: Fast incremental parsing for syntactic analysis
  • CodeAnalyzer: Semantic analysis backend (JAR-based)

See Also

  • PythonAnalysis: Python equivalent.
  • JCodeanalyzer: Backend implementation.
class JavaAnalysis

Analysis facade for Java code.

This class provides a comprehensive interface for performing static analysis on Java projects and source files. It combines Tree-sitter-based parsing for syntactic analysis with the CodeAnalyzer backend for semantic analysis.

The facade is initialized with project_dir and provides full analysis capabilities including cross-file call graphs, class hierarchies, and symbol tables; the single-file source_code mode was removed in 2.0.

Key features

  • Symbol table access with classes, methods, and fields
  • Call graph construction and traversal
  • Caller/callee relationship analysis
  • Class hierarchy and inheritance queries
  • Comment and Javadoc extraction
  • CRUD operation detection
  • Entry point identification

See Also

  • PythonAnalysis: Python equivalent.
  • JCodeanalyzer: Backend.
NameTypeDescription
project_dir
analysis_level
eager_analysis
target_files
backend_configJavaBackend
treesitter_javaTreesitterJava
backendJavaAnalysisBackend
has_resolution_edgesboolWhether call sites carry a resolved callee on this backend right now.
get_imports() -> List[str]

Return every distinct import target of the project, sorted.

A set, not a per-file listing and not the file’s import order: the Neo4j projection aggregates every import of a module that resolves to the same target onto one edge, so the order within a file is not recoverable there and a list that preserved it locally would be one the two backends disagree about. The 1.x signature is a flat List[str] and never carried the file an import belongs to either.

Returns:

  • List[str]: Fully qualified import targets ("java.util.List", "java.io.*"), sorted and
  • List[str]: distinct. A wildcard keeps its .*; static imports are not marked here.

See Also get_symbol_table: per-file JImport records, with spans and the static/wildcard flags.

get_variables(**kwargs) -> Dict

Return the local variables each callable declares.

Parameters:

NameTypeDescription
**kwargsThe 1.x signature’s filtering options, of which there are none. An unexpected keyword raises TypeError naming it, rather than being ignored: silently dropping a filter returns an unfiltered answer that looks filtered.

Returns:

  • Dict: {"<type fqn>.<signature>": [JLocalVariable, ...]}, the J-1 call-graph key of
  • Dict: meth:get_call_graph, and one entry per callable including those declaring nothing.
  • Dict: Fields and parameters are not folded in; they have their own accessors. Each list is
  • Dict: ordered by (start_line, name): the Neo4j projection carries a line-only span, so
  • Dict: two variables declared on one line have no order there to preserve.

Raises:

  • TypeError: An unexpected keyword argument was passed.

See Also get_fields: class-level fields. get_method_parameters: a callable’s parameters.

JavaAnalysis.get_service_entry_point_classes
Section titled “JavaAnalysis.get_service_entry_point_classes”
get_service_entry_point_classes(**kwargs) -> Dict[str, JType]

Return all service entry-point classes.

This method is intended to identify classes that serve as entry points for services, such as JAX-RS resources, Spring controllers, or servlet classes.

Parameters:

NameTypeDescription
**kwargsFramework-specific filtering options (e.g., annotation filters for @RestController, @Path, etc.).

Returns:

  • Dict[str, JType]: A dictionary mapping qualified class names to JType objects
  • Dict[str, JType]: for classes identified as service entry points.

Raises:

  • NotImplementedError: This functionality is not yet implemented.

See Also get_entry_point_classes: For general entry point detection.

JavaAnalysis.get_service_entry_point_methods
Section titled “JavaAnalysis.get_service_entry_point_methods”
get_service_entry_point_methods(**kwargs) -> Dict[str, Dict[str, JCallable]]

Return all service entry-point methods.

This method is intended to identify methods that serve as entry points for services, such as REST endpoint handlers, servlet methods, or message handlers.

Parameters:

NameTypeDescription
**kwargsFramework-specific filtering options (e.g., HTTP method filters, annotation filters for @GET, @POST, etc.).

Returns:

  • Dict[str, Dict[str, JCallable]]: A nested dictionary mapping class names to method signatures to
  • Dict[str, Dict[str, JCallable]]: class:JCallable objects for methods identified as service
  • Dict[str, Dict[str, JCallable]]: entry points.

Raises:

  • NotImplementedError: This functionality is not yet implemented.

See Also get_entry_point_methods: For general entry point detection.

get_application_view() -> JApplication

Return the complete analyzed application model.

Returns the top-level JApplication object that represents the entire analyzed Java project. This object contains all compilation units, classes, methods, and their relationships discovered during analysis.

Returns:

  • JApplication: class:~cldk.models.java.JApplication object containing: - All compilation units (symbol_table attribute) - Project-level metadata - Aggregated statistics about the codebase

See Also get_symbol_table: For direct access to the symbol table. get_compilation_units: For a list of compilation units.

get_symbol_table() -> Dict[str, JCompilationUnit]

Return the symbol table mapping file paths to compilation units.

Returns a dictionary that maps each analyzed Java file’s path to its corresponding JCompilationUnit object. This is the primary data structure for accessing analyzed code structure.

Returns:

  • Dict[str, JCompilationUnit]: A dictionary where keys are file paths (as strings) and values are
  • Dict[str, JCompilationUnit]: class:~cldk.models.java.JCompilationUnit objects containing: - Package declaration - Import statements - Type declarations (classes, interfaces, enums) - Method and field definitions

See Also get_compilation_units: For a list without file paths. get_java_compilation_unit: For direct lookup by path.

get_compilation_units() -> List[JCompilationUnit]

Return all compilation units in the project as a list.

Returns all JCompilationUnit objects discovered during analysis as a flat list. Each compilation unit represents a single Java source file.

Returns:

  • List[JCompilationUnit]: A list of JCompilationUnit objects,
  • List[JCompilationUnit]: one for each Java source file analyzed in the project.

See Also get_symbol_table: For file-path-keyed access.

get_class_hierarchy() -> nx.DiGraph

Return the complete class inheritance hierarchy as a graph.

This method is intended to return a NetworkX directed graph representing the full class inheritance relationships in the project, including extends and implements relationships.

Returns:

  • nx.DiGraph: A networkx.DiGraph with one node per declared type (interfaces, enums, annotations
  • nx.DiGraph: and records included) and an edge subclass → supertype carrying
  • nx.DiGraph: type="EXTENDS" or type="IMPLEMENTS", Java projects the two as separate
  • nx.DiGraph: relationship types and this keeps them apart. A supertype outside the project is a node
  • nx.DiGraph: too, spelled as the declaration wrote it.

See Also get_sub_classes: For finding subclasses of a specific class. get_extended_classes: For finding superclasses. get_implemented_interfaces: For interface implementations.

is_parsable(source_code: str) -> bool

Check if the given source code is valid Java syntax.

Uses the Tree-sitter Java parser to attempt parsing the source code. This is useful for validating code snippets before further processing or for filtering out malformed code.

Parameters:

NameTypeDescription
source_codestrA string containing Java source code to validate. Can be a complete compilation unit, a class definition, or any syntactically valid Java code fragment.

Returns:

  • bool: True if the source code parses without syntax errors,
  • bool: False otherwise. Note that this only checks syntactic validity,
  • bool: not semantic correctness (e.g., type errors won’t be caught).

See Also get_raw_ast: To obtain the full AST for valid code.

get_raw_ast(source_code: str) -> Tree

Parse source code and return the Tree-sitter AST.

Parses the provided Java source code using Tree-sitter and returns the resulting abstract syntax tree. The AST can be traversed to extract syntactic information about the code structure.

Parameters:

NameTypeDescription
source_codestrA string containing Java source code to parse. Should be syntactically valid Java code.

Returns:

  • Tree: A Tree-sitter Tree object representing the parsed AST. The tree
  • Tree: contains nodes representing all syntactic elements of the code,
  • Tree: including classes, methods, statements, and expressions.

Note If the source code contains syntax errors, Tree-sitter will still return a tree but with ERROR nodes at the locations of parse errors. Use is_parsable to check for valid syntax first.

See Also is_parsable: To validate syntax before parsing.

get_call_graph() -> nx.DiGraph

Return the project call graph as a NetworkX directed graph.

Constructs and returns a directed graph representing method call relationships across the entire project. Each node represents a method, and each edge represents a call from one method to another.

The call graph requires analysis_level of at least "call_graph"; below it the graph is empty.

Returns:

  • nx.DiGraph: A networkx.DiGraph where: - Nodes are keyed by the string "<type fqn>.<signature>" (e.g. "com.acme.Svc.run(java.lang.String)"), with a JMethodDetail under method_detail and kind="callable" - Edges represent call relationships, directed from caller to callee, with type, weight and calling_lines

See Also get_callers: For finding callers of a specific method. get_callees: For finding callees of a specific method. get_class_call_graph: For class-scoped call graphs.

get_call_graph_json() -> str

Return the complete analysis results serialized as JSON.

Serializes the full analysis results, including the call graph and symbol table, to a JSON string. This is useful for persisting analysis results, sharing with other tools, or debugging.

Returns:

  • str: A JSON-formatted string containing the complete analysis data,
  • str: including compilation units, classes, methods, and call
  • str: relationships.

See Also get_call_graph: For the graph object directly.

get_callers(target_class_name: str, target_method_declaration: str, using_symbol_table: bool = False) -> Dict

Return all methods that call the specified target method.

Finds and returns information about all methods that invoke the specified target method. This is useful for impact analysis and understanding how a method is used throughout the codebase.

Parameters:

NameTypeDescription
target_class_namestrThe fully qualified name of the class containing the target method (e.g., "com.example.service.UserService").
target_method_declarationstrThe method signature to find callers for (e.g., "getUser(String)" or "process())").
using_symbol_tableboolIf True, uses the symbol table for resolution (faster but may be less accurate). If False (default), uses the full call graph analysis.

Returns:

  • Dict: A dictionary containing information about all callers, including: - Caller method signatures - Call site locations (file and line) - Caller class information

See Also get_callees: For the reverse direction (what a method calls). get_call_graph: For the complete call relationship graph.

get_callees(source_class_name: str, source_method_declaration: str, using_symbol_table: bool = False) -> Dict

Return all methods called by the specified source method.

Finds and returns information about all methods that are invoked by the specified source method. This is useful for understanding method dependencies and tracing execution paths.

Parameters:

NameTypeDescription
source_class_namestrThe fully qualified name of the class containing the source method (e.g., "com.example.service.OrderService").
source_method_declarationstrThe method signature to find callees for (e.g., "processOrder(Order)").
using_symbol_tableboolIf True, uses the symbol table for resolution (faster but may be less accurate). If False (default), uses the full call graph analysis.

Returns:

  • Dict: A dictionary containing information about all callees, including: - Callee method signatures - Target class information - Call site locations within the source method

See Also get_callers: For the reverse direction (who calls a method). get_call_graph: For the complete call relationship graph.

get_methods() -> Dict[str, Dict[str, JCallable]]

Return all methods in the project grouped by class.

Retrieves all methods from all classes in the analyzed project, organized in a nested dictionary structure by qualified class name and then method signature.

Returns:

  • Dict[str, Dict[str, JCallable]]: A nested dictionary with structure:: { “com.example.ClassName”: { “methodName(ParamType)”: JCallable, “anotherMethod()”: JCallable, … }, … }
  • Dict[str, Dict[str, JCallable]]: class:~cldk.models.java.JCallable contains the method’s
  • Dict[str, Dict[str, JCallable]]: signature, parameters, return type, body, annotations, and other
  • Dict[str, Dict[str, JCallable]]: metadata.

See Also get_methods_in_class: For methods of a specific class. get_method: For a single method by name.

get_classes() -> Dict[str, JType]

Return all classes in the project.

Retrieves all type declarations (classes, interfaces, enums, records) discovered during analysis, organized by their fully qualified names.

Returns:

  • Dict[str, JType]: A dictionary mapping fully qualified class names (strings) to
  • Dict[str, JType]: class:~cldk.models.java.JType objects containing class metadata,
  • Dict[str, JType]: methods, fields, and inheritance information.

See Also get_class: For a single class by name. get_classes_by_criteria: For filtered class retrieval.

get_classes_by_criteria(inclusions: List[str] | None = None, exclusions: List[str] | None = None) -> Dict[str, JType]

Return classes matching inclusion/exclusion filter criteria.

Filters the project’s classes based on substring matching against their qualified names. Classes are included if their name contains any inclusion substring AND does not contain any exclusion substring.

Parameters:

NameTypeDescription
inclusionsList[str] | NoneList of substrings that class names must contain to be included. If None or empty, no inclusion filtering is applied (effectively includes nothing unless you have at least one inclusion pattern).
exclusionsList[str] | NoneList of substrings that class names must NOT contain. Classes matching any exclusion pattern are filtered out, even if they match an inclusion pattern.

Returns:

  • Dict[str, JType]: A dictionary mapping qualified class names to
  • Dict[str, JType]: class:~cldk.models.java.JType objects for classes matching
  • Dict[str, JType]: the criteria.

Note The filtering uses substring matching (in operator), not regular expressions or glob patterns.

See Also get_classes: For all classes without filtering.

get_class(qualified_class_name: str) -> JType | None

Return a specific class by its qualified name.

Retrieves detailed information about a single class, including its methods, fields, annotations, modifiers, and inheritance information.

Parameters:

NameTypeDescription
qualified_class_namestrThe fully qualified name of the class (e.g., "com.example.service.UserService").

Returns:

  • JType \| None: class:~cldk.models.java.JType object containing all analyzed
  • JType \| None: information about the class. Returns None if the class is not
  • JType \| None: found in the analyzed project.

See Also get_classes: For all classes in the project. get_java_file: To find which file contains a class.

get_method(qualified_class_name: str, qualified_method_name: str) -> JCallable | None

Return a specific method by class and method signature.

Retrieves detailed information about a single method, including its signature, parameters, return type, annotations, body, and metrics.

Parameters:

NameTypeDescription
qualified_class_namestrThe fully qualified name of the class containing the method (e.g., "com.example.service.UserService").
qualified_method_namestrThe method signature to retrieve (e.g., "getUser(String)" or "process())").

Returns:

  • JCallable \| None: class:~cldk.models.java.JCallable object containing all
  • JCallable \| None: analyzed information about the method. Returns None if the
  • JCallable \| None: method is not found.

Note Two fields depend on which backend answered. On the analysis.json backend code is the body block and body holds every body node. On the Neo4j backend code is the whole declaration (it ends with the body block, because the graph projects one line range per callable and no body_span) and body holds the call nodes only, about 30% of the graph’s body nodes, which is what call_sites needs and all it needs.

See Also get_methods_in_class: For all methods of a class. get_method_parameters: For just the parameter list.

get_method_parameters(qualified_class_name: str, qualified_method_name: str) -> List[JCallableParameter]

Return the parameters of a specific method.

Parameters:

NameTypeDescription
qualified_class_namestrThe fully qualified name of the class containing the method.
qualified_method_namestrThe method signature to get parameters for.

Returns:

  • List[JCallableParameter]: class:~cldk.models.java.models.JCallableParameter objects
  • List[JCallableParameter]: (name, type, annotations, position), in signature order. Returns an
  • List[JCallableParameter]: empty list if the method is not found or has no parameters. (1.x
  • List[JCallableParameter]: annotated this List[str]; it always returned the objects.)

See Also get_method: For complete method information.

get_java_file(qualified_class_name: str) -> str | None

Return the file path containing a class with the given name.

Given a qualified class name, returns the file path where that class is defined. This is useful for navigating from class references back to source files.

Parameters:

NameTypeDescription
qualified_class_namestrThe fully qualified name of the class to locate (e.g., "com.example.service.UserService").

Returns:

  • str \| None: The file path (as a string) containing the class definition.
  • str \| None: Returns None if no class with the given name is found.

See Also get_class: To get the full class object by name. get_java_compilation_unit: To get the compilation unit.

get_java_compilation_unit(file_path: str) -> JCompilationUnit

Return the compilation unit for a specific file path.

Retrieves the JCompilationUnit object corresponding to a specific Java source file in the analyzed project.

Parameters:

NameTypeDescription
file_pathstrThe path to the Java file, which should be an absolute path or a path relative to the project root.

Returns:

  • JCompilationUnit: class:~cldk.models.java.JCompilationUnit for the file,
  • JCompilationUnit: containing all analyzed information about package, imports,
  • JCompilationUnit: and type declarations. Returns None if the file is not
  • JCompilationUnit: part of the analyzed project.

See Also get_symbol_table: For bulk access to all compilation units. get_java_file: For reverse lookup (class to file).

get_methods_in_class(qualified_class_name: str) -> Dict[str, JCallable]

Return all methods defined in a specific class.

Retrieves all methods belonging to the specified class, including instance methods, static methods, and constructors.

Parameters:

NameTypeDescription
qualified_class_namestrThe fully qualified name of the class (e.g., "com.example.service.UserService").

Returns:

  • Dict[str, JCallable]: A dictionary mapping method signatures (strings) to
  • Dict[str, JCallable]: class:~cldk.models.java.JCallable objects. Returns an empty
  • Dict[str, JCallable]: dictionary if the class is not found or has no methods.

See Also get_method: For a single method by signature. get_constructors: For constructors specifically.

get_constructors(qualified_class_name: str) -> Dict[str, JCallable]

Return all constructors of a specific class.

Retrieves all constructor methods defined in the specified class. Constructors are methods with the same name as the class.

Parameters:

NameTypeDescription
qualified_class_namestrThe fully qualified name of the class (e.g., "com.example.model.User").

Returns:

  • Dict[str, JCallable]: A dictionary mapping constructor signatures to
  • Dict[str, JCallable]: class:~cldk.models.java.JCallable objects. Returns an empty
  • Dict[str, JCallable]: dictionary if the class has no explicit constructors.

See Also get_methods_in_class: For all methods including constructors.

get_fields(qualified_class_name: str) -> List[JField]

Return all fields (member variables) of a specific class.

Retrieves all field declarations in the specified class, including instance fields, static fields, and constants.

Parameters:

NameTypeDescription
qualified_class_namestrThe fully qualified name of the class (e.g., "com.example.model.User").

Returns:

  • List[JField]: A list of JField objects, each
  • List[JField]: containing information about a field’s name, type, modifiers,
  • List[JField]: and annotations.

See Also get_class: For complete class information.

get_nested_classes(qualified_class_name: str) -> List[JType]

Return all nested (inner) classes of a specific class.

Retrieves all classes that are defined inside the specified class, including static nested classes and inner classes.

Parameters:

NameTypeDescription
qualified_class_namestrThe fully qualified name of the outer class (e.g., "com.example.model.Container").

Returns:

  • List[JType]: A list of JType objects for each
  • List[JType]: nested class. Returns an empty list if no nested classes exist.

See Also get_class: For the outer class information.

get_sub_classes(qualified_class_name: str) -> Dict[str, JType]

Return all classes that extend the specified class.

Finds all classes in the project that directly extend the specified base class. This is useful for understanding class hierarchies and finding implementations of abstract classes.

Parameters:

NameTypeDescription
qualified_class_namestrThe fully qualified name of the base class to find subclasses of (e.g., "com.example.base.BaseService").

Returns:

  • Dict[str, JType]: A dictionary mapping qualified class names to
  • Dict[str, JType]: class:~cldk.models.java.JType objects for all classes that
  • Dict[str, JType]: extend the specified class.

See Also get_extended_classes: For the reverse (what a class extends). get_class_hierarchy: For the full inheritance graph.

get_extended_classes(qualified_class_name: str) -> List[str]

Return the superclass(es) that a class extends.

Retrieves the parent class for the specified class. In Java, a class can extend at most one other class (single inheritance).

Parameters:

NameTypeDescription
qualified_class_namestrThe fully qualified name of the class to get the superclass for.

Returns:

  • List[str]: A list of superclass names (typically containing zero or one
  • List[str]: element, since Java has single inheritance). Returns empty list
  • List[str]: if the class directly extends Object or is not found.

See Also get_sub_classes: For finding classes that extend this class. get_implemented_interfaces: For interface implementations.

get_implemented_interfaces(qualified_class_name: str) -> List[str]

Return all interfaces implemented by a class.

Retrieves the list of interfaces that the specified class implements. A Java class can implement multiple interfaces.

Parameters:

NameTypeDescription
qualified_class_namestrThe fully qualified name of the class to get implemented interfaces for.

Returns:

  • List[str]: A list of interface names (as strings) that the class implements.
  • List[str]: Returns empty list if the class implements no interfaces.

See Also get_extended_classes: For class inheritance.

get_class_call_graph(qualified_class_name: str, method_signature: str | None = None, using_symbol_table: bool = False) -> List[Tuple[JMethodDetail, JMethodDetail]]

Return call graph edges reachable from a class or method.

Extracts a subset of the call graph containing only edges reachable from the specified class (and optionally a specific method within that class). This is useful for understanding the call structure of a specific component without the noise of the full project graph.

Parameters:

NameTypeDescription
qualified_class_namestrThe fully qualified name of the class to start traversal from (e.g., "com.example.service.UserService").
method_signaturestr | NoneOptional method signature to further constrain the starting point. If provided, only edges reachable from that specific method are included. If None, edges from all methods in the class are included.
using_symbol_tableboolIf True, uses the symbol table for faster but potentially less accurate resolution. If False (default), uses the full call graph analysis.

Returns:

  • List[Tuple[JMethodDetail, JMethodDetail]]: A list of tuples (caller, callee) where each element is a
  • List[Tuple[JMethodDetail, JMethodDetail]]: class:~cldk.models.java.JMethodDetail object representing
  • List[Tuple[JMethodDetail, JMethodDetail]]: a method in the call relationship.

See Also get_call_graph: For the complete project call graph. get_callees: For direct callees of a single method.

get_entry_point_classes() -> Dict[str, JType]

Return all classes identified as application entry points.

Identifies classes that serve as entry points for the application, such as classes containing main methods, servlet classes, or framework-specific entry point classes.

Returns:

  • Dict[str, JType]: A dictionary mapping qualified class names to
  • Dict[str, JType]: class:~cldk.models.java.JType objects for classes identified
  • Dict[str, JType]: as entry points.

See Also get_entry_point_methods: For entry point methods.

get_entry_point_methods() -> Dict[str, Dict[str, JCallable]]

Return all methods identified as application entry points.

Identifies methods that serve as entry points for the application, such as main methods, servlet doGet/doPost methods, or framework- specific handler methods.

Returns:

  • Dict[str, Dict[str, JCallable]]: A nested dictionary mapping class names to method signatures
  • Dict[str, Dict[str, JCallable]]: class:~cldk.models.java.JCallable objects for methods
  • Dict[str, Dict[str, JCallable]]: identified as entry points.

See Also get_entry_point_classes: For entry point classes.

remove_all_comments() -> str

Remove all comments from the source code.

Strips all single-line (//) and multi-line (/* */) comments from the source code, including Javadoc comments. This is useful for code analysis that should ignore comment content.

Raises:

  • NotImplementedError: always. This accessor only ever operated on the
  • meth:TreesitterJava.remove_all_comments directly.

See Also get_all_comments: For extracting comments instead.

get_methods_with_annotations(annotations: List[str]) -> Dict[str, List[Dict]]

Return methods decorated with specific annotations.

This method is intended to find all methods that have any of the specified annotations, such as @Override, @Test, @RequestMapping, or custom annotations.

Parameters:

NameTypeDescription
annotationsList[str]List of annotation names to search for (e.g., ["Override", "Test", "RequestMapping"]). The @ symbol should not be included.

Returns:

  • Dict[str, List[Dict]]: A dictionary keyed by the strings passed in, each mapping to a list of
  • Dict[str, List[Dict]]: {"class", "signature", "method_name", "body"} dicts, sorted by
  • Dict[str, List[Dict]]: (class, signature). An annotation no callable carries is omitted. body is
  • Dict[str, List[Dict]]: attr:~cldk.models.java.models.JCallable.code, which is the body block off
  • Dict[str, List[Dict]]: analysis.json and the whole declaration off the Neo4j projection, the same
  • Dict[str, List[Dict]]: documented model property get_test_methods hands back.
  • Dict[str, List[Dict]]: Matching reads the analyzer’s own annotations rather than re-parsing source, so it
  • Dict[str, List[Dict]]: answers on a Neo4j-backed analysis, which carries no module source at all.

See Also get_test_methods: For finding test methods specifically. get_decorated_callables: The projected form, whose J-5 marker rule this shares.

get_test_methods() -> Dict[str, str]

Return methods identified as test methods.

A callable is a test method when one of its own annotations is a test-declaring one: @Test (JUnit 4/5, TestNG), @ParameterizedTest, @RepeatedTest, @TestFactory or @TestTemplate. The annotation is matched by simple name, so a fully qualified spelling (@org.junit.Test) matches too, and its arguments are ignored, the same marker rule the spec’s J-5 gives get_decorated_callables.

This reads the analyzer’s own annotations off the model rather than re-parsing a module’s source, so it answers identically on both backends: a Neo4j-backed analysis carries no module source at all (JCompilationUnit.source is ""), and the source-parsing version returned {} there, an empty reading as “this application has no tests” on an application with thousands.

Returns:

  • Dict[str, str]: A dictionary mapping "<type fqn>.<signature>", the call-graph node key of J-1,
  • Dict[str, str]: unique application-wide, to the callable’s code. Note that code is the body
  • Dict[str, str]: block off analysis.json and the whole declaration off the Neo4j projection
  • Dict[str, str]: (code).

See Also get_methods_with_annotations: For finding methods with any annotation.

get_calling_lines(target_method_name: str) -> List[int]

Return line numbers where a method is called.

This method is intended to find all line numbers in the source code where the specified method is invoked.

Parameters:

NameTypeDescription
target_method_namestrThe name of the method to find calls to.

Returns:

  • List[int]: Sorted, distinct absolute file lines of every call to a method of that name anywhere
  • List[int]: in the project, read off get_call_graph()’s calling_lines edge attribute. A full
  • List[int]: signature is accepted and cut at its first (; overloads share a name at a call site
  • List[int]: and so cannot be separated here. Empty when nothing calls that name.

See Also get_callers: For finding caller methods instead of lines.

get_call_targets(declared_methods: dict) -> Set[str]

Return call targets using simple name resolution.

This method is intended to find all methods that could be called based on simple name matching in the AST, without full semantic analysis.

Parameters:

NameTypeDescription
declared_methodsdictDictionary of declared method names and signatures to match against.

Returns:

  • Set[str]: The subset of declared_methods’ keys, cut to their simple names at the last
  • Set[str]: (, so a signature-keyed dict such as get_methods_in_class’s can be passed
  • Set[str]: straight in, that some call site in the project actually writes. Simple-name matching
  • Set[str]: no overload resolution, no receiver typing, no hierarchy walk.

See Also get_call_graph: For full semantic call resolution.

get_all_crud_operations() -> List[Dict[str, Union[JType, JCallable, List[JCRUDOperation]]]]

Return all CRUD (Create, Read, Update, Delete) operations.

Identifies and returns all database operations in the project by analyzing JPA/Hibernate annotations, repository patterns, and SQL statements. This is useful for understanding data access patterns in enterprise applications.

Returns:

  • List[Dict[str, Union[JType, JCallable, List[JCRUDOperation]]]]: A list of dictionaries, each containing: - "class": The JType containing the operation - "method": The JCallable performing the operation - "operations": List of JCRUDOperation objects

See Also get_all_create_operations: For create operations only. get_all_read_operations: For read operations only. get_all_update_operations: For update operations only. get_all_delete_operations: For delete operations only.

get_all_create_operations() -> List[Dict[str, Union[JType, JCallable, List[JCRUDOperation]]]]

Return all Create operations from CRUD analysis.

Identifies database insert/create operations by analyzing save(), persist(), insert(), and similar patterns.

Returns:

  • List[Dict[str, Union[JType, JCallable, List[JCRUDOperation]]]]: A list of dictionaries with class, method, and operation details.
  • List[Dict[str, Union[JType, JCallable, List[JCRUDOperation]]]]: Same structure as get_all_crud_operations.

See Also get_all_crud_operations: For all CRUD operations.

get_all_read_operations() -> List[Dict[str, Union[JType, JCallable, List[JCRUDOperation]]]]

Return all Read operations from CRUD analysis.

Identifies database read/select operations by analyzing find(), get(), select(), and similar patterns.

Returns:

  • List[Dict[str, Union[JType, JCallable, List[JCRUDOperation]]]]: A list of dictionaries with class, method, and operation details.
  • List[Dict[str, Union[JType, JCallable, List[JCRUDOperation]]]]: Same structure as get_all_crud_operations.

See Also get_all_crud_operations: For all CRUD operations.

get_all_update_operations() -> List[Dict[str, Union[JType, JCallable, List[JCRUDOperation]]]]

Return all Update operations from CRUD analysis.

Identifies database update operations by analyzing update(), merge(), set(), and similar patterns.

Returns:

  • List[Dict[str, Union[JType, JCallable, List[JCRUDOperation]]]]: A list of dictionaries with class, method, and operation details.
  • List[Dict[str, Union[JType, JCallable, List[JCRUDOperation]]]]: Same structure as get_all_crud_operations.

See Also get_all_crud_operations: For all CRUD operations.

get_all_delete_operations() -> List[Dict[str, Union[JType, JCallable, List[JCRUDOperation]]]]

Return all Delete operations from CRUD analysis.

Identifies database delete operations by analyzing delete(), remove(), and similar patterns.

Returns:

  • List[Dict[str, Union[JType, JCallable, List[JCRUDOperation]]]]: A list of dictionaries with class, method, and operation details.
  • List[Dict[str, Union[JType, JCallable, List[JCRUDOperation]]]]: Same structure as get_all_crud_operations.

See Also get_all_crud_operations: For all CRUD operations.

get_comments_in_a_method(qualified_class_name: str, method_signature: str) -> List[JComment]

Return the method’s own comment.

Not every comment inside the body: on both backends this is the analyzer’s per-declaration comment list, which holds the comment immediately above the declaration and nothing else (at most one; 70 of the 128 callables in the committed -a 4 fixture have one, 65 of them javadoc). Comments inside a method body reach the SDK only through get_comment_in_file, which reports the whole file’s.

Parameters:

NameTypeDescription
qualified_class_namestrThe fully qualified name of the class containing the method.
method_signaturestrThe method signature to get comments from.

Returns:

  • List[JComment]: A list of JComment objects found
  • List[JComment]: within the method body. Returns empty list if method not found.

Note On a backend whose source keeps only per-declaration javadoc, the Neo4j backend, this narrows to the method’s javadoc alone: a strictly smaller set than every comment in the body, and still a real answer about a real declaration, which is why this accessor narrows where get_all_comments and get_comment_in_file refuse (J-16).

See Also get_comments_in_a_class: For class-level comments. get_all_comments: For all comments in the project.

get_comments_in_a_class(qualified_class_name: str) -> List[JComment]

Return the class’s own comment.

Not the comments inside the class body: on both backends this is the type declaration’s own comment list, the comment immediately above class Foo. A method’s comment is on get_comments_in_a_method, and an inline comment in a body is on neither; get_comment_in_file reports the whole file’s.

Parameters:

NameTypeDescription
qualified_class_namestrThe fully qualified name of the class.

Returns:

  • List[JComment]: A list of JComment objects found
  • List[JComment]: within the class. Returns empty list if class not found.

Note Narrows to the class’s javadoc alone on a javadoc-only backend, in exactly the way get_comments_in_a_method does (J-16).

See Also get_comments_in_a_method: For method-specific comments. get_comment_in_file: For file-level comments.

get_comment_in_file(file_path: str) -> List[JComment]

Return all comments in a specific file.

Retrieves all comment nodes from the specified source file, including file-level comments, class comments, and method comments.

Parameters:

NameTypeDescription
file_pathstrThe path to the Java file.

Returns:

  • List[JComment]: A list of JComment objects found
  • List[JComment]: in the file. Returns empty list if file not found.

Raises:

  • CodeanalyzerExecutionException: If the backend’s source carries no file-level comments at all, the Neo4j projection does not, naming what is missing and what to read instead. An empty list would read as “this file has no comments” (J-16).

See Also get_all_comments: For comments across all files.

get_all_comments() -> Dict[str, List[JComment]]

Return all comments in the project grouped by file.

Retrieves all comment nodes from all analyzed files, organized by file path.

Returns:

  • Dict[str, List[JComment]]: A dictionary mapping file paths (strings) to lists of
  • Dict[str, List[JComment]]: class:~cldk.models.java.JComment objects.

Raises:

  • CodeanalyzerExecutionException: As get_comment_in_file does, and for the same reason (J-16).

See Also get_all_docstrings: For Javadoc comments only.

get_all_docstrings() -> Dict[str, List[JComment]]

Return all Javadoc comments in the project grouped by file.

Retrieves only Javadoc-style comments (/** ... */) from all analyzed files. These typically document classes, methods, and fields.

Returns:

  • Dict[str, List[JComment]]: A dictionary mapping file paths (strings) to lists of
  • Dict[str, List[JComment]]: class:~cldk.models.java.JComment objects where
  • Dict[str, List[JComment]]: is_javadoc is True.

Note Which javadoc depends on the backend: the analysis.json backend reports each compilation unit’s own comment list, holding the file-level javadoc; the Neo4j backend reports the javadoc of each declaration in the file (type, callable, field, enum constant, record component). Both are javadoc keyed by file, and they are different sets for the same file (J-16).

See Also get_all_comments: For all comment types.

locate(path: str, line: int) -> LocateResult

Resolve a source position to its enclosing callable, with the source in hand.

The single most-needed query for triaging a scanner alert: an alert arrives as file:line and this resolves it to the enclosing callable in one call, rather than get_method, falling back to get_callers, falling back to scanning the symbol table by hand. Four outcomes stay distinguishable, see LocateResult: inside a callable (callable set, plus body when a body node is that precise), at real module scope (module_scope diagnostic), in the gap between two callables (also module scope, never snapped to the nearest callable), or in a file the analysis has no module for (file_not_in_graph).

There is no col parameter: the Neo4j graph projects only start_line/end_line on :JCallable and :JBodyNode, so a column would work in process and be silently inert over the graph.

Parameters:

NameTypeDescription
pathstrThe file path. Normalised against the backend’s module keys, so a ./-prefixed or absolute path resolves rather than reading back as file_not_in_graph.
lineintThe 1-based line number.

Returns:

  • LocateResult: class:~cldk.analysis.commons.results.LocateResult carrying the innermost body
  • LocateResult: node, the enclosing callable, its owning type, its module, and the source slice, never
  • LocateResult: an ambiguous empty. module.module_name is the unit’s declared package (J-2),
  • LocateResult: and source is the enclosing callable’s text, which is the body block on the
  • LocateResult: analysis.json backend and the whole declaration over Neo4j (see
  • LocateResult: meth:get_source). A module-scope result over Neo4j is "" plus a
  • LocateResult: module_source_unavailable diagnostic: the graph carries no module text.

See Also locate_many: The bulk form, the point, not an optimisation.

locate_many(positions: Sequence[Tuple[str, int]]) -> List[LocateResult]

Resolve many (path, line) positions in one round trip, in input order.

Parameters:

NameTypeDescription
positionsSequence[Tuple[str, int]]The (path, line) pairs to resolve, e.g. from a scanner’s alert list.

Returns:

  • List[LocateResult]: class:~cldk.analysis.commons.results.LocateResult per input position, in the
  • List[LocateResult]: same order.

See Also locate: The single-position form.

resolve_callable(name: str, in_class: str | None = None, in_module: str | None = None) -> SliceNode

Resolve a callable name to the one callable it names, in the caller’s vocabulary.

The addressing step every name-taking accessor performs, exposed so a caller can perform it once and keep the answer::

node = java.resolve_callable("cancelOrder(java.lang.Integer, boolean)", in_class="TradeDirect")
node.callable # "…impl.direct.TradeDirect.cancelOrder(java.lang.Integer, boolean)"
node.file, node.line

name matches whole or as a dotted suffix, and against the signature with its parameter tail cut, so "cancelOrder" names a method a caller has not typed the parameters of; the tail-carrying spelling is what resolves one overload out of a pair (J-3). in_class is a dotted suffix of the owning type’s qualified name, which, for a local or anonymous class, carries the callable that declares it (the J-1 erratum); in_module is a repo-relative path suffix or a dotted spelling of the unit’s declared package, optionally qualified by a type it declares (J-2). Ambiguity raises with every candidate; nothing is guessed.

Everything the analyzer emitted as a callable is addressable (J-6): an initializer (<clinit>$0()) resolves and behaves like a method, and an implicit callable resolves with line=-1, it has no span at all, which is why get_source refuses it by name rather than returning an empty string.

Raises:

  • AmbiguousName: More than one callable matched.
  • SelectorNotInGraph: Nothing matched, naming the argument that missed.
resolve_value(name: str, within: str) -> SliceNode

Resolve a value name inside a callable, in Java, a parameter, to the position that carries it.

The same resolution the dataflow accessors perform on their src, exposed so a caller can check what a name means before asking a question of it::

java.resolve_value("orderID", within="TradeDirect.cancelOrder").kind # "parameter"

Raises:

  • AmbiguousName: within named more than one callable, or name more than one value.
  • SelectorNotInGraph: No such callable, or no such value in it.
get_source(node_id: str) -> str

Return the source text named by node_id, a callable, or one of its body nodes.

node_id is a callable’s "<type fqn>.<signature>" name (what resolve_callable returns in callable), a callable’s opaque id (what it returns in ref), or the body-node id node_id hands back, so a statement or call site locate found can be re-fetched precisely. Passed back as received, never composed.

What comes back for a callable depends on the backend, and it is the graph’s difference, not this method’s. On the analysis.json backend it is the body block; over Neo4j it is the whole declaration, which ends with that body block: the projection carries one line range per callable and no body_span (upstream codeanalyzer-java#176). The relation is exact and total, so a caller reading either can rely on it; it is recorded in the lossiness table of docs/agent-api-reference.md and asserted by the live parity suite. A body node likewise has text only on the analysis.json backend: the graph carries none below callable granularity.

Parameters:

NameTypeDescription
node_idstrA callable’s name or id, or an id from locate, passed back as received, not composed.

Returns:

  • str: The source text, never an ambiguous empty string.

Raises:

  • KeyError: Nothing matches node_id, or it names a node with no recoverable source, an implicit callable (the analyzer emits it with no span and no body), or, over Neo4j, a body node. The message names the reason.
describe(nodes: Sequence[object]) -> List[SliceNode]

Fill in source for these positions, in one round trip.

Addressing answers where; this answers what, and it is a second call because source is the one field with no size ceiling. Takes anything carrying an address, slice nodes, a locate() result, and gives back the same SliceNode shape with source filled.

Afterwards, source=None means exactly one thing: this position exists and there is no text for it. A ref that names nothing raises instead.

Parameters:

NameTypeDescription
nodesSequence[object]The positions to hydrate. An empty sequence costs no round trip.

Returns:

  • List[SliceNode]: The same positions, in the same order, with source filled where the backend has
  • List[SliceNode]: text for them.

Raises:

  • KeyError: A ref names nothing in this application.
  • TypeError: An element carries no address to look up.
get_cfg(callable: str, in_class: str | None = None, page_size: int = DEFAULT_PAGE_SIZE, cursor: str | None = None) -> EdgePage[JCfgEdge]

Return one page of the control flow edges within one callable.

The intraprocedural half of “how does this method run”: the analyzer’s own CFG, one edge per successor, with the branch kind on the edge rather than implied by order. Endpoints are body-node ids get_source accepts, so a statement on a path can be read back.

Parameters:

NameTypeDescription
callablestrThe callable’s name, resolved as in resolve_callable.
in_classstr | NoneDisambiguate by owning class.
page_sizeintMost edges to return.
cursorstr | Nonenext_cursor from a previous page.

Returns:

  • EdgePage[JCfgEdge]: class:~cldk.analysis.commons.results.EdgePage of
  • EdgePage[JCfgEdge]: class:~cldk.models.java.models.JCfgEdge, whose complete says whether the page is
  • EdgePage[JCfgEdge]: the whole graph and whose total says how large that is.

Raises:

  • AmbiguousName: callable named more than one callable.
  • SelectorNotInGraph: Nothing matched.
  • ValueError: page_size below 1, or a cursor from another page.
  • CodeanalyzerUsageException: callable is an implicit callable, it resolves (J-6) and the analyzer emits it with no body, so there is no flow to page, or the analysis was built below analysis_level="program_dependency_graph".
get_cdg(callable: str, in_class: str | None = None, page_size: int = DEFAULT_PAGE_SIZE, cursor: str | None = None) -> EdgePage[JCdgEdge]

Return one page of the control dependence edges within one callable.

src is the branching node dst is control dependent on, the analyzer’s post-dominance over the CFG, not re-derived here. Arguments and failures are get_cfg’s.

get_ddg(callable: str, in_class: str | None = None, page_size: int = DEFAULT_PAGE_SIZE, cursor: str | None = None) -> EdgePage[JDdgEdge]

Return one page of the data dependence edges within one callable.

Each edge names the variable it flows (var) and the evidence for it (prov), which in Java is one of two tiers: ssa (324,959 edges on the reference graph) or points-to (1,134). prov_rank ranks points-to least certain, which is what a caller weighing two hops reads. Arguments and failures are get_cfg’s.

slice_backward(src: str, within: str, depth: int | None = DEFAULT_DEPTH, max_nodes: int = DEFAULT_MAX_NODES) -> Slice

Return everything the value src depends on.

On an analysis whose port lattice carries no dependence edge, codeanalyzer-java before 3.0.3, or --l3-engine wala, that is the seed plus the argument vertex at every call site that passes a value into the parameter, and nothing behind those arguments. It is still a real answer that varies with the program, which is why this one answers where slice_forward refuses. From 3.0.3 the walk carries on into the statements that computed those arguments.

Parameters:

NameTypeDescription
srcstrThe value’s name, in Java, a parameter of within.
withinstrThe callable to look inside. Required: a value name is scoped by its callable.
depthint | NoneMost hops from the seed; None for the whole cone.
max_nodesintMost nodes to return. A cap that fires is reported, never silent.

Returns:

  • Slice: class:~cldk.analysis.commons.results.Slice containing the seed, ordered by node id.

Raises:

  • AmbiguousName: within or src matched more than one thing.
  • SelectorNotInGraph: Either matched nothing.
  • ValueError: depth is not a positive int, or max_nodes is below 1.
slice_forward(src: str, within: str, depth: int | None = DEFAULT_DEPTH, max_nodes: int = DEFAULT_MAX_NODES) -> Slice

Return everything the value src can affect.

Java cannot answer this today and says so. A parameter vertex has no outgoing dependence edge in codeanalyzer-java’s output, so the result would be the seed alone for every parameter of every application, indistinguishable from “this parameter affects nothing”. Arguments and names are judged first; then it raises naming the gap.

Raises:

  • CodeanalyzerExecutionException: The analyzer’s port lattice carries no dependence edge.
backward_cone(sinks: Sequence[str], depth: int | None = DEFAULT_DEPTH, max_nodes: int = DEFAULT_MAX_NODES) -> Slice

Return every callable that can reach any of sinks, “what could get here”.

A call-graph cone, so its vertices are callables; the sinks are in the result and in roots. Bounded by default, because an unbounded cone on a real application is a truncated answer to a question nobody asked; depth=None asks for the whole thing and total says how much a cap left out.

Parameters:

NameTypeDescription
sinksSequence[str]The callables to walk back from, each resolved as in resolve_callable.
depthint | NoneMost call hops back; None for the whole cone.
max_nodesintMost nodes to return.

Raises:

  • AmbiguousName: A sink matched more than one callable.
  • SelectorNotInGraph: A sink matched none.
  • TypeError: sinks is a bare string.
  • ValueError: sinks is empty, or a bound is out of range.
reaches(src: str, dst: str, depth: int | None = None) -> bool

Return whether there is a call path from src to dst.

The cheap check before asking for the paths themselves. Unbounded by default, unlike the slices: a hop budget on a boolean would make “there is no path” and “there is no path within five hops” the same False.

Raises:

  • AmbiguousName: Either name matched more than one callable.
  • SelectorNotInGraph: Either matched none.
  • ValueError: depth is not a positive int.
callers_of(name: str, in_class: str | None = None, in_module: str | None = None) -> List[SliceNode]

Return the callables that call this one, one hop back, addressed by name.

The name-based sibling of get_callers, which takes a class name plus a method signature and returns raw dicts; that one is a frozen 1.x signature and is unchanged. [] is unambiguous, a name matching nothing raises.

Raises:

  • AmbiguousName: name matched more than one callable.
  • SelectorNotInGraph: Nothing matched.
callees_of(name: str, in_class: str | None = None, in_module: str | None = None) -> List[SliceNode]

Return the callables this one calls, one hop forward, addressed by name.

Java’s call graph has no external vertices on either backend (J-1), so unlike Python’s and TypeScript’s this never reports a kind="external" node; get_external_symbols is where call targets outside the project live.

Raises:

  • AmbiguousName: name matched more than one callable.
  • SelectorNotInGraph: Nothing matched.
paths_between(src: str, dst: str, src_within: str, dst_within: str, depth: int | None = None, max_paths: int = DEFAULT_MAX_PATHS) -> FlowPaths

Return how the value src reaches the value dst, the sequences, where a slice is the set.

Two scopes, not one, and neither defaults to the other: a value is addressed by a name plus the callable it enters, and a single scope could never find the cross-callable path this exists for.

Java cannot answer this today and says so: see slice_forward. Arguments and names are judged first.

Raises:

  • AmbiguousName / SelectorNotInGraph: A name matched more than one thing, or nothing.
  • ValueError: A bound is out of range, or the two endpoints are the same position.
  • CodeanalyzerExecutionException: The analyzer’s port lattice carries no dependence edge.
call_paths_between(src: str, dst: str, depth: int | None = None, max_paths: int = DEFAULT_MAX_PATHS) -> FlowPaths

Return how one callable reaches another, the evidence-carrying form of reaches.

Every hop is via="call" with no var and no prov: a call edge carries neither, and saying so is better than inventing a provenance. Only shortest paths, ordered so that max_paths truncates a prefix of one total order rather than an arbitrary subset.

Raises:

  • AmbiguousName / SelectorNotInGraph: A name matched more than one callable, or none.
  • ValueError: A bound is out of range, or src and dst name the same callable.
flows_to_call(src: str, callee: str, within: str, depth: int | None = None) -> bool

Return whether the value src reaches any argument of a call to callee.

Java cannot answer this today and says so: see slice_forward.

Raises:

  • AmbiguousName / SelectorNotInGraph: A name matched more than one thing, or nothing.
  • ValueError: depth is not a positive int.
  • CodeanalyzerExecutionException: The analyzer’s port lattice carries no dependence edge.
flows_to_argument(src: str, callee: str, arg: str, within: str, depth: int | None = None) -> bool

Return whether the value src reaches callee’s parameter arg.

A different question from flows_to_call: a tainted value routinely reaches a method without reaching the parameter that matters. arg is named, never numbered.

Java cannot answer this today and says so: see slice_forward.

Raises:

  • AmbiguousName / SelectorNotInGraph: A name matched more than one thing, or nothing, including arg naming no parameter of callee, which is a caller error and not a False.
  • ValueError: depth is not a positive int.
  • CodeanalyzerExecutionException: The analyzer’s port lattice carries no dependence edge.
taint(sources: Sequence[Tuple[str, str]], sinks: Sequence[Tuple[str, str]], sanitizers: Sequence[Tuple[str, str] | str] = (), depth: int | None = None, max_paths: int = DEFAULT_MAX_PATHS) -> TaintResult

Which of these sources reach which of these sinks, and what to make of the ones that do not.

m sources against n sinks in one traversal, where paths_between proves one flow::

r = java.taint(
sources=[("userID", "TradeAppServlet.doPost")],
sinks=[("sql", "TradeDirect.getOrders")],
sanitizers=["TradeAppServlet.escapeUserID", ("checked", "TradeAppServlet.doPost")],
)
for path in r.paths:
print(" -> ".join(h.to.name for h in path.hops))
for src, sink in r.exhausted:
print(src, "does not reach", sink)

exhausted is the reason to call this and the only output that can do harm. A pair is listed there when it was searched to exhaustion and nothing was found, the refutation paths_between’s [] cannot give, and only when all three hold: no witness, no diagnostic in unresolved implicating it, and depth was None. An explicit depth empties exhausted by rule, because a bound turns a real long flow into an empty result and a wrong refutation closes a live alert.

complete is the batch’s flag, not the pair’s. While it is False, no absence claim stands on any pair in the result: one blocked pair voids the whole batch’s exhausted.

Sources, sinks and sanitizers are the caller’s to supply: no framework catalogue ships here. A bare str cuts a callable on the path (a transforming sanitizer, resolved with resolve_callable and so named as a callable this application declares); a (name, within) pair cuts a variable inside that callable, which is the only thing that severs a validating guard, since a guard never sits on the data path. Both cuts are applied inside the search, so the result is the shortest unsanitized route.

Java refuses this on a disconnected port lattice, exactly as slice_forward, paths_between, flows_to_call and flows_to_argument do (codeanalyzer-java#227). The gate is asked of the data, whether this application’s formal_in vertices carry any outgoing SDG edge, and never of the analyzer’s version, so output that connects the two layers makes this answer with no change here. Names and bounds are judged first, so a typo is reported as a typo.

Parameters:

NameTypeDescription
sourcesSequence[Tuple[str, str]]The values taint enters at, each (name, within).
sinksSequence[Tuple[str, str]]The values it must not reach, addressed the same way.
sanitizersSequence[Tuple[str, str] | str]Bare names cut callables; (name, within) pairs cut variables.
depthint | NoneMost hops; None (the default) for no bound, and exhausted is empty whenever it is set.
max_pathsintMost witnesses per pair, not per call.

Raises:

  • AmbiguousName / SelectorNotInGraph: A name, or a sanitizer’s within, matched more than one thing or nothing, including a sanitizer whose shape disagrees with what it resolves to.
  • TypeError: sources or sinks is a bare string, which would unpack into a pair.
  • ValueError: A bound is out of range, sources or sinks is empty, or a sanitizer names a blank variable.
  • CodeanalyzerExecutionException: The analyzer’s port lattice carries no dependence edge.
  • CodeanalyzerUsageException: This analysis was built below analysis_level="system_dependency_graph".
get_callables_overview() -> List[JCallableOverview]

Return a lightweight overview of every callable in the project, in one bulk read.

A field-projected alternative to get_methods for enumeration: each JCallableOverview carries the callable’s addressable key, declaring type, kind, location, modifiers and annotation names, but not the full reconstruction (body nodes, call sites, local classes). Body-inspect the few you need afterwards via get_method or get_method_bodies.

Returns:

  • List[JCallableOverview]: A flat list, one entry per callable the analyzer emitted, initializers, implicit
  • List[JCallableOverview]: constructors and the callables of local and anonymous classes included (J-6).

See Also get_decorated_callables: The same projection filtered by annotation. get_method_bodies: Bulk source fetch for chosen keys.

get_method_bodies(signatures: List[str]) -> Dict[str, str]

Return source text for the given callables, in one bulk read.

Parameters:

NameTypeDescription
signaturesList[str]The keys get_callables_overview hands back (JCallableOverview.key, the J-1 "<type fqn>.<signature>" name), matched exactly. A bare Java signature is unique only within its declaring type, so it is not an address here.

Returns:

  • Dict[str, str]: A dict mapping each key to its source text. Keys with no matching callable are omitted,
  • Dict[str, str]: as are callables with no source text of their own, the implicit constructors, and only
  • Dict[str, str]: those (1,117 of daytrader8’s 1,216). The <clinit>$N() initializers carry a body
  • Dict[str, str]: block and do come back. Every value is a real, non-empty str.

Note The text differs by backend exactly as get_source does: the body block off analysis.json, the whole declaration off the Neo4j projection (codeanalyzer-java#176).

get_decorated_callables(markers: List[str]) -> List[JCallableOverview]

Return overviews of callables annotated with any of the given markers, in one bulk read.

Parameters:

NameTypeDescription
markersList[str]Annotation names. Each matches by simple name (Test), with a leading @ ignored (@Test), or by fully-qualified name (org.junit.Test), J-5. Nothing is matched fuzzily (E8).

Returns:

  • List[JCallableOverview]: A list of JCallableOverview, one per matching
  • List[JCallableOverview]: callable.

See Also get_callables_overview: The unfiltered projection.

get_entrypoints() -> List[JCallableOverview]

Return overviews of every callable the analyzer marked as an entrypoint, in one bulk read.

codeanalyzer-java’s own detection pass already finds servlet methods, JAX-RS resource methods, MDB listeners and the rest; this surfaces that mark instead of making a caller rediscover it. 133 of daytrader8’s 1,216 callables carry it.

Returns:

  • List[JCallableOverview]: A list of JCallableOverview. Empty means the pass
  • List[JCallableOverview]: found no entrypoint callables, the mark itself is never missing, on either backend.

See Also get_entrypoint_classes: The type-level sibling this walk never sees. get_entrypoint_coverage: Whether the pass itself had gaps, which Java, alone of the three languages, cannot say.

get_entrypoint_classes() -> List[JClassOverview]

Return overviews of every type the analyzer marked as an entrypoint in its own right.

get_entrypoints walks callables only, so a type marked at the declaration with no individually-marked method is invisible to it. This is that sibling, the projected form of get_entry_point_classes, which keeps its 1.x Dict[str, JType] shape.

get_entrypoint_coverage() -> EntrypointCoverage

Report the entrypoint pass’s coverage, which for Java is that there is no report.

codeanalyzer-java 3.0.1 emits the entrypoint marks and nothing about the pass that made them: analysis.json has no report key and the :JApplication anchor carries only name/schema_version/analyzer_name/analyzer_version. So this returns an EntrypointCoverage whose diagnostics carry entrypoint_report_unavailable and whose other fields are therefore not coverage information, the same “say so honestly” shape as diagnostics’s module_source_unavailable, and identical on both backends (J-4).

It is deliberately not synthesised from the is_entrypoint booleans: a count of syntactically-marked callables is not a coverage record.

get_callsites_for(signatures: List[str]) -> Dict[str, List[JCallSite]]

Return the call sites of the given callables, keyed by the key that named them.

Avoids the per-callable reconstruction fan-out when call sites are wanted for a specific frontier.

Parameters:

NameTypeDescription
signaturesList[str]The keys get_callables_overview hands back, matched exactly.

Returns:

  • Dict[str, List[JCallSite]]: A dict mapping each existing key to its list of
  • Dict[str, List[JCallSite]]: class:~cldk.models.java.models.JCallSite (empty when the callable makes no calls);
  • Dict[str, List[JCallSite]]: keys with no matching callable are omitted.

See Also has_resolution_edges: Distinguishes a genuinely unresolved callee from a graph carrying no resolution at all.

get_external_symbols() -> Dict[str, JExternalSymbol]

Return every call-graph endpoint outside the analysed project, keyed by its @external id.

Returns:

  • Dict[str, JExternalSymbol]: The analyzer’s own external_symbols map. Empty means the run homed them and this
  • Dict[str, JExternalSymbol]: project’s call graph makes no calls outside itself.

Raises:

  • CodeanalyzerExecutionException: The run never homed them, which is a different fact. codeanalyzer-java emits external_symbols only under --external-calls, which --emit neo4j forces and a local -a run does not, so the Neo4j backend answers and the local one refuses rather than returning an empty dict that would read as “nothing outside”.
get_artifacts() -> Dict[str, PyArtifact]

Return every non-code project artifact (pom.xml, properties files, descriptors, …), keyed by repo-relative path.

This layer (Artifact/ConfigKey/Package nodes) is the one part of the graph every codeanalyzer-<lang> projects identically and unprefixed, so it is carried in the shared Py* models rather than in Java-specific ones. JArtifact.text_truncated has no home on the shared model; read it off JApplication.artifacts when it matters.

See Also get_dependencies, get_config_keys, get_config_uses.

get_dependencies(direct_only: bool = False, ecosystem: str | None = None, declared_in: str | None = None) -> List[PyDependency]

Return every declared dependency, one entry per declaring manifest, optionally filtered.

All three filters default to “don’t filter”. The Maven group coordinate has no home on the shared model; read it off JApplication.dependencies when name alone is ambiguous.

Parameters:

NameTypeDescription
direct_onlyboolWhen True, excludes lockfile-only transitive pins.
ecosystemstr | NoneWhen given, only dependencies from this package ecosystem ("maven").
declared_instr | NoneWhen given, only dependencies declared by this artifact id.
get_config_keys() -> Dict[str, PyConfigKey]

Return every configuration key flattened out of a config-bearing artifact, keyed "<artifact repo-relative path>@key/<dotted key>" (pom.xml@key/project.artifactId).

That is the analyzer’s own id with its can://<app>/artifact/ prefix dropped: the application name belongs to the run, not to the key, and can:// ids stay off the public surface (E6). The full id is still on PyConfigKey.id. Python and TypeScript key this by the raw id today; aligning the three is tracked as python-sdk#346 and is deliberately not done piecemeal here.

get_config_uses(key: str | None = None) -> List[PyConfigUseEdge]

Return resolved code-to-config edges: which body node reads which config key.

Always [] on codeanalyzer-java 3.0.1, which has no code-to-config detector (there is no config_uses on the Java wire), so there is nothing for key to filter.

Parameters:

NameTypeDescription
keystr | NoneWhen given, only edges whose target key has this bare key.

See Also get_config_readers: The same edges, resolved to their reading callables. get_unresolved_config_reads: The reads this cannot show.

get_unresolved_config_reads() -> List[PyConfigRead]

Return every detector-matched config read that never closed on exactly one declared key.

Always [] on codeanalyzer-java 3.0.1: there is no config-read detector, so there is nothing to have failed to resolve.

get_config_readers(key: str) -> List[JCallableOverview]

Return overviews of every callable reading configuration key key.

Always [] for the same reason get_config_uses is: with no code-to-config edges on the Java wire there is no edge to resolve to a reading callable.

Parameters:

NameTypeDescription
keystrThe bare configuration key, matched as get_config_uses matches it.
get_view_dispatches(view: str | None = None) -> List[JViewDispatch]

Return every resolved view dispatch: which body node hands the request to which view template (JSP, Facelet, Thymeleaf), a forward / include / sendRedirect call, a ModelAndView construction or setViewName, or a Spring controller’s return.

Parameters:

NameTypeDescription
viewstr | NoneWhen given, only edges whose view’s repo-relative path ends with it, segment-aligned (home.jsp or WEB-INF/jsp/home.jsp).

Raises:

  • CodeanalyzerExecutionException: The analysis predates codeanalyzer-java 3.3.0, which is where the pass exists; an older analysis is refused rather than answered [].

See Also get_view_dispatchers: The same edges, resolved to their dispatching callables. get_unresolved_view_dispatches: The dispatches this cannot show.

JavaAnalysis.get_unresolved_view_dispatches
Section titled “JavaAnalysis.get_unresolved_view_dispatches”
get_unresolved_view_dispatches() -> List[JViewDispatchUnresolved]

Return every detected dispatch that closed on no view, a variable target, a servlet URL, a view name matching two templates, with its reason and the tiers attempted.

Raises:

  • CodeanalyzerExecutionException: The analysis predates codeanalyzer-java 3.3.0; or, on the Neo4j backend, always, the record lives in analysis.json only.
get_view_dispatchers(path: str) -> List[JCallableOverview]

Return overviews of every callable that dispatches to the view at path.

Parameters:

NameTypeDescription
pathstrThe view’s repo-relative path or any segment-aligned suffix of it.

Raises:

  • CodeanalyzerExecutionException: As get_view_dispatches.
get_interfaces() -> Dict[str, JType]

Return every interface in the project, keyed by qualified name.

The kind-filtered siblings of get_classes, sharing TypeScript’s names for the same concepts (G3). Measured: 3 interfaces in daytrader8, 594 in ThingsBoard.

get_enums() -> Dict[str, JType]

Return every enum in the project, keyed by qualified name (192 in ThingsBoard; daytrader8 declares none).

get_enum_members(qualified_enum_name: str) -> List[JEnumConstant]

Return the constants declared by one enum.

Parameters:

NameTypeDescription
qualified_enum_namestrThe enum’s qualified name, as get_enums keys it.

Raises:

  • SelectorNotInGraph: The name is not an enum of this application, no type at all, or a type of another kind. An empty list means an enum that declares no constant, which is a different answer (D7).
get_records() -> Dict[str, JType]

Return every record in the project, keyed by qualified name, the one Java-only type kind (35 in ThingsBoard; daytrader8 declares none). Annotation types have no leaf accessor of their own and stay reachable through get_classes (J-7).

Java schema models, a pydantic mirror of codeanalyzer-java/src/main/java/com/ibm/cldk/schema at the 3.0.1 floor, schema v2 (the pin itself is [tool.backend-versions] in pyproject.toml).

The wire is one containment tree: JAnalysis{analyzer, application}JApplication{symbol_table{path → JCompilationUnit}, call_graph, param_in, param_out, artifacts, dependencies, config_uses, config_reads_unresolved, view_dispatches, view_dispatches_unresolved, entrypoint_report}JCompilationUnit{types{name → JType}}JType{fields{}, callables{signature → JCallable}, types{}}JCallable{body{}, cfg, cdg, ddg, summary, types{}}. Every node carries a can:// id and a kind; a unit carries its full source once and every node’s text is a slice of it. Gson omits null fields, so an absent key is a None/empty default here.

What the 1.x models exposed as stored fields is kept as properties where the wire still has the fact in another shape (J-8): code over span + source, call_sites over the call body nodes, thrown_exceptions over error_channel, cyclomatic_complexity over metrics, variable_declarations over local_variables, referenced_types/accessed_fields over refs, the is_* type predicates over kind and the owner chain. What the wire does not carry (CRUD) is an empty list, and the facade raises for it (J-4).

extra="ignore" since #386: an additive analyzer release is consumable without an SDK edit. What that gives up is the drift detector, an unmodelled field is dropped silently, so a field the SDK does not declare is unreachable rather than an error. The projections in projections.py keep extra="forbid", because they are constructed by this SDK and never validated from the wire, so there strictness guards our own typos rather than the analyzer’s additions.

class JSpan(_Base)

start/end are [line, column] (1-based); bytes are [from, to] UTF-8 byte offsets into the owning unit’s source (the analyzer’s Spans.java computes them as prefix sums over getBytes(UTF_8)).

-1 in any position means “not known”, never zero. A span rebuilt from the Neo4j projection carries real lines and real byte offsets — codeanalyzer-java 3.2.0 writes both — and -1 for both columns, which the graph does not write at all; a 0 there would read as column one, which is a position, and a wrong one. Off analysis.json every position is the analyzer’s own.

NameTypeDescription
startTuple[int, int]
endTuple[int, int]
bytesTuple[int, int]
class JComment(_Spanned)

A comment or Javadoc block.

NameTypeDescription
contentstr
is_javadocbool
class JImport(_Spanned)

An import declaration: name is the imported simple name, path the fully-qualified target.

NameTypeDescription
namestr
pathstr
is_staticbool
is_wildcardbool
class JDecorator(_Spanned)

An annotation use; args are the source spellings of its arguments (name="accountejb").

NameTypeDescription
namestr
argsList[str]
class JTypeParameter(_Spanned)
NameTypeDescription
namestr
boundsList[str]
decoratorsList[JDecorator]
class JEnumConstant(_Spanned)
NameTypeDescription
namestr
argumentsList[str]
commentsList[JComment]
decoratorsList[JDecorator]
class JRecordComponent(_Spanned)
NameTypeDescription
namestr
typestr
modifiersList[str]
decoratorsList[JDecorator]
commentsList[JComment]
is_variadicbool
annotationsList[str]
commentOptional[JComment]
is_var_argsbool
class JCallableParameter(_Spanned)
NameTypeDescription
nameOptional[str]
typestr
modifiersList[str]
decoratorsList[JDecorator]
is_variadicbool
annotationsList[str]
class JLocalVariable(_Spanned)

A local variable declaration inside a callable (the 1.x JVariableDeclaration).

NameTypeDescription
namestr
typestr
initializerOptional[str]
commentsList[JComment]
commentOptional[JComment]
class JField(_Node)
NameTypeDescription
kindLiteral['field']
namestr
typestr
modifiersList[str]
commentsList[JComment]
decoratorsList[JDecorator]
initializerOptional[str]
annotationsList[str]
variablesList[str]
variable_initializersOptional[Dict[str, str]]
commentOptional[JComment]
class JMetrics(_Base)
NameTypeDescription
cyclomaticint
class JRefs(_Base)
NameTypeDescription
typesList[str]
fieldsList[str]
class JBodyNode(_Spanned)

One entry of a callable’s body{} map, keyed L:C, @entry/@exit/@formal_in:N/ @formal_out or L:C/actual_in:N/L:C/actual_out. Every attribute is optional: the analyzer writes the empty call-shaped fields on non-call nodes too.

NameTypeDescription
kindstr
calleeOptional[str]
argumentsList[str]
receiver_exprOptional[str]
receiver_typeOptional[str]
argument_typesList[str]
argument_exprList[str]
callee_signatureOptional[str]
method_nameOptional[str]
return_typeOptional[str]
accessibilityOptional[str]
commentOptional[JComment]
is_static_callOptional[bool]
is_constructor_callbool
ofOptional[str]
parentOptional[str]
class JCfgEdge(_Base)
NameTypeDescription
srcstr
dststr
kindstr
class JCdgEdge(_Base)
NameTypeDescription
srcstr
dststr
class JDdgEdge(_Base)
NameTypeDescription
srcstr
dststr
varOptional[str]
provList[str]
class JSummaryEdge(_Base)
NameTypeDescription
srcstr
dststr
class JCRUDOperation(_Base)

Not emitted by codeanalyzer-java 3.0.1 (upstream #187); kept for import compatibility.

NameTypeDescription
line_numberint
operation_typeOptional[CRUDOperationType]
class JCRUDQuery(_Base)

Not emitted by codeanalyzer-java 3.0.1 (upstream #187); kept for import compatibility.

NameTypeDescription
line_numberint
query_argumentsOptional[List[str]]
query_typeOptional[CRUDQueryType]
class JCallSite(_Base)

The 1.x per-call record, built on demand from a call body node (from_body_node). The four visibility booleans derive from accessibility and are None when the callee was not resolved.

NameTypeDescription
commentOptional[JComment]
method_namestr
receiver_exprstr
receiver_typestr
argument_typesList[str]
argument_exprList[str]
return_typestr
callee_signaturestr
is_static_callOptional[bool]
is_privateOptional[bool]
is_publicOptional[bool]
is_protectedOptional[bool]
is_unspecifiedOptional[bool]
is_constructor_callbool
crud_operationOptional[JCRUDOperation]
crud_queryOptional[JCRUDQuery]
start_lineint
start_columnint
end_lineint
end_columnint
from_body_node(node: JBodyNode) -> 'JCallSite'
class JCallable(_Node)

A method, constructor or initializer (<clinit>$N()). Implicit callables (default constructors) carry no span, body, parameters, metrics or declaration.

cfg/cdg/ddg are present from L3 and summary from L4 off analysis.json, where None means the run was below that level and re-running higher fills them in. Off the Neo4j projection all four are None at every level, and re-ingesting does not change that: --emit neo4j already forces L4, and this leg’s projection does not rebuild the per-callable graphs from it (leg 3b reads them on demand). So None here is “this backend does not carry it”, not “analyse deeper”.

NameTypeDescription
kindstr
signaturestr
parametersList[JCallableParameter]
return_typeOptional[str]
error_channelList[str]
modifiersList[str]
decoratorsList[JDecorator]
type_parametersList[JTypeParameter]
body_spanOptional[JSpan]
declarationOptional[str]
is_implicitbool
commentsList[JComment]
is_entrypointbool
entrypoint_frameworksList[str]
metricsOptional[JMetrics]
refsOptional[JRefs]
local_variablesList[JLocalVariable]
bodyDict[str, JBodyNode]
cfgOptional[List[JCfgEdge]]
cdgOptional[List[JCdgEdge]]
ddgOptional[List[JDdgEdge]]
summaryOptional[List[JSummaryEdge]]
typesDict[str, 'JType']
codestrThe 1.x code: the body block (body_span), which is what code_start_line
code_start_lineintThe file line :attr:code starts on: the body block’s first line, or the declaration’s
annotationsList[str]
thrown_exceptionsList[str]
cyclomatic_complexityOptional[int]
variable_declarationsList[JLocalVariable]
referenced_typesList[str]
accessed_fieldsList[str]
call_sitesList[JCallSite]
is_constructorbool
is_staticbool
crud_operationsList[JCRUDOperation]
crud_queriesList[JCRUDQuery]
class JType(_Node)

A class, interface, enum, annotation or record. The wire has no name: the map key is the simple name and the id’s last segment; name is stamped from the key (J-13).

NameTypeDescription
kindLiteral['class', 'interface', 'enum', 'annotation', 'record']
spanJSpan
commentsList[JComment]
modifiersList[str]
base_typesList[str]
interfacesList[str]
decoratorsList[JDecorator]
type_parametersList[JTypeParameter]
is_entrypoint_classbool
entrypoint_frameworksList[str]
enum_constantsList[JEnumConstant]
record_componentsList[JRecordComponent]
fieldsDict[str, JField]
callablesDict[str, JCallable]
typesDict[str, 'JType']
namestr
qualified_namestrpackage.Outer.Inner for a member type, the source spelling, nested types joined
is_interfacebool
is_nested_typebool
is_local_classbool
is_inner_classbool
is_class_or_interface_declarationbool
is_enum_declarationbool
is_annotation_declarationbool
is_record_declarationbool
is_concrete_classbool
extends_listList[str]
implements_listList[str]
annotationsList[str]
parent_typestrQualified name of the enclosing type, "" at top level (the 1.x value).
field_declarationsList[JField]
callable_declarationsDict[str, JCallable]
nested_type_declarationsList[str]Qualified names of the member types (the 1.x value; both backends feed them to get_class).
initialization_blocksList[JCallable]
class JCompilationUnit(_Node)

One .java file. The symbol-table key is its repo-relative path (file_path); the wire carries no file_path/package_name. The wire key imports holds structured JImport records, exposed as import_declarations; the 1.x imports (a list of paths) is the property of that name.

NameTypeDescription
model_config
kindLiteral['module']
spanJSpan
packagestr
sourcestr
commentsList[JComment]
import_declarationsList[JImport]
typesDict[str, JType]
content_hashOptional[str]
file_pathstr
package_namestr
importsList[str]
type_declarationsDict[str, JType]
is_modifiedboolAlways False: the analyzer emits a snapshot, never an edit state.
codestr
model_post_init(__context: Any) -> None
slice(span: JSpan) -> str

source between the span’s UTF-8 byte offsets (J-15); a plain index when the file is ASCII.

class JCallGraphEdge(_Base)

A wire call-graph edge: can:// endpoints, provenance tokens declared / rta.

NameTypeDescription
srcstr
dststr
provList[str]
weightint
class JParamEdge(_Base)

An L4 param_in/param_out edge with global endpoints (<callable id>@L:C/actual_in:N<callable id>@formal_in:N).

var names the bound formal, and it arrived in codeanalyzer-java 3.1.2 (codeanalyzer-java#250). Before that the schema declared the property and the projection wrote nothing, so a consumer predicate on it was null on every edge crossing a call boundary — which under Cypher’s three-valued logic drops the whole path and reads as a proved absence of flow. Optional rather than required because a graph or an analysis.json from 3.1.1 or earlier carries no such key, and both backends attach to artifacts they did not produce. TSParamEdge has carried the same field since its own analyzer added it.

NameTypeDescription
srcstr
dststr
varOptional[str]
class JExternalSymbol(_Base)

A call target outside the project, keyed by its @external/… id on the application. Declared in the analyzer’s schema; not emitted for daytrader8 at any level.

NameTypeDescription
kindstr
signaturestr
declaring_typeOptional[str]
class JConfigKey(_Base)
NameTypeDescription
idstr
keystr
namespacestr
valueOptional[str]
spanOptional[JSpan]
referencesList[str]
class JArtifact(_Base)

A recognized non-code file (config, manifest, build descriptor).

NameTypeDescription
idstr
kindLiteral['artifact']
pathstr
formatstr
rolesList[str]
size_bytesint
sha256str
sourcestr
text_truncatedbool
extractionstr
config_keysList[JConfigKey]
class JDependency(_Base)
NameTypeDescription
groupOptional[str]
namestr
ecosystemstr
specstr
kindstr
extrasList[str]
declared_instr
directbool
locked_versionOptional[str]
provList[str]
class JEntrypointReport(_Base)

Coverage and failure record for the entrypoint pass (codeanalyzer-java#235, 3.1.0).

The same four fields Python and TypeScript already carry (PyEntrypointReport / TSEntrypointReport), so EntrypointCoverage reads one shape across the three languages.

NameTypeDescription
frameworks_detectedList[str]
rulesetsList[str]
unresolvedDict[str, int]
errorsList[str]
class JConfigUse(_Base)

One code-to-config edge: a config read whose key closed on a declared JConfigKey.

src is the reading call’s body-node id (<callable id>@<line>:<col>), dst the matched key’s id. prov names the tier that resolved it and is the reason this is not flattened: ["literal"] is a string literal at the call site (codeanalyzer-java#233); "dataflow" means the key was reached over the L3 DDG / L4 call graph (codeanalyzer-java#237), weaker evidence, and monotone with the analysis level. Python’s PyConfigUseEdge verbatim.

NameTypeDescription
srcstr
dststr
provList[str]
class JConfigRead(_Base)

One config read whose key closed on no declared key, first class, so a read nobody can trace stays as visible as one that resolves.

key is the literal text when it was a literal that matches no declared key (reason="undefined-key") and None when it never closed on one (reason="non-literal"); prov lists every tier that was attempted before giving up, so ["literal", "dataflow"] means the dataflow tier ran too and still could not name the key. Python’s PyConfigRead verbatim.

NameTypeDescription
sitestr
calleestr
keyOptional[str]
reasonstr
provList[str]
class JViewDispatch(_Base)

One resolved view dispatch (codeanalyzer-java 3.3.0, spec 2026-09-11 § 4): the body node that hands the request to a view template and the JArtifact it reaches.

src is the dispatching body node’s id (<callable id>@<line>:<col>), a RequestDispatcher.forward / include or sendRedirect call, a ModelAndView construction or setViewName, or a Spring controller’s return; dst is the artifact’s can://<app>/artifact/<path> id. via names the mechanism (forward | include | redirect | view-name | navigation) and prov the tier that closed the target: ["literal"] is a string at the site, ["dataflow"] a local or parameter traced over the L3/L4 substrate, both mean exactly one target, and ["table"] (3.3.1, § 4.5) a lookup into a static string table, which is a may-dispatch: one edge per entry of the table, from the same site. Kept str rather than Literal on purpose, as reason is: navigation is reserved and unemitted today, and a closed type here would break on the analyzer release that fills it.

NameTypeDescription
srcstr
dststr
viastr
provList[str]
class JViewDispatchUnresolved(_Base)

A detected dispatch that closed on no artifact, first class, so a page nobody can trace stays as visible as one that resolves. target is the decoded literal when there was one and None for reason="non-literal"; reason is non-literal / no-such-artifact (a servlet URL, a *.faces route, a file outside the repository) / ambiguous (a view name matching two templates); prov lists every tier attempted. callee is the dispatching callee’s @external id for a call site and the enclosing callable’s id for a return site. JSON-only: the projection has no node for a target that resolved to nothing.

NameTypeDescription
sitestr
calleestr
targetOptional[str]
viastr
reasonstr
provList[str]
class JApplication(_Base)

The application root. call_graph/param_in/param_out are absent below the level that computes them, empty here, never None.

That reading is exact for call_graph on both backends. param_in/param_out are always empty off the Neo4j projection, at every level: --emit neo4j forces L4, so the dataflow overlay was computed, but this leg does not project the port lattice back out (leg 3b does). An empty pair there is this backend’s silence, not the analyzer’s.

NameTypeDescription
idstr
kindLiteral['application']
symbol_tableDict[str, JCompilationUnit]
call_graphList[JCallGraphEdge]
external_symbolsOptional[Dict[str, JExternalSymbol]]
param_inList[JParamEdge]
param_outList[JParamEdge]
artifactsDict[str, JArtifact]
dependenciesList[JDependency]
config_usesOptional[List[JConfigUse]]
config_reads_unresolvedOptional[List[JConfigRead]]
entrypoint_reportOptional[JEntrypointReport]
view_dispatchesOptional[List[JViewDispatch]]
view_dispatches_unresolvedOptional[List[JViewDispatchUnresolved]]
model_post_init(__context: Any) -> None
class JAnalyzer(_Base)
NameTypeDescription
namestr
versionstr
class JAnalysis(_Base)

The envelope analysis.json IS.

NameTypeDescription
schema_versionstr
languagestr
max_levelint
k_limitOptional[int]
analyzerJAnalyzer
applicationJApplication
class JMethodDetail(_Base)

The method_detail node attribute of get_call_graph(): built from the string node key (klass = everything before the signature’s simple name) and the resolved callable.

NameTypeDescription
method_declarationOptional[str]
klassstr
methodJCallable