mirror of
https://github.com/astral-sh/ruff.git
synced 2025-09-26 20:09:22 +00:00
Implement --extend-fixable
option (#4297)
This commit is contained in:
parent
2e2ba2cb16
commit
15cb21a6f4
7 changed files with 114 additions and 12 deletions
|
@ -32,6 +32,7 @@ pub struct RuleSelection {
|
|||
pub extend_select: Vec<RuleSelector>,
|
||||
pub fixable: Option<Vec<RuleSelector>>,
|
||||
pub unfixable: Vec<RuleSelector>,
|
||||
pub extend_fixable: Vec<RuleSelector>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Default)]
|
||||
|
@ -101,7 +102,13 @@ impl Configuration {
|
|||
.collect(),
|
||||
extend_select: options.extend_select.unwrap_or_default(),
|
||||
fixable: options.fixable,
|
||||
unfixable: options.unfixable.unwrap_or_default(),
|
||||
unfixable: options
|
||||
.unfixable
|
||||
.into_iter()
|
||||
.flatten()
|
||||
.chain(options.extend_unfixable.into_iter().flatten())
|
||||
.collect(),
|
||||
extend_fixable: options.extend_fixable.unwrap_or_default(),
|
||||
}],
|
||||
allowed_confusables: options.allowed_confusables,
|
||||
builtins: options.builtins,
|
||||
|
|
|
@ -258,16 +258,11 @@ impl From<&Configuration> for RuleTable {
|
|||
// across config files (which otherwise wouldn't be possible since ruff
|
||||
// only has `extended` but no `extended-by`).
|
||||
let mut carryover_ignores: Option<&[RuleSelector]> = None;
|
||||
let mut carryover_unfixables: Option<&[RuleSelector]> = None;
|
||||
|
||||
let mut redirects = FxHashMap::default();
|
||||
|
||||
for selection in &config.rule_selections {
|
||||
// We do not have an extend-fixable option, so fixable and unfixable
|
||||
// selectors can simply be applied directly to fixable_set.
|
||||
if selection.fixable.is_some() {
|
||||
fixable_set.clear();
|
||||
}
|
||||
|
||||
// If a selection only specifies extend-select we cannot directly
|
||||
// apply its rule selectors to the select_set because we firstly have
|
||||
// to resolve the effectively selected rules within the current rule selection
|
||||
|
@ -276,10 +271,13 @@ impl From<&Configuration> for RuleTable {
|
|||
// We do this via the following HashMap where the bool indicates
|
||||
// whether to enable or disable the given rule.
|
||||
let mut select_map_updates: FxHashMap<Rule, bool> = FxHashMap::default();
|
||||
let mut fixable_map_updates: FxHashMap<Rule, bool> = FxHashMap::default();
|
||||
|
||||
let carriedover_ignores = carryover_ignores.take();
|
||||
let carriedover_unfixables = carryover_unfixables.take();
|
||||
|
||||
for spec in Specificity::iter() {
|
||||
// Iterate over rule selectors in order of specificity.
|
||||
for selector in selection
|
||||
.select
|
||||
.iter()
|
||||
|
@ -301,17 +299,26 @@ impl From<&Configuration> for RuleTable {
|
|||
select_map_updates.insert(rule, false);
|
||||
}
|
||||
}
|
||||
if let Some(fixable) = &selection.fixable {
|
||||
fixable_set
|
||||
.extend(fixable.iter().filter(|s| s.specificity() == spec).flatten());
|
||||
// Apply the same logic to `fixable` and `unfixable`.
|
||||
for selector in selection
|
||||
.fixable
|
||||
.iter()
|
||||
.flatten()
|
||||
.chain(selection.extend_fixable.iter())
|
||||
.filter(|s| s.specificity() == spec)
|
||||
{
|
||||
for rule in selector {
|
||||
fixable_map_updates.insert(rule, true);
|
||||
}
|
||||
}
|
||||
for selector in selection
|
||||
.unfixable
|
||||
.iter()
|
||||
.chain(carriedover_unfixables.into_iter().flatten())
|
||||
.filter(|s| s.specificity() == spec)
|
||||
{
|
||||
for rule in selector {
|
||||
fixable_set.remove(rule);
|
||||
fixable_map_updates.insert(rule, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -341,6 +348,29 @@ impl From<&Configuration> for RuleTable {
|
|||
}
|
||||
}
|
||||
|
||||
// Apply the same logic to `fixable` and `unfixable`.
|
||||
if let Some(fixable) = &selection.fixable {
|
||||
fixable_set = fixable_map_updates
|
||||
.into_iter()
|
||||
.filter_map(|(rule, enabled)| enabled.then_some(rule))
|
||||
.collect();
|
||||
|
||||
if fixable.is_empty()
|
||||
&& selection.extend_fixable.is_empty()
|
||||
&& !selection.unfixable.is_empty()
|
||||
{
|
||||
carryover_unfixables = Some(&selection.unfixable);
|
||||
}
|
||||
} else {
|
||||
for (rule, enabled) in fixable_map_updates {
|
||||
if enabled {
|
||||
fixable_set.insert(rule);
|
||||
} else {
|
||||
fixable_set.remove(rule);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// We insert redirects into the hashmap so that we
|
||||
// can warn the users about remapped rule codes.
|
||||
for selector in selection
|
||||
|
@ -351,6 +381,7 @@ impl From<&Configuration> for RuleTable {
|
|||
.chain(selection.ignore.iter())
|
||||
.chain(selection.extend_select.iter())
|
||||
.chain(selection.unfixable.iter())
|
||||
.chain(selection.extend_fixable.iter())
|
||||
{
|
||||
if let RuleSelector::Prefix {
|
||||
prefix,
|
||||
|
|
|
@ -175,6 +175,24 @@ pub struct Options {
|
|||
/// A list of rule codes or prefixes to enable, in addition to those
|
||||
/// specified by `select`.
|
||||
pub extend_select: Option<Vec<RuleSelector>>,
|
||||
#[option(
|
||||
default = r#"[]"#,
|
||||
value_type = "list[RuleSelector]",
|
||||
example = r#"
|
||||
# Enable autofix for flake8-bugbear (`B`), on top of any rules specified by `fixable`.
|
||||
extend-fixable = ["B"]
|
||||
"#
|
||||
)]
|
||||
/// A list of rule codes or prefixes to consider autofixable, in addition to those
|
||||
/// specified by `fixable`.
|
||||
pub extend_fixable: Option<Vec<RuleSelector>>,
|
||||
/// A list of rule codes or prefixes to consider non-auto-fixable, in addition to those
|
||||
/// specified by `unfixable`.
|
||||
///
|
||||
/// This option has been **deprecated** in favor of `unfixable` since its usage is now
|
||||
/// interchangeable with `unfixable`.
|
||||
#[schemars(skip)]
|
||||
pub extend_unfixable: Option<Vec<RuleSelector>>,
|
||||
#[option(
|
||||
default = "[]",
|
||||
value_type = "list[str]",
|
||||
|
|
|
@ -189,6 +189,27 @@ pub struct CheckArgs {
|
|||
hide_possible_values = true
|
||||
)]
|
||||
pub unfixable: Option<Vec<RuleSelector>>,
|
||||
/// Like --fixable, but adds additional rule codes on top of the fixable
|
||||
/// ones.
|
||||
#[arg(
|
||||
long,
|
||||
value_delimiter = ',',
|
||||
value_name = "RULE_CODE",
|
||||
value_parser = parse_rule_selector,
|
||||
help_heading = "Rule selection",
|
||||
hide_possible_values = true
|
||||
)]
|
||||
pub extend_fixable: Option<Vec<RuleSelector>>,
|
||||
/// Like --unfixable. (Deprecated: You can just use --unfixable instead.)
|
||||
#[arg(
|
||||
long,
|
||||
value_delimiter = ',',
|
||||
value_name = "RULE_CODE",
|
||||
value_parser = parse_rule_selector,
|
||||
help_heading = "Rule selection",
|
||||
hide = true
|
||||
)]
|
||||
pub extend_unfixable: Option<Vec<RuleSelector>>,
|
||||
/// Respect file exclusions via `.gitignore` and other standard ignore
|
||||
/// files.
|
||||
#[arg(
|
||||
|
@ -375,8 +396,10 @@ impl CheckArgs {
|
|||
dummy_variable_rgx: self.dummy_variable_rgx,
|
||||
exclude: self.exclude,
|
||||
extend_exclude: self.extend_exclude,
|
||||
extend_fixable: self.extend_fixable,
|
||||
extend_ignore: self.extend_ignore,
|
||||
extend_select: self.extend_select,
|
||||
extend_unfixable: self.extend_unfixable,
|
||||
fixable: self.fixable,
|
||||
ignore: self.ignore,
|
||||
line_length: self.line_length,
|
||||
|
@ -442,8 +465,10 @@ pub struct Overrides {
|
|||
pub dummy_variable_rgx: Option<Regex>,
|
||||
pub exclude: Option<Vec<FilePattern>>,
|
||||
pub extend_exclude: Option<Vec<FilePattern>>,
|
||||
pub extend_fixable: Option<Vec<RuleSelector>>,
|
||||
pub extend_ignore: Option<Vec<RuleSelector>>,
|
||||
pub extend_select: Option<Vec<RuleSelector>>,
|
||||
pub extend_unfixable: Option<Vec<RuleSelector>>,
|
||||
pub fixable: Option<Vec<RuleSelector>>,
|
||||
pub ignore: Option<Vec<RuleSelector>>,
|
||||
pub line_length: Option<usize>,
|
||||
|
@ -493,7 +518,14 @@ impl ConfigProcessor for &Overrides {
|
|||
.collect(),
|
||||
extend_select: self.extend_select.clone().unwrap_or_default(),
|
||||
fixable: self.fixable.clone(),
|
||||
unfixable: self.unfixable.clone().unwrap_or_default(),
|
||||
unfixable: self
|
||||
.unfixable
|
||||
.iter()
|
||||
.cloned()
|
||||
.chain(self.extend_unfixable.iter().cloned())
|
||||
.flatten()
|
||||
.collect(),
|
||||
extend_fixable: self.extend_fixable.clone().unwrap_or_default(),
|
||||
});
|
||||
if let Some(format) = &self.format {
|
||||
config.format = Some(*format);
|
||||
|
|
|
@ -96,8 +96,10 @@ pub fn defaultSettings() -> Result<JsValue, JsValue> {
|
|||
allowed_confusables: Some(Vec::default()),
|
||||
builtins: Some(Vec::default()),
|
||||
dummy_variable_rgx: Some(defaults::DUMMY_VARIABLE_RGX.as_str().to_string()),
|
||||
extend_fixable: Some(Vec::default()),
|
||||
extend_ignore: Some(Vec::default()),
|
||||
extend_select: Some(Vec::default()),
|
||||
extend_unfixable: Some(Vec::default()),
|
||||
external: Some(Vec::default()),
|
||||
ignore: Some(Vec::default()),
|
||||
line_length: Some(defaults::LINE_LENGTH),
|
||||
|
|
|
@ -239,6 +239,8 @@ Rule selection:
|
|||
List of rule codes to treat as eligible for autofix. Only applicable when autofix itself is enabled (e.g., via `--fix`)
|
||||
--unfixable <RULE_CODE>
|
||||
List of rule codes to treat as ineligible for autofix. Only applicable when autofix itself is enabled (e.g., via `--fix`)
|
||||
--extend-fixable <RULE_CODE>
|
||||
Like --fixable, but adds additional rule codes on top of the fixable ones
|
||||
|
||||
File selection:
|
||||
--exclude <FILE_PATTERN> List of paths, used to omit files and/or directories from analysis
|
||||
|
|
10
ruff.schema.json
generated
10
ruff.schema.json
generated
|
@ -66,6 +66,16 @@
|
|||
"type": "string"
|
||||
}
|
||||
},
|
||||
"extend-fixable": {
|
||||
"description": "A list of rule codes or prefixes to consider autofixable, in addition to those specified by `fixable`.",
|
||||
"type": [
|
||||
"array",
|
||||
"null"
|
||||
],
|
||||
"items": {
|
||||
"$ref": "#/definitions/RuleSelector"
|
||||
}
|
||||
},
|
||||
"extend-include": {
|
||||
"description": "A list of file patterns to include when linting, in addition to those specified by `include`.\n\nInclusion are based on globs, and should be single-path patterns, like `*.pyw`, to include any file with the `.pyw` extension.\n\nFor more information on the glob syntax, refer to the [`globset` documentation](https://docs.rs/globset/latest/globset/#syntax).",
|
||||
"type": [
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue