mirror of
https://github.com/rust-lang/rust.git
synced 2025-02-05 11:33:04 +00:00
Better handle too many #
recovery in raw str
Point at all the unnecessary trailing `#`. Better handle interaction with outer attributes when `;` is missing. Fix #95030.
This commit is contained in:
parent
1e9aa8a96b
commit
3587406967
@ -431,10 +431,11 @@ impl<'a> Parser<'a> {
|
|||||||
return Ok(true);
|
return Ok(true);
|
||||||
} else if self.look_ahead(0, |t| {
|
} else if self.look_ahead(0, |t| {
|
||||||
t == &token::CloseDelim(token::Brace)
|
t == &token::CloseDelim(token::Brace)
|
||||||
|| (
|
|| (t.can_begin_expr() && t != &token::Semi && t != &token::Pound)
|
||||||
t.can_begin_expr() && t != &token::Semi && t != &token::Pound
|
// Avoid triggering with too many trailing `#` in raw string.
|
||||||
// Avoid triggering with too many trailing `#` in raw string.
|
|| (sm.is_multiline(
|
||||||
)
|
self.prev_token.span.shrink_to_hi().until(self.token.span.shrink_to_lo())
|
||||||
|
) && t == &token::Pound)
|
||||||
}) {
|
}) {
|
||||||
// Missing semicolon typo. This is triggered if the next token could either start a
|
// Missing semicolon typo. This is triggered if the next token could either start a
|
||||||
// new statement or is a block close. For example:
|
// new statement or is a block close. For example:
|
||||||
@ -508,7 +509,12 @@ impl<'a> Parser<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if self.check_too_many_raw_str_terminators(&mut err) {
|
if self.check_too_many_raw_str_terminators(&mut err) {
|
||||||
return Err(err);
|
if expected.contains(&TokenType::Token(token::Semi)) && self.eat(&token::Semi) {
|
||||||
|
err.emit();
|
||||||
|
return Ok(true);
|
||||||
|
} else {
|
||||||
|
return Err(err);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if self.prev_token.span == DUMMY_SP {
|
if self.prev_token.span == DUMMY_SP {
|
||||||
@ -538,6 +544,7 @@ impl<'a> Parser<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn check_too_many_raw_str_terminators(&mut self, err: &mut Diagnostic) -> bool {
|
fn check_too_many_raw_str_terminators(&mut self, err: &mut Diagnostic) -> bool {
|
||||||
|
let sm = self.sess.source_map();
|
||||||
match (&self.prev_token.kind, &self.token.kind) {
|
match (&self.prev_token.kind, &self.token.kind) {
|
||||||
(
|
(
|
||||||
TokenKind::Literal(Lit {
|
TokenKind::Literal(Lit {
|
||||||
@ -545,15 +552,33 @@ impl<'a> Parser<'a> {
|
|||||||
..
|
..
|
||||||
}),
|
}),
|
||||||
TokenKind::Pound,
|
TokenKind::Pound,
|
||||||
) => {
|
) if !sm.is_multiline(
|
||||||
|
self.prev_token.span.shrink_to_hi().until(self.token.span.shrink_to_lo()),
|
||||||
|
) =>
|
||||||
|
{
|
||||||
|
let n_hashes: u8 = *n_hashes;
|
||||||
err.set_primary_message("too many `#` when terminating raw string");
|
err.set_primary_message("too many `#` when terminating raw string");
|
||||||
|
let str_span = self.prev_token.span;
|
||||||
|
let mut span = self.token.span;
|
||||||
|
let mut count = 0;
|
||||||
|
while self.token.kind == TokenKind::Pound
|
||||||
|
&& !sm.is_multiline(span.shrink_to_hi().until(self.token.span.shrink_to_lo()))
|
||||||
|
{
|
||||||
|
span = span.with_hi(self.token.span.hi());
|
||||||
|
self.bump();
|
||||||
|
count += 1;
|
||||||
|
}
|
||||||
|
err.set_span(span);
|
||||||
err.span_suggestion(
|
err.span_suggestion(
|
||||||
self.token.span,
|
span,
|
||||||
"remove the extra `#`",
|
&format!("remove the extra `#`{}", pluralize!(count)),
|
||||||
String::new(),
|
String::new(),
|
||||||
Applicability::MachineApplicable,
|
Applicability::MachineApplicable,
|
||||||
);
|
);
|
||||||
err.note(&format!("the raw string started with {n_hashes} `#`s"));
|
err.span_label(
|
||||||
|
str_span,
|
||||||
|
&format!("this raw string started with {n_hashes} `#`{}", pluralize!(n_hashes)),
|
||||||
|
);
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
_ => false,
|
_ => false,
|
||||||
|
@ -1,4 +1,22 @@
|
|||||||
static s: &'static str =
|
static s: &'static str =
|
||||||
r#"
|
r#""## //~ ERROR too many `#` when terminating raw string
|
||||||
"## //~ too many `#` when terminating raw string
|
|
||||||
;
|
;
|
||||||
|
|
||||||
|
static s2: &'static str =
|
||||||
|
r#"
|
||||||
|
"#### //~ ERROR too many `#` when terminating raw string
|
||||||
|
;
|
||||||
|
|
||||||
|
const A: &'static str = r"" //~ ERROR expected `;`, found `#`
|
||||||
|
|
||||||
|
// Test
|
||||||
|
#[test]
|
||||||
|
fn test() {}
|
||||||
|
|
||||||
|
const B: &'static str = r""## //~ ERROR too many `#` when terminating raw string
|
||||||
|
|
||||||
|
// Test
|
||||||
|
#[test]
|
||||||
|
fn test2() {}
|
||||||
|
|
||||||
|
fn main() {}
|
||||||
|
@ -1,10 +1,36 @@
|
|||||||
error: too many `#` when terminating raw string
|
error: too many `#` when terminating raw string
|
||||||
--> $DIR/raw-str-unbalanced.rs:3:9
|
--> $DIR/raw-str-unbalanced.rs:2:10
|
||||||
|
|
|
|
||||||
LL | "##
|
LL | r#""##
|
||||||
| ^ help: remove the extra `#`
|
| -----^ help: remove the extra `#`
|
||||||
|
| |
|
||||||
|
| this raw string started with 1 `#`
|
||||||
|
|
||||||
|
error: too many `#` when terminating raw string
|
||||||
|
--> $DIR/raw-str-unbalanced.rs:7:9
|
||||||
|
|
|
|
||||||
= note: the raw string started with 1 `#`s
|
LL | / r#"
|
||||||
|
LL | | "####
|
||||||
|
| | -^^^ help: remove the extra `#`s
|
||||||
|
| |________|
|
||||||
|
| this raw string started with 1 `#`
|
||||||
|
|
||||||
error: aborting due to previous error
|
error: expected `;`, found `#`
|
||||||
|
--> $DIR/raw-str-unbalanced.rs:10:28
|
||||||
|
|
|
||||||
|
LL | const A: &'static str = r""
|
||||||
|
| ^ help: add `;` here
|
||||||
|
...
|
||||||
|
LL | #[test]
|
||||||
|
| - unexpected token
|
||||||
|
|
||||||
|
error: too many `#` when terminating raw string
|
||||||
|
--> $DIR/raw-str-unbalanced.rs:16:28
|
||||||
|
|
|
||||||
|
LL | const B: &'static str = r""##
|
||||||
|
| ---^^ help: remove the extra `#`s
|
||||||
|
| |
|
||||||
|
| this raw string started with 0 `#`s
|
||||||
|
|
||||||
|
error: aborting due to 4 previous errors
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user