Preserve raw string prefix and escapes (#15694)

## Summary

Fixes #9663 and also improves the fixes for
[RUF055](https://docs.astral.sh/ruff/rules/unnecessary-regular-expression/)
since regular expressions are often written as raw strings.

This doesn't include raw f-strings.

## Test Plan

Existing snapshots for RUF055 and PT009, plus a new `Generator` test and
a regression test for the reported `PIE810` issue.
This commit is contained in:
Brent Westbrook 2025-01-23 12:12:10 -05:00 committed by GitHub
parent 569060f46c
commit cffd1866ce
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 65 additions and 18 deletions

View file

@ -1284,10 +1284,19 @@ impl<'a> Generator<'a> {
fn unparse_string_literal(&mut self, string_literal: &ast::StringLiteral) {
let ast::StringLiteral { value, flags, .. } = string_literal;
if flags.prefix().is_unicode() {
self.p("u");
// for raw strings, we don't want to perform the UnicodeEscape in `p_str_repr`, so build the
// replacement here
if flags.prefix().is_raw() {
self.p(flags.prefix().as_str());
self.p(self.quote.as_str());
self.p(value);
self.p(self.quote.as_str());
} else {
if flags.prefix().is_unicode() {
self.p("u");
}
self.p_str_repr(value);
}
self.p_str_repr(value);
}
fn unparse_string_literal_value(&mut self, value: &ast::StringLiteralValue) {
@ -1712,7 +1721,7 @@ class Foo:
assert_eq!(round_trip(r#""hello""#), r#""hello""#);
assert_eq!(round_trip(r"'hello'"), r#""hello""#);
assert_eq!(round_trip(r"u'hello'"), r#"u"hello""#);
assert_eq!(round_trip(r"r'hello'"), r#""hello""#);
assert_eq!(round_trip(r"r'hello'"), r#"r"hello""#);
assert_eq!(round_trip(r"b'hello'"), r#"b"hello""#);
assert_eq!(round_trip(r#"("abc" "def" "ghi")"#), r#""abc" "def" "ghi""#);
assert_eq!(round_trip(r#""he\"llo""#), r#"'he"llo'"#);
@ -1720,6 +1729,12 @@ class Foo:
assert_eq!(round_trip(r#"f'abc{"def"}{1}'"#), r#"f"abc{'def'}{1}""#);
}
#[test]
fn raw() {
assert_round_trip!(r#"r"a\.b""#); // https://github.com/astral-sh/ruff/issues/9663
assert_round_trip!(r#"R"a\.b""#);
}
#[test]
fn self_documenting_fstring() {
assert_round_trip!(r#"f"{ chr(65) = }""#);