diff options
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.rs | 341 |
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 @@ | |||
1 | use hir::HasSource; | 1 | use hir::HasSource; |
2 | use ra_syntax::{ | 2 | use 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 | ||
7 | use crate::{ | 11 | use 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 | // ``` |
47 | pub(crate) fn add_missing_impl_members(ctx: AssistCtx) -> Option<Assist> { | 54 | pub(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 | // ``` |
88 | pub(crate) fn add_missing_default_members(ctx: AssistCtx) -> Option<Assist> { | 96 | pub(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 | ||
97 | fn add_missing_impl_members_inner( | 106 | fn 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 | ||
166 | fn add_body(fn_def: ast::FnDef) -> ast::FnDef { | 191 | fn 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)] |
175 | mod tests { | 200 | mod 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#" |
185 | trait Foo { | 210 | trait Foo { |
186 | type Output; | 211 | type Output; |
187 | 212 | ||
@@ -197,8 +222,8 @@ struct S; | |||
197 | impl Foo for S { | 222 | impl Foo for S { |
198 | fn bar(&self) {} | 223 | fn bar(&self) {} |
199 | <|> | 224 | <|> |
200 | }", | 225 | }"#, |
201 | " | 226 | r#" |
202 | trait Foo { | 227 | trait Foo { |
203 | type Output; | 228 | type Output; |
204 | 229 | ||
@@ -213,12 +238,16 @@ struct S; | |||
213 | 238 | ||
214 | impl Foo for S { | 239 | impl 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#" |
230 | trait Foo { | 259 | trait 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; | |||
238 | impl Foo for S { | 267 | impl Foo for S { |
239 | fn bar(&self) {} | 268 | fn bar(&self) {} |
240 | <|> | 269 | <|> |
241 | }", | 270 | }"#, |
242 | " | 271 | r#" |
243 | trait Foo { | 272 | trait 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 | ||
251 | impl Foo for S { | 280 | impl 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#" |
264 | trait Foo { fn foo(&self); } | 295 | trait Foo { fn foo(&self); } |
265 | struct S; | 296 | struct S; |
266 | impl Foo for S { <|> }", | 297 | impl Foo for S { <|> }"#, |
267 | " | 298 | r#" |
268 | trait Foo { fn foo(&self); } | 299 | trait Foo { fn foo(&self); } |
269 | struct S; | 300 | struct S; |
270 | impl Foo for S { | 301 | impl 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#" |
281 | trait Foo<T> { fn foo(&self, t: T) -> &T; } | 314 | trait Foo<T> { fn foo(&self, t: T) -> &T; } |
282 | struct S; | 315 | struct S; |
283 | impl Foo<u32> for S { <|> }", | 316 | impl Foo<u32> for S { <|> }"#, |
284 | " | 317 | r#" |
285 | trait Foo<T> { fn foo(&self, t: T) -> &T; } | 318 | trait Foo<T> { fn foo(&self, t: T) -> &T; } |
286 | struct S; | 319 | struct S; |
287 | impl Foo<u32> for S { | 320 | impl 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#" |
298 | trait Foo<T> { fn foo(&self, t: T) -> &T; } | 333 | trait Foo<T> { fn foo(&self, t: T) -> &T; } |
299 | struct S; | 334 | struct S; |
300 | impl<U> Foo<U> for S { <|> }", | 335 | impl<U> Foo<U> for S { <|> }"#, |
301 | " | 336 | r#" |
302 | trait Foo<T> { fn foo(&self, t: T) -> &T; } | 337 | trait Foo<T> { fn foo(&self, t: T) -> &T; } |
303 | struct S; | 338 | struct S; |
304 | impl<U> Foo<U> for S { | 339 | impl<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#" |
315 | trait Foo { fn foo(&self); } | 352 | trait Foo { fn foo(&self); } |
316 | struct S; | 353 | struct S; |
317 | impl Foo for S {}<|>", | 354 | impl Foo for S {}<|>"#, |
318 | " | 355 | r#" |
319 | trait Foo { fn foo(&self); } | 356 | trait Foo { fn foo(&self); } |
320 | struct S; | 357 | struct S; |
321 | impl Foo for S { | 358 | impl 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#" |
332 | mod foo { | 371 | mod 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 | } |
336 | struct S; | 375 | struct S; |
337 | impl foo::Foo for S { <|> }", | 376 | impl foo::Foo for S { <|> }"#, |
338 | " | 377 | r#" |
339 | mod foo { | 378 | mod 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 | } |
343 | struct S; | 382 | struct S; |
344 | impl foo::Foo for S { | 383 | impl 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#" |
355 | mod foo { | 396 | mod 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 | } |
359 | struct S; | 400 | struct S; |
360 | impl foo::Foo for S { <|> }", | 401 | impl foo::Foo for S { <|> }"#, |
361 | " | 402 | r#" |
362 | mod foo { | 403 | mod 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 | } |
366 | struct S; | 407 | struct S; |
367 | impl foo::Foo for S { | 408 | impl 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#" |
378 | mod foo { | 421 | mod 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 | } |
382 | struct S; | 425 | struct S; |
383 | impl foo::Foo<u32> for S { <|> }", | 426 | impl foo::Foo<u32> for S { <|> }"#, |
384 | " | 427 | r#" |
385 | mod foo { | 428 | mod 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 | } |
389 | struct S; | 432 | struct S; |
390 | impl foo::Foo<u32> for S { | 433 | impl 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#" |
402 | mod foo { | 447 | mod 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 | } |
406 | struct Param; | 451 | struct Param; |
407 | struct S; | 452 | struct S; |
408 | impl foo::Foo<Param> for S { <|> }", | 453 | impl foo::Foo<Param> for S { <|> }"#, |
409 | " | 454 | r#" |
410 | mod foo { | 455 | mod 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 { | |||
414 | struct Param; | 459 | struct Param; |
415 | struct S; | 460 | struct S; |
416 | impl foo::Foo<Param> for S { | 461 | impl 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#" |
427 | mod foo { | 474 | mod 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 | } |
432 | struct S; | 479 | struct S; |
433 | impl foo::Foo for S { <|> }", | 480 | impl foo::Foo for S { <|> }"#, |
434 | " | 481 | r#" |
435 | mod foo { | 482 | mod 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 | } |
440 | struct S; | 487 | struct S; |
441 | impl foo::Foo for S { | 488 | impl 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#" |
452 | mod foo { | 501 | mod 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 | } |
457 | struct S; | 506 | struct S; |
458 | impl foo::Foo for S { <|> }", | 507 | impl foo::Foo for S { <|> }"#, |
459 | " | 508 | r#" |
460 | mod foo { | 509 | mod 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 | } |
465 | struct S; | 514 | struct S; |
466 | impl foo::Foo for S { | 515 | impl 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#" |
477 | mod foo { | 528 | mod 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 | } |
481 | struct S; | 532 | struct S; |
482 | impl foo::Foo for S { <|> }", | 533 | impl foo::Foo for S { <|> }"#, |
483 | " | 534 | r#" |
484 | mod foo { | 535 | mod 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 | } |
488 | struct S; | 539 | struct S; |
489 | impl foo::Foo for S { | 540 | impl 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#" |
500 | trait Foo; | 553 | trait Foo; |
501 | struct S; | 554 | struct S; |
502 | impl Foo for S { <|> }", | 555 | impl 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#" |
511 | trait Foo { | 564 | trait 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 | } |
515 | struct S; | 568 | struct S; |
516 | impl Foo for S { <|> }", | 569 | impl Foo for S { <|> }"#, |
517 | ) | 570 | ) |
518 | } | 571 | } |
519 | 572 | ||
@@ -543,8 +596,10 @@ trait Foo { | |||
543 | } | 596 | } |
544 | struct S; | 597 | struct S; |
545 | impl Foo for S { | 598 | impl 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#" |
557 | trait Foo { | 612 | trait 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 | } |
565 | struct S; | 620 | struct S; |
566 | impl Foo for S { <|> }", | 621 | impl Foo for S { <|> }"#, |
567 | " | 622 | r#" |
568 | trait Foo { | 623 | trait Foo { |
569 | type Output; | 624 | type Output; |
570 | 625 | ||
@@ -575,8 +630,58 @@ trait Foo { | |||
575 | } | 630 | } |
576 | struct S; | 631 | struct S; |
577 | impl Foo for S { | 632 | impl 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#" | ||
643 | trait Foo<T = Self> { | ||
644 | fn bar(&self, other: &T); | ||
645 | } | ||
646 | |||
647 | struct S; | ||
648 | impl Foo for S { <|> }"#, | ||
649 | r#" | ||
650 | trait Foo<T = Self> { | ||
651 | fn bar(&self, other: &T); | ||
652 | } | ||
653 | |||
654 | struct S; | ||
655 | impl 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#" | ||
668 | trait Foo<T1, T2 = Self> { | ||
669 | fn bar(&self, this: &T1, that: &T2); | ||
670 | } | ||
671 | |||
672 | struct S<T>; | ||
673 | impl Foo<T> for S<T> { <|> }"#, | ||
674 | r#" | ||
675 | trait Foo<T1, T2 = Self> { | ||
676 | fn bar(&self, this: &T1, that: &T2); | ||
677 | } | ||
678 | |||
679 | struct S<T>; | ||
680 | impl Foo<T> for S<T> { | ||
681 | fn bar(&self, this: &T, that: &Self) { | ||
682 | ${0:todo!()} | ||
683 | } | ||
684 | }"#, | ||
580 | ) | 685 | ) |
581 | } | 686 | } |
582 | } | 687 | } |