#![cfg_attr(coverage_nightly, coverage(off))]
use anyhow::Result;
use crossbeam_channel;
#[cfg(feature = "watch")]
use notify::{Config, Event, EventKind, RecommendedWatcher, RecursiveMode, Watcher};
use parking_lot::RwLock as ParkingLotRwLock;
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
use std::path::{Path, PathBuf};
use std::sync::Arc;
use std::time::{Duration, SystemTime};
use tracing::info;
use crate::unified_quality::enhanced_parser::EnhancedParser;
use crate::unified_quality::events::QualityEvent;
use crate::unified_quality::metrics::Metrics;
#[cfg(feature = "watch")]
type WatcherType = RecommendedWatcher;
#[cfg(not(feature = "watch"))]
type WatcherType = ();
#[allow(dead_code)]
pub struct QualityMonitor {
watcher: Arc<ParkingLotRwLock<Option<WatcherType>>>,
parser: Arc<std::sync::Mutex<EnhancedParser>>,
metrics: Arc<dashmap::DashMap<PathBuf, Metrics>>,
events: crossbeam_channel::Sender<QualityEvent>,
config: MonitorConfig,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct MonitorConfig {
pub update_interval: Duration,
pub complexity_threshold: u32,
pub watch_patterns: Vec<String>,
pub debounce_interval: Duration,
pub max_batch_size: usize,
pub incremental_parsing: bool,
pub cache_ast: bool,
}
impl Default for MonitorConfig {
fn default() -> Self {
Self {
update_interval: Duration::from_secs(5),
complexity_threshold: 20,
watch_patterns: vec![
"**/*.rs".to_string(),
"**/*.py".to_string(),
"**/*.js".to_string(),
"**/*.ts".to_string(),
],
debounce_interval: Duration::from_millis(500),
max_batch_size: 50,
incremental_parsing: true,
cache_ast: true,
}
}
}
#[derive(Debug, Clone)]
pub struct FileChange {
pub path: PathBuf,
pub content: String,
pub old_tree: Option<String>,
pub timestamp: SystemTime,
}
include!("foundation_impl.rs");
pub use dashmap::DashMap;
#[cfg_attr(coverage_nightly, coverage(off))]
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_monitor_config_default() {
let config = MonitorConfig::default();
assert_eq!(config.complexity_threshold, 20);
assert!(config.incremental_parsing);
assert!(config.cache_ast);
}
#[test]
fn test_should_analyze() {
let patterns = vec!["**/*.rs".to_string(), "**/*.py".to_string()];
assert!(QualityMonitor::should_analyze(
Path::new("src/main.rs"),
&patterns
));
assert!(QualityMonitor::should_analyze(
Path::new("test.py"),
&patterns
));
assert!(!QualityMonitor::should_analyze(
Path::new("README.md"),
&patterns
));
}
#[test]
fn test_enhanced_parser_integration() {
let mut parser = EnhancedParser::new();
let path = PathBuf::from("test.rs");
let code = "fn main() { if true { } }";
let metrics = parser
.parse_incremental(&path, code)
.expect("internal error");
assert!(metrics.complexity > 0);
assert!(metrics.functions > 0);
}
#[tokio::test]
async fn test_quality_monitor_creation() {
let config = MonitorConfig::default();
let monitor = QualityMonitor::new(config).expect("internal error");
assert_eq!(monitor.metrics.len(), 0);
}
}
include!("foundation_property_tests.rs");
include!("foundation_coverage_tests.rs");
include!("foundation_coverage_tests_part2.rs");