aboutsummaryrefslogtreecommitdiff
path: root/crates
diff options
context:
space:
mode:
Diffstat (limited to 'crates')
-rw-r--r--crates/hir/src/lib.rs15
-rw-r--r--crates/ide/src/references/rename.rs81
2 files changed, 56 insertions, 40 deletions
diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs
index bdc1ad852..eb7865c84 100644
--- a/crates/hir/src/lib.rs
+++ b/crates/hir/src/lib.rs
@@ -973,6 +973,14 @@ impl SelfParam {
973 Access::Owned => "self", 973 Access::Owned => "self",
974 } 974 }
975 } 975 }
976
977 pub fn source(&self, db: &dyn HirDatabase) -> Option<InFile<ast::SelfParam>> {
978 let InFile { file_id, value } = Function::from(self.func).source(db)?;
979 value
980 .param_list()
981 .and_then(|params| params.self_param())
982 .map(|value| InFile { file_id, value })
983 }
976} 984}
977 985
978impl HasVisibility for Function { 986impl HasVisibility for Function {
@@ -1348,6 +1356,13 @@ impl Local {
1348 } 1356 }
1349 } 1357 }
1350 1358
1359 pub fn as_self_param(self, db: &dyn HirDatabase) -> Option<SelfParam> {
1360 match self.parent {
1361 DefWithBodyId::FunctionId(func) if self.is_self(db) => Some(SelfParam { func }),
1362 _ => None,
1363 }
1364 }
1365
1351 // FIXME: why is this an option? It shouldn't be? 1366 // FIXME: why is this an option? It shouldn't be?
1352 pub fn name(self, db: &dyn HirDatabase) -> Option<Name> { 1367 pub fn name(self, db: &dyn HirDatabase) -> Option<Name> {
1353 let body = db.body(self.parent); 1368 let body = db.body(self.parent);
diff --git a/crates/ide/src/references/rename.rs b/crates/ide/src/references/rename.rs
index b1ca6d50f..26d6dc9c9 100644
--- a/crates/ide/src/references/rename.rs
+++ b/crates/ide/src/references/rename.rs
@@ -219,40 +219,44 @@ fn rename_reference(
219) -> RenameResult<SourceChange> { 219) -> RenameResult<SourceChange> {
220 let ident_kind = check_identifier(new_name)?; 220 let ident_kind = check_identifier(new_name)?;
221 221
222 let def_is_lbl_or_lt = matches!( 222 if matches!(
223 def, 223 def, // is target a lifetime?
224 Definition::GenericParam(hir::GenericParam::LifetimeParam(_)) | Definition::Label(_) 224 Definition::GenericParam(hir::GenericParam::LifetimeParam(_)) | Definition::Label(_)
225 ); 225 ) {
226 match (ident_kind, def) { 226 match ident_kind {
227 (IdentifierKind::ToSelf, _) 227 IdentifierKind::Ident | IdentifierKind::ToSelf | IdentifierKind::Underscore => {
228 | (IdentifierKind::Underscore, _) 228 cov_mark::hit!(rename_not_a_lifetime_ident_ref);
229 | (IdentifierKind::Ident, _) 229 bail!("Invalid name `{}`: not a lifetime identifier", new_name);
230 if def_is_lbl_or_lt => 230 }
231 { 231 IdentifierKind::Lifetime => cov_mark::hit!(rename_lifetime),
232 cov_mark::hit!(rename_not_a_lifetime_ident_ref);
233 bail!("Invalid name `{}`: not a lifetime identifier", new_name)
234 }
235 (IdentifierKind::Lifetime, _) if def_is_lbl_or_lt => cov_mark::hit!(rename_lifetime),
236 (IdentifierKind::Lifetime, _) => {
237 cov_mark::hit!(rename_not_an_ident_ref);
238 bail!("Invalid name `{}`: not an identifier", new_name)
239 }
240 (IdentifierKind::ToSelf, Definition::Local(local)) if local.is_self(sema.db) => {
241 // no-op
242 cov_mark::hit!(rename_self_to_self);
243 return Ok(SourceChange::default());
244 }
245 (ident_kind, Definition::Local(local)) if local.is_self(sema.db) => {
246 cov_mark::hit!(rename_self_to_param);
247 return rename_self_to_param(sema, local, new_name, ident_kind);
248 }
249 (IdentifierKind::ToSelf, Definition::Local(local)) => {
250 cov_mark::hit!(rename_to_self);
251 return rename_to_self(sema, local);
252 } 232 }
253 (IdentifierKind::ToSelf, _) => bail!("Invalid name `{}`: not an identifier", new_name), 233 } else {
254 (IdentifierKind::Ident, _) | (IdentifierKind::Underscore, _) => { 234 match (ident_kind, def) {
255 cov_mark::hit!(rename_ident) 235 (IdentifierKind::Lifetime, _) => {
236 cov_mark::hit!(rename_not_an_ident_ref);
237 bail!("Invalid name `{}`: not an identifier", new_name);
238 }
239 (IdentifierKind::ToSelf, Definition::Local(local)) => {
240 if local.is_self(sema.db) {
241 // no-op
242 cov_mark::hit!(rename_self_to_self);
243 return Ok(SourceChange::default());
244 } else {
245 cov_mark::hit!(rename_to_self);
246 return rename_to_self(sema, local);
247 }
248 }
249 (ident_kind, Definition::Local(local)) => {
250 if let Some(self_param) = local.as_self_param(sema.db) {
251 cov_mark::hit!(rename_self_to_param);
252 return rename_self_to_param(sema, local, self_param, new_name, ident_kind);
253 } else {
254 cov_mark::hit!(rename_local);
255 }
256 }
257 (IdentifierKind::ToSelf, _) => bail!("Invalid name `{}`: not an identifier", new_name),
258 (IdentifierKind::Ident, _) => cov_mark::hit!(rename_non_local),
259 (IdentifierKind::Underscore, _) => (),
256 } 260 }
257 } 261 }
258 262
@@ -336,16 +340,12 @@ fn rename_to_self(sema: &Semantics<RootDatabase>, local: hir::Local) -> RenameRe
336fn rename_self_to_param( 340fn rename_self_to_param(
337 sema: &Semantics<RootDatabase>, 341 sema: &Semantics<RootDatabase>,
338 local: hir::Local, 342 local: hir::Local,
343 self_param: hir::SelfParam,
339 new_name: &str, 344 new_name: &str,
340 identifier_kind: IdentifierKind, 345 identifier_kind: IdentifierKind,
341) -> RenameResult<SourceChange> { 346) -> RenameResult<SourceChange> {
342 let (file_id, self_param) = match local.source(sema.db) { 347 let InFile { file_id, value: self_param } =
343 InFile { file_id, value: Either::Right(self_param) } => (file_id, self_param), 348 self_param.source(sema.db).ok_or_else(|| format_err!("cannot find function source"))?;
344 _ => {
345 never!(true, "rename_self_to_param invoked on a non-self local");
346 bail!("rename_self_to_param invoked on a non-self local");
347 }
348 };
349 349
350 let def = Definition::Local(local); 350 let def = Definition::Local(local);
351 let usages = def.usages(sema).all(); 351 let usages = def.usages(sema).all();
@@ -701,7 +701,7 @@ foo!(Foo$0);",
701 701
702 #[test] 702 #[test]
703 fn test_rename_for_local() { 703 fn test_rename_for_local() {
704 cov_mark::check!(rename_ident); 704 cov_mark::check!(rename_local);
705 check( 705 check(
706 "k", 706 "k",
707 r#" 707 r#"
@@ -1242,6 +1242,7 @@ pub mod foo$0;
1242 1242
1243 #[test] 1243 #[test]
1244 fn test_enum_variant_from_module_1() { 1244 fn test_enum_variant_from_module_1() {
1245 cov_mark::check!(rename_non_local);
1245 check( 1246 check(
1246 "Baz", 1247 "Baz",
1247 r#" 1248 r#"