Skip to main content

Language Support

Differens parses code with tree-sitter and diffs the resulting trees. Any language with a tree-sitter grammar gets structural diffing. The real question is how much semantics a language gets: Differens either recognizes a node as a Function or a Class, or it just sees a tree-sitter node type like function_item.

Two levels of support

Semantic extractors (T5, L6). Four languages ship a per-language extractor: TypeScript/JavaScript, Python, Rust, and Go. An extractor maps tree-sitter node types to canonical concepts like Function, Class, Method, Import, Export, Variable, Type, Enum, Struct, and Trait, then pulls the declaration name out of the tree. With an extractor, a rename is a rename and a move is a move. Narration can say “renamed computeTotal to calculateTotalAmount”. Generic structural diff (T5, L5). Every other language with a tree-sitter grammar still gets structural diffing. The CST is parsed into a tree and matched structurally, but nodes keep their raw tree-sitter type names instead of canonical concepts, and labels come from the generic name-field rule. Reformatting and restructure are caught. Semantic narration is not.

Languages with full extractors

Anything tree-sitter has a grammar for falls back to the generic structural level (T5, L5). No extractor needed. If no grammar is registered at all, the file falls down the tier ladder to a line diff.

The LanguageExtractor interface

An extractor is a few dozen match arms, not a parser:
The tree-sitter cursor walk reads the name field directly for every node. extractLabel only runs for the types listed in labelFallbackTypes. That is a set lookup instead of a childForFieldName call per node.

Adding a language

To give a language semantic diffs, implement LanguageExtractor and register the extractor with the code tier. See Adding a language extractor in the contributing guide.

Language pages