splitrs 0.3.4

AST-based Rust refactoring tool with trait separation, config files, and intelligent module generation
Documentation

SplitRS πŸ¦€βœ‚οΈ

Crates.io Documentation License

A production-ready Rust refactoring tool that intelligently splits large files into maintainable modules

SplitRS uses AST-based analysis to automatically refactor large Rust source files (>1000 lines) into well-organized, compilable modules. It handles complex generics, async functions, Arc/Mutex patterns, and automatically generates correct imports and visibility modifiers.

✨ Features

Core Refactoring

  • 🎯 AST-Based Refactoring: Uses syn for accurate Rust parsing
  • 🧠 Intelligent Method Clustering: Groups related methods using call graph analysis
  • πŸ“¦ Auto-Generated Imports: Context-aware use statements with proper paths
  • πŸ”’ Visibility Inference: Automatically applies pub(super), pub(crate), or pub
  • πŸš€ Complex Type Support: Handles generics, async, Arc/Mutex, nested types
  • ⚑ Fast: Processes 1600+ line files in <1 second
  • βœ… Production-Tested: Successfully refactored 10,000+ lines of real code

Advanced Features (v0.2.0+)

  • βš™οΈ Configuration Files: .splitrs.toml support for project-specific settings
  • 🎭 Trait Implementation Support: Automatic separation of trait impls into dedicated modules
  • πŸ”— Type Alias Resolution: Intelligent handling of type aliases in import generation
  • πŸ” Circular Dependency Detection: DFS-based cycle detection with Graphviz export
  • πŸ‘€ Enhanced Preview Mode: Beautiful formatted preview with statistics before refactoring
  • πŸ’¬ Interactive Mode: Confirmation prompts before file generation
  • πŸ”„ Automatic Rollback Support: Backup creation for safe refactoring
  • πŸ“ Smart Documentation: Auto-generated module docs with trait listings

v0.3.x Features

  • πŸ”¬ Macro Analyzer: Detects macro_rules! definitions and #[derive] usage with placement suggestions
  • πŸ“Š Metrics Dashboard: Cyclomatic complexity analysis with HTML/JSON/text reports (--metrics)
  • πŸ—‚οΈ Field Access Tracker: Detects field access patterns to prevent broken visibility during splits
  • πŸ”— Trait Method Tracker: Ensures trait method implementations stay coherent after splitting
  • πŸ–₯️ LSP Integration (splitrs-lsp): Language server for real-time refactoring guidance
    • Diagnostics for oversized files and impl blocks
    • Code action Refactor with splitrs (applies a WorkspaceEdit)
    • Hover showing file metrics (LoC, methods, complexity)
    • .splitrs.toml config watch with hot reload

v0.3.3 Features

  • πŸ—ΊοΈ Domain-Mapping for --target-modules: seeded assignment pulls unlisted items into the module with the strongest reference affinity, unknown-name validation with near-miss suggestions, dry-run attribution, and an extended schema (parent, pull_dependencies, doc, max_lines) plus infix/multi-segment glob patterns
  • 🌲 Nested Inline-Mod Descent (--split-nested-mods, --max-mod-depth): recursively splits over-budget inline mod x { ... } blocks through the same analyze β†’ group β†’ generate pipeline
  • 🎭 Facade Style Control (--facade <glob|named|none>): choose glob re-exports, explicit named re-exports, or declarations-only for generated mod.rs facades
  • βœ‚οΈ Verbatim Method Extraction: SourceMap now covers individual extracted impl methods, preserving original formatting byte-for-byte
  • πŸ§ͺ New Integration Test Suites: acceptance_e2e_tests, domain_mapping_tests, nested_mod_tests

πŸ“¦ Installation

cargo install splitrs

Or build from source:

git clone https://github.com/cool-japan/splitrs
cd splitrs
cargo build --release

πŸš€ Quick Start

Basic Usage

# Split a large file into modules
splitrs --input src/large_file.rs --output src/large_file/

# Preview what will be created (no files written)
splitrs --input src/large_file.rs --output src/large_file/ --dry-run

# Interactive mode with confirmation
splitrs --input src/large_file.rs --output src/large_file/ --interactive

Recommended Usage (with impl block splitting)

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

Using Configuration Files

Create a .splitrs.toml in your project root:

[splitrs]
max_lines = 1000
max_impl_lines = 500
split_impl_blocks = true

