use std::collections::BTreeSet;
use std::path::{Path, PathBuf};
use crate::domain::config::{Agent, Config, FileFilter, RelevanceMode, Rule};
use crate::domain::ignore;
use crate::errors::{Error, Result};
use crate::io::files;
pub fn known_rules(config: &Config) -> BTreeSet<&str> {
config.rules.iter().map(|r| r.name.as_str()).collect()
}
pub fn target_files(
cwd: &Path,
config: &Config,
cli_files: &[PathBuf],
) -> Result<BTreeSet<PathBuf>> {
let mut out: BTreeSet<PathBuf> = BTreeSet::new();
for rule in &config.rules {
if matches!(rule.relevance_mode(), RelevanceMode::Never) {
continue;
}
let agent_name = rule.agent.clone().unwrap_or_else(|| "default".to_string());
let agent = config.agent_or_default(&agent_name);
for f in resolve_files(cwd, rule, &agent, cli_files, &config.files)? {
out.insert(f);
}
}
Ok(out)
}
pub fn resolve_files(
cwd: &Path,
rule: &Rule,
agent: &Agent,
cli_files: &[PathBuf],
global: &FileFilter,
) -> Result<Vec<PathBuf>> {
if let Some(f) = &rule.files {
return files::resolve(cwd, f);
}
if let Some(f) = &agent.files {
return files::resolve(cwd, f);
}
if !cli_files.is_empty() {
return Ok(cli_files.to_vec());
}
files::resolve(cwd, global)
}
pub fn check(cwd: &Path, targets: &BTreeSet<PathBuf>, known: &BTreeSet<&str>) -> Result<()> {
let mut problems: Vec<String> = Vec::new();
for rel in targets {
let Some(text) = files::read_text(cwd, rel)? else {
continue;
};
for p in ignore::validate(&text, known) {
problems.push(format!(
" {}:{}: {}",
files::to_slash(rel),
p.line,
p.message
));
}
}
if problems.is_empty() {
Ok(())
} else {
Err(Error::IgnoreDirective(problems.join("\n")))
}
}