diff options
Diffstat (limited to 'crates/ra_syntax/src/validation.rs')
-rw-r--r-- | crates/ra_syntax/src/validation.rs | 78 |
1 files changed, 0 insertions, 78 deletions
diff --git a/crates/ra_syntax/src/validation.rs b/crates/ra_syntax/src/validation.rs deleted file mode 100644 index 009f5052f..000000000 --- a/crates/ra_syntax/src/validation.rs +++ /dev/null | |||
@@ -1,78 +0,0 @@ | |||
1 | use crate::{ | ||
2 | algo::visit::{visitor_ctx, VisitorCtx}, | ||
3 | ast::{self, AstNode}, | ||
4 | File, | ||
5 | string_lexing::{self, CharComponentKind}, | ||
6 | yellow::{ | ||
7 | SyntaxError, | ||
8 | SyntaxErrorKind::*, | ||
9 | }, | ||
10 | }; | ||
11 | |||
12 | pub(crate) fn validate(file: &File) -> Vec<SyntaxError> { | ||
13 | let mut errors = Vec::new(); | ||
14 | for node in file.root.borrowed().descendants() { | ||
15 | let _ = visitor_ctx(&mut errors) | ||
16 | .visit::<ast::Char, _>(validate_char) | ||
17 | .accept(node); | ||
18 | } | ||
19 | errors | ||
20 | } | ||
21 | |||
22 | fn validate_char(node: ast::Char, errors: &mut Vec<SyntaxError>) { | ||
23 | let mut components = string_lexing::parse_char_literal(node.text()); | ||
24 | let mut len = 0; | ||
25 | for component in &mut components { | ||
26 | len += 1; | ||
27 | |||
28 | // Validate escapes | ||
29 | let text = &node.text()[component.range]; | ||
30 | let range = component.range + node.syntax().range().start(); | ||
31 | use self::CharComponentKind::*; | ||
32 | match component.kind { | ||
33 | AsciiEscape => { | ||
34 | if text.len() == 1 { | ||
35 | // Escape sequence consists only of leading `\` | ||
36 | errors.push(SyntaxError::new(EmptyAsciiEscape, range)); | ||
37 | } else { | ||
38 | let escape_code = text.chars().skip(1).next().unwrap(); | ||
39 | if !is_ascii_escape(escape_code) { | ||
40 | errors.push(SyntaxError::new(InvalidAsciiEscape, range)); | ||
41 | } | ||
42 | } | ||
43 | } | ||
44 | AsciiCodeEscape => { | ||
45 | // TODO: | ||
46 | // * First digit is octal | ||
47 | // * Second digit is hex | ||
48 | } | ||
49 | UnicodeEscape => { | ||
50 | // TODO: | ||
51 | // * Only hex digits or underscores allowed | ||
52 | // * Max 6 chars | ||
53 | // * Within allowed range (must be at most 10FFFF) | ||
54 | } | ||
55 | // Code points are always valid | ||
56 | CodePoint => (), | ||
57 | } | ||
58 | } | ||
59 | |||
60 | if !components.has_closing_quote { | ||
61 | errors.push(SyntaxError::new(UnclosedChar, node.syntax().range())); | ||
62 | } | ||
63 | |||
64 | if len == 0 { | ||
65 | errors.push(SyntaxError::new(EmptyChar, node.syntax().range())); | ||
66 | } | ||
67 | |||
68 | if len > 1 { | ||
69 | errors.push(SyntaxError::new(LongChar, node.syntax().range())); | ||
70 | } | ||
71 | } | ||
72 | |||
73 | fn is_ascii_escape(code: char) -> bool { | ||
74 | match code { | ||
75 | '\'' | '"' | 'n' | 'r' | 't' | '0' => true, | ||
76 | _ => false, | ||
77 | } | ||
78 | } | ||