From 90c15aca1cf1aa6e9bf1d69d4627f705042f8017 Mon Sep 17 00:00:00 2001 From: Martin Pool Date: Thu, 2 Jan 2025 17:22:41 -0800 Subject: [PATCH] Split out Options::allows_source_file_path and allows_mutant --- src/options.rs | 24 +++++++++++++++++++++++- src/visit.rs | 26 +++++++++----------------- 2 files changed, 32 insertions(+), 18 deletions(-) diff --git a/src/options.rs b/src/options.rs index 8ee391b4..ebfdf697 100644 --- a/src/options.rs +++ b/src/options.rs @@ -15,7 +15,7 @@ use std::env; use std::ffi::OsString; use std::time::Duration; -use camino::Utf8PathBuf; +use camino::{Utf8Path, Utf8PathBuf}; use globset::GlobSet; use regex::RegexSet; use serde::Deserialize; @@ -25,6 +25,7 @@ use tracing::warn; use crate::config::Config; use crate::glob::build_glob_set; +use crate::mutate::Mutant; use crate::{Args, BaselineStrategy, Context, Phase, Result, ValueEnum}; /// Options for mutation testing, based on both command-line arguments and the @@ -368,6 +369,27 @@ impl Options { }) .collect() } + + /// True if the options allow mutants to be generated from the given path. + /// + /// That is: it matches the examine globset (if specified) and does not match the exclude globset + /// (if specified). + pub fn allows_source_file_path(&self, path: &Utf8Path) -> bool { + self.examine_globset + .as_ref() + .map_or(true, |g| g.is_match(path)) + && !self + .exclude_globset + .as_ref() + .map_or(false, |g| g.is_match(path)) + } + + /// True if the options allow this mutant to be tested. + pub fn allows_mutant(&self, mutant: &Mutant) -> bool { + let name = mutant.name(true); + (self.examine_names.is_empty() || self.examine_names.is_match(&name)) + && (self.exclude_names.is_empty() || !self.exclude_names.is_match(&name)) + } } /// If the first slices is non-empty, return that, otherwise the second. diff --git a/src/visit.rs b/src/visit.rs index 00165171..c89ef4ce 100644 --- a/src/visit.rs +++ b/src/visit.rs @@ -105,6 +105,12 @@ fn walk_package( console.walk_tree_update(files.len(), mutants.len()); check_interrupted()?; let (mut file_mutants, external_mods) = walk_file(&source_file, error_exprs, options)?; + // TODO: It would be better not to spend time generating mutants from + // files that are not going to be visited later. However, we probably do + // still want to walk them to find modules that are referenced by them. + // since otherwise it could be pretty confusing that lower files are not + // visited. + // // We'll still walk down through files that don't match globs, so that // we have a chance to find modules underneath them. However, we won't // collect any mutants from them, and they don't count as "seen" for @@ -114,27 +120,13 @@ fn walk_package( filename_queue.push_back((mod_path, false)); } } - let path = &source_file.tree_relative_path; - if let Some(examine_globset) = &options.examine_globset { - if !examine_globset.is_match(path) { - trace!("{path:?} does not match examine globset"); - continue; - } - } - if let Some(exclude_globset) = &options.exclude_globset { - if exclude_globset.is_match(path) { - trace!("{path:?} excluded by globset"); - continue; - } + if !options.allows_source_file_path(&source_file.tree_relative_path) { + continue; } + file_mutants.retain(|m| options.allows_mutant(m)); mutants.append(&mut file_mutants); files.push(source_file); } - mutants.retain(|m| { - let name = m.name(true); - (options.examine_names.is_empty() || options.examine_names.is_match(&name)) - && (options.exclude_names.is_empty() || !options.exclude_names.is_match(&name)) - }); Ok(()) }