diff options
Diffstat (limited to 'crates')
-rw-r--r-- | crates/hir/src/lib.rs | 15 | ||||
-rw-r--r-- | crates/ide/src/references/rename.rs | 81 |
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 | ||
978 | impl HasVisibility for Function { | 986 | impl 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 | |||
336 | fn rename_self_to_param( | 340 | fn 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#" |