Skip to main content

rsharpier

A Rust port of CSharpier, the opinionated C# formatter. It parses with tree-sitter (a patched copy of tree-sitter-c-sharp) instead of Roslyn and produces the same output as CSharpier for the formatting tests of the .NET version.

uvx rsharpier format .           # or: uv tool install rsharpier / pip install rsharpier
rsharpier format [paths...]      # format files and directories
rsharpier check [paths...]       # exit with 1 if something is not formatted
echo 'class  A{}' | rsharpier format
rsharpier format --write-stdout --stdin-path src/File.cs < src/File.cs
rsharpier pipe-files             # editor integration, files piped through stdin
rsharpier server --server-port N # editor integration, POST /format

Supported: .cs, .csx and the XML flavours (.csproj, .props, .targets, .config, .slnx, .xaml, .axaml, .xml). Options come from .csharpierrc / .csharpierrc.json / .yaml / .yml (with overrides) or .editorconfig; .csharpierignore and .gitignore files are used the same way the .NET version uses them.

Status

The ported formatting tests of CSharpier, which live in a checkout of the .NET repository next to this one (../csharpier, or set CSHARPIER_TEST_FILES), all pass:

cargo test --release
cargo run --release --example conformance [dir] [-v] [name]   # per file results and diffs
FormattingTests/TestFiles/cs 208 / 208
csx, xml_strict, xml_ignore all
DocPrinterTests all 55
PreprocessorSymbolsTests, LineEndingTests, CSharpFormatterTests, DeepRecursionTests ported
OptionsProviderTests, CommandLineFormatterTests, ignore file tests the main scenarios ported (tests/options_provider.rs, tests/cli.rs)

Against real code, cargo run --release --example selfcheck <dir> formats every .cs file below a directory (IDEM=1 formats the output a second time). On CSharpier's own sources 370 of 380 files come out byte for byte the same (the rest were formatted with an older version of the .NET formatter). On more than 25,000 files from other repositories (about 4.5 million lines) formatting never panicked, kept all tokens, and was idempotent for all but two files.

How it works

