aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--crates/ide/src/references/rename.rs75
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::{
14use syntax::{ 14use 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};
19use test_utils::mark; 19use test_utils::mark;
20use text_edit::TextEdit; 20use 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)]
114enum IdentifierKind { 114enum 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#"
1637struct Foo;
1638impl Foo {
1639 fn foo(self$0) {}
1640}
1641"#,
1642 r#"
1643struct Foo;
1644impl Foo {
1645 fn foo(self) {}
1646}
1647"#,
1648 )
1649 }
1609} 1650}