mirror of
https://github.com/astral-sh/ruff.git
synced 2025-10-02 22:55:08 +00:00
Support negated patterns in [extend-]per-file-ignores (#10852)
Fixes #3172 ## Summary Allow prefixing [extend-]per-file-ignores patterns with `!` to negate the pattern; listed rules / prefixes will be ignored in all files that don't match the pattern. ## Test Plan Added tests for the feature. Rendered docs and checked rendered output.
This commit is contained in:
parent
42d52ebbec
commit
02e88fdbb1
5 changed files with 130 additions and 19 deletions
|
@ -9,24 +9,37 @@ use crate::registry::RuleSet;
|
|||
/// Create a set with codes matching the pattern/code pairs.
|
||||
pub(crate) fn ignores_from_path(
|
||||
path: &Path,
|
||||
pattern_code_pairs: &[(GlobMatcher, GlobMatcher, RuleSet)],
|
||||
pattern_code_pairs: &[(GlobMatcher, GlobMatcher, bool, RuleSet)],
|
||||
) -> RuleSet {
|
||||
let file_name = path.file_name().expect("Unable to parse filename");
|
||||
pattern_code_pairs
|
||||
.iter()
|
||||
.filter_map(|(absolute, basename, rules)| {
|
||||
.filter_map(|(absolute, basename, negated, rules)| {
|
||||
if basename.is_match(file_name) {
|
||||
if *negated { None } else {
|
||||
debug!(
|
||||
"Adding per-file ignores for {:?} due to basename match on {:?}: {:?}",
|
||||
path,
|
||||
basename.glob().regex(),
|
||||
rules
|
||||
);
|
||||
Some(rules)
|
||||
}
|
||||
} else if absolute.is_match(path) {
|
||||
if *negated { None } else {
|
||||
debug!(
|
||||
"Adding per-file ignores for {:?} due to absolute match on {:?}: {:?}",
|
||||
path,
|
||||
absolute.glob().regex(),
|
||||
rules
|
||||
);
|
||||
Some(rules)
|
||||
}
|
||||
} else if *negated {
|
||||
debug!(
|
||||
"Adding per-file ignores for {:?} due to basename match on {:?}: {:?}",
|
||||
"Adding per-file ignores for {:?} due to negated pattern matching neither {:?} nor {:?}: {:?}",
|
||||
path,
|
||||
basename.glob().regex(),
|
||||
rules
|
||||
);
|
||||
Some(rules)
|
||||
} else if absolute.is_match(path) {
|
||||
debug!(
|
||||
"Adding per-file ignores for {:?} due to absolute match on {:?}: {:?}",
|
||||
path,
|
||||
absolute.glob().regex(),
|
||||
rules
|
||||
);
|
||||
|
|
|
@ -296,13 +296,22 @@ impl CacheKey for FilePatternSet {
|
|||
pub struct PerFileIgnore {
|
||||
pub(crate) basename: String,
|
||||
pub(crate) absolute: PathBuf,
|
||||
pub(crate) negated: bool,
|
||||
pub(crate) rules: RuleSet,
|
||||
}
|
||||
|
||||
impl PerFileIgnore {
|
||||
pub fn new(pattern: String, prefixes: &[RuleSelector], project_root: Option<&Path>) -> Self {
|
||||
pub fn new(
|
||||
mut pattern: String,
|
||||
prefixes: &[RuleSelector],
|
||||
project_root: Option<&Path>,
|
||||
) -> Self {
|
||||
// Rules in preview are included here even if preview mode is disabled; it's safe to ignore disabled rules
|
||||
let rules: RuleSet = prefixes.iter().flat_map(RuleSelector::all_rules).collect();
|
||||
let negated = pattern.starts_with('!');
|
||||
if negated {
|
||||
pattern.drain(..1);
|
||||
}
|
||||
let path = Path::new(&pattern);
|
||||
let absolute = match project_root {
|
||||
Some(project_root) => fs::normalize_path_to(path, project_root),
|
||||
|
@ -312,6 +321,7 @@ impl PerFileIgnore {
|
|||
Self {
|
||||
basename: pattern,
|
||||
absolute,
|
||||
negated,
|
||||
rules,
|
||||
}
|
||||
}
|
||||
|
@ -593,7 +603,7 @@ pub type IdentifierPattern = glob::Pattern;
|
|||
#[derive(Debug, Clone, CacheKey, Default)]
|
||||
pub struct PerFileIgnores {
|
||||
// Ordered as (absolute path matcher, basename matcher, rules)
|
||||
ignores: Vec<(GlobMatcher, GlobMatcher, RuleSet)>,
|
||||
ignores: Vec<(GlobMatcher, GlobMatcher, bool, RuleSet)>,
|
||||
}
|
||||
|
||||
impl PerFileIgnores {
|
||||
|
@ -609,7 +619,12 @@ impl PerFileIgnores {
|
|||
// Construct basename matcher.
|
||||
let basename = Glob::new(&per_file_ignore.basename)?.compile_matcher();
|
||||
|
||||
Ok((absolute, basename, per_file_ignore.rules))
|
||||
Ok((
|
||||
absolute,
|
||||
basename,
|
||||
per_file_ignore.negated,
|
||||
per_file_ignore.rules,
|
||||
))
|
||||
})
|
||||
.collect();
|
||||
Ok(Self { ignores: ignores? })
|
||||
|
@ -622,10 +637,10 @@ impl Display for PerFileIgnores {
|
|||
write!(f, "{{}}")?;
|
||||
} else {
|
||||
writeln!(f, "{{")?;
|
||||
for (absolute, basename, rules) in &self.ignores {
|
||||
for (absolute, basename, negated, rules) in &self.ignores {
|
||||
writeln!(
|
||||
f,
|
||||
"\t{{ absolute = {absolute:#?}, basename = {basename:#?}, rules = {rules} }},"
|
||||
"\t{{ absolute = {absolute:#?}, basename = {basename:#?}, negated = {negated:#?}, rules = {rules} }},"
|
||||
)?;
|
||||
}
|
||||
write!(f, "}}")?;
|
||||
|
@ -635,7 +650,7 @@ impl Display for PerFileIgnores {
|
|||
}
|
||||
|
||||
impl Deref for PerFileIgnores {
|
||||
type Target = Vec<(GlobMatcher, GlobMatcher, RuleSet)>;
|
||||
type Target = Vec<(GlobMatcher, GlobMatcher, bool, RuleSet)>;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.ignores
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue