Skip to content

Commit 46084a1

Browse files
committed
Auto merge of rust-lang#14015 - vasilev-alex:lifetime-rename, r=Veykril
Don't include lifetime or label apostrophe when renaming Closes rust-lang#13907
2 parents 85736de + 3c898dd commit 46084a1

File tree

2 files changed

+61
-14
lines changed

2 files changed

+61
-14
lines changed

crates/ide-db/src/rename.rs

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -263,11 +263,10 @@ fn rename_reference(
263263
Definition::GenericParam(hir::GenericParam::LifetimeParam(_)) | Definition::Label(_)
264264
) {
265265
match ident_kind {
266-
IdentifierKind::Ident | IdentifierKind::Underscore => {
267-
cov_mark::hit!(rename_not_a_lifetime_ident_ref);
266+
IdentifierKind::Underscore => {
268267
bail!("Invalid name `{}`: not a lifetime identifier", new_name);
269268
}
270-
IdentifierKind::Lifetime => cov_mark::hit!(rename_lifetime),
269+
_ => cov_mark::hit!(rename_lifetime),
271270
}
272271
} else {
273272
match ident_kind {
@@ -335,7 +334,15 @@ pub fn source_edit_from_references(
335334
_ => false,
336335
};
337336
if !has_emitted_edit && !edited_ranges.contains(&range.start()) {
338-
edit.replace(range, new_name.to_string());
337+
let (range, new_name) = match name {
338+
ast::NameLike::Lifetime(_) => (
339+
TextRange::new(range.start() + syntax::TextSize::from(1), range.end()),
340+
new_name.strip_prefix('\'').unwrap_or(new_name).to_owned(),
341+
),
342+
_ => (range, new_name.to_owned()),
343+
};
344+
345+
edit.replace(range, new_name);
339346
edited_ranges.push(range.start());
340347
}
341348
}
@@ -501,7 +508,15 @@ fn source_edit_from_def(
501508
}
502509
}
503510
if edit.is_empty() {
504-
edit.replace(range, new_name.to_string());
511+
let (range, new_name) = match def {
512+
Definition::GenericParam(hir::GenericParam::LifetimeParam(_))
513+
| Definition::Label(_) => (
514+
TextRange::new(range.start() + syntax::TextSize::from(1), range.end()),
515+
new_name.strip_prefix('\'').unwrap_or(new_name).to_owned(),
516+
),
517+
_ => (range, new_name.to_owned()),
518+
};
519+
edit.replace(range, new_name);
505520
}
506521
Ok((file_id, edit.finish()))
507522
}
@@ -522,9 +537,6 @@ impl IdentifierKind {
522537
(SyntaxKind::LIFETIME_IDENT, _) if new_name != "'static" && new_name != "'_" => {
523538
Ok(IdentifierKind::Lifetime)
524539
}
525-
(SyntaxKind::LIFETIME_IDENT, _) => {
526-
bail!("Invalid name `{}`: not a lifetime identifier", new_name)
527-
}
528540
(_, Some(syntax_error)) => bail!("Invalid name `{}`: {}", new_name, syntax_error),
529541
(_, None) => bail!("Invalid name `{}`: not an identifier", new_name),
530542
},

crates/ide/src/rename.rs

Lines changed: 41 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ use ide_db::{
1313
};
1414
use itertools::Itertools;
1515
use stdx::{always, never};
16-
use syntax::{ast, AstNode, SyntaxNode};
16+
use syntax::{ast, AstNode, SyntaxNode, TextRange, TextSize};
1717

1818
use text_edit::TextEdit;
1919

@@ -48,7 +48,13 @@ pub(crate) fn prepare_rename(
4848
frange.range.contains_inclusive(position.offset)
4949
&& frange.file_id == position.file_id
5050
);
51-
Ok(frange.range)
51+
52+
Ok(match name_like {
53+
ast::NameLike::Lifetime(_) => {
54+
TextRange::new(frange.range.start() + TextSize::from(1), frange.range.end())
55+
}
56+
_ => frange.range,
57+
})
5258
})
5359
.reduce(|acc, cur| match (acc, cur) {
5460
// ensure all ranges are the same
@@ -407,7 +413,7 @@ mod tests {
407413
#[test]
408414
fn test_prepare_rename_namelikes() {
409415
check_prepare(r"fn name$0<'lifetime>() {}", expect![[r#"3..7: name"#]]);
410-
check_prepare(r"fn name<'lifetime$0>() {}", expect![[r#"8..17: 'lifetime"#]]);
416+
check_prepare(r"fn name<'lifetime$0>() {}", expect![[r#"9..17: lifetime"#]]);
411417
check_prepare(r"fn name<'lifetime>() { name$0(); }", expect![[r#"23..27: name"#]]);
412418
}
413419

@@ -521,14 +527,18 @@ impl Foo {
521527

522528
#[test]
523529
fn test_rename_to_invalid_identifier_lifetime2() {
524-
cov_mark::check!(rename_not_a_lifetime_ident_ref);
525530
check(
526-
"foo",
531+
"_",
527532
r#"fn main<'a>(_: &'a$0 ()) {}"#,
528-
"error: Invalid name `foo`: not a lifetime identifier",
533+
r#"error: Invalid name `_`: not a lifetime identifier"#,
529534
);
530535
}
531536

537+
#[test]
538+
fn test_rename_accepts_lifetime_without_apostrophe() {
539+
check("foo", r#"fn main<'a>(_: &'a$0 ()) {}"#, r#"fn main<'foo>(_: &'foo ()) {}"#);
540+
}
541+
532542
#[test]
533543
fn test_rename_to_underscore_invalid() {
534544
cov_mark::check!(rename_underscore_multiple);
@@ -1831,6 +1841,31 @@ fn foo<'a>() -> &'a () {
18311841
)
18321842
}
18331843

1844+
#[test]
1845+
fn test_rename_label_new_name_without_apostrophe() {
1846+
check(
1847+
"foo",
1848+
r#"
1849+
fn main() {
1850+
'outer$0: loop {
1851+
'inner: loop {
1852+
break 'outer;
1853+
}
1854+
}
1855+
}
1856+
"#,
1857+
r#"
1858+
fn main() {
1859+
'foo: loop {
1860+
'inner: loop {
1861+
break 'foo;
1862+
}
1863+
}
1864+
}
1865+
"#,
1866+
);
1867+
}
1868+
18341869
#[test]
18351870
fn test_self_to_self() {
18361871
cov_mark::check!(rename_self_to_self);

0 commit comments

Comments
 (0)