path ported from notes
src/doc/ DocTypes, DocPrinter the doc IR, PropagateBreaks, fits logic and printer
src/trivia.rs (new) rebuilds Roslyn's token + leading/trailing trivia model on top of tree-sitter
src/symbols.rs BooleanExpressionParser, PreprocessorSymbols the symbol sets that activate every #if branch
src/format.rs CSharpFormatter pipeline, one pass per symbol set, validation
src/printer/ SyntaxPrinter/* all node printers, member chains, usings, ignore comments, raw strings
src/xml.rs Xml/* the XML reader and printers
src/cli/ CSharpier.Cli commands, configuration, ignore files, server
grammar/ the patched tree-sitter grammar

Trivia

Roslyn attaches comments, directives and disabled text to tokens, and CSharpier's printers are written against that. tree-sitter gives comments as free floating "extras" and parses all #if branches as code. trivia.rs

  1. finds directive lines (ignoring # inside strings and comments),
  2. evaluates #if/#elif/#else for a symbol set, so inactive branches become disabled text,
  3. blanks directives and disabled text with spaces (offsets stay stable) and parses that,
  4. takes the leaves of the tree as tokens, lexes the gaps between them in the original text into trivia and splits them into trailing (up to the first newline) and leading, like Roslyn.

format() then formats its own output once for every symbol set from symbols::get_sets, which is what the C# version does so code in every branch gets formatted.

Validation

format.rs::validate compares the multiset of tokens before and after formatting (commas are excluded, the formatter adds and removes them; multi line strings only by their content). It is the counterpart of SyntaxNodeComparer and catches printers that drop or invent code.

The grammar

tree-sitter-c-sharp 0.23.5 mis-parses or rejects several things CSharpier needs, so the crate is vendored in grammar/tree-sitter-c-sharp. grammar/patch_grammar.py applies the fixes to the pristine grammar.js and regenerates the parser (it needs the tree-sitter CLI):

python3 grammar/patch_grammar.py <path to upstream grammar.js> <tree-sitter binary>

Fixes: x is null || y (the || ended up in the pattern), a ?? b?.c, a.b is X or Y and member access on patterns, list patterns starting with .., params parameters, and/or/not as identifiers, null conditional assignment, unions, extension blocks, allows ref struct, closed, labeled break/continue, destructors with modifiers, checked(...) and plain names/member accesses as statements, extern alias in namespaces and generic names in new List<(int a, int b)>.

Known differences and gaps

  • Sorting of usings uses a lowercase comparison instead of InvariantCultureIgnoreCase.
  • There is no formatting cache (--no-cache/--use-cache are accepted and ignored) and no CSharpier.MsBuild version check (--no-msbuild-check is accepted).
  • Files in an encoding other than UTF-8/UTF-16 with a byte order mark are read as UTF-8.
  • Syntax errors are reported by tree-sitter positions and not with Roslyn's messages.
  • Code that tree-sitter cannot parse (preview syntax that is not in the grammar yet) is reported as a syntax error and left alone.

Metadata

Release files for rsharpier 0.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for rsharpier 0.1.0
File Size Uploaded Provenance Actions
rsharpier-0.1.0.tar.gz 1.8 MB Without provenance Details for rsharpier-0.1.0.tar.gz

Built distributions (wheels)

Table of built distributions (wheels) for rsharpier 0.1.0
File Actions
rsharpier-0.1.0-py3-none-win_amd64.whl Python 3 none Windows x86-64 Details for rsharpier-0.1.0-py3-none-win_amd64.whl
rsharpier-0.1.0-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl Python 3 none Linux glibc 2.17+ x86-64 Details for rsharpier-0.1.0-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
rsharpier-0.1.0-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl Python 3 none Linux glibc 2.17+ ARM64 Details for rsharpier-0.1.0-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
rsharpier-0.1.0-py3-none-macosx_11_0_arm64.whl Python 3 none macOS 11.0+ ARM64 Details for rsharpier-0.1.0-py3-none-macosx_11_0_arm64.whl
rsharpier-0.1.0-py3-none-macosx_10_12_x86_64.whl Python 3 none macOS 10.12+ x86-64 Details for rsharpier-0.1.0-py3-none-macosx_10_12_x86_64.whl

Total release size: 12.9 MB

Release files / rsharpier-0.1.0.tar.gz

Download URL rsharpier-0.1.0.tar.gz
Size 1.8 MB
Tags Source
SHA-256 checksum
How to use checksums
fdf8ded93936728d67c8357caf145b1d3adfac6ec2c286003f72a9e82e8ddfa4
BLAKE2b-256 checksum
How to use checksums
a0bb641232754654d7be14acadd0697338befacf8035d5e89edd05d8022cafc1
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.13.5 {"installer":{"name":"uv","version":"0.13.5","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release files / rsharpier-0.1.0-py3-none-win_amd64.whl

Download URL rsharpier-0.1.0-py3-none-win_amd64.whl
Size 2.0 MB
Tags Python 3 Windows x86-64
SHA-256 checksum
How to use checksums
26d1b08846033106997ec58b842ca9b22113cca3dd4e5f3bcfa90400ba7e2728
BLAKE2b-256 checksum
How to use checksums
5020390aec50d74ad55b19c534ddf761e077fdbca27521b8305f688447b8aaa7
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.13.5 {"installer":{"name":"uv","version":"0.13.5","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release files / rsharpier-0.1.0-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl

Download URL rsharpier-0.1.0-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Size 2.3 MB
Tags Linux glibc 2.17+ x86-64 Python 3
SHA-256 checksum
How to use checksums
34c2d1ba2044e2b3028b39d9169c29d79d05673ed75077a530012efbf14c3717
BLAKE2b-256 checksum
How to use checksums
496f287c8b833882aec84bf520fac2fc0885b443c092b8d1e8345e2213e6c9ef
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.13.5 {"installer":{"name":"uv","version":"0.13.5","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release files / rsharpier-0.1.0-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl

Download URL rsharpier-0.1.0-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Size 2.3 MB
Tags Linux glibc 2.17+ ARM64 Python 3
SHA-256 checksum
How to use checksums
403dd1c53325b1ff275035737d39689480d533b8d33ea9585e4f72fe9e752a7f
BLAKE2b-256 checksum
How to use checksums
9a58a48b6dcfdc97b5e95a0aa20bd29cebe85996089cf2fc137714cf0b9ac394
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.13.5 {"installer":{"name":"uv","version":"0.13.5","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release files / rsharpier-0.1.0-py3-none-macosx_11_0_arm64.whl

Download URL rsharpier-0.1.0-py3-none-macosx_11_0_arm64.whl
Size 2.2 MB
Tags Python 3 macOS 11.0+ ARM64
SHA-256 checksum
How to use checksums
547411437309e41ab40717d5a3e64bc157b27888a898c175dbae00ca8463672d
BLAKE2b-256 checksum
How to use checksums
368e3ce048422fe9447fd77b373dfd8c6c906ca2c2f035f36ddea58bd00ec724
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.13.5 {"installer":{"name":"uv","version":"0.13.5","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release files / rsharpier-0.1.0-py3-none-macosx_10_12_x86_64.whl

Download URL rsharpier-0.1.0-py3-none-macosx_10_12_x86_64.whl
Size 2.2 MB
Tags Python 3 macOS 10.12+ x86-64
SHA-256 checksum
How to use checksums
417af6b990fa2e8adb5c4a7b1de2b7afa9f767373ed707edaa3850e4aef26fd7
BLAKE2b-256 checksum
How to use checksums
3e99a8a7fa5f9e717bb5c7170fd450f56f7736336de77fc00bae1e8d3b1643a0
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.13.5 {"installer":{"name":"uv","version":"0.13.5","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Security for rsharpier 0.1.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Release history Release notifications | RSS feed

This release

0.1.0 This release

6 release files No provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page