Remove SyntaxRewriter usage in insert_use in favor of ted
This commit is contained in:
parent
e8744ed9bb
commit
fa20a5064b
8 changed files with 185 additions and 243 deletions
|
|
@ -101,9 +101,11 @@ pub(crate) fn auto_import(acc: &mut Assists, ctx: &AssistContext) -> Option<()>
|
|||
format!("Import `{}`", import.import_path),
|
||||
range,
|
||||
|builder| {
|
||||
let rewriter =
|
||||
insert_use(&scope, mod_path_to_ast(&import.import_path), ctx.config.insert_use);
|
||||
builder.rewrite(rewriter);
|
||||
let scope = match scope.clone() {
|
||||
ImportScope::File(it) => ImportScope::File(builder.make_ast_mut(it)),
|
||||
ImportScope::Module(it) => ImportScope::Module(builder.make_ast_mut(it)),
|
||||
};
|
||||
insert_use(&scope, mod_path_to_ast(&import.import_path), ctx.config.insert_use);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,9 +13,9 @@ use ide_db::{
|
|||
};
|
||||
use rustc_hash::FxHashSet;
|
||||
use syntax::{
|
||||
algo::{find_node_at_offset, SyntaxRewriter},
|
||||
ast::{self, edit::IndentLevel, make, AstNode, NameOwner, VisibilityOwner},
|
||||
SourceFile, SyntaxElement, SyntaxNode, T,
|
||||
algo::find_node_at_offset,
|
||||
ast::{self, make, AstNode, NameOwner, VisibilityOwner},
|
||||
ted, SourceFile, SyntaxElement, SyntaxNode, T,
|
||||
};
|
||||
|
||||
use crate::{AssistContext, AssistId, AssistKind, Assists};
|
||||
|
|
@ -62,14 +62,17 @@ pub(crate) fn extract_struct_from_enum_variant(
|
|||
let mut visited_modules_set = FxHashSet::default();
|
||||
let current_module = enum_hir.module(ctx.db());
|
||||
visited_modules_set.insert(current_module);
|
||||
let mut def_rewriter = None;
|
||||
let mut def_file_references = None;
|
||||
for (file_id, references) in usages {
|
||||
let mut rewriter = SyntaxRewriter::default();
|
||||
let source_file = ctx.sema.parse(file_id);
|
||||
if file_id == ctx.frange.file_id {
|
||||
def_file_references = Some(references);
|
||||
continue;
|
||||
}
|
||||
builder.edit_file(file_id);
|
||||
let source_file = builder.make_ast_mut(ctx.sema.parse(file_id));
|
||||
for reference in references {
|
||||
update_reference(
|
||||
ctx,
|
||||
&mut rewriter,
|
||||
reference,
|
||||
&source_file,
|
||||
&enum_module_def,
|
||||
|
|
@ -77,25 +80,27 @@ pub(crate) fn extract_struct_from_enum_variant(
|
|||
&mut visited_modules_set,
|
||||
);
|
||||
}
|
||||
if file_id == ctx.frange.file_id {
|
||||
def_rewriter = Some(rewriter);
|
||||
continue;
|
||||
}
|
||||
builder.edit_file(file_id);
|
||||
builder.rewrite(rewriter);
|
||||
}
|
||||
let mut rewriter = def_rewriter.unwrap_or_default();
|
||||
update_variant(&mut rewriter, &variant);
|
||||
builder.edit_file(ctx.frange.file_id);
|
||||
let variant = builder.make_ast_mut(variant.clone());
|
||||
let source_file = builder.make_ast_mut(ctx.sema.parse(ctx.frange.file_id));
|
||||
for reference in def_file_references.into_iter().flatten() {
|
||||
update_reference(
|
||||
ctx,
|
||||
reference,
|
||||
&source_file,
|
||||
&enum_module_def,
|
||||
&variant_hir_name,
|
||||
&mut visited_modules_set,
|
||||
);
|
||||
}
|
||||
extract_struct_def(
|
||||
&mut rewriter,
|
||||
&enum_ast,
|
||||
variant_name.clone(),
|
||||
&field_list,
|
||||
&variant.parent_enum().syntax().clone().into(),
|
||||
enum_ast.visibility(),
|
||||
);
|
||||
builder.edit_file(ctx.frange.file_id);
|
||||
builder.rewrite(rewriter);
|
||||
update_variant(&variant);
|
||||
},
|
||||
)
|
||||
}
|
||||
|
|
@ -138,7 +143,6 @@ fn existing_definition(db: &RootDatabase, variant_name: &ast::Name, variant: &Va
|
|||
|
||||
fn insert_import(
|
||||
ctx: &AssistContext,
|
||||
rewriter: &mut SyntaxRewriter,
|
||||
scope_node: &SyntaxNode,
|
||||
module: &Module,
|
||||
enum_module_def: &ModuleDef,
|
||||
|
|
@ -151,14 +155,12 @@ fn insert_import(
|
|||
mod_path.pop_segment();
|
||||
mod_path.push_segment(variant_hir_name.clone());
|
||||
let scope = ImportScope::find_insert_use_container(scope_node, &ctx.sema)?;
|
||||
*rewriter += insert_use(&scope, mod_path_to_ast(&mod_path), ctx.config.insert_use);
|
||||
insert_use(&scope, mod_path_to_ast(&mod_path), ctx.config.insert_use);
|
||||
}
|
||||
Some(())
|
||||
}
|
||||
|
||||
fn extract_struct_def(
|
||||
rewriter: &mut SyntaxRewriter,
|
||||
enum_: &ast::Enum,
|
||||
variant_name: ast::Name,
|
||||
field_list: &Either<ast::RecordFieldList, ast::TupleFieldList>,
|
||||
start_offset: &SyntaxElement,
|
||||
|
|
@ -180,33 +182,34 @@ fn extract_struct_def(
|
|||
.into(),
|
||||
};
|
||||
|
||||
rewriter.insert_before(
|
||||
start_offset,
|
||||
make::struct_(visibility, variant_name, None, field_list).syntax(),
|
||||
ted::insert_raw(
|
||||
ted::Position::before(start_offset),
|
||||
make::struct_(visibility, variant_name, None, field_list).clone_for_update().syntax(),
|
||||
);
|
||||
rewriter.insert_before(start_offset, &make::tokens::blank_line());
|
||||
ted::insert_raw(ted::Position::before(start_offset), &make::tokens::blank_line());
|
||||
|
||||
if let indent_level @ 1..=usize::MAX = IndentLevel::from_node(enum_.syntax()).0 as usize {
|
||||
rewriter
|
||||
.insert_before(start_offset, &make::tokens::whitespace(&" ".repeat(4 * indent_level)));
|
||||
}
|
||||
// if let indent_level @ 1..=usize::MAX = IndentLevel::from_node(enum_.syntax()).0 as usize {
|
||||
// ted::insert(ted::Position::before(start_offset), &make::tokens::blank_line());
|
||||
// rewriter
|
||||
// .insert_before(start_offset, &make::tokens::whitespace(&" ".repeat(4 * indent_level)));
|
||||
// }
|
||||
Some(())
|
||||
}
|
||||
|
||||
fn update_variant(rewriter: &mut SyntaxRewriter, variant: &ast::Variant) -> Option<()> {
|
||||
fn update_variant(variant: &ast::Variant) -> Option<()> {
|
||||
let name = variant.name()?;
|
||||
let tuple_field = make::tuple_field(None, make::ty(&name.text()));
|
||||
let replacement = make::variant(
|
||||
name,
|
||||
Some(ast::FieldList::TupleFieldList(make::tuple_field_list(iter::once(tuple_field)))),
|
||||
);
|
||||
rewriter.replace(variant.syntax(), replacement.syntax());
|
||||
)
|
||||
.clone_for_update();
|
||||
ted::replace(variant.syntax(), replacement.syntax());
|
||||
Some(())
|
||||
}
|
||||
|
||||
fn update_reference(
|
||||
ctx: &AssistContext,
|
||||
rewriter: &mut SyntaxRewriter,
|
||||
reference: FileReference,
|
||||
source_file: &SourceFile,
|
||||
enum_module_def: &ModuleDef,
|
||||
|
|
@ -230,14 +233,16 @@ fn update_reference(
|
|||
|
||||
let module = ctx.sema.scope(&expr).module()?;
|
||||
if !visited_modules_set.contains(&module) {
|
||||
if insert_import(ctx, rewriter, &expr, &module, enum_module_def, variant_hir_name).is_some()
|
||||
{
|
||||
if insert_import(ctx, &expr, &module, enum_module_def, variant_hir_name).is_some() {
|
||||
visited_modules_set.insert(module);
|
||||
}
|
||||
}
|
||||
rewriter.insert_after(segment.syntax(), &make::token(T!['(']));
|
||||
rewriter.insert_after(segment.syntax(), segment.syntax());
|
||||
rewriter.insert_after(&expr, &make::token(T![')']));
|
||||
ted::insert_raw(
|
||||
ted::Position::before(segment.syntax()),
|
||||
make::path_from_text(&format!("{}", segment)).clone_for_update().syntax(),
|
||||
);
|
||||
ted::insert_raw(ted::Position::before(segment.syntax()), make::token(T!['(']));
|
||||
ted::insert_raw(ted::Position::after(&expr), make::token(T![')']));
|
||||
Some(())
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
use ide_db::helpers::insert_use::{insert_use, ImportScope};
|
||||
use syntax::{algo::SyntaxRewriter, ast, match_ast, AstNode, SyntaxNode};
|
||||
use syntax::{ast, match_ast, ted, AstNode, SyntaxNode};
|
||||
|
||||
use crate::{AssistContext, AssistId, AssistKind, Assists};
|
||||
|
||||
|
|
@ -40,18 +40,17 @@ pub(crate) fn replace_qualified_name_with_use(
|
|||
|builder| {
|
||||
// Now that we've brought the name into scope, re-qualify all paths that could be
|
||||
// affected (that is, all paths inside the node we added the `use` to).
|
||||
let mut rewriter = SyntaxRewriter::default();
|
||||
shorten_paths(&mut rewriter, syntax.clone(), &path);
|
||||
let syntax = builder.make_mut(syntax.clone());
|
||||
if let Some(ref import_scope) = ImportScope::from(syntax.clone()) {
|
||||
rewriter += insert_use(import_scope, path, ctx.config.insert_use);
|
||||
builder.rewrite(rewriter);
|
||||
insert_use(import_scope, path.clone(), ctx.config.insert_use);
|
||||
}
|
||||
shorten_paths(syntax.clone(), &path.clone_for_update());
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
/// Adds replacements to `re` that shorten `path` in all descendants of `node`.
|
||||
fn shorten_paths(rewriter: &mut SyntaxRewriter<'static>, node: SyntaxNode, path: &ast::Path) {
|
||||
fn shorten_paths(node: SyntaxNode, path: &ast::Path) {
|
||||
for child in node.children() {
|
||||
match_ast! {
|
||||
match child {
|
||||
|
|
@ -62,32 +61,28 @@ fn shorten_paths(rewriter: &mut SyntaxRewriter<'static>, node: SyntaxNode, path:
|
|||
ast::Module(_it) => continue,
|
||||
|
||||
ast::Path(p) => {
|
||||
match maybe_replace_path(rewriter, p.clone(), path.clone()) {
|
||||
match maybe_replace_path(p.clone(), path.clone()) {
|
||||
Some(()) => {},
|
||||
None => shorten_paths(rewriter, p.syntax().clone(), path),
|
||||
None => shorten_paths(p.syntax().clone(), path),
|
||||
}
|
||||
},
|
||||
_ => shorten_paths(rewriter, child, path),
|
||||
_ => shorten_paths(child, path),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn maybe_replace_path(
|
||||
rewriter: &mut SyntaxRewriter<'static>,
|
||||
path: ast::Path,
|
||||
target: ast::Path,
|
||||
) -> Option<()> {
|
||||
fn maybe_replace_path(path: ast::Path, target: ast::Path) -> Option<()> {
|
||||
if !path_eq(path.clone(), target) {
|
||||
return None;
|
||||
}
|
||||
|
||||
// Shorten `path`, leaving only its last segment.
|
||||
if let Some(parent) = path.qualifier() {
|
||||
rewriter.delete(parent.syntax());
|
||||
ted::remove(parent.syntax());
|
||||
}
|
||||
if let Some(double_colon) = path.coloncolon_token() {
|
||||
rewriter.delete(&double_colon);
|
||||
ted::remove(&double_colon);
|
||||
}
|
||||
|
||||
Some(())
|
||||
|
|
@ -150,6 +145,7 @@ Debug
|
|||
",
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_replace_add_use_no_anchor_with_item_below() {
|
||||
check_assist(
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue