Skip to content
This repository was archived by the owner on May 28, 2025. It is now read-only.

Commit f655671

Browse files
authored
Merge pull request rust-lang#2983 from topecongiro/issue-2642
Handle raw string literals in CharClasses
2 parents 414f98e + 6748042 commit f655671

File tree

3 files changed

+106
-0
lines changed

3 files changed

+106
-0
lines changed

src/comment.rs

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -785,6 +785,9 @@ enum CharClassesStatus {
785785
Normal,
786786
LitString,
787787
LitStringEscape,
788+
LitRawString(u32),
789+
RawStringPrefix(u32),
790+
RawStringSuffix(u32),
788791
LitChar,
789792
LitCharEscape,
790793
// The u32 is the nesting deepness of the comment
@@ -858,6 +861,20 @@ where
858861
}
859862
}
860863

864+
fn is_raw_string_suffix<T>(iter: &mut MultiPeek<T>, count: u32) -> bool
865+
where
866+
T: Iterator,
867+
T::Item: RichChar,
868+
{
869+
for _ in 0..count {
870+
match iter.peek() {
871+
Some(c) if c.get_char() == '#' => continue,
872+
_ => return false,
873+
}
874+
}
875+
true
876+
}
877+
861878
impl<T> Iterator for CharClasses<T>
862879
where
863880
T: Iterator,
@@ -870,6 +887,43 @@ where
870887
let chr = item.get_char();
871888
let mut char_kind = FullCodeCharKind::Normal;
872889
self.status = match self.status {
890+
CharClassesStatus::LitRawString(sharps) => {
891+
char_kind = FullCodeCharKind::InString;
892+
match chr {
893+
'"' => {
894+
if sharps == 0 {
895+
char_kind = FullCodeCharKind::Normal;
896+
CharClassesStatus::Normal
897+
} else if is_raw_string_suffix(&mut self.base, sharps) {
898+
CharClassesStatus::RawStringSuffix(sharps)
899+
} else {
900+
CharClassesStatus::LitRawString(sharps)
901+
}
902+
}
903+
_ => CharClassesStatus::LitRawString(sharps),
904+
}
905+
}
906+
CharClassesStatus::RawStringPrefix(sharps) => {
907+
char_kind = FullCodeCharKind::InString;
908+
match chr {
909+
'#' => CharClassesStatus::RawStringPrefix(sharps + 1),
910+
'"' => CharClassesStatus::LitRawString(sharps),
911+
_ => CharClassesStatus::Normal, // Unreachable.
912+
}
913+
}
914+
CharClassesStatus::RawStringSuffix(sharps) => {
915+
match chr {
916+
'#' => {
917+
if sharps == 1 {
918+
CharClassesStatus::Normal
919+
} else {
920+
char_kind = FullCodeCharKind::InString;
921+
CharClassesStatus::RawStringSuffix(sharps - 1)
922+
}
923+
}
924+
_ => CharClassesStatus::Normal, // Unreachable
925+
}
926+
}
873927
CharClassesStatus::LitString => match chr {
874928
'"' => CharClassesStatus::Normal,
875929
'\\' => {
@@ -892,6 +946,13 @@ where
892946
},
893947
CharClassesStatus::LitCharEscape => CharClassesStatus::LitChar,
894948
CharClassesStatus::Normal => match chr {
949+
'r' => match self.base.peek().map(|c| c.get_char()) {
950+
Some('#') | Some('"') => {
951+
char_kind = FullCodeCharKind::InString;
952+
CharClassesStatus::RawStringPrefix(0)
953+
}
954+
_ => CharClassesStatus::Normal,
955+
},
895956
'"' => {
896957
char_kind = FullCodeCharKind::InString;
897958
CharClassesStatus::LitString

tests/source/macro_rules.rs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -279,3 +279,23 @@ fn foo() {
279279
}
280280
}
281281
}
282+
283+
// #2642
284+
macro_rules! template {
285+
($name: expr) => {
286+
format_args!(r##"
287+
"http://example.com"
288+
289+
# test
290+
"##, $name)
291+
}
292+
}
293+
294+
macro_rules! template {
295+
() => {
296+
format_args!(r"
297+
//
298+
299+
")
300+
}
301+
}

tests/target/macro_rules.rs

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -333,3 +333,28 @@ fn foo() {
333333
}
334334
}
335335
}
336+
337+
// #2642
338+
macro_rules! template {
339+
($name:expr) => {
340+
format_args!(
341+
r##"
342+
"http://example.com"
343+
344+
# test
345+
"##,
346+
$name
347+
)
348+
};
349+
}
350+
351+
macro_rules! template {
352+
() => {
353+
format_args!(
354+
r"
355+
//
356+
357+
"
358+
)
359+
};
360+
}

0 commit comments

Comments
 (0)