Unnamed repository; edit this file 'description' to name the repository.
8 files changed, 91 insertions, 81 deletions
diff --git a/crates/ide-assists/src/handlers/add_missing_match_arms.rs b/crates/ide-assists/src/handlers/add_missing_match_arms.rs index 9f267daa10..3c33ddec31 100644 --- a/crates/ide-assists/src/handlers/add_missing_match_arms.rs +++ b/crates/ide-assists/src/handlers/add_missing_match_arms.rs @@ -8,7 +8,7 @@ use ide_db::{famous_defs::FamousDefs, helpers::mod_path_to_ast}; use itertools::Itertools; use syntax::ast::edit::IndentLevel; use syntax::ast::syntax_factory::SyntaxFactory; -use syntax::ast::{self, AstNode, MatchArmList, MatchExpr, Pat, make}; +use syntax::ast::{self, AstNode, MatchArmList, MatchExpr, Pat}; use syntax::syntax_editor::{Position, SyntaxEditor}; use syntax::{SyntaxKind, SyntaxNode, ToSmolStr}; @@ -592,12 +592,12 @@ fn build_pat( ExtendedVariant::Variant { variant: var, use_self } => { let edition = module.krate(db).edition(db); let path = if use_self { - make::path_from_segments( + make.path_from_segments( [ - make::path_segment(make::name_ref_self_ty()), - make::path_segment(make::name_ref( - &var.name(db).display(db, edition).to_smolstr(), - )), + make.path_segment(make.name_ref_self_ty()), + make.path_segment( + make.name_ref(&var.name(db).display(db, edition).to_smolstr()), + ), ], false, ) @@ -611,7 +611,7 @@ fn build_pat( let pats = fields.into_iter().map(|f| { let name = name_generator.for_type(&f.ty(db).to_type(db), db, edition); match name { - Some(name) => make::ext::simple_ident_pat(make.name(&name)).into(), + Some(name) => make.ident_pat(false, false, make.name(&name)).into(), None => make.wildcard_pat().into(), } }); diff --git a/crates/ide-assists/src/handlers/convert_named_struct_to_tuple_struct.rs b/crates/ide-assists/src/handlers/convert_named_struct_to_tuple_struct.rs index 21404564fa..5b691dba5e 100644 --- a/crates/ide-assists/src/handlers/convert_named_struct_to_tuple_struct.rs +++ b/crates/ide-assists/src/handlers/convert_named_struct_to_tuple_struct.rs @@ -99,21 +99,20 @@ fn edit_struct_def( ) { // Note that we don't need to consider macro files in this function because this is // currently not triggered for struct definitions inside macro calls. + let editor = builder.make_editor(strukt.syntax()); + let make = editor.make(); + let tuple_fields = record_fields.fields().filter_map(|f| { - let (editor, field) = - SyntaxEditor::with_ast_node(&ast::make::tuple_field(f.visibility(), f.ty()?)); - editor.insert_all( + let (field_editor, field) = + SyntaxEditor::with_ast_node(&make.tuple_field(f.visibility(), f.ty()?)); + field_editor.insert_all( Position::first_child_of(field.syntax()), f.attrs().map(|attr| attr.syntax().clone().into()).collect(), ); - let field_syntax = editor.finish().new_root().clone(); - let field = ast::TupleField::cast(field_syntax)?; - Some(field) + let field_syntax = field_editor.finish().new_root().clone(); + ast::TupleField::cast(field_syntax) }); - let editor = builder.make_editor(strukt.syntax()); - let make = editor.make(); - let tuple_fields = make.tuple_field_list(tuple_fields); let mut elements = vec![tuple_fields.syntax().clone().into()]; diff --git a/crates/ide-assists/src/handlers/convert_tuple_struct_to_named_struct.rs b/crates/ide-assists/src/handlers/convert_tuple_struct_to_named_struct.rs index a1b33a0558..afbcf024b9 100644 --- a/crates/ide-assists/src/handlers/convert_tuple_struct_to_named_struct.rs +++ b/crates/ide-assists/src/handlers/convert_tuple_struct_to_named_struct.rs @@ -105,7 +105,7 @@ fn edit_struct_def( let make = editor.make(); let record_fields = tuple_fields.fields().zip(names).filter_map(|(f, name)| { let (field_editor, field) = - SyntaxEditor::with_ast_node(&ast::make::record_field(f.visibility(), name, f.ty()?)); + SyntaxEditor::with_ast_node(&make.record_field(f.visibility(), name, f.ty()?)); field_editor.insert_all( Position::first_child_of(field.syntax()), f.attrs().map(|attr| attr.syntax().clone().into()).collect(), @@ -119,21 +119,21 @@ fn edit_struct_def( if let Some(w) = strukt.where_clause() { editor.delete(w.syntax()); let mut insert_element = Vec::new(); - insert_element.push(ast::make::tokens::single_newline().syntax_element()); + insert_element.push(make.whitespace("\n").syntax_element()); insert_element.push(w.syntax().syntax_element()); if w.syntax().last_token().is_none_or(|t| t.kind() != SyntaxKind::COMMA) { - insert_element.push(ast::make::token(T![,]).into()); + insert_element.push(make.token(T![,]).into()); } - insert_element.push(ast::make::tokens::single_newline().syntax_element()); + insert_element.push(make.whitespace("\n").syntax_element()); editor.insert_all(tuple_fields_before, insert_element); } else { - editor.insert(tuple_fields_before, ast::make::tokens::single_space()); + editor.insert(tuple_fields_before, make.whitespace(" ")); } if let Some(t) = strukt.semicolon_token() { editor.delete(t); } } else { - editor.insert(tuple_fields_before, ast::make::tokens::single_space()); + editor.insert(tuple_fields_before, make.whitespace(" ")); } editor.replace(tuple_fields.syntax(), record_fields.syntax()); @@ -189,7 +189,7 @@ fn process_struct_name_reference( let range = ctx.sema.original_range_opt(tuple_struct_pat.syntax())?.range; let new = make.record_pat_with_fields( full_path, - generate_record_pat_list(&tuple_struct_pat, names), + generate_record_pat_list(&tuple_struct_pat, names, make), ); editor.replace_all(cover_edit_range(source.syntax(), range), vec![new.syntax().clone().into()]); }, @@ -316,6 +316,7 @@ fn generate_names( fn generate_record_pat_list( pat: &ast::TupleStructPat, names: &[ast::Name], + make: &SyntaxFactory, ) -> ast::RecordPatFieldList { let pure_fields = pat.fields().filter(|p| !matches!(p, ast::Pat::RestPat(_))); let rest_len = names.len().saturating_sub(pure_fields.clone().count()); @@ -327,8 +328,8 @@ fn generate_record_pat_list( let fields = before_rest .chain(after_rest) - .map(|(pat, name)| ast::make::record_pat_field(ast::make::name_ref(&name.text()), pat)); - ast::make::record_pat_field_list(fields, rest_pat) + .map(|(pat, name)| make.record_pat_field(make.name_ref(&name.text()), pat)); + make.record_pat_field_list(fields, rest_pat) } #[cfg(test)] diff --git a/crates/ide-assists/src/handlers/generate_trait_from_impl.rs b/crates/ide-assists/src/handlers/generate_trait_from_impl.rs index f5342b8b70..049398de8c 100644 --- a/crates/ide-assists/src/handlers/generate_trait_from_impl.rs +++ b/crates/ide-assists/src/handlers/generate_trait_from_impl.rs @@ -3,7 +3,8 @@ use ide_db::assists::AssistId; use syntax::{ AstNode, AstToken, SyntaxKind, T, ast::{ - self, HasDocComments, HasGenericParams, HasName, HasVisibility, edit::AstNodeEdit, make, + self, HasDocComments, HasGenericParams, HasName, HasVisibility, edit::AstNodeEdit, + syntax_factory::SyntaxFactory, }, syntax_editor::{Position, SyntaxEditor}, }; @@ -112,7 +113,7 @@ pub(crate) fn generate_trait_from_impl(acc: &mut Assists, ctx: &AssistContext<'_ let make = editor.make(); let trait_ast = make.trait_( false, - &trait_name(&impl_assoc_items).text(), + &trait_name(&impl_assoc_items, make).text(), impl_ast.generic_param_list(), impl_ast.where_clause(), trait_items, @@ -124,9 +125,9 @@ pub(crate) fn generate_trait_from_impl(acc: &mut Assists, ctx: &AssistContext<'_ // Change `impl Foo` to `impl NewTrait for Foo` let mut elements = vec![ trait_name_ref.syntax().clone().into(), - make::tokens::single_space().into(), - make::token(T![for]).into(), - make::tokens::single_space().into(), + make.whitespace(" ").into(), + make.token(T![for]).into(), + make.whitespace(" ").into(), ]; if let Some(params) = impl_ast.generic_param_list() { @@ -146,7 +147,7 @@ pub(crate) fn generate_trait_from_impl(acc: &mut Assists, ctx: &AssistContext<'_ Position::before(impl_ast.syntax()), vec![ trait_ast.syntax().clone().into(), - make::tokens::whitespace(&format!("\n\n{}", impl_ast.indent_level())).into(), + make.whitespace(&format!("\n\n{}", impl_ast.indent_level())).into(), ], ); @@ -163,16 +164,16 @@ pub(crate) fn generate_trait_from_impl(acc: &mut Assists, ctx: &AssistContext<'_ Some(()) } -fn trait_name(items: &ast::AssocItemList) -> ast::Name { +fn trait_name(items: &ast::AssocItemList, make: &SyntaxFactory) -> ast::Name { let mut fn_names = items .assoc_items() .filter_map(|x| if let ast::AssocItem::Fn(f) = x { f.name() } else { None }); fn_names .next() .and_then(|name| { - fn_names.next().is_none().then(|| make::name(&stdx::to_camel_case(&name.text()))) + fn_names.next().is_none().then(|| make.name(&stdx::to_camel_case(&name.text()))) }) - .unwrap_or_else(|| make::name("NewTrait")) + .unwrap_or_else(|| make.name("NewTrait")) } /// `E0449` Trait items always share the visibility of their trait @@ -202,6 +203,7 @@ fn remove_doc_comments(editor: &SyntaxEditor, item: &ast::AssocItem) { } fn strip_body(editor: &SyntaxEditor, item: &ast::AssocItem) { + let make = editor.make(); if let ast::AssocItem::Fn(f) = item && let Some(body) = f.body() { @@ -213,7 +215,7 @@ fn strip_body(editor: &SyntaxEditor, item: &ast::AssocItem) { editor.delete(prev); } - editor.replace(body.syntax(), make::tokens::semicolon()); + editor.replace(body.syntax(), make.token(T![;])); }; } diff --git a/crates/ide-assists/src/handlers/remove_dbg.rs b/crates/ide-assists/src/handlers/remove_dbg.rs index 32fae8a5bb..778533be5a 100644 --- a/crates/ide-assists/src/handlers/remove_dbg.rs +++ b/crates/ide-assists/src/handlers/remove_dbg.rs @@ -1,7 +1,7 @@ use itertools::Itertools; use syntax::{ Edition, NodeOrToken, SyntaxNode, SyntaxToken, T, - ast::{self, AstNode, make}, + ast::{self, AstNode, syntax_factory::SyntaxFactory}, match_ast, syntax_editor::{Position, SyntaxEditor}, }; @@ -24,6 +24,8 @@ use crate::{AssistContext, AssistId, Assists}; // } // ``` pub(crate) fn remove_dbg(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> { + let (editor, _) = SyntaxEditor::new(ctx.source_file().syntax().clone()); + let make = editor.make(); let macro_calls = if ctx.has_empty_selection() { vec![ctx.find_node_at_offset::<ast::MacroExpr>()?] } else { @@ -39,15 +41,16 @@ pub(crate) fn remove_dbg(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<( .collect() }; - let replacements = - macro_calls.into_iter().filter_map(compute_dbg_replacement).collect::<Vec<_>>(); + let replacements = macro_calls + .into_iter() + .filter_map(|macro_expr| compute_dbg_replacement(macro_expr, make)) + .collect::<Vec<_>>(); let target = replacements .iter() .flat_map(|(node_or_token, _)| node_or_token.iter()) .map(|t| t.text_range()) .reduce(|acc, range| acc.cover(range))?; acc.add(AssistId::quick_fix("remove_dbg"), "Remove dbg!()", target, |builder| { - let editor = builder.make_editor(ctx.source_file().syntax()); for (range, expr) in replacements { if let Some(expr) = expr { editor.insert(Position::before(range[0].clone()), expr.syntax()); @@ -68,6 +71,7 @@ pub(crate) fn remove_dbg(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<( /// Returns `Some(_, None)` when the macro call should just be removed. fn compute_dbg_replacement( macro_expr: ast::MacroExpr, + make: &SyntaxFactory, ) -> Option<(Vec<NodeOrToken<SyntaxNode, SyntaxToken>>, Option<ast::Expr>)> { let macro_call = macro_expr.macro_call()?; let tt = macro_call.token_tree()?; @@ -110,7 +114,7 @@ fn compute_dbg_replacement( } (replace, None) }, - _ => (vec![macro_call.syntax().clone().into()], Some(make::ext::expr_unit())), + _ => (vec![macro_call.syntax().clone().into()], Some(make.expr_unit())), } } } @@ -162,14 +166,14 @@ fn compute_dbg_replacement( }, None => false, }; - let expr = replace_nested_dbgs(expr.clone()); - let expr = if wrap { make::expr_paren(expr).into() } else { expr }; + let expr = replace_nested_dbgs(expr.clone(), make); + let expr = if wrap { make.expr_paren(expr).into() } else { expr }; (vec![macro_call.syntax().clone().into()], Some(expr)) } // dbg!(expr0, expr1, ...) exprs => { - let exprs = exprs.iter().cloned().map(replace_nested_dbgs); - let expr = make::expr_tuple(exprs); + let exprs = exprs.iter().cloned().map(|expr| replace_nested_dbgs(expr, make)); + let expr = make.expr_tuple(exprs); (vec![macro_call.syntax().clone().into()], Some(expr.into())) } }) @@ -189,12 +193,12 @@ fn pure_expr(expr: &ast::Expr) -> bool { } } -fn replace_nested_dbgs(expanded: ast::Expr) -> ast::Expr { +fn replace_nested_dbgs(expanded: ast::Expr, make: &SyntaxFactory) -> ast::Expr { if let ast::Expr::MacroExpr(mac) = &expanded { // Special-case when `expanded` itself is `dbg!()` since we cannot replace the whole tree // with `ted`. It should be fairly rare as it means the user wrote `dbg!(dbg!(..))` but you // never know how code ends up being! - let replaced = if let Some((_, expr_opt)) = compute_dbg_replacement(mac.clone()) { + let replaced = if let Some((_, expr_opt)) = compute_dbg_replacement(mac.clone(), make) { match expr_opt { Some(expr) => expr, None => { @@ -215,7 +219,7 @@ fn replace_nested_dbgs(expanded: ast::Expr) -> ast::Expr { expanded.syntax().descendants().filter_map(ast::MacroExpr::cast).collect(); for mac in macro_exprs { - let expr_opt = match compute_dbg_replacement(mac.clone()) { + let expr_opt = match compute_dbg_replacement(mac.clone(), make) { Some((_, expr)) => expr, None => continue, }; diff --git a/crates/ide-assists/src/handlers/unmerge_imports.rs b/crates/ide-assists/src/handlers/unmerge_imports.rs index 8875a72246..ab6317ad44 100644 --- a/crates/ide-assists/src/handlers/unmerge_imports.rs +++ b/crates/ide-assists/src/handlers/unmerge_imports.rs @@ -1,7 +1,7 @@ use syntax::{ AstNode, SyntaxKind, - ast::{self, HasAttrs, HasVisibility, edit::IndentLevel, make}, - syntax_editor::{Element, Position, Removable}, + ast::{self, HasAttrs, HasVisibility, edit::IndentLevel, syntax_factory::SyntaxFactory}, + syntax_editor::{Element, Position, Removable, SyntaxEditor}, }; use crate::{ @@ -22,6 +22,8 @@ use crate::{ // use std::fmt::Display; // ``` pub(crate) fn unmerge_imports(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> { + let (editor, _) = SyntaxEditor::new(ctx.source_file().syntax().clone()); + let make = editor.make(); let tree = ctx.find_node_at_offset::<ast::UseTree>()?; let tree_list = tree.syntax().parent().and_then(ast::UseTreeList::cast)?; @@ -31,7 +33,7 @@ pub(crate) fn unmerge_imports(acc: &mut Assists, ctx: &AssistContext<'_>) -> Opt } let use_ = tree_list.syntax().ancestors().find_map(ast::Use::cast)?; - let path = resolve_full_path(&tree)?; + let path = resolve_full_path(&tree, make)?; // If possible, explain what is going to be done. let label = match tree.path().and_then(|path| path.first_segment()) { @@ -41,7 +43,6 @@ pub(crate) fn unmerge_imports(acc: &mut Assists, ctx: &AssistContext<'_>) -> Opt let target = tree.syntax().text_range(); acc.add(AssistId::refactor_rewrite("unmerge_imports"), label, target, |builder| { - let editor = builder.make_editor(use_.syntax()); let make = editor.make(); let new_use = make.use_( use_.attrs(), @@ -64,7 +65,7 @@ pub(crate) fn unmerge_imports(acc: &mut Assists, ctx: &AssistContext<'_>) -> Opt }) } -fn resolve_full_path(tree: &ast::UseTree) -> Option<ast::Path> { +fn resolve_full_path(tree: &ast::UseTree, make: &SyntaxFactory) -> Option<ast::Path> { let paths = tree .syntax() .ancestors() @@ -72,7 +73,7 @@ fn resolve_full_path(tree: &ast::UseTree) -> Option<ast::Path> { .filter_map(ast::UseTree::cast) .filter_map(|t| t.path()); - let final_path = paths.reduce(|prev, next| make::path_concat(next, prev))?; + let final_path = paths.reduce(|prev, next| make.path_concat(next, prev))?; if final_path.segment().is_some_and(|it| it.self_token().is_some()) { final_path.qualifier() } else { diff --git a/crates/ide-assists/src/handlers/unwrap_block.rs b/crates/ide-assists/src/handlers/unwrap_block.rs index 23bbe21437..77941bcfb2 100644 --- a/crates/ide-assists/src/handlers/unwrap_block.rs +++ b/crates/ide-assists/src/handlers/unwrap_block.rs @@ -3,7 +3,6 @@ use syntax::{ ast::{ self, edit::{AstNodeEdit, IndentLevel}, - make, }, match_ast, syntax_editor::{Element, Position, SyntaxEditor}, @@ -83,7 +82,8 @@ pub(crate) fn unwrap_block(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option }) } -fn delete_else_before(container: SyntaxNode, edit: &SyntaxEditor) { +fn delete_else_before(container: SyntaxNode, editor: &SyntaxEditor) { + let make = editor.make(); let Some(else_token) = container .siblings_with_tokens(syntax::Direction::Prev) .skip(1) @@ -94,10 +94,10 @@ fn delete_else_before(container: SyntaxNode, edit: &SyntaxEditor) { }; itertools::chain(else_token.prev_token(), else_token.next_token()) .filter(|it| it.kind() == SyntaxKind::WHITESPACE) - .for_each(|it| edit.delete(it)); + .for_each(|it| editor.delete(it)); let indent = IndentLevel::from_node(&container); - let newline = make::tokens::whitespace(&format!("\n{indent}")); - edit.replace(else_token, newline); + let newline = make.whitespace(&format!("\n{indent}")); + editor.replace(else_token, newline); } fn wrap_let(assign: &ast::LetStmt, replacement: ast::BlockExpr) -> ast::BlockExpr { diff --git a/crates/ide-assists/src/handlers/wrap_unwrap_cfg_attr.rs b/crates/ide-assists/src/handlers/wrap_unwrap_cfg_attr.rs index f40769e0d7..635fab857d 100644 --- a/crates/ide-assists/src/handlers/wrap_unwrap_cfg_attr.rs +++ b/crates/ide-assists/src/handlers/wrap_unwrap_cfg_attr.rs @@ -1,8 +1,7 @@ use ide_db::source_change::SourceChangeBuilder; -use itertools::Itertools; use syntax::{ NodeOrToken, SyntaxToken, T, TextRange, algo, - ast::{self, AstNode, edit::AstNodeEdit, make}, + ast::{self, AstNode, edit::AstNodeEdit}, }; use crate::{AssistContext, AssistId, Assists}; @@ -151,7 +150,7 @@ pub(crate) fn wrap_unwrap_cfg_attr(acc: &mut Assists, ctx: &AssistContext<'_>) - if let [attr] = &attrs[..] && let Some(ast::Meta::CfgAttrMeta(meta)) = attr.meta() { - unwrap_cfg_attr(acc, meta) + unwrap_cfg_attr(acc, ctx, meta) } else { wrap_cfg_attrs(acc, ctx, attrs) } @@ -267,37 +266,41 @@ fn wrap_cfg_attrs(acc: &mut Assists, ctx: &AssistContext<'_>, attrs: Vec<ast::At Some(()) } -fn unwrap_cfg_attr(acc: &mut Assists, meta: ast::CfgAttrMeta) -> Option<()> { +fn unwrap_cfg_attr( + acc: &mut Assists, + ctx: &AssistContext<'_>, + meta: ast::CfgAttrMeta, +) -> Option<()> { let top_attr = ast::Meta::from(meta.clone()).parent_attr()?; let range = top_attr.syntax().text_range(); - let inner_attrs = meta - .metas() - .map(|meta| { - if top_attr.excl_token().is_some() { - make::attr_inner(meta) - } else { - make::attr_outer(meta) - } - }) - .collect::<Vec<_>>(); - if inner_attrs.is_empty() { + let inner_metas: Vec<ast::Meta> = meta.metas().collect(); + if inner_metas.is_empty() { return None; } - let handle_source_change = |f: &mut SourceChangeBuilder| { - let inner_attrs = inner_attrs - .iter() - .map(|it| it.to_string()) - .join(&format!("\n{}", top_attr.indent_level())); - f.replace(range, inner_attrs); - }; + let is_inner = top_attr.excl_token().is_some(); + let indent = top_attr.indent_level(); acc.add( AssistId::refactor("wrap_unwrap_cfg_attr"), "Extract Inner Attributes from `cfg_attr`", range, - handle_source_change, + |builder: &mut SourceChangeBuilder| { + let editor = builder.make_editor(top_attr.syntax()); + let make = editor.make(); + let mut elements = vec![]; + for (i, meta) in inner_metas.into_iter().enumerate() { + if i > 0 { + elements.push(make.whitespace(&format!("\n{indent}")).into()); + } + let attr = if is_inner { make.attr_inner(meta) } else { make.attr_outer(meta) }; + elements.push(attr.syntax().clone().into()); + } + editor.replace_with_many(top_attr.syntax(), elements); + builder.add_file_edits(ctx.vfs_file_id(), editor); + }, ); Some(()) } + #[cfg(test)] mod tests { use crate::tests::check_assist; |