diff options
-rw-r--r-- | crates/ide/src/references/rename.rs | 75 |
1 files changed, 58 insertions, 17 deletions
diff --git a/crates/ide/src/references/rename.rs b/crates/ide/src/references/rename.rs index 6040fc1f8..44dfa9a0e 100644 --- a/crates/ide/src/references/rename.rs +++ b/crates/ide/src/references/rename.rs | |||
@@ -14,7 +14,7 @@ use ide_db::{ | |||
14 | use syntax::{ | 14 | use syntax::{ |
15 | algo::find_node_at_offset, | 15 | algo::find_node_at_offset, |
16 | ast::{self, NameOwner}, | 16 | ast::{self, NameOwner}, |
17 | lex_single_syntax_kind, match_ast, AstNode, SyntaxKind, SyntaxNode, SyntaxToken, | 17 | lex_single_syntax_kind, match_ast, AstNode, SyntaxKind, SyntaxNode, SyntaxToken, T, |
18 | }; | 18 | }; |
19 | use test_utils::mark; | 19 | use test_utils::mark; |
20 | use text_edit::TextEdit; | 20 | use text_edit::TextEdit; |
@@ -55,7 +55,7 @@ pub(crate) fn prepare_rename( | |||
55 | if let Some(module) = find_module_at_offset(&sema, position, syntax) { | 55 | if let Some(module) = find_module_at_offset(&sema, position, syntax) { |
56 | rename_mod(&sema, position, module, "dummy") | 56 | rename_mod(&sema, position, module, "dummy") |
57 | } else if let Some(self_token) = | 57 | } else if let Some(self_token) = |
58 | syntax.token_at_offset(position.offset).find(|t| t.kind() == SyntaxKind::SELF_KW) | 58 | syntax.token_at_offset(position.offset).find(|t| t.kind() == T![self]) |
59 | { | 59 | { |
60 | rename_self_to_param(&sema, position, self_token, "dummy") | 60 | rename_self_to_param(&sema, position, self_token, "dummy") |
61 | } else { | 61 | } else { |
@@ -85,7 +85,7 @@ pub(crate) fn rename_with_semantics( | |||
85 | if let Some(module) = find_module_at_offset(&sema, position, syntax) { | 85 | if let Some(module) = find_module_at_offset(&sema, position, syntax) { |
86 | rename_mod(&sema, position, module, new_name) | 86 | rename_mod(&sema, position, module, new_name) |
87 | } else if let Some(self_token) = | 87 | } else if let Some(self_token) = |
88 | syntax.token_at_offset(position.offset).find(|t| t.kind() == SyntaxKind::SELF_KW) | 88 | syntax.token_at_offset(position.offset).find(|t| t.kind() == T![self]) |
89 | { | 89 | { |
90 | rename_self_to_param(&sema, position, self_token, new_name) | 90 | rename_self_to_param(&sema, position, self_token, new_name) |
91 | } else { | 91 | } else { |
@@ -110,7 +110,7 @@ pub(crate) fn will_rename_file( | |||
110 | Some(change) | 110 | Some(change) |
111 | } | 111 | } |
112 | 112 | ||
113 | #[derive(PartialEq)] | 113 | #[derive(Debug, PartialEq)] |
114 | enum IdentifierKind { | 114 | enum IdentifierKind { |
115 | Ident, | 115 | Ident, |
116 | Lifetime, | 116 | Lifetime, |
@@ -122,8 +122,8 @@ fn check_identifier(new_name: &str) -> RenameResult<IdentifierKind> { | |||
122 | match lex_single_syntax_kind(new_name) { | 122 | match lex_single_syntax_kind(new_name) { |
123 | Some(res) => match res { | 123 | Some(res) => match res { |
124 | (SyntaxKind::IDENT, _) => Ok(IdentifierKind::Ident), | 124 | (SyntaxKind::IDENT, _) => Ok(IdentifierKind::Ident), |
125 | (SyntaxKind::UNDERSCORE, _) => Ok(IdentifierKind::Underscore), | 125 | (T![_], _) => Ok(IdentifierKind::Underscore), |
126 | (SyntaxKind::SELF_KW, _) => Ok(IdentifierKind::ToSelf), | 126 | (T![self], _) => Ok(IdentifierKind::ToSelf), |
127 | (SyntaxKind::LIFETIME_IDENT, _) if new_name != "'static" && new_name != "'_" => { | 127 | (SyntaxKind::LIFETIME_IDENT, _) if new_name != "'static" && new_name != "'_" => { |
128 | Ok(IdentifierKind::Lifetime) | 128 | Ok(IdentifierKind::Lifetime) |
129 | } | 129 | } |
@@ -390,6 +390,7 @@ fn rename_self_to_param( | |||
390 | IdentifierKind::Lifetime => bail!("Invalid name `{}`: not an identifier", new_name), | 390 | IdentifierKind::Lifetime => bail!("Invalid name `{}`: not an identifier", new_name), |
391 | IdentifierKind::ToSelf => { | 391 | IdentifierKind::ToSelf => { |
392 | // no-op | 392 | // no-op |
393 | mark::hit!(rename_self_to_self); | ||
393 | return Ok(RangeInfo::new(self_token.text_range(), SourceChange::default())); | 394 | return Ok(RangeInfo::new(self_token.text_range(), SourceChange::default())); |
394 | } | 395 | } |
395 | _ => (), | 396 | _ => (), |
@@ -409,9 +410,7 @@ fn rename_self_to_param( | |||
409 | if !search_range.contains_inclusive(offset) { | 410 | if !search_range.contains_inclusive(offset) { |
410 | continue; | 411 | continue; |
411 | } | 412 | } |
412 | if let Some(ref usage) = | 413 | if let Some(ref usage) = syn.token_at_offset(offset).find(|t| t.kind() == T![self]) { |
413 | syn.token_at_offset(offset).find(|t| t.kind() == SyntaxKind::SELF_KW) | ||
414 | { | ||
415 | let edit = if let Some(ref self_param) = ast::SelfParam::cast(usage.parent()) { | 414 | let edit = if let Some(ref self_param) = ast::SelfParam::cast(usage.parent()) { |
416 | text_edit_from_self_param(syn, self_param, new_name) | 415 | text_edit_from_self_param(syn, self_param, new_name) |
417 | .ok_or_else(|| format_err!("No target type found"))? | 416 | .ok_or_else(|| format_err!("No target type found"))? |
@@ -444,21 +443,26 @@ fn rename_reference( | |||
444 | (IdentifierKind::ToSelf, ReferenceKind::Lifetime) | 443 | (IdentifierKind::ToSelf, ReferenceKind::Lifetime) |
445 | | (IdentifierKind::Underscore, ReferenceKind::Lifetime) | 444 | | (IdentifierKind::Underscore, ReferenceKind::Lifetime) |
446 | | (IdentifierKind::Ident, ReferenceKind::Lifetime) => { | 445 | | (IdentifierKind::Ident, ReferenceKind::Lifetime) => { |
446 | mark::hit!(rename_not_a_lifetime_ident_ref); | ||
447 | bail!("Invalid name `{}`: not a lifetime identifier", new_name) | 447 | bail!("Invalid name `{}`: not a lifetime identifier", new_name) |
448 | } | 448 | } |
449 | (IdentifierKind::Lifetime, ReferenceKind::Lifetime) => (), | 449 | (IdentifierKind::Lifetime, ReferenceKind::Lifetime) => mark::hit!(rename_lifetime), |
450 | (IdentifierKind::Lifetime, _) => bail!("Invalid name `{}`: not an identifier", new_name), | 450 | (IdentifierKind::Lifetime, _) => { |
451 | mark::hit!(rename_not_an_ident_ref); | ||
452 | bail!("Invalid name `{}`: not an identifier", new_name) | ||
453 | } | ||
451 | (IdentifierKind::ToSelf, ReferenceKind::SelfKw) => { | 454 | (IdentifierKind::ToSelf, ReferenceKind::SelfKw) => { |
452 | //no-op | 455 | unreachable!("rename_self_to_param should've been called instead") |
453 | return Ok(RangeInfo::new(range, SourceChange::default())); | ||
454 | } | 456 | } |
455 | (IdentifierKind::ToSelf, _) => { | 457 | (IdentifierKind::ToSelf, _) => { |
458 | mark::hit!(rename_to_self); | ||
456 | return rename_to_self(sema, position); | 459 | return rename_to_self(sema, position); |
457 | } | 460 | } |
458 | (IdentifierKind::Underscore, _) if !refs.references.is_empty() => { | 461 | (IdentifierKind::Underscore, _) if !refs.references.is_empty() => { |
462 | mark::hit!(rename_underscore_multiple); | ||
459 | bail!("Cannot rename reference to `_` as it is being referenced multiple times") | 463 | bail!("Cannot rename reference to `_` as it is being referenced multiple times") |
460 | } | 464 | } |
461 | (IdentifierKind::Ident, _) | (IdentifierKind::Underscore, _) => (), | 465 | (IdentifierKind::Ident, _) | (IdentifierKind::Underscore, _) => mark::hit!(rename_ident), |
462 | } | 466 | } |
463 | 467 | ||
464 | let edit = refs | 468 | let edit = refs |
@@ -494,9 +498,11 @@ mod tests { | |||
494 | text_edit_builder.replace(indel.delete, indel.insert); | 498 | text_edit_builder.replace(indel.delete, indel.insert); |
495 | } | 499 | } |
496 | } | 500 | } |
497 | let mut result = analysis.file_text(file_id.unwrap()).unwrap().to_string(); | 501 | if let Some(file_id) = file_id { |
498 | text_edit_builder.finish().apply(&mut result); | 502 | let mut result = analysis.file_text(file_id).unwrap().to_string(); |
499 | assert_eq_text!(ra_fixture_after, &*result); | 503 | text_edit_builder.finish().apply(&mut result); |
504 | assert_eq_text!(ra_fixture_after, &*result); | ||
505 | } | ||
500 | } | 506 | } |
501 | Err(err) => { | 507 | Err(err) => { |
502 | if ra_fixture_after.starts_with("error:") { | 508 | if ra_fixture_after.starts_with("error:") { |
@@ -562,6 +568,7 @@ mod tests { | |||
562 | 568 | ||
563 | #[test] | 569 | #[test] |
564 | fn test_rename_to_invalid_identifier_lifetime() { | 570 | fn test_rename_to_invalid_identifier_lifetime() { |
571 | mark::check!(rename_not_an_ident_ref); | ||
565 | check( | 572 | check( |
566 | "'foo", | 573 | "'foo", |
567 | r#"fn main() { let i$0 = 1; }"#, | 574 | r#"fn main() { let i$0 = 1; }"#, |
@@ -571,6 +578,7 @@ mod tests { | |||
571 | 578 | ||
572 | #[test] | 579 | #[test] |
573 | fn test_rename_to_invalid_identifier_lifetime2() { | 580 | fn test_rename_to_invalid_identifier_lifetime2() { |
581 | mark::check!(rename_not_a_lifetime_ident_ref); | ||
574 | check( | 582 | check( |
575 | "foo", | 583 | "foo", |
576 | r#"fn main<'a>(_: &'a$0 ()) {}"#, | 584 | r#"fn main<'a>(_: &'a$0 ()) {}"#, |
@@ -580,6 +588,7 @@ mod tests { | |||
580 | 588 | ||
581 | #[test] | 589 | #[test] |
582 | fn test_rename_to_underscore_invalid() { | 590 | fn test_rename_to_underscore_invalid() { |
591 | mark::check!(rename_underscore_multiple); | ||
583 | check( | 592 | check( |
584 | "_", | 593 | "_", |
585 | r#"fn main(foo$0: ()) {foo;}"#, | 594 | r#"fn main(foo$0: ()) {foo;}"#, |
@@ -588,7 +597,17 @@ mod tests { | |||
588 | } | 597 | } |
589 | 598 | ||
590 | #[test] | 599 | #[test] |
600 | fn test_rename_mod_invalid() { | ||
601 | check( | ||
602 | "'foo", | ||
603 | r#"mod foo$0 {}"#, | ||
604 | "error: Invalid name `'foo`: cannot rename module to 'foo", | ||
605 | ); | ||
606 | } | ||
607 | |||
608 | #[test] | ||
591 | fn test_rename_for_local() { | 609 | fn test_rename_for_local() { |
610 | mark::check!(rename_ident); | ||
592 | check( | 611 | check( |
593 | "k", | 612 | "k", |
594 | r#" | 613 | r#" |
@@ -1219,6 +1238,7 @@ fn foo(f: foo::Foo) { | |||
1219 | 1238 | ||
1220 | #[test] | 1239 | #[test] |
1221 | fn test_parameter_to_self() { | 1240 | fn test_parameter_to_self() { |
1241 | mark::check!(rename_to_self); | ||
1222 | check( | 1242 | check( |
1223 | "self", | 1243 | "self", |
1224 | r#" | 1244 | r#" |
@@ -1522,6 +1542,7 @@ fn foo(Foo { i: bar }: foo) -> i32 { | |||
1522 | 1542 | ||
1523 | #[test] | 1543 | #[test] |
1524 | fn test_rename_lifetimes() { | 1544 | fn test_rename_lifetimes() { |
1545 | mark::check!(rename_lifetime); | ||
1525 | check( | 1546 | check( |
1526 | "'yeeee", | 1547 | "'yeeee", |
1527 | r#" | 1548 | r#" |
@@ -1606,4 +1627,24 @@ fn foo<'a>() -> &'a () { | |||
1606 | "#, | 1627 | "#, |
1607 | ) | 1628 | ) |
1608 | } | 1629 | } |
1630 | |||
1631 | #[test] | ||
1632 | fn test_self_to_self() { | ||
1633 | mark::check!(rename_self_to_self); | ||
1634 | check( | ||
1635 | "self", | ||
1636 | r#" | ||
1637 | struct Foo; | ||
1638 | impl Foo { | ||
1639 | fn foo(self$0) {} | ||
1640 | } | ||
1641 | "#, | ||
1642 | r#" | ||
1643 | struct Foo; | ||
1644 | impl Foo { | ||
1645 | fn foo(self) {} | ||
1646 | } | ||
1647 | "#, | ||
1648 | ) | ||
1649 | } | ||
1609 | } | 1650 | } |