From cea589b3b52ff5c4e358db52dc6de150eb48a9a0 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Fri, 14 May 2021 18:47:08 +0300 Subject: internal: rewrite assoc item manipulaion to use mutable trees --- .../src/handlers/add_missing_impl_members.rs | 3 ++- crates/ide_assists/src/tests/generated.rs | 1 - crates/ide_assists/src/utils.rs | 26 ++++++++++++---------- 3 files changed, 16 insertions(+), 14 deletions(-) (limited to 'crates/ide_assists/src') diff --git a/crates/ide_assists/src/handlers/add_missing_impl_members.rs b/crates/ide_assists/src/handlers/add_missing_impl_members.rs index 0148635f9..8225ae22c 100644 --- a/crates/ide_assists/src/handlers/add_missing_impl_members.rs +++ b/crates/ide_assists/src/handlers/add_missing_impl_members.rs @@ -64,7 +64,6 @@ pub(crate) fn add_missing_impl_members(acc: &mut Assists, ctx: &AssistContext) - // impl Trait for () { // type X = (); // fn foo(&self) {}$0 -// // } // ``` // -> @@ -195,6 +194,7 @@ impl Foo for S { fn baz(&self) { todo!() } + }"#, ); } @@ -231,6 +231,7 @@ impl Foo for S { fn foo(&self) { ${0:todo!()} } + }"#, ); } diff --git a/crates/ide_assists/src/tests/generated.rs b/crates/ide_assists/src/tests/generated.rs index 49c1a9776..4406406a2 100644 --- a/crates/ide_assists/src/tests/generated.rs +++ b/crates/ide_assists/src/tests/generated.rs @@ -50,7 +50,6 @@ trait Trait { impl Trait for () { type X = (); fn foo(&self) {}$0 - } "#####, r#####" diff --git a/crates/ide_assists/src/utils.rs b/crates/ide_assists/src/utils.rs index 0dcf20c61..7d562d1d4 100644 --- a/crates/ide_assists/src/utils.rs +++ b/crates/ide_assists/src/utils.rs @@ -128,15 +128,12 @@ pub fn add_trait_assoc_items_to_impl( sema: &hir::Semantics, items: Vec, trait_: hir::Trait, - impl_def: ast::Impl, + impl_: ast::Impl, target_scope: hir::SemanticsScope, ) -> (ast::Impl, ast::AssocItem) { - let impl_item_list = impl_def.assoc_item_list().unwrap_or_else(make::assoc_item_list); - - let n_existing_items = impl_item_list.assoc_items().count(); let source_scope = sema.scope_for_def(trait_); let ast_transform = QualifyPaths::new(&target_scope, &source_scope) - .or(SubstituteTypeParams::for_trait_impl(&source_scope, trait_, impl_def.clone())); + .or(SubstituteTypeParams::for_trait_impl(&source_scope, trait_, impl_.clone())); let items = items .into_iter() @@ -147,13 +144,18 @@ pub fn add_trait_assoc_items_to_impl( ast::AssocItem::TypeAlias(def) => ast::AssocItem::TypeAlias(def.remove_bounds()), _ => it, }) - .map(|it| edit::remove_attrs_and_docs(&it)); - - let new_impl_item_list = impl_item_list.append_items(items); - let new_impl_def = impl_def.with_assoc_item_list(new_impl_item_list); - let first_new_item = - new_impl_def.assoc_item_list().unwrap().assoc_items().nth(n_existing_items).unwrap(); - return (new_impl_def, first_new_item); + .map(|it| edit::remove_attrs_and_docs(&it).clone_subtree().clone_for_update()); + + let res = impl_.clone_for_update(); + let assoc_item_list = res.get_or_create_assoc_item_list(); + let mut first_item = None; + for item in items { + if first_item.is_none() { + first_item = Some(item.clone()) + } + assoc_item_list.add_item(item) + } + return (res, first_item.unwrap()); fn add_body(fn_def: ast::Fn) -> ast::Fn { match fn_def.body() { -- cgit v1.2.3 From 6c21d04307edf130851aefad406bacce9edbde23 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Fri, 14 May 2021 18:53:53 +0300 Subject: internal: use standard style for tests --- crates/ide_assists/src/handlers/generate_new.rs | 153 +++++++++++++++--------- 1 file changed, 99 insertions(+), 54 deletions(-) (limited to 'crates/ide_assists/src') diff --git a/crates/ide_assists/src/handlers/generate_new.rs b/crates/ide_assists/src/handlers/generate_new.rs index 8ce5930b7..959a1f86c 100644 --- a/crates/ide_assists/src/handlers/generate_new.rs +++ b/crates/ide_assists/src/handlers/generate_new.rs @@ -1,4 +1,3 @@ -use ast::Adt; use itertools::Itertools; use stdx::format_to; use syntax::ast::{self, AstNode, NameOwner, StructKind, VisibilityOwner}; @@ -37,7 +36,7 @@ pub(crate) fn generate_new(acc: &mut Assists, ctx: &AssistContext) -> Option<()> }; // Return early if we've found an existing new fn - let impl_def = find_struct_impl(&ctx, &Adt::Struct(strukt.clone()), "new")?; + let impl_def = find_struct_impl(&ctx, &ast::Adt::Struct(strukt.clone()), "new")?; let target = strukt.syntax().text_range(); acc.add(AssistId("generate_new", AssistKind::Generate), "Generate `new`", target, |builder| { @@ -60,7 +59,7 @@ pub(crate) fn generate_new(acc: &mut Assists, ctx: &AssistContext) -> Option<()> let start_offset = impl_def .and_then(|impl_def| find_impl_block_start(impl_def, &mut buf)) .unwrap_or_else(|| { - buf = generate_impl_text(&Adt::Struct(strukt.clone()), &buf); + buf = generate_impl_text(&ast::Adt::Struct(strukt.clone()), &buf); strukt.syntax().text_range().end() }); @@ -81,101 +80,132 @@ mod tests { use super::*; #[test] - #[rustfmt::skip] fn test_generate_new() { - // Check output of generation check_assist( generate_new, -"struct Foo {$0}", -"struct Foo {} + r#" +struct Foo {$0} +"#, + r#" +struct Foo {} impl Foo { fn $0new() -> Self { Self { } } -}", +} +"#, ); check_assist( generate_new, -"struct Foo {$0}", -"struct Foo {} + r#" +struct Foo {$0} +"#, + r#" +struct Foo {} impl Foo { fn $0new() -> Self { Self { } } -}", +} +"#, ); check_assist( generate_new, -"struct Foo<'a, T: Foo<'a>> {$0}", -"struct Foo<'a, T: Foo<'a>> {} + r#" +struct Foo<'a, T: Foo<'a>> {$0} +"#, + r#" +struct Foo<'a, T: Foo<'a>> {} impl<'a, T: Foo<'a>> Foo<'a, T> { fn $0new() -> Self { Self { } } -}", +} +"#, ); check_assist( generate_new, -"struct Foo { baz: String $0}", -"struct Foo { baz: String } + r#" +struct Foo { baz: String $0} +"#, + r#" +struct Foo { baz: String } impl Foo { fn $0new(baz: String) -> Self { Self { baz } } -}", +} +"#, ); check_assist( generate_new, -"struct Foo { baz: String, qux: Vec $0}", -"struct Foo { baz: String, qux: Vec } + r#" +struct Foo { baz: String, qux: Vec $0} +"#, + r#" +struct Foo { baz: String, qux: Vec } impl Foo { fn $0new(baz: String, qux: Vec) -> Self { Self { baz, qux } } -}", +} +"#, ); + } - // Check that visibility modifiers don't get brought in for fields + #[test] + fn check_that_visibility_modifiers_dont_get_brought_in() { check_assist( generate_new, -"struct Foo { pub baz: String, pub qux: Vec $0}", -"struct Foo { pub baz: String, pub qux: Vec } + r#" +struct Foo { pub baz: String, pub qux: Vec $0} +"#, + r#" +struct Foo { pub baz: String, pub qux: Vec } impl Foo { fn $0new(baz: String, qux: Vec) -> Self { Self { baz, qux } } -}", +} +"#, ); + } - // Check that it reuses existing impls + #[test] + fn check_it_reuses_existing_impls() { check_assist( generate_new, -"struct Foo {$0} + r#" +struct Foo {$0} impl Foo {} -", -"struct Foo {} +"#, + r#" +struct Foo {} impl Foo { fn $0new() -> Self { Self { } } } -", +"#, ); check_assist( generate_new, -"struct Foo {$0} + r#" +struct Foo {$0} impl Foo { fn qux(&self) {} } -", -"struct Foo {} +"#, + r#" +struct Foo {} impl Foo { fn $0new() -> Self { Self { } } fn qux(&self) {} } -", +"#, ); check_assist( generate_new, -"struct Foo {$0} + r#" +struct Foo {$0} impl Foo { fn qux(&self) {} @@ -183,8 +213,9 @@ impl Foo { 5 } } -", -"struct Foo {} +"#, + r#" +struct Foo {} impl Foo { fn $0new() -> Self { Self { } } @@ -194,27 +225,37 @@ impl Foo { 5 } } -", +"#, ); + } - // Check visibility of new fn based on struct + #[test] + fn check_visibility_of_new_fn_based_on_struct() { check_assist( generate_new, -"pub struct Foo {$0}", -"pub struct Foo {} + r#" +pub struct Foo {$0} +"#, + r#" +pub struct Foo {} impl Foo { pub fn $0new() -> Self { Self { } } -}", +} +"#, ); check_assist( generate_new, -"pub(crate) struct Foo {$0}", -"pub(crate) struct Foo {} + r#" +pub(crate) struct Foo {$0} +"#, + r#" +pub(crate) struct Foo {} impl Foo { pub(crate) fn $0new() -> Self { Self { } } -}", +} +"#, ); } @@ -222,26 +263,28 @@ impl Foo { fn generate_new_not_applicable_if_fn_exists() { check_assist_not_applicable( generate_new, - " + r#" struct Foo {$0} impl Foo { fn new() -> Self { Self } -}", +} +"#, ); check_assist_not_applicable( generate_new, - " + r#" struct Foo {$0} impl Foo { fn New() -> Self { Self } -}", +} +"#, ); } @@ -249,12 +292,12 @@ impl Foo { fn generate_new_target() { check_assist_target( generate_new, - " + r#" struct SomeThingIrrelevant; /// Has a lifetime parameter struct Foo<'a, T: Foo<'a>> {$0} struct EvenMoreIrrelevant; -", +"#, "/// Has a lifetime parameter struct Foo<'a, T: Foo<'a>> {}", ); @@ -264,7 +307,7 @@ struct Foo<'a, T: Foo<'a>> {}", fn test_unrelated_new() { check_assist( generate_new, - r##" + r#" pub struct AstId { file_id: HirFileId, file_ast_id: FileAstId, @@ -285,8 +328,9 @@ impl Source { pub fn map U, U>(self, f: F) -> Source { Source { file_id: self.file_id, ast: f(self.ast) } } -}"##, - r##" +} +"#, + r#" pub struct AstId { file_id: HirFileId, file_ast_id: FileAstId, @@ -309,7 +353,8 @@ impl Source { pub fn map U, U>(self, f: F) -> Source { Source { file_id: self.file_id, ast: f(self.ast) } } -}"##, +} +"#, ); } } -- cgit v1.2.3