[pyupgrade] Fix syntax error on string with newline escape and comment (UP037)#22968
[pyupgrade] Fix syntax error on string with newline escape and comment (UP037)#22968dylwil3 merged 3 commits intoastral-sh:mainfrom
pyupgrade] Fix syntax error on string with newline escape and comment (UP037)#22968Conversation
|
pyupgrade] Fix causes syntax error on string with newline escape and comment (UP037)pyupgrade] Fix syntax error on string with newline escape and comment (UP037)
ntBre
left a comment
There was a problem hiding this comment.
Thanks! This looks good to me, but I'm curious for @dylwil3 to take a quick look since he wrote this comment about the logical newline. I printed out the tokens here, and it seems the last token is a comment instead of a newline:
[crates/ruff_linter/src/rules/pyupgrade/rules/quoted_annotation.rs:116:5] &checker.tokens() = Tokens {
raw: [
Name 0..1,
Newline 1..2,
Comment 2..3,
],
}
I just want to make sure we're not being too permissive here or running into a bug from another part of the code.
crates/ruff_linter/src/rules/pyupgrade/rules/quoted_annotation.rs
Outdated
Show resolved
Hide resolved
dylwil3
left a comment
There was a problem hiding this comment.
Looks right to me! That old comment of mine was mistaken (though it was true for all the examples in the fixture 😄 )
I guess it's sort of an accident that this example worked before
def f() -> """Literal[0]
#
""":
return 0The resulting fix is the same, but it now hits a different match arm here:
let new_content = match (spans_multiple_lines, last_token_is_comment) {
(_, false) if in_parameter_annotation(range.start(), checker.semantic()) => {
annotation.to_string()
}
(false, false) => annotation.to_string(),
(true, false) => format!("({annotation})"),
(_, true) => format!("({annotation}\n)"),
};In any event, thanks for the fix!
* main: (45 commits) [ty] Fix wrong inlay hints for overloaded function arguments (astral-sh#23179) [ty] Respect `@no_type_check` when combined with other decorators (astral-sh#23177) [ty] Use type context when inferring constructor argument types (astral-sh#23139) [`airflow`] Add ruff rules to catch deprecated attribute access from context key for Airflow 3.0 (`AIR301`) (astral-sh#22850) Support formatting `pycon` markdown code blocks (astral-sh#23112) Markdown formatting in LSP (astral-sh#23063) Instruct Claude to use comments more sparingly (astral-sh#23181) [`flake8-gettext`] Fix false negatives for plural argument of ngettext (`INT001`, `INT002`, `INT003`) (astral-sh#21078) [ty] Invoking goto-def on parentheses of a class constructor call takes you too constructor method [ty] Make goto definition on class constructor always go to class definition [ty] Assign lower completions ranking to deprecated functions and classes (astral-sh#23089) [ty] Fix parameter references across files via keyword args (astral-sh#23012) [ty] Exclude enclosing class for base completions (astral-sh#23141) [`pyupgrade`] Fix syntax error on string with newline escape and comment (`UP037`) (astral-sh#22968) [ty] Improve documentation for `expect_single_definition` method (astral-sh#23175) [ty] Configure check mode for all projects Add `home-assistant` to ecosystem projects (astral-sh#23132) Add tabbed shell completion documentation (astral-sh#23169) Bump typing conformance-suite pin (astral-sh#23174) [ty] Fix invalid diagnostic location for a sub-call to a specialized ParamSpec (astral-sh#23036) ...
Summary
Fixes a syntax error introduced by
UP037when a quoted annotation contains a trailing comment.Fixes #19835.
Problem
The logic for detecting trailing comments in quoted annotations was brittle, relying on a fixed offset (
len() - 2) from the end of the token stream. This failed to correctly identify comments in strings like"A\n#", leading to invalid code generation where the closing parenthesis of the function definition was commented out.Approach
Updated the logic in
crates/ruff_linter/src/rules/pyupgrade/rules/quoted_annotation.rsto detect trailing comments. It now iterates backwards through the tokens of the annotation string, skipping any newline tokens, to find if the last significant token is a comment.Test Plan
Added regression tests to
crates/ruff_linter/resources/test/fixtures/pyupgrade/UP037_0.py.Verified with:
cargo test -p ruff_linter pyupgrade::tests