Skip to content

Commit 3e232bb

Browse files
committed
fix: replace unescape fn with the one in ra-ap-rustc_lexer
1 parent a543516 commit 3e232bb

File tree

2 files changed

+31
-34
lines changed

2 files changed

+31
-34
lines changed

crates/hir-expand/src/attrs.rs

+30-34
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ use intern::Interned;
88
use mbe::{syntax_node_to_token_tree, DelimiterKind, Punct};
99
use smallvec::{smallvec, SmallVec};
1010
use span::{Span, SyntaxContextId};
11+
use syntax::unescape;
1112
use syntax::{ast, format_smolstr, match_ast, AstNode, AstToken, SmolStr, SyntaxNode};
1213
use triomphe::ThinArc;
1314

@@ -54,8 +55,7 @@ impl RawAttrs {
5455
Attr {
5556
id,
5657
input: Some(Interned::new(AttrInput::Literal(tt::Literal {
57-
// FIXME: Escape quotes from comment content
58-
text: SmolStr::new(format_smolstr!("\"{doc}\"",)),
58+
text: SmolStr::new(format_smolstr!("\"{}\"", Self::escape_chars(doc))),
5959
span,
6060
}))),
6161
path: Interned::new(ModPath::from(crate::name!(doc))),
@@ -74,6 +74,10 @@ impl RawAttrs {
7474
RawAttrs { entries }
7575
}
7676

77+
fn escape_chars(s: &str) -> String {
78+
s.replace('\\', r#"\\"#).replace('"', r#"\""#)
79+
}
80+
7781
pub fn from_attrs_owner(
7882
db: &dyn ExpandDatabase,
7983
owner: InFile<&dyn ast::HasAttrs>,
@@ -303,9 +307,7 @@ impl Attr {
303307
Some(it) => {
304308
it.trim_matches('#').strip_prefix('"')?.strip_suffix('"').map(Cow::Borrowed)
305309
}
306-
None => {
307-
it.text.strip_prefix('"')?.strip_suffix('"').and_then(unescape).map(Cow::Owned)
308-
}
310+
None => it.text.strip_prefix('"')?.strip_suffix('"').and_then(unescape),
309311
},
310312
_ => None,
311313
}
@@ -360,37 +362,31 @@ impl Attr {
360362
}
361363
}
362364

363-
fn unescape(s: &str) -> Option<String> {
364-
let mut res = String::with_capacity(s.len());
365-
let mut chars = s.chars();
366-
367-
while let Some(c) = chars.next() {
368-
if c == '\\' {
369-
match chars.next()? {
370-
'n' => res.push('\n'),
371-
'r' => res.push('\r'),
372-
't' => res.push('\t'),
373-
'\\' => res.push('\\'),
374-
'\'' => res.push('\''),
375-
'"' => res.push('"'),
376-
'0' => res.push('\0'),
377-
'x' => {
378-
let hex = chars.by_ref().take(2).collect::<String>();
379-
let c = u8::from_str_radix(&hex, 16).ok()?;
380-
res.push(c as char);
381-
}
382-
'u' => {
383-
let hex = chars.by_ref().take(4).collect::<String>();
384-
let c = u32::from_str_radix(&hex, 16).ok()?;
385-
res.push(char::from_u32(c)?);
386-
}
387-
_ => return None,
388-
}
389-
} else {
390-
res.push(c);
365+
fn unescape(s: &str) -> Option<Cow<'_, str>> {
366+
let mut buf = String::new();
367+
let mut prev_end = 0;
368+
let mut has_error = false;
369+
unescape::unescape_unicode(s, unescape::Mode::Str, &mut |char_range, unescaped_char| match (
370+
unescaped_char,
371+
buf.capacity() == 0,
372+
) {
373+
(Ok(c), false) => buf.push(c),
374+
(Ok(_), true) if char_range.len() == 1 && char_range.start == prev_end => {
375+
prev_end = char_range.end
376+
}
377+
(Ok(c), true) => {
378+
buf.reserve_exact(s.len());
379+
buf.push_str(&s[..prev_end]);
380+
buf.push(c);
391381
}
382+
(Err(_), _) => has_error = true,
383+
});
384+
385+
match (has_error, buf.capacity() == 0) {
386+
(true, _) => None,
387+
(false, false) => Some(Cow::Owned(buf)),
388+
(false, true) => Some(Cow::Borrowed(s)),
392389
}
393-
Some(res)
394390
}
395391

396392
pub fn collect_attrs(

crates/syntax/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ pub use rowan::{
6565
api::Preorder, Direction, GreenNode, NodeOrToken, SyntaxText, TextRange, TextSize,
6666
TokenAtOffset, WalkEvent,
6767
};
68+
pub use rustc_lexer::unescape;
6869
pub use smol_str::{format_smolstr, SmolStr};
6970

7071
/// `Parse` is the result of the parsing: a syntax tree and a collection of

0 commit comments

Comments
 (0)