aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_assists/src/handlers/add_missing_impl_members.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_assists/src/handlers/add_missing_impl_members.rs')
-rw-r--r--crates/ra_assists/src/handlers/add_missing_impl_members.rs341
1 files changed, 223 insertions, 118 deletions
diff --git a/crates/ra_assists/src/handlers/add_missing_impl_members.rs b/crates/ra_assists/src/handlers/add_missing_impl_members.rs
index 2d6d44980..abacd4065 100644
--- a/crates/ra_assists/src/handlers/add_missing_impl_members.rs
+++ b/crates/ra_assists/src/handlers/add_missing_impl_members.rs
@@ -1,13 +1,18 @@
1use hir::HasSource; 1use hir::HasSource;
2use ra_syntax::{ 2use ra_syntax::{
3 ast::{self, edit, make, AstNode, NameOwner}, 3 ast::{
4 self,
5 edit::{self, AstNodeEdit, IndentLevel},
6 make, AstNode, NameOwner,
7 },
4 SmolStr, 8 SmolStr,
5}; 9};
6 10
7use crate::{ 11use crate::{
12 assist_context::{AssistContext, Assists},
8 ast_transform::{self, AstTransform, QualifyPaths, SubstituteTypeParams}, 13 ast_transform::{self, AstTransform, QualifyPaths, SubstituteTypeParams},
9 utils::{get_missing_impl_items, resolve_target_trait}, 14 utils::{get_missing_assoc_items, render_snippet, resolve_target_trait, Cursor},
10 Assist, AssistCtx, AssistId, 15 AssistId,
11}; 16};
12 17
13#[derive(PartialEq)] 18#[derive(PartialEq)]
@@ -40,12 +45,15 @@ enum AddMissingImplMembersMode {
40// } 45// }
41// 46//
42// impl Trait<u32> for () { 47// impl Trait<u32> for () {
43// fn foo(&self) -> u32 { todo!() } 48// fn foo(&self) -> u32 {
49// ${0:todo!()}
50// }
44// 51//
45// } 52// }
46// ``` 53// ```
47pub(crate) fn add_missing_impl_members(ctx: AssistCtx) -> Option<Assist> { 54pub(crate) fn add_missing_impl_members(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
48 add_missing_impl_members_inner( 55 add_missing_impl_members_inner(
56 acc,
49 ctx, 57 ctx,
50 AddMissingImplMembersMode::NoDefaultMethods, 58 AddMissingImplMembersMode::NoDefaultMethods,
51 "add_impl_missing_members", 59 "add_impl_missing_members",
@@ -81,12 +89,13 @@ pub(crate) fn add_missing_impl_members(ctx: AssistCtx) -> Option<Assist> {
81// impl Trait for () { 89// impl Trait for () {
82// Type X = (); 90// Type X = ();
83// fn foo(&self) {} 91// fn foo(&self) {}
84// fn bar(&self) {} 92// $0fn bar(&self) {}
85// 93//
86// } 94// }
87// ``` 95// ```
88pub(crate) fn add_missing_default_members(ctx: AssistCtx) -> Option<Assist> { 96pub(crate) fn add_missing_default_members(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
89 add_missing_impl_members_inner( 97 add_missing_impl_members_inner(
98 acc,
90 ctx, 99 ctx,
91 AddMissingImplMembersMode::DefaultMethodsOnly, 100 AddMissingImplMembersMode::DefaultMethodsOnly,
92 "add_impl_default_members", 101 "add_impl_default_members",
@@ -95,36 +104,37 @@ pub(crate) fn add_missing_default_members(ctx: AssistCtx) -> Option<Assist> {
95} 104}
96 105
97fn add_missing_impl_members_inner( 106fn add_missing_impl_members_inner(
98 ctx: AssistCtx, 107 acc: &mut Assists,
108 ctx: &AssistContext,
99 mode: AddMissingImplMembersMode, 109 mode: AddMissingImplMembersMode,
100 assist_id: &'static str, 110 assist_id: &'static str,
101 label: &'static str, 111 label: &'static str,
102) -> Option<Assist> { 112) -> Option<()> {
103 let _p = ra_prof::profile("add_missing_impl_members_inner"); 113 let _p = ra_prof::profile("add_missing_impl_members_inner");
104 let impl_node = ctx.find_node_at_offset::<ast::ImplDef>()?; 114 let impl_def = ctx.find_node_at_offset::<ast::ImplDef>()?;
105 let impl_item_list = impl_node.item_list()?; 115 let impl_item_list = impl_def.item_list()?;
106 116
107 let trait_ = resolve_target_trait(&ctx.sema, &impl_node)?; 117 let trait_ = resolve_target_trait(&ctx.sema, &impl_def)?;
108 118
109 let def_name = |item: &ast::ImplItem| -> Option<SmolStr> { 119 let def_name = |item: &ast::AssocItem| -> Option<SmolStr> {
110 match item { 120 match item {
111 ast::ImplItem::FnDef(def) => def.name(), 121 ast::AssocItem::FnDef(def) => def.name(),
112 ast::ImplItem::TypeAliasDef(def) => def.name(), 122 ast::AssocItem::TypeAliasDef(def) => def.name(),
113 ast::ImplItem::ConstDef(def) => def.name(), 123 ast::AssocItem::ConstDef(def) => def.name(),
114 } 124 }
115 .map(|it| it.text().clone()) 125 .map(|it| it.text().clone())
116 }; 126 };
117 127
118 let missing_items = get_missing_impl_items(&ctx.sema, &impl_node) 128 let missing_items = get_missing_assoc_items(&ctx.sema, &impl_def)
119 .iter() 129 .iter()
120 .map(|i| match i { 130 .map(|i| match i {
121 hir::AssocItem::Function(i) => ast::ImplItem::FnDef(i.source(ctx.db).value), 131 hir::AssocItem::Function(i) => ast::AssocItem::FnDef(i.source(ctx.db).value),
122 hir::AssocItem::TypeAlias(i) => ast::ImplItem::TypeAliasDef(i.source(ctx.db).value), 132 hir::AssocItem::TypeAlias(i) => ast::AssocItem::TypeAliasDef(i.source(ctx.db).value),
123 hir::AssocItem::Const(i) => ast::ImplItem::ConstDef(i.source(ctx.db).value), 133 hir::AssocItem::Const(i) => ast::AssocItem::ConstDef(i.source(ctx.db).value),
124 }) 134 })
125 .filter(|t| def_name(&t).is_some()) 135 .filter(|t| def_name(&t).is_some())
126 .filter(|t| match t { 136 .filter(|t| match t {
127 ast::ImplItem::FnDef(def) => match mode { 137 ast::AssocItem::FnDef(def) => match mode {
128 AddMissingImplMembersMode::DefaultMethodsOnly => def.body().is_some(), 138 AddMissingImplMembersMode::DefaultMethodsOnly => def.body().is_some(),
129 AddMissingImplMembersMode::NoDefaultMethods => def.body().is_none(), 139 AddMissingImplMembersMode::NoDefaultMethods => def.body().is_none(),
130 }, 140 },
@@ -136,44 +146,59 @@ fn add_missing_impl_members_inner(
136 return None; 146 return None;
137 } 147 }
138 148
139 let sema = ctx.sema; 149 let target = impl_def.syntax().text_range();
140 150 acc.add(AssistId(assist_id), label, target, |builder| {
141 ctx.add_assist(AssistId(assist_id), label, |edit| { 151 let n_existing_items = impl_item_list.assoc_items().count();
142 let n_existing_items = impl_item_list.impl_items().count(); 152 let source_scope = ctx.sema.scope_for_def(trait_);
143 let source_scope = sema.scope_for_def(trait_); 153 let target_scope = ctx.sema.scope(impl_item_list.syntax());
144 let target_scope = sema.scope(impl_item_list.syntax());
145 let ast_transform = QualifyPaths::new(&target_scope, &source_scope) 154 let ast_transform = QualifyPaths::new(&target_scope, &source_scope)
146 .or(SubstituteTypeParams::for_trait_impl(&source_scope, trait_, impl_node)); 155 .or(SubstituteTypeParams::for_trait_impl(&source_scope, trait_, impl_def));
147 let items = missing_items 156 let items = missing_items
148 .into_iter() 157 .into_iter()
149 .map(|it| ast_transform::apply(&*ast_transform, it)) 158 .map(|it| ast_transform::apply(&*ast_transform, it))
150 .map(|it| match it { 159 .map(|it| match it {
151 ast::ImplItem::FnDef(def) => ast::ImplItem::FnDef(add_body(def)), 160 ast::AssocItem::FnDef(def) => ast::AssocItem::FnDef(add_body(def)),
152 _ => it, 161 _ => it,
153 }) 162 })
154 .map(|it| edit::remove_attrs_and_docs(&it)); 163 .map(|it| edit::remove_attrs_and_docs(&it));
155 let new_impl_item_list = impl_item_list.append_items(items); 164 let new_impl_item_list = impl_item_list.append_items(items);
156 let cursor_position = { 165 let first_new_item = new_impl_item_list.assoc_items().nth(n_existing_items).unwrap();
157 let first_new_item = new_impl_item_list.impl_items().nth(n_existing_items).unwrap(); 166
158 first_new_item.syntax().text_range().start() 167 let original_range = impl_item_list.syntax().text_range();
168 match ctx.config.snippet_cap {
169 None => builder.replace(original_range, new_impl_item_list.to_string()),
170 Some(cap) => {
171 let mut cursor = Cursor::Before(first_new_item.syntax());
172 let placeholder;
173 if let ast::AssocItem::FnDef(func) = &first_new_item {
174 if let Some(m) = func.syntax().descendants().find_map(ast::MacroCall::cast) {
175 if m.syntax().text() == "todo!()" {
176 placeholder = m;
177 cursor = Cursor::Replace(placeholder.syntax());
178 }
179 }
180 }
181 builder.replace_snippet(
182 cap,
183 original_range,
184 render_snippet(cap, new_impl_item_list.syntax(), cursor),
185 )
186 }
159 }; 187 };
160
161 edit.replace_ast(impl_item_list, new_impl_item_list);
162 edit.set_cursor(cursor_position);
163 }) 188 })
164} 189}
165 190
166fn add_body(fn_def: ast::FnDef) -> ast::FnDef { 191fn add_body(fn_def: ast::FnDef) -> ast::FnDef {
167 if fn_def.body().is_none() { 192 if fn_def.body().is_some() {
168 fn_def.with_body(make::block_from_expr(make::expr_todo())) 193 return fn_def;
169 } else {
170 fn_def
171 } 194 }
195 let body = make::block_expr(None, Some(make::expr_todo())).indent(IndentLevel(1));
196 fn_def.with_body(body)
172} 197}
173 198
174#[cfg(test)] 199#[cfg(test)]
175mod tests { 200mod tests {
176 use crate::helpers::{check_assist, check_assist_not_applicable}; 201 use crate::tests::{check_assist, check_assist_not_applicable};
177 202
178 use super::*; 203 use super::*;
179 204
@@ -181,7 +206,7 @@ mod tests {
181 fn test_add_missing_impl_members() { 206 fn test_add_missing_impl_members() {
182 check_assist( 207 check_assist(
183 add_missing_impl_members, 208 add_missing_impl_members,
184 " 209 r#"
185trait Foo { 210trait Foo {
186 type Output; 211 type Output;
187 212
@@ -197,8 +222,8 @@ struct S;
197impl Foo for S { 222impl Foo for S {
198 fn bar(&self) {} 223 fn bar(&self) {}
199<|> 224<|>
200}", 225}"#,
201 " 226 r#"
202trait Foo { 227trait Foo {
203 type Output; 228 type Output;
204 229
@@ -213,12 +238,16 @@ struct S;
213 238
214impl Foo for S { 239impl Foo for S {
215 fn bar(&self) {} 240 fn bar(&self) {}
216 <|>type Output; 241 $0type Output;
217 const CONST: usize = 42; 242 const CONST: usize = 42;
218 fn foo(&self) { todo!() } 243 fn foo(&self) {
219 fn baz(&self) { todo!() } 244 todo!()
245 }
246 fn baz(&self) {
247 todo!()
248 }
220 249
221}", 250}"#,
222 ); 251 );
223 } 252 }
224 253
@@ -226,7 +255,7 @@ impl Foo for S {
226 fn test_copied_overriden_members() { 255 fn test_copied_overriden_members() {
227 check_assist( 256 check_assist(
228 add_missing_impl_members, 257 add_missing_impl_members,
229 " 258 r#"
230trait Foo { 259trait Foo {
231 fn foo(&self); 260 fn foo(&self);
232 fn bar(&self) -> bool { true } 261 fn bar(&self) -> bool { true }
@@ -238,8 +267,8 @@ struct S;
238impl Foo for S { 267impl Foo for S {
239 fn bar(&self) {} 268 fn bar(&self) {}
240<|> 269<|>
241}", 270}"#,
242 " 271 r#"
243trait Foo { 272trait Foo {
244 fn foo(&self); 273 fn foo(&self);
245 fn bar(&self) -> bool { true } 274 fn bar(&self) -> bool { true }
@@ -250,9 +279,11 @@ struct S;
250 279
251impl Foo for S { 280impl Foo for S {
252 fn bar(&self) {} 281 fn bar(&self) {}
253 <|>fn foo(&self) { todo!() } 282 fn foo(&self) {
283 ${0:todo!()}
284 }
254 285
255}", 286}"#,
256 ); 287 );
257 } 288 }
258 289
@@ -260,16 +291,18 @@ impl Foo for S {
260 fn test_empty_impl_def() { 291 fn test_empty_impl_def() {
261 check_assist( 292 check_assist(
262 add_missing_impl_members, 293 add_missing_impl_members,
263 " 294 r#"
264trait Foo { fn foo(&self); } 295trait Foo { fn foo(&self); }
265struct S; 296struct S;
266impl Foo for S { <|> }", 297impl Foo for S { <|> }"#,
267 " 298 r#"
268trait Foo { fn foo(&self); } 299trait Foo { fn foo(&self); }
269struct S; 300struct S;
270impl Foo for S { 301impl Foo for S {
271 <|>fn foo(&self) { todo!() } 302 fn foo(&self) {
272}", 303 ${0:todo!()}
304 }
305}"#,
273 ); 306 );
274 } 307 }
275 308
@@ -277,16 +310,18 @@ impl Foo for S {
277 fn fill_in_type_params_1() { 310 fn fill_in_type_params_1() {
278 check_assist( 311 check_assist(
279 add_missing_impl_members, 312 add_missing_impl_members,
280 " 313 r#"
281trait Foo<T> { fn foo(&self, t: T) -> &T; } 314trait Foo<T> { fn foo(&self, t: T) -> &T; }
282struct S; 315struct S;
283impl Foo<u32> for S { <|> }", 316impl Foo<u32> for S { <|> }"#,
284 " 317 r#"
285trait Foo<T> { fn foo(&self, t: T) -> &T; } 318trait Foo<T> { fn foo(&self, t: T) -> &T; }
286struct S; 319struct S;
287impl Foo<u32> for S { 320impl Foo<u32> for S {
288 <|>fn foo(&self, t: u32) -> &u32 { todo!() } 321 fn foo(&self, t: u32) -> &u32 {
289}", 322 ${0:todo!()}
323 }
324}"#,
290 ); 325 );
291 } 326 }
292 327
@@ -294,16 +329,18 @@ impl Foo<u32> for S {
294 fn fill_in_type_params_2() { 329 fn fill_in_type_params_2() {
295 check_assist( 330 check_assist(
296 add_missing_impl_members, 331 add_missing_impl_members,
297 " 332 r#"
298trait Foo<T> { fn foo(&self, t: T) -> &T; } 333trait Foo<T> { fn foo(&self, t: T) -> &T; }
299struct S; 334struct S;
300impl<U> Foo<U> for S { <|> }", 335impl<U> Foo<U> for S { <|> }"#,
301 " 336 r#"
302trait Foo<T> { fn foo(&self, t: T) -> &T; } 337trait Foo<T> { fn foo(&self, t: T) -> &T; }
303struct S; 338struct S;
304impl<U> Foo<U> for S { 339impl<U> Foo<U> for S {
305 <|>fn foo(&self, t: U) -> &U { todo!() } 340 fn foo(&self, t: U) -> &U {
306}", 341 ${0:todo!()}
342 }
343}"#,
307 ); 344 );
308 } 345 }
309 346
@@ -311,16 +348,18 @@ impl<U> Foo<U> for S {
311 fn test_cursor_after_empty_impl_def() { 348 fn test_cursor_after_empty_impl_def() {
312 check_assist( 349 check_assist(
313 add_missing_impl_members, 350 add_missing_impl_members,
314 " 351 r#"
315trait Foo { fn foo(&self); } 352trait Foo { fn foo(&self); }
316struct S; 353struct S;
317impl Foo for S {}<|>", 354impl Foo for S {}<|>"#,
318 " 355 r#"
319trait Foo { fn foo(&self); } 356trait Foo { fn foo(&self); }
320struct S; 357struct S;
321impl Foo for S { 358impl Foo for S {
322 <|>fn foo(&self) { todo!() } 359 fn foo(&self) {
323}", 360 ${0:todo!()}
361 }
362}"#,
324 ) 363 )
325 } 364 }
326 365
@@ -328,22 +367,24 @@ impl Foo for S {
328 fn test_qualify_path_1() { 367 fn test_qualify_path_1() {
329 check_assist( 368 check_assist(
330 add_missing_impl_members, 369 add_missing_impl_members,
331 " 370 r#"
332mod foo { 371mod foo {
333 pub struct Bar; 372 pub struct Bar;
334 trait Foo { fn foo(&self, bar: Bar); } 373 trait Foo { fn foo(&self, bar: Bar); }
335} 374}
336struct S; 375struct S;
337impl foo::Foo for S { <|> }", 376impl foo::Foo for S { <|> }"#,
338 " 377 r#"
339mod foo { 378mod foo {
340 pub struct Bar; 379 pub struct Bar;
341 trait Foo { fn foo(&self, bar: Bar); } 380 trait Foo { fn foo(&self, bar: Bar); }
342} 381}
343struct S; 382struct S;
344impl foo::Foo for S { 383impl foo::Foo for S {
345 <|>fn foo(&self, bar: foo::Bar) { todo!() } 384 fn foo(&self, bar: foo::Bar) {
346}", 385 ${0:todo!()}
386 }
387}"#,
347 ); 388 );
348 } 389 }
349 390
@@ -351,22 +392,24 @@ impl foo::Foo for S {
351 fn test_qualify_path_generic() { 392 fn test_qualify_path_generic() {
352 check_assist( 393 check_assist(
353 add_missing_impl_members, 394 add_missing_impl_members,
354 " 395 r#"
355mod foo { 396mod foo {
356 pub struct Bar<T>; 397 pub struct Bar<T>;
357 trait Foo { fn foo(&self, bar: Bar<u32>); } 398 trait Foo { fn foo(&self, bar: Bar<u32>); }
358} 399}
359struct S; 400struct S;
360impl foo::Foo for S { <|> }", 401impl foo::Foo for S { <|> }"#,
361 " 402 r#"
362mod foo { 403mod foo {
363 pub struct Bar<T>; 404 pub struct Bar<T>;
364 trait Foo { fn foo(&self, bar: Bar<u32>); } 405 trait Foo { fn foo(&self, bar: Bar<u32>); }
365} 406}
366struct S; 407struct S;
367impl foo::Foo for S { 408impl foo::Foo for S {
368 <|>fn foo(&self, bar: foo::Bar<u32>) { todo!() } 409 fn foo(&self, bar: foo::Bar<u32>) {
369}", 410 ${0:todo!()}
411 }
412}"#,
370 ); 413 );
371 } 414 }
372 415
@@ -374,22 +417,24 @@ impl foo::Foo for S {
374 fn test_qualify_path_and_substitute_param() { 417 fn test_qualify_path_and_substitute_param() {
375 check_assist( 418 check_assist(
376 add_missing_impl_members, 419 add_missing_impl_members,
377 " 420 r#"
378mod foo { 421mod foo {
379 pub struct Bar<T>; 422 pub struct Bar<T>;
380 trait Foo<T> { fn foo(&self, bar: Bar<T>); } 423 trait Foo<T> { fn foo(&self, bar: Bar<T>); }
381} 424}
382struct S; 425struct S;
383impl foo::Foo<u32> for S { <|> }", 426impl foo::Foo<u32> for S { <|> }"#,
384 " 427 r#"
385mod foo { 428mod foo {
386 pub struct Bar<T>; 429 pub struct Bar<T>;
387 trait Foo<T> { fn foo(&self, bar: Bar<T>); } 430 trait Foo<T> { fn foo(&self, bar: Bar<T>); }
388} 431}
389struct S; 432struct S;
390impl foo::Foo<u32> for S { 433impl foo::Foo<u32> for S {
391 <|>fn foo(&self, bar: foo::Bar<u32>) { todo!() } 434 fn foo(&self, bar: foo::Bar<u32>) {
392}", 435 ${0:todo!()}
436 }
437}"#,
393 ); 438 );
394 } 439 }
395 440
@@ -398,15 +443,15 @@ impl foo::Foo<u32> for S {
398 // when substituting params, the substituted param should not be qualified! 443 // when substituting params, the substituted param should not be qualified!
399 check_assist( 444 check_assist(
400 add_missing_impl_members, 445 add_missing_impl_members,
401 " 446 r#"
402mod foo { 447mod foo {
403 trait Foo<T> { fn foo(&self, bar: T); } 448 trait Foo<T> { fn foo(&self, bar: T); }
404 pub struct Param; 449 pub struct Param;
405} 450}
406struct Param; 451struct Param;
407struct S; 452struct S;
408impl foo::Foo<Param> for S { <|> }", 453impl foo::Foo<Param> for S { <|> }"#,
409 " 454 r#"
410mod foo { 455mod foo {
411 trait Foo<T> { fn foo(&self, bar: T); } 456 trait Foo<T> { fn foo(&self, bar: T); }
412 pub struct Param; 457 pub struct Param;
@@ -414,8 +459,10 @@ mod foo {
414struct Param; 459struct Param;
415struct S; 460struct S;
416impl foo::Foo<Param> for S { 461impl foo::Foo<Param> for S {
417 <|>fn foo(&self, bar: Param) { todo!() } 462 fn foo(&self, bar: Param) {
418}", 463 ${0:todo!()}
464 }
465}"#,
419 ); 466 );
420 } 467 }
421 468
@@ -423,15 +470,15 @@ impl foo::Foo<Param> for S {
423 fn test_qualify_path_associated_item() { 470 fn test_qualify_path_associated_item() {
424 check_assist( 471 check_assist(
425 add_missing_impl_members, 472 add_missing_impl_members,
426 " 473 r#"
427mod foo { 474mod foo {
428 pub struct Bar<T>; 475 pub struct Bar<T>;
429 impl Bar<T> { type Assoc = u32; } 476 impl Bar<T> { type Assoc = u32; }
430 trait Foo { fn foo(&self, bar: Bar<u32>::Assoc); } 477 trait Foo { fn foo(&self, bar: Bar<u32>::Assoc); }
431} 478}
432struct S; 479struct S;
433impl foo::Foo for S { <|> }", 480impl foo::Foo for S { <|> }"#,
434 " 481 r#"
435mod foo { 482mod foo {
436 pub struct Bar<T>; 483 pub struct Bar<T>;
437 impl Bar<T> { type Assoc = u32; } 484 impl Bar<T> { type Assoc = u32; }
@@ -439,8 +486,10 @@ mod foo {
439} 486}
440struct S; 487struct S;
441impl foo::Foo for S { 488impl foo::Foo for S {
442 <|>fn foo(&self, bar: foo::Bar<u32>::Assoc) { todo!() } 489 fn foo(&self, bar: foo::Bar<u32>::Assoc) {
443}", 490 ${0:todo!()}
491 }
492}"#,
444 ); 493 );
445 } 494 }
446 495
@@ -448,15 +497,15 @@ impl foo::Foo for S {
448 fn test_qualify_path_nested() { 497 fn test_qualify_path_nested() {
449 check_assist( 498 check_assist(
450 add_missing_impl_members, 499 add_missing_impl_members,
451 " 500 r#"
452mod foo { 501mod foo {
453 pub struct Bar<T>; 502 pub struct Bar<T>;
454 pub struct Baz; 503 pub struct Baz;
455 trait Foo { fn foo(&self, bar: Bar<Baz>); } 504 trait Foo { fn foo(&self, bar: Bar<Baz>); }
456} 505}
457struct S; 506struct S;
458impl foo::Foo for S { <|> }", 507impl foo::Foo for S { <|> }"#,
459 " 508 r#"
460mod foo { 509mod foo {
461 pub struct Bar<T>; 510 pub struct Bar<T>;
462 pub struct Baz; 511 pub struct Baz;
@@ -464,8 +513,10 @@ mod foo {
464} 513}
465struct S; 514struct S;
466impl foo::Foo for S { 515impl foo::Foo for S {
467 <|>fn foo(&self, bar: foo::Bar<foo::Baz>) { todo!() } 516 fn foo(&self, bar: foo::Bar<foo::Baz>) {
468}", 517 ${0:todo!()}
518 }
519}"#,
469 ); 520 );
470 } 521 }
471 522
@@ -473,22 +524,24 @@ impl foo::Foo for S {
473 fn test_qualify_path_fn_trait_notation() { 524 fn test_qualify_path_fn_trait_notation() {
474 check_assist( 525 check_assist(
475 add_missing_impl_members, 526 add_missing_impl_members,
476 " 527 r#"
477mod foo { 528mod foo {
478 pub trait Fn<Args> { type Output; } 529 pub trait Fn<Args> { type Output; }
479 trait Foo { fn foo(&self, bar: dyn Fn(u32) -> i32); } 530 trait Foo { fn foo(&self, bar: dyn Fn(u32) -> i32); }
480} 531}
481struct S; 532struct S;
482impl foo::Foo for S { <|> }", 533impl foo::Foo for S { <|> }"#,
483 " 534 r#"
484mod foo { 535mod foo {
485 pub trait Fn<Args> { type Output; } 536 pub trait Fn<Args> { type Output; }
486 trait Foo { fn foo(&self, bar: dyn Fn(u32) -> i32); } 537 trait Foo { fn foo(&self, bar: dyn Fn(u32) -> i32); }
487} 538}
488struct S; 539struct S;
489impl foo::Foo for S { 540impl foo::Foo for S {
490 <|>fn foo(&self, bar: dyn Fn(u32) -> i32) { todo!() } 541 fn foo(&self, bar: dyn Fn(u32) -> i32) {
491}", 542 ${0:todo!()}
543 }
544}"#,
492 ); 545 );
493 } 546 }
494 547
@@ -496,10 +549,10 @@ impl foo::Foo for S {
496 fn test_empty_trait() { 549 fn test_empty_trait() {
497 check_assist_not_applicable( 550 check_assist_not_applicable(
498 add_missing_impl_members, 551 add_missing_impl_members,
499 " 552 r#"
500trait Foo; 553trait Foo;
501struct S; 554struct S;
502impl Foo for S { <|> }", 555impl Foo for S { <|> }"#,
503 ) 556 )
504 } 557 }
505 558
@@ -507,13 +560,13 @@ impl Foo for S { <|> }",
507 fn test_ignore_unnamed_trait_members_and_default_methods() { 560 fn test_ignore_unnamed_trait_members_and_default_methods() {
508 check_assist_not_applicable( 561 check_assist_not_applicable(
509 add_missing_impl_members, 562 add_missing_impl_members,
510 " 563 r#"
511trait Foo { 564trait Foo {
512 fn (arg: u32); 565 fn (arg: u32);
513 fn valid(some: u32) -> bool { false } 566 fn valid(some: u32) -> bool { false }
514} 567}
515struct S; 568struct S;
516impl Foo for S { <|> }", 569impl Foo for S { <|> }"#,
517 ) 570 )
518 } 571 }
519 572
@@ -543,8 +596,10 @@ trait Foo {
543} 596}
544struct S; 597struct S;
545impl Foo for S { 598impl Foo for S {
546 <|>type Output; 599 $0type Output;
547 fn foo(&self) { todo!() } 600 fn foo(&self) {
601 todo!()
602 }
548}"#, 603}"#,
549 ) 604 )
550 } 605 }
@@ -553,7 +608,7 @@ impl Foo for S {
553 fn test_default_methods() { 608 fn test_default_methods() {
554 check_assist( 609 check_assist(
555 add_missing_default_members, 610 add_missing_default_members,
556 " 611 r#"
557trait Foo { 612trait Foo {
558 type Output; 613 type Output;
559 614
@@ -563,8 +618,8 @@ trait Foo {
563 fn foo(some: u32) -> bool; 618 fn foo(some: u32) -> bool;
564} 619}
565struct S; 620struct S;
566impl Foo for S { <|> }", 621impl Foo for S { <|> }"#,
567 " 622 r#"
568trait Foo { 623trait Foo {
569 type Output; 624 type Output;
570 625
@@ -575,8 +630,58 @@ trait Foo {
575} 630}
576struct S; 631struct S;
577impl Foo for S { 632impl Foo for S {
578 <|>fn valid(some: u32) -> bool { false } 633 $0fn valid(some: u32) -> bool { false }
579}", 634}"#,
635 )
636 }
637
638 #[test]
639 fn test_generic_single_default_parameter() {
640 check_assist(
641 add_missing_impl_members,
642 r#"
643trait Foo<T = Self> {
644 fn bar(&self, other: &T);
645}
646
647struct S;
648impl Foo for S { <|> }"#,
649 r#"
650trait Foo<T = Self> {
651 fn bar(&self, other: &T);
652}
653
654struct S;
655impl Foo for S {
656 fn bar(&self, other: &Self) {
657 ${0:todo!()}
658 }
659}"#,
660 )
661 }
662
663 #[test]
664 fn test_generic_default_parameter_is_second() {
665 check_assist(
666 add_missing_impl_members,
667 r#"
668trait Foo<T1, T2 = Self> {
669 fn bar(&self, this: &T1, that: &T2);
670}
671
672struct S<T>;
673impl Foo<T> for S<T> { <|> }"#,
674 r#"
675trait Foo<T1, T2 = Self> {
676 fn bar(&self, this: &T1, that: &T2);
677}
678
679struct S<T>;
680impl Foo<T> for S<T> {
681 fn bar(&self, this: &T, that: &Self) {
682 ${0:todo!()}
683 }
684}"#,
580 ) 685 )
581 } 686 }
582} 687}