Always allow explicit multi-line concatenations when implicit are banned (#12532)

## Summary

Closes https://github.com/astral-sh/ruff/issues/11582.
This commit is contained in:
Charlie Marsh 2024-07-26 10:36:35 -04:00 committed by GitHub
parent 1fe4a5faed
commit 49f51583fa
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 27 additions and 62 deletions

View file

@ -1197,9 +1197,11 @@ pub(crate) fn expression(expr: &Expr, checker: &mut Checker) {
op: Operator::Add, .. op: Operator::Add, ..
}) => { }) => {
if checker.enabled(Rule::ExplicitStringConcatenation) { if checker.enabled(Rule::ExplicitStringConcatenation) {
if let Some(diagnostic) = if let Some(diagnostic) = flake8_implicit_str_concat::rules::explicit(
flake8_implicit_str_concat::rules::explicit(expr, checker.locator) expr,
{ checker.locator,
checker.settings,
) {
checker.diagnostics.push(diagnostic); checker.diagnostics.push(diagnostic);
} }
} }

View file

@ -125,9 +125,9 @@ pub(crate) fn check_tokens(
flake8_implicit_str_concat::rules::implicit( flake8_implicit_str_concat::rules::implicit(
&mut diagnostics, &mut diagnostics,
tokens, tokens,
settings,
locator, locator,
indexer, indexer,
settings,
); );
} }

View file

@ -1,5 +1,6 @@
use ruff_python_ast::{self as ast, Expr, Operator}; use ruff_python_ast::{self as ast, Expr, Operator};
use crate::settings::LinterSettings;
use ruff_diagnostics::{Diagnostic, Violation}; use ruff_diagnostics::{Diagnostic, Violation};
use ruff_macros::{derive_message_formats, violation}; use ruff_macros::{derive_message_formats, violation};
use ruff_source_file::Locator; use ruff_source_file::Locator;
@ -40,7 +41,19 @@ impl Violation for ExplicitStringConcatenation {
} }
/// ISC003 /// ISC003
pub(crate) fn explicit(expr: &Expr, locator: &Locator) -> Option<Diagnostic> { pub(crate) fn explicit(
expr: &Expr,
locator: &Locator,
settings: &LinterSettings,
) -> Option<Diagnostic> {
// If the user sets `allow-multiline` to `false`, then we should allow explicitly concatenated
// strings that span multiple lines even if this rule is enabled. Otherwise, there's no way
// for the user to write multiline strings, and that setting is "more explicit" than this rule
// being enabled.
if !settings.flake8_implicit_str_concat.allow_multiline {
return None;
}
if let Expr::BinOp(ast::ExprBinOp { if let Expr::BinOp(ast::ExprBinOp {
left, left,
op, op,

View file

@ -93,9 +93,9 @@ impl Violation for MultiLineImplicitStringConcatenation {
pub(crate) fn implicit( pub(crate) fn implicit(
diagnostics: &mut Vec<Diagnostic>, diagnostics: &mut Vec<Diagnostic>,
tokens: &Tokens, tokens: &Tokens,
settings: &LinterSettings,
locator: &Locator, locator: &Locator,
indexer: &Indexer, indexer: &Indexer,
settings: &LinterSettings,
) { ) {
for (a_token, b_token) in tokens for (a_token, b_token) in tokens
.iter() .iter()

View file

@ -1,55 +1,4 @@
--- ---
source: crates/ruff_linter/src/rules/flake8_implicit_str_concat/mod.rs source: crates/ruff_linter/src/rules/flake8_implicit_str_concat/mod.rs
--- ---
ISC.py:9:3: ISC003 Explicitly concatenated string should be implicitly concatenated
|
8 | _ = (
9 | "abc" +
| ___^
10 | | "def"
| |_______^ ISC003
11 | )
|
ISC.py:14:3: ISC003 Explicitly concatenated string should be implicitly concatenated
|
13 | _ = (
14 | f"abc" +
| ___^
15 | | "def"
| |_______^ ISC003
16 | )
|
ISC.py:19:3: ISC003 Explicitly concatenated string should be implicitly concatenated
|
18 | _ = (
19 | b"abc" +
| ___^
20 | | b"def"
| |________^ ISC003
21 | )
|
ISC.py:78:10: ISC003 Explicitly concatenated string should be implicitly concatenated
|
77 | # Explicitly concatenated nested f-strings
78 | _ = f"a {f"first"
| __________^
79 | | + f"second"} d"
| |_______________^ ISC003
80 | _ = f"a {f"first {f"middle"}"
81 | + f"second"} d"
|
ISC.py:80:10: ISC003 Explicitly concatenated string should be implicitly concatenated
|
78 | _ = f"a {f"first"
79 | + f"second"} d"
80 | _ = f"a {f"first {f"middle"}"
| __________^
81 | | + f"second"} d"
| |_______________^ ISC003
|

View file

@ -1260,10 +1260,11 @@ pub struct Flake8ImplicitStrConcatOptions {
/// allowed (but continuation lines, delimited with a backslash, are /// allowed (but continuation lines, delimited with a backslash, are
/// prohibited). /// prohibited).
/// ///
/// Note that setting `allow-multiline = false` should typically be coupled /// Setting `allow-multiline = false` will automatically disable the
/// with disabling `explicit-string-concatenation` (`ISC003`). Otherwise, /// `explicit-string-concatenation` (`ISC003`) rule. Otherwise, both
/// both explicit and implicit multiline string concatenations will be seen /// implicit and explicit multiline string concatenations would be seen
/// as violations. /// as violations, making it impossible to write a linter-compliant multiline
/// string.
#[option( #[option(
default = r#"true"#, default = r#"true"#,
value_type = "bool", value_type = "bool",

2
ruff.schema.json generated
View file

@ -1033,7 +1033,7 @@
"type": "object", "type": "object",
"properties": { "properties": {
"allow-multiline": { "allow-multiline": {
"description": "Whether to allow implicit string concatenations for multiline strings. By default, implicit concatenations of multiline strings are allowed (but continuation lines, delimited with a backslash, are prohibited).\n\nNote that setting `allow-multiline = false` should typically be coupled with disabling `explicit-string-concatenation` (`ISC003`). Otherwise, both explicit and implicit multiline string concatenations will be seen as violations.", "description": "Whether to allow implicit string concatenations for multiline strings. By default, implicit concatenations of multiline strings are allowed (but continuation lines, delimited with a backslash, are prohibited).\n\nSetting `allow-multiline = false` will automatically disable the `explicit-string-concatenation` (`ISC003`) rule. Otherwise, both implicit and explicit multiline string concatenations would be seen as violations, making it impossible to write a linter-compliant multiline string.",
"type": [ "type": [
"boolean", "boolean",
"null" "null"