diff options
author | David Lattimore <[email protected]> | 2020-08-06 02:30:52 +0100 |
---|---|---|
committer | David Lattimore <[email protected]> | 2020-08-14 11:12:26 +0100 |
commit | c84f98385a28eeb7595f38b7cfaf861a6e06f4ea (patch) | |
tree | 6f8c4a1770aeefde182e365e0d249ed12bc61fdd | |
parent | 674af600f105abe1dcb6c7654058e7df5a402429 (diff) |
Refactor SSR so that placeholders store a Var
This allows lookup of placeholder bindings given a placeholder without
needing to create a Var instance.
-rw-r--r-- | crates/ssr/src/matching.rs | 15 | ||||
-rw-r--r-- | crates/ssr/src/parsing.rs | 24 | ||||
-rw-r--r-- | crates/ssr/src/replacing.rs | 3 | ||||
-rw-r--r-- | crates/ssr/src/tests.rs | 2 |
4 files changed, 26 insertions, 18 deletions
diff --git a/crates/ssr/src/matching.rs b/crates/ssr/src/matching.rs index ffc7202ae..7f0b5061e 100644 --- a/crates/ssr/src/matching.rs +++ b/crates/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 | ||
4 | use crate::{ | 4 | use crate::{ |
5 | parsing::{Constraint, NodeKind, Placeholder}, | 5 | parsing::{Constraint, NodeKind, Placeholder, Var}, |
6 | resolving::{ResolvedPattern, ResolvedRule, UfcsCallInfo}, | 6 | resolving::{ResolvedPattern, ResolvedRule, UfcsCallInfo}, |
7 | SsrMatches, | 7 | SsrMatches, |
8 | }; | 8 | }; |
@@ -56,10 +56,6 @@ pub struct Match { | |||
56 | pub(crate) rendered_template_paths: FxHashMap<SyntaxNode, hir::ModPath>, | 56 | pub(crate) rendered_template_paths: FxHashMap<SyntaxNode, hir::ModPath>, |
57 | } | 57 | } |
58 | 58 | ||
59 | /// Represents a `$var` in an SSR query. | ||
60 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
61 | pub(crate) struct Var(pub String); | ||
62 | |||
63 | /// Information about a placeholder bound in a match. | 59 | /// Information about a placeholder bound in a match. |
64 | #[derive(Debug)] | 60 | #[derive(Debug)] |
65 | pub(crate) struct PlaceholderMatch { | 61 | pub(crate) struct PlaceholderMatch { |
@@ -182,10 +178,9 @@ impl<'db, 'sema> Matcher<'db, 'sema> { | |||
182 | // We validated the range for the node when we started the match, so the placeholder | 178 | // We validated the range for the node when we started the match, so the placeholder |
183 | // probably can't fail range validation, but just to be safe... | 179 | // probably can't fail range validation, but just to be safe... |
184 | self.validate_range(&original_range)?; | 180 | self.validate_range(&original_range)?; |
185 | matches_out.placeholder_values.insert( | 181 | matches_out |
186 | Var(placeholder.ident.to_string()), | 182 | .placeholder_values |
187 | PlaceholderMatch::new(code, original_range), | 183 | .insert(placeholder.ident.clone(), PlaceholderMatch::new(code, original_range)); |
188 | ); | ||
189 | } | 184 | } |
190 | return Ok(()); | 185 | return Ok(()); |
191 | } | 186 | } |
@@ -487,7 +482,7 @@ impl<'db, 'sema> Matcher<'db, 'sema> { | |||
487 | } | 482 | } |
488 | if let Phase::Second(match_out) = phase { | 483 | if let Phase::Second(match_out) = phase { |
489 | match_out.placeholder_values.insert( | 484 | match_out.placeholder_values.insert( |
490 | Var(placeholder.ident.to_string()), | 485 | placeholder.ident.clone(), |
491 | PlaceholderMatch::from_range(FileRange { | 486 | PlaceholderMatch::from_range(FileRange { |
492 | file_id: self.sema.original_range(code).file_id, | 487 | file_id: self.sema.original_range(code).file_id, |
493 | range: first_matched_token | 488 | range: first_matched_token |
diff --git a/crates/ssr/src/parsing.rs b/crates/ssr/src/parsing.rs index 9570e96e3..05b66dcd7 100644 --- a/crates/ssr/src/parsing.rs +++ b/crates/ssr/src/parsing.rs | |||
@@ -8,7 +8,7 @@ | |||
8 | use crate::errors::bail; | 8 | use crate::errors::bail; |
9 | use crate::{SsrError, SsrPattern, SsrRule}; | 9 | use crate::{SsrError, SsrPattern, SsrRule}; |
10 | use rustc_hash::{FxHashMap, FxHashSet}; | 10 | use rustc_hash::{FxHashMap, FxHashSet}; |
11 | use std::str::FromStr; | 11 | use std::{fmt::Display, str::FromStr}; |
12 | use syntax::{ast, AstNode, SmolStr, SyntaxKind, SyntaxNode, T}; | 12 | use syntax::{ast, AstNode, SmolStr, SyntaxKind, SyntaxNode, T}; |
13 | use test_utils::mark; | 13 | use test_utils::mark; |
14 | 14 | ||
@@ -34,12 +34,16 @@ pub(crate) enum PatternElement { | |||
34 | #[derive(Clone, Debug, PartialEq, Eq)] | 34 | #[derive(Clone, Debug, PartialEq, Eq)] |
35 | pub(crate) struct Placeholder { | 35 | pub(crate) struct Placeholder { |
36 | /// The name of this placeholder. e.g. for "$a", this would be "a" | 36 | /// The name of this placeholder. e.g. for "$a", this would be "a" |
37 | pub(crate) ident: SmolStr, | 37 | pub(crate) ident: Var, |
38 | /// A unique name used in place of this placeholder when we parse the pattern as Rust code. | 38 | /// A unique name used in place of this placeholder when we parse the pattern as Rust code. |
39 | stand_in_name: String, | 39 | stand_in_name: String, |
40 | pub(crate) constraints: Vec<Constraint>, | 40 | pub(crate) constraints: Vec<Constraint>, |
41 | } | 41 | } |
42 | 42 | ||
43 | /// Represents a `$var` in an SSR query. | ||
44 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
45 | pub(crate) struct Var(pub String); | ||
46 | |||
43 | #[derive(Clone, Debug, PartialEq, Eq)] | 47 | #[derive(Clone, Debug, PartialEq, Eq)] |
44 | pub(crate) enum Constraint { | 48 | pub(crate) enum Constraint { |
45 | Kind(NodeKind), | 49 | Kind(NodeKind), |
@@ -205,7 +209,7 @@ fn parse_pattern(pattern_str: &str) -> Result<Vec<PatternElement>, SsrError> { | |||
205 | if token.kind == T![$] { | 209 | if token.kind == T![$] { |
206 | let placeholder = parse_placeholder(&mut tokens)?; | 210 | let placeholder = parse_placeholder(&mut tokens)?; |
207 | if !placeholder_names.insert(placeholder.ident.clone()) { | 211 | if !placeholder_names.insert(placeholder.ident.clone()) { |
208 | bail!("Name `{}` repeats more than once", placeholder.ident); | 212 | bail!("Placeholder `{}` repeats more than once", placeholder.ident); |
209 | } | 213 | } |
210 | res.push(PatternElement::Placeholder(placeholder)); | 214 | res.push(PatternElement::Placeholder(placeholder)); |
211 | } else { | 215 | } else { |
@@ -228,7 +232,7 @@ fn validate_rule(rule: &SsrRule) -> Result<(), SsrError> { | |||
228 | for p in &rule.template.tokens { | 232 | for p in &rule.template.tokens { |
229 | if let PatternElement::Placeholder(placeholder) = p { | 233 | if let PatternElement::Placeholder(placeholder) = p { |
230 | if !defined_placeholders.contains(&placeholder.ident) { | 234 | if !defined_placeholders.contains(&placeholder.ident) { |
231 | undefined.push(format!("${}", placeholder.ident)); | 235 | undefined.push(placeholder.ident.to_string()); |
232 | } | 236 | } |
233 | if !placeholder.constraints.is_empty() { | 237 | if !placeholder.constraints.is_empty() { |
234 | bail!("Replacement placeholders cannot have constraints"); | 238 | bail!("Replacement placeholders cannot have constraints"); |
@@ -344,7 +348,17 @@ impl NodeKind { | |||
344 | 348 | ||
345 | impl Placeholder { | 349 | impl Placeholder { |
346 | fn new(name: SmolStr, constraints: Vec<Constraint>) -> Self { | 350 | fn new(name: SmolStr, constraints: Vec<Constraint>) -> Self { |
347 | Self { stand_in_name: format!("__placeholder_{}", name), constraints, ident: name } | 351 | Self { |
352 | stand_in_name: format!("__placeholder_{}", name), | ||
353 | constraints, | ||
354 | ident: Var(name.to_string()), | ||
355 | } | ||
356 | } | ||
357 | } | ||
358 | |||
359 | impl Display for Var { | ||
360 | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { | ||
361 | write!(f, "${}", self.0) | ||
348 | } | 362 | } |
349 | } | 363 | } |
350 | 364 | ||
diff --git a/crates/ssr/src/replacing.rs b/crates/ssr/src/replacing.rs index 8f8fe6149..496a21e6e 100644 --- a/crates/ssr/src/replacing.rs +++ b/crates/ssr/src/replacing.rs | |||
@@ -1,6 +1,5 @@ | |||
1 | //! Code for applying replacement templates for matches that have previously been found. | 1 | //! Code for applying replacement templates for matches that have previously been found. |
2 | 2 | ||
3 | use crate::matching::Var; | ||
4 | use crate::{resolving::ResolvedRule, Match, SsrMatches}; | 3 | use crate::{resolving::ResolvedRule, Match, SsrMatches}; |
5 | use rustc_hash::{FxHashMap, FxHashSet}; | 4 | use rustc_hash::{FxHashMap, FxHashSet}; |
6 | use syntax::ast::{self, AstToken}; | 5 | use syntax::ast::{self, AstToken}; |
@@ -114,7 +113,7 @@ impl ReplacementRenderer<'_> { | |||
114 | fn render_token(&mut self, token: &SyntaxToken) { | 113 | fn render_token(&mut self, token: &SyntaxToken) { |
115 | if let Some(placeholder) = self.rule.get_placeholder(&token) { | 114 | if let Some(placeholder) = self.rule.get_placeholder(&token) { |
116 | if let Some(placeholder_value) = | 115 | if let Some(placeholder_value) = |
117 | self.match_info.placeholder_values.get(&Var(placeholder.ident.to_string())) | 116 | self.match_info.placeholder_values.get(&placeholder.ident) |
118 | { | 117 | { |
119 | let range = &placeholder_value.range.range; | 118 | let range = &placeholder_value.range.range; |
120 | let mut matched_text = | 119 | let mut matched_text = |
diff --git a/crates/ssr/src/tests.rs b/crates/ssr/src/tests.rs index 0d0a00090..65cd38753 100644 --- a/crates/ssr/src/tests.rs +++ b/crates/ssr/src/tests.rs | |||
@@ -31,7 +31,7 @@ fn parser_two_delimiters() { | |||
31 | fn parser_repeated_name() { | 31 | fn parser_repeated_name() { |
32 | assert_eq!( | 32 | assert_eq!( |
33 | parse_error_text("foo($a, $a) ==>>"), | 33 | parse_error_text("foo($a, $a) ==>>"), |
34 | "Parse error: Name `a` repeats more than once" | 34 | "Parse error: Placeholder `$a` repeats more than once" |
35 | ); | 35 | ); |
36 | } | 36 | } |
37 | 37 | ||