**Phase 79 Medium-Priority Refactoring Complete** ## Action 1: Detector/Recorder Separation **New Pure Detection Logic:** - `digitpos_detector.rs` (~350 lines, 7 tests) - Pure detection for A-4 DigitPos pattern - No binding_map dependency - Independently testable - `trim_detector.rs` (~410 lines, 9 tests) - Pure detection for A-3 Trim pattern - No binding_map dependency - Comprehensive test coverage **Simplified Promoters:** - `DigitPosPromoter`: 200+ → 80 lines (60% reduction) - Uses DigitPosDetector for detection - Focuses on orchestration + recording - Removed 6 helper methods - `LoopBodyCarrierPromoter`: 160+ → 70 lines (56% reduction) - Uses TrimDetector for detection - Clean separation of concerns - Removed 3 helper methods ## Action 2: BindingMapProvider Trait **Centralized Feature Gate:** - `binding_map_provider.rs` (~100 lines, 3 tests) - Trait to abstract binding_map access - #[cfg] guards: 10+ locations → 2 locations (80% reduction) - `MirBuilder` implementation - Clean feature-gated access - Single point of control ## Quality Metrics **Code Reduction:** - DigitPosPromoter: 200+ → 80 lines (60%) - LoopBodyCarrierPromoter: 160+ → 70 lines (56%) - Feature guards: 10+ → 2 locations (80%) **Tests:** - All tests passing: 970/970 (100%) - New test coverage: 19+ tests for detectors - No regressions **Design Improvements:** - ✅ Single Responsibility Principle - ✅ Independent unit testing - ✅ Reusable detection logic - ✅ Centralized feature gating 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
108 lines
3.4 KiB
Rust
108 lines
3.4 KiB
Rust
//! BindingMapProvider - Trait to abstract binding_map access
|
|
//!
|
|
//! Centralizes feature-gated binding map access, eliminating scattered
|
|
//! #[cfg] guards across promoters and patterns.
|
|
//!
|
|
//! # Design Philosophy
|
|
//!
|
|
//! This trait follows the **Single Point of Control** principle:
|
|
//! - **Before Phase 79**: `#[cfg(feature = "normalized_dev")]` guards scattered across 10+ locations
|
|
//! - **After Phase 79**: Feature gate centralized in 2 locations (trait + impl)
|
|
//!
|
|
//! # Benefits
|
|
//!
|
|
//! 1. **Maintainability**: Change feature gate logic in one place
|
|
//! 2. **Readability**: Request structs no longer need feature-gated fields
|
|
//! 3. **Testability**: Mock implementations for testing
|
|
//! 4. **Consistency**: Uniform access pattern across all promoters
|
|
//!
|
|
//! # Usage Example
|
|
//!
|
|
//! ```rust,ignore
|
|
//! // Before Phase 79: Scattered #[cfg] guards
|
|
//! #[cfg(feature = "normalized_dev")]
|
|
//! let binding_map = Some(&builder.binding_map);
|
|
//! #[cfg(not(feature = "normalized_dev"))]
|
|
//! let binding_map = None;
|
|
//!
|
|
//! // After Phase 79: Clean trait call
|
|
//! let binding_map = builder.get_binding_map();
|
|
//! ```
|
|
|
|
use crate::mir::binding_id::BindingId;
|
|
use std::collections::BTreeMap;
|
|
|
|
/// Trait to provide optional binding_map access (dev-only).
|
|
///
|
|
/// This trait abstracts the feature-gated access to binding_map,
|
|
/// allowing code to request binding information without knowing
|
|
/// whether the feature is enabled.
|
|
pub trait BindingMapProvider {
|
|
/// Get binding map if available (dev-only).
|
|
///
|
|
/// Returns Some(&BTreeMap) when `normalized_dev` feature is enabled,
|
|
/// None otherwise.
|
|
fn get_binding_map(&self) -> Option<&BTreeMap<String, BindingId>>;
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use super::*;
|
|
|
|
// Mock implementation for testing
|
|
struct MockBuilder {
|
|
#[cfg(feature = "normalized_dev")]
|
|
binding_map: BTreeMap<String, BindingId>,
|
|
}
|
|
|
|
impl BindingMapProvider for MockBuilder {
|
|
#[cfg(feature = "normalized_dev")]
|
|
fn get_binding_map(&self) -> Option<&BTreeMap<String, BindingId>> {
|
|
Some(&self.binding_map)
|
|
}
|
|
|
|
#[cfg(not(feature = "normalized_dev"))]
|
|
fn get_binding_map(&self) -> Option<&BTreeMap<String, BindingId>> {
|
|
None
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
#[cfg(feature = "normalized_dev")]
|
|
fn test_binding_map_provider_dev() {
|
|
let mut map = BTreeMap::new();
|
|
map.insert("x".to_string(), BindingId(1));
|
|
map.insert("y".to_string(), BindingId(2));
|
|
|
|
let builder = MockBuilder { binding_map: map };
|
|
|
|
let result = builder.get_binding_map();
|
|
assert!(result.is_some());
|
|
assert_eq!(result.unwrap().len(), 2);
|
|
}
|
|
|
|
#[test]
|
|
#[cfg(not(feature = "normalized_dev"))]
|
|
fn test_binding_map_provider_non_dev() {
|
|
let builder = MockBuilder {};
|
|
|
|
let result = builder.get_binding_map();
|
|
assert!(result.is_none());
|
|
}
|
|
|
|
#[test]
|
|
fn test_trait_object_compatibility() {
|
|
// Verify trait can be used as trait object
|
|
#[cfg(feature = "normalized_dev")]
|
|
let builder: Box<dyn BindingMapProvider> = Box::new(MockBuilder {
|
|
binding_map: BTreeMap::new(),
|
|
});
|
|
|
|
#[cfg(not(feature = "normalized_dev"))]
|
|
let builder: Box<dyn BindingMapProvider> = Box::new(MockBuilder {});
|
|
|
|
let _result = builder.get_binding_map();
|
|
// Test just verifies compilation and trait object usage
|
|
}
|
|
}
|