use super::{ConfigAnalysis, ConfigType, PerformanceIssue};
use crate::config::{aliaser, deduplicator, nondeterminism, quoter};
use std::path::PathBuf;
pub fn analyze_config(source: &str, file_path: PathBuf) -> ConfigAnalysis {
let config_type = ConfigType::from_path(&file_path);
let line_count = source.lines().count();
let mut issues = Vec::new();
let path_entries = deduplicator::analyze_path_entries(source);
let path_issues = deduplicator::detect_duplicate_paths(&path_entries);
issues.extend(path_issues);
let unquoted_vars = quoter::analyze_unquoted_variables(source);
let quote_issues = quoter::detect_unquoted_variables(&unquoted_vars);
issues.extend(quote_issues);
let aliases = aliaser::analyze_aliases(source);
let alias_issues = aliaser::detect_duplicate_aliases(&aliases);
issues.extend(alias_issues);
let nondeterministic_constructs = nondeterminism::analyze_nondeterminism(source);
let nondeterminism_issues = nondeterminism::detect_nondeterminism(&nondeterministic_constructs);
issues.extend(nondeterminism_issues);
let complexity_score = calculate_complexity(source);
let performance_issues = detect_performance_issues(source);
ConfigAnalysis {
file_path,
config_type,
line_count,
complexity_score,
issues,
path_entries,
performance_issues,
}
}
fn calculate_complexity(source: &str) -> u8 {
let line_count = source.lines().count();
if line_count < 50 {
3
} else if line_count < 100 {
5
} else if line_count < 200 {
7
} else {
9
}
}
fn detect_performance_issues(source: &str) -> Vec<PerformanceIssue> {
let mut issues = Vec::new();
for (line_num, line) in source.lines().enumerate() {
let line_num = line_num + 1;
if line.contains("eval")
&& (line.contains("rbenv") || line.contains("pyenv") || line.contains("nodenv"))
{
let command = line.trim().to_string();
issues.push(PerformanceIssue {
line: line_num,
command,
estimated_cost_ms: 150, suggestion: "Consider lazy-loading this version manager".to_string(),
});
}
}
issues
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_analyze_config_basic() {
let source = r#"export PATH="/usr/local/bin:$PATH"
export EDITOR="vim"
alias ll='ls -la'"#;
let path = PathBuf::from("/home/user/.bashrc");
let analysis = analyze_config(source, path);
assert_eq!(analysis.config_type, ConfigType::Bashrc);
assert_eq!(analysis.line_count, 3);
assert_eq!(analysis.path_entries.len(), 1);
assert_eq!(analysis.issues.len(), 0);
}
#[test]
fn test_analyze_config_with_duplicates() {
let source = r#"export PATH="/usr/local/bin:$PATH"
export PATH="/opt/homebrew/bin:$PATH"
export PATH="/usr/local/bin:$PATH""#;
let path = PathBuf::from("/home/user/.bashrc");
let analysis = analyze_config(source, path);
assert_eq!(analysis.path_entries.len(), 3);
assert_eq!(analysis.issues.len(), 1); assert_eq!(analysis.issues[0].rule_id, "CONFIG-001");
}
#[test]
fn test_detect_performance_issues() {
let source = r#"eval "$(rbenv init -)""#;
let issues = detect_performance_issues(source);
assert_eq!(issues.len(), 1);
assert_eq!(issues[0].line, 1);
assert!(issues[0].command.contains("rbenv"));
}
}