diff options
Diffstat (limited to 'crates/ide_assists/src')
-rw-r--r-- | crates/ide_assists/src/tests.rs | 46 | ||||
-rw-r--r-- | crates/ide_assists/src/utils/suggest_name.rs | 994 |
2 files changed, 424 insertions, 616 deletions
diff --git a/crates/ide_assists/src/tests.rs b/crates/ide_assists/src/tests.rs index 66820058b..b7f616760 100644 --- a/crates/ide_assists/src/tests.rs +++ b/crates/ide_assists/src/tests.rs | |||
@@ -12,7 +12,7 @@ use ide_db::{ | |||
12 | RootDatabase, | 12 | RootDatabase, |
13 | }; | 13 | }; |
14 | use stdx::{format_to, trim_indent}; | 14 | use stdx::{format_to, trim_indent}; |
15 | use syntax::{ast, AstNode, TextRange}; | 15 | use syntax::TextRange; |
16 | use test_utils::{assert_eq_text, extract_offset}; | 16 | use test_utils::{assert_eq_text, extract_offset}; |
17 | 17 | ||
18 | use crate::{handlers::Handler, Assist, AssistConfig, AssistContext, AssistKind, Assists}; | 18 | use crate::{handlers::Handler, Assist, AssistConfig, AssistContext, AssistKind, Assists}; |
@@ -180,50 +180,6 @@ fn labels(assists: &[Assist]) -> String { | |||
180 | labels.into_iter().collect::<String>() | 180 | labels.into_iter().collect::<String>() |
181 | } | 181 | } |
182 | 182 | ||
183 | pub(crate) type NameSuggestion = fn(&ast::Expr, &Semantics<'_, RootDatabase>) -> Option<String>; | ||
184 | |||
185 | #[track_caller] | ||
186 | pub(crate) fn check_name_suggestion( | ||
187 | suggestion: NameSuggestion, | ||
188 | ra_fixture: &str, | ||
189 | suggested_name: &str, | ||
190 | ) { | ||
191 | check_name(suggestion, ra_fixture, Some(suggested_name)); | ||
192 | } | ||
193 | |||
194 | #[track_caller] | ||
195 | pub(crate) fn check_name_suggestion_not_applicable(suggestion: NameSuggestion, ra_fixture: &str) { | ||
196 | check_name(suggestion, ra_fixture, None); | ||
197 | } | ||
198 | |||
199 | #[track_caller] | ||
200 | fn check_name(suggestion: NameSuggestion, ra_fixture: &str, expected: Option<&str>) { | ||
201 | let (db, file_with_carret_id, range_or_offset) = RootDatabase::with_range_or_offset(ra_fixture); | ||
202 | let frange = FileRange { file_id: file_with_carret_id, range: range_or_offset.into() }; | ||
203 | |||
204 | let sema = Semantics::new(&db); | ||
205 | let source_file = sema.parse(frange.file_id); | ||
206 | let element = source_file.syntax().covering_element(frange.range); | ||
207 | let expr = | ||
208 | element.ancestors().find_map(ast::Expr::cast).expect("selection is not an expression"); | ||
209 | assert_eq!( | ||
210 | expr.syntax().text_range(), | ||
211 | frange.range, | ||
212 | "selection is not an expression(yet contained in one)" | ||
213 | ); | ||
214 | |||
215 | let name = suggestion(&expr, &sema); | ||
216 | |||
217 | match (name, expected) { | ||
218 | (Some(name), Some(expected_name)) => { | ||
219 | assert_eq_text!(&name, expected_name); | ||
220 | } | ||
221 | (Some(_), None) => panic!("name suggestion should not be applicable"), | ||
222 | (None, Some(_)) => panic!("name suggestion is not applicable"), | ||
223 | (None, None) => (), | ||
224 | } | ||
225 | } | ||
226 | |||
227 | #[test] | 183 | #[test] |
228 | fn assist_order_field_struct() { | 184 | fn assist_order_field_struct() { |
229 | let before = "struct Foo { $0bar: u32 }"; | 185 | let before = "struct Foo { $0bar: u32 }"; |
diff --git a/crates/ide_assists/src/utils/suggest_name.rs b/crates/ide_assists/src/utils/suggest_name.rs index d37c62642..533624c1f 100644 --- a/crates/ide_assists/src/utils/suggest_name.rs +++ b/crates/ide_assists/src/utils/suggest_name.rs | |||
@@ -11,17 +11,20 @@ use syntax::{ | |||
11 | 11 | ||
12 | /// Trait names, that will be ignored when in `impl Trait` and `dyn Trait` | 12 | /// Trait names, that will be ignored when in `impl Trait` and `dyn Trait` |
13 | const USELESS_TRAITS: &[&str] = &["Send", "Sync", "Copy", "Clone", "Eq", "PartialEq"]; | 13 | const USELESS_TRAITS: &[&str] = &["Send", "Sync", "Copy", "Clone", "Eq", "PartialEq"]; |
14 | |||
14 | /// Identifier names that won't be suggested, ever | 15 | /// Identifier names that won't be suggested, ever |
15 | /// | 16 | /// |
16 | /// **NOTE**: they all must be snake lower case | 17 | /// **NOTE**: they all must be snake lower case |
17 | const USELESS_NAMES: &[&str] = | 18 | const USELESS_NAMES: &[&str] = |
18 | &["new", "default", "option", "some", "none", "ok", "err", "str", "string"]; | 19 | &["new", "default", "option", "some", "none", "ok", "err", "str", "string"]; |
20 | |||
19 | /// Generic types replaced by their first argument | 21 | /// Generic types replaced by their first argument |
20 | /// | 22 | /// |
21 | /// # Examples | 23 | /// # Examples |
22 | /// `Option<Name>` -> `Name` | 24 | /// `Option<Name>` -> `Name` |
23 | /// `Result<User, Error>` -> `User` | 25 | /// `Result<User, Error>` -> `User` |
24 | const WRAPPER_TYPES: &[&str] = &["Box", "Option", "Result"]; | 26 | const WRAPPER_TYPES: &[&str] = &["Box", "Option", "Result"]; |
27 | |||
25 | /// Prefixes to strip from methods names | 28 | /// Prefixes to strip from methods names |
26 | /// | 29 | /// |
27 | /// # Examples | 30 | /// # Examples |
@@ -29,6 +32,7 @@ const WRAPPER_TYPES: &[&str] = &["Box", "Option", "Result"]; | |||
29 | /// `args.into_config()` -> `config` | 32 | /// `args.into_config()` -> `config` |
30 | /// `bytes.to_vec()` -> `vec` | 33 | /// `bytes.to_vec()` -> `vec` |
31 | const USELESS_METHOD_PREFIXES: &[&str] = &["into_", "as_", "to_"]; | 34 | const USELESS_METHOD_PREFIXES: &[&str] = &["into_", "as_", "to_"]; |
35 | |||
32 | /// Useless methods that are stripped from expression | 36 | /// Useless methods that are stripped from expression |
33 | /// | 37 | /// |
34 | /// # Examples | 38 | /// # Examples |
@@ -253,625 +257,473 @@ fn trait_name(trait_: &hir::Trait, db: &RootDatabase) -> Option<String> { | |||
253 | 257 | ||
254 | #[cfg(test)] | 258 | #[cfg(test)] |
255 | mod tests { | 259 | mod tests { |
256 | use super::*; | 260 | use ide_db::base_db::{fixture::WithFixture, FileRange}; |
257 | |||
258 | use crate::tests::check_name_suggestion; | ||
259 | |||
260 | mod from_func_call { | ||
261 | use super::*; | ||
262 | |||
263 | #[test] | ||
264 | fn no_args() { | ||
265 | check_name_suggestion( | ||
266 | |e, _| from_func_call(e), | ||
267 | r#" | ||
268 | fn foo() { | ||
269 | $0bar()$0 | ||
270 | }"#, | ||
271 | "bar", | ||
272 | ); | ||
273 | } | ||
274 | 261 | ||
275 | #[test] | 262 | use super::*; |
276 | fn single_arg() { | ||
277 | check_name_suggestion( | ||
278 | |e, _| from_func_call(e), | ||
279 | r#" | ||
280 | fn foo() { | ||
281 | $0bar(1)$0 | ||
282 | }"#, | ||
283 | "bar", | ||
284 | ); | ||
285 | } | ||
286 | |||
287 | #[test] | ||
288 | fn many_args() { | ||
289 | check_name_suggestion( | ||
290 | |e, _| from_func_call(e), | ||
291 | r#" | ||
292 | fn foo() { | ||
293 | $0bar(1, 2, 3)$0 | ||
294 | }"#, | ||
295 | "bar", | ||
296 | ); | ||
297 | } | ||
298 | |||
299 | #[test] | ||
300 | fn path() { | ||
301 | check_name_suggestion( | ||
302 | |e, _| from_func_call(e), | ||
303 | r#" | ||
304 | fn foo() { | ||
305 | $0i32::bar(1, 2, 3)$0 | ||
306 | }"#, | ||
307 | "bar", | ||
308 | ); | ||
309 | } | ||
310 | 263 | ||
311 | #[test] | 264 | #[track_caller] |
312 | fn generic_params() { | 265 | fn check(ra_fixture: &str, expected: &str) { |
313 | check_name_suggestion( | 266 | let (db, file_id, range_or_offset) = RootDatabase::with_range_or_offset(ra_fixture); |
314 | |e, _| from_func_call(e), | 267 | let frange = FileRange { file_id, range: range_or_offset.into() }; |
315 | r#" | 268 | |
316 | fn foo() { | 269 | let sema = Semantics::new(&db); |
317 | $0bar::<i32>(1, 2, 3)$0 | 270 | let source_file = sema.parse(frange.file_id); |
318 | }"#, | 271 | let element = source_file.syntax().covering_element(frange.range); |
319 | "bar", | 272 | let expr = |
320 | ); | 273 | element.ancestors().find_map(ast::Expr::cast).expect("selection is not an expression"); |
321 | } | 274 | assert_eq!( |
275 | expr.syntax().text_range(), | ||
276 | frange.range, | ||
277 | "selection is not an expression(yet contained in one)" | ||
278 | ); | ||
279 | let name = variable(&expr, &sema); | ||
280 | assert_eq!(&name, expected); | ||
322 | } | 281 | } |
323 | 282 | ||
324 | mod from_method_call { | 283 | #[test] |
325 | use super::*; | 284 | fn no_args() { |
326 | 285 | check(r#"fn foo() { $0bar()$0 }"#, "bar"); | |
327 | #[test] | 286 | check(r#"fn foo() { $0bar.frobnicate()$0 }"#, "frobnicate"); |
328 | fn no_args() { | ||
329 | check_name_suggestion( | ||
330 | |e, _| from_method_call(e), | ||
331 | r#" | ||
332 | fn foo() { | ||
333 | $0bar.frobnicate()$0 | ||
334 | }"#, | ||
335 | "frobnicate", | ||
336 | ); | ||
337 | } | ||
338 | |||
339 | #[test] | ||
340 | fn generic_params() { | ||
341 | check_name_suggestion( | ||
342 | |e, _| from_method_call(e), | ||
343 | r#" | ||
344 | fn foo() { | ||
345 | $0bar.frobnicate::<i32, u32>()$0 | ||
346 | }"#, | ||
347 | "frobnicate", | ||
348 | ); | ||
349 | } | ||
350 | |||
351 | #[test] | ||
352 | fn to_name() { | ||
353 | check_name_suggestion( | ||
354 | |e, _| from_method_call(e), | ||
355 | r#" | ||
356 | struct Args; | ||
357 | struct Config; | ||
358 | impl Args { | ||
359 | fn to_config(&self) -> Config {} | ||
360 | } | ||
361 | fn foo() { | ||
362 | $0Args.to_config()$0; | ||
363 | }"#, | ||
364 | "config", | ||
365 | ); | ||
366 | } | ||
367 | } | 287 | } |
368 | 288 | ||
369 | mod from_param { | 289 | #[test] |
370 | use crate::tests::check_name_suggestion_not_applicable; | 290 | fn single_arg() { |
291 | check(r#"fn foo() { $0bar(1)$0 }"#, "bar"); | ||
292 | } | ||
371 | 293 | ||
372 | use super::*; | 294 | #[test] |
295 | fn many_args() { | ||
296 | check(r#"fn foo() { $0bar(1, 2, 3)$0 }"#, "bar"); | ||
297 | } | ||
373 | 298 | ||
374 | #[test] | 299 | #[test] |
375 | fn plain_func() { | 300 | fn path() { |
376 | check_name_suggestion( | 301 | check(r#"fn foo() { $0i32::bar(1, 2, 3)$0 }"#, "bar"); |
377 | from_param, | 302 | } |
378 | r#" | ||
379 | fn bar(n: i32, m: u32); | ||
380 | fn foo() { | ||
381 | bar($01$0, 2) | ||
382 | }"#, | ||
383 | "n", | ||
384 | ); | ||
385 | } | ||
386 | 303 | ||
387 | #[test] | 304 | #[test] |
388 | fn mut_param() { | 305 | fn generic_params() { |
389 | check_name_suggestion( | 306 | check(r#"fn foo() { $0bar::<i32>(1, 2, 3)$0 }"#, "bar"); |
390 | from_param, | 307 | check(r#"fn foo() { $0bar.frobnicate::<i32, u32>()$0 }"#, "frobnicate"); |
391 | r#" | 308 | } |
392 | fn bar(mut n: i32, m: u32); | ||
393 | fn foo() { | ||
394 | bar($01$0, 2) | ||
395 | }"#, | ||
396 | "n", | ||
397 | ); | ||
398 | } | ||
399 | 309 | ||
400 | #[test] | 310 | #[test] |
401 | fn func_does_not_exist() { | 311 | fn to_name() { |
402 | check_name_suggestion_not_applicable( | 312 | check( |
403 | from_param, | 313 | r#" |
404 | r#" | 314 | struct Args; |
405 | fn foo() { | 315 | struct Config; |
406 | bar($01$0, 2) | 316 | impl Args { |
407 | }"#, | 317 | fn to_config(&self) -> Config {} |
408 | ); | 318 | } |
409 | } | 319 | fn foo() { |
320 | $0Args.to_config()$0; | ||
321 | } | ||
322 | "#, | ||
323 | "config", | ||
324 | ); | ||
325 | } | ||
410 | 326 | ||
411 | #[test] | 327 | #[test] |
412 | fn unnamed_param() { | 328 | fn plain_func() { |
413 | check_name_suggestion_not_applicable( | 329 | check( |
414 | from_param, | 330 | r#" |
415 | r#" | 331 | fn bar(n: i32, m: u32); |
416 | fn bar(_: i32, m: u32); | 332 | fn foo() { bar($01$0, 2) } |
417 | fn foo() { | 333 | "#, |
418 | bar($01$0, 2) | 334 | "n", |
419 | }"#, | 335 | ); |
420 | ); | 336 | } |
421 | } | ||
422 | 337 | ||
423 | #[test] | 338 | #[test] |
424 | fn tuple_pat() { | 339 | fn mut_param() { |
425 | check_name_suggestion_not_applicable( | 340 | check( |
426 | from_param, | 341 | r#" |
427 | r#" | 342 | fn bar(mut n: i32, m: u32); |
428 | fn bar((n, k): (i32, i32), m: u32); | 343 | fn foo() { bar($01$0, 2) } |
429 | fn foo() { | 344 | "#, |
430 | bar($0(1, 2)$0, 3) | 345 | "n", |
431 | }"#, | 346 | ); |
432 | ); | 347 | } |
433 | } | ||
434 | 348 | ||
435 | #[test] | 349 | #[test] |
436 | fn ref_pat() { | 350 | fn func_does_not_exist() { |
437 | check_name_suggestion( | 351 | check(r#"fn foo() { bar($01$0, 2) }"#, "var_name"); |
438 | from_param, | 352 | } |
439 | r#" | ||
440 | fn bar(&n: &i32, m: u32); | ||
441 | fn foo() { | ||
442 | bar($0&1$0, 3) | ||
443 | }"#, | ||
444 | "n", | ||
445 | ); | ||
446 | } | ||
447 | 353 | ||
448 | #[test] | 354 | #[test] |
449 | fn box_pat() { | 355 | fn unnamed_param() { |
450 | check_name_suggestion( | 356 | check( |
451 | from_param, | 357 | r#" |
452 | r#" | 358 | fn bar(_: i32, m: u32); |
453 | fn bar(box n: &i32, m: u32); | 359 | fn foo() { bar($01$0, 2) } |
454 | fn foo() { | 360 | "#, |
455 | bar($01$0, 3) | 361 | "var_name", |
456 | }"#, | 362 | ); |
457 | "n", | 363 | } |
458 | ); | ||
459 | } | ||
460 | 364 | ||
461 | #[test] | 365 | #[test] |
462 | fn param_out_of_index() { | 366 | fn tuple_pat() { |
463 | check_name_suggestion_not_applicable( | 367 | check( |
464 | from_param, | 368 | r#" |
465 | r#" | 369 | fn bar((n, k): (i32, i32), m: u32); |
466 | fn bar(n: i32, m: u32); | 370 | fn foo() { |
467 | fn foo() { | 371 | bar($0(1, 2)$0, 3) |
468 | bar(1, 2, $03$0) | 372 | } |
469 | }"#, | 373 | "#, |
470 | ); | 374 | "var_name", |
471 | } | 375 | ); |
376 | } | ||
472 | 377 | ||
473 | #[test] | 378 | #[test] |
474 | fn generic_param_resolved() { | 379 | fn ref_pat() { |
475 | check_name_suggestion( | 380 | check( |
476 | from_param, | 381 | r#" |
477 | r#" | 382 | fn bar(&n: &i32, m: u32); |
478 | fn bar<T>(n: T, m: u32); | 383 | fn foo() { bar($0&1$0, 3) } |
479 | fn foo() { | 384 | "#, |
480 | bar($01$0, 2) | 385 | "n", |
481 | }"#, | 386 | ); |
482 | "n", | 387 | } |
483 | ); | ||
484 | } | ||
485 | 388 | ||
486 | #[test] | 389 | #[test] |
487 | fn generic_param_unresolved() { | 390 | fn box_pat() { |
488 | check_name_suggestion( | 391 | check( |
489 | from_param, | 392 | r#" |
490 | r#" | 393 | fn bar(box n: &i32, m: u32); |
491 | fn bar<T>(n: T, m: u32); | 394 | fn foo() { bar($01$0, 3) } |
492 | fn foo<T>(x: T) { | 395 | "#, |
493 | bar($0x$0, 2) | 396 | "n", |
494 | }"#, | 397 | ); |
495 | "n", | 398 | } |
496 | ); | ||
497 | } | ||
498 | 399 | ||
499 | #[test] | 400 | #[test] |
500 | fn method() { | 401 | fn param_out_of_index() { |
501 | check_name_suggestion( | 402 | check( |
502 | from_param, | 403 | r#" |
503 | r#" | 404 | fn bar(n: i32, m: u32); |
504 | struct S; | 405 | fn foo() { bar(1, 2, $03$0) } |
505 | impl S { | 406 | "#, |
506 | fn bar(&self, n: i32, m: u32); | 407 | "var_name", |
507 | } | 408 | ); |
508 | fn foo() { | 409 | } |
509 | S.bar($01$0, 2) | ||
510 | }"#, | ||
511 | "n", | ||
512 | ); | ||
513 | } | ||
514 | 410 | ||
515 | #[test] | 411 | #[test] |
516 | fn method_ufcs() { | 412 | fn generic_param_resolved() { |
517 | check_name_suggestion( | 413 | check( |
518 | from_param, | 414 | r#" |
519 | r#" | 415 | fn bar<T>(n: T, m: u32); |
520 | struct S; | 416 | fn foo() { bar($01$0, 2) } |
521 | impl S { | 417 | "#, |
522 | fn bar(&self, n: i32, m: u32); | 418 | "n", |
523 | } | 419 | ); |
524 | fn foo() { | 420 | } |
525 | S::bar(&S, $01$0, 2) | ||
526 | }"#, | ||
527 | "n", | ||
528 | ); | ||
529 | } | ||
530 | 421 | ||
531 | #[test] | 422 | #[test] |
532 | fn method_self() { | 423 | fn generic_param_unresolved() { |
533 | check_name_suggestion_not_applicable( | 424 | check( |
534 | from_param, | 425 | r#" |
535 | r#" | 426 | fn bar<T>(n: T, m: u32); |
536 | struct S; | 427 | fn foo<T>(x: T) { bar($0x$0, 2) } |
537 | impl S { | 428 | "#, |
538 | fn bar(&self, n: i32, m: u32); | 429 | "n", |
539 | } | 430 | ); |
540 | fn foo() { | 431 | } |
541 | S::bar($0&S$0, 1, 2) | ||
542 | }"#, | ||
543 | ); | ||
544 | } | ||
545 | 432 | ||
546 | #[test] | 433 | #[test] |
547 | fn method_self_named() { | 434 | fn method() { |
548 | check_name_suggestion( | 435 | check( |
549 | from_param, | 436 | r#" |
550 | r#" | 437 | struct S; |
551 | struct S; | 438 | impl S { fn bar(&self, n: i32, m: u32); } |
552 | impl S { | 439 | fn foo() { S.bar($01$0, 2) } |
553 | fn bar(strukt: &Self, n: i32, m: u32); | 440 | "#, |
554 | } | 441 | "n", |
555 | fn foo() { | 442 | ); |
556 | S::bar($0&S$0, 1, 2) | ||
557 | }"#, | ||
558 | "strukt", | ||
559 | ); | ||
560 | } | ||
561 | } | 443 | } |
562 | 444 | ||
563 | mod from_type { | 445 | #[test] |
564 | use crate::tests::check_name_suggestion_not_applicable; | 446 | fn method_ufcs() { |
447 | check( | ||
448 | r#" | ||
449 | struct S; | ||
450 | impl S { fn bar(&self, n: i32, m: u32); } | ||
451 | fn foo() { S::bar(&S, $01$0, 2) } | ||
452 | "#, | ||
453 | "n", | ||
454 | ); | ||
455 | } | ||
565 | 456 | ||
566 | use super::*; | 457 | #[test] |
458 | fn method_self() { | ||
459 | check( | ||
460 | r#" | ||
461 | struct S; | ||
462 | impl S { fn bar(&self, n: i32, m: u32); } | ||
463 | fn foo() { S::bar($0&S$0, 1, 2) } | ||
464 | "#, | ||
465 | "s", | ||
466 | ); | ||
467 | } | ||
567 | 468 | ||
568 | #[test] | 469 | #[test] |
569 | fn i32() { | 470 | fn method_self_named() { |
570 | check_name_suggestion_not_applicable( | 471 | check( |
571 | from_type, | 472 | r#" |
572 | r#" | 473 | struct S; |
573 | fn foo() { | 474 | impl S { fn bar(strukt: &Self, n: i32, m: u32); } |
574 | let _: i32 = $01$0; | 475 | fn foo() { S::bar($0&S$0, 1, 2) } |
575 | }"#, | 476 | "#, |
576 | ); | 477 | "strukt", |
577 | } | 478 | ); |
479 | } | ||
578 | 480 | ||
579 | #[test] | 481 | #[test] |
580 | fn u64() { | 482 | fn i32() { |
581 | check_name_suggestion_not_applicable( | 483 | check(r#"fn foo() { let _: i32 = $01$0; }"#, "var_name"); |
582 | from_type, | 484 | } |
583 | r#" | ||
584 | fn foo() { | ||
585 | let _: u64 = $01$0; | ||
586 | }"#, | ||
587 | ); | ||
588 | } | ||
589 | 485 | ||
590 | #[test] | 486 | #[test] |
591 | fn bool() { | 487 | fn u64() { |
592 | check_name_suggestion_not_applicable( | 488 | check(r#"fn foo() { let _: u64 = $01$0; }"#, "var_name"); |
593 | from_type, | 489 | } |
594 | r#" | ||
595 | fn foo() { | ||
596 | let _: bool = $0true$0; | ||
597 | }"#, | ||
598 | ); | ||
599 | } | ||
600 | 490 | ||
601 | #[test] | 491 | #[test] |
602 | fn struct_unit() { | 492 | fn bool() { |
603 | check_name_suggestion( | 493 | check(r#"fn foo() { let _: bool = $0true$0; }"#, "var_name"); |
604 | from_type, | 494 | } |
605 | r#" | ||
606 | struct Seed; | ||
607 | fn foo() { | ||
608 | let _ = $0Seed$0; | ||
609 | }"#, | ||
610 | "seed", | ||
611 | ); | ||
612 | } | ||
613 | 495 | ||
614 | #[test] | 496 | #[test] |
615 | fn struct_unit_to_snake() { | 497 | fn struct_unit() { |
616 | check_name_suggestion( | 498 | check( |
617 | from_type, | 499 | r#" |
618 | r#" | 500 | struct Seed; |
619 | struct SeedState; | 501 | fn foo() { let _ = $0Seed$0; } |
620 | fn foo() { | 502 | "#, |
621 | let _ = $0SeedState$0; | 503 | "seed", |
622 | }"#, | 504 | ); |
623 | "seed_state", | 505 | } |
624 | ); | ||
625 | } | ||
626 | 506 | ||
627 | #[test] | 507 | #[test] |
628 | fn struct_single_arg() { | 508 | fn struct_unit_to_snake() { |
629 | check_name_suggestion( | 509 | check( |
630 | from_type, | 510 | r#" |
631 | r#" | 511 | struct SeedState; |
632 | struct Seed(u32); | 512 | fn foo() { let _ = $0SeedState$0; } |
633 | fn foo() { | 513 | "#, |
634 | let _ = $0Seed(0)$0; | 514 | "seed_state", |
635 | }"#, | 515 | ); |
636 | "seed", | 516 | } |
637 | ); | ||
638 | } | ||
639 | 517 | ||
640 | #[test] | 518 | #[test] |
641 | fn struct_with_fields() { | 519 | fn struct_single_arg() { |
642 | check_name_suggestion( | 520 | check( |
643 | from_type, | 521 | r#" |
644 | r#" | 522 | struct Seed(u32); |
645 | struct Seed { value: u32 } | 523 | fn foo() { let _ = $0Seed(0)$0; } |
646 | fn foo() { | 524 | "#, |
647 | let _ = $0Seed { value: 0 }$0; | 525 | "seed", |
648 | }"#, | 526 | ); |
649 | "seed", | 527 | } |
650 | ); | ||
651 | } | ||
652 | 528 | ||
653 | #[test] | 529 | #[test] |
654 | fn enum_() { | 530 | fn struct_with_fields() { |
655 | check_name_suggestion( | 531 | check( |
656 | from_type, | 532 | r#" |
657 | r#" | 533 | struct Seed { value: u32 } |
658 | enum Kind { A, B } | 534 | fn foo() { let _ = $0Seed { value: 0 }$0; } |
659 | fn foo() { | 535 | "#, |
660 | let _ = $0Kind::A$0; | 536 | "seed", |
661 | }"#, | 537 | ); |
662 | "kind", | 538 | } |
663 | ); | ||
664 | } | ||
665 | 539 | ||
666 | #[test] | 540 | #[test] |
667 | fn enum_generic_resolved() { | 541 | fn enum_() { |
668 | check_name_suggestion( | 542 | check( |
669 | from_type, | 543 | r#" |
670 | r#" | 544 | enum Kind { A, B } |
671 | enum Kind<T> { A(T), B } | 545 | fn foo() { let _ = $0Kind::A$0; } |
672 | fn foo() { | 546 | "#, |
673 | let _ = $0Kind::A(1)$0; | 547 | "kind", |
674 | }"#, | 548 | ); |
675 | "kind", | 549 | } |
676 | ); | ||
677 | } | ||
678 | 550 | ||
679 | #[test] | 551 | #[test] |
680 | fn enum_generic_unresolved() { | 552 | fn enum_generic_resolved() { |
681 | check_name_suggestion( | 553 | check( |
682 | from_type, | 554 | r#" |
683 | r#" | 555 | enum Kind<T> { A { x: T }, B } |
684 | enum Kind<T> { A(T), B } | 556 | fn foo() { let _ = $0Kind::A { x:1 }$0; } |
685 | fn foo<T>(x: T) { | 557 | "#, |
686 | let _ = $0Kind::A(x)$0; | 558 | "kind", |
687 | }"#, | 559 | ); |
688 | "kind", | 560 | } |
689 | ); | ||
690 | } | ||
691 | 561 | ||
692 | #[test] | 562 | #[test] |
693 | fn dyn_trait() { | 563 | fn enum_generic_unresolved() { |
694 | check_name_suggestion( | 564 | check( |
695 | from_type, | 565 | r#" |
696 | r#" | 566 | enum Kind<T> { A { x: T }, B } |
697 | trait DynHandler {} | 567 | fn foo<T>(x: T) { let _ = $0Kind::A { x }$0; } |
698 | fn bar() -> dyn DynHandler {} | 568 | "#, |
699 | fn foo() { | 569 | "kind", |
700 | $0bar()$0; | 570 | ); |
701 | }"#, | 571 | } |
702 | "dyn_handler", | ||
703 | ); | ||
704 | } | ||
705 | 572 | ||
706 | #[test] | 573 | #[test] |
707 | fn impl_trait() { | 574 | fn dyn_trait() { |
708 | check_name_suggestion( | 575 | check( |
709 | from_type, | 576 | r#" |
710 | r#" | 577 | trait DynHandler {} |
711 | trait StaticHandler {} | 578 | fn bar() -> dyn DynHandler {} |
712 | fn bar() -> impl StaticHandler {} | 579 | fn foo() { $0(bar())$0; } |
713 | fn foo() { | 580 | "#, |
714 | $0bar()$0; | 581 | "dyn_handler", |
715 | }"#, | 582 | ); |
716 | "static_handler", | 583 | } |
717 | ); | ||
718 | } | ||
719 | 584 | ||
720 | #[test] | 585 | #[test] |
721 | fn impl_trait_plus_clone() { | 586 | fn impl_trait() { |
722 | check_name_suggestion( | 587 | check( |
723 | from_type, | 588 | r#" |
724 | r#" | 589 | trait StaticHandler {} |
725 | trait StaticHandler {} | 590 | fn bar() -> impl StaticHandler {} |
726 | trait Clone {} | 591 | fn foo() { $0(bar())$0; } |
727 | fn bar() -> impl StaticHandler + Clone {} | 592 | "#, |
728 | fn foo() { | 593 | "static_handler", |
729 | $0bar()$0; | 594 | ); |
730 | }"#, | 595 | } |
731 | "static_handler", | ||
732 | ); | ||
733 | } | ||
734 | 596 | ||
735 | #[test] | 597 | #[test] |
736 | fn impl_trait_plus_lifetime() { | 598 | fn impl_trait_plus_clone() { |
737 | check_name_suggestion( | 599 | check( |
738 | from_type, | 600 | r#" |
739 | r#" | 601 | trait StaticHandler {} |
740 | trait StaticHandler {} | 602 | trait Clone {} |
741 | trait Clone {} | 603 | fn bar() -> impl StaticHandler + Clone {} |
742 | fn bar<'a>(&'a i32) -> impl StaticHandler + 'a {} | 604 | fn foo() { $0(bar())$0; } |
743 | fn foo() { | 605 | "#, |
744 | $0bar(&1)$0; | 606 | "static_handler", |
745 | }"#, | 607 | ); |
746 | "static_handler", | 608 | } |
747 | ); | ||
748 | } | ||
749 | 609 | ||
750 | #[test] | 610 | #[test] |
751 | fn impl_trait_plus_trait() { | 611 | fn impl_trait_plus_lifetime() { |
752 | check_name_suggestion_not_applicable( | 612 | check( |
753 | from_type, | 613 | r#" |
754 | r#" | 614 | trait StaticHandler {} |
755 | trait Handler {} | 615 | trait Clone {} |
756 | trait StaticHandler {} | 616 | fn bar<'a>(&'a i32) -> impl StaticHandler + 'a {} |
757 | fn bar() -> impl StaticHandler + Handler {} | 617 | fn foo() { $0(bar(&1))$0; } |
758 | fn foo() { | 618 | "#, |
759 | $0bar()$0; | 619 | "static_handler", |
760 | }"#, | 620 | ); |
761 | ); | 621 | } |
762 | } | ||
763 | 622 | ||
764 | #[test] | 623 | #[test] |
765 | fn ref_value() { | 624 | fn impl_trait_plus_trait() { |
766 | check_name_suggestion( | 625 | check( |
767 | from_type, | 626 | r#" |
768 | r#" | 627 | trait Handler {} |
769 | struct Seed; | 628 | trait StaticHandler {} |
770 | fn bar() -> &Seed {} | 629 | fn bar() -> impl StaticHandler + Handler {} |
771 | fn foo() { | 630 | fn foo() { $0(bar())$0; } |
772 | $0bar()$0; | 631 | "#, |
773 | }"#, | 632 | "bar", |
774 | "seed", | 633 | ); |
775 | ); | 634 | } |
776 | } | ||
777 | 635 | ||
778 | #[test] | 636 | #[test] |
779 | fn box_value() { | 637 | fn ref_value() { |
780 | check_name_suggestion( | 638 | check( |
781 | from_type, | 639 | r#" |
782 | r#" | 640 | struct Seed; |
783 | struct Box<T>(*const T); | 641 | fn bar() -> &Seed {} |
784 | struct Seed; | 642 | fn foo() { $0(bar())$0; } |
785 | fn bar() -> Box<Seed> {} | 643 | "#, |
786 | fn foo() { | 644 | "seed", |
787 | $0bar()$0; | 645 | ); |
788 | }"#, | 646 | } |
789 | "seed", | ||
790 | ); | ||
791 | } | ||
792 | 647 | ||
793 | #[test] | 648 | #[test] |
794 | fn box_generic() { | 649 | fn box_value() { |
795 | check_name_suggestion_not_applicable( | 650 | check( |
796 | from_type, | 651 | r#" |
797 | r#" | 652 | struct Box<T>(*const T); |
798 | struct Box<T>(*const T); | 653 | struct Seed; |
799 | fn bar<T>() -> Box<T> {} | 654 | fn bar() -> Box<Seed> {} |
800 | fn foo<T>() { | 655 | fn foo() { $0(bar())$0; } |
801 | $0bar::<T>()$0; | 656 | "#, |
802 | }"#, | 657 | "seed", |
803 | ); | 658 | ); |
804 | } | 659 | } |
805 | 660 | ||
806 | #[test] | 661 | #[test] |
807 | fn option_value() { | 662 | fn box_generic() { |
808 | check_name_suggestion( | 663 | check( |
809 | from_type, | 664 | r#" |
810 | r#" | 665 | struct Box<T>(*const T); |
811 | enum Option<T> { Some(T) } | 666 | fn bar<T>() -> Box<T> {} |
812 | struct Seed; | 667 | fn foo<T>() { $0(bar::<T>())$0; } |
813 | fn bar() -> Option<Seed> {} | 668 | "#, |
814 | fn foo() { | 669 | "bar", |
815 | $0bar()$0; | 670 | ); |
816 | }"#, | 671 | } |
817 | "seed", | ||
818 | ); | ||
819 | } | ||
820 | 672 | ||
821 | #[test] | 673 | #[test] |
822 | fn result_value() { | 674 | fn option_value() { |
823 | check_name_suggestion( | 675 | check( |
824 | from_type, | 676 | r#" |
825 | r#" | 677 | enum Option<T> { Some(T) } |
826 | enum Result<T, E> { Ok(T), Err(E) } | 678 | struct Seed; |
827 | struct Seed; | 679 | fn bar() -> Option<Seed> {} |
828 | struct Error; | 680 | fn foo() { $0(bar())$0; } |
829 | fn bar() -> Result<Seed, Error> {} | 681 | "#, |
830 | fn foo() { | 682 | "seed", |
831 | $0bar()$0; | 683 | ); |
832 | }"#, | ||
833 | "seed", | ||
834 | ); | ||
835 | } | ||
836 | } | 684 | } |
837 | 685 | ||
838 | mod variable { | 686 | #[test] |
839 | use super::*; | 687 | fn result_value() { |
688 | check( | ||
689 | r#" | ||
690 | enum Result<T, E> { Ok(T), Err(E) } | ||
691 | struct Seed; | ||
692 | struct Error; | ||
693 | fn bar() -> Result<Seed, Error> {} | ||
694 | fn foo() { $0(bar())$0; } | ||
695 | "#, | ||
696 | "seed", | ||
697 | ); | ||
698 | } | ||
840 | 699 | ||
841 | #[test] | 700 | #[test] |
842 | fn ref_call() { | 701 | fn ref_call() { |
843 | check_name_suggestion( | 702 | check( |
844 | |e, c| Some(variable(e, c)), | 703 | r#" |
845 | r#" | 704 | fn foo() { $0&bar(1, 3)$0 } |
846 | fn foo() { | 705 | "#, |
847 | $0&bar(1, 3)$0 | 706 | "bar", |
848 | }"#, | 707 | ); |
849 | "bar", | 708 | } |
850 | ); | ||
851 | } | ||
852 | 709 | ||
853 | #[test] | 710 | #[test] |
854 | fn name_to_string() { | 711 | fn name_to_string() { |
855 | check_name_suggestion( | 712 | check( |
856 | |e, c| Some(variable(e, c)), | 713 | r#" |
857 | r#" | 714 | fn foo() { $0function.name().to_string()$0 } |
858 | fn foo() { | 715 | "#, |
859 | $0function.name().to_string()$0 | 716 | "name", |
860 | }"#, | 717 | ); |
861 | "name", | 718 | } |
862 | ); | ||
863 | } | ||
864 | 719 | ||
865 | #[test] | 720 | #[test] |
866 | fn nested_useless_method() { | 721 | fn nested_useless_method() { |
867 | check_name_suggestion( | 722 | check( |
868 | |e, c| Some(variable(e, c)), | 723 | r#" |
869 | r#" | 724 | fn foo() { $0function.name().as_ref().unwrap().to_string()$0 } |
870 | fn foo() { | 725 | "#, |
871 | $0function.name().as_ref().unwrap().to_string()$0 | 726 | "name", |
872 | }"#, | 727 | ); |
873 | "name", | ||
874 | ); | ||
875 | } | ||
876 | } | 728 | } |
877 | } | 729 | } |