[naming]
type_module_suffix = "_type"
impl_module_suffix = "_impl"

[output]
preserve_comments = true
format_output = true

Then simply run:

splitrs --input src/large_file.rs --output src/large_file/

Nested Inline-Mod Descent (v0.3.3)

By default, an over-budget inline mod x { ... } block travels as one opaque item. With --split-nested-mods true, SplitRS descends into it and re-runs the full analyze β†’ group β†’ generate pipeline on the module body, recursively:

# Recursively split over-budget inline `mod x { ... }` blocks
splitrs -i src/lib.rs -o src/lib_split/ --split-nested-mods true

# Guard the recursion depth (modules nested deeper stay opaque; default: 8)
splitrs -i src/lib.rs -o src/lib_split/ --split-nested-mods true --max-mod-depth 2

# Control the re-export style of every generated mod.rs
splitrs -i src/lib.rs -o src/lib_split/ --facade named

Each descended module becomes an x/ directory (x/mod.rs plus per-topic files) and is declared in the parent mod.rs with its original visibility, attributes, and doc comments β€” never re-exported, so historical crate::x::Item paths keep resolving. super:: paths inside moved items are deepened by one level per descent (including pub(super) β†’ pub(in super::super)), and the original file-scope use bindings are recreated in the generated mod.rs. Composes with --extract-tests (a per-level tests.rs).

--facade <STYLE> accepts:

  • glob (default) β€” pub use module::*; re-exports
  • named β€” explicit pub use module::{Foo, bar}; lists (better rustdoc, no glob shadowing)
  • none β€” declarations only, for hand-curated re-exports

Domain Mapping with --target-modules (v0.3.3)

Instead of the default types.rs/functions.rs heuristic, a TOML spec can route items into named domain modules β€” and, combined with --split-nested-mods, route them inside a descended module:

# domains.toml
# How items not matched by any rule are assigned:
#   "heuristic" (default) β€” classic types.rs/functions.rs buckets
#   "seeded"              β€” pulled into the named module with the strongest
#                           reference affinity (deterministic fixpoint)
assign_unlisted = "seeded"

[[target_modules]]
name = "hash"
parent = "core"              # route inside the core/ module descended by --split-nested-mods
items = ["*hash*", "Sha*"]   # exact, prefix Foo*, suffix *Foo, infix *foo*, multi a*b*c, catch-all *
pull_dependencies = true     # matched items drag their private helpers along
doc = "Hashing and digest helpers."

[[target_modules]]
name = "compare"
parent = "core"
items = ["compare_*", "Diff*"]

[[target_modules]]
name = "config"
items = ["Config", "SortBy"] # exact names matching nothing = hard error (with near-miss suggestions)
max_lines = 400              # this module overflows into config_2.rs, config_3.rs, ...
splitrs -i src/lib.rs -o src/lib_split/ \
  --split-nested-mods true \
  --target-modules domains.toml \
  --dry-run    # attribution report: which rule (or seed edge) pulled each item

Resulting layout (impls and trait impls travel with their self type):

lib_split/
β”œβ”€β”€ mod.rs        # facade: `pub mod core;` β€” crate::core::Item paths preserved
β”œβ”€β”€ config.rs     # routed by exact name
└── core/
    β”œβ”€β”€ mod.rs
    β”œβ”€β”€ hash.rs
    └── compare.rs

Specs are validated up front: duplicate module names within the same parent scope, rules with an empty items list, catch-all * rules that are not last in their scope, and parent = "..." rules without --split-nested-mods true are all hard errors.

LSP Integration (Editor Support)

splitrs-lsp is included when you cargo install splitrs (LSP is a default feature). It speaks the Language Server Protocol over stdio and provides:

  • πŸ”΄ Diagnostics when files exceed your .splitrs.toml max_lines limit (source: "splitrs", severity: Information)
  • ⚑ Code action Refactor with splitrs to split large files directly from your editor
  • ℹ️ Hover at the top of any Rust file showing metrics (lines of code, method count, avg complexity)

Zero-config quickstart

Neovim (via vim.lsp.start):

require('lspconfig').splitrs_lsp.setup{}
-- Or manually:
vim.lsp.start({ name = 'splitrs-lsp', cmd = { 'splitrs-lsp' } })

Helix (languages.toml):

