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.rs61
1 files changed, 26 insertions, 35 deletions
diff --git a/crates/ra_syntax/src/validation.rs b/crates/ra_syntax/src/validation.rs
index 222ac15f8..445e3b3e4 100644
--- a/crates/ra_syntax/src/validation.rs
+++ b/crates/ra_syntax/src/validation.rs
@@ -111,55 +111,46 @@ pub(crate) fn validate(root: &SyntaxNode) -> Vec<SyntaxError> {
111 errors 111 errors
112} 112}
113 113
114// FIXME: kill duplication
115fn validate_literal(literal: ast::Literal, acc: &mut Vec<SyntaxError>) { 114fn validate_literal(literal: ast::Literal, acc: &mut Vec<SyntaxError>) {
115 fn unquote(text: &str, prefix_len: usize, end_delimiter: char) -> Option<&str> {
116 text.rfind(end_delimiter).and_then(|end| text.get(prefix_len..end))
117 }
118
116 let token = literal.token(); 119 let token = literal.token();
117 let text = token.text().as_str(); 120 let text = token.text().as_str();
121
122 let mut push_err = |prefix_len, (off, err): (usize, unescape::EscapeError)| {
123 let off = token.text_range().start() + TextUnit::from_usize(off + prefix_len);
124 acc.push(SyntaxError::new(err.into(), off));
125 };
126
118 match token.kind() { 127 match token.kind() {
119 BYTE => { 128 BYTE => {
120 if let Some(end) = text.rfind('\'') { 129 if let Some(Err(e)) = unquote(text, 2, '\'').map(unescape::unescape_byte) {
121 if let Some(without_quotes) = text.get(2..end) { 130 push_err(2, e);
122 if let Err((off, err)) = unescape::unescape_byte(without_quotes) {
123 let off = token.text_range().start() + TextUnit::from_usize(off + 2);
124 acc.push(SyntaxError::new(err.into(), off))
125 }
126 }
127 } 131 }
128 } 132 }
129 CHAR => { 133 CHAR => {
130 if let Some(end) = text.rfind('\'') { 134 if let Some(Err(e)) = unquote(text, 1, '\'').map(unescape::unescape_char) {
131 if let Some(without_quotes) = text.get(1..end) { 135 push_err(1, e);
132 if let Err((off, err)) = unescape::unescape_char(without_quotes) {
133 let off = token.text_range().start() + TextUnit::from_usize(off + 1);
134 acc.push(SyntaxError::new(err.into(), off))
135 }
136 }
137 } 136 }
138 } 137 }
139 BYTE_STRING => { 138 BYTE_STRING => {
140 if let Some(end) = text.rfind('\"') { 139 if let Some(without_quotes) = unquote(text, 2, '"') {
141 if let Some(without_quotes) = text.get(2..end) { 140 unescape::unescape_byte_str(without_quotes, &mut |range, char| {
142 unescape::unescape_byte_str(without_quotes, &mut |range, char| { 141 if let Err(err) = char {
143 if let Err(err) = char { 142 push_err(2, (range.start, err));
144 let off = range.start; 143 }
145 let off = token.text_range().start() + TextUnit::from_usize(off + 2); 144 })
146 acc.push(SyntaxError::new(err.into(), off))
147 }
148 })
149 }
150 } 145 }
151 } 146 }
152 STRING => { 147 STRING => {
153 if let Some(end) = text.rfind('\"') { 148 if let Some(without_quotes) = unquote(text, 1, '"') {
154 if let Some(without_quotes) = text.get(1..end) { 149 unescape::unescape_str(without_quotes, &mut |range, char| {
155 unescape::unescape_str(without_quotes, &mut |range, char| { 150 if let Err(err) = char {
156 if let Err(err) = char { 151 push_err(1, (range.start, err));
157 let off = range.start; 152 }
158 let off = token.text_range().start() + TextUnit::from_usize(off + 1); 153 })
159 acc.push(SyntaxError::new(err.into(), off))
160 }
161 })
162 }
163 } 154 }
164 } 155 }
165 _ => (), 156 _ => (),