# How to Add Support for a Custom Programming Language in code-review-graph Using languages.toml

> Learn to add custom programming language support to code-review-graph by configuring languages.toml. Define grammar paths and file extensions in your repository root for seamless integration.

- Repository: [Tirth Kanani/code-review-graph](https://github.com/tirth8205/code-review-graph)
- Tags: how-to-guide
- Published: 2026-08-07

---

**To add support for a custom programming language in code-review-graph, create a [`.code-review-graph/languages.toml`](https://github.com/tirth8205/code-review-graph/blob/main/.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`](https://github.com/tirth8205/code-review-graph/blob/main/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:

```bash
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`](https://github.com/tirth8205/code-review-graph/blob/main/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.

```python
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:

```toml
[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:

```toml
[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`](https://github.com/tirth8205/code-review-graph/blob/main/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:

```python
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 in [`code_review_graph/custom_languages.py`](https://github.com/tirth8205/code-review-graph/blob/main/code_review_graph/custom_languages.py) automatically 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.py`](https://github.com/tirth8205/code-review-graph/blob/main/tests/test_custom_languages.py) for 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`](https://github.com/tirth8205/code-review-graph/blob/main/.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`](https://github.com/tirth8205/code-review-graph/blob/main/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.