From ec6054edce0801fa704b5526d8e1180887965250 Mon Sep 17 00:00:00 2001 From: Charlie Marsh Date: Thu, 2 Feb 2023 12:35:59 -0500 Subject: [PATCH] Treat `if 0:` and `if False:` as type-checking blocks (#2485) --- .../fixtures/flake8_type_checking/TCH005.py | 18 ++++++++-- src/checkers/ast.rs | 2 +- src/rules/flake8_type_checking/helpers.rs | 35 +++++++++++++++++-- .../rules/empty_type_checking_block.rs | 19 +++++----- ...__empty-type-checking-block_TCH005.py.snap | 28 ++++++++++++--- 5 files changed, 81 insertions(+), 21 deletions(-) diff --git a/resources/test/fixtures/flake8_type_checking/TCH005.py b/resources/test/fixtures/flake8_type_checking/TCH005.py index 46ca5e4691..2036166c7e 100644 --- a/resources/test/fixtures/flake8_type_checking/TCH005.py +++ b/resources/test/fixtures/flake8_type_checking/TCH005.py @@ -4,15 +4,22 @@ if TYPE_CHECKING: pass # TCH005 +if False: + pass # TCH005 + +if 0: + pass # TCH005 + + def example(): if TYPE_CHECKING: - pass # TYP005 + pass # TCH005 return class Test: if TYPE_CHECKING: - pass # TYP005 + pass # TCH005 x = 2 @@ -23,3 +30,10 @@ if TYPE_CHECKING: if TYPE_CHECKING: x: List + + +if False: + x: List + +if 0: + x: List diff --git a/src/checkers/ast.rs b/src/checkers/ast.rs index 1dee3d3d56..801e6c6f8c 100644 --- a/src/checkers/ast.rs +++ b/src/checkers/ast.rs @@ -1944,7 +1944,7 @@ where if flake8_type_checking::helpers::is_type_checking_block(self, test) { if self.settings.rules.enabled(&Rule::EmptyTypeCheckingBlock) { - flake8_type_checking::rules::empty_type_checking_block(self, test, body); + flake8_type_checking::rules::empty_type_checking_block(self, body); } let prev_in_type_checking_block = self.in_type_checking_block; diff --git a/src/rules/flake8_type_checking/helpers.rs b/src/rules/flake8_type_checking/helpers.rs index bd112cbef6..9b5041d252 100644 --- a/src/rules/flake8_type_checking/helpers.rs +++ b/src/rules/flake8_type_checking/helpers.rs @@ -1,12 +1,41 @@ -use rustpython_ast::Expr; +use num_traits::Zero; +use rustpython_ast::{Constant, Expr, ExprKind}; use crate::ast::types::{Binding, BindingKind, ExecutionContext}; use crate::checkers::ast::Checker; +/// Return `true` if [`Expr`] is a guard for a type-checking block. pub fn is_type_checking_block(checker: &Checker, test: &Expr) -> bool { - checker.resolve_call_path(test).map_or(false, |call_path| { + // Ex) `if False:` + if matches!( + test.node, + ExprKind::Constant { + value: Constant::Bool(false), + .. + } + ) { + return true; + } + + // Ex) `if 0:` + if let ExprKind::Constant { + value: Constant::Int(value), + .. + } = &test.node + { + if value.is_zero() { + return true; + } + } + + // Ex) `if typing.TYPE_CHECKING:` + if checker.resolve_call_path(test).map_or(false, |call_path| { call_path.as_slice() == ["typing", "TYPE_CHECKING"] - }) + }) { + return true; + } + + false } pub fn is_valid_runtime_import(binding: &Binding) -> bool { diff --git a/src/rules/flake8_type_checking/rules/empty_type_checking_block.rs b/src/rules/flake8_type_checking/rules/empty_type_checking_block.rs index ad29fb4340..8e05b4bca5 100644 --- a/src/rules/flake8_type_checking/rules/empty_type_checking_block.rs +++ b/src/rules/flake8_type_checking/rules/empty_type_checking_block.rs @@ -1,5 +1,6 @@ +use rustpython_ast::{Stmt, StmtKind}; + use ruff_macros::derive_message_formats; -use rustpython_ast::{Expr, Stmt, StmtKind}; use crate::ast::types::Range; use crate::checkers::ast::Checker; @@ -18,15 +19,11 @@ impl Violation for EmptyTypeCheckingBlock { } /// TCH005 -pub fn empty_type_checking_block(checker: &mut Checker, test: &Expr, body: &[Stmt]) { - if checker.resolve_call_path(test).map_or(false, |call_path| { - call_path.as_slice() == ["typing", "TYPE_CHECKING"] - }) { - if body.len() == 1 && matches!(body[0].node, StmtKind::Pass) { - checker.diagnostics.push(Diagnostic::new( - EmptyTypeCheckingBlock, - Range::from_located(&body[0]), - )); - } +pub fn empty_type_checking_block(checker: &mut Checker, body: &[Stmt]) { + if body.len() == 1 && matches!(body[0].node, StmtKind::Pass) { + checker.diagnostics.push(Diagnostic::new( + EmptyTypeCheckingBlock, + Range::from_located(&body[0]), + )); } } diff --git a/src/rules/flake8_type_checking/snapshots/ruff__rules__flake8_type_checking__tests__empty-type-checking-block_TCH005.py.snap b/src/rules/flake8_type_checking/snapshots/ruff__rules__flake8_type_checking__tests__empty-type-checking-block_TCH005.py.snap index 99ef601de6..040de65b75 100644 --- a/src/rules/flake8_type_checking/snapshots/ruff__rules__flake8_type_checking__tests__empty-type-checking-block_TCH005.py.snap +++ b/src/rules/flake8_type_checking/snapshots/ruff__rules__flake8_type_checking__tests__empty-type-checking-block_TCH005.py.snap @@ -15,20 +15,40 @@ expression: diagnostics - kind: EmptyTypeCheckingBlock: ~ location: - row: 9 + row: 8 + column: 4 + end_location: + row: 8 + column: 8 + fix: ~ + parent: ~ +- kind: + EmptyTypeCheckingBlock: ~ + location: + row: 11 + column: 4 + end_location: + row: 11 + column: 8 + fix: ~ + parent: ~ +- kind: + EmptyTypeCheckingBlock: ~ + location: + row: 16 column: 8 end_location: - row: 9 + row: 16 column: 12 fix: ~ parent: ~ - kind: EmptyTypeCheckingBlock: ~ location: - row: 15 + row: 22 column: 8 end_location: - row: 15 + row: 22 column: 12 fix: ~ parent: ~