Skip to content

Commit bdfc770

Browse files
authored
Merge pull request #20269 from Hmikihiro/migrate_indent_mapping
Migrate AstNodeEdit::Indent to SyntaxEditor
2 parents 7cbc5a3 + 6f101d9 commit bdfc770

File tree

8 files changed

+74
-35
lines changed

8 files changed

+74
-35
lines changed

crates/ide-assists/src/handlers/convert_bool_then.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -228,8 +228,7 @@ pub(crate) fn convert_bool_then_to_if(acc: &mut Assists, ctx: &AssistContext<'_>
228228
closure_body,
229229
Some(ast::ElseBranch::Block(make.block_expr(None, Some(none_path)))),
230230
)
231-
.indent(mcall.indent_level())
232-
.clone_for_update();
231+
.indent(mcall.indent_level());
233232
editor.replace(mcall.syntax().clone(), if_expr.syntax().clone());
234233

235234
editor.add_mappings(make.finish_with_mappings());

crates/ide-assists/src/handlers/convert_to_guarded_return.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ fn if_expr_to_guarded_return(
117117

118118
then_block.syntax().last_child_or_token().filter(|t| t.kind() == T!['}'])?;
119119

120-
let then_block_items = then_block.dedent(IndentLevel(1)).clone_for_update();
120+
let then_block_items = then_block.dedent(IndentLevel(1));
121121

122122
let end_of_then = then_block_items.syntax().last_child_or_token()?;
123123
let end_of_then = if end_of_then.prev_sibling_or_token().map(|n| n.kind()) == Some(WHITESPACE) {
@@ -143,7 +143,7 @@ fn if_expr_to_guarded_return(
143143
let cond = invert_boolean_expression_legacy(cond_expr);
144144
make::expr_if(cond, then_branch, None).indent(if_indent_level)
145145
};
146-
new_expr.syntax().clone_for_update()
146+
new_expr.syntax().clone()
147147
}
148148
Some(pat) => {
149149
// If-let.
@@ -154,7 +154,7 @@ fn if_expr_to_guarded_return(
154154
ast::make::tail_only_block_expr(early_expression),
155155
);
156156
let let_else_stmt = let_else_stmt.indent(if_indent_level);
157-
let_else_stmt.syntax().clone_for_update()
157+
let_else_stmt.syntax().clone()
158158
}
159159
};
160160

@@ -225,7 +225,7 @@ fn let_stmt_to_guarded_return(
225225
ast::make::tail_only_block_expr(early_expression),
226226
);
227227
let let_else_stmt = let_else_stmt.indent(let_indent_level);
228-
let_else_stmt.syntax().clone_for_update()
228+
let_else_stmt.syntax().clone()
229229
};
230230

231231
ted::replace(let_stmt.syntax(), replacement)

crates/ide-assists/src/handlers/extract_variable.rs

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,9 @@ use syntax::{
77
NodeOrToken, SyntaxKind, SyntaxNode, T,
88
algo::ancestors_at_offset,
99
ast::{
10-
self, AstNode, edit::IndentLevel, edit_in_place::Indent, make,
10+
self, AstNode,
11+
edit::{AstNodeEdit, IndentLevel},
12+
make,
1113
syntax_factory::SyntaxFactory,
1214
},
1315
syntax_editor::Position,
@@ -253,12 +255,11 @@ pub(crate) fn extract_variable(acc: &mut Assists, ctx: &AssistContext<'_>) -> Op
253255
// `expr_replace` is a descendant of `to_wrap`, so we just replace it with `name_expr`.
254256
editor.replace(expr_replace, name_expr.syntax());
255257
make.block_expr([new_stmt], Some(to_wrap.clone()))
256-
};
258+
}
259+
// fixup indentation of block
260+
.indent_with_mapping(indent_to, &make);
257261

258262
editor.replace(to_wrap.syntax(), block.syntax());
259-
260-
// fixup indentation of block
261-
block.indent(indent_to);
262263
}
263264
}
264265

crates/ide-assists/src/handlers/generate_delegate_trait.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -767,7 +767,7 @@ fn func_assoc_item(
767767
)
768768
.clone_for_update();
769769

770-
Some(AssocItem::Fn(func.indent(edit::IndentLevel(1)).clone_for_update()))
770+
Some(AssocItem::Fn(func.indent(edit::IndentLevel(1))))
771771
}
772772

