aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_ssr/src/matching.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_ssr/src/matching.rs')
-rw-r--r--crates/ra_ssr/src/matching.rs42
1 files changed, 9 insertions, 33 deletions
diff --git a/crates/ra_ssr/src/matching.rs b/crates/ra_ssr/src/matching.rs
index 50b29eab2..842f4b6f3 100644
--- a/crates/ra_ssr/src/matching.rs
+++ b/crates/ra_ssr/src/matching.rs
@@ -2,8 +2,8 @@
2//! process of matching, placeholder values are recorded. 2//! process of matching, placeholder values are recorded.
3 3
4use crate::{ 4use crate::{
5 parsing::{Constraint, NodeKind, Placeholder, SsrTemplate}, 5 parsing::{Constraint, NodeKind, ParsedRule, Placeholder, SsrTemplate},
6 SsrMatches, SsrPattern, SsrRule, 6 SsrMatches,
7}; 7};
8use hir::Semantics; 8use hir::Semantics;
9use ra_db::FileRange; 9use ra_db::FileRange;
@@ -50,7 +50,7 @@ pub struct Match {
50 pub(crate) ignored_comments: Vec<ast::Comment>, 50 pub(crate) ignored_comments: Vec<ast::Comment>,
51 // A copy of the template for the rule that produced this match. We store this on the match for 51 // A copy of the template for the rule that produced this match. We store this on the match for
52 // if/when we do replacement. 52 // if/when we do replacement.
53 pub(crate) template: SsrTemplate, 53 pub(crate) template: Option<SsrTemplate>,
54} 54}
55 55
56/// Represents a `$var` in an SSR query. 56/// Represents a `$var` in an SSR query.
@@ -86,7 +86,7 @@ pub(crate) struct MatchFailed {
86/// parent module, we don't populate nested matches. 86/// parent module, we don't populate nested matches.
87pub(crate) fn get_match( 87pub(crate) fn get_match(
88 debug_active: bool, 88 debug_active: bool,
89 rule: &SsrRule, 89 rule: &ParsedRule,
90 code: &SyntaxNode, 90 code: &SyntaxNode,
91 restrict_range: &Option<FileRange>, 91 restrict_range: &Option<FileRange>,
92 sema: &Semantics<ra_ide_db::RootDatabase>, 92 sema: &Semantics<ra_ide_db::RootDatabase>,
@@ -102,7 +102,7 @@ struct Matcher<'db, 'sema> {
102 /// If any placeholders come from anywhere outside of this range, then the match will be 102 /// If any placeholders come from anywhere outside of this range, then the match will be
103 /// rejected. 103 /// rejected.
104 restrict_range: Option<FileRange>, 104 restrict_range: Option<FileRange>,
105 rule: &'sema SsrRule, 105 rule: &'sema ParsedRule,
106} 106}
107 107
108/// Which phase of matching we're currently performing. We do two phases because most attempted 108/// Which phase of matching we're currently performing. We do two phases because most attempted
@@ -117,15 +117,14 @@ enum Phase<'a> {
117 117
118impl<'db, 'sema> Matcher<'db, 'sema> { 118impl<'db, 'sema> Matcher<'db, 'sema> {
119 fn try_match( 119 fn try_match(
120 rule: &'sema SsrRule, 120 rule: &ParsedRule,
121 code: &SyntaxNode, 121 code: &SyntaxNode,
122 restrict_range: &Option<FileRange>, 122 restrict_range: &Option<FileRange>,
123 sema: &'sema Semantics<'db, ra_ide_db::RootDatabase>, 123 sema: &'sema Semantics<'db, ra_ide_db::RootDatabase>,
124 ) -> Result<Match, MatchFailed> { 124 ) -> Result<Match, MatchFailed> {
125 let match_state = Matcher { sema, restrict_range: restrict_range.clone(), rule }; 125 let match_state = Matcher { sema, restrict_range: restrict_range.clone(), rule };
126 let pattern_tree = rule.pattern.tree_for_kind(code.kind())?;
127 // First pass at matching, where we check that node types and idents match. 126 // First pass at matching, where we check that node types and idents match.
128 match_state.attempt_match_node(&mut Phase::First, &pattern_tree, code)?; 127 match_state.attempt_match_node(&mut Phase::First, &rule.pattern, code)?;
129 match_state.validate_range(&sema.original_range(code))?; 128 match_state.validate_range(&sema.original_range(code))?;
130 let mut the_match = Match { 129 let mut the_match = Match {
131 range: sema.original_range(code), 130 range: sema.original_range(code),
@@ -136,7 +135,7 @@ impl<'db, 'sema> Matcher<'db, 'sema> {
136 }; 135 };
137 // Second matching pass, where we record placeholder matches, ignored comments and maybe do 136 // Second matching pass, where we record placeholder matches, ignored comments and maybe do
138 // any other more expensive checks that we didn't want to do on the first pass. 137 // any other more expensive checks that we didn't want to do on the first pass.
139 match_state.attempt_match_node(&mut Phase::Second(&mut the_match), &pattern_tree, code)?; 138 match_state.attempt_match_node(&mut Phase::Second(&mut the_match), &rule.pattern, code)?;
140 Ok(the_match) 139 Ok(the_match)
141 } 140 }
142 141
@@ -444,8 +443,7 @@ impl<'db, 'sema> Matcher<'db, 'sema> {
444 } 443 }
445 444
446 fn get_placeholder(&self, element: &SyntaxElement) -> Option<&Placeholder> { 445 fn get_placeholder(&self, element: &SyntaxElement) -> Option<&Placeholder> {
447 only_ident(element.clone()) 446 only_ident(element.clone()).and_then(|ident| self.rule.get_placeholder(&ident))
448 .and_then(|ident| self.rule.pattern.placeholders_by_stand_in.get(ident.text()))
449 } 447 }
450} 448}
451 449
@@ -510,28 +508,6 @@ impl PlaceholderMatch {
510 } 508 }
511} 509}
512 510
513impl SsrPattern {
514 pub(crate) fn tree_for_kind(&self, kind: SyntaxKind) -> Result<&SyntaxNode, MatchFailed> {
515 let (tree, kind_name) = if ast::Expr::can_cast(kind) {
516 (&self.expr, "expression")
517 } else if ast::TypeRef::can_cast(kind) {
518 (&self.type_ref, "type reference")
519 } else if ast::ModuleItem::can_cast(kind) {
520 (&self.item, "item")
521 } else if ast::Path::can_cast(kind) {
522 (&self.path, "path")
523 } else if ast::Pat::can_cast(kind) {
524 (&self.pattern, "pattern")
525 } else {
526 fail_match!("Matching nodes of kind {:?} is not supported", kind);
527 };
528 match tree {
529 Some(tree) => Ok(tree),
530 None => fail_match!("Pattern cannot be parsed as a {}", kind_name),
531 }
532 }
533}
534
535impl NodeKind { 511impl NodeKind {
536 fn matches(&self, node: &SyntaxNode) -> Result<(), MatchFailed> { 512 fn matches(&self, node: &SyntaxNode) -> Result<(), MatchFailed> {
537 let ok = match self { 513 let ok = match self {