Skip to content

Commit

Permalink
[red-knot] Display raw characters for string literal (#14351)
Browse files Browse the repository at this point in the history
## 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.
  • Loading branch information
dhruvmanila authored Nov 15, 2024
1 parent 375cead commit 874da9c
Showing 1 changed file with 56 additions and 6 deletions.
62 changes: 56 additions & 6 deletions crates/red_knot_python_semantic/src/types/display.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
//! Display implementations for types.

use std::fmt::{self, Display, Formatter};
use std::fmt::{self, Display, Formatter, Write};

use ruff_db::display::FormatterJoinExtension;
use ruff_python_ast::str::Quote;
use ruff_python_literal::escape::AsciiEscape;

use crate::types::{
ClassLiteralType, InstanceType, IntersectionType, KnownClass, SubclassOfType, Type, UnionType,
ClassLiteralType, InstanceType, IntersectionType, KnownClass, StringLiteralType,
SubclassOfType, Type, UnionType,
};
use crate::Db;
use rustc_hash::FxHashMap;
Expand Down Expand Up @@ -91,9 +92,7 @@ impl Display for DisplayRepresentation<'_> {
Type::Intersection(intersection) => intersection.display(self.db).fmt(f),
Type::IntLiteral(n) => n.fmt(f),
Type::BooleanLiteral(boolean) => f.write_str(if boolean { "True" } else { "False" }),
Type::StringLiteral(string) => {
write!(f, r#""{}""#, string.value(self.db).replace('"', r#"\""#))
}
Type::StringLiteral(string) => string.display(self.db).fmt(f),
Type::LiteralString => f.write_str("LiteralString"),
Type::BytesLiteral(bytes) => {
let escape =
Expand Down Expand Up @@ -328,13 +327,40 @@ impl<'db> Display for DisplayTypeArray<'_, 'db> {
}
}

impl<'db> StringLiteralType<'db> {
fn display(&'db self, db: &'db dyn Db) -> DisplayStringLiteralType<'db> {
DisplayStringLiteralType { db, ty: self }
}
}

struct DisplayStringLiteralType<'db> {
ty: &'db StringLiteralType<'db>,
db: &'db dyn Db,
}

impl Display for DisplayStringLiteralType<'_> {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
let value = self.ty.value(self.db);
f.write_char('"')?;
for ch in value.chars() {
match ch {
// `escape_debug` will escape even single quotes, which is not necessary for our
// use case as we are already using double quotes to wrap the string.
'\'' => f.write_char('\'')?,
_ => write!(f, "{}", ch.escape_debug())?,
}
}
f.write_char('"')
}
}

#[cfg(test)]
mod tests {
use ruff_db::files::system_path_to_file;
use ruff_db::system::{DbWithTestSystem, SystemPathBuf};

use crate::db::tests::TestDb;
use crate::types::{global_symbol, SliceLiteralType, Type, UnionType};
use crate::types::{global_symbol, SliceLiteralType, StringLiteralType, Type, UnionType};
use crate::{Program, ProgramSettings, PythonVersion, SearchPathSettings};

fn setup_db() -> TestDb {
Expand Down Expand Up @@ -451,4 +477,28 @@ mod tests {
"slice[None, None, Literal[2]]"
);
}

#[test]
fn string_literal_display() {
let db = setup_db();

assert_eq!(
Type::StringLiteral(StringLiteralType::new(&db, r"\n"))
.display(&db)
.to_string(),
r#"Literal["\\n"]"#
);
assert_eq!(
Type::StringLiteral(StringLiteralType::new(&db, "'"))
.display(&db)
.to_string(),
r#"Literal["'"]"#
);
assert_eq!(
Type::StringLiteral(StringLiteralType::new(&db, r#"""#))
.display(&db)
.to_string(),
r#"Literal["\""]"#
);
}
}

0 comments on commit 874da9c

Please sign in to comment.