mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-09-28 04:44:57 +00:00
Refactor SSR so that placeholders store a Var
This allows lookup of placeholder bindings given a placeholder without needing to create a Var instance.
This commit is contained in:
parent
674af600f1
commit
c84f98385a
4 changed files with 26 additions and 18 deletions
|
@ -2,7 +2,7 @@
|
||||||
//! process of matching, placeholder values are recorded.
|
//! process of matching, placeholder values are recorded.
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
parsing::{Constraint, NodeKind, Placeholder},
|
parsing::{Constraint, NodeKind, Placeholder, Var},
|
||||||
resolving::{ResolvedPattern, ResolvedRule, UfcsCallInfo},
|
resolving::{ResolvedPattern, ResolvedRule, UfcsCallInfo},
|
||||||
SsrMatches,
|
SsrMatches,
|
||||||
};
|
};
|
||||||
|
@ -56,10 +56,6 @@ pub struct Match {
|
||||||
pub(crate) rendered_template_paths: FxHashMap<SyntaxNode, hir::ModPath>,
|
pub(crate) rendered_template_paths: FxHashMap<SyntaxNode, hir::ModPath>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Represents a `$var` in an SSR query.
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
|
||||||
pub(crate) struct Var(pub String);
|
|
||||||
|
|
||||||
/// Information about a placeholder bound in a match.
|
/// Information about a placeholder bound in a match.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub(crate) struct PlaceholderMatch {
|
pub(crate) struct PlaceholderMatch {
|
||||||
|
@ -182,10 +178,9 @@ impl<'db, 'sema> Matcher<'db, 'sema> {
|
||||||
// We validated the range for the node when we started the match, so the placeholder
|
// We validated the range for the node when we started the match, so the placeholder
|
||||||
// probably can't fail range validation, but just to be safe...
|
// probably can't fail range validation, but just to be safe...
|
||||||
self.validate_range(&original_range)?;
|
self.validate_range(&original_range)?;
|
||||||
matches_out.placeholder_values.insert(
|
matches_out
|
||||||
Var(placeholder.ident.to_string()),
|
.placeholder_values
|
||||||
PlaceholderMatch::new(code, original_range),
|
.insert(placeholder.ident.clone(), PlaceholderMatch::new(code, original_range));
|
||||||
);
|
|
||||||
}
|
}
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
@ -487,7 +482,7 @@ impl<'db, 'sema> Matcher<'db, 'sema> {
|
||||||
}
|
}
|
||||||
if let Phase::Second(match_out) = phase {
|
if let Phase::Second(match_out) = phase {
|
||||||
match_out.placeholder_values.insert(
|
match_out.placeholder_values.insert(
|
||||||
Var(placeholder.ident.to_string()),
|
placeholder.ident.clone(),
|
||||||
PlaceholderMatch::from_range(FileRange {
|
PlaceholderMatch::from_range(FileRange {
|
||||||
file_id: self.sema.original_range(code).file_id,
|
file_id: self.sema.original_range(code).file_id,
|
||||||
range: first_matched_token
|
range: first_matched_token
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
use crate::errors::bail;
|
use crate::errors::bail;
|
||||||
use crate::{SsrError, SsrPattern, SsrRule};
|
use crate::{SsrError, SsrPattern, SsrRule};
|
||||||
use rustc_hash::{FxHashMap, FxHashSet};
|
use rustc_hash::{FxHashMap, FxHashSet};
|
||||||
use std::str::FromStr;
|
use std::{fmt::Display, str::FromStr};
|
||||||
use syntax::{ast, AstNode, SmolStr, SyntaxKind, SyntaxNode, T};
|
use syntax::{ast, AstNode, SmolStr, SyntaxKind, SyntaxNode, T};
|
||||||
use test_utils::mark;
|
use test_utils::mark;
|
||||||
|
|
||||||
|
@ -34,12 +34,16 @@ pub(crate) enum PatternElement {
|
||||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||||
pub(crate) struct Placeholder {
|
pub(crate) struct Placeholder {
|
||||||
/// The name of this placeholder. e.g. for "$a", this would be "a"
|
/// The name of this placeholder. e.g. for "$a", this would be "a"
|
||||||
pub(crate) ident: SmolStr,
|
pub(crate) ident: Var,
|
||||||
/// A unique name used in place of this placeholder when we parse the pattern as Rust code.
|
/// A unique name used in place of this placeholder when we parse the pattern as Rust code.
|
||||||
stand_in_name: String,
|
stand_in_name: String,
|
||||||
pub(crate) constraints: Vec<Constraint>,
|
pub(crate) constraints: Vec<Constraint>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Represents a `$var` in an SSR query.
|
||||||
|
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||||
|
pub(crate) struct Var(pub String);
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||||
pub(crate) enum Constraint {
|
pub(crate) enum Constraint {
|
||||||
Kind(NodeKind),
|
Kind(NodeKind),
|
||||||
|
@ -205,7 +209,7 @@ fn parse_pattern(pattern_str: &str) -> Result<Vec<PatternElement>, SsrError> {
|
||||||
if token.kind == T![$] {
|
if token.kind == T![$] {
|
||||||
let placeholder = parse_placeholder(&mut tokens)?;
|
let placeholder = parse_placeholder(&mut tokens)?;
|
||||||
if !placeholder_names.insert(placeholder.ident.clone()) {
|
if !placeholder_names.insert(placeholder.ident.clone()) {
|
||||||
bail!("Name `{}` repeats more than once", placeholder.ident);
|
bail!("Placeholder `{}` repeats more than once", placeholder.ident);
|
||||||
}
|
}
|
||||||
res.push(PatternElement::Placeholder(placeholder));
|
res.push(PatternElement::Placeholder(placeholder));
|
||||||
} else {
|
} else {
|
||||||
|
@ -228,7 +232,7 @@ fn validate_rule(rule: &SsrRule) -> Result<(), SsrError> {
|
||||||
for p in &rule.template.tokens {
|
for p in &rule.template.tokens {
|
||||||
if let PatternElement::Placeholder(placeholder) = p {
|
if let PatternElement::Placeholder(placeholder) = p {
|
||||||
if !defined_placeholders.contains(&placeholder.ident) {
|
if !defined_placeholders.contains(&placeholder.ident) {
|
||||||
undefined.push(format!("${}", placeholder.ident));
|
undefined.push(placeholder.ident.to_string());
|
||||||
}
|
}
|
||||||
if !placeholder.constraints.is_empty() {
|
if !placeholder.constraints.is_empty() {
|
||||||
bail!("Replacement placeholders cannot have constraints");
|
bail!("Replacement placeholders cannot have constraints");
|
||||||
|
@ -344,7 +348,17 @@ impl NodeKind {
|
||||||
|
|
||||||
impl Placeholder {
|
impl Placeholder {
|
||||||
fn new(name: SmolStr, constraints: Vec<Constraint>) -> Self {
|
fn new(name: SmolStr, constraints: Vec<Constraint>) -> Self {
|
||||||
Self { stand_in_name: format!("__placeholder_{}", name), constraints, ident: name }
|
Self {
|
||||||
|
stand_in_name: format!("__placeholder_{}", name),
|
||||||
|
constraints,
|
||||||
|
ident: Var(name.to_string()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Display for Var {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
write!(f, "${}", self.0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
//! Code for applying replacement templates for matches that have previously been found.
|
//! Code for applying replacement templates for matches that have previously been found.
|
||||||
|
|
||||||
use crate::matching::Var;
|
|
||||||
use crate::{resolving::ResolvedRule, Match, SsrMatches};
|
use crate::{resolving::ResolvedRule, Match, SsrMatches};
|
||||||
use rustc_hash::{FxHashMap, FxHashSet};
|
use rustc_hash::{FxHashMap, FxHashSet};
|
||||||
use syntax::ast::{self, AstToken};
|
use syntax::ast::{self, AstToken};
|
||||||
|
@ -114,7 +113,7 @@ impl ReplacementRenderer<'_> {
|
||||||
fn render_token(&mut self, token: &SyntaxToken) {
|
fn render_token(&mut self, token: &SyntaxToken) {
|
||||||
if let Some(placeholder) = self.rule.get_placeholder(&token) {
|
if let Some(placeholder) = self.rule.get_placeholder(&token) {
|
||||||
if let Some(placeholder_value) =
|
if let Some(placeholder_value) =
|
||||||
self.match_info.placeholder_values.get(&Var(placeholder.ident.to_string()))
|
self.match_info.placeholder_values.get(&placeholder.ident)
|
||||||
{
|
{
|
||||||
let range = &placeholder_value.range.range;
|
let range = &placeholder_value.range.range;
|
||||||
let mut matched_text =
|
let mut matched_text =
|
||||||
|
|
|
@ -31,7 +31,7 @@ fn parser_two_delimiters() {
|
||||||
fn parser_repeated_name() {
|
fn parser_repeated_name() {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
parse_error_text("foo($a, $a) ==>>"),
|
parse_error_text("foo($a, $a) ==>>"),
|
||||||
"Parse error: Name `a` repeats more than once"
|
"Parse error: Placeholder `$a` repeats more than once"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue