Skip to content

Commit 874da9c

Browse files
authored
[red-knot] Display raw characters for string literal (#14351)
## Summary Closes: #14330 | `main` | PR | |--------|--------| | <img width="693" alt="Screenshot 2024-11-15 at 9 41 09 AM" src="https://github.com/user-attachments/assets/0d10f2be-2155-4387-8d39-eb1b5027cfd4"> | <img width="800" alt="Screenshot 2024-11-15 at 9 40 27 AM" src="https://github.com/user-attachments/assets/ba68911c-f4bf-405a-a597-44207b4bde7a"> | ## Test Plan Add test cases for escape and quote characters.
1 parent 375cead commit 874da9c

File tree

1 file changed

+56
-6
lines changed
  • crates/red_knot_python_semantic/src/types

1 file changed

+56
-6
lines changed

crates/red_knot_python_semantic/src/types/display.rs

Lines changed: 56 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
11
//! Display implementations for types.
22
3-
use std::fmt::{self, Display, Formatter};
3+
use std::fmt::{self, Display, Formatter, Write};
44

55
use ruff_db::display::FormatterJoinExtension;
66
use ruff_python_ast::str::Quote;
77
use ruff_python_literal::escape::AsciiEscape;
88

99
use crate::types::{
10-
ClassLiteralType, InstanceType, IntersectionType, KnownClass, SubclassOfType, Type, UnionType,
10+
ClassLiteralType, InstanceType, IntersectionType, KnownClass, StringLiteralType,
11+
SubclassOfType, Type, UnionType,
1112
};
1213
use crate::Db;
1314
use rustc_hash::FxHashMap;
@@ -91,9 +92,7 @@ impl Display for DisplayRepresentation<'_> {
9192
Type::Intersection(intersection) => intersection.display(self.db).fmt(f),
9293
Type::IntLiteral(n) => n.fmt(f),
9394
Type::BooleanLiteral(boolean) => f.write_str(if boolean { "True" } else { "False" }),
94-
Type::StringLiteral(string) => {
95-
write!(f, r#""{}""#, string.value(self.db).replace('"', r#"\""#))
96-
}
95+
Type::StringLiteral(string) => string.display(self.db).fmt(f),
9796
Type::LiteralString => f.write_str("LiteralString"),
9897
Type::BytesLiteral(bytes) => {
9998
let escape =
@@ -328,13 +327,40 @@ impl<'db> Display for DisplayTypeArray<'_, 'db> {
328327
}
329328
}
330329

330+
impl<'db> StringLiteralType<'db> {
331+
fn display(&'db self, db: &'db dyn Db) -> DisplayStringLiteralType<'db> {
332+
DisplayStringLiteralType { db, ty: self }
333+
}
334+
}
335+
336+
struct DisplayStringLiteralType<'db> {
337+
ty: &'db StringLiteralType<'db>,
338+
db: &'db dyn Db,
339+
}
340+
341+
impl Display for DisplayStringLiteralType<'_> {
342+
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
343+
let value = self.ty.value(self.db);
344+
f.write_char('"')?;
345+
for ch in value.chars() {
346+
match ch {
347+
// `escape_debug` will escape even single quotes, which is not necessary for our
348+
// use case as we are already using double quotes to wrap the string.
349+
'\'' => f.write_char('\'')?,
350+
_ => write!(f, "{}", ch.escape_debug())?,
351+
}
352+
}
353+
f.write_char('"')
354+
}
355+
}
356+
331357
#[cfg(test)]
332358
mod tests {
333359
use ruff_db::files::system_path_to_file;
334360
use ruff_db::system::{DbWithTestSystem, SystemPathBuf};
335361

336362
use crate::db::tests::TestDb;
337-
use crate::types::{global_symbol, SliceLiteralType, Type, UnionType};
363+
use crate::types::{global_symbol, SliceLiteralType, StringLiteralType, Type, UnionType};
338364
use crate::{Program, ProgramSettings, PythonVersion, SearchPathSettings};
339365

340366
fn setup_db() -> TestDb {
@@ -451,4 +477,28 @@ mod tests {
451477
"slice[None, None, Literal[2]]"
452478
);
453479
}
480+
481+
#[test]
482+
fn string_literal_display() {
483+
let db = setup_db();
484+
485+
assert_eq!(
486+
Type::StringLiteral(StringLiteralType::new(&db, r"\n"))
487+
.display(&db)
488+
.to_string(),
489+
r#"Literal["\\n"]"#
490+
);
491+
assert_eq!(
492+
Type::StringLiteral(StringLiteralType::new(&db, "'"))
493+
.display(&db)
494+
.to_string(),
495+
r#"Literal["'"]"#
496+
);
497+
assert_eq!(
498+
Type::StringLiteral(StringLiteralType::new(&db, r#"""#))
499+
.display(&db)
500+
.to_string(),
501+
r#"Literal["\""]"#
502+
);
503+
}
454504
}

0 commit comments

Comments
 (0)