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.rs83
1 files changed, 76 insertions, 7 deletions
diff --git a/crates/ra_syntax/src/validation.rs b/crates/ra_syntax/src/validation.rs
index 009f5052f..a550ce0ab 100644
--- a/crates/ra_syntax/src/validation.rs
+++ b/crates/ra_syntax/src/validation.rs
@@ -1,3 +1,5 @@
1use std::u32;
2
1use crate::{ 3use crate::{
2 algo::visit::{visitor_ctx, VisitorCtx}, 4 algo::visit::{visitor_ctx, VisitorCtx},
3 ast::{self, AstNode}, 5 ast::{self, AstNode},
@@ -42,15 +44,82 @@ fn validate_char(node: ast::Char, errors: &mut Vec<SyntaxError>) {
42 } 44 }
43 } 45 }
44 AsciiCodeEscape => { 46 AsciiCodeEscape => {
45 // TODO: 47 // An AsciiCodeEscape has 4 chars, example: `\xDD`
46 // * First digit is octal 48 if text.len() < 4 {
47 // * Second digit is hex 49 errors.push(SyntaxError::new(TooShortAsciiCodeEscape, range));
50 } else {
51 assert!(text.chars().count() == 4, "AsciiCodeEscape cannot be longer than 4 chars");
52
53 match u8::from_str_radix(&text[2..], 16) {
54 Ok(code) if code < 128 => { /* Escape code is valid */ },
55 Ok(_) => errors.push(SyntaxError::new(AsciiCodeEscapeOutOfRange, range)),
56 Err(_) => errors.push(SyntaxError::new(MalformedAsciiCodeEscape, range)),
57 }
58
59 }
48 } 60 }
49 UnicodeEscape => { 61 UnicodeEscape => {
50 // TODO: 62 assert!(&text[..2] == "\\u", "UnicodeEscape always starts with \\u");
51 // * Only hex digits or underscores allowed 63
52 // * Max 6 chars 64 if text.len() == 2 {
53 // * Within allowed range (must be at most 10FFFF) 65 // No starting `{`
66 errors.push(SyntaxError::new(MalformedUnicodeEscape, range));
67 return;
68 }
69
70 if text.len() == 3 {
71 // Only starting `{`
72 errors.push(SyntaxError::new(UnclosedUnicodeEscape, range));
73 return;
74 }
75
76 let mut code = String::new();
77 let mut closed = false;
78 for c in text[3..].chars() {
79 assert!(!closed, "no characters after escape is closed");
80
81 if c.is_digit(16) {
82 code.push(c);
83 } else if c == '_' {
84 // Reject leading _
85 if code.len() == 0 {
86 errors.push(SyntaxError::new(MalformedUnicodeEscape, range));
87 return;
88 }
89 } else if c == '}' {
90 closed = true;
91 } else {
92 errors.push(SyntaxError::new(MalformedUnicodeEscape, range));
93 return;
94 }
95 }
96
97 if !closed {
98 errors.push(SyntaxError::new(UnclosedUnicodeEscape, range))
99 }
100
101 if code.len() == 0 {
102 errors.push(SyntaxError::new(EmptyUnicodeEcape, range));
103 return;
104 }
105
106 if code.len() > 6 {
107 errors.push(SyntaxError::new(OverlongUnicodeEscape, range));
108 }
109
110 match u32::from_str_radix(&code, 16) {
111 Ok(code_u32) if code_u32 > 0x10FFFF => {
112 errors.push(SyntaxError::new(UnicodeEscapeOutOfRange, range));
113 }
114 Ok(_) => {
115 // Valid escape code
116 }
117 Err(_) => {
118 errors.push(SyntaxError::new(MalformedUnicodeEscape, range));
119 }
120 }
121
122 // FIXME: we really need tests for this
54 } 123 }
55 // Code points are always valid 124 // Code points are always valid
56 CodePoint => (), 125 CodePoint => (),