ruff/crates
GiGaGon 47f88b3008
[flake8-type-checking] Fix syntax error introduced by fix (TC008) (#19150)
<!--
Thank you for contributing to Ruff/ty! To help us out with reviewing,
please consider the following:

- Does this pull request include a summary of the change? (See below.)
- Does this pull request include a descriptive title? (Please prefix
with `[ty]` for ty pull
  requests.)
- Does this pull request include references to any relevant issues?
-->

## Summary

<!-- What's the purpose of the change? What does it do, and why? -->

I noticed this while working on #18972. If the string targeted by
[quoted-type-alias
(TC008)](https://docs.astral.sh/ruff/rules/quoted-type-alias/#quoted-type-alias-tc008)
is a multiline string, the fix would introduce a syntax error. This PR
fixes that by adding parenthesis around the resulting replacement if the
string contained any newline characters (`\n`, `\r`) if it doesn't
already have parenthesis outside `("""...""")` or inside `"""(...)"""`
the annotation.

Failing examples:
https://play.ruff.rs/8793eb95-860a-4bb3-9cbc-6a042fee2946
```
PS D:\rust_projects\ruff> Get-Content issue.py
```
```py
from typing import TypeAlias

OptInt: TypeAlias = """int
| None"""

type OptInt = """int
| None"""
```
```
PS D:\rust_projects\ruff> uvx ruff check issue.py --isolated --select TC008 --fix --diff --preview
```
```

error: Fix introduced a syntax error. Reverting all changes.

This indicates a bug in Ruff. If you could open an issue at:

    https://github.com/astral-sh/ruff/issues/new?title=%5BFix%20error%5D

...quoting the contents of `issue.py`, the rule codes TC008, along with the `pyproject.toml` settings and executed command, we'd be very appreciative!
```

This PR also makes the example error out-of-the-box for #18972

Old example: https://play.ruff.rs/f6cd5adb-7f9b-444d-bb3e-8c045241d93e
```py
OptInt: TypeAlias = "int | None"
```

New example: https://play.ruff.rs/906c1056-72c0-4777-b70b-2114eb9e6eaf
```py
from typing import TypeAlias

OptInt: TypeAlias = "int | None"
```

The import was also added to the "Use instead" section.

## Test Plan

<!-- How was it tested? -->

Added multiple test cases
2025-07-07 15:34:14 -05:00
..
ruff Combine OldDiagnostic and Diagnostic (#19053) 2025-07-03 13:01:09 -04:00
ruff_annotate_snippets Update Rust toolchain to 1.88 and MSRV to 1.86 (#19011) 2025-06-28 20:24:00 +02:00
ruff_benchmark [ty] Re-enable multithreaded pydantic benchmark (#19176) 2025-07-07 14:28:15 +02:00
ruff_cache
ruff_db Combine OldDiagnostic and Diagnostic (#19053) 2025-07-03 13:01:09 -04:00
ruff_dev Avoid reformatting comments in rules reference documentation (#19093) 2025-07-02 17:16:44 +02:00
ruff_diagnostics Combine OldDiagnostic and Diagnostic (#19053) 2025-07-03 13:01:09 -04:00
ruff_formatter
ruff_graph Update Rust toolchain to 1.88 and MSRV to 1.86 (#19011) 2025-06-28 20:24:00 +02:00
ruff_index Update Rust toolchain to 1.88 and MSRV to 1.86 (#19011) 2025-06-28 20:24:00 +02:00
ruff_linter [flake8-type-checking] Fix syntax error introduced by fix (TC008) (#19150) 2025-07-07 15:34:14 -05:00
ruff_macros Apply fix availability and applicability when adding to DiagnosticGuard and remove NoqaCode::rule (#18834) 2025-06-24 10:08:36 -04:00
ruff_notebook
ruff_options_metadata
ruff_python_ast Make dependency get-size2 truly optional in ruff_python_ast (#19052) 2025-06-30 21:50:59 -05:00
ruff_python_ast_integration_tests [ty] AST garbage collection (#18482) 2025-06-13 08:40:11 -04:00
ruff_python_codegen Fix f-string interpolation escaping (#18882) 2025-06-25 10:04:15 +02:00
ruff_python_formatter Update pre-commit dependencies (#19162) 2025-07-07 04:07:44 +00:00
ruff_python_index
ruff_python_literal
ruff_python_parser Combine OldDiagnostic and Diagnostic (#19053) 2025-07-03 13:01:09 -04:00
ruff_python_semantic [flake8-pyi] Expand Optional[A] to A | None (PYI016) (#18572) 2025-06-27 15:43:11 +00:00
ruff_python_stdlib
ruff_python_trivia Treat ty: comments as pragma comments (#18532) 2025-06-07 16:02:43 +02:00
ruff_python_trivia_integration_tests
ruff_server [ty] Add documentation for server traits (#19137) 2025-07-07 14:26:09 +00:00
ruff_source_file [ty] Add environment variable to dump Salsa memory usage stats (#18928) 2025-06-26 21:27:51 +00:00
ruff_text_size [ty] Add environment variable to dump Salsa memory usage stats (#18928) 2025-06-26 21:27:51 +00:00
ruff_wasm Combine OldDiagnostic and Diagnostic (#19053) 2025-07-03 13:01:09 -04:00
ruff_workspace Fix description of the format.skip-magic-trailing-comma example (#19095) 2025-07-03 10:39:59 -04:00
ty [ty] Add separate CI job for memory usage stats (#19134) 2025-07-07 12:17:02 -04:00
ty_ide [ty] Sync vendored typeshed stubs (#19174) 2025-07-07 12:00:09 +02:00
ty_project [ty] Add separate CI job for memory usage stats (#19134) 2025-07-07 12:17:02 -04:00
ty_python_semantic [ty] Add separate CI job for memory usage stats (#19134) 2025-07-07 12:17:02 -04:00
ty_server [ty] Add documentation for server traits (#19137) 2025-07-07 14:26:09 +00:00
ty_test Combine OldDiagnostic and Diagnostic (#19053) 2025-07-03 13:01:09 -04:00
ty_vendored [ty] Sync vendored typeshed stubs (#19174) 2025-07-07 12:00:09 +02:00
ty_wasm [ty] Support LSP go-to with vendored typeshed stubs (#19057) 2025-07-02 07:58:58 -04:00