How to Add Support for a Custom Programming Language in code-review-graph Using languages.toml
To add support for a custom programming language in code-review-graph, create a .code-review-graph/languages.toml file in your repository root and define language specifications under the [languages.<name>] table with required fields for grammar paths and file extensions.
The code-review-graph engine supports user-defined language definitions without requiring modifications to the core source code. By placing a languages.toml configuration file in the hidden .code-review-graph/ directory, you can extend the analyzer to recognize new file types, parse them with custom grammars, and integrate them into the call-graph construction process. This approach leverages the load_custom_languages() function in code_review_graph/custom_languages.py to dynamically inject language support at runtime.
Understanding the languages.toml Configuration Schema
The configuration file follows a strict TOML schema that the engine validates on load. Each language definition resides under a table keyed as [languages.<name>] where <name> identifies your custom language.
Required Fields for Language Definition
Every language entry must specify two critical parameters:
- grammar: A filesystem path (relative to the repository root) pointing to a compiled Tree-sitter grammar WASM file or custom parser module capable of parsing the language syntax.
- extensions: An array of file extension strings (excluding the leading dot) that the engine should associate with this language.
Optional Fields for Advanced Customization
You can fine-tune language detection and symbol resolution using optional fields:
- aliases: Alternative identifiers that may appear in import statements or cross-language references.
- probe_fields: A list of attribute names used by the heuristic parser to identify callables when static analysis encounters dynamic patterns.
Creating the Configuration File
First, create the hidden configuration directory at your repository root, then write the TOML definitions:
mkdir -p .code-review-graph
cat > .code-review-graph/languages.toml <<'EOF'
[languages.foolang]
grammar = "grammars/foolang/tree-sitter-foolang.wasm"
extensions = ["foo", "fool"]
aliases = ["fl"]
probe_fields = ["module", "handler"]
[languages.mydsl]
grammar = "grammars/mydsl/tree-sitter-mydsl.wasm"
extensions = ["mydsl", "mdl"]
EOF
The engine automatically discovers this file when you run the analysis from the repository root.
Loading and Validating Custom Languages
The load_custom_languages() function in code_review_graph/custom_languages.py handles the discovery, parsing, and validation of your configuration. This function expects a Path object pointing to the repository root and returns a dictionary mapping language names to configuration objects.
from pathlib import Path
from code_review_graph.custom_languages import load_custom_languages
repo_root = Path(".")
custom_langs = load_custom_languages(repo_root)
for name, config in custom_langs.items():
print(f"Loaded {name}: grammar={config.grammar}, extensions={config.extensions}")
If your languages.toml contains missing required keys, malformed paths, or duplicate language names, the validator raises a clear error immediately, preventing the analysis from proceeding with an inconsistent setup.
Practical Implementation Examples
Adding a Fictional Language (FooLang)
Consider extending the analyzer to support FooLang, a hypothetical scripting language. You would compile the Tree-sitter grammar to WASM, place it at grammars/foolang/tree-sitter-foolang.wasm, and define:
[languages.foolang]
grammar = "grammars/foolang/tree-sitter-foolang.wasm"
extensions = ["foo", "fool"]
aliases = ["fl"]
probe_fields = ["module", "handler"]
When the engine encounters files ending in .foo or .fool, it routes them through your custom grammar and recognizes fl as a valid alias in import resolution.
Integrating a Domain-Specific Language (MyDSL)
For a domain-specific language used in microservices, configure probe_fields to help the engine identify service endpoints:
[languages.mydsl]
grammar = "grammars/mydsl/tree-sitter-mydsl.wasm"
extensions = ["mydsl", "mdl"]
aliases = ["mydsl_lang"]
probe_fields = ["service", "endpoint"]
This configuration ensures that calls to service and endpoint attributes are correctly mapped in the final call graph, even when the underlying grammar uses dynamic dispatch patterns.
Testing Your Custom Language Configuration
The tests/test_custom_languages.py file contains the official test suite demonstrating how the loader behaves under various conditions. You should verify your configuration using similar patterns:
def test_custom_language_loaded(tmp_path):
# Arrange: Create the configuration directory and file
config_dir = tmp_path / ".code-review-graph"
config_dir.mkdir()
config_file = config_dir / "languages.toml"
config_file.write_text(
"[languages.testlang]\n"
'grammar = "grammars/testlang/tree-sitter-testlang.wasm"\n'
'extensions = ["tl"]\n'
)
# Act: Load the configuration
from code_review_graph.custom_languages import load_custom_languages
langs = load_custom_languages(tmp_path)
# Assert: Verify the language was parsed correctly
assert "testlang" in langs
assert langs["testlang"].extensions == ["tl"]
assert langs["testlang"].grammar == "grammars/testlang/tree-sitter-testlang.wasm"
This test pattern validates that your languages.toml syntax is correct and that the load_custom_languages() function properly ingests your definitions before the full analysis begins.
Summary
- Place a languages.toml file inside the
.code-review-graph/directory at your repository root to enable custom language support. - Define each language under a
[languages.<name>]table with mandatory grammar and extensions fields. - Use optional aliases and probe_fields to refine cross-language reference resolution and heuristic symbol detection.
- The
load_custom_languages()function incode_review_graph/custom_languages.pyautomatically loads and validates these configurations at runtime. - Validation errors in the TOML file prevent analysis from running, ensuring consistent parsing behavior.
- Reference
tests/test_custom_languages.pyfor implementation patterns when testing your custom configurations.
Frequently Asked Questions
Where should I place the languages.toml file?
You must create the file at .code-review-graph/languages.toml relative to your repository root. The load_custom_languages() function specifically searches for this path when initializing the analysis pipeline. If the file is missing or located elsewhere, the engine proceeds with only the built-in language definitions.
What file format does the grammar field expect?
The grammar field expects a path to a compiled Tree-sitter grammar in WASM format or a Python module path that implements the parser interface. The path is relative to the repository root, allowing you to version control custom grammars alongside your source code. The engine loads this grammar to parse files matching your specified extensions.
How does code-review-graph validate custom language configurations?
The validation occurs inside code_review_graph/custom_languages.py during the loading phase. The parser checks for required keys (grammar and extensions), verifies that extension strings do not contain leading dots, ensures grammar paths are syntactically valid, and prevents duplicate language names. Any violation raises a ConfigurationError with a descriptive message before the analysis engine starts processing source files.
Can I define multiple custom languages in a single file?
Yes, you can define any number of languages by creating multiple [languages.<name>] tables within the same languages.toml file. Each table operates independently, allowing you to add support for several domain-specific languages or experimental grammars simultaneously. Ensure each language name is unique to avoid validation errors during the loading process.
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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →