Skip to content

Commit 594b7b0

Browse files
authored
[ty] Preserve quoting style when autofixing TypedDict keys (#21682)
1 parent b5b4917 commit 594b7b0

File tree

3 files changed

+42
-4
lines changed

3 files changed

+42
-4
lines changed

crates/ty_python_semantic/resources/mdtest/snapshots/typed_dict.md_-_`TypedDict`_-_Diagnostics_(e5289abf5c570c29).snap

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,9 @@ mdtest path: crates/ty_python_semantic/resources/mdtest/typed_dict.md
5252
38 |
5353
39 | def write_to_readonly_key(employee: Employee):
5454
40 | employee["id"] = 42 # error: [invalid-assignment]
55+
41 | def write_to_non_existing_key_single_quotes(person: Person):
56+
42 | # error: [invalid-key]
57+
43 | person['naem'] = "Alice" # fmt: skip
5558
```
5659

5760
# Diagnostics
@@ -217,6 +220,8 @@ error[invalid-assignment]: Cannot assign to key "id" on TypedDict `Employee`
217220
| -------- ^^^^ key is marked read-only
218221
| |
219222
| TypedDict `Employee`
223+
41 | def write_to_non_existing_key_single_quotes(person: Person):
224+
42 | # error: [invalid-key]
220225
|
221226
info: Item declaration
222227
--> src/mdtest_snippet.py:36:5
@@ -229,3 +234,24 @@ info: Item declaration
229234
info: rule `invalid-assignment` is enabled by default
230235
231236
```
237+
238+
```
239+
error[invalid-key]: Unknown key "naem" for TypedDict `Person`
240+
--> src/mdtest_snippet.py:43:5
241+
|
242+
41 | def write_to_non_existing_key_single_quotes(person: Person):
243+
42 | # error: [invalid-key]
244+
43 | person['naem'] = "Alice" # fmt: skip
245+
| ------ ^^^^^^ Did you mean 'name'?
246+
| |
247+
| TypedDict `Person`
248+
|
249+
info: rule `invalid-key` is enabled by default
250+
40 | employee["id"] = 42 # error: [invalid-assignment]
251+
41 | def write_to_non_existing_key_single_quotes(person: Person):
252+
42 | # error: [invalid-key]
253+
- person['naem'] = "Alice" # fmt: skip
254+
43 + person['name'] = "Alice" # fmt: skip
255+
note: This is an unsafe fix and may change runtime behavior
256+
257+
```

crates/ty_python_semantic/resources/mdtest/typed_dict.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1502,6 +1502,14 @@ def write_to_readonly_key(employee: Employee):
15021502
employee["id"] = 42 # error: [invalid-assignment]
15031503
```
15041504

1505+
If the key uses single quotes, the autofix preserves that quoting style:
1506+
1507+
```py
1508+
def write_to_non_existing_key_single_quotes(person: Person):
1509+
# error: [invalid-key]
1510+
person['naem'] = "Alice" # fmt: skip
1511+
```
1512+
15051513
## Import aliases
15061514

15071515
`TypedDict` can be imported with aliases and should work correctly:

crates/ty_python_semantic/src/types/diagnostic.rs

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ use ruff_db::{
4040
use ruff_diagnostics::{Edit, Fix};
4141
use ruff_python_ast::name::Name;
4242
use ruff_python_ast::parenthesize::parentheses_iterator;
43-
use ruff_python_ast::{self as ast, AnyNodeRef};
43+
use ruff_python_ast::{self as ast, AnyNodeRef, StringFlags};
4444
use ruff_python_trivia::CommentRanges;
4545
use ruff_text_size::{Ranged, TextRange};
4646
use rustc_hash::FxHashSet;
@@ -3456,11 +3456,15 @@ pub(crate) fn report_invalid_key_on_typed_dict<'db>(
34563456

34573457
let existing_keys = items.keys();
34583458
if let Some(suggestion) = did_you_mean(existing_keys, key) {
3459-
if key_node.is_expr_string_literal() {
3459+
if let AnyNodeRef::ExprStringLiteral(literal) = key_node {
3460+
let quoted_suggestion = format!(
3461+
"{quote}{suggestion}{quote}",
3462+
quote = literal.value.first_literal_flags().quote_str()
3463+
);
34603464
diagnostic
3461-
.set_primary_message(format_args!("Did you mean \"{suggestion}\"?"));
3465+
.set_primary_message(format_args!("Did you mean {quoted_suggestion}?"));
34623466
diagnostic.set_fix(Fix::unsafe_edit(Edit::range_replacement(
3463-
format!("\"{suggestion}\""),
3467+
quoted_suggestion,
34643468
key_node.range(),
34653469
)));
34663470
} else {

0 commit comments

Comments
 (0)