diff --git a/crates/ruff/src/commands/format.rs b/crates/ruff/src/commands/format.rs index 2d49f0d5e0539..fa4704eca4f95 100644 --- a/crates/ruff/src/commands/format.rs +++ b/crates/ruff/src/commands/format.rs @@ -233,7 +233,7 @@ pub(crate) fn format( } /// Format the file at the given [`Path`]. -#[tracing::instrument(level="debug", skip_all, fields(path = %path.display()))] +#[tracing::instrument(level = "debug", skip_all, fields(path = %path.display()))] pub(crate) fn format_path( path: &Path, settings: &FormatterSettings, @@ -788,8 +788,6 @@ pub(super) fn warn_incompatible_formatter_settings(resolver: &Resolver) { let mut incompatible_rules = FxHashSet::default(); for setting in resolver.settings() { for rule in [ - // The formatter might collapse implicit string concatenation on a single line. - Rule::SingleLineImplicitStringConcatenation, // Flags missing trailing commas when all arguments are on its own line: // ```python // def args( @@ -829,6 +827,19 @@ pub(super) fn warn_incompatible_formatter_settings(resolver: &Resolver) { warn_user_once!("The `format.indent-style=\"tab\"` option is incompatible with `W191`, which lints against all uses of tabs. We recommend disabling these rules when using the formatter, which enforces a consistent indentation style. Alternatively, set the `format.indent-style` option to `\"space\"`."); } + if !setting + .linter + .rules + .enabled(Rule::SingleLineImplicitStringConcatenation) + && setting + .linter + .rules + .enabled(Rule::MultiLineImplicitStringConcatenation) + && !setting.linter.flake8_implicit_str_concat.allow_multiline + { + warn_user_once!("The `lint.flake8-implicit-str-concat.allow-multiline = false` option is incompatible with the formatter unless `ISC001` is enabled. We recommend enabling `ISC001` or setting `allow-multiline=true`."); + } + // Validate all rules that rely on tab styles. if setting.linter.rules.enabled(Rule::DocstringTabIndentation) && setting.formatter.indent_style.is_tab() diff --git a/crates/ruff/tests/format.rs b/crates/ruff/tests/format.rs index ff0ded80c7371..2e0acc01ec1e8 100644 --- a/crates/ruff/tests/format.rs +++ b/crates/ruff/tests/format.rs @@ -877,7 +877,7 @@ indent-width = 2 [lint] select = ["ALL"] -ignore = ["D203", "D212"] +ignore = ["D203", "D212", "ISC001"] [lint.isort] lines-after-imports = 3 @@ -891,6 +891,9 @@ inline-quotes = "single" docstring-quotes = "single" multiline-quotes = "single" +[lint.flake8-implicit-str-concat] +allow-multiline = false + [format] skip-magic-trailing-comma = true indent-style = "tab" @@ -915,8 +918,9 @@ def say_hy(name: str): 1 file reformatted ----- stderr ----- - warning: The following rules may cause conflicts when used with the formatter: `COM812`, `ISC001`. To avoid unexpected behavior, we recommend disabling these rules, either by removing them from the `select` or `extend-select` configuration, or adding them to the `ignore` configuration. + warning: The following rule may cause conflicts when used with the formatter: `COM812`. To avoid unexpected behavior, we recommend disabling this rule, either by removing it from the `select` or `extend-select` configuration, or adding it to the `ignore` configuration. warning: The `format.indent-style="tab"` option is incompatible with `W191`, which lints against all uses of tabs. We recommend disabling these rules when using the formatter, which enforces a consistent indentation style. Alternatively, set the `format.indent-style` option to `"space"`. + warning: The `lint.flake8-implicit-str-concat.allow-multiline = false` option is incompatible with the formatter unless `ISC001` is enabled. We recommend enabling `ISC001` or setting `allow-multiline=true`. warning: The `format.indent-style="tab"` option is incompatible with `D206`, with requires space-based indentation. We recommend disabling these rules when using the formatter, which enforces a consistent indentation style. Alternatively, set the `format.indent-style` option to `"space"`. warning: The `flake8-quotes.inline-quotes="single"` option is incompatible with the formatter's `format.quote-style="double"`. We recommend disabling `Q000` and `Q003` when using the formatter, which enforces a consistent quote style. Alternatively, set both options to either `"single"` or `"double"`. warning: The `flake8-quotes.multiline-quotes="single"` option is incompatible with the formatter. We recommend disabling `Q001` when using the formatter, which enforces double quotes for multiline strings. Alternatively, set the `flake8-quotes.multiline-quotes` option to `"double"`.` @@ -974,7 +978,7 @@ def say_hy(name: str): print(f"Hy {name}") ----- stderr ----- - warning: The following rules may cause conflicts when used with the formatter: `COM812`, `ISC001`. To avoid unexpected behavior, we recommend disabling these rules, either by removing them from the `select` or `extend-select` configuration, or adding them to the `ignore` configuration. + warning: The following rule may cause conflicts when used with the formatter: `COM812`. To avoid unexpected behavior, we recommend disabling this rule, either by removing it from the `select` or `extend-select` configuration, or adding it to the `ignore` configuration. warning: The `format.indent-style="tab"` option is incompatible with `W191`, which lints against all uses of tabs. We recommend disabling these rules when using the formatter, which enforces a consistent indentation style. Alternatively, set the `format.indent-style` option to `"space"`. warning: The `format.indent-style="tab"` option is incompatible with `D206`, with requires space-based indentation. We recommend disabling these rules when using the formatter, which enforces a consistent indentation style. Alternatively, set the `format.indent-style` option to `"space"`. warning: The `flake8-quotes.inline-quotes="single"` option is incompatible with the formatter's `format.quote-style="double"`. We recommend disabling `Q000` and `Q003` when using the formatter, which enforces a consistent quote style. Alternatively, set both options to either `"single"` or `"double"`. @@ -1114,7 +1118,7 @@ def say_hy(name: str): ----- stderr ----- warning: `incorrect-blank-line-before-class` (D203) and `no-blank-line-before-class` (D211) are incompatible. Ignoring `incorrect-blank-line-before-class`. warning: `multi-line-summary-first-line` (D212) and `multi-line-summary-second-line` (D213) are incompatible. Ignoring `multi-line-summary-second-line`. - warning: The following rules may cause conflicts when used with the formatter: `COM812`, `ISC001`. To avoid unexpected behavior, we recommend disabling these rules, either by removing them from the `select` or `extend-select` configuration, or adding them to the `ignore` configuration. + warning: The following rule may cause conflicts when used with the formatter: `COM812`. To avoid unexpected behavior, we recommend disabling this rule, either by removing it from the `select` or `extend-select` configuration, or adding it to the `ignore` configuration. "); Ok(()) } diff --git a/crates/ruff_linter/src/rules/flake8_implicit_str_concat/rules/implicit.rs b/crates/ruff_linter/src/rules/flake8_implicit_str_concat/rules/implicit.rs index 86c90bbd7c883..8cbbcc18bf180 100644 --- a/crates/ruff_linter/src/rules/flake8_implicit_str_concat/rules/implicit.rs +++ b/crates/ruff_linter/src/rules/flake8_implicit_str_concat/rules/implicit.rs @@ -34,21 +34,6 @@ use crate::Locator; /// ```python /// z = "The quick brown fox." /// ``` -/// -/// # Formatter compatibility -/// Use of this rule alongside the [formatter] must be handled with care. -/// Currently, the [formatter] can introduce new single-line implicitly -/// concatenated strings, therefore we suggest rerunning the linter and -/// [formatter] in the following order: -/// 1. Run the linter with this rule (`ISC001`) disabled -/// 2. Run the [formatter] -/// 3. Rerun the linter with this rule (`ISC001`) enabled -/// -/// This is one of very few cases where the [formatter] can produce code that -/// contains lint violations. It is a known issue that should be resolved by the -/// new 2025 style guide. -/// -/// [formatter]:https://docs.astral.sh/ruff/formatter/ #[derive(ViolationMetadata)] pub(crate) struct SingleLineImplicitStringConcatenation; @@ -96,19 +81,13 @@ impl Violation for SingleLineImplicitStringConcatenation { /// ## Options /// - `lint.flake8-implicit-str-concat.allow-multiline` /// -/// # Formatter compatibility -/// Use of this rule alongside the [formatter] must be handled with care. -/// Currently, the [formatter] can introduce new multi-line implicitly -/// concatenated strings, therefore we suggest rerunning the linter and -/// [formatter] in the following order: -/// -/// 1. Run the linter with this rule (`ISC002`) disabled -/// 2. Run the [formatter] -/// 3. Rerun the linter with this rule (`ISC002`) enabled +/// ## Formatter compatibility +/// Using this rule with `allow-multiline = false` can be incompatible with the +/// formatter because the [formatter] can introduce new multi-line implicitly +/// concatenated strings. We recommend to either: /// -/// This is one of very few cases where the [formatter] can produce code that -/// contains lint violations. It is a known issue that should be resolved by the -/// new 2025 style guide. +/// * Enable `ISC001` to disallow all implicit concatenated strings +/// * Setting `allow-multiline = true` /// /// [PEP 8]: https://peps.python.org/pep-0008/#maximum-line-length /// [formatter]:https://docs.astral.sh/ruff/formatter/ diff --git a/docs/formatter.md b/docs/formatter.md index 6dcc976706300..c35d437866278 100644 --- a/docs/formatter.md +++ b/docs/formatter.md @@ -330,8 +330,7 @@ When using Ruff as a formatter, we recommend avoiding the following lint rules: - [`avoidable-escaped-quote`](rules/avoidable-escaped-quote.md) (`Q003`) - [`missing-trailing-comma`](rules/missing-trailing-comma.md) (`COM812`) - [`prohibited-trailing-comma`](rules/prohibited-trailing-comma.md) (`COM819`) -- [`single-line-implicit-string-concatenation`](rules/single-line-implicit-string-concatenation.md) (`ISC001`) -- [`multi-line-implicit-string-concatenation`](rules/multi-line-implicit-string-concatenation.md) (`ISC002`) +- [`multi-line-implicit-string-concatenation`](rules/multi-line-implicit-string-concatenation.md) (`ISC002`) if used without `ISC001` and `flake8-implicit-str-concat.allow-multiline = false` While the [`line-too-long`](rules/line-too-long.md) (`E501`) rule _can_ be used alongside the formatter, the formatter only makes a best-effort attempt to wrap lines at the configured