mirror of
https://github.com/astral-sh/ruff.git
synced 2025-09-30 13:51:37 +00:00
Properly combine CLI and pyproject.toml ignores and selects (#329)
This commit is contained in:
parent
f80d5e70dd
commit
5bf8b13644
7 changed files with 195 additions and 162 deletions
122
src/check_ast.rs
122
src/check_ast.rs
|
@ -234,7 +234,7 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
if self.settings.select.contains(&CheckCode::E741) {
|
||||
if self.settings.enabled.contains(&CheckCode::E741) {
|
||||
let location = self.locate_check(Range::from_located(stmt));
|
||||
self.checks.extend(
|
||||
names.iter().filter_map(|name| {
|
||||
|
@ -244,7 +244,7 @@ where
|
|||
}
|
||||
}
|
||||
StmtKind::Break => {
|
||||
if self.settings.select.contains(&CheckCode::F701) {
|
||||
if self.settings.enabled.contains(&CheckCode::F701) {
|
||||
if let Some(check) = checks::check_break_outside_loop(
|
||||
stmt,
|
||||
&self.parents,
|
||||
|
@ -256,7 +256,7 @@ where
|
|||
}
|
||||
}
|
||||
StmtKind::Continue => {
|
||||
if self.settings.select.contains(&CheckCode::F702) {
|
||||
if self.settings.enabled.contains(&CheckCode::F702) {
|
||||
if let Some(check) = checks::check_continue_outside_loop(
|
||||
stmt,
|
||||
&self.parents,
|
||||
|
@ -281,7 +281,7 @@ where
|
|||
args,
|
||||
..
|
||||
} => {
|
||||
if self.settings.select.contains(&CheckCode::E743) {
|
||||
if self.settings.enabled.contains(&CheckCode::E743) {
|
||||
if let Some(check) = checks::check_ambiguous_function_name(
|
||||
name,
|
||||
self.locate_check(Range::from_located(stmt)),
|
||||
|
@ -342,7 +342,7 @@ where
|
|||
StmtKind::Return { .. } => {
|
||||
if self
|
||||
.settings
|
||||
.select
|
||||
.enabled
|
||||
.contains(CheckKind::ReturnOutsideFunction.code())
|
||||
{
|
||||
if let Some(scope_index) = self.scope_stack.last().cloned() {
|
||||
|
@ -365,7 +365,7 @@ where
|
|||
decorator_list,
|
||||
..
|
||||
} => {
|
||||
if self.settings.select.contains(&CheckCode::R001) {
|
||||
if self.settings.enabled.contains(&CheckCode::R001) {
|
||||
let scope =
|
||||
&self.scopes[*(self.scope_stack.last().expect("No current scope found."))];
|
||||
if let Some(check) = checks::check_useless_object_inheritance(
|
||||
|
@ -381,7 +381,7 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
if self.settings.select.contains(&CheckCode::E742) {
|
||||
if self.settings.enabled.contains(&CheckCode::E742) {
|
||||
if let Some(check) = checks::check_ambiguous_class_name(
|
||||
name,
|
||||
self.locate_check(Range::from_located(stmt)),
|
||||
|
@ -410,7 +410,7 @@ where
|
|||
StmtKind::Import { names } => {
|
||||
if self
|
||||
.settings
|
||||
.select
|
||||
.enabled
|
||||
.contains(CheckKind::ModuleImportNotAtTopOfFile.code())
|
||||
&& self.seen_non_import
|
||||
&& stmt.location.column() == 1
|
||||
|
@ -470,7 +470,7 @@ where
|
|||
} => {
|
||||
if self
|
||||
.settings
|
||||
.select
|
||||
.enabled
|
||||
.contains(CheckKind::ModuleImportNotAtTopOfFile.code())
|
||||
&& self.seen_non_import
|
||||
&& stmt.location.column() == 1
|
||||
|
@ -508,7 +508,7 @@ where
|
|||
self.annotations_future_enabled = true;
|
||||
}
|
||||
|
||||
if self.settings.select.contains(&CheckCode::F407)
|
||||
if self.settings.enabled.contains(&CheckCode::F407)
|
||||
&& !ALL_FEATURE_NAMES.contains(&alias.node.name.deref())
|
||||
{
|
||||
self.checks.push(Check::new(
|
||||
|
@ -517,7 +517,7 @@ where
|
|||
));
|
||||
}
|
||||
|
||||
if self.settings.select.contains(&CheckCode::F404) && !self.futures_allowed
|
||||
if self.settings.enabled.contains(&CheckCode::F404) && !self.futures_allowed
|
||||
{
|
||||
self.checks.push(Check::new(
|
||||
CheckKind::LateFutureImport,
|
||||
|
@ -540,7 +540,7 @@ where
|
|||
},
|
||||
);
|
||||
|
||||
if self.settings.select.contains(&CheckCode::F406) {
|
||||
if self.settings.enabled.contains(&CheckCode::F406) {
|
||||
let scope = &self.scopes
|
||||
[*(self.scope_stack.last().expect("No current scope found."))];
|
||||
if !matches!(scope.kind, ScopeKind::Module) {
|
||||
|
@ -551,7 +551,7 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
if self.settings.select.contains(&CheckCode::F403) {
|
||||
if self.settings.enabled.contains(&CheckCode::F403) {
|
||||
self.checks.push(Check::new(
|
||||
CheckKind::ImportStarUsed(module_name.to_string()),
|
||||
self.locate_check(Range::from_located(stmt)),
|
||||
|
@ -584,7 +584,7 @@ where
|
|||
}
|
||||
}
|
||||
StmtKind::Raise { exc, .. } => {
|
||||
if self.settings.select.contains(&CheckCode::F901) {
|
||||
if self.settings.enabled.contains(&CheckCode::F901) {
|
||||
if let Some(expr) = exc {
|
||||
if let Some(check) = checks::check_raise_not_implemented(expr) {
|
||||
self.checks.push(check);
|
||||
|
@ -596,7 +596,7 @@ where
|
|||
self.handle_node_load(target);
|
||||
}
|
||||
StmtKind::If { test, .. } => {
|
||||
if self.settings.select.contains(&CheckCode::F634) {
|
||||
if self.settings.enabled.contains(&CheckCode::F634) {
|
||||
if let Some(check) =
|
||||
checks::check_if_tuple(test, self.locate_check(Range::from_located(stmt)))
|
||||
{
|
||||
|
@ -605,7 +605,11 @@ where
|
|||
}
|
||||
}
|
||||
StmtKind::Assert { test, .. } => {
|
||||
if self.settings.select.contains(CheckKind::AssertTuple.code()) {
|
||||
if self
|
||||
.settings
|
||||
.enabled
|
||||
.contains(CheckKind::AssertTuple.code())
|
||||
{
|
||||
if let Some(check) = checks::check_assert_tuple(
|
||||
test,
|
||||
self.locate_check(Range::from_located(stmt)),
|
||||
|
@ -615,14 +619,14 @@ where
|
|||
}
|
||||
}
|
||||
StmtKind::Try { handlers, .. } => {
|
||||
if self.settings.select.contains(&CheckCode::F707) {
|
||||
if self.settings.enabled.contains(&CheckCode::F707) {
|
||||
if let Some(check) = checks::check_default_except_not_last(handlers) {
|
||||
self.checks.push(check);
|
||||
}
|
||||
}
|
||||
}
|
||||
StmtKind::Assign { targets, value, .. } => {
|
||||
if self.settings.select.contains(&CheckCode::E731) {
|
||||
if self.settings.enabled.contains(&CheckCode::E731) {
|
||||
if let Some(check) = checks::check_do_not_assign_lambda(
|
||||
value,
|
||||
self.locate_check(Range::from_located(stmt)),
|
||||
|
@ -630,7 +634,7 @@ where
|
|||
self.checks.push(check);
|
||||
}
|
||||
}
|
||||
if self.settings.select.contains(&CheckCode::U001) {
|
||||
if self.settings.enabled.contains(&CheckCode::U001) {
|
||||
if let Some(mut check) = checks::check_useless_metaclass_type(
|
||||
targets,
|
||||
value,
|
||||
|
@ -663,7 +667,7 @@ where
|
|||
}
|
||||
}
|
||||
StmtKind::AnnAssign { value, .. } => {
|
||||
if self.settings.select.contains(&CheckCode::E731) {
|
||||
if self.settings.enabled.contains(&CheckCode::E731) {
|
||||
if let Some(value) = value {
|
||||
if let Some(check) = checks::check_do_not_assign_lambda(
|
||||
value,
|
||||
|
@ -743,9 +747,9 @@ where
|
|||
ExprKind::Tuple { elts, ctx } | ExprKind::List { elts, ctx } => {
|
||||
if matches!(ctx, ExprContext::Store) {
|
||||
let check_too_many_expressions =
|
||||
self.settings.select.contains(&CheckCode::F621);
|
||||
self.settings.enabled.contains(&CheckCode::F621);
|
||||
let check_two_starred_expressions =
|
||||
self.settings.select.contains(&CheckCode::F622);
|
||||
self.settings.enabled.contains(&CheckCode::F622);
|
||||
if let Some(check) = checks::check_starred_expressions(
|
||||
elts,
|
||||
check_too_many_expressions,
|
||||
|
@ -759,7 +763,7 @@ where
|
|||
ExprKind::Name { id, ctx } => match ctx {
|
||||
ExprContext::Load => self.handle_node_load(expr),
|
||||
ExprContext::Store => {
|
||||
if self.settings.select.contains(&CheckCode::E741) {
|
||||
if self.settings.enabled.contains(&CheckCode::E741) {
|
||||
if let Some(check) = checks::check_ambiguous_variable_name(
|
||||
id,
|
||||
self.locate_check(Range::from_located(expr)),
|
||||
|
@ -777,14 +781,14 @@ where
|
|||
ExprContext::Del => self.handle_node_delete(expr),
|
||||
},
|
||||
ExprKind::Call { func, args, .. } => {
|
||||
if self.settings.select.contains(&CheckCode::R002) {
|
||||
if self.settings.enabled.contains(&CheckCode::R002) {
|
||||
if let Some(check) = checks::check_assert_equals(func, self.autofix) {
|
||||
self.checks.push(check)
|
||||
}
|
||||
}
|
||||
|
||||
// flake8-super
|
||||
if self.settings.select.contains(&CheckCode::SPR001) {
|
||||
if self.settings.enabled.contains(&CheckCode::SPR001) {
|
||||
// Only bother going through the super check at all if we're in a `super` call.
|
||||
// (We check this in `check_super_args` too, so this is just an optimization.)
|
||||
if checks::is_super_call_with_arguments(func, args) {
|
||||
|
@ -811,8 +815,8 @@ where
|
|||
}
|
||||
|
||||
// flake8-print
|
||||
if self.settings.select.contains(&CheckCode::T201)
|
||||
|| self.settings.select.contains(&CheckCode::T203)
|
||||
if self.settings.enabled.contains(&CheckCode::T201)
|
||||
|| self.settings.enabled.contains(&CheckCode::T203)
|
||||
{
|
||||
if let Some(mut check) = checks::check_print_call(expr, func) {
|
||||
if matches!(self.autofix, fixer::Mode::Generate | fixer::Mode::Apply) {
|
||||
|
@ -863,8 +867,8 @@ where
|
|||
}
|
||||
}
|
||||
ExprKind::Dict { keys, .. } => {
|
||||
let check_repeated_literals = self.settings.select.contains(&CheckCode::F601);
|
||||
let check_repeated_variables = self.settings.select.contains(&CheckCode::F602);
|
||||
let check_repeated_literals = self.settings.enabled.contains(&CheckCode::F601);
|
||||
let check_repeated_variables = self.settings.enabled.contains(&CheckCode::F602);
|
||||
if check_repeated_literals || check_repeated_variables {
|
||||
self.checks.extend(checks::check_repeated_keys(
|
||||
keys,
|
||||
|
@ -879,7 +883,7 @@ where
|
|||
&self.scopes[*(self.scope_stack.last().expect("No current scope found."))];
|
||||
if self
|
||||
.settings
|
||||
.select
|
||||
.enabled
|
||||
.contains(CheckKind::YieldOutsideFunction.code())
|
||||
&& matches!(scope.kind, ScopeKind::Class | ScopeKind::Module)
|
||||
{
|
||||
|
@ -893,7 +897,7 @@ where
|
|||
if self.in_f_string.is_none()
|
||||
&& self
|
||||
.settings
|
||||
.select
|
||||
.enabled
|
||||
.contains(CheckKind::FStringMissingPlaceholders.code())
|
||||
&& !values
|
||||
.iter()
|
||||
|
@ -911,7 +915,7 @@ where
|
|||
op: Operator::RShift,
|
||||
..
|
||||
} => {
|
||||
if self.settings.select.contains(&CheckCode::F633) {
|
||||
if self.settings.enabled.contains(&CheckCode::F633) {
|
||||
if let ExprKind::Name { id, .. } = &left.node {
|
||||
if id == "print" {
|
||||
let scope = &self.scopes
|
||||
|
@ -931,8 +935,8 @@ where
|
|||
}
|
||||
}
|
||||
ExprKind::UnaryOp { op, operand } => {
|
||||
let check_not_in = self.settings.select.contains(&CheckCode::E713);
|
||||
let check_not_is = self.settings.select.contains(&CheckCode::E714);
|
||||
let check_not_in = self.settings.enabled.contains(&CheckCode::E713);
|
||||
let check_not_is = self.settings.enabled.contains(&CheckCode::E714);
|
||||
if check_not_in || check_not_is {
|
||||
self.checks.extend(checks::check_not_tests(
|
||||
op,
|
||||
|
@ -948,8 +952,8 @@ where
|
|||
ops,
|
||||
comparators,
|
||||
} => {
|
||||
let check_none_comparisons = self.settings.select.contains(&CheckCode::E711);
|
||||
let check_true_false_comparisons = self.settings.select.contains(&CheckCode::E712);
|
||||
let check_none_comparisons = self.settings.enabled.contains(&CheckCode::E711);
|
||||
let check_true_false_comparisons = self.settings.enabled.contains(&CheckCode::E712);
|
||||
if check_none_comparisons || check_true_false_comparisons {
|
||||
self.checks.extend(checks::check_literal_comparisons(
|
||||
left,
|
||||
|
@ -961,7 +965,7 @@ where
|
|||
));
|
||||
}
|
||||
|
||||
if self.settings.select.contains(&CheckCode::F632) {
|
||||
if self.settings.enabled.contains(&CheckCode::F632) {
|
||||
self.checks.extend(checks::check_is_literal(
|
||||
left,
|
||||
ops,
|
||||
|
@ -970,7 +974,7 @@ where
|
|||
));
|
||||
}
|
||||
|
||||
if self.settings.select.contains(&CheckCode::E721) {
|
||||
if self.settings.enabled.contains(&CheckCode::E721) {
|
||||
self.checks.extend(checks::check_type_comparison(
|
||||
ops,
|
||||
comparators,
|
||||
|
@ -1164,7 +1168,7 @@ where
|
|||
fn visit_excepthandler(&mut self, excepthandler: &'b Excepthandler) {
|
||||
match &excepthandler.node {
|
||||
ExcepthandlerKind::ExceptHandler { type_, name, .. } => {
|
||||
if self.settings.select.contains(&CheckCode::E722) && type_.is_none() {
|
||||
if self.settings.enabled.contains(&CheckCode::E722) && type_.is_none() {
|
||||
self.checks.push(Check::new(
|
||||
CheckKind::DoNotUseBareExcept,
|
||||
Range::from_located(excepthandler),
|
||||
|
@ -1172,7 +1176,7 @@ where
|
|||
}
|
||||
match name {
|
||||
Some(name) => {
|
||||
if self.settings.select.contains(&CheckCode::E741) {
|
||||
if self.settings.enabled.contains(&CheckCode::E741) {
|
||||
if let Some(check) = checks::check_ambiguous_variable_name(
|
||||
name,
|
||||
self.locate_check(Range::from_located(excepthandler)),
|
||||
|
@ -1227,7 +1231,7 @@ where
|
|||
let scope = &mut self.scopes
|
||||
[*(self.scope_stack.last().expect("No current scope found."))];
|
||||
if let Some(binding) = &scope.values.remove(name) {
|
||||
if self.settings.select.contains(&CheckCode::F841)
|
||||
if self.settings.enabled.contains(&CheckCode::F841)
|
||||
&& binding.used.is_none()
|
||||
{
|
||||
self.checks.push(Check::new(
|
||||
|
@ -1248,7 +1252,7 @@ where
|
|||
}
|
||||
|
||||
fn visit_arguments(&mut self, arguments: &'b Arguments) {
|
||||
if self.settings.select.contains(&CheckCode::F831) {
|
||||
if self.settings.enabled.contains(&CheckCode::F831) {
|
||||
self.checks
|
||||
.extend(checks::check_duplicate_arguments(arguments));
|
||||
}
|
||||
|
@ -1282,7 +1286,7 @@ where
|
|||
},
|
||||
);
|
||||
|
||||
if self.settings.select.contains(&CheckCode::E741) {
|
||||
if self.settings.enabled.contains(&CheckCode::E741) {
|
||||
if let Some(check) = checks::check_ambiguous_variable_name(
|
||||
&arg.node.arg,
|
||||
self.locate_check(Range::from_located(arg)),
|
||||
|
@ -1368,7 +1372,7 @@ impl<'a> Checker<'a> {
|
|||
let binding = match scope.values.get(&name) {
|
||||
None => binding,
|
||||
Some(existing) => {
|
||||
if self.settings.select.contains(&CheckCode::F402)
|
||||
if self.settings.enabled.contains(&CheckCode::F402)
|
||||
&& matches!(binding.kind, BindingKind::LoopVar)
|
||||
&& matches!(
|
||||
existing.kind,
|
||||
|
@ -1422,7 +1426,7 @@ impl<'a> Checker<'a> {
|
|||
}
|
||||
|
||||
if import_starred {
|
||||
if self.settings.select.contains(&CheckCode::F405) {
|
||||
if self.settings.enabled.contains(&CheckCode::F405) {
|
||||
let mut from_list = vec![];
|
||||
for scope_index in self.scope_stack.iter().rev() {
|
||||
let scope = &self.scopes[*scope_index];
|
||||
|
@ -1442,7 +1446,7 @@ impl<'a> Checker<'a> {
|
|||
return;
|
||||
}
|
||||
|
||||
if self.settings.select.contains(&CheckCode::F821) {
|
||||
if self.settings.enabled.contains(&CheckCode::F821) {
|
||||
// Allow __path__.
|
||||
if self.path.ends_with("__init__.py") && id == "__path__" {
|
||||
return;
|
||||
|
@ -1460,7 +1464,7 @@ impl<'a> Checker<'a> {
|
|||
let current =
|
||||
&self.scopes[*(self.scope_stack.last().expect("No current scope found."))];
|
||||
|
||||
if self.settings.select.contains(&CheckCode::F823)
|
||||
if self.settings.enabled.contains(&CheckCode::F823)
|
||||
&& matches!(current.kind, ScopeKind::Function(_))
|
||||
&& !current.values.contains_key(id)
|
||||
{
|
||||
|
@ -1560,7 +1564,7 @@ impl<'a> Checker<'a> {
|
|||
|
||||
let scope =
|
||||
&mut self.scopes[*(self.scope_stack.last().expect("No current scope found."))];
|
||||
if scope.values.remove(id).is_none() && self.settings.select.contains(&CheckCode::F821)
|
||||
if scope.values.remove(id).is_none() && self.settings.enabled.contains(&CheckCode::F821)
|
||||
{
|
||||
self.checks.push(Check::new(
|
||||
CheckKind::UndefinedName(id.clone()),
|
||||
|
@ -1586,7 +1590,7 @@ impl<'a> Checker<'a> {
|
|||
if let Ok(mut expr) = parser::parse_expression(expression, "<filename>") {
|
||||
relocate_expr(&mut expr, location);
|
||||
allocator.push(expr);
|
||||
} else if self.settings.select.contains(&CheckCode::F722) {
|
||||
} else if self.settings.enabled.contains(&CheckCode::F722) {
|
||||
self.checks.push(Check::new(
|
||||
CheckKind::ForwardAnnotationSyntaxError(expression.to_string()),
|
||||
self.locate_check(location),
|
||||
|
@ -1641,7 +1645,7 @@ impl<'a> Checker<'a> {
|
|||
}
|
||||
|
||||
fn check_deferred_assignments(&mut self) {
|
||||
if self.settings.select.contains(&CheckCode::F841) {
|
||||
if self.settings.enabled.contains(&CheckCode::F841) {
|
||||
while let Some(index) = self.deferred_assignments.pop() {
|
||||
self.checks.extend(checks::check_unused_variables(
|
||||
&self.scopes[index],
|
||||
|
@ -1653,9 +1657,9 @@ impl<'a> Checker<'a> {
|
|||
}
|
||||
|
||||
fn check_dead_scopes(&mut self) {
|
||||
if !self.settings.select.contains(&CheckCode::F401)
|
||||
&& !self.settings.select.contains(&CheckCode::F405)
|
||||
&& !self.settings.select.contains(&CheckCode::F822)
|
||||
if !self.settings.enabled.contains(&CheckCode::F401)
|
||||
&& !self.settings.enabled.contains(&CheckCode::F405)
|
||||
&& !self.settings.enabled.contains(&CheckCode::F822)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
@ -1669,7 +1673,7 @@ impl<'a> Checker<'a> {
|
|||
_ => None,
|
||||
});
|
||||
|
||||
if self.settings.select.contains(&CheckCode::F822)
|
||||
if self.settings.enabled.contains(&CheckCode::F822)
|
||||
&& !scope.import_starred
|
||||
&& !self.path.ends_with("__init__.py")
|
||||
{
|
||||
|
@ -1687,7 +1691,7 @@ impl<'a> Checker<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
if self.settings.select.contains(&CheckCode::F405) && scope.import_starred {
|
||||
if self.settings.enabled.contains(&CheckCode::F405) && scope.import_starred {
|
||||
if let Some(all_binding) = all_binding {
|
||||
if let Some(names) = all_names {
|
||||
let mut from_list = vec![];
|
||||
|
@ -1710,7 +1714,7 @@ impl<'a> Checker<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
if self.settings.select.contains(&CheckCode::F401) {
|
||||
if self.settings.enabled.contains(&CheckCode::F401) {
|
||||
// Collect all unused imports by location. (Multiple unused imports at the same
|
||||
// location indicates an `import from`.)
|
||||
let mut unused: BTreeMap<(ImportKind, usize, Option<usize>), Vec<&str>> =
|
||||
|
@ -1793,7 +1797,7 @@ impl<'a> Checker<'a> {
|
|||
|
||||
// flake8-builtins
|
||||
if is_attribute && matches!(scope.kind, ScopeKind::Class) {
|
||||
if self.settings.select.contains(&CheckCode::A003) {
|
||||
if self.settings.enabled.contains(&CheckCode::A003) {
|
||||
if let Some(check) = checks::check_builtin_shadowing(
|
||||
name,
|
||||
self.locate_check(location),
|
||||
|
@ -1802,7 +1806,7 @@ impl<'a> Checker<'a> {
|
|||
self.checks.push(check);
|
||||
}
|
||||
}
|
||||
} else if self.settings.select.contains(&CheckCode::A001) {
|
||||
} else if self.settings.enabled.contains(&CheckCode::A001) {
|
||||
if let Some(check) = checks::check_builtin_shadowing(
|
||||
name,
|
||||
self.locate_check(location),
|
||||
|
@ -1814,7 +1818,7 @@ impl<'a> Checker<'a> {
|
|||
}
|
||||
|
||||
fn check_builtin_arg_shadowing(&mut self, name: &str, location: Range) {
|
||||
if self.settings.select.contains(&CheckCode::A002) {
|
||||
if self.settings.enabled.contains(&CheckCode::A002) {
|
||||
if let Some(check) = checks::check_builtin_shadowing(
|
||||
name,
|
||||
self.locate_check(location),
|
||||
|
|
|
@ -32,8 +32,8 @@ pub fn check_lines(
|
|||
settings: &Settings,
|
||||
autofix: &fixer::Mode,
|
||||
) {
|
||||
let enforce_line_too_long = settings.select.contains(&CheckCode::E501);
|
||||
let enforce_noqa = settings.select.contains(&CheckCode::M001);
|
||||
let enforce_line_too_long = settings.enabled.contains(&CheckCode::E501);
|
||||
let enforce_noqa = settings.enabled.contains(&CheckCode::M001);
|
||||
|
||||
let mut noqa_directives: BTreeMap<usize, (Directive, Vec<&str>)> = BTreeMap::new();
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@ use rustpython_parser::lexer::LexResult;
|
|||
use crate::autofix::fixer::Mode;
|
||||
use crate::linter::{check_path, tokenize};
|
||||
use crate::message::Message;
|
||||
use crate::settings::Settings;
|
||||
use crate::settings::{RawSettings, Settings};
|
||||
|
||||
mod ast;
|
||||
mod autofix;
|
||||
|
@ -40,7 +40,7 @@ pub fn check(path: &Path, contents: &str) -> Result<Vec<Message>> {
|
|||
None => debug!("Unable to find pyproject.toml; using default settings..."),
|
||||
};
|
||||
|
||||
let settings = Settings::from_pyproject(pyproject, project_root)?;
|
||||
let settings = Settings::from_raw(RawSettings::from_pyproject(pyproject, project_root)?);
|
||||
|
||||
// Tokenize once.
|
||||
let tokens: Vec<LexResult> = tokenize(contents);
|
||||
|
|
|
@ -44,7 +44,7 @@ pub(crate) fn check_path(
|
|||
|
||||
// Run the AST-based checks.
|
||||
if settings
|
||||
.select
|
||||
.enabled
|
||||
.iter()
|
||||
.any(|check_code| matches!(check_code.lint_source(), LintSource::AST))
|
||||
{
|
||||
|
@ -53,7 +53,7 @@ pub(crate) fn check_path(
|
|||
checks.extend(check_ast(&python_ast, contents, settings, autofix, path))
|
||||
}
|
||||
Err(parse_error) => {
|
||||
if settings.select.contains(&CheckCode::E999) {
|
||||
if settings.enabled.contains(&CheckCode::E999) {
|
||||
checks.push(Check::new(
|
||||
CheckKind::SyntaxError(parse_error.error.to_string()),
|
||||
Range {
|
||||
|
|
27
src/main.rs
27
src/main.rs
|
@ -27,6 +27,7 @@ use ::ruff::settings::CurrentSettings;
|
|||
use ::ruff::settings::{FilePattern, PerFileIgnore, Settings};
|
||||
use ::ruff::tell_user;
|
||||
use ruff::linter::autoformat_path;
|
||||
use ruff::settings::RawSettings;
|
||||
|
||||
const CARGO_PKG_NAME: &str = env!("CARGO_PKG_NAME");
|
||||
const CARGO_PKG_VERSION: &str = env!("CARGO_PKG_VERSION");
|
||||
|
@ -120,7 +121,7 @@ fn check_for_updates() {
|
|||
}
|
||||
}
|
||||
|
||||
fn show_settings(settings: Settings) {
|
||||
fn show_settings(settings: RawSettings) {
|
||||
println!("{:#?}", CurrentSettings::from_settings(settings));
|
||||
}
|
||||
|
||||
|
@ -169,7 +170,7 @@ fn run_once(
|
|||
}
|
||||
.unwrap_or_else(|(path, message)| {
|
||||
if let Some(path) = path {
|
||||
if settings.select.contains(&CheckCode::E902) {
|
||||
if settings.enabled.contains(&CheckCode::E902) {
|
||||
vec![Message {
|
||||
kind: CheckKind::IOError(message),
|
||||
fixed: false,
|
||||
|
@ -287,7 +288,7 @@ fn inner_main() -> Result<ExitCode> {
|
|||
.map(|pair| PerFileIgnore::new(pair, &project_root))
|
||||
.collect();
|
||||
|
||||
let mut settings = Settings::from_pyproject(pyproject, project_root)?;
|
||||
let mut settings = RawSettings::from_pyproject(pyproject, project_root)?;
|
||||
if !exclude.is_empty() {
|
||||
settings.exclude = exclude;
|
||||
}
|
||||
|
@ -298,17 +299,16 @@ fn inner_main() -> Result<ExitCode> {
|
|||
settings.per_file_ignores = per_file_ignores;
|
||||
}
|
||||
if !cli.select.is_empty() {
|
||||
settings.clear();
|
||||
settings.select(cli.select);
|
||||
settings.select = cli.select;
|
||||
}
|
||||
if !cli.extend_select.is_empty() {
|
||||
settings.select(cli.extend_select);
|
||||
settings.extend_select = cli.extend_select;
|
||||
}
|
||||
if !cli.ignore.is_empty() {
|
||||
settings.ignore(&cli.ignore);
|
||||
settings.ignore = cli.ignore;
|
||||
}
|
||||
if !cli.extend_ignore.is_empty() {
|
||||
settings.ignore(&cli.extend_ignore);
|
||||
settings.extend_ignore = cli.extend_ignore;
|
||||
}
|
||||
if let Some(dummy_variable_rgx) = cli.dummy_variable_rgx {
|
||||
settings.dummy_variable_rgx = dummy_variable_rgx;
|
||||
|
@ -318,15 +318,18 @@ fn inner_main() -> Result<ExitCode> {
|
|||
eprintln!("Error: specify --show-settings or show-files (not both).");
|
||||
return Ok(ExitCode::FAILURE);
|
||||
}
|
||||
if cli.show_files {
|
||||
show_files(&cli.files, &settings);
|
||||
return Ok(ExitCode::SUCCESS);
|
||||
}
|
||||
if cli.show_settings {
|
||||
show_settings(settings);
|
||||
return Ok(ExitCode::SUCCESS);
|
||||
}
|
||||
|
||||
let settings = Settings::from_raw(settings);
|
||||
|
||||
if cli.show_files {
|
||||
show_files(&cli.files, &settings);
|
||||
return Ok(ExitCode::SUCCESS);
|
||||
}
|
||||
|
||||
cache::init()?;
|
||||
|
||||
let mut printer = Printer::new(cli.format, cli.verbose);
|
||||
|
|
|
@ -37,6 +37,8 @@ pub struct Config {
|
|||
#[serde(default)]
|
||||
pub ignore: Vec<CheckCode>,
|
||||
#[serde(default)]
|
||||
pub extend_ignore: Vec<CheckCode>,
|
||||
#[serde(default)]
|
||||
pub per_file_ignores: Vec<StrCheckCodePair>,
|
||||
pub dummy_variable_rgx: Option<String>,
|
||||
}
|
||||
|
@ -184,6 +186,7 @@ mod tests {
|
|||
select: None,
|
||||
extend_select: vec![],
|
||||
ignore: vec![],
|
||||
extend_ignore: vec![],
|
||||
per_file_ignores: vec![],
|
||||
dummy_variable_rgx: None,
|
||||
})
|
||||
|
@ -207,6 +210,7 @@ line-length = 79
|
|||
select: None,
|
||||
extend_select: vec![],
|
||||
ignore: vec![],
|
||||
extend_ignore: vec![],
|
||||
per_file_ignores: vec![],
|
||||
dummy_variable_rgx: None,
|
||||
})
|
||||
|
@ -230,6 +234,7 @@ exclude = ["foo.py"]
|
|||
select: None,
|
||||
extend_select: vec![],
|
||||
ignore: vec![],
|
||||
extend_ignore: vec![],
|
||||
per_file_ignores: vec![],
|
||||
dummy_variable_rgx: None,
|
||||
})
|
||||
|
@ -253,6 +258,7 @@ select = ["E501"]
|
|||
select: Some(vec![CheckCode::E501]),
|
||||
extend_select: vec![],
|
||||
ignore: vec![],
|
||||
extend_ignore: vec![],
|
||||
per_file_ignores: vec![],
|
||||
dummy_variable_rgx: None,
|
||||
})
|
||||
|
@ -277,6 +283,7 @@ ignore = ["E501"]
|
|||
select: None,
|
||||
extend_select: vec![CheckCode::M001],
|
||||
ignore: vec![CheckCode::E501],
|
||||
extend_ignore: vec![],
|
||||
per_file_ignores: vec![],
|
||||
dummy_variable_rgx: None,
|
||||
})
|
||||
|
@ -344,6 +351,7 @@ other-attribute = 1
|
|||
select: None,
|
||||
extend_select: vec![],
|
||||
ignore: vec![],
|
||||
extend_ignore: vec![],
|
||||
per_file_ignores: vec![],
|
||||
dummy_variable_rgx: None,
|
||||
}
|
||||
|
|
194
src/settings.rs
194
src/settings.rs
|
@ -51,56 +51,18 @@ impl PerFileIgnore {
|
|||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Settings {
|
||||
pub pyproject: Option<PathBuf>,
|
||||
pub project_root: Option<PathBuf>,
|
||||
pub line_length: usize,
|
||||
pub struct RawSettings {
|
||||
pub dummy_variable_rgx: Regex,
|
||||
pub exclude: Vec<FilePattern>,
|
||||
pub extend_exclude: Vec<FilePattern>,
|
||||
pub select: BTreeSet<CheckCode>,
|
||||
pub extend_ignore: Vec<CheckCode>,
|
||||
pub extend_select: Vec<CheckCode>,
|
||||
pub ignore: Vec<CheckCode>,
|
||||
pub line_length: usize,
|
||||
pub per_file_ignores: Vec<PerFileIgnore>,
|
||||
pub dummy_variable_rgx: Regex,
|
||||
}
|
||||
|
||||
impl Settings {
|
||||
pub fn for_rule(check_code: CheckCode) -> Self {
|
||||
Self {
|
||||
pyproject: None,
|
||||
project_root: None,
|
||||
line_length: 88,
|
||||
exclude: vec![],
|
||||
extend_exclude: vec![],
|
||||
select: BTreeSet::from([check_code]),
|
||||
per_file_ignores: vec![],
|
||||
dummy_variable_rgx: DEFAULT_DUMMY_VARIABLE_RGX.clone(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn for_rules(check_codes: Vec<CheckCode>) -> Self {
|
||||
Self {
|
||||
pyproject: None,
|
||||
project_root: None,
|
||||
line_length: 88,
|
||||
exclude: vec![],
|
||||
extend_exclude: vec![],
|
||||
select: BTreeSet::from_iter(check_codes),
|
||||
per_file_ignores: vec![],
|
||||
dummy_variable_rgx: DEFAULT_DUMMY_VARIABLE_RGX.clone(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Hash for Settings {
|
||||
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||
self.line_length.hash(state);
|
||||
self.dummy_variable_rgx.as_str().hash(state);
|
||||
for value in self.select.iter() {
|
||||
value.hash(state);
|
||||
}
|
||||
for value in self.per_file_ignores.iter() {
|
||||
value.hash(state);
|
||||
}
|
||||
}
|
||||
pub project_root: Option<PathBuf>,
|
||||
pub pyproject: Option<PathBuf>,
|
||||
pub select: Vec<CheckCode>,
|
||||
}
|
||||
|
||||
static DEFAULT_EXCLUDE: Lazy<Vec<FilePattern>> = Lazy::new(|| {
|
||||
|
@ -130,14 +92,18 @@ static DEFAULT_EXCLUDE: Lazy<Vec<FilePattern>> = Lazy::new(|| {
|
|||
static DEFAULT_DUMMY_VARIABLE_RGX: Lazy<Regex> =
|
||||
Lazy::new(|| Regex::new("^(_+|(_+[a-zA-Z0-9_]*[a-zA-Z0-9]+?))$").unwrap());
|
||||
|
||||
impl Settings {
|
||||
impl RawSettings {
|
||||
pub fn from_pyproject(
|
||||
pyproject: Option<PathBuf>,
|
||||
project_root: Option<PathBuf>,
|
||||
) -> Result<Self> {
|
||||
let config = load_config(&pyproject)?;
|
||||
let mut settings = Settings {
|
||||
line_length: config.line_length.unwrap_or(88),
|
||||
Ok(RawSettings {
|
||||
dummy_variable_rgx: match config.dummy_variable_rgx {
|
||||
Some(pattern) => Regex::new(&pattern)
|
||||
.map_err(|e| anyhow!("Invalid dummy-variable-rgx value: {e}"))?,
|
||||
None => DEFAULT_DUMMY_VARIABLE_RGX.clone(),
|
||||
},
|
||||
exclude: config
|
||||
.exclude
|
||||
.map(|paths| {
|
||||
|
@ -152,42 +118,88 @@ impl Settings {
|
|||
.iter()
|
||||
.map(|path| FilePattern::from_user(path, &project_root))
|
||||
.collect(),
|
||||
select: if let Some(select) = config.select {
|
||||
BTreeSet::from_iter(select)
|
||||
} else {
|
||||
BTreeSet::from_iter(DEFAULT_CHECK_CODES)
|
||||
},
|
||||
extend_ignore: config.extend_ignore,
|
||||
extend_select: config.extend_select,
|
||||
ignore: config.ignore,
|
||||
line_length: config.line_length.unwrap_or(88),
|
||||
per_file_ignores: config
|
||||
.per_file_ignores
|
||||
.into_iter()
|
||||
.map(|pair| PerFileIgnore::new(pair, &project_root))
|
||||
.collect(),
|
||||
dummy_variable_rgx: match config.dummy_variable_rgx {
|
||||
Some(pattern) => Regex::new(&pattern)
|
||||
.map_err(|e| anyhow!("Invalid dummy-variable-rgx value: {e}"))?,
|
||||
None => DEFAULT_DUMMY_VARIABLE_RGX.clone(),
|
||||
},
|
||||
pyproject,
|
||||
project_root,
|
||||
};
|
||||
settings.select(config.extend_select);
|
||||
settings.ignore(&config.ignore);
|
||||
Ok(settings)
|
||||
}
|
||||
|
||||
pub fn clear(&mut self) {
|
||||
self.select.clear();
|
||||
}
|
||||
|
||||
pub fn select(&mut self, codes: Vec<CheckCode>) {
|
||||
for code in codes {
|
||||
self.select.insert(code);
|
||||
pyproject,
|
||||
select: config
|
||||
.select
|
||||
.unwrap_or_else(|| DEFAULT_CHECK_CODES.to_vec()),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
pub fn ignore(&mut self, codes: &[CheckCode]) {
|
||||
for code in codes {
|
||||
self.select.remove(code);
|
||||
#[derive(Debug)]
|
||||
pub struct Settings {
|
||||
pub dummy_variable_rgx: Regex,
|
||||
pub enabled: BTreeSet<CheckCode>,
|
||||
pub exclude: Vec<FilePattern>,
|
||||
pub extend_exclude: Vec<FilePattern>,
|
||||
pub line_length: usize,
|
||||
pub per_file_ignores: Vec<PerFileIgnore>,
|
||||
}
|
||||
|
||||
impl Settings {
|
||||
pub fn from_raw(settings: RawSettings) -> Self {
|
||||
// Materialize the set of enabled CheckCodes.
|
||||
let mut enabled: BTreeSet<CheckCode> = BTreeSet::new();
|
||||
enabled.extend(settings.select);
|
||||
enabled.extend(settings.extend_select);
|
||||
for code in &settings.ignore {
|
||||
enabled.remove(code);
|
||||
}
|
||||
for code in &settings.extend_ignore {
|
||||
enabled.remove(code);
|
||||
}
|
||||
Self {
|
||||
dummy_variable_rgx: settings.dummy_variable_rgx,
|
||||
enabled,
|
||||
exclude: settings.exclude,
|
||||
extend_exclude: settings.extend_exclude,
|
||||
line_length: settings.line_length,
|
||||
per_file_ignores: settings.per_file_ignores,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn for_rule(check_code: CheckCode) -> Self {
|
||||
Self {
|
||||
dummy_variable_rgx: DEFAULT_DUMMY_VARIABLE_RGX.clone(),
|
||||
enabled: BTreeSet::from([check_code]),
|
||||
exclude: vec![],
|
||||
extend_exclude: vec![],
|
||||
line_length: 88,
|
||||
per_file_ignores: vec![],
|
||||
}
|
||||
}
|
||||
|
||||
pub fn for_rules(check_codes: Vec<CheckCode>) -> Self {
|
||||
Self {
|
||||
dummy_variable_rgx: DEFAULT_DUMMY_VARIABLE_RGX.clone(),
|
||||
enabled: BTreeSet::from_iter(check_codes),
|
||||
exclude: vec![],
|
||||
extend_exclude: vec![],
|
||||
line_length: 88,
|
||||
per_file_ignores: vec![],
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Hash for Settings {
|
||||
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||
self.line_length.hash(state);
|
||||
self.dummy_variable_rgx.as_str().hash(state);
|
||||
for value in self.enabled.iter() {
|
||||
value.hash(state);
|
||||
}
|
||||
for value in self.per_file_ignores.iter() {
|
||||
value.hash(state);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -218,22 +230,23 @@ impl Exclusion {
|
|||
/// Struct to render user-facing Settings.
|
||||
#[derive(Debug)]
|
||||
pub struct CurrentSettings {
|
||||
pub pyproject: Option<PathBuf>,
|
||||
pub project_root: Option<PathBuf>,
|
||||
pub line_length: usize,
|
||||
pub dummy_variable_rgx: Regex,
|
||||
pub exclude: Vec<Exclusion>,
|
||||
pub extend_exclude: Vec<Exclusion>,
|
||||
pub select: BTreeSet<CheckCode>,
|
||||
pub extend_ignore: Vec<CheckCode>,
|
||||
pub extend_select: Vec<CheckCode>,
|
||||
pub ignore: Vec<CheckCode>,
|
||||
pub line_length: usize,
|
||||
pub per_file_ignores: Vec<PerFileIgnore>,
|
||||
pub dummy_variable_rgx: Regex,
|
||||
pub project_root: Option<PathBuf>,
|
||||
pub pyproject: Option<PathBuf>,
|
||||
pub select: Vec<CheckCode>,
|
||||
}
|
||||
|
||||
impl CurrentSettings {
|
||||
pub fn from_settings(settings: Settings) -> Self {
|
||||
pub fn from_settings(settings: RawSettings) -> Self {
|
||||
Self {
|
||||
pyproject: settings.pyproject,
|
||||
project_root: settings.project_root,
|
||||
line_length: settings.line_length,
|
||||
dummy_variable_rgx: settings.dummy_variable_rgx,
|
||||
exclude: settings
|
||||
.exclude
|
||||
.into_iter()
|
||||
|
@ -244,9 +257,14 @@ impl CurrentSettings {
|
|||
.into_iter()
|
||||
.map(Exclusion::from_file_pattern)
|
||||
.collect(),
|
||||
select: settings.select,
|
||||
extend_ignore: settings.extend_ignore,
|
||||
extend_select: settings.extend_select,
|
||||
ignore: settings.ignore,
|
||||
line_length: settings.line_length,
|
||||
per_file_ignores: settings.per_file_ignores,
|
||||
dummy_variable_rgx: settings.dummy_variable_rgx,
|
||||
project_root: settings.project_root,
|
||||
pyproject: settings.pyproject,
|
||||
select: settings.select,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue