aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_ssr/src/matching.rs
diff options
context:
space:
mode:
authorDavid Lattimore <[email protected]>2020-07-03 03:57:17 +0100
committerDavid Lattimore <[email protected]>2020-07-24 12:34:00 +0100
commit1fce8b6ba32bebba36d588d07781e9e578845728 (patch)
treec027096421e49a7e0279711e0ccd7491ca3d6a9a /crates/ra_ssr/src/matching.rs
parent2b53639e381b1f17c829fb33f6e4135a9c930f41 (diff)
SSR: Change the way rules are stored internally.
Previously we had: - Multiple rules - Each rule had its pattern parsed as an expression, path etc This meant that there were two levels at which there could be multiple rules. Now we just have multiple rules. If a pattern can parse as more than one kind of thing, then they get stored as multiple separate rules. We also now don't have separate fields for the different kinds of things that a pattern can parse as. This makes adding new kinds of things simpler. Previously, add_search_pattern would construct a rule with a dummy replacement. Now the replacement is an Option. This is slightly cleaner and also opens the way for parsing the replacement template as the same kind of thing as the search pattern.
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 {