Unnamed repository; edit this file 'description' to name the repository.
Merge pull request #22808 from bit-aloo/2026-07-15-remove-mutable-rowan-api
remove clone_for_update / mutable rowan API's
Chayim Refael Friedman 9 days ago
parent ad35b20 · parent e1ab771 · commit d600cff
-rw-r--r--crates/ide-assists/src/handlers/generate_blanket_trait_impl.rs2
-rw-r--r--crates/ide-assists/src/handlers/replace_derive_with_manual_impl.rs9
-rw-r--r--crates/syntax/src/ast.rs6
-rw-r--r--crates/syntax/src/ast/syntax_factory/constructors.rs330
-rw-r--r--crates/syntax/src/syntax_editor.rs21
-rw-r--r--crates/syntax/src/syntax_editor/edit_algo.rs1055
-rw-r--r--crates/syntax/src/syntax_editor/mapping.rs69
7 files changed, 833 insertions, 659 deletions
diff --git a/crates/ide-assists/src/handlers/generate_blanket_trait_impl.rs b/crates/ide-assists/src/handlers/generate_blanket_trait_impl.rs
index 1e3f2ac677..acd98aed00 100644
--- a/crates/ide-assists/src/handlers/generate_blanket_trait_impl.rs
+++ b/crates/ide-assists/src/handlers/generate_blanket_trait_impl.rs
@@ -141,7 +141,7 @@ pub(crate) fn generate_blanket_trait_impl(
if let Some(cap) = ctx.config.snippet_cap
&& let Some(self_ty) = impl_.self_ty()
{
- builder.add_tabstop_before(cap, self_ty);
+ editor.add_annotation(self_ty.syntax(), builder.make_tabstop_before(cap));
}
builder.add_file_edits(ctx.vfs_file_id(), editor);
},
diff --git a/crates/ide-assists/src/handlers/replace_derive_with_manual_impl.rs b/crates/ide-assists/src/handlers/replace_derive_with_manual_impl.rs
index 4e85b30b58..707b3321c3 100644
--- a/crates/ide-assists/src/handlers/replace_derive_with_manual_impl.rs
+++ b/crates/ide-assists/src/handlers/replace_derive_with_manual_impl.rs
@@ -187,15 +187,18 @@ fn add_assist(
&& m.syntax().text() == "todo!()"
{
// Make the `todo!()` a placeholder
- builder.add_placeholder_snippet(cap, m);
+ editor.add_annotation(m.syntax(), builder.make_placeholder_snippet(cap));
} else {
// If we haven't already added a snippet, add a tabstop before the generated function
- builder.add_tabstop_before(cap, first_assoc_item);
+ editor.add_annotation(
+ first_assoc_item.syntax(),
+ builder.make_tabstop_before(cap),
+ );
}
} else if let Some(l_curly) =
impl_def.assoc_item_list().and_then(|it| it.l_curly_token())
{
- builder.add_tabstop_after_token(cap, l_curly);
+ editor.add_annotation(l_curly, builder.make_tabstop_after(cap));
}
}
diff --git a/crates/syntax/src/ast.rs b/crates/syntax/src/ast.rs
index d8c7e15830..855b5a80a5 100644
--- a/crates/syntax/src/ast.rs
+++ b/crates/syntax/src/ast.rs
@@ -61,12 +61,6 @@ pub trait AstNode {
Self: Sized;
fn syntax(&self) -> &SyntaxNode;
- fn clone_for_update(&self) -> Self
- where
- Self: Sized,
- {
- Self::cast(self.syntax().clone_for_update()).unwrap()
- }
fn clone_subtree(&self) -> Self
where
Self: Sized,
diff --git a/crates/syntax/src/ast/syntax_factory/constructors.rs b/crates/syntax/src/ast/syntax_factory/constructors.rs
index 22c8c842d8..23fb0e2e02 100644
--- a/crates/syntax/src/ast/syntax_factory/constructors.rs
+++ b/crates/syntax/src/ast/syntax_factory/constructors.rs
@@ -14,49 +14,45 @@ use super::SyntaxFactory;
impl SyntaxFactory {
pub fn name(&self, name: &str) -> ast::Name {
- make::name(name).clone_for_update()
+ make::name(name)
}
pub fn name_ref(&self, name: &str) -> ast::NameRef {
- make::name_ref(name).clone_for_update()
+ make::name_ref(name)
}
pub fn name_ref_self_ty(&self) -> ast::NameRef {
- make::name_ref_self_ty().clone_for_update()
+ make::name_ref_self_ty()
}
pub fn expr_todo(&self) -> ast::Expr {
- make::ext::expr_todo().clone_for_update()
+ make::ext::expr_todo()
}
pub fn expr_self(&self) -> ast::Expr {
- make::ext::expr_self().clone_for_update()
+ make::ext::expr_self()
}
pub fn expr_const_value(&self, text: &str) -> ast::ConstArg {
- make::expr_const_value(text).clone_for_update()
+ make::expr_const_value(text)
}
pub fn lifetime(&self, text: &str) -> ast::Lifetime {
- make::lifetime(text).clone_for_update()
+ make::lifetime(text)
}
pub fn ty(&self, text: &str) -> ast::Type {
- make::ty(text).clone_for_update()
+ make::ty(text)
}
pub fn ty_infer(&self) -> ast::InferType {
- let ast::Type::InferType(ast) = make::ty_placeholder().clone_for_update() else {
- unreachable!()
- };
+ let ast::Type::InferType(ast) = make::ty_placeholder() else { unreachable!() };
ast
}
pub fn ty_path(&self, path: ast::Path) -> ast::PathType {
- let ast::Type::PathType(ast) = make::ty_path(path.clone()).clone_for_update() else {
- unreachable!()
- };
+ let ast::Type::PathType(ast) = make::ty_path(path.clone()) else { unreachable!() };
if let Some(mut mapping) = self.mappings() {
let mut builder = SyntaxMappingBuilder::new(ast.syntax().clone());
@@ -76,11 +72,11 @@ impl SyntaxFactory {
}
pub fn type_bound(&self, bound: ast::Type) -> ast::TypeBound {
- make::type_bound(bound).clone_for_update()
+ make::type_bound(bound)
}
pub fn type_bound_text(&self, bound: &str) -> ast::TypeBound {
- make::type_bound_text(bound).clone_for_update()
+ make::type_bound_text(bound)
}
pub fn use_tree_list(
@@ -88,7 +84,7 @@ impl SyntaxFactory {
use_trees: impl IntoIterator<Item = ast::UseTree>,
) -> ast::UseTreeList {
let (use_trees, input) = iterator_input(use_trees);
- let ast = make::use_tree_list(use_trees).clone_for_update();
+ let ast = make::use_tree_list(use_trees);
if let Some(mut mapping) = self.mappings() {
let mut builder = SyntaxMappingBuilder::new(ast.syntax().clone());
@@ -104,7 +100,7 @@ impl SyntaxFactory {
bounds: impl IntoIterator<Item = ast::TypeBound>,
) -> Option<ast::TypeBoundList> {
let (bounds, input) = iterator_input(bounds);
- let ast = make::type_bound_list(bounds)?.clone_for_update();
+ let ast = make::type_bound_list(bounds)?;
if let Some(mut mapping) = self.mappings() {
let mut builder = SyntaxMappingBuilder::new(ast.syntax().clone());
@@ -122,7 +118,7 @@ impl SyntaxFactory {
name: ast::Name,
bounds: Option<ast::TypeBoundList>,
) -> ast::TypeParam {
- let ast = make::type_param(name.clone(), bounds.clone()).clone_for_update();
+ let ast = make::type_param(name.clone(), bounds.clone());
if let Some(mut mapping) = self.mappings() {
let mut builder = SyntaxMappingBuilder::new(ast.syntax().clone());
@@ -140,23 +136,23 @@ impl SyntaxFactory {
}
pub fn path_from_text(&self, text: &str) -> ast::Path {
- make::path_from_text(text).clone_for_update()
+ make::path_from_text(text)
}
pub fn path_from_text_with_edition(&self, text: &str, edition: Edition) -> ast::Path {
- make::path_from_text_with_edition(text, edition).clone_for_update()
+ make::path_from_text_with_edition(text, edition)
}
pub fn path_concat(&self, first: ast::Path, second: ast::Path) -> ast::Path {
- make::path_concat(first, second).clone_for_update()
+ make::path_concat(first, second)
}
pub fn visibility_pub_crate(&self) -> ast::Visibility {
- make::visibility_pub_crate().clone_for_update()
+ make::visibility_pub_crate()
}
pub fn visibility_pub(&self) -> ast::Visibility {
- make::visibility_pub().clone_for_update()
+ make::visibility_pub()
}
pub fn struct_(
@@ -171,8 +167,7 @@ impl SyntaxFactory {
strukt_name.clone(),
generic_param_list.clone(),
field_list.clone(),
- )
- .clone_for_update();
+ );
if let Some(mut mapping) = self.mappings() {
let mut builder = SyntaxMappingBuilder::new(ast.syntax().clone());
@@ -198,7 +193,7 @@ impl SyntaxFactory {
}
pub fn unnamed_param(&self, ty: ast::Type) -> ast::Param {
- let ast = make::unnamed_param(ty.clone()).clone_for_update();
+ let ast = make::unnamed_param(ty.clone());
if let Some(mut mapping) = self.mappings() {
let mut builder = SyntaxMappingBuilder::new(ast.syntax().clone());
@@ -210,7 +205,7 @@ impl SyntaxFactory {
}
pub fn untyped_param(&self, pat: ast::Pat) -> ast::Param {
- let ast = make::untyped_param(pat.clone()).clone_for_update();
+ let ast = make::untyped_param(pat.clone());
if let Some(mut mapping) = self.mappings() {
let mut builder = SyntaxMappingBuilder::new(ast.syntax().clone());
@@ -229,8 +224,7 @@ impl SyntaxFactory {
ret_type: Option<ast::RetType>,
) -> ast::FnPtrType {
let (params, params_input) = iterator_input(params);
- let ast = make::ty_fn_ptr(is_unsafe, abi.clone(), params.into_iter(), ret_type.clone())
- .clone_for_update();
+ let ast = make::ty_fn_ptr(is_unsafe, abi.clone(), params.into_iter(), ret_type.clone());
if let Some(mut mapping) = self.mappings() {
let mut builder = SyntaxMappingBuilder::new(ast.syntax().clone());
@@ -257,7 +251,7 @@ impl SyntaxFactory {
bounds: impl IntoIterator<Item = ast::TypeBound>,
) -> ast::WherePred {
let (bounds, bounds_input) = iterator_input(bounds);
- let ast = make::where_pred(path.clone(), bounds).clone_for_update();
+ let ast = make::where_pred(path.clone(), bounds);
if let Some(mut mapping) = self.mappings() {
let mut builder = SyntaxMappingBuilder::new(ast.syntax().clone());
@@ -293,7 +287,7 @@ impl SyntaxFactory {
predicates: impl IntoIterator<Item = ast::WherePred>,
) -> ast::WhereClause {
let (predicates, input) = iterator_input(predicates);
- let ast = make::where_clause(predicates).clone_for_update();
+ let ast = make::where_clause(predicates);
if let Some(mut mapping) = self.mappings() {
let mut builder = SyntaxMappingBuilder::new(ast.syntax().clone());
@@ -305,7 +299,7 @@ impl SyntaxFactory {
}
pub fn impl_trait_type(&self, bounds: ast::TypeBoundList) -> ast::ImplTraitType {
- let ast = make::impl_trait_type(bounds.clone()).clone_for_update();
+ let ast = make::impl_trait_type(bounds.clone());
if let Some(mut mapping) = self.mappings() {
let mut builder = SyntaxMappingBuilder::new(ast.syntax().clone());
@@ -318,9 +312,7 @@ impl SyntaxFactory {
}
pub fn expr_field(&self, receiver: ast::Expr, field: &str) -> ast::FieldExpr {
- let ast::Expr::FieldExpr(ast) =
- make::expr_field(receiver.clone(), field).clone_for_update()
- else {
+ let ast::Expr::FieldExpr(ast) = make::expr_field(receiver.clone(), field) else {
unreachable!()
};
@@ -362,8 +354,7 @@ impl SyntaxFactory {
trait_where_clause.clone(),
ty_where_clause.clone(),
body.clone(),
- )
- .clone_for_update();
+ );
if let Some(mut mapping) = self.mappings() {
let mut builder = SyntaxMappingBuilder::new(ast.syntax().clone());
@@ -411,8 +402,7 @@ impl SyntaxFactory {
type_param_bounds.clone(),
where_clause.clone(),
assignment.clone(),
- )
- .clone_for_update();
+ );
if let Some(mut mapping) = self.mappings() {
let mut builder = SyntaxMappingBuilder::new(ast.syntax().clone());
@@ -450,7 +440,7 @@ impl SyntaxFactory {
params: impl IntoIterator<Item = ast::Param>,
) -> ast::ParamList {
let (params, input) = iterator_input(params);
- let ast = make::param_list(self_param.clone(), params).clone_for_update();
+ let ast = make::param_list(self_param.clone(), params);
if let Some(mut mapping) = self.mappings() {
let mut builder = SyntaxMappingBuilder::new(ast.syntax().clone());
@@ -467,7 +457,7 @@ impl SyntaxFactory {
}
pub fn const_param(&self, name: ast::Name, ty: ast::Type) -> ast::ConstParam {
- let ast = make::const_param(name.clone(), ty.clone()).clone_for_update();
+ let ast = make::const_param(name.clone(), ty.clone());
if let Some(mut mapping) = self.mappings() {
let mut builder = SyntaxMappingBuilder::new(ast.syntax().clone());
@@ -480,7 +470,7 @@ impl SyntaxFactory {
}
pub fn lifetime_param(&self, lifetime: ast::Lifetime) -> ast::LifetimeParam {
- let ast = make::lifetime_param(lifetime.clone()).clone_for_update();
+ let ast = make::lifetime_param(lifetime.clone());
if let Some(mut mapping) = self.mappings() {
let mut builder = SyntaxMappingBuilder::new(ast.syntax().clone());
@@ -496,7 +486,7 @@ impl SyntaxFactory {
params: impl IntoIterator<Item = ast::GenericParam>,
) -> ast::GenericParamList {
let (params, input) = iterator_input(params);
- let ast = make::generic_param_list(params).clone_for_update();
+ let ast = make::generic_param_list(params);
if let Some(mut mapping) = self.mappings() {
let mut builder = SyntaxMappingBuilder::new(ast.syntax().clone());
@@ -508,7 +498,7 @@ impl SyntaxFactory {
}
pub fn path_segment(&self, name_ref: ast::NameRef) -> ast::PathSegment {
- let ast = make::path_segment(name_ref.clone()).clone_for_update();
+ let ast = make::path_segment(name_ref.clone());
if let Some(mut mapping) = self.mappings() {
let mut builder = SyntaxMappingBuilder::new(ast.syntax().clone());
@@ -520,15 +510,15 @@ impl SyntaxFactory {
}
pub fn path_segment_self(&self) -> ast::PathSegment {
- make::path_segment_self().clone_for_update()
+ make::path_segment_self()
}
pub fn path_segment_super(&self) -> ast::PathSegment {
- make::path_segment_super().clone_for_update()
+ make::path_segment_super()
}
pub fn path_segment_crate(&self) -> ast::PathSegment {
- make::path_segment_crate().clone_for_update()
+ make::path_segment_crate()
}
pub fn generic_ty_path_segment(
@@ -537,7 +527,7 @@ impl SyntaxFactory {
generic_args: impl IntoIterator<Item = ast::GenericArg>,
) -> ast::PathSegment {
let (generic_args, input) = iterator_input(generic_args);
- let ast = make::generic_ty_path_segment(name_ref.clone(), generic_args).clone_for_update();
+ let ast = make::generic_ty_path_segment(name_ref.clone(), generic_args);
if let Some(mut mapping) = self.mappings() {
let mut builder = SyntaxMappingBuilder::new(ast.syntax().clone());
@@ -555,7 +545,7 @@ impl SyntaxFactory {
}
pub fn tail_only_block_expr(&self, tail_expr: ast::Expr) -> ast::BlockExpr {
- let ast = make::tail_only_block_expr(tail_expr.clone()).clone_for_update();
+ let ast = make::tail_only_block_expr(tail_expr.clone());
if let Some(mut mapping) = self.mappings() {
let stmt_list = ast.stmt_list().unwrap();
@@ -571,9 +561,7 @@ impl SyntaxFactory {
}
pub fn expr_bin_op(&self, lhs: ast::Expr, op: ast::BinaryOp, rhs: ast::Expr) -> ast::Expr {
- let ast::Expr::BinExpr(ast) =
- make::expr_bin_op(lhs.clone(), op, rhs.clone()).clone_for_update()
- else {
+ let ast::Expr::BinExpr(ast) = make::expr_bin_op(lhs.clone(), op, rhs.clone()) else {
unreachable!()
};
@@ -588,16 +576,16 @@ impl SyntaxFactory {
}
pub fn ty_placeholder(&self) -> ast::Type {
- make::ty_placeholder().clone_for_update()
+ make::ty_placeholder()
}
pub fn ty_unit(&self) -> ast::Type {
- make::ty_unit().clone_for_update()
+ make::ty_unit()
}
pub fn ty_tuple(&self, types: impl IntoIterator<Item = ast::Type>) -> ast::Type {
let (types, input) = iterator_input(types);
- let ast = make::ty_tuple(types).clone_for_update();
+ let ast = make::ty_tuple(types);
if let Some(mut mapping) = self.mappings()
&& let ast::Type::TupleType(tuple_ty) = &ast
@@ -631,7 +619,7 @@ impl SyntaxFactory {
unreachable!();
};
- let ast = path.path().unwrap().segment().unwrap().clone_for_update();
+ let ast = path.path().unwrap().segment().unwrap();
if let Some(mut mapping) = self.mappings() {
let mut builder = SyntaxMappingBuilder::new(ast.syntax().clone());
@@ -653,7 +641,7 @@ impl SyntaxFactory {
use_tree: ast::UseTree,
) -> ast::Use {
let (attrs, attrs_input) = iterator_input(attrs);
- let ast = make::use_(attrs, visibility.clone(), use_tree.clone()).clone_for_update();
+ let ast = make::use_(attrs, visibility.clone(), use_tree.clone());
if let Some(mut mapping) = self.mappings() {
let mut builder = SyntaxMappingBuilder::new(ast.syntax().clone());
@@ -678,8 +666,7 @@ impl SyntaxFactory {
alias: Option<ast::Rename>,
add_star: bool,
) -> ast::UseTree {
- let ast = make::use_tree(path.clone(), use_tree_list.clone(), alias.clone(), add_star)
- .clone_for_update();
+ let ast = make::use_tree(path.clone(), use_tree_list.clone(), alias.clone(), add_star);
if let Some(mut mapping) = self.mappings() {
let mut builder = SyntaxMappingBuilder::new(ast.syntax().clone());
@@ -700,11 +687,11 @@ impl SyntaxFactory {
}
pub fn use_tree_glob(&self) -> ast::UseTree {
- make::use_tree_glob().clone_for_update()
+ make::use_tree_glob()
}
pub fn path_unqualified(&self, segment: ast::PathSegment) -> ast::Path {
- let ast = make::path_unqualified(segment.clone()).clone_for_update();
+ let ast = make::path_unqualified(segment.clone());
if let Some(mut mapping) = self.mappings() {
let mut builder = SyntaxMappingBuilder::new(ast.syntax().clone());
@@ -716,7 +703,7 @@ impl SyntaxFactory {
}
pub fn path_qualified(&self, qual: ast::Path, segment: ast::PathSegment) -> ast::Path {
- let ast = make::path_qualified(qual.clone(), segment.clone()).clone_for_update();
+ let ast = make::path_qualified(qual.clone(), segment.clone());
if let Some(mut mapping) = self.mappings() {
let mut builder = SyntaxMappingBuilder::new(ast.syntax().clone());
@@ -738,7 +725,7 @@ impl SyntaxFactory {
is_abs: bool,
) -> ast::Path {
let (segments, input) = iterator_input(segments);
- let ast = make::path_from_segments(segments, is_abs).clone_for_update();
+ let ast = make::path_from_segments(segments, is_abs);
if let Some(mut mapping) = self.mappings() {
let mut current_path = Some(ast.clone());
@@ -757,7 +744,7 @@ impl SyntaxFactory {
}
pub fn ident_pat(&self, ref_: bool, mut_: bool, name: ast::Name) -> ast::IdentPat {
- let ast = make::ident_pat(ref_, mut_, name.clone()).clone_for_update();
+ let ast = make::ident_pat(ref_, mut_, name.clone());
if let Some(mut mapping) = self.mappings() {
let mut builder = SyntaxMappingBuilder::new(ast.syntax().clone());
@@ -769,7 +756,7 @@ impl SyntaxFactory {
}
pub fn simple_ident_pat(&self, name: ast::Name) -> ast::IdentPat {
- let ast = make::ext::simple_ident_pat(name.clone()).clone_for_update();
+ let ast = make::ext::simple_ident_pat(name.clone());
if let Some(mut mapping) = self.mappings() {
let mut builder = SyntaxMappingBuilder::new(ast.syntax().clone());
@@ -781,16 +768,16 @@ impl SyntaxFactory {
}
pub fn wildcard_pat(&self) -> ast::WildcardPat {
- make::wildcard_pat().clone_for_update()
+ make::wildcard_pat()
}
pub fn literal_pat(&self, text: &str) -> ast::LiteralPat {
- make::literal_pat(text).clone_for_update()
+ make::literal_pat(text)
}
pub fn slice_pat(&self, pats: impl IntoIterator<Item = ast::Pat>) -> ast::SlicePat {
let (pats, input) = iterator_input(pats);
- let ast = make::slice_pat(pats).clone_for_update();
+ let ast = make::slice_pat(pats);
if let Some(mut mapping) = self.mappings() {
let mut builder = SyntaxMappingBuilder::new(ast.syntax().clone());
@@ -803,7 +790,7 @@ impl SyntaxFactory {
pub fn tuple_pat(&self, pats: impl IntoIterator<Item = ast::Pat>) -> ast::TuplePat {
let (pats, input) = iterator_input(pats);
- let ast = make::tuple_pat(pats).clone_for_update();
+ let ast = make::tuple_pat(pats);
if let Some(mut mapping) = self.mappings() {
let mut builder = SyntaxMappingBuilder::new(ast.syntax().clone());
@@ -820,7 +807,7 @@ impl SyntaxFactory {
fields: impl IntoIterator<Item = ast::Pat>,
) -> ast::TupleStructPat {
let (fields, input) = iterator_input(fields);
- let ast = make::tuple_struct_pat(path.clone(), fields).clone_for_update();
+ let ast = make::tuple_struct_pat(path.clone(), fields);
if let Some(mut mapping) = self.mappings() {
let mut builder = SyntaxMappingBuilder::new(ast.syntax().clone());
@@ -837,7 +824,7 @@ impl SyntaxFactory {
path: ast::Path,
fields: ast::RecordPatFieldList,
) -> ast::RecordPat {
- let ast = make::record_pat_with_fields(path.clone(), fields.clone()).clone_for_update();
+ let ast = make::record_pat_with_fields(path.clone(), fields.clone());
if let Some(mut mapping) = self.mappings() {
let mut builder = SyntaxMappingBuilder::new(ast.syntax().clone());
@@ -858,7 +845,7 @@ impl SyntaxFactory {
rest_pat: Option<ast::RestPat>,
) -> ast::RecordPatFieldList {
let (fields, input) = iterator_input(fields);
- let ast = make::record_pat_field_list(fields, rest_pat.clone()).clone_for_update();
+ let ast = make::record_pat_field_list(fields, rest_pat.clone());
if let Some(mut mapping) = self.mappings() {
let mut builder = SyntaxMappingBuilder::new(ast.syntax().clone());
@@ -874,7 +861,7 @@ impl SyntaxFactory {
}
pub fn record_pat_field(&self, name_ref: ast::NameRef, pat: ast::Pat) -> ast::RecordPatField {
- let ast = make::record_pat_field(name_ref.clone(), pat.clone()).clone_for_update();
+ let ast = make::record_pat_field(name_ref.clone(), pat.clone());
if let Some(mut mapping) = self.mappings() {
let mut builder = SyntaxMappingBuilder::new(ast.syntax().clone());
@@ -887,7 +874,7 @@ impl SyntaxFactory {
}
pub fn record_pat_field_shorthand(&self, pat: ast::Pat) -> ast::RecordPatField {
- let ast = make::record_pat_field_shorthand(pat.clone()).clone_for_update();
+ let ast = make::record_pat_field_shorthand(pat.clone());
if let Some(mut mapping) = self.mappings() {
let mut builder = SyntaxMappingBuilder::new(ast.syntax().clone());
@@ -899,7 +886,7 @@ impl SyntaxFactory {
}
pub fn path_pat(&self, path: ast::Path) -> ast::Pat {
- let ast = make::path_pat(path.clone()).clone_for_update();
+ let ast = make::path_pat(path.clone());
match &ast {
ast::Pat::PathPat(ast) => {
@@ -923,7 +910,7 @@ impl SyntaxFactory {
}
pub fn rest_pat(&self) -> ast::RestPat {
- make::rest_pat().clone_for_update()
+ make::rest_pat()
}
pub fn or_pat(
@@ -932,7 +919,7 @@ impl SyntaxFactory {
leading_pipe: bool,
) -> ast::OrPat {
let (pats, input) = iterator_input(pats);
- let ast = make::or_pat(pats, leading_pipe).clone_for_update();
+ let ast = make::or_pat(pats, leading_pipe);
if let Some(mut mapping) = self.mappings() {
let mut builder = SyntaxMappingBuilder::new(ast.syntax().clone());
@@ -944,7 +931,7 @@ impl SyntaxFactory {
}
pub fn box_pat(&self, pat: ast::Pat) -> ast::BoxPat {
- let ast = make::box_pat(pat.clone()).clone_for_update();
+ let ast = make::box_pat(pat.clone());
if let Some(mut mapping) = self.mappings() {
let mut builder = SyntaxMappingBuilder::new(ast.syntax().clone());
@@ -956,11 +943,11 @@ impl SyntaxFactory {
}
pub fn deref_pat(&self, pat: ast::Pat) -> ast::Pat {
- make::deref_pat(pat.clone()).clone_for_update()
+ make::deref_pat(pat.clone())
}
pub fn paren_pat(&self, pat: ast::Pat) -> ast::ParenPat {
- let ast = make::paren_pat(pat.clone()).clone_for_update();
+ let ast = make::paren_pat(pat.clone());
if let Some(mut mapping) = self.mappings() {
let mut builder = SyntaxMappingBuilder::new(ast.syntax().clone());
@@ -972,7 +959,7 @@ impl SyntaxFactory {
}
pub fn range_pat(&self, start: Option<ast::Pat>, end: Option<ast::Pat>) -> ast::RangePat {
- let ast = make::range_pat(start.clone(), end.clone()).clone_for_update();
+ let ast = make::range_pat(start.clone(), end.clone());
if let Some(mut mapping) = self.mappings() {
let mut builder = SyntaxMappingBuilder::new(ast.syntax().clone());
@@ -989,7 +976,7 @@ impl SyntaxFactory {
}
pub fn ref_pat(&self, pat: ast::Pat) -> ast::RefPat {
- let ast = make::ref_pat(pat.clone()).clone_for_update();
+ let ast = make::ref_pat(pat.clone());
if let Some(mut mapping) = self.mappings() {
let mut builder = SyntaxMappingBuilder::new(ast.syntax().clone());
@@ -1007,7 +994,7 @@ impl SyntaxFactory {
) -> ast::BlockExpr {
let (statements, mut input) = iterator_input(statements);
- let ast = make::block_expr(statements, tail_expr.clone()).clone_for_update();
+ let ast = make::block_expr(statements, tail_expr.clone());
if let Some(mut mapping) = self.mappings() {
let stmt_list = ast.stmt_list().unwrap();
@@ -1040,7 +1027,7 @@ impl SyntaxFactory {
) -> ast::BlockExpr {
let (statements, mut input) = iterator_input(statements);
- let ast = make::async_move_block_expr(statements, tail_expr.clone()).clone_for_update();
+ let ast = make::async_move_block_expr(statements, tail_expr.clone());
if let Some(mut mapping) = self.mappings() {
let stmt_list = ast.stmt_list().unwrap();
@@ -1065,11 +1052,11 @@ impl SyntaxFactory {
}
pub fn expr_empty_block(&self) -> ast::BlockExpr {
- make::expr_empty_block().clone_for_update()
+ make::expr_empty_block()
}
pub fn expr_paren(&self, expr: ast::Expr) -> ast::ParenExpr {
- let ast = make::expr_paren(expr.clone()).clone_for_update();
+ let ast = make::expr_paren(expr.clone());
if let Some(mut mapping) = self.mappings() {
let mut builder = SyntaxMappingBuilder::new(ast.syntax().clone());
@@ -1082,7 +1069,7 @@ impl SyntaxFactory {
pub fn expr_tuple(&self, fields: impl IntoIterator<Item = ast::Expr>) -> ast::TupleExpr {
let (fields, input) = iterator_input(fields);
- let ast = make::expr_tuple(fields).clone_for_update();
+ let ast = make::expr_tuple(fields);
if let Some(mut mapping) = self.mappings() {
let mut builder = SyntaxMappingBuilder::new(ast.syntax().clone());
@@ -1094,7 +1081,7 @@ impl SyntaxFactory {
}
pub fn expr_assignment(&self, lhs: ast::Expr, rhs: ast::Expr) -> ast::BinExpr {
- let ast = make::expr_assignment(lhs.clone(), rhs.clone()).clone_for_update();
+ let ast = make::expr_assignment(lhs.clone(), rhs.clone());
if let Some(mut mapping) = self.mappings() {
let mut builder = SyntaxMappingBuilder::new(ast.syntax().clone());
@@ -1107,9 +1094,7 @@ impl SyntaxFactory {
}
pub fn expr_bin(&self, lhs: ast::Expr, op: ast::BinaryOp, rhs: ast::Expr) -> ast::BinExpr {
- let ast::Expr::BinExpr(ast) =
- make::expr_bin_op(lhs.clone(), op, rhs.clone()).clone_for_update()
- else {
+ let ast::Expr::BinExpr(ast) = make::expr_bin_op(lhs.clone(), op, rhs.clone()) else {
unreachable!()
};
@@ -1124,13 +1109,11 @@ impl SyntaxFactory {
}
pub fn expr_literal(&self, text: &str) -> ast::Literal {
- make::expr_literal(text).clone_for_update()
+ make::expr_literal(text)
}
pub fn expr_path(&self, path: ast::Path) -> ast::Expr {
- let ast::Expr::PathExpr(ast) = make::expr_path(path.clone()).clone_for_update() else {
- unreachable!()
- };
+ let ast::Expr::PathExpr(ast) = make::expr_path(path.clone()) else { unreachable!() };
if let Some(mut mapping) = self.mappings() {
let mut builder = SyntaxMappingBuilder::new(ast.syntax().clone());
@@ -1142,7 +1125,7 @@ impl SyntaxFactory {
}
pub fn expr_prefix(&self, op: SyntaxKind, expr: ast::Expr) -> ast::PrefixExpr {
- let ast = make::expr_prefix(op, expr.clone()).clone_for_update();
+ let ast = make::expr_prefix(op, expr.clone());
if let Some(mut mapping) = self.mappings() {
let mut builder = SyntaxMappingBuilder::new(ast.syntax().clone());
@@ -1154,7 +1137,7 @@ impl SyntaxFactory {
}
pub fn expr_call(&self, expr: ast::Expr, arg_list: ast::ArgList) -> ast::CallExpr {
- let ast = make::expr_call(expr.clone(), arg_list.clone()).clone_for_update();
+ let ast = make::expr_call(expr.clone(), arg_list.clone());
if let Some(mut mapping) = self.mappings() {
let mut builder = SyntaxMappingBuilder::new(ast.syntax().clone());
@@ -1172,8 +1155,7 @@ impl SyntaxFactory {
method: ast::NameRef,
arg_list: ast::ArgList,
) -> ast::MethodCallExpr {
- let ast = make::expr_method_call(receiver.clone(), method.clone(), arg_list.clone())
- .clone_for_update();
+ let ast = make::expr_method_call(receiver.clone(), method.clone(), arg_list.clone());
if let Some(mut mapping) = self.mappings() {
let mut builder = SyntaxMappingBuilder::new(ast.syntax().clone());
@@ -1188,7 +1170,7 @@ impl SyntaxFactory {
pub fn arg_list(&self, args: impl IntoIterator<Item = ast::Expr>) -> ast::ArgList {
let (args, input) = iterator_input(args);
- let ast = make::arg_list(args).clone_for_update();
+ let ast = make::arg_list(args);
if let Some(mut mapping) = self.mappings() {
let mut builder = SyntaxMappingBuilder::new(ast.syntax.clone());
@@ -1200,8 +1182,7 @@ impl SyntaxFactory {
}
pub fn expr_ref(&self, expr: ast::Expr, exclusive: bool) -> ast::Expr {
- let ast::Expr::RefExpr(ast) = make::expr_ref(expr.clone(), exclusive).clone_for_update()
- else {
+ let ast::Expr::RefExpr(ast) = make::expr_ref(expr.clone(), exclusive) else {
unreachable!()
};
@@ -1215,9 +1196,7 @@ impl SyntaxFactory {
}
pub fn expr_reborrow(&self, expr: ast::Expr) -> ast::Expr {
- let ast::Expr::RefExpr(ast) = make::expr_reborrow(expr.clone()).clone_for_update() else {
- unreachable!()
- };
+ let ast::Expr::RefExpr(ast) = make::expr_reborrow(expr.clone()) else { unreachable!() };
if let Some(mut mapping) = self.mappings() {
// Layout: RefExpr(&mut, PrefixExpr(*, expr)). Map `expr` to the
@@ -1236,9 +1215,7 @@ impl SyntaxFactory {
}
pub fn expr_raw_ref(&self, expr: ast::Expr, exclusive: bool) -> ast::Expr {
- let ast::Expr::RefExpr(ast) =
- make::expr_raw_ref(expr.clone(), exclusive).clone_for_update()
- else {
+ let ast::Expr::RefExpr(ast) = make::expr_raw_ref(expr.clone(), exclusive) else {
unreachable!()
};
@@ -1257,7 +1234,7 @@ impl SyntaxFactory {
expr: ast::Expr,
) -> ast::ClosureExpr {
let (args, input) = iterator_input(pats);
- let ast = make::expr_closure(args, expr.clone()).clone_for_update();
+ let ast = make::expr_closure(args, expr.clone());
if let Some(mut mapping) = self.mappings() {
let mut builder = SyntaxMappingBuilder::new(ast.syntax().clone());
@@ -1275,9 +1252,7 @@ impl SyntaxFactory {
}
pub fn expr_return(&self, expr: Option<ast::Expr>) -> ast::ReturnExpr {
- let ast::Expr::ReturnExpr(ast) = make::expr_return(expr.clone()).clone_for_update() else {
- unreachable!()
- };
+ let ast::Expr::ReturnExpr(ast) = make::expr_return(expr.clone()) else { unreachable!() };
if let Some(mut mapping) = self.mappings() {
let mut builder = SyntaxMappingBuilder::new(ast.syntax().clone());
@@ -1291,9 +1266,7 @@ impl SyntaxFactory {
}
pub fn expr_underscore(&self) -> ast::UnderscoreExpr {
- let ast::Expr::UnderscoreExpr(ast) = make::ext::expr_underscore().clone_for_update() else {
- unreachable!()
- };
+ let ast::Expr::UnderscoreExpr(ast) = make::ext::expr_underscore() else { unreachable!() };
ast
}
@@ -1304,8 +1277,7 @@ impl SyntaxFactory {
then_branch: ast::BlockExpr,
else_branch: Option<ast::ElseBranch>,
) -> ast::IfExpr {
- let ast = make::expr_if(condition.clone(), then_branch.clone(), else_branch.clone())
- .clone_for_update();
+ let ast = make::expr_if(condition.clone(), then_branch.clone(), else_branch.clone());
if let Some(mut mapping) = self.mappings() {
let mut builder = SyntaxMappingBuilder::new(ast.syntax().clone());
@@ -1328,9 +1300,7 @@ impl SyntaxFactory {
}
pub fn expr_loop(&self, body: ast::BlockExpr) -> ast::LoopExpr {
- let ast::Expr::LoopExpr(ast) = make::expr_loop(body.clone()).clone_for_update() else {
- unreachable!()
- };
+ let ast::Expr::LoopExpr(ast) = make::expr_loop(body.clone()) else { unreachable!() };
if let Some(mut mapping) = self.mappings() {
let mut builder = SyntaxMappingBuilder::new(ast.syntax().clone());
@@ -1342,7 +1312,7 @@ impl SyntaxFactory {
}
pub fn expr_while_loop(&self, condition: ast::Expr, body: ast::BlockExpr) -> ast::WhileExpr {
- let ast = make::expr_while_loop(condition.clone(), body.clone()).clone_for_update();
+ let ast = make::expr_while_loop(condition.clone(), body.clone());
if let Some(mut mapping) = self.mappings() {
let mut builder = SyntaxMappingBuilder::new(ast.syntax().clone());
@@ -1360,8 +1330,7 @@ impl SyntaxFactory {
iterable: ast::Expr,
body: ast::BlockExpr,
) -> ast::ForExpr {
- let ast =
- make::expr_for_loop(pat.clone(), iterable.clone(), body.clone()).clone_for_update();
+ let ast = make::expr_for_loop(pat.clone(), iterable.clone(), body.clone());
if let Some(mut mapping) = self.mappings() {
let mut builder = SyntaxMappingBuilder::new(ast.syntax().clone());
@@ -1375,7 +1344,7 @@ impl SyntaxFactory {
}
pub fn expr_let(&self, pattern: ast::Pat, expr: ast::Expr) -> ast::LetExpr {
- let ast = make::expr_let(pattern.clone(), expr.clone()).clone_for_update();
+ let ast = make::expr_let(pattern.clone(), expr.clone());
if let Some(mut mapping) = self.mappings() {
let mut builder = SyntaxMappingBuilder::new(ast.syntax().clone());
@@ -1388,7 +1357,7 @@ impl SyntaxFactory {
}
pub fn expr_stmt(&self, expr: ast::Expr) -> ast::ExprStmt {
- let ast = make::expr_stmt(expr.clone()).clone_for_update();
+ let ast = make::expr_stmt(expr.clone());
if let Some(mut mapping) = self.mappings() {
let mut builder = SyntaxMappingBuilder::new(ast.syntax().clone());
@@ -1400,7 +1369,7 @@ impl SyntaxFactory {
}
pub fn expr_match(&self, expr: ast::Expr, match_arm_list: ast::MatchArmList) -> ast::MatchExpr {
- let ast = make::expr_match(expr.clone(), match_arm_list.clone()).clone_for_update();
+ let ast = make::expr_match(expr.clone(), match_arm_list.clone());
if let Some(mut mapping) = self.mappings() {
let mut builder = SyntaxMappingBuilder::new(ast.syntax().clone());
@@ -1416,7 +1385,7 @@ impl SyntaxFactory {
}
pub fn expr_macro(&self, path: ast::Path, tt: ast::TokenTree) -> ast::MacroExpr {
- let ast = make::expr_macro(path.clone(), tt.clone()).clone_for_update();
+ let ast = make::expr_macro(path.clone(), tt.clone());
if let Some(mut mapping) = self.mappings() {
let macro_call = ast.macro_call().unwrap();
@@ -1436,7 +1405,7 @@ impl SyntaxFactory {
guard: Option<ast::MatchGuard>,
expr: ast::Expr,
) -> ast::MatchArm {
- let ast = make::match_arm(pat.clone(), guard.clone(), expr.clone()).clone_for_update();
+ let ast = make::match_arm(pat.clone(), guard.clone(), expr.clone());
if let Some(mut mapping) = self.mappings() {
let mut builder = SyntaxMappingBuilder::new(ast.syntax().clone());
@@ -1452,7 +1421,7 @@ impl SyntaxFactory {
}
pub fn match_guard(&self, condition: ast::Expr) -> ast::MatchGuard {
- let ast = make::match_guard(condition.clone()).clone_for_update();
+ let ast = make::match_guard(condition.clone());
if let Some(mut mapping) = self.mappings() {
let mut builder = SyntaxMappingBuilder::new(ast.syntax().clone());
@@ -1468,7 +1437,7 @@ impl SyntaxFactory {
match_arms: impl IntoIterator<Item = ast::MatchArm>,
) -> ast::MatchArmList {
let (match_arms, input) = iterator_input(match_arms);
- let ast = make::match_arm_list(match_arms).clone_for_update();
+ let ast = make::match_arm_list(match_arms);
if let Some(mut mapping) = self.mappings() {
let mut builder = SyntaxMappingBuilder::new(ast.syntax().clone());
@@ -1485,8 +1454,7 @@ impl SyntaxFactory {
ty: Option<ast::Type>,
initializer: Option<ast::Expr>,
) -> ast::LetStmt {
- let ast =
- make::let_stmt(pattern.clone(), ty.clone(), initializer.clone()).clone_for_update();
+ let ast = make::let_stmt(pattern.clone(), ty.clone(), initializer.clone());
if let Some(mut mapping) = self.mappings() {
let mut builder = SyntaxMappingBuilder::new(ast.syntax().clone());
@@ -1516,8 +1484,7 @@ impl SyntaxFactory {
ty.clone(),
initializer.clone(),
diverging.clone(),
- )
- .clone_for_update();
+ );
if let Some(mut mapping) = self.mappings() {
let mut builder = SyntaxMappingBuilder::new(ast.syntax().clone());
@@ -1537,7 +1504,7 @@ impl SyntaxFactory {
}
pub fn type_arg(&self, ty: ast::Type) -> ast::TypeArg {
- let ast = make::type_arg(ty.clone()).clone_for_update();
+ let ast = make::type_arg(ty.clone());
if let Some(mut mapping) = self.mappings() {
let mut builder = SyntaxMappingBuilder::new(ast.syntax().clone());
@@ -1549,7 +1516,7 @@ impl SyntaxFactory {
}
pub fn lifetime_arg(&self, lifetime: ast::Lifetime) -> ast::LifetimeArg {
- let ast = make::lifetime_arg(lifetime.clone()).clone_for_update();
+ let ast = make::lifetime_arg(lifetime.clone());
if let Some(mut mapping) = self.mappings() {
let mut builder = SyntaxMappingBuilder::new(ast.syntax().clone());
@@ -1570,8 +1537,7 @@ impl SyntaxFactory {
) -> ast::Const {
let (attrs, attrs_input) = iterator_input(attrs);
let ast =
- make::item_const(attrs, visibility.clone(), name.clone(), ty.clone(), expr.clone())
- .clone_for_update();
+ make::item_const(attrs, visibility.clone(), name.clone(), ty.clone(), expr.clone());
if let Some(mut mapping) = self.mappings() {
let mut builder = SyntaxMappingBuilder::new(ast.syntax().clone());
@@ -1607,8 +1573,7 @@ impl SyntaxFactory {
name.clone(),
ty.clone(),
expr.clone(),
- )
- .clone_for_update();
+ );
if let Some(mut mapping) = self.mappings() {
let mut builder = SyntaxMappingBuilder::new(ast.syntax().clone());
@@ -1651,9 +1616,9 @@ impl SyntaxFactory {
) -> ast::GenericArgList {
let (generic_args, input) = iterator_input(generic_args);
let ast = if is_turbo {
- make::turbofish_generic_arg_list(generic_args).clone_for_update()
+ make::turbofish_generic_arg_list(generic_args)
} else {
- make::generic_arg_list(generic_args).clone_for_update()
+ make::generic_arg_list(generic_args)
};
if let Some(mut mapping) = self.mappings() {
@@ -1670,7 +1635,7 @@ impl SyntaxFactory {
path: ast::Path,
fields: ast::RecordExprFieldList,
) -> ast::RecordExpr {
- let ast = make::record_expr(path.clone(), fields.clone()).clone_for_update();
+ let ast = make::record_expr(path.clone(), fields.clone());
if let Some(mut mapping) = self.mappings() {
let mut builder = SyntaxMappingBuilder::new(ast.syntax().clone());
builder.map_node(path.syntax().clone(), ast.path().unwrap().syntax().clone());
@@ -1688,7 +1653,7 @@ impl SyntaxFactory {
fields: impl IntoIterator<Item = ast::RecordExprField>,
) -> ast::RecordExprFieldList {
let (fields, input) = iterator_input(fields);
- let ast = make::record_expr_field_list(fields).clone_for_update();
+ let ast = make::record_expr_field_list(fields);
if let Some(mut mapping) = self.mappings() {
let mut builder = SyntaxMappingBuilder::new(ast.syntax().clone());
@@ -1704,7 +1669,7 @@ impl SyntaxFactory {
name: ast::NameRef,
expr: Option<ast::Expr>,
) -> ast::RecordExprField {
- let ast = make::record_expr_field(name.clone(), expr.clone()).clone_for_update();
+ let ast = make::record_expr_field(name.clone(), expr.clone());
if let Some(mut mapping) = self.mappings() {
let mut builder = SyntaxMappingBuilder::new(ast.syntax().clone());
@@ -1738,7 +1703,7 @@ impl SyntaxFactory {
fields: impl IntoIterator<Item = ast::RecordField>,
) -> ast::RecordFieldList {
let (fields, input) = iterator_input(fields);
- let ast = make::record_field_list(fields).clone_for_update();
+ let ast = make::record_field_list(fields);
if let Some(mut mapping) = self.mappings() {
let mut builder = SyntaxMappingBuilder::new(ast.syntax().clone());
@@ -1757,8 +1722,7 @@ impl SyntaxFactory {
name: ast::Name,
ty: ast::Type,
) -> ast::RecordField {
- let ast =
- make::record_field(visibility.clone(), name.clone(), ty.clone()).clone_for_update();
+ let ast = make::record_field(visibility.clone(), name.clone(), ty.clone());
if let Some(mut mapping) = self.mappings() {
let mut builder = SyntaxMappingBuilder::new(ast.syntax().clone());
@@ -1783,7 +1747,7 @@ impl SyntaxFactory {
fields: impl IntoIterator<Item = ast::TupleField>,
) -> ast::TupleFieldList {
let (fields, input) = iterator_input(fields);
- let ast = make::tuple_field_list(fields).clone_for_update();
+ let ast = make::tuple_field_list(fields);
if let Some(mut mapping) = self.mappings() {
let mut builder = SyntaxMappingBuilder::new(ast.syntax().clone());
@@ -1801,7 +1765,7 @@ impl SyntaxFactory {
visibility: Option<ast::Visibility>,
ty: ast::Type,
) -> ast::TupleField {
- let ast = make::tuple_field(visibility.clone(), ty.clone()).clone_for_update();
+ let ast = make::tuple_field(visibility.clone(), ty.clone());
if let Some(mut mapping) = self.mappings() {
let mut builder = SyntaxMappingBuilder::new(ast.syntax().clone());
@@ -1836,8 +1800,7 @@ impl SyntaxFactory {
generic_param_list.clone(),
where_clause.clone(),
variant_list.clone(),
- )
- .clone_for_update();
+ );
if let Some(mut mapping) = self.mappings() {
let mut builder = SyntaxMappingBuilder::new(ast.syntax().clone());
@@ -1880,7 +1843,7 @@ impl SyntaxFactory {
variants: impl IntoIterator<Item = ast::Variant>,
) -> ast::VariantList {
let (variants, input) = iterator_input(variants);
- let ast = make::variant_list(variants).clone_for_update();
+ let ast = make::variant_list(variants);
if let Some(mut mapping) = self.mappings() {
let mut builder = SyntaxMappingBuilder::new(ast.syntax().clone());
@@ -1905,8 +1868,7 @@ impl SyntaxFactory {
name.clone(),
field_list.clone(),
discriminant.clone(),
- )
- .clone_for_update();
+ );
if let Some(mut mapping) = self.mappings() {
let mut builder = SyntaxMappingBuilder::new(ast.syntax().clone());
@@ -2012,7 +1974,7 @@ impl SyntaxFactory {
) -> ast::AssocItemList {
let (items, input) = iterator_input(items);
let items_vec: Vec<_> = items.into_iter().collect();
- let ast = make::assoc_item_list(Some(items_vec)).clone_for_update();
+ let ast = make::assoc_item_list(Some(items_vec));
if let Some(mut mapping) = self.mappings() {
let mut builder = SyntaxMappingBuilder::new(ast.syntax().clone());
@@ -2024,13 +1986,13 @@ impl SyntaxFactory {
}
pub fn assoc_item_list_empty(&self) -> ast::AssocItemList {
- make::assoc_item_list(None).clone_for_update()
+ make::assoc_item_list(None)
}
pub fn item_list(&self, items: impl IntoIterator<Item = ast::Item>) -> ast::ItemList {
let (items, input) = iterator_input(items);
let items_vec: Vec<_> = items.into_iter().collect();
- let ast = make::item_list(Some(items_vec)).clone_for_update();
+ let ast = make::item_list(Some(items_vec));
if let Some(mut mapping) = self.mappings() {
let mut builder = SyntaxMappingBuilder::new(ast.syntax().clone());
@@ -2042,7 +2004,7 @@ impl SyntaxFactory {
}
pub fn mod_(&self, name: ast::Name, body: Option<ast::ItemList>) -> ast::Module {
- let ast = make::mod_(name.clone(), body.clone()).clone_for_update();
+ let ast = make::mod_(name.clone(), body.clone());
if let Some(mut mapping) = self.mappings() {
let mut builder = SyntaxMappingBuilder::new(ast.syntax().clone());
@@ -2057,7 +2019,7 @@ impl SyntaxFactory {
}
pub fn attr_outer(&self, meta: ast::Meta) -> ast::Attr {
- let ast = make::attr_outer(meta.clone()).clone_for_update();
+ let ast = make::attr_outer(meta.clone());
if let Some(mut mapping) = self.mappings() {
let mut builder = SyntaxMappingBuilder::new(ast.syntax().clone());
@@ -2069,7 +2031,7 @@ impl SyntaxFactory {
}
pub fn attr_inner(&self, meta: ast::Meta) -> ast::Attr {
- let ast = make::attr_inner(meta.clone()).clone_for_update();
+ let ast = make::attr_inner(meta.clone());
if let Some(mut mapping) = self.mappings() {
let mut builder = SyntaxMappingBuilder::new(ast.syntax().clone());
@@ -2081,7 +2043,7 @@ impl SyntaxFactory {
}
pub fn meta_token_tree(&self, path: ast::Path, tt: ast::TokenTree) -> ast::Meta {
- let ast = make::meta_token_tree(path.clone(), tt.clone()).clone_for_update();
+ let ast = make::meta_token_tree(path.clone(), tt.clone());
if let Some(mut mapping) = self.mappings() {
let mut builder = SyntaxMappingBuilder::new(ast.syntax().clone());
@@ -2095,7 +2057,7 @@ impl SyntaxFactory {
}
pub fn cfg_flag(&self, flag: &str) -> ast::CfgPredicate {
- make::cfg_flag(flag).clone_for_update()
+ make::cfg_flag(flag)
}
pub fn cfg_attr_meta(
@@ -2104,7 +2066,7 @@ impl SyntaxFactory {
inner: impl IntoIterator<Item = ast::Meta>,
) -> ast::CfgAttrMeta {
let inner = Vec::from_iter(inner);
- let ast = make::cfg_attr_meta(predicate.clone(), inner.iter().cloned()).clone_for_update();
+ let ast = make::cfg_attr_meta(predicate.clone(), inner.iter().cloned());
if let Some(mut mapping) = self.mappings() {
let mut builder = SyntaxMappingBuilder::new(ast.syntax().clone());
@@ -2130,7 +2092,7 @@ impl SyntaxFactory {
let tt: Vec<_> = tt.into_iter().collect();
let input: Vec<_> = tt.iter().cloned().filter_map(only_nodes).collect();
- let ast = make::token_tree(delimiter, tt).clone_for_update();
+ let ast = make::token_tree(delimiter, tt);
if let Some(mut mapping) = self.mappings() {
let mut builder = SyntaxMappingBuilder::new(ast.syntax().clone());
@@ -2158,7 +2120,7 @@ impl SyntaxFactory {
}
pub fn mut_self_param(&self) -> ast::SelfParam {
- let ast = make::mut_self_param().clone_for_update();
+ let ast = make::mut_self_param();
if let Some(mut mapping) = self.mappings() {
let builder = SyntaxMappingBuilder::new(ast.syntax().clone());
@@ -2169,7 +2131,7 @@ impl SyntaxFactory {
}
pub fn self_param(&self) -> ast::SelfParam {
- let ast = make::self_param().clone_for_update();
+ let ast = make::self_param();
if let Some(mut mapping) = self.mappings() {
let builder = SyntaxMappingBuilder::new(ast.syntax().clone());
@@ -2196,8 +2158,7 @@ impl SyntaxFactory {
path_type.clone(),
where_clause.clone(),
body.clone(),
- )
- .clone_for_update();
+ );
if let Some(mut mapping) = self.mappings() {
let mut builder = SyntaxMappingBuilder::new(ast.syntax().clone());
@@ -2241,8 +2202,7 @@ impl SyntaxFactory {
generic_param_list.clone(),
where_clause.clone(),
assoc_items.clone(),
- )
- .clone_for_update();
+ );
if let Some(mut mapping) = self.mappings() {
let mut builder = SyntaxMappingBuilder::new(ast.syntax().clone());
@@ -2269,7 +2229,7 @@ impl SyntaxFactory {
}
pub fn ret_type(&self, ty: ast::Type) -> ast::RetType {
- let ast = make::ret_type(ty.clone()).clone_for_update();
+ let ast = make::ret_type(ty.clone());
if let Some(mut mapping) = self.mappings() {
let mut builder = SyntaxMappingBuilder::new(ast.syntax().clone());
@@ -2280,7 +2240,7 @@ impl SyntaxFactory {
}
pub fn ty_ref(&self, ty: ast::Type, is_mut: bool) -> ast::Type {
- let ast = make::ty_ref(ty.clone(), is_mut).clone_for_update();
+ let ast = make::ty_ref(ty.clone(), is_mut);
if let Some(mut mapping) = self.mappings() {
let mut builder = SyntaxMappingBuilder::new(ast.syntax().clone());
@@ -2303,7 +2263,7 @@ impl SyntaxFactory {
}
pub fn ty_name(&self, name: ast::Name) -> ast::Type {
- let ast = make::ext::ty_name(name.clone()).clone_for_update();
+ let ast = make::ext::ty_name(name.clone());
if let Some(mut mapping) = self.mappings()
&& let ast::Type::PathType(path_ty) = &ast
@@ -2318,9 +2278,7 @@ impl SyntaxFactory {
}
pub fn expr_await(&self, expr: ast::Expr) -> ast::AwaitExpr {
- let ast::Expr::AwaitExpr(ast) = make::expr_await(expr.clone()).clone_for_update() else {
- unreachable!()
- };
+ let ast::Expr::AwaitExpr(ast) = make::expr_await(expr.clone()) else { unreachable!() };
if let Some(mut mapping) = self.mappings() {
let mut builder = SyntaxMappingBuilder::new(ast.syntax().clone());
@@ -2332,7 +2290,7 @@ impl SyntaxFactory {
}
pub fn expr_try(&self, expr: ast::Expr) -> ast::Expr {
- let ast = make::expr_try(expr.clone()).clone_for_update();
+ let ast = make::expr_try(expr.clone());
if let Some(mut mapping) = self.mappings() {
let mut builder = SyntaxMappingBuilder::new(ast.syntax().clone());
@@ -2353,8 +2311,7 @@ impl SyntaxFactory {
tail_expr: Option<ast::Expr>,
) -> ast::BlockExpr {
let elements = elements.into_iter().collect::<Vec<_>>();
- let ast =
- make::hacky_block_expr(elements.iter().cloned(), tail_expr.clone()).clone_for_update();
+ let ast = make::hacky_block_expr(elements.iter().cloned(), tail_expr.clone());
if let Some(mut mapping) = self.mappings()
&& let Some(stmt_list) = ast.stmt_list()
@@ -2379,9 +2336,7 @@ impl SyntaxFactory {
}
pub fn expr_break(&self, label: Option<Lifetime>, expr: Option<ast::Expr>) -> ast::BreakExpr {
- let ast::Expr::BreakExpr(ast) =
- make::expr_break(label.clone(), expr.clone()).clone_for_update()
- else {
+ let ast::Expr::BreakExpr(ast) = make::expr_break(label.clone(), expr.clone()) else {
unreachable!()
};
@@ -2400,8 +2355,7 @@ impl SyntaxFactory {
}
pub fn expr_continue(&self, label: Option<Lifetime>) -> ast::ContinueExpr {
- let ast::Expr::ContinueExpr(ast) = make::expr_continue(label.clone()).clone_for_update()
- else {
+ let ast::Expr::ContinueExpr(ast) = make::expr_continue(label.clone()) else {
unreachable!()
};
@@ -2427,11 +2381,11 @@ impl SyntaxFactory {
&self,
parts: impl IntoIterator<Item = &'a str>,
) -> Option<ast::Path> {
- make::ext::path_from_idents(parts).map(|path| path.clone_for_update())
+ make::ext::path_from_idents(parts)
}
pub fn token_tree_from_node(&self, node: &SyntaxNode) -> ast::TokenTree {
- make::ext::token_tree_from_node(node).clone_for_update()
+ make::ext::token_tree_from_node(node)
}
pub fn expr_unit(&self) -> ast::Expr {
diff --git a/crates/syntax/src/syntax_editor.rs b/crates/syntax/src/syntax_editor.rs
index 7d15195c6f..3ddc791476 100644
--- a/crates/syntax/src/syntax_editor.rs
+++ b/crates/syntax/src/syntax_editor.rs
@@ -1,6 +1,6 @@
//! Syntax Tree editor
//!
-//! Inspired by Roslyn's [`SyntaxEditor`], but is temporarily built upon mutable syntax tree editing.
+//! Inspired by Roslyn's [`SyntaxEditor`].
//!
//! [`SyntaxEditor`]: https://github.com/dotnet/roslyn/blob/43b0b05cc4f492fd5de00f6f6717409091df8daa/src/Workspaces/Core/Portable/Editing/SyntaxEditor.cs
@@ -39,13 +39,12 @@ impl SyntaxEditor {
/// Creates a syntax editor from `root`.
///
/// The returned `root` is guaranteed to be a detached, immutable node.
- /// If the provided node is not a root (i.e., has a parent) or is already
- /// mutable, it is cloned into a fresh subtree to satisfy syntax editor
- /// invariants.
+ /// If the provided node is not a root (i.e., has a parent), it is cloned
+ /// into a fresh subtree to satisfy syntax editor invariants.
pub fn new(root: SyntaxNode) -> (Self, SyntaxNode) {
let mut root = root;
- if root.parent().is_some() || root.is_mutable() {
+ if root.parent().is_some() {
root = root.clone_subtree()
};
@@ -603,7 +602,7 @@ mod tests {
let to_replace = root.syntax().descendants().find_map(ast::BinExpr::cast).unwrap();
let name = make::name("var_name");
- let name_ref = make::name_ref("var_name").clone_for_update();
+ let name_ref = make::name_ref("var_name");
let placeholder_snippet = SyntaxAnnotation::default();
editor.add_annotation(name.syntax(), placeholder_snippet);
@@ -884,7 +883,7 @@ mod tests {
}
#[test]
- fn test_more_times_replace_node_to_mutable_token() {
+ fn test_more_times_replace_node_to_same_token() {
let arg_list =
make::arg_list([make::expr_literal("1").into(), make::expr_literal("2").into()]);
@@ -903,13 +902,13 @@ mod tests {
}
#[test]
- fn test_more_times_replace_node_to_mutable() {
+ fn test_more_times_replace_node_to_same_node() {
let arg_list =
make::arg_list([make::expr_literal("1").into(), make::expr_literal("2").into()]);
let (editor, arg_list) = SyntaxEditor::with_ast_node(&arg_list);
- let target_expr = make::expr_literal("3").clone_for_update();
+ let target_expr = make::expr_literal("3");
for arg in arg_list.args() {
editor.replace(arg.syntax(), target_expr.syntax());
@@ -922,13 +921,13 @@ mod tests {
}
#[test]
- fn test_more_times_insert_node_to_mutable() {
+ fn test_more_times_insert_node_to_same_node() {
let arg_list =
make::arg_list([make::expr_literal("1").into(), make::expr_literal("2").into()]);
let (editor, arg_list) = SyntaxEditor::with_ast_node(&arg_list);
- let target_expr = make::ext::expr_unit().clone_for_update();
+ let target_expr = make::ext::expr_unit();
for arg in arg_list.args() {
editor.insert(Position::before(arg.syntax()), target_expr.syntax());
diff --git a/crates/syntax/src/syntax_editor/edit_algo.rs b/crates/syntax/src/syntax_editor/edit_algo.rs
index 36f50e3918..d24d9b1334 100644
--- a/crates/syntax/src/syntax_editor/edit_algo.rs
+++ b/crates/syntax/src/syntax_editor/edit_algo.rs
@@ -1,415 +1,700 @@
//! Implementation of applying changes to a syntax tree.
-use std::{
- cmp::Ordering,
- collections::VecDeque,
- ops::{Range, RangeInclusive},
-};
+use std::{cmp::Ordering, ops::Range};
use rowan::TextRange;
use rustc_hash::FxHashMap;
use stdx::format_to;
-use crate::{
- SyntaxElement, SyntaxNode, SyntaxNodePtr,
- syntax_editor::{Change, ChangeKind, PositionRepr, mapping::MissingMapping},
-};
-
-use super::{SyntaxEdit, SyntaxEditor};
+use crate::{NodeOrToken, SyntaxElement, SyntaxNode};
-pub(super) fn apply_edits(editor: SyntaxEditor) -> SyntaxEdit {
- // Algorithm overview:
- //
- // - Sort changes by (range, type)
- // - Ensures that parent edits are before child edits
- // - Ensures that inserts will be guaranteed to be inserted at the right range
- // - Validate changes
- // - Checking for invalid changes is easy since the changes will be sorted by range
- // - Fixup change targets
- // - standalone change? map to original syntax tree
- // - dependent change?
- // - try to map to parent change (either independent or another dependent)
- // - note: need to keep track of a parent change stack, since a change can be a parent of multiple changes
- // - Apply changes
- // - find changes to apply to real tree by applying nested changes first
- // - changed nodes become part of the changed node set (useful for the formatter to only change those parts)
- // - Propagate annotations
+use super::{
+ Change, ChangeKind, PositionRepr, SyntaxAnnotation, SyntaxEdit, SyntaxEditor, SyntaxMapping,
+ mapping::MissingMapping,
+};
- let SyntaxEditor { root, changes, annotations, make } = editor;
- let mut changes = changes.into_inner();
- let annotations = annotations.into_inner();
- let mappings = make.take();
+/// A validated batch of changes in the exact order in which it must execute.
+///
+/// Planning is deliberately separate from tree mutation. Once an `EditPlan`
+/// exists, execution does not need to reason about overlaps, dependencies, or
+/// source ordering.
+struct EditPlan {
+ changes: Vec<PlannedChange>,
+}
- let mut node_depths = FxHashMap::<SyntaxNode, usize>::default();
- let mut get_node_depth = |node: SyntaxNode| {
- *node_depths.entry(node).or_insert_with_key(|node| node.ancestors().count())
- };
+/// A change whose target tree and output tracking are fully known.
+struct PlannedChange {
+ tree: SyntaxNode,
+ change: Change,
+ record_as_changed: bool,
+}
- // Sort changes by range, then depth, then change kind, so that we can:
- // - ensure that parent edits are ordered before child edits
- // - ensure that inserts will be guaranteed to be inserted at the right range
- // - easily check for disjoint replace ranges
- changes.sort_by(|a, b| {
- a.target_range()
- .start()
- .cmp(&b.target_range().start())
- .then_with(|| {
- let a_target = a.target_parent();
- let b_target = b.target_parent();
+impl PlannedChange {
+ /// Returns the immutable source elements that this change will slice in.
+ fn replacement_elements(&self) -> &[SyntaxElement] {
+ match &self.change {
+ Change::Insert(_, element) | Change::Replace(_, Some(element)) => {
+ std::slice::from_ref(element)
+ }
+ Change::InsertAll(_, elements)
+ | Change::ReplaceWithMany(_, elements)
+ | Change::ReplaceAll(_, elements) => elements,
+ Change::Replace(_, None) => &[],
+ }
+ }
+}
- if a_target == b_target {
- return Ordering::Equal;
- }
+/// The dependency info accumulated from one source ordered changes.
+///
+/// `parent` is an edge to the nearest containing node replacement. A discarded
+/// entry has no executable graph node because an ancestor deletion or ambiguous
+/// range replacement has mde its target unavailable.
+#[derive(Clone, Copy, Default)]
+struct PlanEntry {
+ parent: Option<usize>,
+ discarded: bool,
+}
- get_node_depth(a_target).cmp(&get_node_depth(b_target))
- })
- .then(a.change_kind().cmp(&b.change_kind()))
- });
+/// Planning failure containing the source-ordered changes use for diag.
+struct InvalidEditPlan {
+ changes: Vec<Change>,
+}
- let disjoint_replaces_ranges = changes
- .iter()
- .zip(changes.iter().skip(1))
- .filter(|(l, r)| {
- // We only care about checking for disjoint replace ranges
- matches!(
- (l.change_kind(), r.change_kind()),
- (
- ChangeKind::Replace | ChangeKind::ReplaceRange,
- ChangeKind::Replace | ChangeKind::ReplaceRange
- )
- )
- })
- .all(|(l, r)| {
- get_node_depth(l.target_parent()) != get_node_depth(r.target_parent())
- || (l.target_range().end() <= r.target_range().start())
+impl EditPlan {
+ /// Validates raw editor changes and turns them into an execution schedule.
+ ///
+ /// The input is first sorted in source order, dependent targets are then
+ /// rewritten from their input trees into ancestor replacement trees. Finally,
+ /// discarded changes are removed and the dependency forest is traversed in
+ /// postorder.
+ /// Independent roots and sibling changes are prioritized right to left.
+ fn build(
+ mut changes: Vec<Change>,
+ mappings: &SyntaxMapping,
+ mut node_depth: impl FnMut(SyntaxNode) -> usize,
+ ) -> Result<Self, InvalidEditPlan> {
+ changes.sort_by(|left, right| {
+ left.target_range()
+ .start()
+ .cmp(&right.target_range().start())
+ .then_with(|| {
+ let left_target = left.target_parent();
+ let right_target = right.target_parent();
+ if left_target == right_target {
+ Ordering::Equal
+ } else {
+ node_depth(left_target).cmp(&node_depth(right_target))
+ }
+ })
+ .then(left.change_kind().cmp(&right.change_kind()))
});
- if !disjoint_replaces_ranges {
- report_intersecting_changes(&changes, get_node_depth, &root);
+ if !Self::replacements_are_disjoint(&changes, &mut node_depth) {
+ return Err(InvalidEditPlan { changes });
+ }
- return SyntaxEdit {
- old_root: root.clone(),
- new_root: root,
- annotations: Default::default(),
- changed_elements: vec![],
- };
- }
+ let mut entries = vec![PlanEntry::default(); changes.len()];
+ let mut regions_by_tree = FxHashMap::<SyntaxNode, Vec<ChangedRegion>>::default();
+
+ for (index, change) in changes.iter().enumerate() {
+ let target_tree = change.target_parent().tree_top();
+ let regions = regions_by_tree.entry(target_tree).or_default();
+ if let Some(region_index) = regions
+ .iter()
+ .rposition(|region| region.range.contains_range(change.target_range()))
+ {
+ regions.truncate(region_index + 1);
+ match regions[region_index].nested_changes {
+ NestedChanges::Remap => {
+ entries[index].parent = Some(regions[region_index].change_index);
+ }
+ NestedChanges::Discard => entries[index].discarded = true,
+ }
+ } else {
+ regions.clear();
+ }
- #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
- struct DependentChange {
- parent: u32,
- child: u32,
- }
+ if let Some(region) = ChangedRegion::for_change(change, index, entries[index].discarded)
+ {
+ regions.push(region);
+ }
+ }
- // Build change tree
- let mut changed_ancestors: VecDeque<ChangedAncestor> = VecDeque::new();
- let mut dependent_changes = vec![];
- let mut independent_changes = vec![];
- let mut outdated_changes = vec![];
+ // Work from the innermost dependency towards the outermost one. This
+ // lets a chain A -> B -> C rewrite C into B before B itself is mapped
+ // into A's replacement tree.
+ for (child, entry) in entries.iter().enumerate().rev() {
+ if let Some(parent) = entry.parent {
+ Self::rewrite_dependent_target(&mut changes, parent, child, mappings);
+ }
+ }
- for (change_index, change) in changes.iter().enumerate() {
- // Check if this change is dependent on another change (i.e. it's contained within another range)
- if let Some(index) = changed_ancestors
+ let mut children = vec![Vec::new(); changes.len()];
+ for (child, entry) in entries.iter().enumerate() {
+ if let Some(parent) = entry.parent {
+ children[parent].push(child);
+ }
+ }
+ for siblings in &mut children {
+ siblings.sort_by(|&left, &right| {
+ Self::execution_priority(&changes[left], &changes[right], &mut node_depth)
+ });
+ }
+
+ let mut roots = entries
.iter()
- .rposition(|ancestor| ancestor.affected_range().contains_range(change.target_range()))
- {
- // Pop off any ancestors that aren't applicable
- changed_ancestors.drain((index + 1)..);
+ .enumerate()
+ .filter_map(|(index, entry)| {
+ (!entry.discarded && entry.parent.is_none()).then_some(index)
+ })
+ .collect::<Vec<_>>();
+ roots.sort_by(|&left, &right| {
+ Self::execution_priority(&changes[left], &changes[right], &mut node_depth)
+ });
- // FIXME: Resolve changes that depend on a range of elements
- let ancestor = &changed_ancestors[index];
+ let mut planned = changes
+ .into_iter()
+ .zip(entries)
+ .map(|(change, entry)| {
+ (!entry.discarded).then_some(PlannedChange {
+ tree: change.target_parent().tree_top(),
+ change,
+ record_as_changed: entry.parent.is_none(),
+ })
+ })
+ .collect::<Vec<_>>();
- if let Change::Replace(_, None) = changes[ancestor.change_index] {
- outdated_changes.push(change_index as u32);
- } else {
- dependent_changes.push(DependentChange {
- parent: ancestor.change_index as u32,
- child: change_index as u32,
- });
- }
- } else {
- // This change is independent of any other change
+ let mut ordered = Vec::new();
+ for root in roots {
+ Self::append_postorder(root, &children, &mut planned, &mut ordered);
+ }
+
+ Ok(Self { changes: ordered })
+ }
- // Drain the changed ancestors since we're no longer in a set of dependent changes
- changed_ancestors.drain(..);
+ /// Orders disjoint changes from right to left, with deeper ties first.
+ fn execution_priority(
+ left: &Change,
+ right: &Change,
+ node_depth: &mut impl FnMut(SyntaxNode) -> usize,
+ ) -> Ordering {
+ right
+ .target_range()
+ .start()
+ .cmp(&left.target_range().start())
+ .then_with(|| node_depth(right.target_parent()).cmp(&node_depth(left.target_parent())))
+ .then(right.change_kind().cmp(&left.change_kind()))
+ }
- independent_changes.push(change_index as u32);
+ /// Appends a dependency subtree in post order fashion.
+ fn append_postorder(
+ index: usize,
+ children: &[Vec<usize>],
+ planned: &mut [Option<PlannedChange>],
+ ordered: &mut Vec<PlannedChange>,
+ ) {
+ for &child in &children[index] {
+ Self::append_postorder(child, children, planned, ordered);
}
+ ordered.push(planned[index].take().expect("reachable plan nodes are not discarded"));
+ }
- // Add to changed ancestors, if applicable
- match change {
- Change::Replace(SyntaxElement::Node(target), _)
- | Change::ReplaceWithMany(SyntaxElement::Node(target), _) => {
- changed_ancestors.push_back(ChangedAncestor::single(target, change_index))
+ /// Checks that replacement at the same tree depth do not overlap
+ ///
+ /// `changes` is sorted by range start, so overlap is a single comparison against the
+ /// last range at that key, and `insert` can throw away the range it evicts.
+ fn replacements_are_disjoint(
+ changes: &[Change],
+ mut node_depth: impl FnMut(SyntaxNode) -> usize,
+ ) -> bool {
+ let mut previous = FxHashMap::<(SyntaxNode, usize), TextRange>::default();
+ for change in changes {
+ if !matches!(change.change_kind(), ChangeKind::Replace | ChangeKind::ReplaceRange) {
+ continue;
}
- Change::ReplaceAll(range, _) => {
- changed_ancestors.push_back(ChangedAncestor::multiple(range, change_index))
+
+ let parent = change.target_parent();
+ let key = (parent.tree_top(), node_depth(parent));
+ if previous
+ .insert(key, change.target_range())
+ .is_some_and(|range| range.end() > change.target_range().start())
+ {
+ return false;
}
- _ => (),
}
+ true
}
- // Map change targets to the correct syntax nodes
- let tree_mutator = TreeMutator::new(&root);
- let mut changed_elements = vec![];
- let mut changed_elements_set = rustc_hash::FxHashSet::default();
- let mut deduplicate_node = |node_or_token: &mut SyntaxElement| {
- let node;
- let node = match node_or_token {
- SyntaxElement::Token(token) => match token.parent() {
- None => return,
- Some(parent) => {
- node = parent;
- &node
- }
- },
- SyntaxElement::Node(node) => node,
+ /// Maps one dependent change into its ancestor replacement tree.
+ fn rewrite_dependent_target(
+ changes: &mut [Change],
+ parent: usize,
+ child: usize,
+ mappings: &SyntaxMapping,
+ ) {
+ let (input_ancestor, output_ancestor) = match &changes[parent] {
+ Change::Replace(
+ SyntaxElement::Node(target),
+ Some(SyntaxElement::Node(replacement)),
+ ) => (target.clone(), replacement.clone()),
+ _ => unreachable!("only node replacements can own dependent changes"),
};
- if changed_elements_set.contains(node) {
- let new_node = node.clone_subtree().clone_for_update();
- match node_or_token {
- SyntaxElement::Node(node) => *node = new_node,
- SyntaxElement::Token(token) => {
- *token = new_node
- .children_with_tokens()
- .filter_map(SyntaxElement::into_token)
- .find(|it| it.kind() == token.kind() && it.text() == token.text())
- .unwrap();
- }
- }
- } else {
- changed_elements_set.insert(node.clone());
- }
- };
- for index in independent_changes {
- match &mut changes[index as usize] {
- Change::Insert(target, _) | Change::InsertAll(target, _) => {
- match &mut target.repr {
- PositionRepr::FirstChild(parent) => {
- *parent = tree_mutator.make_syntax_mut(parent);
- }
- PositionRepr::After(child) => {
- *child = tree_mutator.make_element_mut(child);
- }
- };
- }
- Change::Replace(SyntaxElement::Node(target), Some(SyntaxElement::Node(_))) => {
- *target = tree_mutator.make_syntax_mut(target);
+ let upmap_node = |target: &SyntaxNode| {
+ mappings.upmap_child(target, &input_ancestor, &output_ancestor).unwrap_or_else(
+ |MissingMapping(current)| {
+ panic!(
+ "no mappings exist between {current:?} (ancestor of {input_ancestor:?}) and {output_ancestor:?}"
+ )
+ },
+ )
+ };
+ let upmap_element = |target: &SyntaxElement| {
+ mappings.upmap_child_element(target, &input_ancestor, &output_ancestor).unwrap_or_else(
+ |MissingMapping(current)| {
+ panic!(
+ "no mappings exist between {current:?} (ancestor of {input_ancestor:?}) and {output_ancestor:?}"
+ )
+ },
+ )
+ };
+
+ match &mut changes[child] {
+ Change::Insert(position, _) | Change::InsertAll(position, _) => {
+ match &mut position.repr {
+ PositionRepr::FirstChild(parent) => *parent = upmap_node(parent),
+ PositionRepr::After(child) => *child = upmap_element(child),
+ }
}
Change::Replace(target, _) | Change::ReplaceWithMany(target, _) => {
- *target = tree_mutator.make_element_mut(target);
+ *target = upmap_element(target);
}
Change::ReplaceAll(range, _) => {
- let start = tree_mutator.make_element_mut(range.start());
- let end = tree_mutator.make_element_mut(range.end());
-
- *range = start..=end;
+ *range = upmap_element(range.start())..=upmap_element(range.end());
}
}
+ }
+}
- match &mut changes[index as usize] {
- Change::Insert(_, SyntaxElement::Node(node))
- | Change::Replace(_, Some(SyntaxElement::Node(node))) => {
- if node.parent().is_some() {
- *node = node.clone_subtree().clone_for_update();
- } else if !node.is_mutable() {
- *node = node.clone_for_update();
- }
- }
- Change::Insert(_, SyntaxElement::Token(token))
- | Change::Replace(_, Some(SyntaxElement::Token(token))) => {
- if let Some(parent) = token.parent() {
- let idx = token.index();
- let new_parent = parent.clone_subtree().clone_for_update();
- *token = new_parent
- .children_with_tokens()
- .nth(idx)
- .and_then(SyntaxElement::into_token)
- .unwrap();
- }
- }
- Change::InsertAll(_, elements)
- | Change::ReplaceWithMany(_, elements)
- | Change::ReplaceAll(_, elements) => {
- for element in elements {
- match element {
- SyntaxElement::Node(node) => {
- if node.parent().is_some() {
- *node = node.clone_subtree().clone_for_update();
- } else if !node.is_mutable() {
- *node = node.clone_for_update();
- }
- }
- SyntaxElement::Token(token) => {
- if let Some(parent) = token.parent() {
- let idx = token.index();
- let new_parent = parent.clone_subtree().clone_for_update();
- *token = new_parent
- .children_with_tokens()
- .nth(idx)
- .and_then(SyntaxElement::into_token)
- .unwrap();
- }
- }
- }
- }
- }
- _ => {}
- }
+/// A stable structural address expressed as `children_with_token` indices.
+#[derive(Clone)]
+struct SyntaxPath {
+ child_indices: Vec<usize>,
+}
- match &mut changes[index as usize] {
- Change::Insert(_, element) | Change::Replace(_, Some(element)) => {
- deduplicate_node(element);
- }
- Change::InsertAll(_, elements)
- | Change::ReplaceWithMany(_, elements)
- | Change::ReplaceAll(_, elements) => {
- elements.iter_mut().for_each(&mut deduplicate_node);
+impl SyntaxPath {
+ /// Builds the root-relative path of element in its current tree.
+ fn new(element: &SyntaxElement) -> Self {
+ let mut child_indices = Vec::new();
+ let mut node = match element {
+ SyntaxElement::Node(node) => node.clone(),
+ SyntaxElement::Token(token) => {
+ child_indices.push(token.index());
+ token.parent().unwrap()
}
- Change::Replace(_, None) => (),
+ };
+
+ while let Some(parent) = node.parent() {
+ child_indices.push(node.index());
+ node = parent;
}
+ child_indices.reverse();
+ Self { child_indices }
+ }
- // Collect changed elements
- match &changes[index as usize] {
- Change::Insert(_, element) => changed_elements.push(element.clone()),
- Change::InsertAll(_, elements) => changed_elements.extend(elements.iter().cloned()),
- Change::Replace(_, Some(element)) => changed_elements.push(element.clone()),
- Change::Replace(_, None) => {}
- Change::ReplaceWithMany(_, elements) => {
- changed_elements.extend(elements.iter().cloned())
- }
- Change::ReplaceAll(_, elements) => changed_elements.extend(elements.iter().cloned()),
+ /// Follows this path from root, returning None if the structure differs.
+ fn resolve(&self, root: &SyntaxNode) -> Option<SyntaxElement> {
+ let mut current = SyntaxElement::Node(root.clone());
+ for &index in &self.child_indices {
+ current = current.into_node()?.children_with_tokens().nth(index)?;
}
+ Some(current)
}
- for DependentChange { parent, child } in dependent_changes.into_iter().rev() {
- let (input_ancestor, output_ancestor) = match &changes[parent as usize] {
- // No change will depend on an insert since changes can only depend on nodes in the root tree
- Change::Insert(_, _) | Change::InsertAll(_, _) => unreachable!(),
- Change::Replace(target, Some(new_target)) => {
- (to_owning_node(target), to_owning_node(new_target))
- }
- Change::Replace(_, None) => {
- unreachable!("deletions should not generate dependent changes")
- }
- Change::ReplaceAll(_, _) | Change::ReplaceWithMany(_, _) => {
- unimplemented!("cannot resolve changes that depend on replacing many elements")
- }
- };
+ /// Removes `ancestor`'s prefix, yielding this path within that subtree.
+ ///
+ /// Could have used LCA?
+ fn relative_to(&self, ancestor: &SyntaxPath) -> Option<SyntaxPath> {
+ self.child_indices
+ .strip_prefix(ancestor.child_indices.as_slice())
+ .map(|relative| SyntaxPath { child_indices: relative.to_vec() })
+ }
- let upmap_target_node = |target: &SyntaxNode| match mappings.upmap_child(
- target,
- &input_ancestor,
- &output_ancestor,
- ) {
- Ok(it) => it,
- Err(MissingMapping(current)) => unreachable!(
- "no mappings exist between {current:?} (ancestor of {input_ancestor:?}) and {output_ancestor:?}"
- ),
- };
+ /// Appends an inserted child slot and a path relative to that child.
+ fn in_child(&self, index: usize, relative: &SyntaxPath) -> SyntaxPath {
+ let mut child_indices =
+ Vec::with_capacity(self.child_indices.len() + relative.child_indices.len() + 1);
+ child_indices.extend_from_slice(&self.child_indices);
+ child_indices.push(index);
+ child_indices.extend_from_slice(&relative.child_indices);
+ SyntaxPath { child_indices }
+ }
- let upmap_target = |target: &SyntaxElement| match mappings.upmap_child_element(
- target,
- &input_ancestor,
- &output_ancestor,
- ) {
- Ok(it) => it,
- Err(MissingMapping(current)) => unreachable!(
- "no mappings exist between {current:?} (ancestor of {input_ancestor:?}) and {output_ancestor:?}"
- ),
+ /// Updates this path for a splice and reports whether its element survives.
+ fn adjust_for_splice(
+ &mut self,
+ parent: &SyntaxPath,
+ deleted: &Range<usize>,
+ inserted: usize,
+ ) -> bool {
+ let Some(relative) = self.child_indices.strip_prefix(parent.child_indices.as_slice())
+ else {
+ return true;
};
+ let Some((&child, _)) = relative.split_first() else { return true };
- match &mut changes[child as usize] {
- Change::Insert(target, _) | Change::InsertAll(target, _) => match &mut target.repr {
- PositionRepr::FirstChild(parent) => {
- *parent = upmap_target_node(parent);
- }
- PositionRepr::After(child) => {
- *child = upmap_target(child);
+ if deleted.contains(&child) {
+ return false;
+ }
+ if child >= deleted.end {
+ let new_child = child + inserted;
+ self.child_indices[parent.child_indices.len()] =
+ new_child - (deleted.end - deleted.start);
+ }
+ true
+ }
+}
+
+/// An annotation paired with its structural location and registration order.
+#[derive(Clone)]
+struct TrackedAnnotation {
+ path: SyntaxPath,
+ annotation: SyntaxAnnotation,
+ order: usize,
+}
+
+/// A structural edit used to translate original paths into a current tree.
+enum PathEdit {
+ /// A child-list splice with all coordinates relative to the pre-edit tree.
+ Splice { parent: SyntaxPath, deleted: Range<usize>, inserted: usize },
+ /// A root replacement, after which no path into the old root survives.
+ ReplaceRoot,
+}
+
+/// The evolving immutable root and location metadata for one source tree.
+///
+/// A syntax edit can involve the editor root plus several detached factory
+/// trees. Each receives an independent state so dependent edits can be applied
+/// before a generated tree is inserted elsewhere.
+struct TreeState {
+ root: SyntaxNode,
+ edits: Vec<PathEdit>,
+ changed: Vec<SyntaxPath>,
+ original_annotations: Vec<TrackedAnnotation>,
+ annotations: Vec<TrackedAnnotation>,
+}
+
+impl TreeState {
+ /// Starts tracking an unmodified immutable root.
+ fn new(root: SyntaxNode) -> Self {
+ Self {
+ root,
+ edits: Vec::new(),
+ changed: Vec::new(),
+ original_annotations: Vec::new(),
+ annotations: Vec::new(),
+ }
+ }
+
+ /// Replay structural edits to translate an original path into this state.
+ fn map_original_path(&self, mut path: SyntaxPath) -> Option<SyntaxPath> {
+ for edit in &self.edits {
+ match edit {
+ PathEdit::Splice { parent, deleted, inserted } => {
+ if !path.adjust_for_splice(parent, deleted, *inserted) {
+ return None;
+ }
}
- },
- Change::Replace(target, _) | Change::ReplaceWithMany(target, _) => {
- *target = upmap_target(target);
- }
- Change::ReplaceAll(range, _) => {
- *range = upmap_target(range.start())..=upmap_target(range.end());
+ PathEdit::ReplaceRoot => return None,
}
}
+ Some(path)
}
- // We reverse here since we pushed to this in ascending order,
- // and we want to remove elements in descending order
- for idx in outdated_changes.into_iter().rev() {
- changes.remove(idx as usize);
+ /// Finds a change target in the current root.
+ fn map_original_element(&self, element: &SyntaxElement) -> SyntaxElement {
+ self.map_original_path(SyntaxPath::new(element))
+ .and_then(|path| path.resolve(&self.root))
+ .expect("an edit target must still be present")
}
- // Apply changes
- let mut root = tree_mutator.mutable_clone;
+ /// Applies one child-list splice and updates tracked structural path.
+ fn splice(
+ &mut self,
+ parent_path: SyntaxPath,
+ deleted: Range<usize>,
+ inserted: Vec<PreparedElement>,
+ track_as_changed: bool,
+ ) {
+ let inserted_count = inserted.len();
+ self.changed
+ .retain_mut(|path| path.adjust_for_splice(&parent_path, &deleted, inserted_count));
+ self.annotations
+ .retain_mut(|it| it.path.adjust_for_splice(&parent_path, &deleted, inserted_count));
+
+ for (offset, element) in inserted.iter().enumerate() {
+ let index = deleted.start + offset;
+ if track_as_changed {
+ self.changed
+ .push(parent_path.in_child(index, &SyntaxPath { child_indices: Vec::new() }));
+ }
+ self.annotations.extend(element.annotations.iter().map(|annotation| {
+ TrackedAnnotation {
+ path: parent_path.in_child(index, &annotation.path),
+ annotation: annotation.annotation,
+ order: annotation.order,
+ }
+ }));
+ }
+
+ let parent = parent_path.resolve(&self.root).and_then(SyntaxElement::into_node).unwrap();
+ let green = rowan::GreenNodeData::splice_children(
+ parent.green().as_ref(),
+ deleted.clone(),
+ inserted.into_iter().map(PreparedElement::into_green),
+ );
+ self.root = SyntaxNode::new_root(parent.replace_with(green));
+ self.edits.push(PathEdit::Splice {
+ parent: parent_path,
+ deleted,
+ inserted: inserted_count,
+ });
+ }
+
+ /// Replaces the tree's root with a prepared node payload.
+ fn replace_root(&mut self, replacement: PreparedElement, track_as_changed: bool) {
+ let NodeOrToken::Node(node) = replacement.syntax else {
+ panic!("root node replacement should be a node")
+ };
+ self.root = SyntaxNode::new_root(node.green().into_owned());
+ self.changed.clear();
+ if track_as_changed {
+ self.changed.push(SyntaxPath { child_indices: Vec::new() });
+ }
+ self.annotations = replacement.annotations;
+ self.edits.push(PathEdit::ReplaceRoot);
+ }
- for change in changes {
+ /// Applies a planned change to this tree using already prepared payloads.
+ fn apply(
+ &mut self,
+ change: &Change,
+ replacement: Vec<PreparedElement>,
+ record_as_changed: bool,
+ ) {
match change {
- Change::Insert(position, element) => {
- let (parent, index) = position.place();
- parent.splice_children(index..index, vec![element]);
- }
- Change::InsertAll(position, elements) => {
- let (parent, index) = position.place();
- parent.splice_children(index..index, elements);
- }
- Change::Replace(target, None) => {
- target.detach();
- }
- Change::Replace(SyntaxElement::Node(target), Some(new_target)) if target == root => {
- root = new_target.into_node().expect("root node replacement should be a node");
+ Change::Insert(position, _) | Change::InsertAll(position, _) => {
+ let (parent, index) = match &position.repr {
+ PositionRepr::FirstChild(parent) => {
+ let parent = self.map_original_element(&parent.clone().into());
+ (parent.into_node().unwrap(), 0)
+ }
+ PositionRepr::After(child) => {
+ let child = self.map_original_element(child);
+ (child.parent().unwrap(), child.index() + 1)
+ }
+ };
+ self.splice(
+ SyntaxPath::new(&parent.into()),
+ index..index,
+ replacement,
+ record_as_changed,
+ );
}
- Change::Replace(target, Some(new_target)) => {
- let parent = target.parent().unwrap();
- parent.splice_children(target.index()..target.index() + 1, vec![new_target]);
+ Change::Replace(SyntaxElement::Node(target), Some(_)) if target.parent().is_none() => {
+ self.replace_root(replacement.into_iter().next().unwrap(), record_as_changed);
}
- Change::ReplaceWithMany(target, elements) => {
+ Change::Replace(target, _) | Change::ReplaceWithMany(target, _) => {
+ let target = self.map_original_element(target);
let parent = target.parent().unwrap();
- parent.splice_children(target.index()..target.index() + 1, elements);
+ let index = target.index();
+ self.splice(
+ SyntaxPath::new(&parent.into()),
+ index..index + 1,
+ replacement,
+ record_as_changed,
+ );
}
- Change::ReplaceAll(range, elements) => {
- let start = range.start().index();
- let end = range.end().index();
- let parent = range.start().parent().unwrap();
- parent.splice_children(start..end + 1, elements);
+ Change::ReplaceAll(range, _) => {
+ let start = self.map_original_element(range.start());
+ let end = self.map_original_element(range.end());
+ let parent = start.parent().unwrap();
+ self.splice(
+ SyntaxPath::new(&parent.into()),
+ start.index()..end.index() + 1,
+ replacement,
+ record_as_changed,
+ );
}
}
}
+}
+
+/// A replacement payload paired with the annotation below it.
+///
+/// The syntax element remains an immutable snapshot of its source tree.
+/// Annotation paths are relative to the payload root and are rebased by
+/// splice
+struct PreparedElement {
+ syntax: SyntaxElement,
+ annotations: Vec<TrackedAnnotation>,
+}
- // Propagate annotations
- let annotations = annotations.into_iter().filter_map(|(element, annotation)| {
- match mappings.upmap_element(&element, &root) {
- // Needed to follow the new tree to find the resulting element
- Some(Ok(mapped)) => Some((mapped, annotation)),
- // Element did not need to be mapped
- None => Some((element, annotation)),
- // Element did not make it to the final tree
- Some(Err(_)) => None,
+impl PreparedElement {
+ fn into_green(self) -> rowan::NodeOrToken<rowan::GreenNode, rowan::GreenToken> {
+ match self.syntax {
+ SyntaxElement::Node(node) => NodeOrToken::Node(node.green().into_owned()),
+ SyntaxElement::Token(token) => NodeOrToken::Token(token.green().to_owned()),
}
- });
+ }
+}
- let mut annotation_groups = FxHashMap::default();
+/// Owns all evolving trees involved in executing an edit plan.
+struct TreeStore {
+ states: FxHashMap<SyntaxNode, TreeState>,
+}
- for (element, annotation) in annotations {
- annotation_groups.entry(annotation).or_insert(vec![]).push(element);
+impl TreeStore {
+ /// Creates per tree state for annotations after following factory mapping.
+ fn with_annotations(
+ annotations: Vec<(SyntaxElement, SyntaxAnnotation)>,
+ mappings: &SyntaxMapping,
+ ) -> Self {
+ let mut states = FxHashMap::<SyntaxNode, TreeState>::default();
+ for (order, (element, annotation)) in annotations.into_iter().enumerate() {
+ let element = mappings.upmap_element(&element);
+ let tree = element.tree_top();
+ let tracked = TrackedAnnotation { path: SyntaxPath::new(&element), annotation, order };
+ let state = states.entry(tree.clone()).or_insert_with(|| TreeState::new(tree));
+ state.original_annotations.push(tracked.clone());
+ state.annotations.push(tracked);
+ }
+ Self { states }
+ }
+
+ /// Execute an already ordered plan without performing further analysis.
+ fn execute(&mut self, plan: EditPlan) {
+ for planned in plan.changes {
+ self.states
+ .entry(planned.tree.clone())
+ .or_insert_with(|| TreeState::new(planned.tree.clone()));
+ let replacement = planned
+ .replacement_elements()
+ .iter()
+ .map(|element| self.prepare_element(element))
+ .collect();
+ self.states.get_mut(&planned.tree).unwrap().apply(
+ &planned.change,
+ replacement,
+ planned.record_as_changed,
+ );
+ }
}
- SyntaxEdit {
- old_root: tree_mutator.immutable,
- new_root: root,
- changed_elements,
- annotations: annotation_groups,
+ /// Captures the source element and annotations used by a replacement.
+ fn prepare_element(&self, element: &SyntaxElement) -> PreparedElement {
+ let tree = element.tree_top();
+ let original_path = SyntaxPath::new(element);
+ let (element, annotations) = match self.states.get(&tree) {
+ Some(state) => {
+ let annotations_below =
+ |annotations: &[TrackedAnnotation], ancestor: &SyntaxPath| {
+ annotations
+ .iter()
+ .filter_map(|annotation| {
+ annotation.path.relative_to(ancestor).map(|path| {
+ TrackedAnnotation {
+ path,
+ annotation: annotation.annotation,
+ order: annotation.order,
+ }
+ })
+ })
+ .collect()
+ };
+ match state.map_original_path(original_path.clone()) {
+ Some(path) => {
+ let element = path.resolve(&state.root).unwrap();
+ let annotations = annotations_below(&state.annotations, &path);
+ (element, annotations)
+ }
+ None => {
+ let annotations =
+ annotations_below(&state.original_annotations, &original_path);
+ (element.clone(), annotations)
+ }
+ }
+ }
+ None => (element.clone(), Vec::new()),
+ };
+ PreparedElement { syntax: element, annotations }
+ }
+
+ /// Resolves the editor roots tracked paths and constructs the public edit.
+ fn finish(mut self, old_root: SyntaxNode) -> SyntaxEdit {
+ let state =
+ self.states.remove(&old_root).unwrap_or_else(|| TreeState::new(old_root.clone()));
+ let new_root = state.root;
+
+ let mut changed_elements = state
+ .changed
+ .into_iter()
+ .filter_map(|path| path.resolve(&new_root))
+ .collect::<Vec<_>>();
+ changed_elements.sort_by_key(|element| element.text_range().start());
+
+ let mut annotations = FxHashMap::<SyntaxAnnotation, Vec<(usize, SyntaxElement)>>::default();
+ for annotation in state.annotations {
+ if let Some(element) = annotation.path.resolve(&new_root) {
+ annotations
+ .entry(annotation.annotation)
+ .or_default()
+ .push((annotation.order, element));
+ }
+ }
+ let annotations = annotations
+ .into_iter()
+ .map(|(annotation, mut elements)| {
+ elements.sort_by_key(|(order, element)| (*order, element.text_range().start()));
+ (annotation, elements.into_iter().map(|(_, element)| element).collect())
+ })
+ .collect();
+
+ SyntaxEdit { old_root, new_root, changed_elements, annotations }
}
}
+/// Plans and executes all changes recorded by a SyntaxEditor.
+pub(super) fn apply_edits(editor: SyntaxEditor) -> SyntaxEdit {
+ let SyntaxEditor { root, changes, annotations, make } = editor;
+ let mappings = make.take();
+ let mut node_depths = FxHashMap::<SyntaxNode, usize>::default();
+ let mut node_depth = |node: SyntaxNode| {
+ *node_depths.entry(node).or_insert_with_key(|node| node.ancestors().count())
+ };
+
+ let plan = match EditPlan::build(changes.into_inner(), &mappings, &mut node_depth) {
+ Ok(plan) => plan,
+ Err(InvalidEditPlan { changes }) => {
+ report_intersecting_changes(&changes, &mut node_depth, &root);
+ return SyntaxEdit {
+ old_root: root.clone(),
+ new_root: root,
+ annotations: FxHashMap::default(),
+ changed_elements: Vec::new(),
+ };
+ }
+ };
+
+ let mut trees = TreeStore::with_annotations(annotations.into_inner(), &mappings);
+ trees.execute(plan);
+ trees.finish(root)
+}
+
fn report_intersecting_changes(
changes: &[Change],
- mut get_node_depth: impl FnMut(rowan::SyntaxNode<crate::RustLanguage>) -> usize,
- root: &rowan::SyntaxNode<crate::RustLanguage>,
+ mut get_node_depth: impl FnMut(SyntaxNode) -> usize,
+ root: &SyntaxNode,
) {
let intersecting_changes = changes
.iter()
@@ -478,77 +763,49 @@ fn report_intersecting_changes(
stdx::always!(false, "{}", error_msg);
}
-fn to_owning_node(element: &SyntaxElement) -> SyntaxNode {
- match element {
- SyntaxElement::Node(node) => node.clone(),
- SyntaxElement::Token(token) => token.parent().unwrap(),
- }
-}
-
-struct ChangedAncestor {
- kind: ChangedAncestorKind,
+/// A replacement region that can contain later source ordered changeds
+struct ChangedRegion {
+ range: TextRange,
change_index: usize,
+ nested_changes: NestedChanges,
}
-enum ChangedAncestorKind {
- Single { node: SyntaxNode },
- Range { _changed_elements: RangeInclusive<SyntaxElement>, _in_parent: SyntaxNode },
-}
-
-impl ChangedAncestor {
- fn single(node: &SyntaxNode, change_index: usize) -> Self {
- let kind = ChangedAncestorKind::Single { node: node.clone() };
-
- Self { kind, change_index }
- }
-
- fn multiple(range: &RangeInclusive<SyntaxElement>, change_index: usize) -> Self {
- Self {
- kind: ChangedAncestorKind::Range {
- _changed_elements: range.clone(),
- _in_parent: range.start().parent().unwrap(),
- },
- change_index,
- }
- }
-
- fn affected_range(&self) -> TextRange {
- match &self.kind {
- ChangedAncestorKind::Single { node } => node.text_range(),
- ChangedAncestorKind::Range { _changed_elements: changed_nodes, _in_parent: _ } => {
- TextRange::new(
- changed_nodes.start().text_range().start(),
- changed_nodes.end().text_range().end(),
- )
- }
- }
- }
-}
-
-struct TreeMutator {
- immutable: SyntaxNode,
- mutable_clone: SyntaxNode,
+/// How changes nested within a replacement region are handled.
+enum NestedChanges {
+ /// Map nested targets into a one-to-one node replacement.
+ Remap,
+ /// Drop nested changes because the replacement has no unique counterpart.
+ Discard,
}
-impl TreeMutator {
- fn new(immutable: &SyntaxNode) -> TreeMutator {
- let immutable = immutable.clone();
- let mutable_clone = immutable.clone_for_update();
- TreeMutator { immutable, mutable_clone }
- }
-
- fn make_element_mut(&self, element: &SyntaxElement) -> SyntaxElement {
- match element {
- SyntaxElement::Node(node) => SyntaxElement::Node(self.make_syntax_mut(node)),
- SyntaxElement::Token(token) => {
- let parent = self.make_syntax_mut(&token.parent().unwrap());
- parent.children_with_tokens().nth(token.index()).unwrap()
- }
+impl ChangedRegion {
+ /// Describes a region replaced by change, if it can contain changes.
+ fn for_change(change: &Change, change_index: usize, discarded: bool) -> Option<Self> {
+ match change {
+ Change::Replace(SyntaxElement::Node(target), replacement) => Some(Self {
+ range: target.text_range(),
+ change_index,
+ nested_changes: if !discarded && matches!(replacement, Some(SyntaxElement::Node(_)))
+ {
+ NestedChanges::Remap
+ } else {
+ NestedChanges::Discard
+ },
+ }),
+ Change::ReplaceWithMany(SyntaxElement::Node(target), _) => Some(Self {
+ range: target.text_range(),
+ change_index,
+ nested_changes: NestedChanges::Discard,
+ }),
+ Change::ReplaceAll(elements, _) => Some(Self {
+ range: TextRange::new(
+ elements.start().text_range().start(),
+ elements.end().text_range().end(),
+ ),
+ change_index,
+ nested_changes: NestedChanges::Discard,
+ }),
+ _ => None,
}
}
-
- fn make_syntax_mut(&self, node: &SyntaxNode) -> SyntaxNode {
- let ptr = SyntaxNodePtr::new(node);
- ptr.to_node(&self.mutable_clone)
- }
}
diff --git a/crates/syntax/src/syntax_editor/mapping.rs b/crates/syntax/src/syntax_editor/mapping.rs
index 180c2e69fa..17319368af 100644
--- a/crates/syntax/src/syntax_editor/mapping.rs
+++ b/crates/syntax/src/syntax_editor/mapping.rs
@@ -21,7 +21,7 @@ pub struct SyntaxMapping {
impl SyntaxMapping {
/// Like [`SyntaxMapping::upmap_child`] but for syntax elements.
- pub fn upmap_child_element(
+ pub(super) fn upmap_child_element(
&self,
child: &SyntaxElement,
input_ancestor: &SyntaxNode,
@@ -48,7 +48,7 @@ impl SyntaxMapping {
/// Maps a child node of the input ancestor to the corresponding node in
/// the output ancestor.
- pub fn upmap_child(
+ pub(super) fn upmap_child(
&self,
child: &SyntaxNode,
input_ancestor: &SyntaxNode,
@@ -127,55 +127,22 @@ impl SyntaxMapping {
Err(MissingMapping(current))
}
- pub fn upmap_element(
- &self,
- input: &SyntaxElement,
- output_root: &SyntaxNode,
- ) -> Option<Result<SyntaxElement, MissingMapping>> {
- match input {
- SyntaxElement::Node(node) => {
- Some(self.upmap_node(node, output_root)?.map(SyntaxElement::Node))
- }
- SyntaxElement::Token(token) => {
- let upmap_parent = match self.upmap_node(&token.parent().unwrap(), output_root)? {
- Ok(it) => it,
- Err(err) => return Some(Err(err)),
- };
+ pub(super) fn upmap_element(&self, input: &SyntaxElement) -> SyntaxElement {
+ let mut current = input.clone();
- let element = upmap_parent.children_with_tokens().nth(token.index()).unwrap();
- debug_assert!(
- element.as_token().is_some_and(|it| it.kind() == token.kind()),
- "token upmapping mapped to the wrong node ({token:?} -> {element:?})"
- );
-
- Some(Ok(element))
- }
- }
- }
-
- pub fn upmap_node(
- &self,
- input: &SyntaxNode,
- output_root: &SyntaxNode,
- ) -> Option<Result<SyntaxNode, MissingMapping>> {
- // Try to follow the mapping tree, if it exists
- let input_mapping = self.upmap_node_single(input);
- let input_ancestor =
- input.ancestors().find(|ancestor| self.upmap_node_single(ancestor).is_some());
-
- match (input_mapping, input_ancestor) {
- (Some(input_mapping), _) => {
- // A mapping exists at the input, follow along the tree
- Some(self.upmap_child(&input_mapping, &input_mapping, output_root))
- }
- (None, Some(input_ancestor)) => {
- // A mapping exists at an ancestor, follow along the tree
- Some(self.upmap_child(input, &input_ancestor, output_root))
- }
- (None, None) => {
- // No mapping exists at all, is the same position in the final tree
- None
- }
+ loop {
+ let node = match &current {
+ SyntaxElement::Node(node) => node.clone(),
+ SyntaxElement::Token(token) => token.parent().unwrap(),
+ };
+ let Some((input_ancestor, output_ancestor)) = node.ancestors().find_map(|ancestor| {
+ self.upmap_node_single(&ancestor).map(|output_ancestor| (ancestor, output_ancestor))
+ }) else {
+ return current;
+ };
+ current = self
+ .upmap_child_element(&current, &input_ancestor, &output_ancestor.parent().unwrap())
+ .expect("the nearest mapped ancestor must map its descendants");
}
}
@@ -257,7 +224,7 @@ impl SyntaxMappingBuilder {
}
#[derive(Debug)]
-pub struct MissingMapping(pub SyntaxNode);
+pub(super) struct MissingMapping(pub SyntaxNode);
#[derive(Debug, Clone, Copy)]
struct MappingEntry {