diff options
Diffstat (limited to 'crates/ra_ssr/src/matching.rs')
-rw-r--r-- | crates/ra_ssr/src/matching.rs | 42 |
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 | ||
4 | use crate::{ | 4 | use crate::{ |
5 | parsing::{Constraint, NodeKind, Placeholder, SsrTemplate}, | 5 | parsing::{Constraint, NodeKind, ParsedRule, Placeholder, SsrTemplate}, |
6 | SsrMatches, SsrPattern, SsrRule, | 6 | SsrMatches, |
7 | }; | 7 | }; |
8 | use hir::Semantics; | 8 | use hir::Semantics; |
9 | use ra_db::FileRange; | 9 | use 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. |
87 | pub(crate) fn get_match( | 87 | pub(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 | ||
118 | impl<'db, 'sema> Matcher<'db, 'sema> { | 118 | impl<'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 | ||
513 | impl 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 | |||
535 | impl NodeKind { | 511 | impl 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 { |