COOLJAPAN
← All posts

SplitRS 0.3.5 Released — Eight Correctness Fixes Found Splitting a Real SQLite Parser

SplitRS 0.3.5 fixes eight correctness issues found splitting a real sqlite3-parser crate: file-backed mod declarations, --split-impl-blocks cross-chunk calls, bitflags type exports, and grouped-import collisions, resolving E0583, E0624, E0425, and E0252. 608 tests passing, up from 570 in 0.3.4.

release splitrs rust refactoring ast developer-tools bitflags imports bugfix

The best fuzzer for a refactoring tool isn’t a fixture file — it’s a real, gnarly codebase. Splitting the oxisqlite-core/oxisql sqlite3-parser crate found eight distinct ways SplitRS’s generated code could fail to compile.

Today we released SplitRS 0.3.5 — another pure correctness release, and like 0.3.4 it has an empty Added section. Every one of its eight fixes traces back to a real compiler error hit while splitting a real crate, and every one of them is fixed.

SplitRS is the AST-based Rust refactoring tool that splits oversized source files into clean, compilable modules: it parses with syn, clusters methods and types, infers visibility, and writes the imports and mod.rs facades for you. No C, no external formatter shelling out to system tools — it links prettyplease in-process and compiles to a single static binary.

Why 0.3.5 matters

Running a splitter against a large, real-world parser crate exercises code shapes a hand-written test suite doesn’t always think to cover — file-backed submodules, cross-chunk method calls, macro-defined types, trait-bound imports. 0.3.5 fixes the eight failure modes that dogfooding on sqlite3-parser actually found:

None of this changes the CLI surface — every flag works exactly as documented in 0.3.4. This release makes the code SplitRS generates compile (and keep its comments) more often.

Technical Deep Dive

  1. FileAnalyzer::file_backed_mods scans the source for mod x; items with no inline body (content: None) before chunking begins, producing a pinned set the chunker must never place into a generated bucket file.
  2. rewrite_pinned_mod_refs_in_use walks every forwarded use tree the generator writes and, for any path segment matching a pinned file-backed mod, inserts the super:: prefix so the reference still resolves from its new location.
  3. FileAnalyzer::module_defined_callables extends the “who defines this callable” analysis to look inside individual method_group chunks, not just whole impl blocks, so a call from a sibling chunk resolves to the correct definition site instead of being assumed private-and-inaccessible.
  4. free_fn_to_module is a narrower, free-function-only companion map: it stops the (invalid) use super::<mod>::<method>; shape from ever being emitted for a method, since only free functions can legally be imported that way.
  5. bitflags_defined_idents / bitflags_defines_pub_type scan the raw macro token stream of every bitflags::bitflags! { ... } invocation — rather than trying to expand the macro — to recover the type name(s) it defines, feeding them into the same cross-module import/re-export machinery as an ordinary struct/enum.
  6. collect_use_bound_names replaces a first-{...}-only string scan inside already_imported with a real AST walk, so nested multi-segment grouped imports are parsed correctly instead of pattern-matched.
  7. upgrade_verbatim_item_visibility text-patches a pub(super) prefix directly onto a byte-verbatim-sliced item — correctly skipping past leading attributes and ////* */ comments to find the insertion point — so a visibility upgrade no longer forces a prettyplease round-trip that drops comments.
  8. generate_tests_rs_full / generate_tests_rs_with_imports_deep, plus test_module_splitter::generate_per_test_file/generate_fallback_tests_rs, all gained an original_source: Option<&str> parameter, threading the original file text down to wherever verbatim slicing needs it.

Getting Started

Install the latest SplitRS:

cargo install splitrs

Two of this release’s fixes (cross-chunk method calls, cross-module const/static imports) show up specifically under impl-block splitting, so it’s worth running with that flag on:

splitrs \
  --input src/large_file.rs \
  --output src/large_file/ \
  --split-impl-blocks \
  --max-impl-lines 200

If you hit E0583, E0624, E0425, E0433, E0599, or E0252 against generated output on 0.3.4 or earlier, upgrading to 0.3.5 and re-running the same command should resolve it without any config changes.

What’s New in 0.3.5

Tips

This is the foundation

SplitRS remains the development workhorse behind the COOLJAPAN policy of keeping every file under 2,000 lines, used across the ecosystem’s Rust codebases — OxiZ, NumRS2, SciRS2, and dozens of oxi* crates — whenever a module outgrows its budget. Fittingly, 0.3.5’s entire fix list came from dogfooding: splitting the oxisqlite-core/oxisql sqlite3-parser crate for real is what surfaced all eight of these bugs, not a synthetic test fixture.

Repository: https://github.com/cool-japan/splitrs

Star the repo if you want a refactoring tool that treats its own real-world failures as bugs worth a dedicated release. Pure Rust refactoring is here — fast, safe, and getting more battle-tested with every crate it splits.

KitaSan at COOLJAPAN OÜ July 14, 2026

↑ Back to all posts