aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_syntax/src/validation.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_syntax/src/validation.rs')
-rw-r--r--crates/ra_syntax/src/validation.rs64
1 files changed, 54 insertions, 10 deletions
diff --git a/crates/ra_syntax/src/validation.rs b/crates/ra_syntax/src/validation.rs
index c2f545173..11a1fb4a7 100644
--- a/crates/ra_syntax/src/validation.rs
+++ b/crates/ra_syntax/src/validation.rs
@@ -1,17 +1,17 @@
1mod byte; 1mod unescape;
2mod byte_string; 2
3mod char;
4mod string;
5mod block; 3mod block;
6mod field_expr; 4mod field_expr;
7 5
8use crate::{ 6use crate::{
9 SourceFile, SyntaxError, AstNode, SyntaxNode, 7 SourceFile, SyntaxError, AstNode, SyntaxNode, TextUnit,
10 SyntaxKind::{L_CURLY, R_CURLY, BYTE, BYTE_STRING, STRING, CHAR}, 8 SyntaxKind::{L_CURLY, R_CURLY, BYTE, BYTE_STRING, STRING, CHAR},
11 ast, 9 ast,
12 algo::visit::{visitor_ctx, VisitorCtx}, 10 algo::visit::{visitor_ctx, VisitorCtx},
13}; 11};
14 12
13pub(crate) use unescape::EscapeError;
14
15pub(crate) fn validate(file: &SourceFile) -> Vec<SyntaxError> { 15pub(crate) fn validate(file: &SourceFile) -> Vec<SyntaxError> {
16 let mut errors = Vec::new(); 16 let mut errors = Vec::new();
17 for node in file.syntax().descendants() { 17 for node in file.syntax().descendants() {
@@ -26,11 +26,55 @@ pub(crate) fn validate(file: &SourceFile) -> Vec<SyntaxError> {
26 26
27// FIXME: kill duplication 27// FIXME: kill duplication
28fn validate_literal(literal: &ast::Literal, acc: &mut Vec<SyntaxError>) { 28fn validate_literal(literal: &ast::Literal, acc: &mut Vec<SyntaxError>) {
29 match literal.token().kind() { 29 let token = literal.token();
30 BYTE => byte::validate_byte_node(literal.token(), acc), 30 let text = token.text().as_str();
31 BYTE_STRING => byte_string::validate_byte_string_node(literal.token(), acc), 31 match token.kind() {
32 STRING => string::validate_string_node(literal.token(), acc), 32 BYTE => {
33 CHAR => char::validate_char_node(literal.token(), acc), 33 if let Some(end) = text.rfind('\'') {
34 if let Some(without_quotes) = text.get(2..end) {
35 if let Err((off, err)) = unescape::unescape_byte(without_quotes) {
36 let off = token.range().start() + TextUnit::from_usize(off + 2);
37 acc.push(SyntaxError::new(err.into(), off))
38 }
39 }
40 }
41 }
42 CHAR => {
43 if let Some(end) = text.rfind('\'') {
44 if let Some(without_quotes) = text.get(1..end) {
45 if let Err((off, err)) = unescape::unescape_char(without_quotes) {
46 let off = token.range().start() + TextUnit::from_usize(off + 1);
47 acc.push(SyntaxError::new(err.into(), off))
48 }
49 }
50 }
51 }
52 BYTE_STRING => {
53 if let Some(end) = text.rfind('\"') {
54 if let Some(without_quotes) = text.get(2..end) {
55 unescape::unescape_byte_str(without_quotes, &mut |range, char| {
56 if let Err(err) = char {
57 let off = range.start;
58 let off = token.range().start() + TextUnit::from_usize(off + 2);
59 acc.push(SyntaxError::new(err.into(), off))
60 }
61 })
62 }
63 }
64 }
65 STRING => {
66 if let Some(end) = text.rfind('\"') {
67 if let Some(without_quotes) = text.get(1..end) {
68 unescape::unescape_str(without_quotes, &mut |range, char| {
69 if let Err(err) = char {
70 let off = range.start;
71 let off = token.range().start() + TextUnit::from_usize(off + 1);
72 acc.push(SyntaxError::new(err.into(), off))
73 }
74 })
75 }
76 }
77 }
34 _ => (), 78 _ => (),
35 } 79 }
36} 80}