aboutsummaryrefslogtreecommitdiff
path: root/crates/ssr/src/parsing.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ssr/src/parsing.rs')
-rw-r--r--crates/ssr/src/parsing.rs24
1 files changed, 19 insertions, 5 deletions
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