refactor: Merge Settings.enabled and Settings.fixable

The Settings struct previously contained the fields:

     pub enabled: HashableHashSet<RuleCode>,
     pub fixable: HashableHashSet<RuleCode>,

This commit merges both fields into one by introducing a new
RuleTable type, wrapping HashableHashMap<RuleCode, bool>,
which has the following benefits:

1. It makes the invalid state that a rule is
   disabled but fixable unrepresentable.

2. It encapsulates the implementation details of the table.
   (It currently uses an FxHashMap but that may change.)

3. It results in more readable code.

       settings.rules.enabled(rule)
       settings.rules.should_fix(rule)

   is more readable than:

       settings.enabled.contains(rule)
       settings.fixable.contains(rule)
This commit is contained in:
Martin Fischer 2023-01-17 10:02:25 +01:00 committed by Charlie Marsh
parent 580da1fa6b
commit a6566b1b34
30 changed files with 758 additions and 685 deletions

View file

@ -114,7 +114,7 @@ pub fn run(
.unwrap_or_else(|(path, message)| {
if let Some(path) = &path {
let settings = resolver.resolve(path, pyproject_strategy);
if settings.enabled.contains(&RuleCode::E902) {
if settings.rules.enabled(&RuleCode::E902) {
Diagnostics::new(vec![Message {
kind: IOError(message).into(),
location: Location::default(),

File diff suppressed because it is too large Load diff

View file

@ -36,7 +36,7 @@ pub fn check_imports(
// Enforce import rules.
let mut diagnostics = vec![];
if settings.enabled.contains(&RuleCode::I001) {
if settings.rules.enabled(&RuleCode::I001) {
for block in &blocks {
if !block.imports.is_empty() {
if let Some(diagnostic) = isort::rules::organize_imports(
@ -47,7 +47,7 @@ pub fn check_imports(
}
}
}
if settings.enabled.contains(&RuleCode::I002) {
if settings.rules.enabled(&RuleCode::I002) {
diagnostics.extend(isort::rules::add_required_imports(
&blocks, python_ast, locator, settings, autofix,
));

View file

@ -17,12 +17,12 @@ pub fn check_lines(
) -> Vec<Diagnostic> {
let mut diagnostics: Vec<Diagnostic> = vec![];
let enforce_blanket_noqa = settings.enabled.contains(&RuleCode::PGH004);
let enforce_blanket_type_ignore = settings.enabled.contains(&RuleCode::PGH003);
let enforce_doc_line_too_long = settings.enabled.contains(&RuleCode::W505);
let enforce_line_too_long = settings.enabled.contains(&RuleCode::E501);
let enforce_no_newline_at_end_of_file = settings.enabled.contains(&RuleCode::W292);
let enforce_unnecessary_coding_comment = settings.enabled.contains(&RuleCode::UP009);
let enforce_blanket_noqa = settings.rules.enabled(&RuleCode::PGH004);
let enforce_blanket_type_ignore = settings.rules.enabled(&RuleCode::PGH003);
let enforce_doc_line_too_long = settings.rules.enabled(&RuleCode::W505);
let enforce_line_too_long = settings.rules.enabled(&RuleCode::E501);
let enforce_no_newline_at_end_of_file = settings.rules.enabled(&RuleCode::W292);
let enforce_unnecessary_coding_comment = settings.rules.enabled(&RuleCode::UP009);
let mut commented_lines_iter = commented_lines.iter().peekable();
let mut doc_lines_iter = doc_lines.iter().peekable();
@ -37,7 +37,7 @@ pub fn check_lines(
index,
line,
matches!(autofix, flags::Autofix::Enabled)
&& settings.fixable.contains(&RuleCode::UP009),
&& settings.rules.should_fix(&RuleCode::UP009),
) {
diagnostics.push(diagnostic);
}
@ -79,7 +79,7 @@ pub fn check_lines(
if let Some(diagnostic) = no_newline_at_end_of_file(
contents,
matches!(autofix, flags::Autofix::Enabled)
&& settings.fixable.contains(&RuleCode::W292),
&& settings.rules.should_fix(&RuleCode::W292),
) {
diagnostics.push(diagnostic);
}

View file

@ -24,7 +24,7 @@ pub fn check_noqa(
let mut noqa_directives: IntMap<usize, (Directive, Vec<&str>)> = IntMap::default();
let mut ignored = vec![];
let enforce_noqa = settings.enabled.contains(&RuleCode::RUF100);
let enforce_noqa = settings.rules.enabled(&RuleCode::RUF100);
let lines: Vec<&str> = contents.lines().collect();
for lineno in commented_lines {
@ -108,7 +108,7 @@ pub fn check_noqa(
Range::new(Location::new(row + 1, start), Location::new(row + 1, end)),
);
if matches!(autofix, flags::Autofix::Enabled)
&& settings.fixable.contains(diagnostic.kind.code())
&& settings.rules.should_fix(diagnostic.kind.code())
{
diagnostic.amend(Fix::deletion(
Location::new(row + 1, start - spaces),
@ -135,7 +135,7 @@ pub fn check_noqa(
valid_codes.push(code);
} else {
if let Ok(rule_code) = RuleCode::from_str(code) {
if settings.enabled.contains(&rule_code) {
if settings.rules.enabled(&rule_code) {
unmatched_codes.push(code);
} else {
disabled_codes.push(code);
@ -172,7 +172,7 @@ pub fn check_noqa(
Range::new(Location::new(row + 1, start), Location::new(row + 1, end)),
);
if matches!(autofix, flags::Autofix::Enabled)
&& settings.fixable.contains(diagnostic.kind.code())
&& settings.rules.should_fix(diagnostic.kind.code())
{
if valid_codes.is_empty() {
diagnostic.amend(Fix::deletion(

View file

@ -19,20 +19,20 @@ pub fn check_tokens(
) -> Vec<Diagnostic> {
let mut diagnostics: Vec<Diagnostic> = vec![];
let enforce_ambiguous_unicode_character = settings.enabled.contains(&RuleCode::RUF001)
|| settings.enabled.contains(&RuleCode::RUF002)
|| settings.enabled.contains(&RuleCode::RUF003);
let enforce_quotes = settings.enabled.contains(&RuleCode::Q000)
|| settings.enabled.contains(&RuleCode::Q001)
|| settings.enabled.contains(&RuleCode::Q002)
|| settings.enabled.contains(&RuleCode::Q003);
let enforce_commented_out_code = settings.enabled.contains(&RuleCode::ERA001);
let enforce_invalid_escape_sequence = settings.enabled.contains(&RuleCode::W605);
let enforce_implicit_string_concatenation = settings.enabled.contains(&RuleCode::ISC001)
|| settings.enabled.contains(&RuleCode::ISC002);
let enforce_trailing_comma = settings.enabled.contains(&RuleCode::COM812)
|| settings.enabled.contains(&RuleCode::COM818)
|| settings.enabled.contains(&RuleCode::COM819);
let enforce_ambiguous_unicode_character = settings.rules.enabled(&RuleCode::RUF001)
|| settings.rules.enabled(&RuleCode::RUF002)
|| settings.rules.enabled(&RuleCode::RUF003);
let enforce_quotes = settings.rules.enabled(&RuleCode::Q000)
|| settings.rules.enabled(&RuleCode::Q001)
|| settings.rules.enabled(&RuleCode::Q002)
|| settings.rules.enabled(&RuleCode::Q003);
let enforce_commented_out_code = settings.rules.enabled(&RuleCode::ERA001);
let enforce_invalid_escape_sequence = settings.rules.enabled(&RuleCode::W605);
let enforce_implicit_string_concatenation =
settings.rules.enabled(&RuleCode::ISC001) || settings.rules.enabled(&RuleCode::ISC002);
let enforce_trailing_comma = settings.rules.enabled(&RuleCode::COM812)
|| settings.rules.enabled(&RuleCode::COM818)
|| settings.rules.enabled(&RuleCode::COM819);
let mut state_machine = StateMachine::default();
for &(start, ref tok, end) in tokens.iter().flatten() {
@ -75,7 +75,7 @@ pub fn check_tokens(
settings,
autofix,
) {
if settings.enabled.contains(diagnostic.kind.code()) {
if settings.rules.enabled(diagnostic.kind.code()) {
diagnostics.push(diagnostic);
}
}
@ -101,7 +101,7 @@ pub fn check_tokens(
start,
end,
matches!(autofix, flags::Autofix::Enabled)
&& settings.fixable.contains(&RuleCode::W605),
&& settings.rules.should_fix(&RuleCode::W605),
));
}
}
@ -112,7 +112,7 @@ pub fn check_tokens(
diagnostics.extend(
flake8_implicit_str_concat::rules::implicit(tokens)
.into_iter()
.filter(|diagnostic| settings.enabled.contains(diagnostic.kind.code())),
.filter(|diagnostic| settings.rules.enabled(diagnostic.kind.code())),
);
}
@ -121,7 +121,7 @@ pub fn check_tokens(
diagnostics.extend(
flake8_commas::rules::trailing_commas(tokens, locator)
.into_iter()
.filter(|diagnostic| settings.enabled.contains(diagnostic.kind.code())),
.filter(|diagnostic| settings.rules.enabled(diagnostic.kind.code())),
);
}

View file

@ -18,8 +18,8 @@ bitflags! {
impl Flags {
pub fn from_settings(settings: &Settings) -> Self {
if settings
.enabled
.iter()
.rules
.iter_enabled()
.any(|rule_code| matches!(rule_code.lint_source(), LintSource::Imports))
{
Flags::NOQA | Flags::ISORT

View file

@ -47,7 +47,7 @@ pub fn check_path(
// Collect doc lines. This requires a rare mix of tokens (for comments) and AST
// (for docstrings), which demands special-casing at this level.
let use_doc_lines = settings.enabled.contains(&RuleCode::W505);
let use_doc_lines = settings.rules.enabled(&RuleCode::W505);
let mut doc_lines = vec![];
if use_doc_lines {
doc_lines.extend(doc_lines_from_tokens(&tokens));
@ -55,8 +55,8 @@ pub fn check_path(
// Run the token-based rules.
if settings
.enabled
.iter()
.rules
.iter_enabled()
.any(|rule_code| matches!(rule_code.lint_source(), LintSource::Tokens))
{
diagnostics.extend(check_tokens(locator, &tokens, settings, autofix));
@ -64,13 +64,13 @@ pub fn check_path(
// Run the AST-based rules.
let use_ast = settings
.enabled
.iter()
.rules
.iter_enabled()
.any(|rule_code| matches!(rule_code.lint_source(), LintSource::Ast));
let use_imports = !directives.isort.skip_file
&& settings
.enabled
.iter()
.rules
.iter_enabled()
.any(|rule_code| matches!(rule_code.lint_source(), LintSource::Imports));
if use_ast || use_imports || use_doc_lines {
match rustpython_helpers::parse_program_tokens(tokens, "<filename>") {
@ -106,7 +106,7 @@ pub fn check_path(
}
}
Err(parse_error) => {
if settings.enabled.contains(&RuleCode::E999) {
if settings.rules.enabled(&RuleCode::E999) {
diagnostics.push(Diagnostic::new(
violations::SyntaxError(parse_error.error.to_string()),
Range::new(parse_error.location, parse_error.location),
@ -124,8 +124,8 @@ pub fn check_path(
// Run the lines-based rules.
if settings
.enabled
.iter()
.rules
.iter_enabled()
.any(|rule_code| matches!(rule_code.lint_source(), LintSource::Lines))
{
diagnostics.extend(check_lines(
@ -140,8 +140,8 @@ pub fn check_path(
// Enforce `noqa` directives.
if (matches!(noqa, flags::Noqa::Enabled) && !diagnostics.is_empty())
|| settings
.enabled
.iter()
.rules
.iter_enabled()
.any(|rule_code| matches!(rule_code.lint_source(), LintSource::NoQa))
{
check_noqa(

View file

@ -35,7 +35,7 @@ pub fn commented_out_code(
if is_standalone_comment(&line) && comment_contains_code(&line, &settings.task_tags[..]) {
let mut diagnostic = Diagnostic::new(violations::CommentedOutCode, Range::new(start, end));
if matches!(autofix, flags::Autofix::Enabled)
&& settings.fixable.contains(&RuleCode::ERA001)
&& settings.rules.should_fix(&RuleCode::ERA001)
{
diagnostic.amend(Fix::deletion(location, end_location));
}

View file

@ -27,14 +27,13 @@ pub fn subscript(checker: &mut Checker, value: &Expr, slice: &Expr) {
..
} = &upper.node
{
if *i == BigInt::from(1) && checker.settings.enabled.contains(&RuleCode::YTT303)
{
if *i == BigInt::from(1) && checker.settings.rules.enabled(&RuleCode::YTT303) {
checker.diagnostics.push(Diagnostic::new(
violations::SysVersionSlice1Referenced,
Range::from_located(value),
));
} else if *i == BigInt::from(3)
&& checker.settings.enabled.contains(&RuleCode::YTT101)
&& checker.settings.rules.enabled(&RuleCode::YTT101)
{
checker.diagnostics.push(Diagnostic::new(
violations::SysVersionSlice3Referenced,
@ -48,13 +47,12 @@ pub fn subscript(checker: &mut Checker, value: &Expr, slice: &Expr) {
value: Constant::Int(i),
..
} => {
if *i == BigInt::from(2) && checker.settings.enabled.contains(&RuleCode::YTT102) {
if *i == BigInt::from(2) && checker.settings.rules.enabled(&RuleCode::YTT102) {
checker.diagnostics.push(Diagnostic::new(
violations::SysVersion2Referenced,
Range::from_located(value),
));
} else if *i == BigInt::from(0)
&& checker.settings.enabled.contains(&RuleCode::YTT301)
} else if *i == BigInt::from(0) && checker.settings.rules.enabled(&RuleCode::YTT301)
{
checker.diagnostics.push(Diagnostic::new(
violations::SysVersion0Referenced,
@ -91,7 +89,7 @@ pub fn compare(checker: &mut Checker, left: &Expr, ops: &[Cmpop], comparators: &
) = (ops, comparators)
{
if *n == BigInt::from(3)
&& checker.settings.enabled.contains(&RuleCode::YTT201)
&& checker.settings.rules.enabled(&RuleCode::YTT201)
{
checker.diagnostics.push(Diagnostic::new(
violations::SysVersionInfo0Eq3Referenced,
@ -112,7 +110,7 @@ pub fn compare(checker: &mut Checker, left: &Expr, ops: &[Cmpop], comparators: &
}],
) = (ops, comparators)
{
if checker.settings.enabled.contains(&RuleCode::YTT203) {
if checker.settings.rules.enabled(&RuleCode::YTT203) {
checker.diagnostics.push(Diagnostic::new(
violations::SysVersionInfo1CmpInt,
Range::from_located(left),
@ -138,7 +136,7 @@ pub fn compare(checker: &mut Checker, left: &Expr, ops: &[Cmpop], comparators: &
}],
) = (ops, comparators)
{
if checker.settings.enabled.contains(&RuleCode::YTT204) {
if checker.settings.rules.enabled(&RuleCode::YTT204) {
checker.diagnostics.push(Diagnostic::new(
violations::SysVersionInfoMinorCmpInt,
Range::from_located(left),
@ -164,13 +162,13 @@ pub fn compare(checker: &mut Checker, left: &Expr, ops: &[Cmpop], comparators: &
) = (ops, comparators)
{
if s.len() == 1 {
if checker.settings.enabled.contains(&RuleCode::YTT302) {
if checker.settings.rules.enabled(&RuleCode::YTT302) {
checker.diagnostics.push(Diagnostic::new(
violations::SysVersionCmpStr10,
Range::from_located(left),
));
}
} else if checker.settings.enabled.contains(&RuleCode::YTT103) {
} else if checker.settings.rules.enabled(&RuleCode::YTT103) {
checker.diagnostics.push(Diagnostic::new(
violations::SysVersionCmpStr3,
Range::from_located(left),

View file

@ -85,14 +85,14 @@ pub fn definition(checker: &mut Checker, definition: &Definition, visibility: &V
.chain(args.kwonlyargs.iter())
{
if let Some(expr) = &arg.node.annotation {
if checker.settings.enabled.contains(&RuleCode::ANN401) {
if checker.settings.rules.enabled(&RuleCode::ANN401) {
check_dynamically_typed(checker, expr, || arg.node.arg.to_string());
};
} else {
if !(checker.settings.flake8_annotations.suppress_dummy_args
&& checker.settings.dummy_variable_rgx.is_match(&arg.node.arg))
{
if checker.settings.enabled.contains(&RuleCode::ANN001) {
if checker.settings.rules.enabled(&RuleCode::ANN001) {
checker.diagnostics.push(Diagnostic::new(
violations::MissingTypeFunctionArgument(arg.node.arg.to_string()),
Range::from_located(arg),
@ -106,7 +106,7 @@ pub fn definition(checker: &mut Checker, definition: &Definition, visibility: &V
if let Some(arg) = &args.vararg {
if let Some(expr) = &arg.node.annotation {
if !checker.settings.flake8_annotations.allow_star_arg_any {
if checker.settings.enabled.contains(&RuleCode::ANN401) {
if checker.settings.rules.enabled(&RuleCode::ANN401) {
let name = arg.node.arg.to_string();
check_dynamically_typed(checker, expr, || format!("*{name}"));
}
@ -115,7 +115,7 @@ pub fn definition(checker: &mut Checker, definition: &Definition, visibility: &V
if !(checker.settings.flake8_annotations.suppress_dummy_args
&& checker.settings.dummy_variable_rgx.is_match(&arg.node.arg))
{
if checker.settings.enabled.contains(&RuleCode::ANN002) {
if checker.settings.rules.enabled(&RuleCode::ANN002) {
checker.diagnostics.push(Diagnostic::new(
violations::MissingTypeArgs(arg.node.arg.to_string()),
Range::from_located(arg),
@ -129,7 +129,7 @@ pub fn definition(checker: &mut Checker, definition: &Definition, visibility: &V
if let Some(arg) = &args.kwarg {
if let Some(expr) = &arg.node.annotation {
if !checker.settings.flake8_annotations.allow_star_arg_any {
if checker.settings.enabled.contains(&RuleCode::ANN401) {
if checker.settings.rules.enabled(&RuleCode::ANN401) {
let name = arg.node.arg.to_string();
check_dynamically_typed(checker, expr, || format!("**{name}"));
}
@ -138,7 +138,7 @@ pub fn definition(checker: &mut Checker, definition: &Definition, visibility: &V
if !(checker.settings.flake8_annotations.suppress_dummy_args
&& checker.settings.dummy_variable_rgx.is_match(&arg.node.arg))
{
if checker.settings.enabled.contains(&RuleCode::ANN003) {
if checker.settings.rules.enabled(&RuleCode::ANN003) {
checker.diagnostics.push(Diagnostic::new(
violations::MissingTypeKwargs(arg.node.arg.to_string()),
Range::from_located(arg),
@ -150,7 +150,7 @@ pub fn definition(checker: &mut Checker, definition: &Definition, visibility: &V
// ANN201, ANN202, ANN401
if let Some(expr) = &returns {
if checker.settings.enabled.contains(&RuleCode::ANN401) {
if checker.settings.rules.enabled(&RuleCode::ANN401) {
check_dynamically_typed(checker, expr, || name.to_string());
};
} else {
@ -164,7 +164,7 @@ pub fn definition(checker: &mut Checker, definition: &Definition, visibility: &V
match visibility {
Visibility::Public => {
if checker.settings.enabled.contains(&RuleCode::ANN201) {
if checker.settings.rules.enabled(&RuleCode::ANN201) {
checker.diagnostics.push(Diagnostic::new(
violations::MissingReturnTypePublicFunction(name.to_string()),
helpers::identifier_range(stmt, checker.locator),
@ -172,7 +172,7 @@ pub fn definition(checker: &mut Checker, definition: &Definition, visibility: &V
}
}
Visibility::Private => {
if checker.settings.enabled.contains(&RuleCode::ANN202) {
if checker.settings.rules.enabled(&RuleCode::ANN202) {
checker.diagnostics.push(Diagnostic::new(
violations::MissingReturnTypePrivateFunction(name.to_string()),
helpers::identifier_range(stmt, checker.locator),
@ -203,14 +203,14 @@ pub fn definition(checker: &mut Checker, definition: &Definition, visibility: &V
// ANN401 for dynamically typed arguments
if let Some(annotation) = &arg.node.annotation {
has_any_typed_arg = true;
if checker.settings.enabled.contains(&RuleCode::ANN401) {
if checker.settings.rules.enabled(&RuleCode::ANN401) {
check_dynamically_typed(checker, annotation, || arg.node.arg.to_string());
}
} else {
if !(checker.settings.flake8_annotations.suppress_dummy_args
&& checker.settings.dummy_variable_rgx.is_match(&arg.node.arg))
{
if checker.settings.enabled.contains(&RuleCode::ANN001) {
if checker.settings.rules.enabled(&RuleCode::ANN001) {
checker.diagnostics.push(Diagnostic::new(
violations::MissingTypeFunctionArgument(arg.node.arg.to_string()),
Range::from_located(arg),
@ -225,7 +225,7 @@ pub fn definition(checker: &mut Checker, definition: &Definition, visibility: &V
has_any_typed_arg = true;
if let Some(expr) = &arg.node.annotation {
if !checker.settings.flake8_annotations.allow_star_arg_any {
if checker.settings.enabled.contains(&RuleCode::ANN401) {
if checker.settings.rules.enabled(&RuleCode::ANN401) {
let name = arg.node.arg.to_string();
check_dynamically_typed(checker, expr, || format!("*{name}"));
}
@ -234,7 +234,7 @@ pub fn definition(checker: &mut Checker, definition: &Definition, visibility: &V
if !(checker.settings.flake8_annotations.suppress_dummy_args
&& checker.settings.dummy_variable_rgx.is_match(&arg.node.arg))
{
if checker.settings.enabled.contains(&RuleCode::ANN002) {
if checker.settings.rules.enabled(&RuleCode::ANN002) {
checker.diagnostics.push(Diagnostic::new(
violations::MissingTypeArgs(arg.node.arg.to_string()),
Range::from_located(arg),
@ -249,7 +249,7 @@ pub fn definition(checker: &mut Checker, definition: &Definition, visibility: &V
has_any_typed_arg = true;
if let Some(expr) = &arg.node.annotation {
if !checker.settings.flake8_annotations.allow_star_arg_any {
if checker.settings.enabled.contains(&RuleCode::ANN401) {
if checker.settings.rules.enabled(&RuleCode::ANN401) {
let name = arg.node.arg.to_string();
check_dynamically_typed(checker, expr, || format!("**{name}"));
}
@ -258,7 +258,7 @@ pub fn definition(checker: &mut Checker, definition: &Definition, visibility: &V
if !(checker.settings.flake8_annotations.suppress_dummy_args
&& checker.settings.dummy_variable_rgx.is_match(&arg.node.arg))
{
if checker.settings.enabled.contains(&RuleCode::ANN003) {
if checker.settings.rules.enabled(&RuleCode::ANN003) {
checker.diagnostics.push(Diagnostic::new(
violations::MissingTypeKwargs(arg.node.arg.to_string()),
Range::from_located(arg),
@ -273,14 +273,14 @@ pub fn definition(checker: &mut Checker, definition: &Definition, visibility: &V
if let Some(arg) = args.args.first() {
if arg.node.annotation.is_none() {
if visibility::is_classmethod(checker, cast::decorator_list(stmt)) {
if checker.settings.enabled.contains(&RuleCode::ANN102) {
if checker.settings.rules.enabled(&RuleCode::ANN102) {
checker.diagnostics.push(Diagnostic::new(
violations::MissingTypeCls(arg.node.arg.to_string()),
Range::from_located(arg),
));
}
} else {
if checker.settings.enabled.contains(&RuleCode::ANN101) {
if checker.settings.rules.enabled(&RuleCode::ANN101) {
checker.diagnostics.push(Diagnostic::new(
violations::MissingTypeSelf(arg.node.arg.to_string()),
Range::from_located(arg),
@ -293,7 +293,7 @@ pub fn definition(checker: &mut Checker, definition: &Definition, visibility: &V
// ANN201, ANN202
if let Some(expr) = &returns {
if checker.settings.enabled.contains(&RuleCode::ANN401) {
if checker.settings.rules.enabled(&RuleCode::ANN401) {
check_dynamically_typed(checker, expr, || name.to_string());
}
} else {
@ -306,14 +306,14 @@ pub fn definition(checker: &mut Checker, definition: &Definition, visibility: &V
}
if visibility::is_classmethod(checker, cast::decorator_list(stmt)) {
if checker.settings.enabled.contains(&RuleCode::ANN206) {
if checker.settings.rules.enabled(&RuleCode::ANN206) {
checker.diagnostics.push(Diagnostic::new(
violations::MissingReturnTypeClassMethod(name.to_string()),
helpers::identifier_range(stmt, checker.locator),
));
}
} else if visibility::is_staticmethod(checker, cast::decorator_list(stmt)) {
if checker.settings.enabled.contains(&RuleCode::ANN205) {
if checker.settings.rules.enabled(&RuleCode::ANN205) {
checker.diagnostics.push(Diagnostic::new(
violations::MissingReturnTypeStaticMethod(name.to_string()),
helpers::identifier_range(stmt, checker.locator),
@ -322,7 +322,7 @@ pub fn definition(checker: &mut Checker, definition: &Definition, visibility: &V
} else if visibility::is_init(cast::name(stmt)) {
// Allow omission of return annotation in `__init__` functions, as long as at
// least one argument is typed.
if checker.settings.enabled.contains(&RuleCode::ANN204) {
if checker.settings.rules.enabled(&RuleCode::ANN204) {
if !(checker.settings.flake8_annotations.mypy_init_return
&& has_any_typed_arg)
{
@ -342,7 +342,7 @@ pub fn definition(checker: &mut Checker, definition: &Definition, visibility: &V
}
}
} else if visibility::is_magic(cast::name(stmt)) {
if checker.settings.enabled.contains(&RuleCode::ANN204) {
if checker.settings.rules.enabled(&RuleCode::ANN204) {
checker.diagnostics.push(Diagnostic::new(
violations::MissingReturnTypeSpecialMethod(name.to_string()),
helpers::identifier_range(stmt, checker.locator),
@ -351,7 +351,7 @@ pub fn definition(checker: &mut Checker, definition: &Definition, visibility: &V
} else {
match visibility {
Visibility::Public => {
if checker.settings.enabled.contains(&RuleCode::ANN201) {
if checker.settings.rules.enabled(&RuleCode::ANN201) {
checker.diagnostics.push(Diagnostic::new(
violations::MissingReturnTypePublicFunction(name.to_string()),
helpers::identifier_range(stmt, checker.locator),
@ -359,7 +359,7 @@ pub fn definition(checker: &mut Checker, definition: &Definition, visibility: &V
}
}
Visibility::Private => {
if checker.settings.enabled.contains(&RuleCode::ANN202) {
if checker.settings.rules.enabled(&RuleCode::ANN202) {
checker.diagnostics.push(Diagnostic::new(
violations::MissingReturnTypePrivateFunction(name.to_string()),
helpers::identifier_range(stmt, checker.locator),

View file

@ -76,7 +76,7 @@ pub fn abstract_base_class(
let has_abstract_decorator = is_abstract(checker, decorator_list);
has_abstract_method |= has_abstract_decorator;
if !checker.settings.enabled.contains(&RuleCode::B027) {
if !checker.settings.rules.enabled(&RuleCode::B027) {
continue;
}
@ -87,7 +87,7 @@ pub fn abstract_base_class(
));
}
}
if checker.settings.enabled.contains(&RuleCode::B024) {
if checker.settings.rules.enabled(&RuleCode::B024) {
if !has_abstract_method {
checker.diagnostics.push(Diagnostic::new(
violations::AbstractBaseClassWithoutAbstractMethod(name.to_string()),

View file

@ -41,7 +41,7 @@ fn duplicate_handler_exceptions<'a>(
}
}
if checker.settings.enabled.contains(&RuleCode::B014) {
if checker.settings.rules.enabled(&RuleCode::B014) {
// TODO(charlie): Handle "BaseException" and redundant exception aliases.
if !duplicates.is_empty() {
let mut diagnostic = Diagnostic::new(
@ -105,7 +105,7 @@ pub fn duplicate_exceptions(checker: &mut Checker, handlers: &[Excepthandler]) {
}
}
if checker.settings.enabled.contains(&RuleCode::B025) {
if checker.settings.rules.enabled(&RuleCode::B025) {
for (name, exprs) in duplicates {
for expr in exprs {
checker.diagnostics.push(Diagnostic::new(

View file

@ -15,7 +15,7 @@ pub fn string_in_exception(checker: &mut Checker, exc: &Expr) {
value: Constant::Str(string),
..
} => {
if checker.settings.enabled.contains(&RuleCode::EM101) {
if checker.settings.rules.enabled(&RuleCode::EM101) {
if string.len() > checker.settings.flake8_errmsg.max_string_length {
checker.diagnostics.push(Diagnostic::new(
violations::RawStringInException,
@ -26,7 +26,7 @@ pub fn string_in_exception(checker: &mut Checker, exc: &Expr) {
}
// Check for f-strings
ExprKind::JoinedStr { .. } => {
if checker.settings.enabled.contains(&RuleCode::EM102) {
if checker.settings.rules.enabled(&RuleCode::EM102) {
checker.diagnostics.push(Diagnostic::new(
violations::FStringInException,
Range::from_located(first),
@ -35,7 +35,7 @@ pub fn string_in_exception(checker: &mut Checker, exc: &Expr) {
}
// Check for .format() calls
ExprKind::Call { func, .. } => {
if checker.settings.enabled.contains(&RuleCode::EM103) {
if checker.settings.rules.enabled(&RuleCode::EM103) {
if let ExprKind::Attribute { value, attr, .. } = &func.node {
if attr == "format" && matches!(value.node, ExprKind::Constant { .. }) {
checker.diagnostics.push(Diagnostic::new(

View file

@ -44,7 +44,7 @@ pub fn print_call(checker: &mut Checker, func: &Expr, keywords: &[Keyword]) {
}
};
if !checker.settings.enabled.contains(diagnostic.kind.code()) {
if !checker.settings.rules.enabled(diagnostic.kind.code()) {
return;
}

View file

@ -98,7 +98,7 @@ fn check_fixture_decorator(checker: &mut Checker, func_name: &str, decorator: &E
keywords,
..
} => {
if checker.settings.enabled.contains(&RuleCode::PT001)
if checker.settings.rules.enabled(&RuleCode::PT001)
&& !checker.settings.flake8_pytest_style.fixture_parentheses
&& args.is_empty()
&& keywords.is_empty()
@ -111,14 +111,14 @@ fn check_fixture_decorator(checker: &mut Checker, func_name: &str, decorator: &E
pytest_fixture_parentheses(checker, decorator, fix, "", "()");
}
if checker.settings.enabled.contains(&RuleCode::PT002) && !args.is_empty() {
if checker.settings.rules.enabled(&RuleCode::PT002) && !args.is_empty() {
checker.diagnostics.push(Diagnostic::new(
violations::FixturePositionalArgs(func_name.to_string()),
Range::from_located(decorator),
));
}
if checker.settings.enabled.contains(&RuleCode::PT003) {
if checker.settings.rules.enabled(&RuleCode::PT003) {
let scope_keyword = keywords
.iter()
.find(|kw| kw.node.arg == Some("scope".to_string()));
@ -134,7 +134,7 @@ fn check_fixture_decorator(checker: &mut Checker, func_name: &str, decorator: &E
}
}
_ => {
if checker.settings.enabled.contains(&RuleCode::PT001)
if checker.settings.rules.enabled(&RuleCode::PT001)
&& checker.settings.flake8_pytest_style.fixture_parentheses
{
let fix = Fix::insertion("()".to_string(), decorator.end_location.unwrap());
@ -152,7 +152,7 @@ fn check_fixture_returns(checker: &mut Checker, func: &Stmt, func_name: &str, bo
visitor.visit_stmt(stmt);
}
if checker.settings.enabled.contains(&RuleCode::PT005)
if checker.settings.rules.enabled(&RuleCode::PT005)
&& visitor.has_return_with_value
&& func_name.starts_with('_')
{
@ -160,7 +160,7 @@ fn check_fixture_returns(checker: &mut Checker, func: &Stmt, func_name: &str, bo
violations::IncorrectFixtureNameUnderscore(func_name.to_string()),
Range::from_located(func),
));
} else if checker.settings.enabled.contains(&RuleCode::PT004)
} else if checker.settings.rules.enabled(&RuleCode::PT004)
&& !visitor.has_return_with_value
&& !visitor.has_yield_from
&& !func_name.starts_with('_')
@ -171,7 +171,7 @@ fn check_fixture_returns(checker: &mut Checker, func: &Stmt, func_name: &str, bo
));
}
if checker.settings.enabled.contains(&RuleCode::PT022) {
if checker.settings.rules.enabled(&RuleCode::PT022) {
if let Some(stmt) = body.last() {
if let StmtKind::Expr { value, .. } = &stmt.node {
if let ExprKind::Yield { .. } = value.node {
@ -246,7 +246,7 @@ fn check_fixture_marks(checker: &mut Checker, decorators: &[Expr]) {
for mark in get_mark_decorators(decorators) {
let name = get_mark_name(mark);
if checker.settings.enabled.contains(&RuleCode::PT024) {
if checker.settings.rules.enabled(&RuleCode::PT024) {
if name == "asyncio" {
let mut diagnostic = Diagnostic::new(
violations::UnnecessaryAsyncioMarkOnFixture,
@ -261,7 +261,7 @@ fn check_fixture_marks(checker: &mut Checker, decorators: &[Expr]) {
}
}
if checker.settings.enabled.contains(&RuleCode::PT025) {
if checker.settings.rules.enabled(&RuleCode::PT025) {
if name == "usefixtures" {
let mut diagnostic = Diagnostic::new(
violations::ErroneousUseFixturesOnFixture,
@ -288,39 +288,39 @@ pub fn fixture(
) {
let decorator = get_fixture_decorator(checker, decorators);
if let Some(decorator) = decorator {
if checker.settings.enabled.contains(&RuleCode::PT001)
|| checker.settings.enabled.contains(&RuleCode::PT002)
|| checker.settings.enabled.contains(&RuleCode::PT003)
if checker.settings.rules.enabled(&RuleCode::PT001)
|| checker.settings.rules.enabled(&RuleCode::PT002)
|| checker.settings.rules.enabled(&RuleCode::PT003)
{
check_fixture_decorator(checker, func_name, decorator);
}
if checker.settings.enabled.contains(&RuleCode::PT020)
if checker.settings.rules.enabled(&RuleCode::PT020)
&& checker.settings.flake8_pytest_style.fixture_parentheses
{
check_fixture_decorator_name(checker, decorator);
}
if (checker.settings.enabled.contains(&RuleCode::PT004)
|| checker.settings.enabled.contains(&RuleCode::PT005)
|| checker.settings.enabled.contains(&RuleCode::PT022))
if (checker.settings.rules.enabled(&RuleCode::PT004)
|| checker.settings.rules.enabled(&RuleCode::PT005)
|| checker.settings.rules.enabled(&RuleCode::PT022))
&& !has_abstractmethod_decorator(decorators, checker)
{
check_fixture_returns(checker, func, func_name, body);
}
if checker.settings.enabled.contains(&RuleCode::PT021) {
if checker.settings.rules.enabled(&RuleCode::PT021) {
check_fixture_addfinalizer(checker, args, body);
}
if checker.settings.enabled.contains(&RuleCode::PT024)
|| checker.settings.enabled.contains(&RuleCode::PT025)
if checker.settings.rules.enabled(&RuleCode::PT024)
|| checker.settings.rules.enabled(&RuleCode::PT025)
{
check_fixture_marks(checker, decorators);
}
}
if checker.settings.enabled.contains(&RuleCode::PT019) && func_name.starts_with("test_") {
if checker.settings.rules.enabled(&RuleCode::PT019) && func_name.starts_with("test_") {
check_test_function_args(checker, args);
}
}

View file

@ -84,8 +84,8 @@ fn check_useless_usefixtures(checker: &mut Checker, decorator: &Expr) {
}
pub fn marks(checker: &mut Checker, decorators: &[Expr]) {
let enforce_parentheses = checker.settings.enabled.contains(&RuleCode::PT023);
let enforce_useless_usefixtures = checker.settings.enabled.contains(&RuleCode::PT026);
let enforce_parentheses = checker.settings.rules.enabled(&RuleCode::PT023);
let enforce_useless_usefixtures = checker.settings.rules.enabled(&RuleCode::PT026);
for mark in get_mark_decorators(decorators) {
if enforce_parentheses {

View file

@ -328,12 +328,12 @@ pub fn parametrize(checker: &mut Checker, decorators: &[Expr]) {
let decorator = get_parametrize_decorator(checker, decorators);
if let Some(decorator) = decorator {
if let ExprKind::Call { args, .. } = &decorator.node {
if checker.settings.enabled.contains(&RuleCode::PT006) {
if checker.settings.rules.enabled(&RuleCode::PT006) {
if let Some(arg) = args.get(0) {
check_names(checker, arg);
}
}
if checker.settings.enabled.contains(&RuleCode::PT007) {
if checker.settings.rules.enabled(&RuleCode::PT007) {
if let Some(arg) = args.get(1) {
check_values(checker, arg);
}

View file

@ -25,7 +25,7 @@ fn is_non_trivial_with_body(body: &[Stmt]) -> bool {
pub fn raises_call(checker: &mut Checker, func: &Expr, args: &[Expr], keywords: &[Keyword]) {
if is_pytest_raises(checker, func) {
if checker.settings.enabled.contains(&RuleCode::PT010) {
if checker.settings.rules.enabled(&RuleCode::PT010) {
if args.is_empty() && keywords.is_empty() {
checker.diagnostics.push(Diagnostic::new(
violations::RaisesWithoutException,
@ -34,7 +34,7 @@ pub fn raises_call(checker: &mut Checker, func: &Expr, args: &[Expr], keywords:
}
}
if checker.settings.enabled.contains(&RuleCode::PT011) {
if checker.settings.rules.enabled(&RuleCode::PT011) {
let match_keyword = keywords
.iter()
.find(|kw| kw.node.arg == Some("match".to_string()));

View file

@ -80,7 +80,7 @@ pub fn quotes(
violations::BadQuotesDocstring(quotes_settings.docstring_quotes.clone()),
Range::new(start, end),
);
if matches!(autofix, flags::Autofix::Enabled) && settings.fixable.contains(&RuleCode::Q002)
if matches!(autofix, flags::Autofix::Enabled) && settings.rules.should_fix(&RuleCode::Q002)
{
let quote_count = if is_multiline { 3 } else { 1 };
let string_contents = &raw_text[quote_count..raw_text.len() - quote_count];
@ -110,7 +110,7 @@ pub fn quotes(
Range::new(start, end),
);
if matches!(autofix, flags::Autofix::Enabled) && settings.fixable.contains(&RuleCode::Q001)
if matches!(autofix, flags::Autofix::Enabled) && settings.rules.should_fix(&RuleCode::Q001)
{
let string_contents = &raw_text[3..raw_text.len() - 3];
let quote = good_multiline(&quotes_settings.multiline_quotes);
@ -137,7 +137,7 @@ pub fn quotes(
let mut diagnostic =
Diagnostic::new(violations::AvoidQuoteEscape, Range::new(start, end));
if matches!(autofix, flags::Autofix::Enabled)
&& settings.fixable.contains(&RuleCode::Q003)
&& settings.rules.should_fix(&RuleCode::Q003)
{
let quote = bad_single(&quotes_settings.inline_quotes);
@ -193,7 +193,7 @@ pub fn quotes(
Range::new(start, end),
);
if matches!(autofix, flags::Autofix::Enabled)
&& settings.fixable.contains(&RuleCode::Q000)
&& settings.rules.should_fix(&RuleCode::Q000)
{
let quote = good_single(&quotes_settings.inline_quotes);
let mut fixed_contents =

View file

@ -226,7 +226,7 @@ fn superfluous_else_node(checker: &mut Checker, stmt: &Stmt, branch: Branch) ->
};
for child in body {
if matches!(child.node, StmtKind::Return { .. }) {
if checker.settings.enabled.contains(&RuleCode::RET505) {
if checker.settings.rules.enabled(&RuleCode::RET505) {
checker.diagnostics.push(Diagnostic::new(
violations::SuperfluousElseReturn(branch),
elif_else_range(stmt, checker.locator)
@ -236,7 +236,7 @@ fn superfluous_else_node(checker: &mut Checker, stmt: &Stmt, branch: Branch) ->
return true;
}
if matches!(child.node, StmtKind::Break) {
if checker.settings.enabled.contains(&RuleCode::RET508) {
if checker.settings.rules.enabled(&RuleCode::RET508) {
checker.diagnostics.push(Diagnostic::new(
violations::SuperfluousElseBreak(branch),
elif_else_range(stmt, checker.locator)
@ -246,7 +246,7 @@ fn superfluous_else_node(checker: &mut Checker, stmt: &Stmt, branch: Branch) ->
return true;
}
if matches!(child.node, StmtKind::Raise { .. }) {
if checker.settings.enabled.contains(&RuleCode::RET506) {
if checker.settings.rules.enabled(&RuleCode::RET506) {
checker.diagnostics.push(Diagnostic::new(
violations::SuperfluousElseRaise(branch),
elif_else_range(stmt, checker.locator)
@ -256,7 +256,7 @@ fn superfluous_else_node(checker: &mut Checker, stmt: &Stmt, branch: Branch) ->
return true;
}
if matches!(child.node, StmtKind::Continue) {
if checker.settings.enabled.contains(&RuleCode::RET507) {
if checker.settings.rules.enabled(&RuleCode::RET507) {
checker.diagnostics.push(Diagnostic::new(
violations::SuperfluousElseContinue(branch),
elif_else_range(stmt, checker.locator)
@ -319,10 +319,10 @@ pub fn function(checker: &mut Checker, body: &[Stmt]) {
visitor.stack
};
if checker.settings.enabled.contains(&RuleCode::RET505)
|| checker.settings.enabled.contains(&RuleCode::RET506)
|| checker.settings.enabled.contains(&RuleCode::RET507)
|| checker.settings.enabled.contains(&RuleCode::RET508)
if checker.settings.rules.enabled(&RuleCode::RET505)
|| checker.settings.rules.enabled(&RuleCode::RET506)
|| checker.settings.rules.enabled(&RuleCode::RET507)
|| checker.settings.rules.enabled(&RuleCode::RET508)
{
if superfluous_elif(checker, &stack) {
return;
@ -338,20 +338,20 @@ pub fn function(checker: &mut Checker, body: &[Stmt]) {
}
if !result_exists(&stack.returns) {
if checker.settings.enabled.contains(&RuleCode::RET501) {
if checker.settings.rules.enabled(&RuleCode::RET501) {
unnecessary_return_none(checker, &stack);
}
return;
}
if checker.settings.enabled.contains(&RuleCode::RET502) {
if checker.settings.rules.enabled(&RuleCode::RET502) {
implicit_return_value(checker, &stack);
}
if checker.settings.enabled.contains(&RuleCode::RET503) {
if checker.settings.rules.enabled(&RuleCode::RET503) {
implicit_return(checker, last_stmt);
}
if checker.settings.enabled.contains(&RuleCode::RET504) {
if checker.settings.rules.enabled(&RuleCode::RET504) {
for (_, expr) in &stack.returns {
if let Some(expr) = expr {
unnecessary_assign(checker, &stack, expr);

View file

@ -178,7 +178,7 @@ pub fn convert_for_loop_to_any_all(checker: &mut Checker, stmt: &Stmt, sibling:
Some(sibling) => return_values_for_siblings(stmt, sibling),
} {
if loop_info.return_value && !loop_info.next_return_value {
if checker.settings.enabled.contains(&RuleCode::SIM110) {
if checker.settings.rules.enabled(&RuleCode::SIM110) {
let contents = return_stmt(
"any",
loop_info.test,
@ -211,7 +211,7 @@ pub fn convert_for_loop_to_any_all(checker: &mut Checker, stmt: &Stmt, sibling:
}
if !loop_info.return_value && loop_info.next_return_value {
if checker.settings.enabled.contains(&RuleCode::SIM111) {
if checker.settings.rules.enabled(&RuleCode::SIM111) {
// Invert the condition.
let test = {
if let ExprKind::UnaryOp {

View file

@ -128,8 +128,8 @@ pub fn unused_arguments(
FunctionType::Function => {
if checker
.settings
.enabled
.contains(Argumentable::Function.rule_code())
.rules
.enabled(Argumentable::Function.rule_code())
&& !visibility::is_overload(checker, decorator_list)
{
function(
@ -150,8 +150,8 @@ pub fn unused_arguments(
FunctionType::Method => {
if checker
.settings
.enabled
.contains(Argumentable::Method.rule_code())
.rules
.enabled(Argumentable::Method.rule_code())
&& !helpers::is_empty(body)
&& (!visibility::is_magic(name)
|| visibility::is_init(name)
@ -179,8 +179,8 @@ pub fn unused_arguments(
FunctionType::ClassMethod => {
if checker
.settings
.enabled
.contains(Argumentable::ClassMethod.rule_code())
.rules
.enabled(Argumentable::ClassMethod.rule_code())
&& !helpers::is_empty(body)
&& (!visibility::is_magic(name)
|| visibility::is_init(name)
@ -208,8 +208,8 @@ pub fn unused_arguments(
FunctionType::StaticMethod => {
if checker
.settings
.enabled
.contains(Argumentable::StaticMethod.rule_code())
.rules
.enabled(Argumentable::StaticMethod.rule_code())
&& !helpers::is_empty(body)
&& (!visibility::is_magic(name)
|| visibility::is_init(name)
@ -239,8 +239,8 @@ pub fn unused_arguments(
ScopeKind::Lambda(Lambda { args, .. }) => {
if checker
.settings
.enabled
.contains(Argumentable::Lambda.rule_code())
.rules
.enabled(Argumentable::Lambda.rule_code())
{
function(
&Argumentable::Lambda,

View file

@ -125,7 +125,7 @@ fn add_required_import(
violations::MissingRequiredImport(required_import.clone()),
Range::new(Location::default(), Location::default()),
);
if matches!(autofix, flags::Autofix::Enabled) && settings.fixable.contains(&RuleCode::I002) {
if matches!(autofix, flags::Autofix::Enabled) && settings.rules.should_fix(&RuleCode::I002) {
// Determine the location at which the import should be inserted.
let splice = helpers::find_splice_location(python_ast, locator);

View file

@ -99,7 +99,7 @@ pub fn organize_imports(
} else {
let mut diagnostic = Diagnostic::new(violations::UnsortedImports, range);
if matches!(autofix, flags::Autofix::Enabled)
&& settings.fixable.contains(diagnostic.kind.code())
&& settings.rules.should_fix(diagnostic.kind.code())
{
diagnostic.amend(Fix::replacement(
indent(&expected, indentation),

View file

@ -34,7 +34,7 @@ pub fn not_missing(
match definition.kind {
DefinitionKind::Module => {
if checker.settings.enabled.contains(&RuleCode::D100) {
if checker.settings.rules.enabled(&RuleCode::D100) {
checker.diagnostics.push(Diagnostic::new(
violations::PublicModule,
Range::new(Location::new(1, 0), Location::new(1, 0)),
@ -43,7 +43,7 @@ pub fn not_missing(
false
}
DefinitionKind::Package => {
if checker.settings.enabled.contains(&RuleCode::D104) {
if checker.settings.rules.enabled(&RuleCode::D104) {
checker.diagnostics.push(Diagnostic::new(
violations::PublicPackage,
Range::new(Location::new(1, 0), Location::new(1, 0)),
@ -52,7 +52,7 @@ pub fn not_missing(
false
}
DefinitionKind::Class(stmt) => {
if checker.settings.enabled.contains(&RuleCode::D101) {
if checker.settings.rules.enabled(&RuleCode::D101) {
checker.diagnostics.push(Diagnostic::new(
violations::PublicClass,
identifier_range(stmt, checker.locator),
@ -61,7 +61,7 @@ pub fn not_missing(
false
}
DefinitionKind::NestedClass(stmt) => {
if checker.settings.enabled.contains(&RuleCode::D106) {
if checker.settings.rules.enabled(&RuleCode::D106) {
checker.diagnostics.push(Diagnostic::new(
violations::PublicNestedClass,
identifier_range(stmt, checker.locator),
@ -73,7 +73,7 @@ pub fn not_missing(
if is_overload(checker, cast::decorator_list(stmt)) {
true
} else {
if checker.settings.enabled.contains(&RuleCode::D103) {
if checker.settings.rules.enabled(&RuleCode::D103) {
checker.diagnostics.push(Diagnostic::new(
violations::PublicFunction,
identifier_range(stmt, checker.locator),
@ -88,7 +88,7 @@ pub fn not_missing(
{
true
} else if is_init(cast::name(stmt)) {
if checker.settings.enabled.contains(&RuleCode::D107) {
if checker.settings.rules.enabled(&RuleCode::D107) {
checker.diagnostics.push(Diagnostic::new(
violations::PublicInit,
identifier_range(stmt, checker.locator),
@ -96,7 +96,7 @@ pub fn not_missing(
}
true
} else if is_new(cast::name(stmt)) || is_call(cast::name(stmt)) {
if checker.settings.enabled.contains(&RuleCode::D102) {
if checker.settings.rules.enabled(&RuleCode::D102) {
checker.diagnostics.push(Diagnostic::new(
violations::PublicMethod,
identifier_range(stmt, checker.locator),
@ -104,7 +104,7 @@ pub fn not_missing(
}
true
} else if is_magic(cast::name(stmt)) {
if checker.settings.enabled.contains(&RuleCode::D105) {
if checker.settings.rules.enabled(&RuleCode::D105) {
checker.diagnostics.push(Diagnostic::new(
violations::MagicMethod,
identifier_range(stmt, checker.locator),
@ -112,7 +112,7 @@ pub fn not_missing(
}
true
} else {
if checker.settings.enabled.contains(&RuleCode::D102) {
if checker.settings.rules.enabled(&RuleCode::D102) {
checker.diagnostics.push(Diagnostic::new(
violations::PublicMethod,
identifier_range(stmt, checker.locator),
@ -163,7 +163,7 @@ pub fn blank_before_after_function(checker: &mut Checker, docstring: &Docstring)
return;
};
if checker.settings.enabled.contains(&RuleCode::D201) {
if checker.settings.rules.enabled(&RuleCode::D201) {
let (before, ..) = checker.locator.partition_source_code_at(
&Range::from_located(parent),
&Range::from_located(docstring.expr),
@ -191,7 +191,7 @@ pub fn blank_before_after_function(checker: &mut Checker, docstring: &Docstring)
}
}
if checker.settings.enabled.contains(&RuleCode::D202) {
if checker.settings.rules.enabled(&RuleCode::D202) {
let (_, _, after) = checker.locator.partition_source_code_at(
&Range::from_located(parent),
&Range::from_located(docstring.expr),
@ -242,8 +242,8 @@ pub fn blank_before_after_class(checker: &mut Checker, docstring: &Docstring) {
return;
};
if checker.settings.enabled.contains(&RuleCode::D203)
|| checker.settings.enabled.contains(&RuleCode::D211)
if checker.settings.rules.enabled(&RuleCode::D203)
|| checker.settings.rules.enabled(&RuleCode::D211)
{
let (before, ..) = checker.locator.partition_source_code_at(
&Range::from_located(parent),
@ -256,7 +256,7 @@ pub fn blank_before_after_class(checker: &mut Checker, docstring: &Docstring) {
.skip(1)
.take_while(|line| line.trim().is_empty())
.count();
if checker.settings.enabled.contains(&RuleCode::D211) {
if checker.settings.rules.enabled(&RuleCode::D211) {
if blank_lines_before != 0 {
let mut diagnostic = Diagnostic::new(
violations::NoBlankLineBeforeClass(blank_lines_before),
@ -272,7 +272,7 @@ pub fn blank_before_after_class(checker: &mut Checker, docstring: &Docstring) {
checker.diagnostics.push(diagnostic);
}
}
if checker.settings.enabled.contains(&RuleCode::D203) {
if checker.settings.rules.enabled(&RuleCode::D203) {
if blank_lines_before != 1 {
let mut diagnostic = Diagnostic::new(
violations::OneBlankLineBeforeClass(blank_lines_before),
@ -291,7 +291,7 @@ pub fn blank_before_after_class(checker: &mut Checker, docstring: &Docstring) {
}
}
if checker.settings.enabled.contains(&RuleCode::D204) {
if checker.settings.rules.enabled(&RuleCode::D204) {
let (_, _, after) = checker.locator.partition_source_code_at(
&Range::from_located(parent),
&Range::from_located(docstring.expr),
@ -409,7 +409,7 @@ pub fn indent(checker: &mut Checker, docstring: &Docstring) {
// yet.
has_seen_tab = has_seen_tab || line_indent.contains('\t');
if checker.settings.enabled.contains(&RuleCode::D207) {
if checker.settings.rules.enabled(&RuleCode::D207) {
// We report under-indentation on every line. This isn't great, but enables
// autofix.
if (i == lines.len() - 1 || !is_blank)
@ -448,7 +448,7 @@ pub fn indent(checker: &mut Checker, docstring: &Docstring) {
}
}
if checker.settings.enabled.contains(&RuleCode::D206) {
if checker.settings.rules.enabled(&RuleCode::D206) {
if has_seen_tab {
checker.diagnostics.push(Diagnostic::new(
violations::IndentWithSpaces,
@ -457,7 +457,7 @@ pub fn indent(checker: &mut Checker, docstring: &Docstring) {
}
}
if checker.settings.enabled.contains(&RuleCode::D208) {
if checker.settings.rules.enabled(&RuleCode::D208) {
// If every line (except the last) is over-indented...
if is_over_indented {
for i in over_indented_lines {
@ -605,14 +605,14 @@ pub fn multi_line_summary_start(checker: &mut Checker, docstring: &Docstring) {
return;
};
if constants::TRIPLE_QUOTE_PREFIXES.contains(&first_line) {
if checker.settings.enabled.contains(&RuleCode::D212) {
if checker.settings.rules.enabled(&RuleCode::D212) {
checker.diagnostics.push(Diagnostic::new(
violations::MultiLineSummaryFirstLine,
Range::from_located(docstring.expr),
));
}
} else {
if checker.settings.enabled.contains(&RuleCode::D213) {
if checker.settings.rules.enabled(&RuleCode::D213) {
checker.diagnostics.push(Diagnostic::new(
violations::MultiLineSummarySecondLine,
Range::from_located(docstring.expr),
@ -907,7 +907,7 @@ pub fn not_empty(checker: &mut Checker, docstring: &Docstring) -> bool {
return true;
}
if checker.settings.enabled.contains(&RuleCode::D419) {
if checker.settings.rules.enabled(&RuleCode::D419) {
checker.diagnostics.push(Diagnostic::new(
violations::NonEmpty,
Range::from_located(docstring.expr),
@ -970,7 +970,7 @@ fn blanks_and_section_underline(
// Nothing but blank lines after the section header.
if blank_lines_after_header == context.following_lines.len() {
if checker.settings.enabled.contains(&RuleCode::D407) {
if checker.settings.rules.enabled(&RuleCode::D407) {
let mut diagnostic = Diagnostic::new(
violations::DashedUnderlineAfterSection(context.section_name.to_string()),
Range::from_located(docstring.expr),
@ -992,7 +992,7 @@ fn blanks_and_section_underline(
}
checker.diagnostics.push(diagnostic);
}
if checker.settings.enabled.contains(&RuleCode::D414) {
if checker.settings.rules.enabled(&RuleCode::D414) {
checker.diagnostics.push(Diagnostic::new(
violations::NonEmptySection(context.section_name.to_string()),
Range::from_located(docstring.expr),
@ -1008,7 +1008,7 @@ fn blanks_and_section_underline(
if dash_line_found {
if blank_lines_after_header > 0 {
if checker.settings.enabled.contains(&RuleCode::D408) {
if checker.settings.rules.enabled(&RuleCode::D408) {
let mut diagnostic = Diagnostic::new(
violations::SectionUnderlineAfterName(context.section_name.to_string()),
Range::from_located(docstring.expr),
@ -1040,7 +1040,7 @@ fn blanks_and_section_underline(
.count()
!= context.section_name.len()
{
if checker.settings.enabled.contains(&RuleCode::D409) {
if checker.settings.rules.enabled(&RuleCode::D409) {
let mut diagnostic = Diagnostic::new(
violations::SectionUnderlineMatchesSectionLength(
context.section_name.to_string(),
@ -1077,7 +1077,7 @@ fn blanks_and_section_underline(
}
}
if checker.settings.enabled.contains(&RuleCode::D215) {
if checker.settings.rules.enabled(&RuleCode::D215) {
let leading_space = whitespace::leading_space(non_empty_line);
if leading_space.len() > docstring.indentation.len() {
let mut diagnostic = Diagnostic::new(
@ -1119,14 +1119,14 @@ fn blanks_and_section_underline(
.take_while(|line| line.trim().is_empty())
.count();
if blank_lines_after_dashes == rest_of_lines.len() {
if checker.settings.enabled.contains(&RuleCode::D414) {
if checker.settings.rules.enabled(&RuleCode::D414) {
checker.diagnostics.push(Diagnostic::new(
violations::NonEmptySection(context.section_name.to_string()),
Range::from_located(docstring.expr),
));
}
} else {
if checker.settings.enabled.contains(&RuleCode::D412) {
if checker.settings.rules.enabled(&RuleCode::D412) {
let mut diagnostic = Diagnostic::new(
violations::NoBlankLinesBetweenHeaderAndContent(
context.section_name.to_string(),
@ -1158,7 +1158,7 @@ fn blanks_and_section_underline(
}
}
} else {
if checker.settings.enabled.contains(&RuleCode::D414) {
if checker.settings.rules.enabled(&RuleCode::D414) {
checker.diagnostics.push(Diagnostic::new(
violations::NonEmptySection(context.section_name.to_string()),
Range::from_located(docstring.expr),
@ -1166,7 +1166,7 @@ fn blanks_and_section_underline(
}
}
} else {
if checker.settings.enabled.contains(&RuleCode::D407) {
if checker.settings.rules.enabled(&RuleCode::D407) {
let mut diagnostic = Diagnostic::new(
violations::DashedUnderlineAfterSection(context.section_name.to_string()),
Range::from_located(docstring.expr),
@ -1189,7 +1189,7 @@ fn blanks_and_section_underline(
checker.diagnostics.push(diagnostic);
}
if blank_lines_after_header > 0 {
if checker.settings.enabled.contains(&RuleCode::D412) {
if checker.settings.rules.enabled(&RuleCode::D412) {
let mut diagnostic = Diagnostic::new(
violations::NoBlankLinesBetweenHeaderAndContent(
context.section_name.to_string(),
@ -1224,7 +1224,7 @@ fn common_section(
context: &SectionContext,
style: &SectionStyle,
) {
if checker.settings.enabled.contains(&RuleCode::D405) {
if checker.settings.rules.enabled(&RuleCode::D405) {
if !style.section_names().contains(&context.section_name) {
let capitalized_section_name = titlecase::titlecase(context.section_name);
if style
@ -1260,7 +1260,7 @@ fn common_section(
}
}
if checker.settings.enabled.contains(&RuleCode::D214) {
if checker.settings.rules.enabled(&RuleCode::D214) {
let leading_space = whitespace::leading_space(context.line);
if leading_space.len() > docstring.indentation.len() {
let mut diagnostic = Diagnostic::new(
@ -1288,7 +1288,7 @@ fn common_section(
.map_or(true, |line| !line.trim().is_empty())
{
if context.is_last_section {
if checker.settings.enabled.contains(&RuleCode::D413) {
if checker.settings.rules.enabled(&RuleCode::D413) {
let mut diagnostic = Diagnostic::new(
violations::BlankLineAfterLastSection(context.section_name.to_string()),
Range::from_located(docstring.expr),
@ -1309,7 +1309,7 @@ fn common_section(
checker.diagnostics.push(diagnostic);
}
} else {
if checker.settings.enabled.contains(&RuleCode::D410) {
if checker.settings.rules.enabled(&RuleCode::D410) {
let mut diagnostic = Diagnostic::new(
violations::BlankLineAfterSection(context.section_name.to_string()),
Range::from_located(docstring.expr),
@ -1332,7 +1332,7 @@ fn common_section(
}
}
if checker.settings.enabled.contains(&RuleCode::D411) {
if checker.settings.rules.enabled(&RuleCode::D411) {
if !context.previous_line.is_empty() {
let mut diagnostic = Diagnostic::new(
violations::BlankLineBeforeSection(context.section_name.to_string()),
@ -1516,7 +1516,7 @@ fn parameters_section(checker: &mut Checker, docstring: &Docstring, context: &Se
fn numpy_section(checker: &mut Checker, docstring: &Docstring, context: &SectionContext) {
common_section(checker, docstring, context, &SectionStyle::Numpy);
if checker.settings.enabled.contains(&RuleCode::D406) {
if checker.settings.rules.enabled(&RuleCode::D406) {
let suffix = context
.line
.trim()
@ -1551,7 +1551,7 @@ fn numpy_section(checker: &mut Checker, docstring: &Docstring, context: &Section
}
}
if checker.settings.enabled.contains(&RuleCode::D417) {
if checker.settings.rules.enabled(&RuleCode::D417) {
let capitalized_section_name = titlecase::titlecase(context.section_name);
if capitalized_section_name == "Parameters" {
parameters_section(checker, docstring, context);
@ -1562,7 +1562,7 @@ fn numpy_section(checker: &mut Checker, docstring: &Docstring, context: &Section
fn google_section(checker: &mut Checker, docstring: &Docstring, context: &SectionContext) {
common_section(checker, docstring, context, &SectionStyle::Google);
if checker.settings.enabled.contains(&RuleCode::D416) {
if checker.settings.rules.enabled(&RuleCode::D416) {
let suffix = context
.line
.trim()
@ -1598,7 +1598,7 @@ fn google_section(checker: &mut Checker, docstring: &Docstring, context: &Sectio
}
}
if checker.settings.enabled.contains(&RuleCode::D417) {
if checker.settings.rules.enabled(&RuleCode::D417) {
let capitalized_section_name = titlecase::titlecase(context.section_name);
if capitalized_section_name == "Args" || capitalized_section_name == "Arguments" {
args_section(checker, docstring, context);

View file

@ -37,7 +37,7 @@ pub fn repeated_keys(checker: &mut Checker, keys: &[Expr], values: &[Expr]) {
if let Some(seen_values) = seen.get_mut(&key) {
match key {
DictionaryKey::Constant(..) => {
if checker.settings.enabled.contains(&RuleCode::F601) {
if checker.settings.rules.enabled(&RuleCode::F601) {
let comparable_value: ComparableExpr = (&values[i]).into();
let is_duplicate_value = seen_values.contains(&comparable_value);
let mut diagnostic = Diagnostic::new(
@ -61,7 +61,7 @@ pub fn repeated_keys(checker: &mut Checker, keys: &[Expr], values: &[Expr]) {
}
}
DictionaryKey::Variable(key) => {
if checker.settings.enabled.contains(&RuleCode::F602) {
if checker.settings.rules.enabled(&RuleCode::F602) {
let comparable_value: ComparableExpr = (&values[i]).into();
let is_duplicate_value = seen_values.contains(&comparable_value);
let mut diagnostic = Diagnostic::new(

View file

@ -1650,9 +1650,9 @@ pub fn ambiguous_unicode_character(
},
Range::new(location, end_location),
);
if settings.enabled.contains(diagnostic.kind.code()) {
if settings.rules.enabled(diagnostic.kind.code()) {
if matches!(autofix, flags::Autofix::Enabled)
&& settings.fixable.contains(diagnostic.kind.code())
&& settings.rules.should_fix(diagnostic.kind.code())
{
diagnostic.amend(Fix::replacement(
representant.to_string(),

View file

@ -16,6 +16,7 @@ use regex::Regex;
use rustc_hash::FxHashSet;
use self::hashable::{HashableGlobMatcher, HashableGlobSet, HashableHashSet, HashableRegex};
use self::rule_table::RuleTable;
use crate::cache::cache_dir;
use crate::registry::{RuleCode, RuleCodePrefix, SuffixLength, CATEGORIES, INCOMPATIBLE_CODES};
use crate::rules::{
@ -35,6 +36,7 @@ pub mod hashable;
pub mod options;
pub mod options_base;
pub mod pyproject;
mod rule_table;
pub mod types;
const CARGO_PKG_VERSION: &str = env!("CARGO_PKG_VERSION");
@ -77,8 +79,7 @@ pub struct CliSettings {
#[derive(Debug, Hash)]
#[allow(clippy::struct_excessive_bools)]
pub struct Settings {
pub enabled: HashableHashSet<RuleCode>,
pub fixable: HashableHashSet<RuleCode>,
pub rules: RuleTable,
pub per_file_ignores: Vec<(
HashableGlobMatcher,
HashableGlobMatcher,
@ -154,6 +155,15 @@ static DEFAULT_DUMMY_VARIABLE_RGX: Lazy<Regex> =
impl Settings {
pub fn from_configuration(config: Configuration, project_root: &Path) -> Result<Self> {
Ok(Self {
rules: build_rule_table(
config.fixable,
config.unfixable,
config.select,
config.ignore,
&config.extend_select,
&config.extend_ignore,
&config.pydocstyle,
),
allowed_confusables: config
.allowed_confusables
.map(FxHashSet::from_iter)
@ -164,53 +174,14 @@ impl Settings {
.dummy_variable_rgx
.unwrap_or_else(|| DEFAULT_DUMMY_VARIABLE_RGX.clone())
.into(),
enabled: validate_enabled(resolve_codes(
[RuleCodeSpec {
select: &config
.select
.unwrap_or_else(|| vec![RuleCodePrefix::E, RuleCodePrefix::F]),
ignore: &config.ignore.unwrap_or_default(),
}]
.into_iter()
.chain(
config
.extend_select
.iter()
.zip(config.extend_ignore.iter())
.map(|(select, ignore)| RuleCodeSpec { select, ignore }),
)
.chain(
// If a docstring convention is specified, force-disable any incompatible error
// codes.
if let Some(convention) = config
.pydocstyle
.as_ref()
.and_then(|pydocstyle| pydocstyle.convention)
{
Left(iter::once(RuleCodeSpec {
select: &[],
ignore: convention.codes(),
}))
} else {
Right(iter::empty())
},
),
))
.into(),
exclude: HashableGlobSet::new(
config.exclude.unwrap_or_else(|| DEFAULT_EXCLUDE.clone()),
)?,
extend_exclude: HashableGlobSet::new(config.extend_exclude)?,
external: FxHashSet::from_iter(config.external.unwrap_or_default()).into(),
fixable: resolve_codes(
[RuleCodeSpec {
select: &config.fixable.unwrap_or_else(|| CATEGORIES.to_vec()),
ignore: &config.unfixable.unwrap_or_default(),
}]
.into_iter(),
)
.into(),
force_exclude: config.force_exclude.unwrap_or(false),
ignore_init_module_imports: config.ignore_init_module_imports.unwrap_or_default(),
line_length: config.line_length.unwrap_or(88),
namespace_packages: config.namespace_packages.unwrap_or_default(),
@ -265,16 +236,15 @@ impl Settings {
#[cfg(test)]
pub fn for_rule(rule_code: RuleCode) -> Self {
Self {
rules: [rule_code].into(),
allowed_confusables: FxHashSet::from_iter([]).into(),
builtins: vec![],
dummy_variable_rgx: Regex::new("^(_+|(_+[a-zA-Z0-9_]*[a-zA-Z0-9]+?))$")
.unwrap()
.into(),
enabled: FxHashSet::from_iter([rule_code.clone()]).into(),
exclude: HashableGlobSet::empty(),
extend_exclude: HashableGlobSet::empty(),
external: HashableHashSet::default(),
fixable: FxHashSet::from_iter([rule_code]).into(),
force_exclude: false,
ignore_init_module_imports: false,
line_length: 88,
@ -308,16 +278,15 @@ impl Settings {
#[cfg(test)]
pub fn for_rules(rule_codes: Vec<RuleCode>) -> Self {
Self {
rules: rule_codes.into(),
allowed_confusables: HashableHashSet::default(),
builtins: vec![],
dummy_variable_rgx: Regex::new("^(_+|(_+[a-zA-Z0-9_]*[a-zA-Z0-9]+?))$")
.unwrap()
.into(),
enabled: FxHashSet::from_iter(rule_codes.clone()).into(),
exclude: HashableGlobSet::empty(),
extend_exclude: HashableGlobSet::empty(),
external: HashableHashSet::default(),
fixable: FxHashSet::from_iter(rule_codes).into(),
force_exclude: false,
ignore_init_module_imports: false,
line_length: 88,
@ -362,6 +331,59 @@ impl Settings {
}
}
fn build_rule_table(
fixable: Option<Vec<RuleCodePrefix>>,
unfixable: Option<Vec<RuleCodePrefix>>,
select: Option<Vec<RuleCodePrefix>>,
ignore: Option<Vec<RuleCodePrefix>>,
extend_select: &[Vec<RuleCodePrefix>],
extend_ignore: &[Vec<RuleCodePrefix>],
pydocstyle: &Option<pydocstyle::settings::Options>,
) -> RuleTable {
let mut rules = RuleTable::empty();
let fixable = resolve_codes(
[RuleCodeSpec {
select: &fixable.unwrap_or_else(|| CATEGORIES.to_vec()),
ignore: &unfixable.unwrap_or_default(),
}]
.into_iter(),
);
for code in validate_enabled(resolve_codes(
[RuleCodeSpec {
select: &select.unwrap_or_else(|| vec![RuleCodePrefix::E, RuleCodePrefix::F]),
ignore: &ignore.unwrap_or_default(),
}]
.into_iter()
.chain(
extend_select
.iter()
.zip(extend_ignore.iter())
.map(|(select, ignore)| RuleCodeSpec { select, ignore }),
)
.chain(
// If a docstring convention is specified, force-disable any incompatible error
// codes.
if let Some(convention) = pydocstyle
.as_ref()
.and_then(|pydocstyle| pydocstyle.convention)
{
Left(iter::once(RuleCodeSpec {
select: &[],
ignore: convention.codes(),
}))
} else {
Right(iter::empty())
},
),
)) {
let fix = fixable.contains(&code);
rules.enable(code, fix);
}
rules
}
/// Given a list of patterns, create a `GlobSet`.
pub fn resolve_per_file_ignores(
per_file_ignores: Vec<PerFileIgnore>,

View file

@ -0,0 +1,55 @@
use std::collections::hash_map;
use rustc_hash::FxHashMap;
use super::hashable::HashableHashMap;
use crate::registry::RuleCode;
/// A table to keep track of which rules are enabled
/// and whether or not they should be autofixed.
#[derive(Debug, Hash)]
pub struct RuleTable {
/// Maps rule codes to a boolean indicating if the rule should be autofixed.
enabled: HashableHashMap<RuleCode, bool>,
}
impl RuleTable {
/// Creates a new empty rule table.
pub fn empty() -> Self {
Self {
enabled: HashableHashMap::default(),
}
}
/// Returns whether the given rule should be checked.
pub fn enabled(&self, code: &RuleCode) -> bool {
self.enabled.contains_key(code)
}
/// Returns whether violations of the given rule should be autofixed.
pub fn should_fix(&self, code: &RuleCode) -> bool {
*self.enabled.get(code).unwrap_or(&false)
}
/// Returns an iterator over all enabled rules.
pub fn iter_enabled(&self) -> hash_map::Keys<RuleCode, bool> {
self.enabled.keys()
}
/// Enables the given rule.
pub fn enable(&mut self, code: RuleCode, should_fix: bool) {
self.enabled.insert(code, should_fix);
}
}
impl<I: IntoIterator<Item = RuleCode>> From<I> for RuleTable {
fn from(codes: I) -> Self {
let mut enabled = FxHashMap::default();
for code in codes {
enabled.insert(code, true);
}
Self {
enabled: enabled.into(),
}
}
}