aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_ssr/src/matching.rs
diff options
context:
space:
mode:
authorDavid Lattimore <[email protected]>2020-06-23 10:07:42 +0100
committerDavid Lattimore <[email protected]>2020-07-01 09:44:11 +0100
commit3d9997889bfe536a96e70535ab208a6e7ff3bc12 (patch)
tree6f280e6af08979d7a5c17d45a15b94a54798dba3 /crates/ra_ssr/src/matching.rs
parentd34fd372bbcce4600fe7dd1ca61b9b213a7f5ced (diff)
SSR: Add initial support for placeholder constraints
Diffstat (limited to 'crates/ra_ssr/src/matching.rs')
-rw-r--r--crates/ra_ssr/src/matching.rs39
1 files changed, 38 insertions, 1 deletions
diff --git a/crates/ra_ssr/src/matching.rs b/crates/ra_ssr/src/matching.rs
index 53d802e77..ce53d46d2 100644
--- a/crates/ra_ssr/src/matching.rs
+++ b/crates/ra_ssr/src/matching.rs
@@ -2,7 +2,7 @@
2//! process of matching, placeholder values are recorded. 2//! process of matching, placeholder values are recorded.
3 3
4use crate::{ 4use crate::{
5 parsing::{Placeholder, SsrTemplate}, 5 parsing::{Constraint, NodeKind, Placeholder, SsrTemplate},
6 SsrMatches, SsrPattern, SsrRule, 6 SsrMatches, SsrPattern, SsrRule,
7}; 7};
8use hir::Semantics; 8use hir::Semantics;
@@ -11,6 +11,7 @@ use ra_syntax::ast::{AstNode, AstToken};
11use ra_syntax::{ast, SyntaxElement, SyntaxElementChildren, SyntaxKind, SyntaxNode, SyntaxToken}; 11use ra_syntax::{ast, SyntaxElement, SyntaxElementChildren, SyntaxKind, SyntaxNode, SyntaxToken};
12use rustc_hash::FxHashMap; 12use rustc_hash::FxHashMap;
13use std::{cell::Cell, iter::Peekable}; 13use std::{cell::Cell, iter::Peekable};
14use test_utils::mark;
14 15
15// Creates a match error. If we're currently attempting to match some code that we thought we were 16// Creates a match error. If we're currently attempting to match some code that we thought we were
16// going to match, as indicated by the --debug-snippet flag, then populate the reason field. 17// going to match, as indicated by the --debug-snippet flag, then populate the reason field.
@@ -169,6 +170,9 @@ impl<'db, 'sema> MatchState<'db, 'sema> {
169 if let Some(placeholder) = 170 if let Some(placeholder) =
170 match_inputs.get_placeholder(&SyntaxElement::Node(pattern.clone())) 171 match_inputs.get_placeholder(&SyntaxElement::Node(pattern.clone()))
171 { 172 {
173 for constraint in &placeholder.constraints {
174 self.check_constraint(constraint, code)?;
175 }
172 if self.match_out.is_none() { 176 if self.match_out.is_none() {
173 return Ok(()); 177 return Ok(());
174 } 178 }
@@ -292,6 +296,24 @@ impl<'db, 'sema> MatchState<'db, 'sema> {
292 Ok(()) 296 Ok(())
293 } 297 }
294 298
299 fn check_constraint(
300 &self,
301 constraint: &Constraint,
302 code: &SyntaxNode,
303 ) -> Result<(), MatchFailed> {
304 match constraint {
305 Constraint::Kind(kind) => {
306 kind.matches(code)?;
307 }
308 Constraint::Not(sub) => {
309 if self.check_constraint(&*sub, code).is_ok() {
310 fail_match!("Constraint {:?} failed for '{}'", constraint, code.text());
311 }
312 }
313 }
314 Ok(())
315 }
316
295 /// We want to allow the records to match in any order, so we have special matching logic for 317 /// We want to allow the records to match in any order, so we have special matching logic for
296 /// them. 318 /// them.
297 fn attempt_match_record_field_list( 319 fn attempt_match_record_field_list(
@@ -515,6 +537,21 @@ impl SsrPattern {
515 } 537 }
516} 538}
517 539
540impl NodeKind {
541 fn matches(&self, node: &SyntaxNode) -> Result<(), MatchFailed> {
542 let ok = match self {
543 Self::Literal => {
544 mark::hit!(literal_constraint);
545 ast::Literal::can_cast(node.kind())
546 }
547 };
548 if !ok {
549 fail_match!("Code '{}' isn't of kind {:?}", node.text(), self);
550 }
551 Ok(())
552 }
553}
554
518// If `node` contains nothing but an ident then return it, otherwise return None. 555// If `node` contains nothing but an ident then return it, otherwise return None.
519fn only_ident(element: SyntaxElement) -> Option<SyntaxToken> { 556fn only_ident(element: SyntaxElement) -> Option<SyntaxToken> {
520 match element { 557 match element {