aboutsummaryrefslogtreecommitdiff
path: root/crates/ssr/src
diff options
context:
space:
mode:
authorDavid Lattimore <[email protected]>2020-08-06 02:30:52 +0100
committerDavid Lattimore <[email protected]>2020-08-14 11:12:26 +0100
commitc84f98385a28eeb7595f38b7cfaf861a6e06f4ea (patch)
tree6f8c4a1770aeefde182e365e0d249ed12bc61fdd /crates/ssr/src
parent674af600f105abe1dcb6c7654058e7df5a402429 (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.
Diffstat (limited to 'crates/ssr/src')
-rw-r--r--crates/ssr/src/matching.rs15
-rw-r--r--crates/ssr/src/parsing.rs24
-rw-r--r--crates/ssr/src/replacing.rs3
-rw-r--r--crates/ssr/src/tests.rs2
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
4use crate::{ 4use 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)]
61pub(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)]
65pub(crate) struct PlaceholderMatch { 61pub(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 @@
8use crate::errors::bail; 8use crate::errors::bail;
9use crate::{SsrError, SsrPattern, SsrRule}; 9use crate::{SsrError, SsrPattern, SsrRule};
10use rustc_hash::{FxHashMap, FxHashSet}; 10use rustc_hash::{FxHashMap, FxHashSet};
11use std::str::FromStr; 11use std::{fmt::Display, str::FromStr};
12use syntax::{ast, AstNode, SmolStr, SyntaxKind, SyntaxNode, T}; 12use syntax::{ast, AstNode, SmolStr, SyntaxKind, SyntaxNode, T};
13use test_utils::mark; 13use 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)]
35pub(crate) struct Placeholder { 35pub(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)]
45pub(crate) struct Var(pub String);
46
43#[derive(Clone, Debug, PartialEq, Eq)] 47#[derive(Clone, Debug, PartialEq, Eq)]
44pub(crate) enum Constraint { 48pub(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
345impl Placeholder { 349impl 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
359impl 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
3use crate::matching::Var;
4use crate::{resolving::ResolvedRule, Match, SsrMatches}; 3use crate::{resolving::ResolvedRule, Match, SsrMatches};
5use rustc_hash::{FxHashMap, FxHashSet}; 4use rustc_hash::{FxHashMap, FxHashSet};
6use syntax::ast::{self, AstToken}; 5use 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() {
31fn parser_repeated_name() { 31fn 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