aboutsummaryrefslogtreecommitdiff
path: root/crates/ide/src/references
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ide/src/references')
-rw-r--r--crates/ide/src/references/rename.rs69
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
37impl Error for RenameError {} 37impl Error for RenameError {}
38 38
39macro_rules! format_err {
40 ($fmt:expr) => {RenameError(format!($fmt))};
41 ($fmt:expr, $($arg:tt)+) => {RenameError(format!($fmt, $($arg)+))}
42}
43
44macro_rules! bail {
45 ($($tokens:tt)*) => {return Err(format_err!($($tokens)*))}
46}
47
39pub(crate) fn prepare_rename( 48pub(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
134fn find_module_at_offset( 140fn 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
170fn source_edit_from_reference( 176fn 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 }