diff options
Diffstat (limited to 'crates/ide/src/references')
-rw-r--r-- | crates/ide/src/references/rename.rs | 69 |
1 files changed, 30 insertions, 39 deletions
diff --git a/crates/ide/src/references/rename.rs b/crates/ide/src/references/rename.rs index dd322631b..6040fc1f8 100644 --- a/crates/ide/src/references/rename.rs +++ b/crates/ide/src/references/rename.rs | |||
@@ -36,6 +36,15 @@ impl fmt::Display for RenameError { | |||
36 | 36 | ||
37 | impl Error for RenameError {} | 37 | impl Error for RenameError {} |
38 | 38 | ||
39 | macro_rules! format_err { | ||
40 | ($fmt:expr) => {RenameError(format!($fmt))}; | ||
41 | ($fmt:expr, $($arg:tt)+) => {RenameError(format!($fmt, $($arg)+))} | ||
42 | } | ||
43 | |||
44 | macro_rules! bail { | ||
45 | ($($tokens:tt)*) => {return Err(format_err!($($tokens)*))} | ||
46 | } | ||
47 | |||
39 | pub(crate) fn prepare_rename( | 48 | pub(crate) fn prepare_rename( |
40 | db: &RootDatabase, | 49 | db: &RootDatabase, |
41 | position: FilePosition, | 50 | position: FilePosition, |
@@ -119,16 +128,13 @@ fn check_identifier(new_name: &str) -> RenameResult<IdentifierKind> { | |||
119 | Ok(IdentifierKind::Lifetime) | 128 | Ok(IdentifierKind::Lifetime) |
120 | } | 129 | } |
121 | (SyntaxKind::LIFETIME_IDENT, _) => { | 130 | (SyntaxKind::LIFETIME_IDENT, _) => { |
122 | Err(format!("Invalid name `{0}`: Cannot rename lifetime to {0}", new_name)) | 131 | bail!("Invalid name `{0}`: Cannot rename lifetime to {0}", new_name) |
123 | } | 132 | } |
124 | (_, Some(syntax_error)) => { | 133 | (_, Some(syntax_error)) => bail!("Invalid name `{}`: {}", new_name, syntax_error), |
125 | Err(format!("Invalid name `{}`: {}", new_name, syntax_error)) | 134 | (_, None) => bail!("Invalid name `{}`: not an identifier", new_name), |
126 | } | ||
127 | (_, None) => Err(format!("Invalid name `{}`: not an identifier", new_name)), | ||
128 | }, | 135 | }, |
129 | None => Err(format!("Invalid name `{}`: not an identifier", new_name)), | 136 | None => bail!("Invalid name `{}`: not an identifier", new_name), |
130 | } | 137 | } |
131 | .map_err(RenameError) | ||
132 | } | 138 | } |
133 | 139 | ||
134 | fn find_module_at_offset( | 140 | fn find_module_at_offset( |
@@ -164,7 +170,7 @@ fn find_all_refs( | |||
164 | position: FilePosition, | 170 | position: FilePosition, |
165 | ) -> RenameResult<RangeInfo<ReferenceSearchResult>> { | 171 | ) -> RenameResult<RangeInfo<ReferenceSearchResult>> { |
166 | crate::references::find_all_refs(sema, position, None) | 172 | crate::references::find_all_refs(sema, position, None) |
167 | .ok_or_else(|| RenameError("No references found at position".to_string())) | 173 | .ok_or_else(|| format_err!("No references found at position")) |
168 | } | 174 | } |
169 | 175 | ||
170 | fn source_edit_from_reference( | 176 | fn source_edit_from_reference( |
@@ -237,10 +243,7 @@ fn rename_mod( | |||
237 | new_name: &str, | 243 | new_name: &str, |
238 | ) -> RenameResult<RangeInfo<SourceChange>> { | 244 | ) -> RenameResult<RangeInfo<SourceChange>> { |
239 | if IdentifierKind::Ident != check_identifier(new_name)? { | 245 | if IdentifierKind::Ident != check_identifier(new_name)? { |
240 | return Err(RenameError(format!( | 246 | bail!("Invalid name `{0}`: cannot rename module to {0}", new_name); |
241 | "Invalid name `{0}`: cannot rename module to {0}", | ||
242 | new_name | ||
243 | ))); | ||
244 | } | 247 | } |
245 | let mut source_file_edits = Vec::new(); | 248 | let mut source_file_edits = Vec::new(); |
246 | let mut file_system_edits = Vec::new(); | 249 | let mut file_system_edits = Vec::new(); |
@@ -291,27 +294,26 @@ fn rename_to_self( | |||
291 | 294 | ||
292 | let (fn_def, fn_ast) = find_node_at_offset::<ast::Fn>(syn, position.offset) | 295 | let (fn_def, fn_ast) = find_node_at_offset::<ast::Fn>(syn, position.offset) |
293 | .and_then(|fn_ast| sema.to_def(&fn_ast).zip(Some(fn_ast))) | 296 | .and_then(|fn_ast| sema.to_def(&fn_ast).zip(Some(fn_ast))) |
294 | .ok_or_else(|| RenameError("No surrounding method declaration found".to_string()))?; | 297 | .ok_or_else(|| format_err!("No surrounding method declaration found"))?; |
295 | let param_range = fn_ast | 298 | let param_range = fn_ast |
296 | .param_list() | 299 | .param_list() |
297 | .and_then(|p| p.params().next()) | 300 | .and_then(|p| p.params().next()) |
298 | .ok_or_else(|| RenameError("Method has no parameters".to_string()))? | 301 | .ok_or_else(|| format_err!("Method has no parameters"))? |
299 | .syntax() | 302 | .syntax() |
300 | .text_range(); | 303 | .text_range(); |
301 | if !param_range.contains(position.offset) { | 304 | if !param_range.contains(position.offset) { |
302 | return Err(RenameError("Only the first parameter can be self".to_string())); | 305 | bail!("Only the first parameter can be self"); |
303 | } | 306 | } |
304 | 307 | ||
305 | let impl_block = find_node_at_offset::<ast::Impl>(syn, position.offset) | 308 | let impl_block = find_node_at_offset::<ast::Impl>(syn, position.offset) |
306 | .and_then(|def| sema.to_def(&def)) | 309 | .and_then(|def| sema.to_def(&def)) |
307 | .ok_or_else(|| RenameError("No impl block found for function".to_string()))?; | 310 | .ok_or_else(|| format_err!("No impl block found for function"))?; |
308 | if fn_def.self_param(sema.db).is_some() { | 311 | if fn_def.self_param(sema.db).is_some() { |
309 | return Err(RenameError("Method already has a self parameter".to_string())); | 312 | bail!("Method already has a self parameter"); |
310 | } | 313 | } |
311 | 314 | ||
312 | let params = fn_def.assoc_fn_params(sema.db); | 315 | let params = fn_def.assoc_fn_params(sema.db); |
313 | let first_param = | 316 | let first_param = params.first().ok_or_else(|| format_err!("Method has no parameters"))?; |
314 | params.first().ok_or_else(|| RenameError("Method has no parameters".into()))?; | ||
315 | let first_param_ty = first_param.ty(); | 317 | let first_param_ty = first_param.ty(); |
316 | let impl_ty = impl_block.target_ty(sema.db); | 318 | let impl_ty = impl_block.target_ty(sema.db); |
317 | let (ty, self_param) = if impl_ty.remove_ref().is_some() { | 319 | let (ty, self_param) = if impl_ty.remove_ref().is_some() { |
@@ -324,7 +326,7 @@ fn rename_to_self( | |||
324 | }; | 326 | }; |
325 | 327 | ||
326 | if ty != impl_ty { | 328 | if ty != impl_ty { |
327 | return Err(RenameError("Parameter type differs from impl block type".to_string())); | 329 | bail!("Parameter type differs from impl block type"); |
328 | } | 330 | } |
329 | 331 | ||
330 | let RangeInfo { range, info: refs } = find_all_refs(sema, position)?; | 332 | let RangeInfo { range, info: refs } = find_all_refs(sema, position)?; |
@@ -334,7 +336,7 @@ fn rename_to_self( | |||
334 | .partition(|reference| param_range.intersect(reference.file_range.range).is_some()); | 336 | .partition(|reference| param_range.intersect(reference.file_range.range).is_some()); |
335 | 337 | ||
336 | if param_ref.is_empty() { | 338 | if param_ref.is_empty() { |
337 | return Err(RenameError("Parameter to rename not found".to_string())); | 339 | bail!("Parameter to rename not found"); |
338 | } | 340 | } |
339 | 341 | ||
340 | let mut edits = usages | 342 | let mut edits = usages |
@@ -385,9 +387,7 @@ fn rename_self_to_param( | |||
385 | ) -> Result<RangeInfo<SourceChange>, RenameError> { | 387 | ) -> Result<RangeInfo<SourceChange>, RenameError> { |
386 | let ident_kind = check_identifier(new_name)?; | 388 | let ident_kind = check_identifier(new_name)?; |
387 | match ident_kind { | 389 | match ident_kind { |
388 | IdentifierKind::Lifetime => { | 390 | IdentifierKind::Lifetime => bail!("Invalid name `{}`: not an identifier", new_name), |
389 | return Err(RenameError(format!("Invalid name `{}`: not an identifier", new_name))) | ||
390 | } | ||
391 | IdentifierKind::ToSelf => { | 391 | IdentifierKind::ToSelf => { |
392 | // no-op | 392 | // no-op |
393 | return Ok(RangeInfo::new(self_token.text_range(), SourceChange::default())); | 393 | return Ok(RangeInfo::new(self_token.text_range(), SourceChange::default())); |
@@ -399,7 +399,7 @@ fn rename_self_to_param( | |||
399 | 399 | ||
400 | let text = sema.db.file_text(position.file_id); | 400 | let text = sema.db.file_text(position.file_id); |
401 | let fn_def = find_node_at_offset::<ast::Fn>(syn, position.offset) | 401 | let fn_def = find_node_at_offset::<ast::Fn>(syn, position.offset) |
402 | .ok_or_else(|| RenameError("No surrounding method declaration found".to_string()))?; | 402 | .ok_or_else(|| format_err!("No surrounding method declaration found"))?; |
403 | let search_range = fn_def.syntax().text_range(); | 403 | let search_range = fn_def.syntax().text_range(); |
404 | 404 | ||
405 | let mut edits: Vec<SourceFileEdit> = vec![]; | 405 | let mut edits: Vec<SourceFileEdit> = vec![]; |
@@ -414,7 +414,7 @@ fn rename_self_to_param( | |||
414 | { | 414 | { |
415 | let edit = if let Some(ref self_param) = ast::SelfParam::cast(usage.parent()) { | 415 | let edit = if let Some(ref self_param) = ast::SelfParam::cast(usage.parent()) { |
416 | text_edit_from_self_param(syn, self_param, new_name) | 416 | text_edit_from_self_param(syn, self_param, new_name) |
417 | .ok_or_else(|| RenameError("No target type found".to_string()))? | 417 | .ok_or_else(|| format_err!("No target type found"))? |
418 | } else { | 418 | } else { |
419 | TextEdit::replace(usage.text_range(), String::from(new_name)) | 419 | TextEdit::replace(usage.text_range(), String::from(new_name)) |
420 | }; | 420 | }; |
@@ -423,9 +423,7 @@ fn rename_self_to_param( | |||
423 | } | 423 | } |
424 | 424 | ||
425 | if edits.len() > 1 && ident_kind == IdentifierKind::Underscore { | 425 | if edits.len() > 1 && ident_kind == IdentifierKind::Underscore { |
426 | return Err(RenameError(format!( | 426 | bail!("Cannot rename reference to `_` as it is being referenced multiple times"); |
427 | "Cannot rename reference to `_` as it is being referenced multiple times", | ||
428 | ))); | ||
429 | } | 427 | } |
430 | 428 | ||
431 | let range = ast::SelfParam::cast(self_token.parent()) | 429 | let range = ast::SelfParam::cast(self_token.parent()) |
@@ -446,15 +444,10 @@ fn rename_reference( | |||
446 | (IdentifierKind::ToSelf, ReferenceKind::Lifetime) | 444 | (IdentifierKind::ToSelf, ReferenceKind::Lifetime) |
447 | | (IdentifierKind::Underscore, ReferenceKind::Lifetime) | 445 | | (IdentifierKind::Underscore, ReferenceKind::Lifetime) |
448 | | (IdentifierKind::Ident, ReferenceKind::Lifetime) => { | 446 | | (IdentifierKind::Ident, ReferenceKind::Lifetime) => { |
449 | return Err(RenameError(format!( | 447 | bail!("Invalid name `{}`: not a lifetime identifier", new_name) |
450 | "Invalid name `{}`: not a lifetime identifier", | ||
451 | new_name | ||
452 | ))) | ||
453 | } | 448 | } |
454 | (IdentifierKind::Lifetime, ReferenceKind::Lifetime) => (), | 449 | (IdentifierKind::Lifetime, ReferenceKind::Lifetime) => (), |
455 | (IdentifierKind::Lifetime, _) => { | 450 | (IdentifierKind::Lifetime, _) => bail!("Invalid name `{}`: not an identifier", new_name), |
456 | return Err(RenameError(format!("Invalid name `{}`: not an identifier", new_name))) | ||
457 | } | ||
458 | (IdentifierKind::ToSelf, ReferenceKind::SelfKw) => { | 451 | (IdentifierKind::ToSelf, ReferenceKind::SelfKw) => { |
459 | //no-op | 452 | //no-op |
460 | return Ok(RangeInfo::new(range, SourceChange::default())); | 453 | return Ok(RangeInfo::new(range, SourceChange::default())); |
@@ -463,9 +456,7 @@ fn rename_reference( | |||
463 | return rename_to_self(sema, position); | 456 | return rename_to_self(sema, position); |
464 | } | 457 | } |
465 | (IdentifierKind::Underscore, _) if !refs.references.is_empty() => { | 458 | (IdentifierKind::Underscore, _) if !refs.references.is_empty() => { |
466 | return Err(RenameError(format!( | 459 | bail!("Cannot rename reference to `_` as it is being referenced multiple times") |
467 | "Cannot rename reference to `_` as it is being referenced multiple times", | ||
468 | ))) | ||
469 | } | 460 | } |
470 | (IdentifierKind::Ident, _) | (IdentifierKind::Underscore, _) => (), | 461 | (IdentifierKind::Ident, _) | (IdentifierKind::Underscore, _) => (), |
471 | } | 462 | } |