mirror of
https://github.com/astral-sh/ruff.git
synced 2025-10-02 22:54:42 +00:00
Avoid raising TRY200 violations within new scopes (#3275)
This commit is contained in:
parent
1c79dff3bd
commit
67d1f74587
4 changed files with 82 additions and 84 deletions
|
@ -30,3 +30,11 @@ def good():
|
||||||
raise e # This is verbose violation, shouldn't trigger no cause
|
raise e # This is verbose violation, shouldn't trigger no cause
|
||||||
except Exception:
|
except Exception:
|
||||||
raise # Just re-raising don't need 'from'
|
raise # Just re-raising don't need 'from'
|
||||||
|
|
||||||
|
|
||||||
|
def good():
|
||||||
|
try:
|
||||||
|
from mod import f
|
||||||
|
except ImportError:
|
||||||
|
def f():
|
||||||
|
raise MyException() # Raising within a new scope is fine
|
||||||
|
|
|
@ -765,7 +765,7 @@ pub fn from_relative_import<'a>(module: &'a [String], name: &'a str) -> CallPath
|
||||||
call_path
|
call_path
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A [`Visitor`] that collects all return statements in a function or method.
|
/// A [`Visitor`] that collects all `return` statements in a function or method.
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct ReturnStatementVisitor<'a> {
|
pub struct ReturnStatementVisitor<'a> {
|
||||||
pub returns: Vec<Option<&'a Expr>>,
|
pub returns: Vec<Option<&'a Expr>>,
|
||||||
|
@ -786,6 +786,48 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A [`Visitor`] that collects all `raise` statements in a function or method.
|
||||||
|
#[derive(Default)]
|
||||||
|
pub struct RaiseStatementVisitor<'a> {
|
||||||
|
pub raises: Vec<(Range, Option<&'a Expr>, Option<&'a Expr>)>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, 'b> Visitor<'b> for RaiseStatementVisitor<'b>
|
||||||
|
where
|
||||||
|
'b: 'a,
|
||||||
|
{
|
||||||
|
fn visit_stmt(&mut self, stmt: &'b Stmt) {
|
||||||
|
match &stmt.node {
|
||||||
|
StmtKind::Raise { exc, cause } => {
|
||||||
|
self.raises
|
||||||
|
.push((Range::from_located(stmt), exc.as_deref(), cause.as_deref()));
|
||||||
|
}
|
||||||
|
StmtKind::ClassDef { .. }
|
||||||
|
| StmtKind::FunctionDef { .. }
|
||||||
|
| StmtKind::AsyncFunctionDef { .. }
|
||||||
|
| StmtKind::Try { .. }
|
||||||
|
| StmtKind::TryStar { .. } => {}
|
||||||
|
StmtKind::If { body, orelse, .. } => {
|
||||||
|
visitor::walk_body(self, body);
|
||||||
|
visitor::walk_body(self, orelse);
|
||||||
|
}
|
||||||
|
StmtKind::While { body, .. }
|
||||||
|
| StmtKind::With { body, .. }
|
||||||
|
| StmtKind::AsyncWith { body, .. }
|
||||||
|
| StmtKind::For { body, .. }
|
||||||
|
| StmtKind::AsyncFor { body, .. } => {
|
||||||
|
visitor::walk_body(self, body);
|
||||||
|
}
|
||||||
|
StmtKind::Match { cases, .. } => {
|
||||||
|
for case in cases {
|
||||||
|
visitor::walk_body(self, &case.body);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Convert a location within a file (relative to `base`) to an absolute
|
/// Convert a location within a file (relative to `base`) to an absolute
|
||||||
/// position.
|
/// position.
|
||||||
pub fn to_absolute(relative: Location, base: Location) -> Location {
|
pub fn to_absolute(relative: Location, base: Location) -> Location {
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
|
use rustpython_parser::ast::{ExprKind, Stmt};
|
||||||
|
|
||||||
use ruff_macros::{define_violation, derive_message_formats};
|
use ruff_macros::{define_violation, derive_message_formats};
|
||||||
use ruff_python::str::is_lower;
|
use ruff_python::str::is_lower;
|
||||||
use rustpython_parser::ast::{ExprKind, Stmt, StmtKind};
|
|
||||||
|
|
||||||
use crate::ast::types::Range;
|
use crate::ast::helpers::RaiseStatementVisitor;
|
||||||
use crate::ast::visitor;
|
use crate::ast::visitor;
|
||||||
use crate::ast::visitor::Visitor;
|
|
||||||
use crate::checkers::ast::Checker;
|
use crate::checkers::ast::Checker;
|
||||||
use crate::registry::Diagnostic;
|
use crate::registry::Diagnostic;
|
||||||
use crate::violation::Violation;
|
use crate::violation::Violation;
|
||||||
|
@ -16,62 +16,32 @@ impl Violation for RaiseWithoutFromInsideExcept {
|
||||||
#[derive_message_formats]
|
#[derive_message_formats]
|
||||||
fn message(&self) -> String {
|
fn message(&self) -> String {
|
||||||
format!(
|
format!(
|
||||||
"Within an except clause, raise exceptions with `raise ... from err` or `raise ... \
|
"Within an `except` clause, raise exceptions with `raise ... from err` or `raise ... \
|
||||||
from None` to distinguish them from errors in exception handling"
|
from None` to distinguish them from errors in exception handling"
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct RaiseVisitor {
|
/// B904
|
||||||
diagnostics: Vec<Diagnostic>,
|
pub fn raise_without_from_inside_except(checker: &mut Checker, body: &[Stmt]) {
|
||||||
}
|
let raises = {
|
||||||
|
let mut visitor = RaiseStatementVisitor::default();
|
||||||
|
visitor::walk_body(&mut visitor, body);
|
||||||
|
visitor.raises
|
||||||
|
};
|
||||||
|
|
||||||
impl<'a> Visitor<'a> for RaiseVisitor {
|
for (range, exc, cause) in raises {
|
||||||
fn visit_stmt(&mut self, stmt: &'a Stmt) {
|
if cause.is_none() {
|
||||||
match &stmt.node {
|
if let Some(exc) = exc {
|
||||||
StmtKind::Raise {
|
match &exc.node {
|
||||||
exc: Some(exc),
|
ExprKind::Name { id, .. } if is_lower(id) => {}
|
||||||
cause: None,
|
_ => {
|
||||||
} => match &exc.node {
|
checker
|
||||||
ExprKind::Name { id, .. } if is_lower(id) => {}
|
.diagnostics
|
||||||
_ => {
|
.push(Diagnostic::new(RaiseWithoutFromInsideExcept, range));
|
||||||
self.diagnostics.push(Diagnostic::new(
|
}
|
||||||
RaiseWithoutFromInsideExcept,
|
|
||||||
Range::from_located(stmt),
|
|
||||||
));
|
|
||||||
}
|
|
||||||
},
|
|
||||||
StmtKind::ClassDef { .. }
|
|
||||||
| StmtKind::FunctionDef { .. }
|
|
||||||
| StmtKind::AsyncFunctionDef { .. }
|
|
||||||
| StmtKind::Try { .. }
|
|
||||||
| StmtKind::TryStar { .. } => {}
|
|
||||||
StmtKind::If { body, orelse, .. } => {
|
|
||||||
visitor::walk_body(self, body);
|
|
||||||
visitor::walk_body(self, orelse);
|
|
||||||
}
|
|
||||||
StmtKind::While { body, .. }
|
|
||||||
| StmtKind::With { body, .. }
|
|
||||||
| StmtKind::AsyncWith { body, .. }
|
|
||||||
| StmtKind::For { body, .. }
|
|
||||||
| StmtKind::AsyncFor { body, .. } => {
|
|
||||||
visitor::walk_body(self, body);
|
|
||||||
}
|
|
||||||
StmtKind::Match { cases, .. } => {
|
|
||||||
for case in cases {
|
|
||||||
visitor::walk_body(self, &case.body);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => {}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// B904
|
|
||||||
pub fn raise_without_from_inside_except(checker: &mut Checker, body: &[Stmt]) {
|
|
||||||
let mut visitor = RaiseVisitor {
|
|
||||||
diagnostics: vec![],
|
|
||||||
};
|
|
||||||
visitor::walk_body(&mut visitor, body);
|
|
||||||
checker.diagnostics.extend(visitor.diagnostics);
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
use ruff_macros::{define_violation, derive_message_formats};
|
use rustpython_parser::ast::{ExprKind, Stmt};
|
||||||
use rustpython_parser::ast::{ExprKind, Stmt, StmtKind};
|
|
||||||
|
|
||||||
use crate::ast::types::Range;
|
use ruff_macros::{define_violation, derive_message_formats};
|
||||||
use crate::ast::visitor::{self, Visitor};
|
|
||||||
|
use crate::ast::helpers::RaiseStatementVisitor;
|
||||||
|
use crate::ast::visitor::Visitor;
|
||||||
use crate::checkers::ast::Checker;
|
use crate::checkers::ast::Checker;
|
||||||
use crate::registry::Diagnostic;
|
use crate::registry::Diagnostic;
|
||||||
use crate::violation::Violation;
|
use crate::violation::Violation;
|
||||||
|
@ -17,23 +18,6 @@ impl Violation for ReraiseNoCause {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default)]
|
|
||||||
struct RaiseStatementVisitor<'a> {
|
|
||||||
raises: Vec<&'a Stmt>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a, 'b> Visitor<'b> for RaiseStatementVisitor<'a>
|
|
||||||
where
|
|
||||||
'b: 'a,
|
|
||||||
{
|
|
||||||
fn visit_stmt(&mut self, stmt: &'b Stmt) {
|
|
||||||
match stmt.node {
|
|
||||||
StmtKind::Raise { .. } => self.raises.push(stmt),
|
|
||||||
_ => visitor::walk_stmt(self, stmt),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// TRY200
|
/// TRY200
|
||||||
pub fn reraise_no_cause(checker: &mut Checker, body: &[Stmt]) {
|
pub fn reraise_no_cause(checker: &mut Checker, body: &[Stmt]) {
|
||||||
let raises = {
|
let raises = {
|
||||||
|
@ -44,17 +28,11 @@ pub fn reraise_no_cause(checker: &mut Checker, body: &[Stmt]) {
|
||||||
visitor.raises
|
visitor.raises
|
||||||
};
|
};
|
||||||
|
|
||||||
for stmt in raises {
|
for (range, exc, cause) in raises {
|
||||||
if let StmtKind::Raise { exc, cause, .. } = &stmt.node {
|
if exc.map_or(false, |expr| matches!(expr.node, ExprKind::Call { .. })) && cause.is_none() {
|
||||||
if exc
|
checker
|
||||||
.as_ref()
|
.diagnostics
|
||||||
.map_or(false, |expr| matches!(expr.node, ExprKind::Call { .. }))
|
.push(Diagnostic::new(ReraiseNoCause, range));
|
||||||
&& cause.is_none()
|
|
||||||
{
|
|
||||||
checker
|
|
||||||
.diagnostics
|
|
||||||
.push(Diagnostic::new(ReraiseNoCause, Range::from_located(stmt)));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue