Unnamed repository; edit this file 'description' to name the repository.
7 files changed, 81 insertions, 55 deletions
diff --git a/crates/ide-assists/src/handlers/add_label_to_loop.rs b/crates/ide-assists/src/handlers/add_label_to_loop.rs index b84ad24cfc..7e9552e1fd 100644 --- a/crates/ide-assists/src/handlers/add_label_to_loop.rs +++ b/crates/ide-assists/src/handlers/add_label_to_loop.rs @@ -3,11 +3,7 @@ use ide_db::{ }; use syntax::{ SyntaxToken, T, - ast::{ - self, AstNode, HasLoopBody, - make::{self, tokens}, - syntax_factory::SyntaxFactory, - }, + ast::{self, AstNode, HasLoopBody, syntax_factory::SyntaxFactory}, syntax_editor::{Position, SyntaxEditor}, }; @@ -52,8 +48,8 @@ pub(crate) fn add_label_to_loop(acc: &mut Assists, ctx: &AssistContext<'_>) -> O let label = make.lifetime("'l"); let elements = vec![ label.syntax().clone().into(), - make::token(T![:]).into(), - tokens::single_space().into(), + make.token(T![:]).into(), + make.whitespace(" ").into(), ]; editor.insert_all(Position::before(&loop_kw), elements); @@ -88,7 +84,7 @@ fn insert_label_after_token( builder: &mut SourceChangeBuilder, ) { let label = make.lifetime("'l"); - let elements = vec![tokens::single_space().into(), label.syntax().clone().into()]; + let elements = vec![make.whitespace(" ").into(), label.syntax().clone().into()]; editor.insert_all(Position::after(token), elements); if let Some(cap) = ctx.config.snippet_cap { diff --git a/crates/ide-assists/src/handlers/desugar_try_expr.rs b/crates/ide-assists/src/handlers/desugar_try_expr.rs index 9976e34e73..4022030159 100644 --- a/crates/ide-assists/src/handlers/desugar_try_expr.rs +++ b/crates/ide-assists/src/handlers/desugar_try_expr.rs @@ -9,7 +9,6 @@ use syntax::{ ast::{ self, edit::{AstNodeEdit, IndentLevel}, - make, syntax_factory::SyntaxFactory, }, }; @@ -68,41 +67,46 @@ pub(crate) fn desugar_try_expr(acc: &mut Assists, ctx: &AssistContext<'_>) -> Op AssistId::refactor_rewrite("desugar_try_expr_match"), "Replace try expression with match", target, - |edit| { + |builder| { + let make = SyntaxFactory::with_mappings(); + let mut editor = builder.make_editor(try_expr.syntax()); + let sad_pat = match try_enum { - TryEnum::Option => make::path_pat(make::ext::ident_path("None")), - TryEnum::Result => make::tuple_struct_pat( - make::ext::ident_path("Err"), - iter::once(make::path_pat(make::ext::ident_path("err"))), - ) - .into(), + TryEnum::Option => make.path_pat(make.ident_path("None")), + TryEnum::Result => make + .tuple_struct_pat( + make.ident_path("Err"), + iter::once(make.path_pat(make.ident_path("err"))), + ) + .into(), }; let sad_expr = match try_enum { - TryEnum::Option => { - make::expr_return(Some(make::expr_path(make::ext::ident_path("None")))) - } - TryEnum::Result => make::expr_return(Some( - make::expr_call( - make::expr_path(make::ext::ident_path("Err")), - make::arg_list(iter::once(make::expr_path(make::ext::ident_path("err")))), + TryEnum::Option => make.expr_return(Some(make.expr_path(make.ident_path("None")))), + TryEnum::Result => make.expr_return(Some( + make.expr_call( + make.expr_path(make.ident_path("Err")), + make.arg_list(iter::once(make.expr_path(make.ident_path("err")))), ) .into(), )), }; - let happy_arm = make::match_arm( - try_enum.happy_pattern(make::ident_pat(false, false, make::name("it")).into()), + let happy_arm = make.match_arm( + try_enum.happy_pattern(make.ident_pat(false, false, make.name("it")).into()), None, - make::expr_path(make::ext::ident_path("it")), + make.expr_path(make.ident_path("it")), ); - let sad_arm = make::match_arm(sad_pat, None, sad_expr); + let sad_arm = make.match_arm(sad_pat, None, sad_expr.into()); - let match_arm_list = make::match_arm_list([happy_arm, sad_arm]); + let match_arm_list = make.match_arm_list([happy_arm, sad_arm]); - let expr_match = make::expr_match(expr.clone(), match_arm_list) + let expr_match = make + .expr_match(expr.clone(), match_arm_list) .indent(IndentLevel::from_node(try_expr.syntax())); - edit.replace_ast::<ast::Expr>(try_expr.clone().into(), expr_match.into()); + editor.replace(try_expr.syntax(), expr_match.syntax()); + editor.add_mappings(make.finish_with_mappings()); + builder.add_file_edits(ctx.vfs_file_id(), editor); }, ); diff --git a/crates/ide-assists/src/handlers/extract_variable.rs b/crates/ide-assists/src/handlers/extract_variable.rs index 7c60184142..0927755962 100644 --- a/crates/ide-assists/src/handlers/extract_variable.rs +++ b/crates/ide-assists/src/handlers/extract_variable.rs @@ -9,7 +9,6 @@ use syntax::{ ast::{ self, AstNode, edit::{AstNodeEdit, IndentLevel}, - make, syntax_factory::SyntaxFactory, }, syntax_editor::Position, @@ -176,7 +175,7 @@ pub(crate) fn extract_variable(acc: &mut Assists, ctx: &AssistContext<'_>) -> Op let mut editor = edit.make_editor(&expr_replace); let pat_name = make.name(&var_name); - let name_expr = make.expr_path(make::ext::ident_path(&var_name)); + let name_expr = make.expr_path(make.ident_path(&var_name)); if let Some(cap) = ctx.config.snippet_cap { let tabstop = edit.make_tabstop_before(cap); @@ -233,7 +232,7 @@ pub(crate) fn extract_variable(acc: &mut Assists, ctx: &AssistContext<'_>) -> Op Position::before(place), vec![ new_stmt.syntax().clone().into(), - make::tokens::whitespace(&trailing_ws).into(), + make.whitespace(&trailing_ws).into(), ], ); diff --git a/crates/ide-assists/src/handlers/qualify_method_call.rs b/crates/ide-assists/src/handlers/qualify_method_call.rs index 495a84d62b..8b9e6570e9 100644 --- a/crates/ide-assists/src/handlers/qualify_method_call.rs +++ b/crates/ide-assists/src/handlers/qualify_method_call.rs @@ -1,6 +1,6 @@ use hir::{AsAssocItem, AssocItem, AssocItemContainer, ItemInNs, ModuleDef, db::HirDatabase}; use ide_db::assists::AssistId; -use syntax::{AstNode, ast}; +use syntax::{AstNode, ast, ast::syntax_factory::SyntaxFactory}; use crate::{ assist_context::{AssistContext, Assists}, @@ -52,19 +52,25 @@ pub(crate) fn qualify_method_call(acc: &mut Assists, ctx: &AssistContext<'_>) -> cfg, )?; - let qualify_candidate = QualifyCandidate::ImplMethod(ctx.sema.db, call, resolved_call); + let qualify_candidate = QualifyCandidate::ImplMethod(ctx.sema.db, call.clone(), resolved_call); acc.add( AssistId::refactor_rewrite("qualify_method_call"), format!("Qualify `{ident}` method call"), range, |builder| { + let make = SyntaxFactory::with_mappings(); + let mut editor = builder.make_editor(call.syntax()); qualify_candidate.qualify( - |replace_with: String| builder.replace(range, replace_with), + |_| {}, + &mut editor, + &make, &receiver_path, item_in_ns, current_edition, - ) + ); + editor.add_mappings(make.finish_with_mappings()); + builder.add_file_edits(ctx.vfs_file_id(), editor); }, ); Some(()) diff --git a/crates/ide-assists/src/handlers/qualify_path.rs b/crates/ide-assists/src/handlers/qualify_path.rs index b3cf296965..c059f758c4 100644 --- a/crates/ide-assists/src/handlers/qualify_path.rs +++ b/crates/ide-assists/src/handlers/qualify_path.rs @@ -11,7 +11,8 @@ use syntax::Edition; use syntax::ast::HasGenericArgs; use syntax::{ AstNode, ast, - ast::{HasArgList, make}, + ast::{HasArgList, syntax_factory::SyntaxFactory}, + syntax_editor::SyntaxEditor, }; use crate::{ @@ -54,25 +55,25 @@ pub(crate) fn qualify_path(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option let qualify_candidate = match candidate { ImportCandidate::Path(candidate) if !candidate.qualifier.is_empty() => { cov_mark::hit!(qualify_path_qualifier_start); - let path = ast::Path::cast(syntax_under_caret)?; + let path = ast::Path::cast(syntax_under_caret.clone())?; let (prev_segment, segment) = (path.qualifier()?.segment()?, path.segment()?); QualifyCandidate::QualifierStart(segment, prev_segment.generic_arg_list()) } ImportCandidate::Path(_) => { cov_mark::hit!(qualify_path_unqualified_name); - let path = ast::Path::cast(syntax_under_caret)?; + let path = ast::Path::cast(syntax_under_caret.clone())?; let generics = path.segment()?.generic_arg_list(); QualifyCandidate::UnqualifiedName(generics) } ImportCandidate::TraitAssocItem(_) => { cov_mark::hit!(qualify_path_trait_assoc_item); - let path = ast::Path::cast(syntax_under_caret)?; + let path = ast::Path::cast(syntax_under_caret.clone())?; let (qualifier, segment) = (path.qualifier()?, path.segment()?); QualifyCandidate::TraitAssocItem(qualifier, segment) } ImportCandidate::TraitMethod(_) => { cov_mark::hit!(qualify_path_trait_method); - let mcall_expr = ast::MethodCallExpr::cast(syntax_under_caret)?; + let mcall_expr = ast::MethodCallExpr::cast(syntax_under_caret.clone())?; QualifyCandidate::TraitMethod(ctx.sema.db, mcall_expr) } }; @@ -101,12 +102,18 @@ pub(crate) fn qualify_path(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option label(ctx.db(), candidate, &import, current_edition), range, |builder| { + let make = SyntaxFactory::with_mappings(); + let mut editor = builder.make_editor(&syntax_under_caret); qualify_candidate.qualify( |replace_with: String| builder.replace(range, replace_with), + &mut editor, + &make, &import.import_path, import.item_to_import, current_edition, - ) + ); + editor.add_mappings(make.finish_with_mappings()); + builder.add_file_edits(ctx.vfs_file_id(), editor); }, ); } @@ -124,6 +131,8 @@ impl QualifyCandidate<'_> { pub(crate) fn qualify( &self, mut replacer: impl FnMut(String), + editor: &mut SyntaxEditor, + make: &SyntaxFactory, import: &hir::ModPath, item: hir::ItemInNs, edition: Edition, @@ -142,10 +151,10 @@ impl QualifyCandidate<'_> { replacer(format!("<{qualifier} as {import}>::{segment}")); } QualifyCandidate::TraitMethod(db, mcall_expr) => { - Self::qualify_trait_method(db, mcall_expr, replacer, import, item); + Self::qualify_trait_method(db, mcall_expr, editor, make, import, item); } QualifyCandidate::ImplMethod(db, mcall_expr, hir_fn) => { - Self::qualify_fn_call(db, mcall_expr, replacer, import, hir_fn); + Self::qualify_fn_call(db, mcall_expr, editor, make, import, hir_fn); } } } @@ -153,7 +162,8 @@ impl QualifyCandidate<'_> { fn qualify_fn_call( db: &RootDatabase, mcall_expr: &ast::MethodCallExpr, - mut replacer: impl FnMut(String), + editor: &mut SyntaxEditor, + make: &SyntaxFactory, import: ast::Path, hir_fn: &hir::Function, ) -> Option<()> { @@ -165,15 +175,17 @@ impl QualifyCandidate<'_> { if let Some(self_access) = hir_fn.self_param(db).map(|sp| sp.access(db)) { let receiver = match self_access { - hir::Access::Shared => make::expr_ref(receiver, false), - hir::Access::Exclusive => make::expr_ref(receiver, true), + hir::Access::Shared => make.expr_ref(receiver, false), + hir::Access::Exclusive => make.expr_ref(receiver, true), hir::Access::Owned => receiver, }; let arg_list = match arg_list { - Some(args) => make::arg_list(iter::once(receiver).chain(args)), - None => make::arg_list(iter::once(receiver)), + Some(args) => make.arg_list(iter::once(receiver).chain(args)), + None => make.arg_list(iter::once(receiver)), }; - replacer(format!("{import}::{method_name}{generics}{arg_list}")); + let call_path = make.path_from_text(&format!("{import}::{method_name}{generics}")); + let call_expr = make.expr_call(make.expr_path(call_path), arg_list); + editor.replace(mcall_expr.syntax(), call_expr.syntax()); } Some(()) } @@ -181,14 +193,15 @@ impl QualifyCandidate<'_> { fn qualify_trait_method( db: &RootDatabase, mcall_expr: &ast::MethodCallExpr, - replacer: impl FnMut(String), + editor: &mut SyntaxEditor, + make: &SyntaxFactory, import: ast::Path, item: hir::ItemInNs, ) -> Option<()> { let trait_method_name = mcall_expr.name_ref()?; let trait_ = item_as_trait(db, item)?; let method = find_trait_method(db, trait_, &trait_method_name)?; - Self::qualify_fn_call(db, mcall_expr, replacer, import, &method) + Self::qualify_fn_call(db, mcall_expr, editor, make, import, &method) } } diff --git a/crates/ide-assists/src/handlers/replace_let_with_if_let.rs b/crates/ide-assists/src/handlers/replace_let_with_if_let.rs index 5587f1b59c..6ff5f0bbd3 100644 --- a/crates/ide-assists/src/handlers/replace_let_with_if_let.rs +++ b/crates/ide-assists/src/handlers/replace_let_with_if_let.rs @@ -86,8 +86,8 @@ pub(crate) fn replace_let_with_if_let(acc: &mut Assists, ctx: &AssistContext<'_> } fn let_expr_needs_paren(expr: &ast::Expr) -> bool { - let fake_expr_let = - ast::make::expr_let(ast::make::tuple_pat(None).into(), ast::make::ext::expr_unit()); + let make = SyntaxFactory::without_mappings(); + let fake_expr_let = make.expr_let(make.tuple_pat(None).into(), make.expr_unit()); let Some(fake_expr) = fake_expr_let.expr() else { stdx::never!(); return false; diff --git a/crates/syntax/src/ast/syntax_factory/constructors.rs b/crates/syntax/src/ast/syntax_factory/constructors.rs index c94277f8cf..517d805f5f 100644 --- a/crates/syntax/src/ast/syntax_factory/constructors.rs +++ b/crates/syntax/src/ast/syntax_factory/constructors.rs @@ -21,6 +21,14 @@ impl SyntaxFactory { make::name_ref(name).clone_for_update() } + pub fn name_ref_self_ty(&self) -> ast::NameRef { + make::name_ref_self_ty().clone_for_update() + } + + pub fn expr_todo(&self) -> ast::Expr { + make::ext::expr_todo().clone_for_update() + } + pub fn lifetime(&self, text: &str) -> ast::Lifetime { make::lifetime(text).clone_for_update() } |