Skip to content

Commit 1573144

Browse files
committed
introduce interior mutability to SyntaxEditor to let go of &mut usage
1 parent 434895f commit 1573144

4 files changed

Lines changed: 104 additions & 105 deletions

File tree

crates/syntax/src/ast/edit.rs

Lines changed: 12 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ impl IndentLevel {
108108
}
109109

110110
pub(super) fn clone_increase_indent(self, node: &SyntaxNode) -> SyntaxNode {
111-
let (mut editor, node) = SyntaxEditor::new(node.clone());
111+
let (editor, node) = SyntaxEditor::new(node.clone());
112112
let tokens = node
113113
.preorder_with_tokens()
114114
.filter_map(|event| match event {
@@ -142,7 +142,7 @@ impl IndentLevel {
142142
}
143143

144144
pub(super) fn clone_decrease_indent(self, node: &SyntaxNode) -> SyntaxNode {
145-
let (mut editor, node) = SyntaxEditor::new(node.clone());
145+
let (editor, node) = SyntaxEditor::new(node.clone());
146146
let tokens = node
147147
.preorder_with_tokens()
148148
.filter_map(|event| match event {
@@ -198,11 +198,8 @@ pub trait AstNodeEdit: AstNode + Clone + Sized {
198198
impl<N: AstNode + Clone> AstNodeEdit for N {}
199199

200200
impl ast::IdentPat {
201-
pub fn set_pat(
202-
&self,
203-
pat: Option<ast::Pat>,
204-
syntax_editor: &mut SyntaxEditor,
205-
) -> ast::IdentPat {
201+
pub fn set_pat(&self, pat: Option<ast::Pat>, editor: &SyntaxEditor) -> ast::IdentPat {
202+
let make = editor.make();
206203
match pat {
207204
None => {
208205
if let Some(at_token) = self.at_token() {
@@ -212,7 +209,7 @@ impl ast::IdentPat {
212209
.pat()
213210
.map(|it| it.syntax().clone().into())
214211
.unwrap_or_else(|| at_token.into());
215-
syntax_editor.delete_all(start..=end);
212+
editor.delete_all(start..=end);
216213

217214
// Remove any trailing ws
218215
if let Some(last) =
@@ -225,28 +222,28 @@ impl ast::IdentPat {
225222
Some(pat) => {
226223
if let Some(old_pat) = self.pat() {
227224
// Replace existing pattern
228-
syntax_editor.replace(old_pat.syntax(), pat.syntax())
225+
editor.replace(old_pat.syntax(), pat.syntax())
229226
} else if let Some(at_token) = self.at_token() {
230227
// Have an `@` token but not a pattern yet
231-
syntax_editor.insert(Position::after(at_token), pat.syntax());
228+
editor.insert(Position::after(at_token), pat.syntax());
232229
} else {
233230
// Don't have an `@`, should have a name
234231
let name = self.name().unwrap();
235232
let elements = vec![
236-
syntax_editor.make().whitespace(" ").into(),
237-
syntax_editor.make().token(T![@]).into(),
238-
syntax_editor.make().whitespace(" ").into(),
233+
make.whitespace(" ").into(),
234+
make.token(T![@]).into(),
235+
make.whitespace(" ").into(),
239236
pat.syntax().clone().into(),
240237
];
241238

242239
if self.syntax().parent().is_none() {
243-
let (mut local, local_self) = SyntaxEditor::with_ast_node(self);
240+
let (local, local_self) = SyntaxEditor::with_ast_node(self);
244241
let local_name = local_self.name().unwrap();
245242
local.insert_all(Position::after(local_name.syntax()), elements);
246243
let edit = local.finish();
247244
return ast::IdentPat::cast(edit.new_root().clone()).unwrap();
248245
} else {
249-
syntax_editor.insert_all(Position::after(name.syntax()), elements);
246+
editor.insert_all(Position::after(name.syntax()), elements);
250247
}
251248
}
252249
}

crates/syntax/src/syntax_editor.rs

Lines changed: 61 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
//! [`SyntaxEditor`]: https://github.com/dotnet/roslyn/blob/43b0b05cc4f492fd5de00f6f6717409091df8daa/src/Workspaces/Core/Portable/Editing/SyntaxEditor.cs
66
77
use std::{
8+
cell::RefCell,
89
fmt, iter,
910
num::NonZeroU32,
1011
ops::RangeInclusive,
@@ -29,8 +30,8 @@ pub use mapping::{SyntaxMapping, SyntaxMappingBuilder};
2930
#[derive(Debug)]
3031
pub struct SyntaxEditor {
3132
root: SyntaxNode,
32-
changes: Vec<Change>,
33-
annotations: Vec<(SyntaxElement, SyntaxAnnotation)>,
33+
changes: RefCell<Vec<Change>>,
34+
annotations: RefCell<Vec<(SyntaxElement, SyntaxAnnotation)>>,
3435
make: SyntaxFactory,
3536
}
3637

@@ -50,8 +51,8 @@ impl SyntaxEditor {
5051

5152
let editor = Self {
5253
root: root.clone(),
53-
changes: Vec::new(),
54-
annotations: Vec::new(),
54+
changes: RefCell::new(Vec::new()),
55+
annotations: RefCell::new(Vec::new()),
5556
make: SyntaxFactory::with_mappings(),
5657
};
5758

@@ -72,53 +73,46 @@ impl SyntaxEditor {
7273
&self.make
7374
}
7475

75-
pub fn add_annotation(&mut self, element: impl Element, annotation: SyntaxAnnotation) {
76-
self.annotations.push((element.syntax_element(), annotation))
76+
pub fn add_annotation(&self, element: impl Element, annotation: SyntaxAnnotation) {
77+
self.annotations.borrow_mut().push((element.syntax_element(), annotation))
7778
}
7879

79-
pub fn add_annotation_all(
80-
&mut self,
81-
elements: Vec<impl Element>,
82-
annotation: SyntaxAnnotation,
83-
) {
80+
pub fn add_annotation_all(&self, elements: Vec<impl Element>, annotation: SyntaxAnnotation) {
8481
self.annotations
82+
.borrow_mut()
8583
.extend(elements.into_iter().map(|e| e.syntax_element()).zip(iter::repeat(annotation)));
8684
}
8785

88-
pub fn merge(&mut self, mut other: SyntaxEditor) {
86+
pub fn merge(&self, other: SyntaxEditor) {
8987
debug_assert!(
9088
self.root == other.root || other.root.ancestors().any(|node| node == self.root),
9189
"{:?} is not in the same tree as {:?}",
9290
other.root,
9391
self.root
9492
);
9593

96-
self.changes.append(&mut other.changes);
94+
self.changes.borrow_mut().append(&mut other.changes.into_inner());
9795
if let Some(mut m) = self.make.mappings() {
9896
m.merge(other.make.take());
9997
}
100-
self.annotations.append(&mut other.annotations);
98+
self.annotations.borrow_mut().append(&mut other.annotations.into_inner());
10199
}
102100

103-
pub fn insert(&mut self, position: Position, element: impl Element) {
101+
pub fn insert(&self, position: Position, element: impl Element) {
104102
debug_assert!(is_ancestor_or_self(&position.parent(), &self.root));
105-
self.changes.push(Change::Insert(position, element.syntax_element()))
103+
self.changes.borrow_mut().push(Change::Insert(position, element.syntax_element()))
106104
}
107105

108-
pub fn insert_all(&mut self, position: Position, elements: Vec<SyntaxElement>) {
106+
pub fn insert_all(&self, position: Position, elements: Vec<SyntaxElement>) {
109107
debug_assert!(is_ancestor_or_self(&position.parent(), &self.root));
110-
self.changes.push(Change::InsertAll(position, elements))
108+
self.changes.borrow_mut().push(Change::InsertAll(position, elements))
111109
}
112110

113-
pub fn insert_with_whitespace(&mut self, position: Position, element: impl Element) {
111+
pub fn insert_with_whitespace(&self, position: Position, element: impl Element) {
114112
self.insert_all_with_whitespace(position, vec![element.syntax_element()])
115113
}
116114

117-
pub fn insert_all_with_whitespace(
118-
&mut self,
119-
position: Position,
120-
mut elements: Vec<SyntaxElement>,
121-
) {
115+
pub fn insert_all_with_whitespace(&self, position: Position, mut elements: Vec<SyntaxElement>) {
122116
if let Some(first) = elements.first()
123117
&& let Some(ws) = ws_before(&position, first, &self.make)
124118
{
@@ -132,50 +126,52 @@ impl SyntaxEditor {
132126
self.insert_all(position, elements)
133127
}
134128

135-
pub fn delete(&mut self, element: impl Element) {
129+
pub fn delete(&self, element: impl Element) {
136130
let element = element.syntax_element();
137131
debug_assert!(is_ancestor_or_self_of_element(&element, &self.root));
138132
debug_assert!(
139133
!matches!(&element, SyntaxElement::Node(node) if node == &self.root),
140134
"should not delete root node"
141135
);
142-
self.changes.push(Change::Replace(element.syntax_element(), None));
136+
self.changes.borrow_mut().push(Change::Replace(element.syntax_element(), None));
143137
}
144138

145-
pub fn delete_all(&mut self, range: RangeInclusive<SyntaxElement>) {
139+
pub fn delete_all(&self, range: RangeInclusive<SyntaxElement>) {
146140
if range.start() == range.end() {
147141
self.delete(range.start());
148142
return;
149143
}
150144

151145
debug_assert!(is_ancestor_or_self_of_element(range.start(), &self.root));
152-
self.changes.push(Change::ReplaceAll(range, Vec::new()))
146+
self.changes.borrow_mut().push(Change::ReplaceAll(range, Vec::new()))
153147
}
154148

155-
pub fn replace(&mut self, old: impl Element, new: impl Element) {
149+
pub fn replace(&self, old: impl Element, new: impl Element) {
156150
let old = old.syntax_element();
157151
debug_assert!(is_ancestor_or_self_of_element(&old, &self.root));
158-
self.changes.push(Change::Replace(old.syntax_element(), Some(new.syntax_element())));
152+
self.changes
153+
.borrow_mut()
154+
.push(Change::Replace(old.syntax_element(), Some(new.syntax_element())));
159155
}
160156

161-
pub fn replace_with_many(&mut self, old: impl Element, new: Vec<SyntaxElement>) {
157+
pub fn replace_with_many(&self, old: impl Element, new: Vec<SyntaxElement>) {
162158
let old = old.syntax_element();
163159
debug_assert!(is_ancestor_or_self_of_element(&old, &self.root));
164160
debug_assert!(
165161
!(matches!(&old, SyntaxElement::Node(node) if node == &self.root) && new.len() > 1),
166162
"cannot replace root node with many elements"
167163
);
168-
self.changes.push(Change::ReplaceWithMany(old.syntax_element(), new));
164+
self.changes.borrow_mut().push(Change::ReplaceWithMany(old.syntax_element(), new));
169165
}
170166

171-
pub fn replace_all(&mut self, range: RangeInclusive<SyntaxElement>, new: Vec<SyntaxElement>) {
167+
pub fn replace_all(&self, range: RangeInclusive<SyntaxElement>, new: Vec<SyntaxElement>) {
172168
if range.start() == range.end() {
173169
self.replace_with_many(range.start(), new);
174170
return;
175171
}
176172

177173
debug_assert!(is_ancestor_or_self_of_element(range.start(), &self.root));
178-
self.changes.push(Change::ReplaceAll(range, new))
174+
self.changes.borrow_mut().push(Change::ReplaceAll(range, new))
179175
}
180176

181177
pub fn finish(self) -> SyntaxEdit {
@@ -555,7 +551,8 @@ mod tests {
555551
.into(),
556552
);
557553

558-
let (mut editor, root) = SyntaxEditor::with_ast_node(&root);
554+
let (editor, root) = SyntaxEditor::with_ast_node(&root);
555+
let make = editor.make();
559556

560557
let to_wrap = root.syntax().descendants().find_map(ast::TupleExpr::cast).unwrap();
561558
let to_replace = root.syntax().descendants().find_map(ast::BinExpr::cast).unwrap();
@@ -567,11 +564,11 @@ mod tests {
567564
editor.add_annotation(name.syntax(), placeholder_snippet);
568565
editor.add_annotation(name_ref.syntax(), placeholder_snippet);
569566

570-
let new_block = editor.make().block_expr(
567+
let new_block = make.block_expr(
571568
[editor
572569
.make()
573570
.let_stmt(
574-
editor.make().ident_pat(false, false, name.clone()).into(),
571+
make.ident_pat(false, false, name.clone()).into(),
575572
None,
576573
Some(to_replace.clone().into()),
577574
)
@@ -612,31 +609,28 @@ mod tests {
612609
None,
613610
);
614611

615-
let (mut editor, root) = SyntaxEditor::with_ast_node(&root);
612+
let (editor, root) = SyntaxEditor::with_ast_node(&root);
613+
let make = editor.make();
616614
let second_let = root.syntax().descendants().find_map(ast::LetStmt::cast).unwrap();
617615

618616
editor.insert(
619617
Position::first_child_of(root.stmt_list().unwrap().syntax()),
620-
editor
621-
.make()
622-
.let_stmt(
623-
make::ext::simple_ident_pat(make::name("first")).into(),
624-
None,
625-
Some(make::expr_literal("1").into()),
626-
)
627-
.syntax(),
618+
make.let_stmt(
619+
make::ext::simple_ident_pat(make::name("first")).into(),
620+
None,
621+
Some(make::expr_literal("1").into()),
622+
)
623+
.syntax(),
628624
);
629625

630626
editor.insert(
631627
Position::after(second_let.syntax()),
632-
editor
633-
.make()
634-
.let_stmt(
635-
make::ext::simple_ident_pat(make::name("third")).into(),
636-
None,
637-
Some(make::expr_literal("3").into()),
638-
)
639-
.syntax(),
628+
make.let_stmt(
629+
make::ext::simple_ident_pat(make::name("third")).into(),
630+
None,
631+
Some(make::expr_literal("3").into()),
632+
)
633+
.syntax(),
640634
);
641635

642636
let edit = editor.finish();
@@ -666,22 +660,22 @@ mod tests {
666660
),
667661
);
668662

669-
let (mut editor, root) = SyntaxEditor::with_ast_node(&root);
663+
let (editor, root) = SyntaxEditor::with_ast_node(&root);
664+
let make = editor.make();
670665

671666
let inner_block =
672667
root.syntax().descendants().flat_map(ast::BlockExpr::cast).nth(1).unwrap();
673668
let second_let = root.syntax().descendants().find_map(ast::LetStmt::cast).unwrap();
674669

675-
let new_block_expr =
676-
editor.make().block_expr([], Some(ast::Expr::BlockExpr(inner_block.clone())));
670+
let new_block_expr = make.block_expr([], Some(ast::Expr::BlockExpr(inner_block.clone())));
677671

678-
let first_let = editor.make().let_stmt(
672+
let first_let = make.let_stmt(
679673
make::ext::simple_ident_pat(make::name("first")).into(),
680674
None,
681675
Some(make::expr_literal("1").into()),
682676
);
683677

684-
let third_let = editor.make().let_stmt(
678+
let third_let = make.let_stmt(
685679
make::ext::simple_ident_pat(make::name("third")).into(),
686680
None,
687681
Some(make::expr_literal("3").into()),
@@ -719,14 +713,14 @@ mod tests {
719713
None,
720714
);
721715

722-
let (mut editor, root) = SyntaxEditor::with_ast_node(&root);
716+
let (editor, root) = SyntaxEditor::with_ast_node(&root);
717+
let make = editor.make();
723718

724719
let inner_block = root;
725720

726-
let new_block_expr =
727-
editor.make().block_expr([], Some(ast::Expr::BlockExpr(inner_block.clone())));
721+
let new_block_expr = make.block_expr([], Some(ast::Expr::BlockExpr(inner_block.clone())));
728722

729-
let first_let = editor.make().let_stmt(
723+
let first_let = make.let_stmt(
730724
make::ext::simple_ident_pat(make::name("first")).into(),
731725
None,
732726
Some(make::expr_literal("1").into()),
@@ -766,7 +760,7 @@ mod tests {
766760
false,
767761
);
768762

769-
let (mut editor, parent_fn) = SyntaxEditor::with_ast_node(&parent_fn);
763+
let (editor, parent_fn) = SyntaxEditor::with_ast_node(&parent_fn);
770764

771765
if let Some(ret_ty) = parent_fn.ret_type() {
772766
editor.delete(ret_ty.syntax().clone());
@@ -793,7 +787,7 @@ mod tests {
793787
let arg_list =
794788
make::arg_list([make::expr_literal("1").into(), make::expr_literal("2").into()]);
795789

796-
let (mut editor, arg_list) = SyntaxEditor::with_ast_node(&arg_list);
790+
let (editor, arg_list) = SyntaxEditor::with_ast_node(&arg_list);
797791

798792
let target_expr = make::token(parser::SyntaxKind::UNDERSCORE);
799793

@@ -812,7 +806,7 @@ mod tests {
812806
let arg_list =
813807
make::arg_list([make::expr_literal("1").into(), make::expr_literal("2").into()]);
814808

815-
let (mut editor, arg_list) = SyntaxEditor::with_ast_node(&arg_list);
809+
let (editor, arg_list) = SyntaxEditor::with_ast_node(&arg_list);
816810

817811
let target_expr = make::expr_literal("3").clone_for_update();
818812

@@ -831,7 +825,7 @@ mod tests {
831825
let arg_list =
832826
make::arg_list([make::expr_literal("1").into(), make::expr_literal("2").into()]);
833827

834-
let (mut editor, arg_list) = SyntaxEditor::with_ast_node(&arg_list);
828+
let (editor, arg_list) = SyntaxEditor::with_ast_node(&arg_list);
835829

836830
let target_expr = make::ext::expr_unit().clone_for_update();
837831

0 commit comments

Comments
 (0)