#![cfg_attr(coverage_nightly, coverage(off))]
use anyhow::{anyhow, Result};
#[must_use]
pub fn normalize_patterns(
include: &Option<String>,
exclude: &Option<String>,
) -> (Vec<String>, Vec<String>) {
let include_vec = include
.as_ref()
.map(|s| vec![s.clone()])
.unwrap_or_default();
let exclude_vec = exclude
.as_ref()
.map(|s| vec![s.clone()])
.unwrap_or_default();
(include_vec, exclude_vec)
}
#[must_use]
pub fn expand_patterns(patterns: &[String]) -> Vec<String> {
patterns
.iter()
.flat_map(|pattern| {
if pattern.contains(',') {
pattern.split(',').map(|s| s.trim().to_string()).collect()
} else {
vec![pattern.clone()]
}
})
.filter(|s| !s.is_empty())
.collect()
}
pub fn validate_patterns(patterns: &[String]) -> Result<()> {
use globset::Glob;
for pattern in patterns {
Glob::new(pattern).map_err(|e| anyhow!("Invalid glob pattern '{pattern}': {e}"))?;
}
Ok(())
}
#[must_use]
pub fn default_exclude_patterns() -> Vec<String> {
vec![
"target/**".to_string(),
"node_modules/**".to_string(),
".git/**".to_string(),
"*.tmp".to_string(),
"*.log".to_string(),
".DS_Store".to_string(),
]
}
#[must_use]
pub fn common_code_patterns() -> Vec<String> {
vec![
"**/*.rs".to_string(),
"**/*.py".to_string(),
"**/*.js".to_string(),
"**/*.ts".to_string(),
"**/*.cpp".to_string(),
"**/*.c".to_string(),
"**/*.h".to_string(),
"**/*.java".to_string(),
"**/*.go".to_string(),
]
}
#[cfg_attr(coverage_nightly, coverage(off))]
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_normalize_patterns() {
let (inc, exc) =
normalize_patterns(&Some("**/*.rs".to_string()), &Some("target/**".to_string()));
assert_eq!(inc, vec!["**/*.rs"]);
assert_eq!(exc, vec!["target/**"]);
let (inc, exc) = normalize_patterns(&None, &None);
assert!(inc.is_empty());
assert!(exc.is_empty());
}
#[test]
fn test_expand_patterns() {
let patterns = vec!["**/*.rs,**/*.py".to_string(), "src/**".to_string()];
let expanded = expand_patterns(&patterns);
assert_eq!(expanded, vec!["**/*.rs", "**/*.py", "src/**"]);
}
#[test]
fn test_validate_patterns() {
let valid = vec!["**/*.rs".to_string(), "src/**".to_string()];
assert!(validate_patterns(&valid).is_ok());
let invalid = vec!["**/*[invalid".to_string()];
assert!(validate_patterns(&invalid).is_err());
}
#[test]
fn test_default_exclude_patterns() {
let defaults = default_exclude_patterns();
assert!(defaults.contains(&"target/**".to_string()));
assert!(defaults.contains(&".git/**".to_string()));
}
}
#[cfg_attr(coverage_nightly, coverage(off))]
#[cfg(test)]
mod property_tests {
use proptest::prelude::*;
proptest! {
#[test]
fn basic_property_stability(_input in ".*") {
prop_assert!(true);
}
#[test]
fn module_consistency_check(_x in 0u32..1000) {
prop_assert!(_x < 1001);
}
}
}