Skip to content

Add a Rust frontend

StubHelp wanted

This page is a stub. A Rust frontend does not exist yet. This page describes the form that it will take and where to begin. If you want to build one, open an issue first to coordinate with the maintainers.

A frontend is an SDK that reads the canonical analysis JSON from the codeanalyzer backends. It gives you an analysis API over that JSON. The Python SDK is the reference implementation.

The backends do all the language analysis. A new frontend therefore supports every existing backend with no extra work. A Rust SDK can read Java, Python, and TypeScript analyses from the first day, and Go when that backend exists.

Rust suits this role: strong types for the schema, serde for fast deserialization, and petgraph for call-graph queries that match the networkx graphs of the Python SDK.

flowchart LR
    CA["codeanalyzer-* backends"] -->|canonical JSON| RS["Rust SDK (cldk-rs)"]
    RS --> M["serde models"]
    RS --> F["Analysis API"]
    RS --> G["petgraph call graph"]

Mirror the structure of the Python SDK, module by module. None of this work is done yet. Treat each step as a tracking item.

  1. Model the canonical schema with serde. Translate the backend JSON entities (JApplication, JType, JCallable, PyModule, PyClass, PyCallable) into Rust structs with #[derive(Deserialize)]. These structs are the Rust form of cldk/models/*. Start with one language, Java, to prove the round trip.

  2. Define the analysis trait. Write a LanguageAnalysis trait with the core methods (get_symbol_table, get_classes, get_method, get_call_graph, get_callers, get_callees). Every language implementation then shares one surface, the same as the Python analysis APIs.

  3. Build the call graph with petgraph. Deserialize the call-graph edges from the backend into a petgraph::DiGraph. Reachability is then petgraph::algo::has_path_connecting, the Rust form of networkx.has_path.

  4. Run the backends. Reuse the same CLI contract that the Python SDK uses to run codeanalyzer-* (input project directory, output JSON, analysis level). See the CLI interface of the backend. The wire format is shared, so this step is mostly process management and JSON parsing.

  5. Register languages with per-language factories. cldk/core.py gives one factory for each language: CLDK.java(...), CLDK.python(...), and CLDK.typescript(...). Each facade then selects its backend by the type of a backend= configuration object. CodeAnalyzerConfig selects the in-process codeanalyzer. Neo4jConnectionConfig selects the read-only graph.

    The Rust port must do the same. Write per-language constructors such as CLDK::java(project_path), and choose the backend by configuration type. An enum or a trait object works here. Each LanguageAnalysis implementation matches on Backend::CodeAnalyzer { cache_dir } or Backend::Neo4j { uri, .. }. (Python keeps a deprecated CLDK(language).analysis(...) shim that forwards to the factories. A Rust port does not need this shim.)

  6. Validate against the same fixtures. Run it against the Java fixtures of the Python SDK, DayTrader 8 and PlantsByWebSphere, in tests/resources/java/application/. Assert the same facts that the Python test suite asserts: same project, same results, different host language.