diff --git a/crates/ruff_linter/resources/test/fixtures/flake8_errmsg/EM.py b/crates/ruff_linter/resources/test/fixtures/flake8_errmsg/EM.py index fbf6eb464a..432005bc44 100644 --- a/crates/ruff_linter/resources/test/fixtures/flake8_errmsg/EM.py +++ b/crates/ruff_linter/resources/test/fixtures/flake8_errmsg/EM.py @@ -88,3 +88,25 @@ def f_multi_line_string2(): example="example" ) ) + + +def raise_typing_cast_exception(): + import typing + raise typing.cast("Exception", None) + + +def f_typing_cast_excluded(): + from typing import cast + raise cast(RuntimeError, "This should not trigger EM101") + + +def f_typing_cast_excluded_import(): + import typing + raise typing.cast(RuntimeError, "This should not trigger EM101") + + +def f_typing_cast_excluded_aliased(): + from typing import cast as my_cast + raise my_cast(RuntimeError, "This should not trigger EM101") + + diff --git a/crates/ruff_linter/src/rules/flake8_errmsg/rules/string_in_exception.rs b/crates/ruff_linter/src/rules/flake8_errmsg/rules/string_in_exception.rs index 9f1a2fae36..62b981b5b8 100644 --- a/crates/ruff_linter/src/rules/flake8_errmsg/rules/string_in_exception.rs +++ b/crates/ruff_linter/src/rules/flake8_errmsg/rules/string_in_exception.rs @@ -182,60 +182,27 @@ impl Violation for DotFormatInException { /// EM101, EM102, EM103 pub(crate) fn string_in_exception(checker: &Checker, stmt: &Stmt, exc: &Expr) { - if let Expr::Call(ast::ExprCall { + let Expr::Call(ast::ExprCall { + func, arguments: Arguments { args, .. }, .. }) = exc - { - if let Some(first) = args.first() { - match first { - // Check for string literals. - Expr::StringLiteral(ast::ExprStringLiteral { value: string, .. }) => { - if checker.is_rule_enabled(Rule::RawStringInException) { - if string.len() >= checker.settings().flake8_errmsg.max_string_length { - let mut diagnostic = - checker.report_diagnostic(RawStringInException, first.range()); - if let Some(indentation) = - whitespace::indentation(checker.source(), stmt) - { - diagnostic.set_fix(generate_fix( - stmt, - first, - indentation, - checker.stylist(), - checker.locator(), - )); - } - } - } - } - // Check for byte string literals. - Expr::BytesLiteral(ast::ExprBytesLiteral { value: bytes, .. }) => { - if checker.settings().rules.enabled(Rule::RawStringInException) { - if bytes.len() >= checker.settings().flake8_errmsg.max_string_length - && is_raise_exception_byte_string_enabled(checker.settings()) - { - let mut diagnostic = - checker.report_diagnostic(RawStringInException, first.range()); - if let Some(indentation) = - whitespace::indentation(checker.source(), stmt) - { - diagnostic.set_fix(generate_fix( - stmt, - first, - indentation, - checker.stylist(), - checker.locator(), - )); - } - } - } - } - // Check for f-strings. - Expr::FString(_) => { - if checker.is_rule_enabled(Rule::FStringInException) { + else { + return; + }; + + if checker.semantic().match_typing_expr(func, "cast") { + return; + } + + if let Some(first) = args.first() { + match first { + // Check for string literals. + Expr::StringLiteral(ast::ExprStringLiteral { value: string, .. }) => { + if checker.is_rule_enabled(Rule::RawStringInException) { + if string.len() >= checker.settings().flake8_errmsg.max_string_length { let mut diagnostic = - checker.report_diagnostic(FStringInException, first.range()); + checker.report_diagnostic(RawStringInException, first.range()); if let Some(indentation) = whitespace::indentation(checker.source(), stmt) { diagnostic.set_fix(generate_fix( stmt, @@ -247,32 +214,66 @@ pub(crate) fn string_in_exception(checker: &Checker, stmt: &Stmt, exc: &Expr) { } } } - // Check for .format() calls. - Expr::Call(ast::ExprCall { func, .. }) => { - if checker.is_rule_enabled(Rule::DotFormatInException) { - if let Expr::Attribute(ast::ExprAttribute { value, attr, .. }) = - func.as_ref() - { - if attr == "format" && value.is_literal_expr() { - let mut diagnostic = - checker.report_diagnostic(DotFormatInException, first.range()); - if let Some(indentation) = - whitespace::indentation(checker.source(), stmt) - { - diagnostic.set_fix(generate_fix( - stmt, - first, - indentation, - checker.stylist(), - checker.locator(), - )); - } + } + // Check for byte string literals. + Expr::BytesLiteral(ast::ExprBytesLiteral { value: bytes, .. }) => { + if checker.settings().rules.enabled(Rule::RawStringInException) { + if bytes.len() >= checker.settings().flake8_errmsg.max_string_length + && is_raise_exception_byte_string_enabled(checker.settings()) + { + let mut diagnostic = + checker.report_diagnostic(RawStringInException, first.range()); + if let Some(indentation) = whitespace::indentation(checker.source(), stmt) { + diagnostic.set_fix(generate_fix( + stmt, + first, + indentation, + checker.stylist(), + checker.locator(), + )); + } + } + } + } + // Check for f-strings. + Expr::FString(_) => { + if checker.is_rule_enabled(Rule::FStringInException) { + let mut diagnostic = + checker.report_diagnostic(FStringInException, first.range()); + if let Some(indentation) = whitespace::indentation(checker.source(), stmt) { + diagnostic.set_fix(generate_fix( + stmt, + first, + indentation, + checker.stylist(), + checker.locator(), + )); + } + } + } + // Check for .format() calls. + Expr::Call(ast::ExprCall { func, .. }) => { + if checker.is_rule_enabled(Rule::DotFormatInException) { + if let Expr::Attribute(ast::ExprAttribute { value, attr, .. }) = func.as_ref() { + if attr == "format" && value.is_literal_expr() { + let mut diagnostic = + checker.report_diagnostic(DotFormatInException, first.range()); + if let Some(indentation) = + whitespace::indentation(checker.source(), stmt) + { + diagnostic.set_fix(generate_fix( + stmt, + first, + indentation, + checker.stylist(), + checker.locator(), + )); } } } } - _ => {} } + _ => {} } } } diff --git a/crates/ruff_linter/src/rules/flake8_errmsg/snapshots/ruff_linter__rules__flake8_errmsg__tests__custom.snap b/crates/ruff_linter/src/rules/flake8_errmsg/snapshots/ruff_linter__rules__flake8_errmsg__tests__custom.snap index bb2dfde20b..ca47a2e7f7 100644 --- a/crates/ruff_linter/src/rules/flake8_errmsg/snapshots/ruff_linter__rules__flake8_errmsg__tests__custom.snap +++ b/crates/ruff_linter/src/rules/flake8_errmsg/snapshots/ruff_linter__rules__flake8_errmsg__tests__custom.snap @@ -278,3 +278,6 @@ EM.py:84:9: EM103 [*] Exception must not use a `.format()` string directly, assi 91 |+ raise RuntimeError( 92 |+ msg 93 |+ ) +91 94 | +92 95 | +93 96 | def raise_typing_cast_exception(): diff --git a/crates/ruff_linter/src/rules/flake8_errmsg/snapshots/ruff_linter__rules__flake8_errmsg__tests__defaults.snap b/crates/ruff_linter/src/rules/flake8_errmsg/snapshots/ruff_linter__rules__flake8_errmsg__tests__defaults.snap index 42e9f41250..07fece4a7f 100644 --- a/crates/ruff_linter/src/rules/flake8_errmsg/snapshots/ruff_linter__rules__flake8_errmsg__tests__defaults.snap +++ b/crates/ruff_linter/src/rules/flake8_errmsg/snapshots/ruff_linter__rules__flake8_errmsg__tests__defaults.snap @@ -343,3 +343,6 @@ EM.py:84:9: EM103 [*] Exception must not use a `.format()` string directly, assi 91 |+ raise RuntimeError( 92 |+ msg 93 |+ ) +91 94 | +92 95 | +93 96 | def raise_typing_cast_exception():