From f73dfbbfd3624e68f3ad666a944fd1dd012f5257 Mon Sep 17 00:00:00 2001 From: Harutaka Kawamura Date: Sat, 31 Dec 2022 21:58:46 +0900 Subject: [PATCH] Fix E722 and F707 ranges (#1508) --- src/ast/helpers.rs | 36 +++++++++++++++++-- src/checkers/ast.rs | 7 ++-- src/pycodestyle/checks.rs | 11 ++++-- ...uff__pycodestyle__tests__E722_E722.py.snap | 12 +++---- src/pyflakes/checks.rs | 9 +++-- .../ruff__pyflakes__tests__F707_F707.py.snap | 12 +++---- 6 files changed, 66 insertions(+), 21 deletions(-) diff --git a/src/ast/helpers.rs b/src/ast/helpers.rs index 901ba0235e..275c889e84 100644 --- a/src/ast/helpers.rs +++ b/src/ast/helpers.rs @@ -426,6 +426,31 @@ pub fn excepthandler_name_range( } } +/// Return the `Range` of `except` in `Excepthandler`. +pub fn except_range(handler: &Excepthandler, locator: &SourceCodeLocator) -> Range { + let ExcepthandlerKind::ExceptHandler { body, type_, .. } = &handler.node; + let end = if let Some(type_) = type_ { + type_.location + } else { + body.first() + .expect("Expected body to be non-empty") + .location + }; + let contents = locator.slice_source_code_range(&Range { + location: handler.location, + end_location: end, + }); + let range = lexer::make_tokenizer_located(&contents, handler.location) + .flatten() + .find(|(_, kind, _)| matches!(kind, Tok::Except { .. })) + .map(|(location, _, end_location)| Range { + location, + end_location, + }) + .expect("Failed to find `except` range"); + range +} + /// Return the `Range` of `else` in `For`, `AsyncFor`, and `While` statements. pub fn else_range(stmt: &Stmt, locator: &SourceCodeLocator) -> Option { match &stmt.node { @@ -434,10 +459,17 @@ pub fn else_range(stmt: &Stmt, locator: &SourceCodeLocator) -> Option { | StmtKind::While { body, orelse, .. } if !orelse.is_empty() => { - let body_end = body.last().unwrap().end_location.unwrap(); + let body_end = body + .last() + .expect("Expected body to be non-empty") + .end_location + .unwrap(); let contents = locator.slice_source_code_range(&Range { location: body_end, - end_location: orelse[0].location, + end_location: orelse + .first() + .expect("Expected orelse to be non-empty") + .location, }); let range = lexer::make_tokenizer_located(&contents, body_end) .flatten() diff --git a/src/checkers/ast.rs b/src/checkers/ast.rs index 8797dfee1f..8629bae850 100644 --- a/src/checkers/ast.rs +++ b/src/checkers/ast.rs @@ -1171,7 +1171,9 @@ where } StmtKind::Try { handlers, .. } => { if self.settings.enabled.contains(&CheckCode::F707) { - if let Some(check) = pyflakes::checks::default_except_not_last(handlers) { + if let Some(check) = + pyflakes::checks::default_except_not_last(handlers, self.locator) + { self.add_check(check); } } @@ -2682,7 +2684,8 @@ where if let Some(check) = pycodestyle::checks::do_not_use_bare_except( type_.as_deref(), body, - Range::from_located(excepthandler), + excepthandler, + self.locator, ) { self.add_check(check); } diff --git a/src/pycodestyle/checks.rs b/src/pycodestyle/checks.rs index 1b996a4130..a3b70c6ed7 100644 --- a/src/pycodestyle/checks.rs +++ b/src/pycodestyle/checks.rs @@ -1,9 +1,10 @@ use itertools::izip; use once_cell::sync::Lazy; use regex::Regex; -use rustpython_ast::{Constant, Located, Location, Stmt, StmtKind}; +use rustpython_ast::{Constant, Excepthandler, Located, Location, Stmt, StmtKind}; use rustpython_parser::ast::{Cmpop, Expr, ExprKind}; +use crate::ast::helpers::except_range; use crate::ast::types::Range; use crate::autofix::Fix; use crate::checks::{Check, CheckKind}; @@ -88,14 +89,18 @@ pub fn type_comparison(ops: &[Cmpop], comparators: &[Expr], location: Range) -> pub fn do_not_use_bare_except( type_: Option<&Expr>, body: &[Stmt], - location: Range, + handler: &Excepthandler, + locator: &SourceCodeLocator, ) -> Option { if type_.is_none() && !body .iter() .any(|stmt| matches!(stmt.node, StmtKind::Raise { exc: None, .. })) { - Some(Check::new(CheckKind::DoNotUseBareExcept, location)) + Some(Check::new( + CheckKind::DoNotUseBareExcept, + except_range(handler, locator), + )) } else { None } diff --git a/src/pycodestyle/snapshots/ruff__pycodestyle__tests__E722_E722.py.snap b/src/pycodestyle/snapshots/ruff__pycodestyle__tests__E722_E722.py.snap index e6dd3d3f69..ba398c6f6a 100644 --- a/src/pycodestyle/snapshots/ruff__pycodestyle__tests__E722_E722.py.snap +++ b/src/pycodestyle/snapshots/ruff__pycodestyle__tests__E722_E722.py.snap @@ -7,8 +7,8 @@ expression: checks row: 4 column: 0 end_location: - row: 5 - column: 8 + row: 4 + column: 6 fix: ~ parent: ~ - kind: DoNotUseBareExcept @@ -16,8 +16,8 @@ expression: checks row: 11 column: 0 end_location: - row: 12 - column: 8 + row: 11 + column: 6 fix: ~ parent: ~ - kind: DoNotUseBareExcept @@ -25,8 +25,8 @@ expression: checks row: 16 column: 0 end_location: - row: 17 - column: 8 + row: 16 + column: 6 fix: ~ parent: ~ diff --git a/src/pyflakes/checks.rs b/src/pyflakes/checks.rs index c0f5b9481c..f0dc5baf5a 100644 --- a/src/pyflakes/checks.rs +++ b/src/pyflakes/checks.rs @@ -5,8 +5,10 @@ use rustpython_parser::ast::{ Constant, Excepthandler, ExcepthandlerKind, Expr, ExprKind, Stmt, StmtKind, }; +use crate::ast::helpers::except_range; use crate::ast::types::{Binding, BindingKind, Range, Scope, ScopeKind}; use crate::checks::{Check, CheckKind}; +use crate::source_code_locator::SourceCodeLocator; /// F631 pub fn assert_tuple(test: &Expr, location: Range) -> Option { @@ -110,13 +112,16 @@ pub fn unused_annotation( } /// F707 -pub fn default_except_not_last(handlers: &[Excepthandler]) -> Option { +pub fn default_except_not_last( + handlers: &[Excepthandler], + locator: &SourceCodeLocator, +) -> Option { for (idx, handler) in handlers.iter().enumerate() { let ExcepthandlerKind::ExceptHandler { type_, .. } = &handler.node; if type_.is_none() && idx < handlers.len() - 1 { return Some(Check::new( CheckKind::DefaultExceptNotLast, - Range::from_located(handler), + except_range(handler, locator), )); } } diff --git a/src/pyflakes/snapshots/ruff__pyflakes__tests__F707_F707.py.snap b/src/pyflakes/snapshots/ruff__pyflakes__tests__F707_F707.py.snap index 3ce5368b50..d7cc7ae330 100644 --- a/src/pyflakes/snapshots/ruff__pyflakes__tests__F707_F707.py.snap +++ b/src/pyflakes/snapshots/ruff__pyflakes__tests__F707_F707.py.snap @@ -7,8 +7,8 @@ expression: checks row: 3 column: 0 end_location: - row: 4 - column: 8 + row: 3 + column: 6 fix: ~ parent: ~ - kind: DefaultExceptNotLast @@ -16,8 +16,8 @@ expression: checks row: 10 column: 0 end_location: - row: 11 - column: 8 + row: 10 + column: 6 fix: ~ parent: ~ - kind: DefaultExceptNotLast @@ -25,8 +25,8 @@ expression: checks row: 19 column: 0 end_location: - row: 20 - column: 8 + row: 19 + column: 6 fix: ~ parent: ~