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
| -rw-r--r-- | crates/ide-assists/src/handlers/generate_blanket_trait_impl.rs | 2 | ||||
| -rw-r--r-- | crates/ide-assists/src/handlers/replace_derive_with_manual_impl.rs | 9 | ||||
| -rw-r--r-- | crates/syntax/src/ast.rs | 6 | ||||
| -rw-r--r-- | crates/syntax/src/ast/syntax_factory/constructors.rs | 330 | ||||
| -rw-r--r-- | crates/syntax/src/syntax_editor.rs | 21 | ||||
| -rw-r--r-- | crates/syntax/src/syntax_editor/edit_algo.rs | 1055 | ||||
| -rw-r--r-- | crates/syntax/src/syntax_editor/mapping.rs | 69 |
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 ¤t { + 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(¤t, &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 { |