Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/syntax/src/validation.rs')
| -rw-r--r-- | crates/syntax/src/validation.rs | 56 |
1 files changed, 41 insertions, 15 deletions
diff --git a/crates/syntax/src/validation.rs b/crates/syntax/src/validation.rs index fb2381110b..e0ec6a242f 100644 --- a/crates/syntax/src/validation.rs +++ b/crates/syntax/src/validation.rs @@ -5,11 +5,11 @@ mod block; use rowan::Direction; -use rustc_lexer::unescape::{self, unescape_byte, unescape_char, unescape_literal, Mode}; +use rustc_lexer::unescape::{self, unescape_literal, Mode}; use crate::{ algo, - ast::{self, HasAttrs, HasVisibility}, + ast::{self, HasAttrs, HasVisibility, IsString}, match_ast, AstNode, SyntaxError, SyntaxKind::{CONST, FN, INT_NUMBER, TYPE_ALIAS}, SyntaxNode, SyntaxToken, TextSize, T, @@ -44,7 +44,7 @@ pub(crate) fn validate(root: &SyntaxNode) -> Vec<SyntaxError> { errors } -fn rustc_unescape_error_to_string(err: unescape::EscapeError) -> &'static str { +fn rustc_unescape_error_to_string(err: unescape::EscapeError) -> (&'static str, bool) { use unescape::EscapeError as EE; #[rustfmt::skip] @@ -103,12 +103,15 @@ fn rustc_unescape_error_to_string(err: unescape::EscapeError) -> &'static str { EE::UnicodeEscapeInByte => { "Byte literals must not contain unicode escapes" } - EE::NonAsciiCharInByte | EE::NonAsciiCharInByteString => { + EE::NonAsciiCharInByte => { "Byte literals must not contain non-ASCII characters" } + EE::UnskippedWhitespaceWarning => "Whitespace after this escape is not skipped", + EE::MultipleSkippedLinesWarning => "Multiple lines are skipped by this escape", + }; - err_message + (err_message, err.is_fatal()) } fn validate_literal(literal: ast::Literal, acc: &mut Vec<SyntaxError>) { @@ -121,9 +124,13 @@ fn validate_literal(literal: ast::Literal, acc: &mut Vec<SyntaxError>) { let text = token.text(); // FIXME: lift this lambda refactor to `fn` (https://github.com/rust-lang/rust-analyzer/pull/2834#discussion_r366199205) - let mut push_err = |prefix_len, (off, err): (usize, unescape::EscapeError)| { + let mut push_err = |prefix_len, off, err: unescape::EscapeError| { let off = token.text_range().start() + TextSize::try_from(off + prefix_len).unwrap(); - acc.push(SyntaxError::new_at_offset(rustc_unescape_error_to_string(err), off)); + let (message, is_err) = rustc_unescape_error_to_string(err); + // FIXME: Emit lexer warnings + if is_err { + acc.push(SyntaxError::new_at_offset(message, off)); + } }; match literal.kind() { @@ -132,7 +139,7 @@ fn validate_literal(literal: ast::Literal, acc: &mut Vec<SyntaxError>) { if let Some(without_quotes) = unquote(text, 1, '"') { unescape_literal(without_quotes, Mode::Str, &mut |range, char| { if let Err(err) = char { - push_err(1, (range.start, err)); + push_err(1, range.start, err); } }); } @@ -143,20 +150,39 @@ fn validate_literal(literal: ast::Literal, acc: &mut Vec<SyntaxError>) { if let Some(without_quotes) = unquote(text, 2, '"') { unescape_literal(without_quotes, Mode::ByteStr, &mut |range, char| { if let Err(err) = char { - push_err(2, (range.start, err)); + push_err(1, range.start, err); + } + }); + } + } + } + ast::LiteralKind::CString(s) => { + if !s.is_raw() { + if let Some(without_quotes) = unquote(text, 2, '"') { + unescape_literal(without_quotes, Mode::ByteStr, &mut |range, char| { + if let Err(err) = char { + push_err(1, range.start, err); } }); } } } ast::LiteralKind::Char(_) => { - if let Some(Err(e)) = unquote(text, 1, '\'').map(unescape_char) { - push_err(1, e); + if let Some(without_quotes) = unquote(text, 1, '\'') { + unescape_literal(without_quotes, Mode::Char, &mut |range, char| { + if let Err(err) = char { + push_err(1, range.start, err); + } + }); } } ast::LiteralKind::Byte(_) => { - if let Some(Err(e)) = unquote(text, 2, '\'').map(unescape_byte) { - push_err(2, e); + if let Some(without_quotes) = unquote(text, 2, '\'') { + unescape_literal(without_quotes, Mode::Byte, &mut |range, char| { + if let Err(err) = char { + push_err(2, range.start, err); + } + }); } } ast::LiteralKind::IntNumber(_) @@ -175,14 +201,14 @@ pub(crate) fn validate_block_structure(root: &SyntaxNode) { assert_eq!( node.parent(), pair.parent(), - "\nunpaired curlys:\n{}\n{:#?}\n", + "\nunpaired curlies:\n{}\n{:#?}\n", root.text(), root, ); assert!( node.next_sibling_or_token().is_none() && pair.prev_sibling_or_token().is_none(), - "\nfloating curlys at {:?}\nfile:\n{}\nerror:\n{}\n", + "\nfloating curlies at {:?}\nfile:\n{}\nerror:\n{}\n", node, root.text(), node, |