aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_syntax
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_syntax')
-rw-r--r--crates/ra_syntax/src/lib.rs12
-rw-r--r--crates/ra_syntax/src/validation.rs18
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]
325macro_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;
5use rustc_lexer::unescape; 5use rustc_lexer::unescape;
6 6
7use crate::{ 7use 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 {
97pub(crate) fn validate(root: &SyntaxNode) -> Vec<SyntaxError> { 96pub(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}