tree-sitter-c-sharp

C# grammar for tree-sitter, based on the Roslyn language grammar

Library
Cargo
v0.23.5
317stars
MIT License

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum.How we score it →
61/100Good
Development Activity48
Maintenance36
Community80
Maturity60
Momentum20

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation.How we score it →
74/100Good
Architecture83
Code Quality80
Innovation72
Learning Curve62

tree-sitter-c-sharp is the C# grammar for tree-sitter, the incremental parsing library used by editors and tooling to build syntax trees in real time. The grammar is derived from Roslyn’s official C# grammar export, adapted to work around differences between parsing technologies, handle preprocessor directives (#if/#else/#elif/#endif), and keep the resulting syntax tree simpler and the parser state count lower than a direct Roslyn port would produce.

It comprehensively supports C# 1 through 14.0, with a few documented gaps (contextual keywords like async/var/await used as identifiers in all valid positions, and newer file-based-app preprocessor directives). As with tree-sitter’s other grammars, it ships pre-generated parser tables and bindings for Rust, Node.js, Python, Go, and Swift from a single grammar source, along with highlighting and tagging query files for editor integration.

What You Get

  • A LANGUAGE constant (Rust) or equivalent binding (Node, Python, Go, Swift) that plugs into a tree_sitter::Parser
  • Comprehensive C# 1 through 14.0 grammar coverage, based on the Roslyn language grammar export
  • Preprocessor directive support (#if/#else/#elif/#endif) adapted to tree-sitter’s incremental parsing model
  • Pre-generated parser.c/grammar.json/node-types.json so consumers skip the tree-sitter CLI generation step
  • Bundled .scm query files for syntax highlighting and tagging, ready for editor integration

Common Use Cases

  • Building editor syntax highlighting and structural navigation for C# files in tree-sitter-based editors (Neovim, Helix)
  • Powering static analysis or code-intelligence tools that need a real C# syntax tree instead of regex-based parsing
  • Embedding incremental C# parsing in a Rust, Node.js, Python, or Go application via the corresponding language binding
  • Parsing C# code fragments for syntax highlighting in documentation or code-snippet rendering tools

Under The Hood

Architecture - The grammar is authored in grammar.js (62KB, the largest file in the repo, reflecting C#‘s syntactic breadth versus JavaScript) and compiled ahead of time by the tree-sitter CLI into checked-in src/parser.c, src/grammar.json, and src/node-types.json. Because the grammar is adapted from Roslyn’s C# grammar rather than authored from scratch, its design goals explicitly include reducing parser state count and simplifying the output tree relative to a literal Roslyn port — trade-offs documented directly in the README. The queries/ directory holds highlights.scm and tags.scm for editor integration, a smaller query surface than tree-sitter-javascript’s (no separate JSX/locals variants, reflecting C#‘s simpler tagging needs). bindings/rust/lib.rs follows the same thin extern "C" pattern used across tree-sitter language crates.

Tech Stack - JavaScript grammar source (45% of the codebase) with C# fixture/test files (35%) and a small C runtime layer (17%) for the compiled parser tables. The Rust binding depends only on tree-sitter-language plus cc as a build-dependency; equivalent thin bindings exist for Node.js, Python, Go, and Swift, wrapping the same generated C sources.

Code Quality - test/ contains corpus-based parse tests (source input plus expected S-expression trees) covering C# language features across versions, plus dedicated preprocessor-directive test fixtures given how much extra logic those directives require. CI runs across the multi-language binding matrix. The README explicitly documents known coverage gaps (contextual keyword edge cases, newer file-based-app directives) rather than silently under-supporting them, which is useful signal for consumers deciding whether the grammar covers their use case.

API Design - Like the JavaScript grammar, the public surface is a small set of exported constants (LANGUAGE, NODE_TYPES, HIGHLIGHT_QUERY, TAGS_QUERY) rather than functions to call — one line (parser.set_language(&tree_sitter_c_sharp::LANGUAGE.into())) is enough to start parsing C#, keeping integration cost minimal for tool authors.

Join founders buildingwith open source

Opinionated takes, migration guides, cost-saving tips, and insights from the open source ecosystem.

Subscribe on Substack
Join 750+ subscribers

Search