[[language]]
name = "rust"
language-servers = ["rust-analyzer", "splitrs-lsp"]

[language-server.splitrs-lsp]
command = "splitrs-lsp"

Rich editor plugins (in editors/)

For a full-featured experience (config-watch, :SplitrsRefactor command, settings UI), use the plugins in the editors/ directory:

Neovim β€” editors/nvim/

Full Lua plugin with setup{} API, .splitrs.toml watcher, and :SplitrsRefactor command:

-- With lazy.nvim (from a local checkout):
{ dir = '/path/to/splitrs/editors/nvim', config = true }

-- Manual setup:
vim.opt.rtp:prepend('/path/to/splitrs/editors/nvim')
require('splitrs').setup()

-- Custom options:
require('splitrs').setup({
  cmd = { '/usr/local/bin/splitrs-lsp' },  -- custom binary path
  enabled = true,
})

VSCode β€” editors/vscode/

TypeScript extension activating on onLanguage:rust. Sideload:

cd editors/vscode
npm install
npx vsce package          # creates splitrs-*.vsix
code --install-extension splitrs-*.vsix

Configure via settings.json:

{
  "splitrs.serverPath": "splitrs-lsp",
  "splitrs.enable": true,
  "splitrs.trace.server": "off"
}

Use the Command Palette (Ctrl+Shift+P) β†’ splitrs: Refactor current file.

Emacs β€” editors/emacs/

Supports both built-in eglot (Emacs 29.1+) and lsp-mode:

;; With use-package:
(use-package splitrs
  :load-path "path/to/splitrs/editors/emacs"
  :hook ((rust-mode . splitrs-mode)
         (rust-ts-mode . splitrs-mode)))

