From c6ea7cbafa6dfdfe6cad577af592b98d9d7dbdcf Mon Sep 17 00:00:00 2001 From: Shoyu Vanilla Date: Sun, 9 Mar 2025 15:51:37 +0900 Subject: [PATCH] internal: Migrate `inline_local_variable` to `SyntaxEditor` --- .../src/handlers/inline_local_variable.rs | 72 ++++++++++--------- .../src/ast/syntax_factory/constructors.rs | 21 ++++++ 2 files changed, 58 insertions(+), 35 deletions(-) diff --git a/crates/ide-assists/src/handlers/inline_local_variable.rs b/crates/ide-assists/src/handlers/inline_local_variable.rs index cc7bea5152..0aa9970a72 100644 --- a/crates/ide-assists/src/handlers/inline_local_variable.rs +++ b/crates/ide-assists/src/handlers/inline_local_variable.rs @@ -5,7 +5,7 @@ use ide_db::{ EditionedFileId, RootDatabase, }; use syntax::{ - ast::{self, AstNode, AstToken, HasName}, + ast::{self, syntax_factory::SyntaxFactory, AstNode, AstToken, HasName}, SyntaxElement, TextRange, }; @@ -43,22 +43,6 @@ pub(crate) fn inline_local_variable(acc: &mut Assists, ctx: &AssistContext<'_>) }?; let initializer_expr = let_stmt.initializer()?; - let delete_range = delete_let.then(|| { - if let Some(whitespace) = let_stmt - .syntax() - .next_sibling_or_token() - .and_then(SyntaxElement::into_token) - .and_then(ast::Whitespace::cast) - { - TextRange::new( - let_stmt.syntax().text_range().start(), - whitespace.syntax().text_range().end(), - ) - } else { - let_stmt.syntax().text_range() - } - }); - let wrap_in_parens = references .into_iter() .filter_map(|FileReference { range, name, .. }| match name { @@ -76,37 +60,55 @@ pub(crate) fn inline_local_variable(acc: &mut Assists, ctx: &AssistContext<'_>) let usage_parent_option = usage_node.and_then(|it| it.parent()); let usage_parent = match usage_parent_option { Some(u) => u, - None => return Some((range, name_ref, false)), + None => return Some((name_ref, false)), }; - Some((range, name_ref, initializer_expr.needs_parens_in(&usage_parent))) + Some((name_ref, initializer_expr.needs_parens_in(&usage_parent))) }) .collect::>>()?; - let init_str = initializer_expr.syntax().text().to_string(); - let init_in_paren = format!("({init_str})"); - let target = match target { - ast::NameOrNameRef::Name(it) => it.syntax().text_range(), - ast::NameOrNameRef::NameRef(it) => it.syntax().text_range(), + ast::NameOrNameRef::Name(it) => it.syntax().clone(), + ast::NameOrNameRef::NameRef(it) => it.syntax().clone(), }; acc.add( AssistId("inline_local_variable", AssistKind::RefactorInline), "Inline variable", - target, + target.text_range(), move |builder| { - if let Some(range) = delete_range { - builder.delete(range); - } - for (range, name, should_wrap) in wrap_in_parens { - let replacement = if should_wrap { &init_in_paren } else { &init_str }; - if ast::RecordExprField::for_field_name(&name).is_some() { - cov_mark::hit!(inline_field_shorthand); - builder.insert(range.end(), format!(": {replacement}")); - } else { - builder.replace(range, replacement.clone()) + let mut editor = builder.make_editor(&target); + if delete_let { + editor.delete(let_stmt.syntax()); + if let Some(whitespace) = let_stmt + .syntax() + .next_sibling_or_token() + .and_then(SyntaxElement::into_token) + .and_then(ast::Whitespace::cast) + { + editor.delete(whitespace.syntax()); } } + + let make = SyntaxFactory::new(); + + for (name, should_wrap) in wrap_in_parens { + let replacement = if should_wrap { + make.expr_paren(initializer_expr.clone()).into() + } else { + initializer_expr.clone() + }; + + if let Some(record_field) = ast::RecordExprField::for_field_name(&name) { + cov_mark::hit!(inline_field_shorthand); + let replacement = make.record_expr_field(name, Some(replacement)); + editor.replace(record_field.syntax(), replacement.syntax()); + } else { + editor.replace(name.syntax(), replacement.syntax()); + } + } + + editor.add_mappings(make.finish_with_mappings()); + builder.add_file_edits(ctx.file_id(), editor); }, ) } diff --git a/crates/syntax/src/ast/syntax_factory/constructors.rs b/crates/syntax/src/ast/syntax_factory/constructors.rs index 85393ca5b4..44f13041c2 100644 --- a/crates/syntax/src/ast/syntax_factory/constructors.rs +++ b/crates/syntax/src/ast/syntax_factory/constructors.rs @@ -783,6 +783,27 @@ impl SyntaxFactory { ast } + pub fn record_expr_field( + &self, + name: ast::NameRef, + expr: Option, + ) -> ast::RecordExprField { + let ast = make::record_expr_field(name.clone(), expr.clone()).clone_for_update(); + + if let Some(mut mapping) = self.mappings() { + let mut builder = SyntaxMappingBuilder::new(ast.syntax().clone()); + + builder.map_node(name.syntax().clone(), ast.name_ref().unwrap().syntax().clone()); + if let Some(expr) = expr { + builder.map_node(expr.syntax().clone(), ast.expr().unwrap().syntax().clone()); + } + + builder.finish(&mut mapping); + } + + ast + } + pub fn record_field_list( &self, fields: impl IntoIterator,