How code-review-graph Resolves Cross-Language Dependencies and Imports

The code-review-graph system resolves cross-language dependencies by normalizing import statements through language-specific tokenization and querying a SQLite-backed graph database to match symbols across language boundaries.

The open-source tool code-review-graph (available at tirth8205/code-review-graph) constructs a unified dependency graph across heterogeneous codebases. Understanding how it handles cross-language dependencies and imports requires examining the scoped resolution engine that maps imports from one language to concrete symbols in another while maintaining strict language boundaries.

Language-Agnostic Import Resolution

The core resolution logic lives in code_review_graph/scoped_resolver.py. This module implements a multi-phase pipeline that transforms raw import statements into resolvable graph queries.

Token Normalization with _fold

The resolver first splits import targets into path segments using language-specific separators. The _fold helper function normalizes tokens by applying case-folding rules appropriate to each language—lower-casing segments for case-insensitive languages like PHP while preserving case for Rust or C#. Normalization uses separators such as . (Python), \ (PHP), and / (JavaScript/TypeScript) to break import paths into comparable token sequences.

Safe Suffix Validation

Before querying the database, the resolver validates imports against _safe_import_suffixes to eliminate ambiguous partial matches. Each language maintains distinct rules: Rust requires at least two path segments, PHP treats the entire path case-insensitively, and C# follows namespace conventions. This whitelist ensures that import foo in Python does not spuriously match a Rust module named foo when insufficient context exists.

SQLite Graph Queries

The resolver loads language metadata by executing SELECT DISTINCT file_path, language FROM nodes against the SQLite graph database. It constructs a method map keyed by the tuple (language, class_key, method_key), then queries the nodes table for candidates where qualified_name and language match the normalized import tokens.

Cross-Language Matching Strategy

Cross-language resolution relies on composite keys that include the source language identifier. Because the method map is keyed by language, a PHP class named User never resolves to a Rust type named User. The resolver performs final candidate filtering by comparing folded token sequences:

_fold(left, language) == _fold(right, language)

When multiple candidates survive filtering, the resolver applies a language-matching preference hierarchy, selecting the candidate whose file language matches the import statement's source language before falling back to best-effort suffix matching.

Key Source Files and Architecture

File Purpose
code_review_graph/scoped_resolver.py Core resolution engine implementing _fold, suffix validation, and database lookups.
code_review_graph/parser.py Populates the graph with IMPORTS_FROM edges using tree-sitter parsers.
code_review_graph/graph.py Wraps the SQLite database, exposing the nodes table and edge creation methods.
code_review_graph/python_resolver.py Supplies Python-specific import resolution hints to the scoped resolver.
code_review_graph/tsconfig_resolver.py Handles TypeScript path aliasing by parsing tsconfig.json mappings.

Practical Resolution Examples

The following example demonstrates parsing a mixed-language project and querying cross-language import edges:

from code_review_graph.parser import CodeParser
from code_review_graph.graph import GraphStore

# Initialize the parser and graph store

parser = CodeParser()
graph = GraphStore()

# Parse a directory containing Python, JavaScript, and PHP files

parser.parse_path("/path/to/project", graph)

# Retrieve cross-language import edges from a Python file

python_file = "/path/to/project/app/main.py"
imports = graph.edges_from(python_file, kind="IMPORTS_FROM")

for edge in imports:
    print(f"{edge.source} -> {edge.target} ({edge.language})")

Alternatively, invoke the resolution pipeline via CLI:

python -m code_review_graph.main /path/to/project --resolve-imports

Summary

  • Normalization pipeline: The _fold function in scoped_resolver.py tokenizes imports using language-specific separators and case rules.
  • Language isolation: Composite keys (language, class_key, method_key) prevent cross-language symbol collision.
  • Database integration: Resolution queries the SQLite nodes table for qualified_name and language matches.
  • Multi-language support: Specialized resolvers for Python, TypeScript, PHP, Rust, and C# feed language-specific rules into the generic engine.

Frequently Asked Questions

How does code-review-graph prevent false matches between languages with similar naming conventions?

The system isolates symbols by including the source language as a primary key component in the method map. When comparing candidates, the resolver executes _fold(left, language) == _fold(right, language), ensuring that case-folding and tokenization rules apply within a single language context, preventing a PHP class from resolving to a Rust struct of the same name.

Which database table stores the language metadata for import resolution?

The nodes table stores language metadata in the language column alongside file_path and qualified_name. The resolver queries this table with SELECT DISTINCT file_path, language FROM nodes to build the initial language index before resolving import paths.

What languages receive special handling in the safe suffix validation logic?

Rust, C#, and PHP receive explicit handling in the _safe_import_suffixes logic. Rust imports must contain at least two segments, PHP paths undergo case-insensitive normalization, and C# follows namespace-specific validation rules to ensure valid cross-references.

Can the resolver handle TypeScript path aliases defined in tsconfig.json?

Yes. The code_review_graph/tsconfig_resolver.py module parses tsconfig.json files to extract path mappings and base URL configurations. These mappings feed into the scoped resolver, allowing imports like import { foo } from '@/utils' to resolve correctly to their physical file locations across language boundaries.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →