-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Escape control chars in source when printing diagnostics #8049
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: trunk
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,4 @@ | ||
use alloc::{boxed::Box, string::String}; | ||
use alloc::{borrow::Cow, boxed::Box, string::String}; | ||
use core::{error::Error, fmt}; | ||
|
||
#[derive(Clone, Debug)] | ||
|
@@ -41,7 +41,7 @@ impl fmt::Display for ShaderError<crate::WithSpan<crate::valid::ValidationError> | |
use codespan_reporting::{files::SimpleFile, term}; | ||
|
||
let label = self.label.as_deref().unwrap_or_default(); | ||
let files = SimpleFile::new(label, &self.source); | ||
let files = SimpleFile::new(label, replace_control_chars(&self.source)); | ||
let config = term::Config::default(); | ||
|
||
let writer = { | ||
|
@@ -137,3 +137,29 @@ where | |
Some(&self.inner) | ||
} | ||
} | ||
|
||
pub(crate) fn replace_control_chars(s: &str) -> Cow<'_, str> { | ||
const REPLACEMENT_CHAR: &str = "\u{FFFD}"; | ||
|
||
let mut res = Cow::Borrowed(s); | ||
let mut base = 0; | ||
|
||
while let Some(found_pos) = res[base..].find(|c: char| c.is_control() && !c.is_whitespace()) { | ||
let found_len = res[base + found_pos..].chars().next().unwrap().len_utf8(); | ||
res.to_mut().replace_range( | ||
base + found_pos..base + found_pos + found_len, | ||
REPLACEMENT_CHAR, | ||
); | ||
base += found_pos + REPLACEMENT_CHAR.len(); | ||
} | ||
Comment on lines
+148
to
+153
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nitpick(non-blocking): I think it'd be easier to understand this code (including |
||
|
||
res | ||
} | ||
|
||
#[test] | ||
fn test_replace_control_chars() { | ||
// The UTF-8 encoding of \u{0080} is multiple bytes. | ||
let input = "Foo\u{0080}Bar\u{0001}Baz\n"; | ||
let expected = "Foo\u{FFFD}Bar\u{FFFD}Baz\n"; | ||
assert_eq!(replace_control_chars(input), expected); | ||
} |
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. suggestion: Let's add a |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nitpick: We should
use std::char::REPLACEMENT_CHARACTER
instead of using this ad-hocconst
ant.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wanted to, but couldn't find a way to go from
char
to&str
without a buffer.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh, hmm. I suppose you could use a stack-allocated buffer and
char::encode_utf8
?I'd be satisfied with merely a (doc) comment pointing to
REPLACEMENT_CHARACTER
expressing the type woe you're working around, too.