SplitRS ๐ฆโ๏ธ
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
synfor accurate Rust parsing - ๐ง Intelligent Method Clustering: Groups related methods using call graph analysis
- ๐ฆ Auto-Generated Imports: Context-aware
usestatements with proper paths - ๐ Visibility Inference: Automatically applies
pub(super),pub(crate), orpub - ๐ 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.tomlsupport 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 aWorkspaceEdit) - Hover showing file metrics (LoC, methods, complexity)
.splitrs.tomlconfig watch with hot reload
๐ฆ Installation
Or build from source:
๐ Quick Start
Basic Usage
# Split a large file into modules
# Preview what will be created (no files written)
# Interactive mode with confirmation
Recommended Usage (with impl block splitting)
Using Configuration Files
Create a .splitrs.toml in your project root:
[]
= 1000
= 500
= true
[]
= "_type"
= "_impl"
[]
= true
= true
Then simply run:
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.tomlmax_lineslimit (source: "splitrs", severity: Information) - โก Code action
Refactor with splitrsto 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..
-- Or manually:
vim..
Helix (languages.toml):
[[]]
= "rust"
= ["rust-analyzer", "splitrs-lsp"]
[]
= "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):
-- Manual setup:
vim..:
require.
-- Custom options:
require.
VSCode โ editors/vscode/
TypeScript extension activating on onLanguage:rust. Sideload:
Configure via settings.json:
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:
# 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:
[]
= 1000 # warn when a file exceeds this many lines
= 300 # warn on oversized impl blocks (if split_impl_blocks = true)
= true
The server hot-reloads .splitrs.toml whenever the file changes.
To use LSP-only (without the full splitrs CLI):
๐ Examples
Example 1: Trait Implementations
SplitRS automatically detects and separates trait implementations:
Input: user.rs
Command:
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 User;
Example 2: Basic Refactoring
Input: connection_pool.rs (1660 lines)
Command:
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:
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
// Output (auto-generated)
// cache_type.rs
use HashMap;
use ;
// cache_insert_group.rs
use Cache;
use HashMap;
๐๏ธ 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 |
Configuration File Options
When using a .splitrs.toml file, you can configure:
[splitrs] section:
max_lines- Maximum lines per modulemax_impl_lines- Maximum lines per impl blocksplit_impl_blocks- Enable impl block splitting
[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 documentationpreserve_comments- Preserve original comments (default:true)format_output- Format with prettyplease (default:true)
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:
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)
--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-purebody 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.
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:
- AST Parsing: Parse input file with
syn - Scope Analysis: Determine organization strategy and visibility
- Method Clustering: Build call graph and cluster related methods
- Type Extraction: Extract types from fields for import generation
- Module Generation: Generate well-organized modules with correct imports
- 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)
# Or with the built-in test runner
# Test on example files
๐ Documentation
API Documentation (docs.rs)
Full API documentation is available at docs.rs/splitrs.
Generate documentation locally:
# Generate and open documentation
# Generate documentation for all features
Module Structure
The codebase is organized into these main modules:
main.rs- CLI interface, file analysis, and module generationconfig.rs- Configuration file parsing and management (.splitrs.toml)method_analyzer.rs- Method dependency analysis and groupingimport_analyzer.rs- Type usage tracking and import generationscope_analyzer.rs- Module scope analysis and visibility inferencedependency_analyzer.rs- Circular dependency detection and graph visualization
Key Types and Traits
Core Types:
FileAnalyzer- Main analyzer for processing Rust filesTypeInfo- Information about a Rust type and its implementationsModule- Represents a generated moduleConfig- Configuration loaded from.splitrs.toml
Analysis Types:
ImplBlockAnalyzer- Analyzes impl blocks for splittingMethodGroup- Groups related methods togetherImportAnalyzer- Tracks type usage and generates importsDependencyGraph- 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
Implemented Features (v0.3.2 - Latest)
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 oversizedstatic/constarray literals across chunk files withconst fncompile-time reconstruction - โ
Test-module splitter (
--split-test-modules): splits multiple#[cfg(test)]blocks into per-moduletests_NAME.rsfiles - โ
Editor integrations shipped in
editors/: Emacs, IntelliJ, Neovim, VSCode - โ
module_generatorrefactored intosrc/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-lspbinary, tower-lsp, diagnostics, code actions, hover, config watch) - โ Batched trait implementations into shared modules to reduce file clutter
- โ
Accurate line count estimation via
prettypleaseformatting - โ
Conditional
lib.rspreservation (writesmod.rsinstead of overwriting the crate root) - โ
Deduplicated
std::collectionsimport 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 expandintegration) - 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
- ๐ API Documentation: docs.rs/splitrs
- ๐ฆ Crate: crates.io/crates/splitrs
- ๐ป Source Code: github.com/cool-japan/splitrs
- ๐ Issue Tracker: github.com/cool-japan/splitrs/issues
- ๐ฌ Discussions: github.com/cool-japan/splitrs/discussions
Getting Help
- Check the docs: Read the API documentation and examples
- Search issues: Check if your question is already answered in issues
- Ask questions: Start a discussion
- 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.
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