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.rs78
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 @@
1use 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
12pub(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
22fn 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
73fn is_ascii_escape(code: char) -> bool {
74 match code {
75 '\'' | '"' | 'n' | 'r' | 't' | '0' => true,
76 _ => false,
77 }
78}