;; Manual:
(add-to-list 'load-path "path/to/splitrs/editors/emacs")
(require 'splitrs)
(splitrs-setup)  ; registers with eglot and lsp-mode

;; Refactor from a Rust buffer:
;; M-x splitrs-refactor-current-file

splitrs-lsp runs alongside rust-analyzer β€” it uses :add-on? t in lsp-mode and appends to eglot-server-programs so neither server displaces the other.

IntelliJ IDEA β€” editors/intellij/

Kotlin/Gradle plugin using IntelliJ 2024.2+'s built-in LSP API. Build:

cd editors/intellij
gradle wrapper --gradle-version 8.10   # one-time setup
./gradlew buildPlugin
# Install: Settings β†’ Plugins β†’ Install Plugin from Disk β†’ build/distributions/*.zip

Requires: IntelliJ IDEA 2024.2 or later, JDK 21, splitrs-lsp on $PATH.


Configuration (all editors)

Create .splitrs.toml in your project root to customise the server:

[splitrs]
max_lines = 1000       # warn when a file exceeds this many lines
max_impl_lines = 300   # warn on oversized impl blocks (if split_impl_blocks = true)
split_impl_blocks = true

The server hot-reloads .splitrs.toml whenever the file changes.

To use LSP-only (without the full splitrs CLI):

cargo install splitrs --no-default-features --features lsp

πŸ“– Examples

Example 1: Trait Implementations

SplitRS automatically detects and separates trait implementations:

Input: user.rs

pub struct User {
    pub name: String,
    pub age: u32,
}

impl User {
    pub fn new(name: String, age: u32) -> Self { /* ... */ }
}

impl Debug for User { /* ... */ }
impl Display for User { /* ... */ }
impl Clone for User { /* ... */ }
impl Default for User { /* ... */ }

Command:

splitrs --input user.rs --output user/ --dry-run

Output:

user/
β”œβ”€β”€ types.rs         # struct User definition + inherent impl
β”œβ”€β”€ user_traits.rs   # All trait implementations (Debug, Display, Clone, Default)
└── mod.rs          # Module organization

Generated user_traits.rs:

//! # User - Trait Implementations
//!
//! This module contains trait implementations for `User`.
//!
//! ## Implemented Traits
//!
//! - `Debug`
//! - `Display`
//! - `Clone`
//! - `Default`
//!
//! πŸ€– Generated with [SplitRS](https://github.com/cool-japan/splitrs)

use super::types::User;

impl Debug for User { /* ... */ }
impl Display for User { /* ... */ }
impl Clone for User { /* ... */ }
impl Default for User { /* ... */ }

Example 2: Basic Refactoring

Input: connection_pool.rs (1660 lines)

pub struct ConnectionPool<T> {
    connections: Arc<Mutex<Vec<T>>>,
    config: PoolConfig,
    // ... 50 fields
}

impl<T: Clone + Send + Sync> ConnectionPool<T> {
    pub fn new(config: PoolConfig) -> Self { ... }
    pub async fn acquire(&self) -> Result<T> { ... }
    pub async fn release(&self, conn: T) -> Result<()> { ... }
    // ... 80 methods
}

Command:

splitrs --input connection_pool.rs --output connection_pool/ --split-impl-blocks

Output: 25 well-organized modules

connection_pool/
β”œβ”€β”€ mod.rs                          # Module organization & re-exports
β”œβ”€β”€ connectionpool_type.rs          # Type definition with proper visibility
β”œβ”€β”€ connectionpool_new_group.rs     # Constructor methods
β”œβ”€β”€ connectionpool_acquire_group.rs # Connection acquisition
β”œβ”€β”€ connectionpool_release_group.rs # Connection release
└── ... (20 more focused modules)

Example 3: Preview Mode

Get detailed information before refactoring:

splitrs --input examples/trait_impl_example.rs --output /tmp/preview -n

Output:

============================================================
DRY RUN - Preview Mode
============================================================

πŸ“Š Statistics:
  Original file: 82 lines
  Total modules to create: 4

πŸ“ Module Structure:
  πŸ“„ product_traits.rs (2 trait impls)
  πŸ“„ user_traits.rs (4 trait impls)
  πŸ“„ types.rs (2 types)
  πŸ“„ functions.rs (1 items)

πŸ’Ύ Files that would be created:
  πŸ“ /tmp/preview/
    πŸ“„ product_traits.rs
    πŸ“„ user_traits.rs
    πŸ“„ types.rs
    πŸ“„ functions.rs
    πŸ“„ mod.rs

============================================================
βœ“ Preview complete - no files were created
============================================================

Example 4: Complex Types

SplitRS correctly handles complex Rust patterns:

// Input
pub struct Cache<K, V>
where
    K: Hash + Eq + Clone,
    V: Clone + Send + Sync + 'static,
{
    data: Arc<RwLock<HashMap<K, V>>>,
    eviction: EvictionPolicy,
}

// Output (auto-generated)
// cache_type.rs
use std::collections::HashMap;
use std::sync::{Arc, RwLock};

pub struct Cache<K, V>
where
    K: Hash + Eq + Clone,
    V: Clone + Send + Sync + 'static,
{
    pub(super) data: Arc<RwLock<HashMap<K, V>>>,
    pub(super) eviction: EvictionPolicy,
}

// cache_insert_group.rs
use super::cache_type::Cache;
use std::collections::HashMap;

impl<K, V> Cache<K, V>
where
    K: Hash + Eq + Clone,
    V: Clone + Send + Sync + 'static,
{
    pub async fn insert(&mut self, key: K, value: V) -> Result<()> {
        // ... implementation
    }
}

πŸŽ›οΈ Command-Line Options

Option Short Description Default
--input <FILE> -i Input Rust source file (required) -
--output <DIR> -o Output directory for modules (required) -
--max-lines <N> -m Maximum lines per module 1000
--split-impl-blocks Split large impl blocks into method groups false
--max-impl-lines <N> Maximum lines per impl block before splitting 500
--dry-run -n Preview without creating files false
--interactive -I Prompt for confirmation before creating files false
--config <FILE> -c Path to configuration file .splitrs.toml
--target-modules <TOML-FILE> TOML file with [[target_modules]] routing rules for named splits -
--split-nested-mods <BOOL> Descend into over-budget inline mod x { ... } blocks recursively false
--max-mod-depth <N> Recursion depth guard for --split-nested-mods 8
--facade <STYLE> Re-export style in each generated mod.rs: glob, named, none glob

Configuration File Options

When using a .splitrs.toml file, you can configure:

[splitrs] section:

  • max_lines - Maximum lines per module
  • max_impl_lines - Maximum lines per impl block
  • split_impl_blocks - Enable impl block splitting
  • split_nested_mods - Descend into over-budget inline mod x { ... } blocks (default: false)
  • max_mod_depth - Recursion depth guard for split_nested_mods (default: 8)

[naming] section:

  • type_module_suffix - Suffix for type modules (default: "_type")
  • impl_module_suffix - Suffix for impl modules (default: "_impl")
  • use_snake_case - Use snake_case for module names (default: true)

[output] section:

  • module_doc_template - Template for module documentation
  • preserve_comments - Preserve original comments (default: true)
  • format_output - Format with prettyplease (default: true)
  • facade - mod.rs re-export style: "glob", "named", or "none" (default: "glob")

Command-line arguments always override configuration file settings.

πŸ”¬ SMT-verified refactoring (experimental β€” --features smt)

SplitRS can prove certain refactorings preserve semantics before applying them, using OxiZ β€” a Pure-Rust SMT solver β€” as the verification backend. This is off by default; build it in with:

cargo build --features smt
cargo run --features smt -- <args>

Three capabilities are exposed:

--verify-equiv --left FILE::FN --right FILE::FN β€” prove two pure fixed-width-integer functions compute the same result for all inputs, or get a concrete counterexample:

# Proves `a` and `b` are equivalent (QF_BV, all inputs)
splitrs --features smt --verify-equiv --left calc.rs::a --right calc.rs::b

--extract-pure β€” an SMT-verified pre-pass that runs before the split. It scans every over-budget free function for a pure-integer sub-run, factors it into a helper, and commits the rewrite only when the solver proves it equivalent to the original. Committed helpers are ordinary functions that then flow through the normal split/write pipeline. Non-equivalent or out-of-fragment candidates are skipped (with a reason) and the original is left untouched.

--verify β€” emit an honest Semantic verification report that separates what was proven from what is merely assumed:

  • Each --extract-pure body rewrite that committed β†’ SMT-Verified equivalent (QF_BV, all inputs).
  • The default whole-item module moves β†’ structural identity: a byte-identical relocation. SplitRS does not claim to SMT-prove move safety; name-resolution and visibility correctness is the Rust compiler's job β€” verify with cargo check.
splitrs --features smt -i big.rs -o out/ --extract-pure --verify

Soundness boundary. The proven fragment is pure, fixed-width integers only: + - * & | ^ << >>, comparisons, if/else, let, and integer casts. Anything outside it β€” division/remainder, function calls, references, loops, floats β€” is reported as Unsupported and never committed (the gate refuses to rubber-stamp it). Whole-item relocations remain structural identity, not SMT-proven.

πŸ—οΈ How It Works

SplitRS uses a multi-stage analysis pipeline:

  1. AST Parsing: Parse input file with syn
  2. Scope Analysis: Determine organization strategy and visibility
  3. Method Clustering: Build call graph and cluster related methods
  4. Type Extraction: Extract types from fields for import generation
  5. Module Generation: Generate well-organized modules with correct imports
  6. Code Formatting: Format output with prettyplease

Organization Strategies

Inline - Keep impl blocks with type definition:

typename_module.rs
  β”œβ”€β”€ struct TypeName { ... }
  └── impl TypeName { ... }

Submodule - Split type and impl blocks (recommended for large files):

typename_type.rs       # Type definition
typename_new_group.rs  # Constructor methods
typename_getters.rs    # Getter methods
mod.rs                 # Module organization

Wrapper - Wrap in parent module:

typename/
  β”œβ”€β”€ type.rs
  β”œβ”€β”€ methods.rs
  └── mod.rs

πŸ“Š Performance

Tested on real-world codebases:

File Size Lines Time Modules Generated
Small 500-1000 <100ms 3-5
Medium 1000-1500 <500ms 5-12
Large 1500-2000 <1s 10-25
Very Large 2000+ <2s 25-40

πŸ§ͺ Testing

SplitRS includes 450 comprehensive tests covering all analysis components:

# Run all tests (recommended)
cargo nextest run --all-features

# Or with the built-in test runner
cargo test --all-features

# Test on example files
cargo run -- --input examples/large_struct.rs --output /tmp/test_output

πŸ“š Documentation

API Documentation (docs.rs)

Full API documentation is available at docs.rs/splitrs.

Generate documentation locally:

# Generate and open documentation
cargo doc --no-deps --open

# Generate documentation for all features
cargo doc --all-features --no-deps

Module Structure

The codebase is organized into these main modules:

  • main.rs - CLI interface, file analysis, and module generation
  • config.rs - Configuration file parsing and management (.splitrs.toml)
  • method_analyzer.rs - Method dependency analysis and grouping
  • import_analyzer.rs - Type usage tracking and import generation
  • scope_analyzer.rs - Module scope analysis and visibility inference
  • dependency_analyzer.rs - Circular dependency detection and graph visualization

Key Types and Traits

Core Types:

  • FileAnalyzer - Main analyzer for processing Rust files
  • TypeInfo - Information about a Rust type and its implementations
  • Module - Represents a generated module
  • Config - Configuration loaded from .splitrs.toml

Analysis Types:

  • ImplBlockAnalyzer - Analyzes impl blocks for splitting
  • MethodGroup - Groups related methods together
  • ImportAnalyzer - Tracks type usage and generates imports
  • DependencyGraph - Detects circular dependencies

πŸ“š Use Cases

When to Use SplitRS

βœ… Perfect for:

  • Files >1000 lines with large impl blocks
  • Monolithic modules that need organization
  • Legacy code refactoring
  • Improving code maintainability

⚠️ Consider Carefully:

  • Files with circular dependencies (will generate modules but may need manual fixes)
  • Files with heavy macro usage (basic support, may need manual review)

❌ Not Recommended:

  • Files <500 lines (probably already well-organized)
  • Files with complex conditional compilation (#[cfg])

πŸ”§ Integration

CI/CD Pipeline

# .github/workflows/refactor.yml
name: Auto-refactor
on:
  workflow_dispatch:
    inputs:
      file:
        description: 'File to refactor'
        required: true

jobs:
  refactor:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - uses: actions-rs/toolchain@v1
        with:
          toolchain: stable
      - run: cargo install splitrs
      - run: |
          splitrs --input ${{ github.event.inputs.file }} \
                  --output $(dirname ${{ github.event.inputs.file }})/refactored \
                  --split-impl-blocks
      - uses: peter-evans/create-pull-request@v5
        with:
          title: "Refactor: Split ${{ github.event.inputs.file }}"

🀝 Contributing

Contributions are welcome! Please see CONTRIBUTING.md for guidelines.

Development Setup

git clone https://github.com/cool-japan/splitrs
cd splitrs
cargo build
cargo test

Implemented Features (v0.3.4 β€” Latest Release)

v0.3.4 Highlights (2026-07-06):

  • βœ… Nested-mod descent correctness review: relocated private inline mod items are widened to pub(super) (new Item::Mod arm in upgrade_type_visibility), fixing E0603 against the use self::<bucket>::<mod>; re-binding in generated mod.rs
  • βœ… Parent-scope binding recreation no longer drops the forwarded use super::*; glob when an unresolved bare fn call or method belongs to an item the parent scope provides (compute_parent_scope_items / ParentScopeItems); fixes E0425/E0599 in descended module bodies
  • βœ… macro_rules! names excluded from the type-to-module import map, eliminating bogus use super::macros::<name>; imports (E0432) and the resulting E0659 ambiguity with #[macro_use]-expanded macros
  • βœ… collect_use_bound_names widened pub(super) β†’ pub(crate) so nested_mod_splitter can enumerate the bindings a generated mod.rs recreates for its descended children
  • βœ… Parent-scope import pruning also subtracts names the nested body binds through its own non-super use trees, removing duplicated unused_imports warnings from emitted mod.rs
  • βœ… Test suite: 570 tests passing with --all-features (499 with default features, 1 skipped), was 565 in v0.3.3 β€” five new regression tests, one per review finding

v0.3.3 Highlights (2026-07-06):

  • βœ… Domain-mapping for --target-modules (seeded assignment, unknown-name validation, dry-run attribution, extended schema: parent/pull_dependencies/doc/max_lines, infix/multi-segment glob patterns, validate_target_modules())
  • βœ… Nested inline-mod descent (--split-nested-mods, --max-mod-depth): recursively splits over-budget inline mod x { ... } blocks
  • βœ… --facade <glob|named|none> flag / [output] facade config option for controlling generated mod.rs re-export style
  • βœ… Verbatim source slicing (src/source_map.rs) extended to cover individual extracted impl methods
  • βœ… New integration test suites: acceptance_e2e_tests, domain_mapping_tests, nested_mod_tests
  • βœ… run_workspace_mode extracted into its own module, src/workspace_mode.rs
  • βœ… Dependency bumps: syn gained visit-mut feature, proc-macro2 added (span-locations), tokio 1.52.1β†’1.52.3, dashmap 6.1.0β†’6.2.1
  • βœ… Test suite: 565 tests passing with --all-features (494 with default features), was 450 in v0.3.2

v0.3.2 Highlights (2026-06-09):

  • βœ… SMT-verified function extraction (--features smt --extract-pure): extracts pure integer sub-blocks from over-budget free functions, committing only when OxiZ proves semantic equivalence
  • βœ… SMT equivalence oracle (splitrs smt-verify-equiv): standalone equivalence checker between two Rust functions using QF_BV theory
  • βœ… Array-splitting mode (--split-arrays): splits oversized static/const array literals across chunk files with const fn compile-time reconstruction
  • βœ… Test-module splitter (--split-test-modules): splits multiple #[cfg(test)] blocks into per-module tests_NAME.rs files
  • βœ… Editor integrations shipped in editors/: Emacs, IntelliJ, Neovim, VSCode
  • βœ… module_generator refactored into src/module_generator/ (3 modules, all under 2000 lines)
  • βœ… Test suite: 450 tests passing (was 269 in v0.3.1)

v0.3.1 Highlights:

  • βœ… LSP Integration (splitrs-lsp binary, tower-lsp, diagnostics, code actions, hover, config watch)
  • βœ… Batched trait implementations into shared modules to reduce file clutter
  • βœ… Accurate line count estimation via prettyplease formatting
  • βœ… Conditional lib.rs preservation (writes mod.rs instead of overwriting the crate root)
  • βœ… Deduplicated std::collections import handling across split modules

v0.3.0 Highlights:

  • βœ… Macro Analyzer (macro_rules! detection, #[derive] tracking, placement suggestions)
  • βœ… Metrics Dashboard (cyclomatic complexity, HTML/JSON/text reports)
  • βœ… Field access tracking for smarter module splitting
  • βœ… Trait method tracking for coherent trait splitting
  • βœ… No-unwrap policy compliance (production code)
  • βœ… Refactored main.rs into file_analyzer.rs + module_generator.rs
  • βœ… Dependencies upgraded (toml 1.0, rayon 1.11)

v0.2.x Features:

  • βœ… Configuration file support (.splitrs.toml)
  • βœ… Trait implementation separation & trait bound tracking
  • βœ… Type alias resolution & circular dependency detection
  • βœ… Incremental refactoring with merge strategies
  • βœ… Custom naming strategies (snake_case, domain-specific, kebab-case)
  • βœ… Workspace-level refactoring with parallel processing (rayon)
  • βœ… Enhanced error recovery, rollback support
  • βœ… CI/CD templates (GitHub Actions, GitLab CI)
  • βœ… Private helper dependency tracking & glob import analysis
  • βœ… Comprehensive benchmarking suite (Criterion)

Roadmap to v1.0

Current status: 95% production-ready

Next features (v0.4.0+):

  • Macro expansion support (full cargo expand integration)
  • Extended SMT fragment: division, loops, references

Future enhancements (v0.5.0+):

  • Cross-language support exploration
  • AI-assisted refactoring

πŸ“„ License

Licensed under the Apache License, Version 2.0 (LICENSE or http://www.apache.org/licenses/LICENSE-2.0).

πŸ™ Acknowledgments

  • Built with syn for Rust parsing
  • Formatted with prettyplease
  • Developed during the OxiRS refactoring project (32,398 lines refactored)

πŸ“ž Resources & Support

Getting Help

  1. Check the docs: Read the API documentation and examples
  2. Search issues: Check if your question is already answered in issues
  3. Ask questions: Start a discussion
  4. Report bugs: Open an issue with a reproducible example

Made with ❀️ by the OxiRS team | Star ⭐ us on GitHub!

Sponsorship

SplitRS is developed and maintained by COOLJAPAN OU (Team Kitasan).

If you find SplitRS useful, please consider sponsoring the project to support continued development of the Pure Rust ecosystem.

Sponsor

https://github.com/sponsors/cool-japan

Your sponsorship helps us:

  • Maintain and improve the COOLJAPAN ecosystem
  • Keep the entire ecosystem (OxiBLAS, OxiFFT, SciRS2, etc.) 100% Pure Rust
  • Provide long-term support and security updates