3 syntax_helpers::insert_whitespace_into_node::insert_ws_into, traits::resolve_target_trait,
5 use syntax::ast::{self, make, AstNode};
8 assist_context::{AssistContext, Assists},
10 add_trait_assoc_items_to_impl, filter_assoc_items, gen_trait_fn_body, render_snippet,
11 Cursor, DefaultMethods,
16 // Assist: add_impl_missing_members
18 // Adds scaffold for required impl members.
23 // fn foo(&self) -> T;
27 // impl Trait<u32> for () {$0
35 // fn foo(&self) -> T;
39 // impl Trait<u32> for () {
42 // fn foo(&self) -> u32 {
47 pub(crate) fn add_missing_impl_members(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
48 add_missing_impl_members_inner(
52 "add_impl_missing_members",
53 "Implement missing members",
57 // Assist: add_impl_default_members
59 // Adds scaffold for overriding default impl members.
68 // impl Trait for () {
81 // impl Trait for () {
88 pub(crate) fn add_missing_default_members(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
89 add_missing_impl_members_inner(
93 "add_impl_default_members",
94 "Implement default members",
98 fn add_missing_impl_members_inner(
101 mode: DefaultMethods,
102 assist_id: &'static str,
105 let _p = profile::span("add_missing_impl_members_inner");
106 let impl_def = ctx.find_node_at_offset::<ast::Impl>()?;
107 let target_scope = ctx.sema.scope(impl_def.syntax())?;
108 let trait_ = resolve_target_trait(&ctx.sema, &impl_def)?;
110 let missing_items = filter_assoc_items(
112 &ide_db::traits::get_missing_assoc_items(&ctx.sema, &impl_def),
116 if missing_items.is_empty() {
120 let target = impl_def.syntax().text_range();
121 acc.add(AssistId(assist_id, AssistKind::QuickFix), label, target, |builder| {
122 let missing_items = missing_items
125 if ctx.sema.hir_file_for(it.syntax()).is_macro() {
126 if let Some(it) = ast::AssocItem::cast(insert_ws_into(it.syntax().clone())) {
130 it.clone_for_update()
133 let (new_impl_def, first_new_item) = add_trait_assoc_items_to_impl(
140 match ctx.config.snippet_cap {
141 None => builder.replace(target, new_impl_def.to_string()),
143 let mut cursor = Cursor::Before(first_new_item.syntax());
145 if let ast::AssocItem::Fn(func) = &first_new_item {
146 if try_gen_trait_body(ctx, func, &trait_, &impl_def).is_none() {
147 if let Some(m) = func.syntax().descendants().find_map(ast::MacroCall::cast)
149 if m.syntax().text() == "todo!()" {
151 cursor = Cursor::Replace(placeholder.syntax());
156 builder.replace_snippet(
159 render_snippet(cap, new_impl_def.syntax(), cursor),
166 fn try_gen_trait_body(
170 impl_def: &ast::Impl,
172 let trait_path = make::ext::ident_path(&trait_.name(ctx.db()).to_string());
173 let hir_ty = ctx.sema.resolve_type(&impl_def.self_ty()?)?;
174 let adt = hir_ty.as_adt()?.source(ctx.db())?;
175 gen_trait_fn_body(func, &trait_path, &adt.value)
180 use crate::tests::{check_assist, check_assist_not_applicable};
185 fn test_add_missing_impl_members() {
187 add_missing_impl_members,
192 const CONST: usize = 42;
209 const CONST: usize = 42;
223 const CONST: usize = 42;
238 fn test_copied_overriden_members() {
240 add_missing_impl_members,
244 fn bar(&self) -> bool { true }
245 fn baz(&self) -> u32 { 42 }
257 fn bar(&self) -> bool { true }
258 fn baz(&self) -> u32 { 42 }
275 fn test_empty_impl_def() {
277 add_missing_impl_members,
279 trait Foo { fn foo(&self); }
281 impl Foo for S { $0 }"#,
283 trait Foo { fn foo(&self); }
294 fn test_impl_def_without_braces() {
296 add_missing_impl_members,
298 trait Foo { fn foo(&self); }
302 trait Foo { fn foo(&self); }
313 fn fill_in_type_params_1() {
315 add_missing_impl_members,
317 trait Foo<T> { fn foo(&self, t: T) -> &T; }
319 impl Foo<u32> for S { $0 }"#,
321 trait Foo<T> { fn foo(&self, t: T) -> &T; }
323 impl Foo<u32> for S {
324 fn foo(&self, t: u32) -> &u32 {
332 fn fill_in_type_params_2() {
334 add_missing_impl_members,
336 trait Foo<T> { fn foo(&self, t: T) -> &T; }
338 impl<U> Foo<U> for S { $0 }"#,
340 trait Foo<T> { fn foo(&self, t: T) -> &T; }
342 impl<U> Foo<U> for S {
343 fn foo(&self, t: U) -> &U {
351 fn test_cursor_after_empty_impl_def() {
353 add_missing_impl_members,
355 trait Foo { fn foo(&self); }
357 impl Foo for S {}$0"#,
359 trait Foo { fn foo(&self); }
370 fn test_qualify_path_1() {
372 add_missing_impl_members,
376 trait Foo { fn foo(&self, bar: Bar); }
379 impl foo::Foo for S { $0 }"#,
383 trait Foo { fn foo(&self, bar: Bar); }
386 impl foo::Foo for S {
387 fn foo(&self, bar: foo::Bar) {
395 fn test_qualify_path_2() {
397 add_missing_impl_members,
402 pub trait Foo { fn foo(&self, bar: Bar); }
409 impl bar::Foo for S { $0 }"#,
414 pub trait Foo { fn foo(&self, bar: Bar); }
421 impl bar::Foo for S {
422 fn foo(&self, bar: bar::Bar) {
430 fn test_qualify_path_generic() {
432 add_missing_impl_members,
436 trait Foo { fn foo(&self, bar: Bar<u32>); }
439 impl foo::Foo for S { $0 }"#,
443 trait Foo { fn foo(&self, bar: Bar<u32>); }
446 impl foo::Foo for S {
447 fn foo(&self, bar: foo::Bar<u32>) {
455 fn test_qualify_path_and_substitute_param() {
457 add_missing_impl_members,
461 trait Foo<T> { fn foo(&self, bar: Bar<T>); }
464 impl foo::Foo<u32> for S { $0 }"#,
468 trait Foo<T> { fn foo(&self, bar: Bar<T>); }
471 impl foo::Foo<u32> for S {
472 fn foo(&self, bar: foo::Bar<u32>) {
480 fn test_substitute_param_no_qualify() {
481 // when substituting params, the substituted param should not be qualified!
483 add_missing_impl_members,
486 trait Foo<T> { fn foo(&self, bar: T); }
491 impl foo::Foo<Param> for S { $0 }"#,
494 trait Foo<T> { fn foo(&self, bar: T); }
499 impl foo::Foo<Param> for S {
500 fn foo(&self, bar: Param) {
508 fn test_qualify_path_associated_item() {
510 add_missing_impl_members,
514 impl Bar<T> { type Assoc = u32; }
515 trait Foo { fn foo(&self, bar: Bar<u32>::Assoc); }
518 impl foo::Foo for S { $0 }"#,
522 impl Bar<T> { type Assoc = u32; }
523 trait Foo { fn foo(&self, bar: Bar<u32>::Assoc); }
526 impl foo::Foo for S {
527 fn foo(&self, bar: foo::Bar<u32>::Assoc) {
535 fn test_qualify_path_nested() {
537 add_missing_impl_members,
542 trait Foo { fn foo(&self, bar: Bar<Baz>); }
545 impl foo::Foo for S { $0 }"#,
550 trait Foo { fn foo(&self, bar: Bar<Baz>); }
553 impl foo::Foo for S {
554 fn foo(&self, bar: foo::Bar<foo::Baz>) {
562 fn test_qualify_path_fn_trait_notation() {
564 add_missing_impl_members,
567 pub trait Fn<Args> { type Output; }
568 trait Foo { fn foo(&self, bar: dyn Fn(u32) -> i32); }
571 impl foo::Foo for S { $0 }"#,
574 pub trait Fn<Args> { type Output; }
575 trait Foo { fn foo(&self, bar: dyn Fn(u32) -> i32); }
578 impl foo::Foo for S {
579 fn foo(&self, bar: dyn Fn(u32) -> i32) {
587 fn test_empty_trait() {
588 check_assist_not_applicable(
589 add_missing_impl_members,
593 impl Foo for S { $0 }"#,
598 fn test_ignore_unnamed_trait_members_and_default_methods() {
599 check_assist_not_applicable(
600 add_missing_impl_members,
604 fn valid(some: u32) -> bool { false }
607 impl Foo for S { $0 }"#,
612 fn test_with_docstring_and_attrs() {
614 add_missing_impl_members,
616 #[doc(alias = "test alias")]
625 impl Foo for S {}$0"#,
627 #[doc(alias = "test alias")]
647 fn test_default_methods() {
649 add_missing_default_members,
654 const CONST: usize = 42;
656 fn valid(some: u32) -> bool { false }
657 fn foo(some: u32) -> bool;
660 impl Foo for S { $0 }"#,
665 const CONST: usize = 42;
667 fn valid(some: u32) -> bool { false }
668 fn foo(some: u32) -> bool;
672 $0fn valid(some: u32) -> bool { false }
678 fn test_generic_single_default_parameter() {
680 add_missing_impl_members,
682 trait Foo<T = Self> {
683 fn bar(&self, other: &T);
687 impl Foo for S { $0 }"#,
689 trait Foo<T = Self> {
690 fn bar(&self, other: &T);
695 fn bar(&self, other: &Self) {
703 fn test_generic_default_parameter_is_second() {
705 add_missing_impl_members,
707 trait Foo<T1, T2 = Self> {
708 fn bar(&self, this: &T1, that: &T2);
712 impl Foo<T> for S<T> { $0 }"#,
714 trait Foo<T1, T2 = Self> {
715 fn bar(&self, this: &T1, that: &T2);
719 impl Foo<T> for S<T> {
720 fn bar(&self, this: &T, that: &Self) {
728 fn test_assoc_type_bounds_are_removed() {
730 add_missing_impl_members,
733 type Ty: Copy + 'static;
740 type Ty: Copy + 'static;
750 fn test_whitespace_fixup_preserves_bad_tokens() {
752 add_missing_impl_members,
776 fn test_whitespace_fixup_preserves_comments() {
778 add_missing_impl_members,
804 add_missing_impl_members,
807 fn foo(&self, x: crate)
815 fn foo(&self, x: crate)
818 fn foo(&self, x: crate) {
827 fn missing_generic_type() {
829 add_missing_impl_members,
832 fn foo(&self, bar: BAR);
840 fn foo(&self, bar: BAR);
843 fn foo(&self, bar: BAR) {
852 fn does_not_requalify_self_as_crate() {
854 add_missing_default_members,
856 struct Wrapper<T>(T);
859 fn f(self) -> Wrapper<Self> {
869 struct Wrapper<T>(T);
872 fn f(self) -> Wrapper<Self> {
878 $0fn f(self) -> Wrapper<Self> {
887 fn test_default_body_generation() {
889 add_missing_impl_members,
891 //- minicore: default
894 impl Default for Foo {
901 impl Default for Foo {
902 $0fn default() -> Self {
903 Self(Default::default())
911 fn test_from_macro() {
913 add_missing_default_members,
918 fn foo<'lt>(&'lt self) {}
933 fn foo<'lt>(&'lt self) {}
941 $0fn foo< 'lt>(& 'lt self){}
949 fn test_assoc_type_when_trait_with_same_name_in_scope() {
951 add_missing_impl_members,
959 pub trait Behavior<T: Types> {
960 fn reproduce(&self, foo: T::Foo);
965 impl<T: Types> Behavior<T> for Impl { $0 }"#,
973 pub trait Behavior<T: Types> {
974 fn reproduce(&self, foo: T::Foo);
979 impl<T: Types> Behavior<T> for Impl {
980 fn reproduce(&self, foo: <T as Types>::Foo) {
988 fn test_assoc_type_on_concrete_type() {
990 add_missing_impl_members,
1000 pub trait Behavior<T: Types> {
1001 fn reproduce(&self, foo: T::Foo);
1006 impl Behavior<u32> for Impl { $0 }"#,
1012 impl Types for u32 {
1016 pub trait Behavior<T: Types> {
1017 fn reproduce(&self, foo: T::Foo);
1022 impl Behavior<u32> for Impl {
1023 fn reproduce(&self, foo: <u32 as Types>::Foo) {
1031 fn test_assoc_type_on_concrete_type_qualified() {
1033 add_missing_impl_members,
1039 impl Types for std::string::String {
1043 pub trait Behavior<T: Types> {
1044 fn reproduce(&self, foo: T::Foo);
1049 impl Behavior<std::string::String> for Impl { $0 }"#,
1055 impl Types for std::string::String {
1059 pub trait Behavior<T: Types> {
1060 fn reproduce(&self, foo: T::Foo);
1065 impl Behavior<std::string::String> for Impl {
1066 fn reproduce(&self, foo: <std::string::String as Types>::Foo) {
1074 fn test_assoc_type_on_concrete_type_multi_option_ambiguous() {
1076 add_missing_impl_members,
1086 impl Types for u32 {
1090 impl Types2 for u32 {
1094 pub trait Behavior<T: Types + Types2> {
1095 fn reproduce(&self, foo: <T as Types2>::Foo);
1100 impl Behavior<u32> for Impl { $0 }"#,
1110 impl Types for u32 {
1114 impl Types2 for u32 {
1118 pub trait Behavior<T: Types + Types2> {
1119 fn reproduce(&self, foo: <T as Types2>::Foo);
1124 impl Behavior<u32> for Impl {
1125 fn reproduce(&self, foo: <u32 as Types2>::Foo) {
1133 fn test_assoc_type_on_concrete_type_multi_option() {
1135 add_missing_impl_members,
1145 impl Types for u32 {
1149 impl Types2 for u32 {
1153 pub trait Behavior<T: Types + Types2> {
1154 fn reproduce(&self, foo: T::Bar);
1159 impl Behavior<u32> for Impl { $0 }"#,
1169 impl Types for u32 {
1173 impl Types2 for u32 {
1177 pub trait Behavior<T: Types + Types2> {
1178 fn reproduce(&self, foo: T::Bar);
1183 impl Behavior<u32> for Impl {
1184 fn reproduce(&self, foo: <u32 as Types2>::Bar) {
1192 fn test_assoc_type_on_concrete_type_multi_option_foreign() {
1194 add_missing_impl_members,
1206 impl Types for u32 {
1210 impl bar::Types2 for u32 {
1214 pub trait Behavior<T: Types + bar::Types2> {
1215 fn reproduce(&self, foo: T::Bar);
1220 impl Behavior<u32> for Impl { $0 }"#,
1232 impl Types for u32 {
1236 impl bar::Types2 for u32 {
1240 pub trait Behavior<T: Types + bar::Types2> {
1241 fn reproduce(&self, foo: T::Bar);
1246 impl Behavior<u32> for Impl {
1247 fn reproduce(&self, foo: <u32 as bar::Types2>::Bar) {
1255 fn test_transform_path_in_path_expr() {
1257 add_missing_default_members,
1263 pub trait Trait<T: Const> {
1272 impl Const for u32 {
1278 impl Trait<u32> for Impl { $0 }"#,
1284 pub trait Trait<T: Const> {
1293 impl Const for u32 {
1299 impl Trait<u32> for Impl {
1300 $0fn foo() -> bool {
1301 match <u32 as Const>::FOO {