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.
- π― 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
- βοΈ 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
cargo install splitrsOr build from source:
git clone https://github.com/cool-japan/splitrs
cd splitrs
cargo build --release# 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/ --interactivesplitrs \
--input src/large_file.rs \
--output src/large_file/ \
--split-impl-blocks \
--max-impl-lines 200Create 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 = trueThen simply run:
splitrs --input src/large_file.rs --output src/large_file/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-runOutput:
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 { /* ... */ }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-blocksOutput: 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)
Get detailed information before refactoring:
splitrs --input examples/trait_impl_example.rs --output /tmp/preview -nOutput:
============================================================
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
============================================================
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
}
}| 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 |
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.
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
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
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 |
SplitRS includes comprehensive tests:
# Run all tests
cargo test
# Test on example files
cargo run -- --input examples/large_struct.rs --output /tmp/test_outputFull 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-depsThe 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
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
β Perfect for:
- Files >1000 lines with large impl blocks
- Monolithic modules that need organization
- Legacy code refactoring
- Improving code maintainability
- 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])
# .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 }}"Contributions are welcome! Please see CONTRIBUTING.md for guidelines.
git clone https://github.com/cool-japan/splitrs
cd splitrs
cargo build
cargo testv0.3.0 Highlights:
- β 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)
Current status: 92% production-ready
Next features (v0.4.0+):
- Macro expansion support
- LSP integration exploration
Future enhancements (v0.5.0+):
- Editor plugins (VS Code, IntelliJ)
- Cross-language support exploration
- AI-assisted refactoring
Licensed under the Apache License, Version 2.0 (LICENSE or http://www.apache.org/licenses/LICENSE-2.0).
- Built with syn for Rust parsing
- Formatted with prettyplease
- Developed during the OxiRS refactoring project (32,398 lines refactored)
- π 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
- 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!