about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2023-01-25 13:57:29 +0000
committerbors <bors@rust-lang.org>2023-01-25 13:57:29 +0000
commit46084a1e71c7e8733eb51c62699b565f96795fd5 (patch)
treea8a9cec0b064294df4852a942f0e96e05043ce35
parent85736de3bcd5ecab337a022bcc43014917296388 (diff)
parent3c898dd9a10350a53bdfe94eb5ffb848addeb762 (diff)
downloadrust-46084a1e71c7e8733eb51c62699b565f96795fd5.tar.gz
rust-46084a1e71c7e8733eb51c62699b565f96795fd5.zip
Auto merge of #14015 - vasilev-alex:lifetime-rename, r=Veykril
Don't include lifetime or label apostrophe when renaming

Closes #13907
-rw-r--r--crates/ide-db/src/rename.rs28
-rw-r--r--crates/ide/src/rename.rs47
2 files changed, 61 insertions, 14 deletions
diff --git a/crates/ide-db/src/rename.rs b/crates/ide-db/src/rename.rs
index 0e5906097c3..6da650aeb6b 100644
--- a/crates/ide-db/src/rename.rs
+++ b/crates/ide-db/src/rename.rs
@@ -263,11 +263,10 @@ fn rename_reference(
         Definition::GenericParam(hir::GenericParam::LifetimeParam(_)) | Definition::Label(_)
     ) {
         match ident_kind {
-            IdentifierKind::Ident | IdentifierKind::Underscore => {
-                cov_mark::hit!(rename_not_a_lifetime_ident_ref);
+            IdentifierKind::Underscore => {
                 bail!("Invalid name `{}`: not a lifetime identifier", new_name);
             }
-            IdentifierKind::Lifetime => cov_mark::hit!(rename_lifetime),
+            _ => cov_mark::hit!(rename_lifetime),
         }
     } else {
         match ident_kind {
@@ -335,7 +334,15 @@ pub fn source_edit_from_references(
             _ => false,
         };
         if !has_emitted_edit && !edited_ranges.contains(&range.start()) {
-            edit.replace(range, new_name.to_string());
+            let (range, new_name) = match name {
+                ast::NameLike::Lifetime(_) => (
+                    TextRange::new(range.start() + syntax::TextSize::from(1), range.end()),
+                    new_name.strip_prefix('\'').unwrap_or(new_name).to_owned(),
+                ),
+                _ => (range, new_name.to_owned()),
+            };
+
+            edit.replace(range, new_name);
             edited_ranges.push(range.start());
         }
     }
@@ -501,7 +508,15 @@ fn source_edit_from_def(
         }
     }
     if edit.is_empty() {
-        edit.replace(range, new_name.to_string());
+        let (range, new_name) = match def {
+            Definition::GenericParam(hir::GenericParam::LifetimeParam(_))
+            | Definition::Label(_) => (
+                TextRange::new(range.start() + syntax::TextSize::from(1), range.end()),
+                new_name.strip_prefix('\'').unwrap_or(new_name).to_owned(),
+            ),
+            _ => (range, new_name.to_owned()),
+        };
+        edit.replace(range, new_name);
     }
     Ok((file_id, edit.finish()))
 }
@@ -522,9 +537,6 @@ impl IdentifierKind {
                 (SyntaxKind::LIFETIME_IDENT, _) if new_name != "'static" && new_name != "'_" => {
                     Ok(IdentifierKind::Lifetime)
                 }
-                (SyntaxKind::LIFETIME_IDENT, _) => {
-                    bail!("Invalid name `{}`: not a lifetime identifier", new_name)
-                }
                 (_, Some(syntax_error)) => bail!("Invalid name `{}`: {}", new_name, syntax_error),
                 (_, None) => bail!("Invalid name `{}`: not an identifier", new_name),
             },
diff --git a/crates/ide/src/rename.rs b/crates/ide/src/rename.rs
index 15bdf14fb9b..25d165d1113 100644
--- a/crates/ide/src/rename.rs
+++ b/crates/ide/src/rename.rs
@@ -13,7 +13,7 @@ use ide_db::{
 };
 use itertools::Itertools;
 use stdx::{always, never};
-use syntax::{ast, AstNode, SyntaxNode};
+use syntax::{ast, AstNode, SyntaxNode, TextRange, TextSize};
 
 use text_edit::TextEdit;
 
@@ -48,7 +48,13 @@ pub(crate) fn prepare_rename(
                 frange.range.contains_inclusive(position.offset)
                     && frange.file_id == position.file_id
             );
-            Ok(frange.range)
+
+            Ok(match name_like {
+                ast::NameLike::Lifetime(_) => {
+                    TextRange::new(frange.range.start() + TextSize::from(1), frange.range.end())
+                }
+                _ => frange.range,
+            })
         })
         .reduce(|acc, cur| match (acc, cur) {
             // ensure all ranges are the same
@@ -407,7 +413,7 @@ mod tests {
     #[test]
     fn test_prepare_rename_namelikes() {
         check_prepare(r"fn name$0<'lifetime>() {}", expect![[r#"3..7: name"#]]);
-        check_prepare(r"fn name<'lifetime$0>() {}", expect![[r#"8..17: 'lifetime"#]]);
+        check_prepare(r"fn name<'lifetime$0>() {}", expect![[r#"9..17: lifetime"#]]);
         check_prepare(r"fn name<'lifetime>() { name$0(); }", expect![[r#"23..27: name"#]]);
     }
 
@@ -521,15 +527,19 @@ impl Foo {
 
     #[test]
     fn test_rename_to_invalid_identifier_lifetime2() {
-        cov_mark::check!(rename_not_a_lifetime_ident_ref);
         check(
-            "foo",
+            "_",
             r#"fn main<'a>(_: &'a$0 ()) {}"#,
-            "error: Invalid name `foo`: not a lifetime identifier",
+            r#"error: Invalid name `_`: not a lifetime identifier"#,
         );
     }
 
     #[test]
+    fn test_rename_accepts_lifetime_without_apostrophe() {
+        check("foo", r#"fn main<'a>(_: &'a$0 ()) {}"#, r#"fn main<'foo>(_: &'foo ()) {}"#);
+    }
+
+    #[test]
     fn test_rename_to_underscore_invalid() {
         cov_mark::check!(rename_underscore_multiple);
         check(
@@ -1832,6 +1842,31 @@ fn foo<'a>() -> &'a () {
     }
 
     #[test]
+    fn test_rename_label_new_name_without_apostrophe() {
+        check(
+            "foo",
+            r#"
+fn main() {
+    'outer$0: loop {
+        'inner: loop {
+            break 'outer;
+        }
+    }
+}
+        "#,
+            r#"
+fn main() {
+    'foo: loop {
+        'inner: loop {
+            break 'foo;
+        }
+    }
+}
+        "#,
+        );
+    }
+
+    #[test]
     fn test_self_to_self() {
         cov_mark::check!(rename_self_to_self);
         check(