773773
fn ty_assoc_item(item: syntax::ast::TypeAlias, qual_path_ty: Path) -> Option<AssocItem> {

crates/ide-assists/src/utils.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -236,7 +236,7 @@ pub fn add_trait_assoc_items_to_impl(
236236
),
237237
new_indent_level,
238238
);
239-
ted::replace(fn_.get_or_create_body().syntax(), body.clone_for_update().syntax())
239+
ted::replace(fn_.get_or_create_body().syntax(), body.syntax())
240240
}
241241
ast::AssocItem::TypeAlias(type_alias) => {
242242
if let Some(type_bound_list) = type_alias.type_bound_list() {

crates/ide-assists/src/utils/gen_trait_fn_body.rs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,7 @@ fn gen_clone_impl(adt: &ast::Adt, func: &ast::Fn) -> Option<()> {
139139
}
140140
};
141141
let body = make::block_expr(None, Some(expr)).indent(ast::edit::IndentLevel(1));
142-
ted::replace(func.body()?.syntax(), body.clone_for_update().syntax());
142+
ted::replace(func.body()?.syntax(), body.syntax());
143143
Some(())
144144
}
145145

@@ -248,7 +248,7 @@ fn gen_debug_impl(adt: &ast::Adt, func: &ast::Fn) -> Option<()> {
248248

249249
let body = make::block_expr(None, Some(match_expr.into()));
250250
let body = body.indent(ast::edit::IndentLevel(1));
251-
ted::replace(func.body()?.syntax(), body.clone_for_update().syntax());
251+
ted::replace(func.body()?.syntax(), body.syntax());
252252
Some(())
253253
}
254254

@@ -296,7 +296,7 @@ fn gen_debug_impl(adt: &ast::Adt, func: &ast::Fn) -> Option<()> {
296296
let method = make::name_ref("finish");
297297
let expr = make::expr_method_call(expr, method, make::arg_list(None)).into();
298298
let body = make::block_expr(None, Some(expr)).indent(ast::edit::IndentLevel(1));
299-
ted::replace(func.body()?.syntax(), body.clone_for_update().syntax());
299+
ted::replace(func.body()?.syntax(), body.syntax());
300300
Some(())
301301
}
302302
}
@@ -342,7 +342,7 @@ fn gen_default_impl(adt: &ast::Adt, func: &ast::Fn) -> Option<()> {
342342
}
343343
};
344344
let body = make::block_expr(None, Some(expr)).indent(ast::edit::IndentLevel(1));
345-
ted::replace(func.body()?.syntax(), body.clone_for_update().syntax());
345+
ted::replace(func.body()?.syntax(), body.syntax());
346346
Some(())
347347
}
348348
}
@@ -400,7 +400,7 @@ fn gen_hash_impl(adt: &ast::Adt, func: &ast::Fn) -> Option<()> {
400400
},
401401
};
402402

403-
ted::replace(func.body()?.syntax(), body.clone_for_update().syntax());
403+
ted::replace(func.body()?.syntax(), body.syntax());
404404
Some(())
405405
}
406406

@@ -595,7 +595,7 @@ fn gen_partial_eq(adt: &ast::Adt, func: &ast::Fn, trait_ref: Option<TraitRef<'_>
595595
},
596596
};
597597

598-
ted::replace(func.body()?.syntax(), body.clone_for_update().syntax());
598+
ted::replace(func.body()?.syntax(), body.syntax());
599599
Some(())
600600
}
601601

@@ -686,7 +686,7 @@ fn gen_partial_ord(adt: &ast::Adt, func: &ast::Fn, trait_ref: Option<TraitRef<'_
686686
},
687687
};
688688

689-
ted::replace(func.body()?.syntax(), body.clone_for_update().syntax());
689+
ted::replace(func.body()?.syntax(), body.syntax());
690690
Some(())
691691
}
692692

crates/syntax/src/ast/edit.rs

Lines changed: 53 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,12 @@ use std::{fmt, iter, ops};
66
use crate::{
77
AstToken, NodeOrToken, SyntaxElement, SyntaxNode, SyntaxToken,
88
ast::{self, AstNode, make},
9+
syntax_editor::{SyntaxEditor, SyntaxMappingBuilder},
910
ted,
1011
};
1112

13+
use super::syntax_factory::SyntaxFactory;
14+
1215
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
1316
pub struct IndentLevel(pub u8);
1417

@@ -95,6 +98,24 @@ impl IndentLevel {
9598
}
9699
}
97100

