diff options
Diffstat (limited to 'crates/ra_syntax')
-rw-r--r-- | crates/ra_syntax/src/lib.rs | 12 | ||||
-rw-r--r-- | crates/ra_syntax/src/validation.rs | 18 |
2 files changed, 22 insertions, 8 deletions
diff --git a/crates/ra_syntax/src/lib.rs b/crates/ra_syntax/src/lib.rs index edb6076bb..09230ccb2 100644 --- a/crates/ra_syntax/src/lib.rs +++ b/crates/ra_syntax/src/lib.rs | |||
@@ -295,6 +295,7 @@ fn api_walkthrough() { | |||
295 | // 1. explicitly call getter methods on AST nodes. | 295 | // 1. explicitly call getter methods on AST nodes. |
296 | // 2. use descendants and `AstNode::cast`. | 296 | // 2. use descendants and `AstNode::cast`. |
297 | // 3. use descendants and the visitor. | 297 | // 3. use descendants and the visitor. |
298 | // 4. use descendants and `match_ast!`. | ||
298 | // | 299 | // |
299 | // Here's how the first one looks like: | 300 | // Here's how the first one looks like: |
300 | let exprs_cast: Vec<String> = file | 301 | let exprs_cast: Vec<String> = file |
@@ -319,3 +320,14 @@ fn api_walkthrough() { | |||
319 | } | 320 | } |
320 | assert_eq!(exprs_cast, exprs_visit); | 321 | assert_eq!(exprs_cast, exprs_visit); |
321 | } | 322 | } |
323 | |||
324 | #[macro_export] | ||
325 | macro_rules! match_ast { | ||
326 | (match $node:ident { | ||
327 | $( ast::$ast:ident($it:ident) => $res:block, )* | ||
328 | _ => $catch_all:expr, | ||
329 | }) => {{ | ||
330 | $( if let Some($it) = ast::$ast::cast($node.clone()) $res else )* | ||
331 | { $catch_all } | ||
332 | }}; | ||
333 | } | ||
diff --git a/crates/ra_syntax/src/validation.rs b/crates/ra_syntax/src/validation.rs index 4f8935b2c..ab4f15908 100644 --- a/crates/ra_syntax/src/validation.rs +++ b/crates/ra_syntax/src/validation.rs | |||
@@ -5,8 +5,7 @@ mod block; | |||
5 | use rustc_lexer::unescape; | 5 | use rustc_lexer::unescape; |
6 | 6 | ||
7 | use crate::{ | 7 | use crate::{ |
8 | algo::visit::{visitor_ctx, VisitorCtx}, | 8 | ast, match_ast, AstNode, SyntaxError, SyntaxErrorKind, |
9 | ast, AstNode, SyntaxError, SyntaxErrorKind, | ||
10 | SyntaxKind::{BYTE, BYTE_STRING, CHAR, INT_NUMBER, STRING}, | 9 | SyntaxKind::{BYTE, BYTE_STRING, CHAR, INT_NUMBER, STRING}, |
11 | SyntaxNode, SyntaxToken, TextUnit, T, | 10 | SyntaxNode, SyntaxToken, TextUnit, T, |
12 | }; | 11 | }; |
@@ -97,12 +96,15 @@ impl From<rustc_lexer::unescape::EscapeError> for SyntaxErrorKind { | |||
97 | pub(crate) fn validate(root: &SyntaxNode) -> Vec<SyntaxError> { | 96 | pub(crate) fn validate(root: &SyntaxNode) -> Vec<SyntaxError> { |
98 | let mut errors = Vec::new(); | 97 | let mut errors = Vec::new(); |
99 | for node in root.descendants() { | 98 | for node in root.descendants() { |
100 | let _ = visitor_ctx(&mut errors) | 99 | match_ast! { |
101 | .visit::<ast::Literal, _>(validate_literal) | 100 | match node { |
102 | .visit::<ast::BlockExpr, _>(block::validate_block_expr) | 101 | ast::Literal(it) => { validate_literal(it, &mut errors) }, |
103 | .visit::<ast::FieldExpr, _>(|it, errors| validate_numeric_name(it.name_ref(), errors)) | 102 | ast::BlockExpr(it) => { block::validate_block_expr(it, &mut errors) }, |
104 | .visit::<ast::RecordField, _>(|it, errors| validate_numeric_name(it.name_ref(), errors)) | 103 | ast::FieldExpr(it) => { validate_numeric_name(it.name_ref(), &mut errors) }, |
105 | .accept(&node); | 104 | ast::RecordField(it) => { validate_numeric_name(it.name_ref(), &mut errors) }, |
105 | _ => (), | ||
106 | } | ||
107 | } | ||
106 | } | 108 | } |
107 | errors | 109 | errors |
108 | } | 110 | } |