|
9 | 9 | //! include info about comments and whitespace.
|
10 | 10 |
|
11 | 11 | use rustc_dependencies::lexer as rustc_lexer;
|
| 12 | + |
12 | 13 | use std::ops;
|
13 | 14 |
|
| 15 | +use rustc_lexer::unescape::{EscapeError, Mode}; |
| 16 | + |
14 | 17 | use crate::{
|
15 | 18 | SyntaxKind::{self, *},
|
16 | 19 | T,
|
@@ -254,13 +257,28 @@ impl<'a> Converter<'a> {
|
254 | 257 | rustc_lexer::LiteralKind::Char { terminated } => {
|
255 | 258 | if !terminated {
|
256 | 259 | err = "Missing trailing `'` symbol to terminate the character literal";
|
| 260 | + } else { |
| 261 | + let text = &self.res.text[self.offset + 1..][..len - 1]; |
| 262 | + let i = text.rfind('\'').unwrap(); |
| 263 | + let text = &text[..i]; |
| 264 | + if let Err(e) = rustc_lexer::unescape::unescape_char(text) { |
| 265 | + err = error_to_diagnostic_message(e, Mode::Char); |
| 266 | + } |
257 | 267 | }
|
258 | 268 | CHAR
|
259 | 269 | }
|
260 | 270 | rustc_lexer::LiteralKind::Byte { terminated } => {
|
261 | 271 | if !terminated {
|
262 | 272 | err = "Missing trailing `'` symbol to terminate the byte literal";
|
| 273 | + } else { |
| 274 | + let text = &self.res.text[self.offset + 2..][..len - 2]; |
| 275 | + let i = text.rfind('\'').unwrap(); |
| 276 | + let text = &text[..i]; |
| 277 | + if let Err(e) = rustc_lexer::unescape::unescape_char(text) { |
| 278 | + err = error_to_diagnostic_message(e, Mode::Byte); |
| 279 | + } |
263 | 280 | }
|
| 281 | + |
264 | 282 | BYTE
|
265 | 283 | }
|
266 | 284 | rustc_lexer::LiteralKind::Str { terminated } => {
|
@@ -305,3 +323,40 @@ impl<'a> Converter<'a> {
|
305 | 323 | self.push(syntax_kind, len, err);
|
306 | 324 | }
|
307 | 325 | }
|
| 326 | + |
| 327 | +fn error_to_diagnostic_message(error: EscapeError, mode: Mode) -> &'static str { |
| 328 | + match error { |
| 329 | + EscapeError::ZeroChars => "empty character literal", |
| 330 | + EscapeError::MoreThanOneChar => "character literal may only contain one codepoint", |
| 331 | + EscapeError::LoneSlash => "", |
| 332 | + EscapeError::InvalidEscape if mode == Mode::Byte || mode == Mode::ByteStr => { |
| 333 | + "unknown byte escape" |
| 334 | + } |
| 335 | + EscapeError::InvalidEscape => "unknown character escape", |
| 336 | + EscapeError::BareCarriageReturn => "", |
| 337 | + EscapeError::BareCarriageReturnInRawString => "", |
| 338 | + EscapeError::EscapeOnlyChar if mode == Mode::Byte => "byte constant must be escaped", |
| 339 | + EscapeError::EscapeOnlyChar => "character constant must be escaped", |
| 340 | + EscapeError::TooShortHexEscape => "numeric character escape is too short", |
| 341 | + EscapeError::InvalidCharInHexEscape => "invalid character in numeric character escape", |
| 342 | + EscapeError::OutOfRangeHexEscape => "out of range hex escape", |
| 343 | + EscapeError::NoBraceInUnicodeEscape => "incorrect unicode escape sequence", |
| 344 | + EscapeError::InvalidCharInUnicodeEscape => "invalid character in unicode escape", |
| 345 | + EscapeError::EmptyUnicodeEscape => "empty unicode escape", |
| 346 | + EscapeError::UnclosedUnicodeEscape => "unterminated unicode escape", |
| 347 | + EscapeError::LeadingUnderscoreUnicodeEscape => "invalid start of unicode escape", |
| 348 | + EscapeError::OverlongUnicodeEscape => "overlong unicode escape", |
| 349 | + EscapeError::LoneSurrogateUnicodeEscape => "invalid unicode character escape", |
| 350 | + EscapeError::OutOfRangeUnicodeEscape => "invalid unicode character escape", |
| 351 | + EscapeError::UnicodeEscapeInByte => "unicode escape in byte string", |
| 352 | + EscapeError::NonAsciiCharInByte if mode == Mode::Byte => { |
| 353 | + "non-ASCII character in byte literal" |
| 354 | + } |
| 355 | + EscapeError::NonAsciiCharInByte if mode == Mode::ByteStr => { |
| 356 | + "non-ASCII character in byte string literal" |
| 357 | + } |
| 358 | + EscapeError::NonAsciiCharInByte => "non-ASCII character in raw byte string literal", |
| 359 | + EscapeError::UnskippedWhitespaceWarning => "", |
| 360 | + EscapeError::MultipleSkippedLinesWarning => "", |
| 361 | + } |
| 362 | +} |
0 commit comments