101+
pub(super) fn clone_increase_indent(self, node: &SyntaxNode) -> SyntaxNode {
102+
let node = node.clone_subtree();
103+
let mut editor = SyntaxEditor::new(node.clone());
104+
let tokens = node
105+
.preorder_with_tokens()
106+
.filter_map(|event| match event {
107+
rowan::WalkEvent::Leave(NodeOrToken::Token(it)) => Some(it),
108+
_ => None,
109+
})
110+
.filter_map(ast::Whitespace::cast)
111+
.filter(|ws| ws.text().contains('\n'));
112+
for ws in tokens {
113+
let new_ws = make::tokens::whitespace(&format!("{}{self}", ws.syntax()));
114+
editor.replace(ws.syntax(), &new_ws);
115+
}
116+
editor.finish().new_root().clone()
117+
}
118+
98119
pub(super) fn decrease_indent(self, node: &SyntaxNode) {
99120
let tokens = node.preorder_with_tokens().filter_map(|event| match event {
100121
rowan::WalkEvent::Leave(NodeOrToken::Token(it)) => Some(it),
@@ -111,36 +132,54 @@ impl IndentLevel {
111132
}
112133
}
113134
}
135+
136+
pub(super) fn clone_decrease_indent(self, node: &SyntaxNode) -> SyntaxNode {
137+
let node = node.clone_subtree();
138+
let mut editor = SyntaxEditor::new(node.clone());
139+
let tokens = node
140+
.preorder_with_tokens()
141+
.filter_map(|event| match event {
142+
rowan::WalkEvent::Leave(NodeOrToken::Token(it)) => Some(it),
143+
_ => None,
144+
})
145+
.filter_map(ast::Whitespace::cast)
146+
.filter(|ws| ws.text().contains('\n'));
147+
for ws in tokens {
148+
let new_ws =
149+
make::tokens::whitespace(&ws.syntax().text().replace(&format!("\n{self}"), "\n"));
150+
editor.replace(ws.syntax(), &new_ws);
151+
}
152+
editor.finish().new_root().clone()
153+
}
114154
}
115155

116156
fn prev_tokens(token: SyntaxToken) -> impl Iterator<Item = SyntaxToken> {
117157
iter::successors(Some(token), |token| token.prev_token())
118158
}
119159

120-
/// Soft-deprecated in favor of mutable tree editing API `edit_in_place::Ident`.
121160
pub trait AstNodeEdit: AstNode + Clone + Sized {
122161
fn indent_level(&self) -> IndentLevel {
123162
IndentLevel::from_node(self.syntax())
124163
}
125164
#[must_use]
126165
fn indent(&self, level: IndentLevel) -> Self {
127-
fn indent_inner(node: &SyntaxNode, level: IndentLevel) -> SyntaxNode {
128-
let res = node.clone_subtree().clone_for_update();
129-
level.increase_indent(&res);
130-
res.clone_subtree()
166+
Self::cast(level.clone_increase_indent(self.syntax())).unwrap()
167+
}
168+
#[must_use]
169+
fn indent_with_mapping(&self, level: IndentLevel, make: &SyntaxFactory) -> Self {
170+
let new_node = self.indent(level);
171+
if let Some(mut mapping) = make.mappings() {
172+
let mut builder = SyntaxMappingBuilder::new(new_node.syntax().clone());
173+
for (old, new) in self.syntax().children().zip(new_node.syntax().children()) {
174+
builder.map_node(old, new);
175+
}
176+
builder.finish(&mut mapping);
131177
}
132-
133-
Self::cast(indent_inner(self.syntax(), level)).unwrap()
178+
new_node
134179
}
135180
#[must_use]
136181
fn dedent(&self, level: IndentLevel) -> Self {
137-
fn dedent_inner(node: &SyntaxNode, level: IndentLevel) -> SyntaxNode {
138-
let res = node.clone_subtree().clone_for_update();
139-
level.decrease_indent(&res);
140-
res.clone_subtree()
141-
}
142-
143-
Self::cast(dedent_inner(self.syntax(), level)).unwrap()
182+
Self::cast(level.clone_decrease_indent(self.syntax())).unwrap()
144183
}
145184
#[must_use]
146185
fn reset_indent(&self) -> Self {

crates/syntax/src/ast/syntax_factory.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ impl SyntaxFactory {
3838
self.mappings.as_ref().map(|mappings| mappings.take()).unwrap_or_default()
3939
}
4040

41-
fn mappings(&self) -> Option<RefMut<'_, SyntaxMapping>> {
41+
pub(crate) fn mappings(&self) -> Option<RefMut<'_, SyntaxMapping>> {
4242
self.mappings.as_ref().map(|it| it.borrow_mut())
4343
}
4444
}

0 commit comments

Comments
 (0)