src/
├── analysis/ # Code analysis functionality
│ ├── crates.rs # Workspace/crate discovery
│ ├── imports.rs # Import analysis & categorization
│ ├── exports.rs # Export analysis & merging
│ ├── exports_analyzer.rs # Export scanning utility
│ └── macro_scanning.rs # Macro export detection
├── syntax/ # AST manipulation & code generation
│ ├── parser.rs # Import parsing from files
│ ├── visitor.rs # AST visitor for pub use extraction
│ ├── generator.rs # Pub use statement generation
│ ├── transformer.rs # Import replacement strategies
│ └── item_info.rs # Generic item information trait
├── core/ # Core business logic
│ ├── api.rs # High-level API interface
│ └── engine/ # Refactoring execution engine
│ └── refactor.rs
├── io/ # File operations
├── common/ # Shared utilities
└── cli/ # Command-line interface
Duplicated Logic Locations:
syntax/parser.rs:ImportVisitor::extract_use_info_recursive()syntax/visitor.rs:extract_use_items()analysis/exports.rs:ExistingExportParser::extract_exported_items()analysis/mod.rs:extract_exported_items_from_use_tree()syntax/generator.rs:collect_existing_pub_uses()(different function but similar traversal)
Current Implementation Issues:
- 5 different functions performing nearly identical
syn::UseTreerecursive traversal - Each has slightly different return types and collection strategies
- No shared abstraction for use tree navigation
- Different handling of edge cases (aliases, globs, groups)
Duplicated Logic Locations:
analysis/exports_analyzer.rs:ExportAnalyzer::collect_existing_exports()analysis/exports.rs:ExistingExportParser::parse_existing_exports()syntax/generator.rs:collect_existing_pub_uses()core/engine/refactor.rs:RefactorEngine::update_source_lib_rs()(inline logic)
Current Implementation Issues:
- Multiple approaches to scanning syntax trees for public items
- Different strategies for handling conditional compilation
- Inconsistent treatment of macro exports vs regular exports
- Redundant file reading and AST parsing
Duplicated Logic Locations:
syntax/visitor.rs:merge_pub_uses()syntax/generator.rs:generate_nested_pub_use()+build_nested_structure()analysis/exports.rs:ExistingExportParser::merge_exports()
Current Implementation Issues:
- Three different approaches to merging existing and new pub use statements
- Different nesting strategies and output formats
- Inconsistent handling of path normalization
- No unified approach to conflict resolution
Well-Factored Areas:
syntax/transformer.rssuccessfully uses strategy pattern- Clear separation between
CrossCrateReplacementStrategyandSelfCrateReplacementStrategy - Unified
replace_imports_with_strategy()function
- Heavy reliance on string splitting and prefix matching
- Error-prone crate name normalization (hyphens vs underscores)
- No structured representation of import paths
- Hardcoded
lib.rsassumptions in multiple places - Limited to single-file export consolidation
- No support for distributed pub use statements
- Multiple file reads and syntax tree parsing for the same files
- No caching or memoization of parsed ASTs
- Wasteful re-parsing during analysis phases
Both modes share the following core operations:
- Import Discovery: Scan target crate files for relevant imports
- Export Analysis: Analyze source crate for existing exports
- Conflict Resolution: Determine which items need new pub use statements
- Pub Use Generation: Create consolidated export statements
- Import Replacement: Replace imports with simpler forms
- Compilation Validation: Ensure changes don't break builds
Key Differences:
- Scope: Cross-crate operates between two crates, self-crate within one
- Target Format: Cross-crate →
use source::*, self-crate → direct access - Import Sources: Cross-crate scans target crate, self-crate scans source crate
pub struct UseTreeNavigator;
impl UseTreeNavigator {
pub fn extract_items<T>(&self, tree: &UseTree, collector: &mut T)
where T: UseTreeItemCollector;
pub fn find_patterns<P>(&self, tree: &UseTree, pattern: P) -> Vec<UseTreeMatch>
where P: UseTreePattern;
}
pub trait UseTreeItemCollector {
fn collect_name(&mut self, name: &str, path: &[String]);
fn collect_glob(&mut self, path: &[String]);
fn collect_rename(&mut self, original: &str, renamed: &str, path: &[String]);
}#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct ImportPath {
crate_name: String,
segments: Vec<String>,
final_item: String,
}
impl ImportPath {
pub fn parse(path_str: &str) -> Result<Self>;
pub fn normalize_crate_name(&mut self);
pub fn relative_to_crate(&self) -> String;
pub fn is_glob(&self) -> bool;
}pub struct AstManager {
cache: HashMap<PathBuf, (SystemTime, syn::File)>,
}
impl AstManager {
pub fn get_or_parse(&mut self, path: &Path) -> Result<&syn::File>;
pub fn invalidate(&mut self, path: &Path);
pub fn get_cached_exports(&mut self, path: &Path) -> Result<ExportInfo>;
}pub struct RefactorContext {
pub mode: RefactorMode,
pub source_crate: CrateInfo,
pub target_crate: Option<CrateInfo>,
pub workspace_root: PathBuf,
pub ast_manager: AstManager,
}
pub enum RefactorMode {
CrossCrate { target_crate: CrateInfo },
SelfCrate,
}pub trait RefactorAnalyzer {
fn analyze(&self, context: &RefactorContext) -> Result<AnalysisResult>;
}
pub struct AnalysisPipeline {
analyzers: Vec<Box<dyn RefactorAnalyzer>>,
}
impl AnalysisPipeline {
pub fn new() -> Self;
pub fn add_analyzer<A: RefactorAnalyzer + 'static>(mut self, analyzer: A) -> Self;
pub fn run(&self, context: &RefactorContext) -> Result<CombinedAnalysis>;
}src/
├── core/ # Core abstractions & business logic
│ ├── context.rs # RefactorContext and mode definitions
│ ├── path.rs # ImportPath structured representation
│ ├── ast_manager.rs # Cached AST parsing and management
│ └── pipeline.rs # Analysis pipeline orchestration
├── analysis/ # Specialized analyzers (pluggable)
│ ├── import_analyzer.rs # Import discovery and categorization
│ ├── export_analyzer.rs # Export scanning and conflict detection
│ ├── usage_analyzer.rs # Usage pattern analysis
│ └── dependency_analyzer.rs # Crate dependency analysis
├── syntax/ # AST manipulation primitives
│ ├── navigator.rs # Unified UseTree navigation
│ ├── extractor.rs # Generic item extraction
│ ├── generator.rs # Pub use statement generation
│ └── transformer.rs # Import replacement (existing, good)
├── strategies/ # Refactoring strategy implementations
│ ├── cross_crate.rs # Cross-crate refactoring logic
│ ├── self_crate.rs # Self-crate refactoring logic
│ └── common.rs # Shared strategy utilities
├── execution/ # Refactoring execution
│ ├── planner.rs # Refactoring plan generation
│ ├── executor.rs # Plan execution with validation
│ └── validation.rs # Compilation and correctness checks
└── api/ # Public interfaces
├── refactor_api.rs # High-level refactoring API
└── analysis_api.rs # Analysis-only API
- Single
AstManagerwith intelligent caching - Parse each file exactly once per refactoring session
- Invalidation based on file modification times
- Memory-efficient caching with LRU eviction
- Single
UseTreeNavigatorwith visitor pattern - Pluggable collectors for different extraction needs
- Consistent handling of all use tree variants
- Comprehensive test coverage for edge cases
- Replace string manipulation with
ImportPathstruct - Proper crate name normalization
- Path canonicalization and comparison
- Support for complex path patterns
- Generic
RefactorContextcontaining all necessary state - Mode-specific strategies inheriting from common base
- Pluggable analyzer pipeline for extensibility
- Clear separation of analysis vs execution phases
- Structured error types with context
- Graceful degradation for parsing failures
- Better user feedback for common issues
- Recovery strategies for partial failures
- Implement
ImportPathand path utilities - Create
AstManagerwith caching - Build
UseTreeNavigatorabstraction - Add comprehensive tests
- Refactor export analysis to use new abstractions
- Consolidate import discovery logic
- Create pluggable analyzer interfaces
- Migrate existing analyzers
- Extract common refactoring logic
- Parameterize cross-crate vs self-crate differences
- Implement unified execution pipeline
- Add validation framework
- Simplify public API surface
- Improve error messages and user experience
- Add configuration options
- Performance optimization
- ~60% reduction in duplicated logic
- Improved maintainability through clear abstractions
- Better test coverage with focused unit tests
- Enhanced extensibility for future features
- Faster execution through AST caching
- Reduced memory usage with intelligent cache eviction
- Parallel analysis potential with improved architecture
- Better error handling with structured error types
- More reliable path handling with structured representations
- Comprehensive edge case coverage through unified processing
- Clearer module boundaries and responsibilities
- Easier debugging with better abstractions
- Simpler testing through dependency injection
- Better documentation with focused APIs
- HIGH: Use tree navigation unification (eliminates most duplication)
- HIGH: AST caching system (major performance improvement)
- MEDIUM: Structured path handling (reduces error-prone string manipulation)
- MEDIUM: Analysis pipeline refactoring (improves extensibility)
- LOW: Strategy pattern improvements (already well-factored)
This architecture would transform the current codebase from a collection of similar but distinct implementations into a cohesive, extensible framework suitable for complex refactoring operations while maintaining the existing feature set.