diff options
Diffstat (limited to 'crates/ide')
-rw-r--r-- | crates/ide/src/references/rename.rs | 81 |
1 files changed, 40 insertions, 41 deletions
diff --git a/crates/ide/src/references/rename.rs b/crates/ide/src/references/rename.rs index e1ed6de35..6b3d02bf4 100644 --- a/crates/ide/src/references/rename.rs +++ b/crates/ide/src/references/rename.rs | |||
@@ -86,6 +86,18 @@ pub(crate) fn rename_with_semantics( | |||
86 | let syntax = source_file.syntax(); | 86 | let syntax = source_file.syntax(); |
87 | 87 | ||
88 | let def = find_definition(sema, syntax, position)?; | 88 | let def = find_definition(sema, syntax, position)?; |
89 | |||
90 | if let Definition::Local(local) = def { | ||
91 | if let Some(self_param) = local.as_self_param(sema.db) { | ||
92 | cov_mark::hit!(rename_self_to_param); | ||
93 | return rename_self_to_param(sema, local, self_param, new_name); | ||
94 | } | ||
95 | if new_name == "self" { | ||
96 | cov_mark::hit!(rename_to_self); | ||
97 | return rename_to_self(sema, local); | ||
98 | } | ||
99 | } | ||
100 | |||
89 | match def { | 101 | match def { |
90 | Definition::ModuleDef(hir::ModuleDef::Module(module)) => rename_mod(sema, module, new_name), | 102 | Definition::ModuleDef(hir::ModuleDef::Module(module)) => rename_mod(sema, module, new_name), |
91 | Definition::SelfType(_) => bail!("Cannot rename `Self`"), | 103 | Definition::SelfType(_) => bail!("Cannot rename `Self`"), |
@@ -113,26 +125,26 @@ pub(crate) fn will_rename_file( | |||
113 | enum IdentifierKind { | 125 | enum IdentifierKind { |
114 | Ident, | 126 | Ident, |
115 | Lifetime, | 127 | Lifetime, |
116 | ToSelf, | ||
117 | Underscore, | 128 | Underscore, |
118 | } | 129 | } |
119 | 130 | ||
120 | fn check_identifier(new_name: &str) -> RenameResult<IdentifierKind> { | 131 | impl IdentifierKind { |
121 | match lex_single_syntax_kind(new_name) { | 132 | fn classify(new_name: &str) -> RenameResult<IdentifierKind> { |
122 | Some(res) => match res { | 133 | match lex_single_syntax_kind(new_name) { |
123 | (SyntaxKind::IDENT, _) => Ok(IdentifierKind::Ident), | 134 | Some(res) => match res { |
124 | (T![_], _) => Ok(IdentifierKind::Underscore), | 135 | (SyntaxKind::IDENT, _) => Ok(IdentifierKind::Ident), |
125 | (T![self], _) => Ok(IdentifierKind::ToSelf), | 136 | (T![_], _) => Ok(IdentifierKind::Underscore), |
126 | (SyntaxKind::LIFETIME_IDENT, _) if new_name != "'static" && new_name != "'_" => { | 137 | (SyntaxKind::LIFETIME_IDENT, _) if new_name != "'static" && new_name != "'_" => { |
127 | Ok(IdentifierKind::Lifetime) | 138 | Ok(IdentifierKind::Lifetime) |
128 | } | 139 | } |
129 | (SyntaxKind::LIFETIME_IDENT, _) => { | 140 | (SyntaxKind::LIFETIME_IDENT, _) => { |
130 | bail!("Invalid name `{}`: not a lifetime identifier", new_name) | 141 | bail!("Invalid name `{}`: not a lifetime identifier", new_name) |
131 | } | 142 | } |
132 | (_, Some(syntax_error)) => bail!("Invalid name `{}`: {}", new_name, syntax_error), | 143 | (_, Some(syntax_error)) => bail!("Invalid name `{}`: {}", new_name, syntax_error), |
133 | (_, None) => bail!("Invalid name `{}`: not an identifier", new_name), | 144 | (_, None) => bail!("Invalid name `{}`: not an identifier", new_name), |
134 | }, | 145 | }, |
135 | None => bail!("Invalid name `{}`: not an identifier", new_name), | 146 | None => bail!("Invalid name `{}`: not an identifier", new_name), |
147 | } | ||
136 | } | 148 | } |
137 | } | 149 | } |
138 | 150 | ||
@@ -182,7 +194,7 @@ fn rename_mod( | |||
182 | module: hir::Module, | 194 | module: hir::Module, |
183 | new_name: &str, | 195 | new_name: &str, |
184 | ) -> RenameResult<SourceChange> { | 196 | ) -> RenameResult<SourceChange> { |
185 | if IdentifierKind::Ident != check_identifier(new_name)? { | 197 | if IdentifierKind::classify(new_name)? != IdentifierKind::Ident { |
186 | bail!("Invalid name `{0}`: cannot rename module to {0}", new_name); | 198 | bail!("Invalid name `{0}`: cannot rename module to {0}", new_name); |
187 | } | 199 | } |
188 | 200 | ||
@@ -227,14 +239,14 @@ fn rename_reference( | |||
227 | mut def: Definition, | 239 | mut def: Definition, |
228 | new_name: &str, | 240 | new_name: &str, |
229 | ) -> RenameResult<SourceChange> { | 241 | ) -> RenameResult<SourceChange> { |
230 | let ident_kind = check_identifier(new_name)?; | 242 | let ident_kind = IdentifierKind::classify(new_name)?; |
231 | 243 | ||
232 | if matches!( | 244 | if matches!( |
233 | def, // is target a lifetime? | 245 | def, // is target a lifetime? |
234 | Definition::GenericParam(hir::GenericParam::LifetimeParam(_)) | Definition::Label(_) | 246 | Definition::GenericParam(hir::GenericParam::LifetimeParam(_)) | Definition::Label(_) |
235 | ) { | 247 | ) { |
236 | match ident_kind { | 248 | match ident_kind { |
237 | IdentifierKind::Ident | IdentifierKind::ToSelf | IdentifierKind::Underscore => { | 249 | IdentifierKind::Ident | IdentifierKind::Underscore => { |
238 | cov_mark::hit!(rename_not_a_lifetime_ident_ref); | 250 | cov_mark::hit!(rename_not_a_lifetime_ident_ref); |
239 | bail!("Invalid name `{}`: not a lifetime identifier", new_name); | 251 | bail!("Invalid name `{}`: not a lifetime identifier", new_name); |
240 | } | 252 | } |
@@ -246,25 +258,6 @@ fn rename_reference( | |||
246 | cov_mark::hit!(rename_not_an_ident_ref); | 258 | cov_mark::hit!(rename_not_an_ident_ref); |
247 | bail!("Invalid name `{}`: not an identifier", new_name); | 259 | bail!("Invalid name `{}`: not an identifier", new_name); |
248 | } | 260 | } |
249 | (IdentifierKind::ToSelf, Definition::Local(local)) => { | ||
250 | if local.is_self(sema.db) { | ||
251 | // no-op | ||
252 | cov_mark::hit!(rename_self_to_self); | ||
253 | return Ok(SourceChange::default()); | ||
254 | } else { | ||
255 | cov_mark::hit!(rename_to_self); | ||
256 | return rename_to_self(sema, local); | ||
257 | } | ||
258 | } | ||
259 | (ident_kind, Definition::Local(local)) => { | ||
260 | if let Some(self_param) = local.as_self_param(sema.db) { | ||
261 | cov_mark::hit!(rename_self_to_param); | ||
262 | return rename_self_to_param(sema, local, self_param, new_name, ident_kind); | ||
263 | } else { | ||
264 | cov_mark::hit!(rename_local); | ||
265 | } | ||
266 | } | ||
267 | (IdentifierKind::ToSelf, _) => bail!("Invalid name `{}`: not an identifier", new_name), | ||
268 | (IdentifierKind::Ident, _) => cov_mark::hit!(rename_non_local), | 261 | (IdentifierKind::Ident, _) => cov_mark::hit!(rename_non_local), |
269 | (IdentifierKind::Underscore, _) => (), | 262 | (IdentifierKind::Underscore, _) => (), |
270 | } | 263 | } |
@@ -383,8 +376,15 @@ fn rename_self_to_param( | |||
383 | local: hir::Local, | 376 | local: hir::Local, |
384 | self_param: hir::SelfParam, | 377 | self_param: hir::SelfParam, |
385 | new_name: &str, | 378 | new_name: &str, |
386 | identifier_kind: IdentifierKind, | ||
387 | ) -> RenameResult<SourceChange> { | 379 | ) -> RenameResult<SourceChange> { |
380 | if new_name == "self" { | ||
381 | // Let's do nothing rather than complain. | ||
382 | cov_mark::hit!(rename_self_to_self); | ||
383 | return Ok(SourceChange::default()); | ||
384 | } | ||
385 | |||
386 | let identifier_kind = IdentifierKind::classify(new_name)?; | ||
387 | |||
388 | let InFile { file_id, value: self_param } = | 388 | let InFile { file_id, value: self_param } = |
389 | self_param.source(sema.db).ok_or_else(|| format_err!("cannot find function source"))?; | 389 | self_param.source(sema.db).ok_or_else(|| format_err!("cannot find function source"))?; |
390 | 390 | ||
@@ -879,7 +879,6 @@ impl Foo { | |||
879 | 879 | ||
880 | #[test] | 880 | #[test] |
881 | fn test_rename_for_local() { | 881 | fn test_rename_for_local() { |
882 | cov_mark::check!(rename_local); | ||
883 | check( | 882 | check( |
884 | "k", | 883 | "k", |
885 | r#" | 884 | r#" |