Unnamed repository; edit this file 'description' to name the repository.
Merge pull request #21174 from Young-Flash/migrate_convert_iter_for_each_to_for
internal: migrate `convert_iter_for_each_to_for` to SyntaxEditor api
Shoyu Vanilla (Flint) 5 months ago
parent 3dfe74e · parent 03d0e79 · commit a071c5c
-rw-r--r--crates/ide-assists/src/handlers/convert_iter_for_each_to_for.rs18
-rw-r--r--crates/syntax/src/ast/make.rs2
-rw-r--r--crates/syntax/src/ast/syntax_factory/constructors.rs20
3 files changed, 32 insertions, 8 deletions
diff --git a/crates/ide-assists/src/handlers/convert_iter_for_each_to_for.rs b/crates/ide-assists/src/handlers/convert_iter_for_each_to_for.rs
index 0c0458468d..2eea4f71ed 100644
--- a/crates/ide-assists/src/handlers/convert_iter_for_each_to_for.rs
+++ b/crates/ide-assists/src/handlers/convert_iter_for_each_to_for.rs
@@ -3,7 +3,7 @@ use ide_db::famous_defs::FamousDefs;
use stdx::format_to;
use syntax::{
AstNode,
- ast::{self, HasArgList, HasLoopBody, edit_in_place::Indent, make},
+ ast::{self, HasArgList, HasLoopBody, edit_in_place::Indent, syntax_factory::SyntaxFactory},
};
use crate::{AssistContext, AssistId, Assists};
@@ -57,18 +57,22 @@ pub(crate) fn convert_iter_for_each_to_for(
"Replace this `Iterator::for_each` with a for loop",
range,
|builder| {
+ let make = SyntaxFactory::with_mappings();
let indent =
stmt.as_ref().map_or_else(|| method.indent_level(), ast::ExprStmt::indent_level);
let block = match body {
- ast::Expr::BlockExpr(block) => block,
- _ => make::block_expr(Vec::new(), Some(body)),
- }
- .clone_for_update();
+ ast::Expr::BlockExpr(block) => block.clone_for_update(),
+ _ => make.block_expr(Vec::new(), Some(body)),
+ };
block.reindent_to(indent);
- let expr_for_loop = make::expr_for_loop(param, receiver, block);
- builder.replace(range, expr_for_loop.to_string())
+ let expr_for_loop = make.expr_for_loop(param, receiver, block);
+
+ let target_node = stmt.as_ref().map_or(method.syntax(), AstNode::syntax);
+ let mut editor = builder.make_editor(target_node);
+ editor.replace(target_node, expr_for_loop.syntax());
+ builder.add_file_edits(ctx.vfs_file_id(), editor);
},
)
}
diff --git a/crates/syntax/src/ast/make.rs b/crates/syntax/src/ast/make.rs
index dba39204e3..19019ad08d 100644
--- a/crates/syntax/src/ast/make.rs
+++ b/crates/syntax/src/ast/make.rs
@@ -658,7 +658,7 @@ pub fn expr_if(
};
expr_from_text(&format!("if {condition} {then_branch} {else_branch}"))
}
-pub fn expr_for_loop(pat: ast::Pat, expr: ast::Expr, block: ast::BlockExpr) -> ast::Expr {
+pub fn expr_for_loop(pat: ast::Pat, expr: ast::Expr, block: ast::BlockExpr) -> ast::ForExpr {
expr_from_text(&format!("for {pat} in {expr} {block}"))
}
diff --git a/crates/syntax/src/ast/syntax_factory/constructors.rs b/crates/syntax/src/ast/syntax_factory/constructors.rs
index 560dd77662..aca6fcfb2e 100644
--- a/crates/syntax/src/ast/syntax_factory/constructors.rs
+++ b/crates/syntax/src/ast/syntax_factory/constructors.rs
@@ -853,6 +853,26 @@ impl SyntaxFactory {
ast
}
+ pub fn expr_for_loop(
+ &self,
+ pat: ast::Pat,
+ iterable: ast::Expr,
+ body: ast::BlockExpr,
+ ) -> ast::ForExpr {
+ let ast =
+ make::expr_for_loop(pat.clone(), iterable.clone(), body.clone()).clone_for_update();
+
+ if let Some(mut mapping) = self.mappings() {
+ let mut builder = SyntaxMappingBuilder::new(ast.syntax().clone());
+ builder.map_node(pat.syntax().clone(), ast.pat().unwrap().syntax().clone());
+ builder.map_node(iterable.syntax().clone(), ast.iterable().unwrap().syntax().clone());
+ builder.map_node(body.syntax().clone(), ast.loop_body().unwrap().syntax().clone());
+ builder.finish(&mut mapping);
+ }
+
+ ast
+ }
+
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();