[flake8-simplify] Add autofix for contextlib.suppress (SIM105) (#3915)

This commit is contained in:
Leiser Fernández Gallo 2023-04-10 00:45:19 +02:00 committed by GitHub
parent 311ba29d0f
commit 002caadf9e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 143 additions and 25 deletions

View file

@ -1,36 +1,44 @@
use rustpython_parser::ast::{Excepthandler, ExcepthandlerKind, Located, Stmt, StmtKind};
use rustpython_parser::ast::{Excepthandler, ExcepthandlerKind, Located, Location, Stmt, StmtKind};
use ruff_diagnostics::{Diagnostic, Violation};
use ruff_diagnostics::{AlwaysAutofixableViolation, Diagnostic, Edit, Fix};
use ruff_macros::{derive_message_formats, violation};
use ruff_python_ast::call_path::compose_call_path;
use ruff_python_ast::helpers;
use ruff_python_ast::types::Range;
use crate::autofix::actions::get_or_import_symbol;
use crate::checkers::ast::Checker;
use crate::registry::AsRule;
#[violation]
pub struct SuppressibleException {
pub exception: String,
}
impl Violation for SuppressibleException {
impl AlwaysAutofixableViolation for SuppressibleException {
#[derive_message_formats]
fn message(&self) -> String {
let SuppressibleException { exception } = self;
format!("Use `contextlib.suppress({exception})` instead of try-except-pass")
format!("Use `contextlib.suppress({exception})` instead of `try`-`except`-`pass`")
}
fn autofix_title(&self) -> String {
let SuppressibleException { exception } = self;
format!("Replace with `contextlib.suppress({exception})`")
}
}
/// SIM105
pub fn suppressible_exception(
checker: &mut Checker,
stmt: &Stmt,
body: &[Stmt],
try_body: &[Stmt],
handlers: &[Excepthandler],
orelse: &[Stmt],
finalbody: &[Stmt],
) {
if !matches!(
body,
try_body,
[Located {
node: StmtKind::Delete { .. }
| StmtKind::Assign { .. }
@ -62,10 +70,36 @@ pub fn suppressible_exception(
} else {
handler_names.join(", ")
};
checker.diagnostics.push(Diagnostic::new(
SuppressibleException { exception },
let mut diagnostic = Diagnostic::new(
SuppressibleException {
exception: exception.clone(),
},
Range::from(stmt),
));
);
if checker.patch(diagnostic.kind.rule()) {
diagnostic.try_set_fix(|| {
let (import_edit, binding) = get_or_import_symbol(
"contextlib",
"suppress",
&checker.ctx,
&checker.importer,
checker.locator,
)?;
let try_ending = stmt.location.with_col_offset(3); // size of "try"
let replace_try = Edit::replacement(
format!("with {binding}({exception})"),
stmt.location,
try_ending,
);
let handler_line_begin = Location::new(handler.location.row(), 0);
let remove_handler =
Edit::deletion(handler_line_begin, handler.end_location.unwrap());
Ok(Fix::from_iter([import_edit, replace_try, remove_handler]))
});
}
checker.diagnostics.push(diagnostic);
}
}
}

View file

@ -4,9 +4,9 @@ expression: diagnostics
---
- kind:
name: SuppressibleException
body: "Use `contextlib.suppress(ValueError)` instead of try-except-pass"
suggestion: ~
fixable: false
body: "Use `contextlib.suppress(ValueError)` instead of `try`-`except`-`pass`"
suggestion: "Replace with `contextlib.suppress(ValueError)`"
fixable: true
location:
row: 4
column: 0
@ -14,13 +14,34 @@ expression: diagnostics
row: 7
column: 8
fix:
edits: []
edits:
- content: "import contextlib\n"
location:
row: 1
column: 0
end_location:
row: 1
column: 0
- content: with contextlib.suppress(ValueError)
location:
row: 4
column: 0
end_location:
row: 4
column: 3
- content: ""
location:
row: 6
column: 0
end_location:
row: 7
column: 8
parent: ~
- kind:
name: SuppressibleException
body: "Use `contextlib.suppress(ValueError, OSError)` instead of try-except-pass"
suggestion: ~
fixable: false
body: "Use `contextlib.suppress(ValueError, OSError)` instead of `try`-`except`-`pass`"
suggestion: "Replace with `contextlib.suppress(ValueError, OSError)`"
fixable: true
location:
row: 9
column: 0
@ -28,13 +49,34 @@ expression: diagnostics
row: 12
column: 8
fix:
edits: []
edits:
- content: "import contextlib\n"
location:
row: 1
column: 0
end_location:
row: 1
column: 0
- content: "with contextlib.suppress(ValueError, OSError)"
location:
row: 9
column: 0
end_location:
row: 9
column: 3
- content: ""
location:
row: 11
column: 0
end_location:
row: 12
column: 8
parent: ~
- kind:
name: SuppressibleException
body: "Use `contextlib.suppress(Exception)` instead of try-except-pass"
suggestion: ~
fixable: false
body: "Use `contextlib.suppress(Exception)` instead of `try`-`except`-`pass`"
suggestion: "Replace with `contextlib.suppress(Exception)`"
fixable: true
location:
row: 14
column: 0
@ -42,13 +84,34 @@ expression: diagnostics
row: 17
column: 8
fix:
edits: []
edits:
- content: "import contextlib\n"
location:
row: 1
column: 0
end_location:
row: 1
column: 0
- content: with contextlib.suppress(Exception)
location:
row: 14
column: 0
end_location:
row: 14
column: 3
- content: ""
location:
row: 16
column: 0
end_location:
row: 17
column: 8
parent: ~
- kind:
name: SuppressibleException
body: "Use `contextlib.suppress(a.Error, b.Error)` instead of try-except-pass"
suggestion: ~
fixable: false
body: "Use `contextlib.suppress(a.Error, b.Error)` instead of `try`-`except`-`pass`"
suggestion: "Replace with `contextlib.suppress(a.Error, b.Error)`"
fixable: true
location:
row: 19
column: 0
@ -56,6 +119,27 @@ expression: diagnostics
row: 22
column: 8
fix:
edits: []
edits:
- content: "import contextlib\n"
location:
row: 1
column: 0
end_location:
row: 1
column: 0
- content: "with contextlib.suppress(a.Error, b.Error)"
location:
row: 19
column: 0
end_location:
row: 19
column: 3
- content: ""
location:
row: 21
column: 0
end_location:
row: 22
column: 8
parent: ~