[flake8-type-checking] Fix some safe fixes being labeled unsafe (#15638)

## Summary

We were mistakenly using `CommentRanges::has_comments` to determine
whether our edits
were safe, which sometimes expands the checked range to the end of a
line. But in order to
determine safety we need to check exactly the range we're replacing.

This bug affected the rules `runtime-cast-value` (`TC006`) and
`quoted-type-alias` (`TC008`)
although it was very unlikely to be hit for `TC006` and for `TC008` we
never hit it because we
were checking the wrong expression.

## Test Plan

`cargo nextest run`
This commit is contained in:
David Salvisberg 2025-01-21 15:08:46 +01:00 committed by GitHub
parent cff9c13c42
commit 4366473d9b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 33 additions and 8 deletions

View file

@ -80,3 +80,12 @@ def f():
from typing import cast, Annotated, Literal
cast(list[Annotated["list['Literal[\"A\"]']", "Foo"]], ['A'])
def f():
from typing import cast
cast(
int # TC006
, 6.0
)

View file

@ -69,10 +69,7 @@ pub(crate) fn runtime_cast_value(checker: &mut Checker, type_expr: &Expr) {
checker.stylist(),
checker.locator(),
);
if checker
.comment_ranges()
.has_comments(type_expr, checker.source())
{
if checker.comment_ranges().intersects(type_expr.range()) {
diagnostic.set_fix(Fix::unsafe_edit(edit));
} else {
diagnostic.set_fix(Fix::safe_edit(edit));

View file

@ -289,10 +289,7 @@ pub(crate) fn quoted_type_alias(
let range = annotation_expr.range();
let mut diagnostic = Diagnostic::new(QuotedTypeAlias, range);
let edit = Edit::range_replacement(annotation_expr.value.to_string(), range);
if checker
.comment_ranges()
.has_comments(expr, checker.source())
{
if checker.comment_ranges().intersects(range) {
diagnostic.set_fix(Fix::unsafe_edit(edit));
} else {
diagnostic.set_fix(Fix::safe_edit(edit));

View file

@ -190,3 +190,25 @@ TC006.py:82:10: TC006 [*] Add quotes to type expression in `typing.cast()`
81 81 |
82 |- cast(list[Annotated["list['Literal[\"A\"]']", "Foo"]], ['A'])
82 |+ cast("list[Annotated[list[Literal['A']], 'Foo']]", ['A'])
83 83 |
84 84 |
85 85 | def f():
TC006.py:89:9: TC006 [*] Add quotes to type expression in `typing.cast()`
|
88 | cast(
89 | int # TC006
| ^^^ TC006
90 | , 6.0
91 | )
|
= help: Add quotes
Safe fix
86 86 | from typing import cast
87 87 |
88 88 | cast(
89 |- int # TC006
89 |+ "int" # TC006
90 90 | , 6.0
91 91 | )