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.rs433
1 files changed, 258 insertions, 175 deletions
diff --git a/crates/ide/src/references/rename.rs b/crates/ide/src/references/rename.rs
index 854bf194e..c3ae568c2 100644
--- a/crates/ide/src/references/rename.rs
+++ b/crates/ide/src/references/rename.rs
@@ -1,29 +1,30 @@
1//! FIXME: write short doc here 1//! FIXME: write short doc here
2use std::{ 2use std::{
3 convert::TryInto, 3 convert::TryInto,
4 error::Error,
5 fmt::{self, Display}, 4 fmt::{self, Display},
6}; 5};
7 6
8use hir::{Module, ModuleDef, ModuleSource, Semantics}; 7use hir::{Module, ModuleDef, ModuleSource, Semantics};
9use ide_db::base_db::{AnchoredPathBuf, FileId, FileRange, SourceDatabaseExt};
10use ide_db::{ 8use ide_db::{
9 base_db::{AnchoredPathBuf, FileId, FileRange, SourceDatabaseExt},
11 defs::{Definition, NameClass, NameRefClass}, 10 defs::{Definition, NameClass, NameRefClass},
11 search::FileReference,
12 RootDatabase, 12 RootDatabase,
13}; 13};
14use syntax::{ 14use syntax::{
15 algo::find_node_at_offset, 15 algo::find_node_at_offset,
16 ast::{self, NameOwner}, 16 ast::{self, NameOwner},
17 lex_single_syntax_kind, match_ast, AstNode, SyntaxKind, SyntaxNode, SyntaxToken, 17 lex_single_syntax_kind, match_ast, AstNode, SyntaxKind, SyntaxNode, SyntaxToken, T,
18}; 18};
19use test_utils::mark; 19use test_utils::mark;
20use text_edit::TextEdit; 20use text_edit::TextEdit;
21 21
22use crate::{ 22use crate::{
23 references::find_all_refs, FilePosition, FileSystemEdit, RangeInfo, Reference, ReferenceKind, 23 FilePosition, FileSystemEdit, RangeInfo, ReferenceKind, ReferenceSearchResult, SourceChange,
24 SourceChange, SourceFileEdit, TextRange, TextSize, 24 SourceFileEdit, TextRange, TextSize,
25}; 25};
26 26
27type RenameResult<T> = Result<T, RenameError>;
27#[derive(Debug)] 28#[derive(Debug)]
28pub struct RenameError(pub(crate) String); 29pub struct RenameError(pub(crate) String);
29 30
@@ -33,26 +34,30 @@ impl fmt::Display for RenameError {
33 } 34 }
34} 35}
35 36
36impl Error for RenameError {} 37macro_rules! format_err {
38 ($fmt:expr) => {RenameError(format!($fmt))};
39 ($fmt:expr, $($arg:tt)+) => {RenameError(format!($fmt, $($arg)+))}
40}
41
42macro_rules! bail {
43 ($($tokens:tt)*) => {return Err(format_err!($($tokens)*))}
44}
37 45
38pub(crate) fn prepare_rename( 46pub(crate) fn prepare_rename(
39 db: &RootDatabase, 47 db: &RootDatabase,
40 position: FilePosition, 48 position: FilePosition,
41) -> Result<RangeInfo<()>, RenameError> { 49) -> RenameResult<RangeInfo<()>> {
42 let sema = Semantics::new(db); 50 let sema = Semantics::new(db);
43 let source_file = sema.parse(position.file_id); 51 let source_file = sema.parse(position.file_id);
44 let syntax = source_file.syntax(); 52 let syntax = source_file.syntax();
45 if let Some(module) = find_module_at_offset(&sema, position, syntax) { 53 if let Some(module) = find_module_at_offset(&sema, position, syntax) {
46 rename_mod(&sema, position, module, "dummy") 54 rename_mod(&sema, position, module, "dummy")
47 } else if let Some(self_token) = 55 } else if let Some(self_token) =
48 syntax.token_at_offset(position.offset).find(|t| t.kind() == SyntaxKind::SELF_KW) 56 syntax.token_at_offset(position.offset).find(|t| t.kind() == T![self])
49 { 57 {
50 rename_self_to_param(&sema, position, self_token, "dummy") 58 rename_self_to_param(&sema, position, self_token, "dummy")
51 } else { 59 } else {
52 let range = match find_all_refs(&sema, position, None) { 60 let RangeInfo { range, .. } = find_all_refs(&sema, position)?;
53 Some(RangeInfo { range, .. }) => range,
54 None => return Err(RenameError("No references found at position".to_string())),
55 };
56 Ok(RangeInfo::new(range, SourceChange::from(vec![]))) 61 Ok(RangeInfo::new(range, SourceChange::from(vec![])))
57 } 62 }
58 .map(|info| RangeInfo::new(info.range, ())) 63 .map(|info| RangeInfo::new(info.range, ()))
@@ -62,7 +67,7 @@ pub(crate) fn rename(
62 db: &RootDatabase, 67 db: &RootDatabase,
63 position: FilePosition, 68 position: FilePosition,
64 new_name: &str, 69 new_name: &str,
65) -> Result<RangeInfo<SourceChange>, RenameError> { 70) -> RenameResult<RangeInfo<SourceChange>> {
66 let sema = Semantics::new(db); 71 let sema = Semantics::new(db);
67 rename_with_semantics(&sema, position, new_name) 72 rename_with_semantics(&sema, position, new_name)
68} 73}
@@ -71,42 +76,18 @@ pub(crate) fn rename_with_semantics(
71 sema: &Semantics<RootDatabase>, 76 sema: &Semantics<RootDatabase>,
72 position: FilePosition, 77 position: FilePosition,
73 new_name: &str, 78 new_name: &str,
74) -> Result<RangeInfo<SourceChange>, RenameError> { 79) -> RenameResult<RangeInfo<SourceChange>> {
75 let is_lifetime_name = match lex_single_syntax_kind(new_name) {
76 Some(res) => match res {
77 (SyntaxKind::IDENT, _) => false,
78 (SyntaxKind::UNDERSCORE, _) => false,
79 (SyntaxKind::SELF_KW, _) => return rename_to_self(&sema, position),
80 (SyntaxKind::LIFETIME_IDENT, _) if new_name != "'static" && new_name != "'_" => true,
81 (SyntaxKind::LIFETIME_IDENT, _) => {
82 return Err(RenameError(format!(
83 "Invalid name `{0}`: Cannot rename lifetime to {0}",
84 new_name
85 )))
86 }
87 (_, Some(syntax_error)) => {
88 return Err(RenameError(format!("Invalid name `{}`: {}", new_name, syntax_error)))
89 }
90 (_, None) => {
91 return Err(RenameError(format!("Invalid name `{}`: not an identifier", new_name)))
92 }
93 },
94 None => return Err(RenameError(format!("Invalid name `{}`: not an identifier", new_name))),
95 };
96
97 let source_file = sema.parse(position.file_id); 80 let source_file = sema.parse(position.file_id);
98 let syntax = source_file.syntax(); 81 let syntax = source_file.syntax();
99 // this is here to prevent lifetime renames from happening on modules and self 82
100 if is_lifetime_name { 83 if let Some(module) = find_module_at_offset(&sema, position, syntax) {
101 rename_reference(&sema, position, new_name, is_lifetime_name)
102 } else if let Some(module) = find_module_at_offset(&sema, position, syntax) {
103 rename_mod(&sema, position, module, new_name) 84 rename_mod(&sema, position, module, new_name)
104 } else if let Some(self_token) = 85 } else if let Some(self_token) =
105 syntax.token_at_offset(position.offset).find(|t| t.kind() == SyntaxKind::SELF_KW) 86 syntax.token_at_offset(position.offset).find(|t| t.kind() == T![self])
106 { 87 {
107 rename_self_to_param(&sema, position, self_token, new_name) 88 rename_self_to_param(&sema, position, self_token, new_name)
108 } else { 89 } else {
109 rename_reference(&sema, position, new_name, is_lifetime_name) 90 rename_reference(&sema, position, new_name)
110 } 91 }
111} 92}
112 93
@@ -127,6 +108,33 @@ pub(crate) fn will_rename_file(
127 Some(change) 108 Some(change)
128} 109}
129 110
111#[derive(Debug, PartialEq)]
112enum IdentifierKind {
113 Ident,
114 Lifetime,
115 ToSelf,
116 Underscore,
117}
118
119fn check_identifier(new_name: &str) -> RenameResult<IdentifierKind> {
120 match lex_single_syntax_kind(new_name) {
121 Some(res) => match res {
122 (SyntaxKind::IDENT, _) => Ok(IdentifierKind::Ident),
123 (T![_], _) => Ok(IdentifierKind::Underscore),
124 (T![self], _) => Ok(IdentifierKind::ToSelf),
125 (SyntaxKind::LIFETIME_IDENT, _) if new_name != "'static" && new_name != "'_" => {
126 Ok(IdentifierKind::Lifetime)
127 }
128 (SyntaxKind::LIFETIME_IDENT, _) => {
129 bail!("Invalid name `{0}`: Cannot rename lifetime to {0}", new_name)
130 }
131 (_, Some(syntax_error)) => bail!("Invalid name `{}`: {}", new_name, syntax_error),
132 (_, None) => bail!("Invalid name `{}`: not an identifier", new_name),
133 },
134 None => bail!("Invalid name `{}`: not an identifier", new_name),
135 }
136}
137
130fn find_module_at_offset( 138fn find_module_at_offset(
131 sema: &Semantics<RootDatabase>, 139 sema: &Semantics<RootDatabase>,
132 position: FilePosition, 140 position: FilePosition,
@@ -155,39 +163,54 @@ fn find_module_at_offset(
155 Some(module) 163 Some(module)
156} 164}
157 165
158fn source_edit_from_reference( 166fn find_all_refs(
167 sema: &Semantics<RootDatabase>,
168 position: FilePosition,
169) -> RenameResult<RangeInfo<ReferenceSearchResult>> {
170 crate::references::find_all_refs(sema, position, None)
171 .ok_or_else(|| format_err!("No references found at position"))
172}
173
174fn source_edit_from_references(
159 sema: &Semantics<RootDatabase>, 175 sema: &Semantics<RootDatabase>,
160 reference: Reference, 176 file_id: FileId,
177 references: &[FileReference],
161 new_name: &str, 178 new_name: &str,
162) -> SourceFileEdit { 179) -> SourceFileEdit {
163 let mut replacement_text = String::new(); 180 let mut edit = TextEdit::builder();
164 let range = match reference.kind { 181 for reference in references {
165 ReferenceKind::FieldShorthandForField => { 182 let mut replacement_text = String::new();
166 mark::hit!(test_rename_struct_field_for_shorthand); 183 let range = match reference.kind {
167 replacement_text.push_str(new_name); 184 ReferenceKind::FieldShorthandForField => {
168 replacement_text.push_str(": "); 185 mark::hit!(test_rename_struct_field_for_shorthand);
169 TextRange::new(reference.file_range.range.start(), reference.file_range.range.start()) 186 replacement_text.push_str(new_name);
170 } 187 replacement_text.push_str(": ");
171 ReferenceKind::FieldShorthandForLocal => { 188 TextRange::new(reference.range.start(), reference.range.start())
172 mark::hit!(test_rename_local_for_field_shorthand); 189 }
173 replacement_text.push_str(": "); 190 ReferenceKind::FieldShorthandForLocal => {
174 replacement_text.push_str(new_name); 191 mark::hit!(test_rename_local_for_field_shorthand);
175 TextRange::new(reference.file_range.range.end(), reference.file_range.range.end()) 192 replacement_text.push_str(": ");
176 } 193 replacement_text.push_str(new_name);
177 ReferenceKind::RecordFieldExprOrPat => { 194 TextRange::new(reference.range.end(), reference.range.end())
178 mark::hit!(test_rename_field_expr_pat); 195 }
179 replacement_text.push_str(new_name); 196 ReferenceKind::RecordFieldExprOrPat => {
180 edit_text_range_for_record_field_expr_or_pat(sema, reference.file_range, new_name) 197 mark::hit!(test_rename_field_expr_pat);
181 } 198 replacement_text.push_str(new_name);
182 _ => { 199 edit_text_range_for_record_field_expr_or_pat(
183 replacement_text.push_str(new_name); 200 sema,
184 reference.file_range.range 201 FileRange { file_id, range: reference.range },
185 } 202 new_name,
186 }; 203 )
187 SourceFileEdit { 204 }
188 file_id: reference.file_range.file_id, 205 _ => {
189 edit: TextEdit::replace(range, replacement_text), 206 replacement_text.push_str(new_name);
207 reference.range
208 }
209 };
210 edit.replace(range, replacement_text);
190 } 211 }
212
213 SourceFileEdit { file_id, edit: edit.finish() }
191} 214}
192 215
193fn edit_text_range_for_record_field_expr_or_pat( 216fn edit_text_range_for_record_field_expr_or_pat(
@@ -223,7 +246,10 @@ fn rename_mod(
223 position: FilePosition, 246 position: FilePosition,
224 module: Module, 247 module: Module,
225 new_name: &str, 248 new_name: &str,
226) -> Result<RangeInfo<SourceChange>, RenameError> { 249) -> RenameResult<RangeInfo<SourceChange>> {
250 if IdentifierKind::Ident != check_identifier(new_name)? {
251 bail!("Invalid name `{0}`: cannot rename module to {0}", new_name);
252 }
227 let mut source_file_edits = Vec::new(); 253 let mut source_file_edits = Vec::new();
228 let mut file_system_edits = Vec::new(); 254 let mut file_system_edits = Vec::new();
229 255
@@ -254,12 +280,10 @@ fn rename_mod(
254 source_file_edits.push(edit); 280 source_file_edits.push(edit);
255 } 281 }
256 282
257 let RangeInfo { range, info: refs } = find_all_refs(sema, position, None) 283 let RangeInfo { range, info: refs } = find_all_refs(sema, position)?;
258 .ok_or_else(|| RenameError("No references found at position".to_string()))?; 284 let ref_edits = refs.references().iter().map(|(&file_id, references)| {
259 let ref_edits = refs 285 source_edit_from_references(sema, file_id, references, new_name)
260 .references 286 });
261 .into_iter()
262 .map(|reference| source_edit_from_reference(sema, reference, new_name));
263 source_file_edits.extend(ref_edits); 287 source_file_edits.extend(ref_edits);
264 288
265 Ok(RangeInfo::new(range, SourceChange::from_edits(source_file_edits, file_system_edits))) 289 Ok(RangeInfo::new(range, SourceChange::from_edits(source_file_edits, file_system_edits)))
@@ -274,27 +298,26 @@ fn rename_to_self(
274 298
275 let (fn_def, fn_ast) = find_node_at_offset::<ast::Fn>(syn, position.offset) 299 let (fn_def, fn_ast) = find_node_at_offset::<ast::Fn>(syn, position.offset)
276 .and_then(|fn_ast| sema.to_def(&fn_ast).zip(Some(fn_ast))) 300 .and_then(|fn_ast| sema.to_def(&fn_ast).zip(Some(fn_ast)))
277 .ok_or_else(|| RenameError("No surrounding method declaration found".to_string()))?; 301 .ok_or_else(|| format_err!("No surrounding method declaration found"))?;
278 let param_range = fn_ast 302 let param_range = fn_ast
279 .param_list() 303 .param_list()
280 .and_then(|p| p.params().next()) 304 .and_then(|p| p.params().next())
281 .ok_or_else(|| RenameError("Method has no parameters".to_string()))? 305 .ok_or_else(|| format_err!("Method has no parameters"))?
282 .syntax() 306 .syntax()
283 .text_range(); 307 .text_range();
284 if !param_range.contains(position.offset) { 308 if !param_range.contains(position.offset) {
285 return Err(RenameError("Only the first parameter can be self".to_string())); 309 bail!("Only the first parameter can be self");
286 } 310 }
287 311
288 let impl_block = find_node_at_offset::<ast::Impl>(syn, position.offset) 312 let impl_block = find_node_at_offset::<ast::Impl>(syn, position.offset)
289 .and_then(|def| sema.to_def(&def)) 313 .and_then(|def| sema.to_def(&def))
290 .ok_or_else(|| RenameError("No impl block found for function".to_string()))?; 314 .ok_or_else(|| format_err!("No impl block found for function"))?;
291 if fn_def.self_param(sema.db).is_some() { 315 if fn_def.self_param(sema.db).is_some() {
292 return Err(RenameError("Method already has a self parameter".to_string())); 316 bail!("Method already has a self parameter");
293 } 317 }
294 318
295 let params = fn_def.assoc_fn_params(sema.db); 319 let params = fn_def.assoc_fn_params(sema.db);
296 let first_param = 320 let first_param = params.first().ok_or_else(|| format_err!("Method has no parameters"))?;
297 params.first().ok_or_else(|| RenameError("Method has no parameters".into()))?;
298 let first_param_ty = first_param.ty(); 321 let first_param_ty = first_param.ty();
299 let impl_ty = impl_block.target_ty(sema.db); 322 let impl_ty = impl_block.target_ty(sema.db);
300 let (ty, self_param) = if impl_ty.remove_ref().is_some() { 323 let (ty, self_param) = if impl_ty.remove_ref().is_some() {
@@ -307,23 +330,17 @@ fn rename_to_self(
307 }; 330 };
308 331
309 if ty != impl_ty { 332 if ty != impl_ty {
310 return Err(RenameError("Parameter type differs from impl block type".to_string())); 333 bail!("Parameter type differs from impl block type");
311 } 334 }
312 335
313 let RangeInfo { range, info: refs } = find_all_refs(sema, position, None) 336 let RangeInfo { range, info: refs } = find_all_refs(sema, position)?;
314 .ok_or_else(|| RenameError("No reference found at position".to_string()))?;
315
316 let (param_ref, usages): (Vec<Reference>, Vec<Reference>) = refs
317 .into_iter()
318 .partition(|reference| param_range.intersect(reference.file_range.range).is_some());
319
320 if param_ref.is_empty() {
321 return Err(RenameError("Parameter to rename not found".to_string()));
322 }
323 337
324 let mut edits = usages 338 let mut edits = refs
325 .into_iter() 339 .references()
326 .map(|reference| source_edit_from_reference(sema, reference, "self")) 340 .iter()
341 .map(|(&file_id, references)| {
342 source_edit_from_references(sema, file_id, references, "self")
343 })
327 .collect::<Vec<_>>(); 344 .collect::<Vec<_>>();
328 345
329 edits.push(SourceFileEdit { 346 edits.push(SourceFileEdit {
@@ -367,12 +384,22 @@ fn rename_self_to_param(
367 self_token: SyntaxToken, 384 self_token: SyntaxToken,
368 new_name: &str, 385 new_name: &str,
369) -> Result<RangeInfo<SourceChange>, RenameError> { 386) -> Result<RangeInfo<SourceChange>, RenameError> {
387 let ident_kind = check_identifier(new_name)?;
388 match ident_kind {
389 IdentifierKind::Lifetime => bail!("Invalid name `{}`: not an identifier", new_name),
390 IdentifierKind::ToSelf => {
391 // no-op
392 mark::hit!(rename_self_to_self);
393 return Ok(RangeInfo::new(self_token.text_range(), SourceChange::default()));
394 }
395 _ => (),
396 }
370 let source_file = sema.parse(position.file_id); 397 let source_file = sema.parse(position.file_id);
371 let syn = source_file.syntax(); 398 let syn = source_file.syntax();
372 399
373 let text = sema.db.file_text(position.file_id); 400 let text = sema.db.file_text(position.file_id);
374 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)
375 .ok_or_else(|| RenameError("No surrounding method declaration found".to_string()))?; 402 .ok_or_else(|| format_err!("No surrounding method declaration found"))?;
376 let search_range = fn_def.syntax().text_range(); 403 let search_range = fn_def.syntax().text_range();
377 404
378 let mut edits: Vec<SourceFileEdit> = vec![]; 405 let mut edits: Vec<SourceFileEdit> = vec![];
@@ -382,12 +409,10 @@ fn rename_self_to_param(
382 if !search_range.contains_inclusive(offset) { 409 if !search_range.contains_inclusive(offset) {
383 continue; 410 continue;
384 } 411 }
385 if let Some(ref usage) = 412 if let Some(ref usage) = syn.token_at_offset(offset).find(|t| t.kind() == T![self]) {
386 syn.token_at_offset(offset).find(|t| t.kind() == SyntaxKind::SELF_KW)
387 {
388 let edit = if let Some(ref self_param) = ast::SelfParam::cast(usage.parent()) { 413 let edit = if let Some(ref self_param) = ast::SelfParam::cast(usage.parent()) {
389 text_edit_from_self_param(syn, self_param, new_name) 414 text_edit_from_self_param(syn, self_param, new_name)
390 .ok_or_else(|| RenameError("No target type found".to_string()))? 415 .ok_or_else(|| format_err!("No target type found"))?
391 } else { 416 } else {
392 TextEdit::replace(usage.text_range(), String::from(new_name)) 417 TextEdit::replace(usage.text_range(), String::from(new_name))
393 }; 418 };
@@ -395,6 +420,10 @@ fn rename_self_to_param(
395 } 420 }
396 } 421 }
397 422
423 if edits.len() > 1 && ident_kind == IdentifierKind::Underscore {
424 bail!("Cannot rename reference to `_` as it is being referenced multiple times");
425 }
426
398 let range = ast::SelfParam::cast(self_token.parent()) 427 let range = ast::SelfParam::cast(self_token.parent())
399 .map_or(self_token.text_range(), |p| p.syntax().text_range()); 428 .map_or(self_token.text_range(), |p| p.syntax().text_range());
400 429
@@ -405,35 +434,43 @@ fn rename_reference(
405 sema: &Semantics<RootDatabase>, 434 sema: &Semantics<RootDatabase>,
406 position: FilePosition, 435 position: FilePosition,
407 new_name: &str, 436 new_name: &str,
408 is_lifetime_name: bool,
409) -> Result<RangeInfo<SourceChange>, RenameError> { 437) -> Result<RangeInfo<SourceChange>, RenameError> {
410 let RangeInfo { range, info: refs } = match find_all_refs(sema, position, None) { 438 let ident_kind = check_identifier(new_name)?;
411 Some(range_info) => range_info, 439 let RangeInfo { range, info: refs } = find_all_refs(sema, position)?;
412 None => return Err(RenameError("No references found at position".to_string())), 440
413 }; 441 match (ident_kind, &refs.declaration.kind) {
414 442 (IdentifierKind::ToSelf, ReferenceKind::Lifetime)
415 match (refs.declaration.kind == ReferenceKind::Lifetime, is_lifetime_name) { 443 | (IdentifierKind::Underscore, ReferenceKind::Lifetime)
416 (true, false) => { 444 | (IdentifierKind::Ident, ReferenceKind::Lifetime) => {
417 return Err(RenameError(format!( 445 mark::hit!(rename_not_a_lifetime_ident_ref);
418 "Invalid name `{}`: not a lifetime identifier", 446 bail!("Invalid name `{}`: not a lifetime identifier", new_name)
419 new_name
420 )))
421 } 447 }
422 (false, true) => { 448 (IdentifierKind::Lifetime, ReferenceKind::Lifetime) => mark::hit!(rename_lifetime),
423 return Err(RenameError(format!("Invalid name `{}`: not an identifier", new_name))) 449 (IdentifierKind::Lifetime, _) => {
450 mark::hit!(rename_not_an_ident_ref);
451 bail!("Invalid name `{}`: not an identifier", new_name)
424 } 452 }
425 _ => (), 453 (IdentifierKind::ToSelf, ReferenceKind::SelfKw) => {
454 unreachable!("rename_self_to_param should've been called instead")
455 }
456 (IdentifierKind::ToSelf, _) => {
457 mark::hit!(rename_to_self);
458 return rename_to_self(sema, position);
459 }
460 (IdentifierKind::Underscore, _) if !refs.references.is_empty() => {
461 mark::hit!(rename_underscore_multiple);
462 bail!("Cannot rename reference to `_` as it is being referenced multiple times")
463 }
464 (IdentifierKind::Ident, _) | (IdentifierKind::Underscore, _) => mark::hit!(rename_ident),
426 } 465 }
427 466
428 let edit = refs 467 let edit = refs
429 .into_iter() 468 .into_iter()
430 .map(|reference| source_edit_from_reference(sema, reference, new_name)) 469 .map(|(file_id, references)| {
470 source_edit_from_references(sema, file_id, &references, new_name)
471 })
431 .collect::<Vec<_>>(); 472 .collect::<Vec<_>>();
432 473
433 if edit.is_empty() {
434 return Err(RenameError("No references found at position".to_string()));
435 }
436
437 Ok(RangeInfo::new(range, SourceChange::from(edit))) 474 Ok(RangeInfo::new(range, SourceChange::from(edit)))
438} 475}
439 476
@@ -462,9 +499,11 @@ mod tests {
462 text_edit_builder.replace(indel.delete, indel.insert); 499 text_edit_builder.replace(indel.delete, indel.insert);
463 } 500 }
464 } 501 }
465 let mut result = analysis.file_text(file_id.unwrap()).unwrap().to_string(); 502 if let Some(file_id) = file_id {
466 text_edit_builder.finish().apply(&mut result); 503 let mut result = analysis.file_text(file_id).unwrap().to_string();
467 assert_eq_text!(ra_fixture_after, &*result); 504 text_edit_builder.finish().apply(&mut result);
505 assert_eq_text!(ra_fixture_after, &*result);
506 }
468 } 507 }
469 Err(err) => { 508 Err(err) => {
470 if ra_fixture_after.starts_with("error:") { 509 if ra_fixture_after.starts_with("error:") {
@@ -493,19 +532,19 @@ mod tests {
493 532
494 #[test] 533 #[test]
495 fn test_rename_to_underscore() { 534 fn test_rename_to_underscore() {
496 check("_", r#"fn main() { let i<|> = 1; }"#, r#"fn main() { let _ = 1; }"#); 535 check("_", r#"fn main() { let i$0 = 1; }"#, r#"fn main() { let _ = 1; }"#);
497 } 536 }
498 537
499 #[test] 538 #[test]
500 fn test_rename_to_raw_identifier() { 539 fn test_rename_to_raw_identifier() {
501 check("r#fn", r#"fn main() { let i<|> = 1; }"#, r#"fn main() { let r#fn = 1; }"#); 540 check("r#fn", r#"fn main() { let i$0 = 1; }"#, r#"fn main() { let r#fn = 1; }"#);
502 } 541 }
503 542
504 #[test] 543 #[test]
505 fn test_rename_to_invalid_identifier1() { 544 fn test_rename_to_invalid_identifier1() {
506 check( 545 check(
507 "invalid!", 546 "invalid!",
508 r#"fn main() { let i<|> = 1; }"#, 547 r#"fn main() { let i$0 = 1; }"#,
509 "error: Invalid name `invalid!`: not an identifier", 548 "error: Invalid name `invalid!`: not an identifier",
510 ); 549 );
511 } 550 }
@@ -514,7 +553,7 @@ mod tests {
514 fn test_rename_to_invalid_identifier2() { 553 fn test_rename_to_invalid_identifier2() {
515 check( 554 check(
516 "multiple tokens", 555 "multiple tokens",
517 r#"fn main() { let i<|> = 1; }"#, 556 r#"fn main() { let i$0 = 1; }"#,
518 "error: Invalid name `multiple tokens`: not an identifier", 557 "error: Invalid name `multiple tokens`: not an identifier",
519 ); 558 );
520 } 559 }
@@ -523,38 +562,60 @@ mod tests {
523 fn test_rename_to_invalid_identifier3() { 562 fn test_rename_to_invalid_identifier3() {
524 check( 563 check(
525 "let", 564 "let",
526 r#"fn main() { let i<|> = 1; }"#, 565 r#"fn main() { let i$0 = 1; }"#,
527 "error: Invalid name `let`: not an identifier", 566 "error: Invalid name `let`: not an identifier",
528 ); 567 );
529 } 568 }
530 569
531 #[test] 570 #[test]
532 fn test_rename_to_invalid_identifier_lifetime() { 571 fn test_rename_to_invalid_identifier_lifetime() {
572 mark::check!(rename_not_an_ident_ref);
533 check( 573 check(
534 "'foo", 574 "'foo",
535 r#"fn main() { let i<|> = 1; }"#, 575 r#"fn main() { let i$0 = 1; }"#,
536 "error: Invalid name `'foo`: not an identifier", 576 "error: Invalid name `'foo`: not an identifier",
537 ); 577 );
538 } 578 }
539 579
540 #[test] 580 #[test]
541 fn test_rename_to_invalid_identifier_lifetime2() { 581 fn test_rename_to_invalid_identifier_lifetime2() {
582 mark::check!(rename_not_a_lifetime_ident_ref);
542 check( 583 check(
543 "foo", 584 "foo",
544 r#"fn main<'a>(_: &'a<|> ()) {}"#, 585 r#"fn main<'a>(_: &'a$0 ()) {}"#,
545 "error: Invalid name `foo`: not a lifetime identifier", 586 "error: Invalid name `foo`: not a lifetime identifier",
546 ); 587 );
547 } 588 }
548 589
549 #[test] 590 #[test]
591 fn test_rename_to_underscore_invalid() {
592 mark::check!(rename_underscore_multiple);
593 check(
594 "_",
595 r#"fn main(foo$0: ()) {foo;}"#,
596 "error: Cannot rename reference to `_` as it is being referenced multiple times",
597 );
598 }
599
600 #[test]
601 fn test_rename_mod_invalid() {
602 check(
603 "'foo",
604 r#"mod foo$0 {}"#,
605 "error: Invalid name `'foo`: cannot rename module to 'foo",
606 );
607 }
608
609 #[test]
550 fn test_rename_for_local() { 610 fn test_rename_for_local() {
611 mark::check!(rename_ident);
551 check( 612 check(
552 "k", 613 "k",
553 r#" 614 r#"
554fn main() { 615fn main() {
555 let mut i = 1; 616 let mut i = 1;
556 let j = 1; 617 let j = 1;
557 i = i<|> + j; 618 i = i$0 + j;
558 619
559 { i = 0; } 620 { i = 0; }
560 621
@@ -579,7 +640,7 @@ fn main() {
579 fn test_rename_unresolved_reference() { 640 fn test_rename_unresolved_reference() {
580 check( 641 check(
581 "new_name", 642 "new_name",
582 r#"fn main() { let _ = unresolved_ref<|>; }"#, 643 r#"fn main() { let _ = unresolved_ref$0; }"#,
583 "error: No references found at position", 644 "error: No references found at position",
584 ); 645 );
585 } 646 }
@@ -591,7 +652,7 @@ fn main() {
591 r#" 652 r#"
592macro_rules! foo {($i:ident) => {$i} } 653macro_rules! foo {($i:ident) => {$i} }
593fn main() { 654fn main() {
594 let a<|> = "test"; 655 let a$0 = "test";
595 foo!(a); 656 foo!(a);
596} 657}
597"#, 658"#,
@@ -613,7 +674,7 @@ fn main() {
613macro_rules! foo {($i:ident) => {$i} } 674macro_rules! foo {($i:ident) => {$i} }
614fn main() { 675fn main() {
615 let a = "test"; 676 let a = "test";
616 foo!(a<|>); 677 foo!(a$0);
617} 678}
618"#, 679"#,
619 r#" 680 r#"
@@ -634,7 +695,7 @@ fn main() {
634macro_rules! define_fn {($id:ident) => { fn $id{} }} 695macro_rules! define_fn {($id:ident) => { fn $id{} }}
635define_fn!(foo); 696define_fn!(foo);
636fn main() { 697fn main() {
637 fo<|>o(); 698 fo$0o();
638} 699}
639"#, 700"#,
640 r#" 701 r#"
@@ -653,7 +714,7 @@ fn main() {
653 "bar", 714 "bar",
654 r#" 715 r#"
655macro_rules! define_fn {($id:ident) => { fn $id{} }} 716macro_rules! define_fn {($id:ident) => { fn $id{} }}
656define_fn!(fo<|>o); 717define_fn!(fo$0o);
657fn main() { 718fn main() {
658 foo(); 719 foo();
659} 720}
@@ -670,17 +731,17 @@ fn main() {
670 731
671 #[test] 732 #[test]
672 fn test_rename_for_param_inside() { 733 fn test_rename_for_param_inside() {
673 check("j", r#"fn foo(i : u32) -> u32 { i<|> }"#, r#"fn foo(j : u32) -> u32 { j }"#); 734 check("j", r#"fn foo(i : u32) -> u32 { i$0 }"#, r#"fn foo(j : u32) -> u32 { j }"#);
674 } 735 }
675 736
676 #[test] 737 #[test]
677 fn test_rename_refs_for_fn_param() { 738 fn test_rename_refs_for_fn_param() {
678 check("j", r#"fn foo(i<|> : u32) -> u32 { i }"#, r#"fn foo(j : u32) -> u32 { j }"#); 739 check("j", r#"fn foo(i$0 : u32) -> u32 { i }"#, r#"fn foo(j : u32) -> u32 { j }"#);
679 } 740 }
680 741
681 #[test] 742 #[test]
682 fn test_rename_for_mut_param() { 743 fn test_rename_for_mut_param() {
683 check("j", r#"fn foo(mut i<|> : u32) -> u32 { i }"#, r#"fn foo(mut j : u32) -> u32 { j }"#); 744 check("j", r#"fn foo(mut i$0 : u32) -> u32 { i }"#, r#"fn foo(mut j : u32) -> u32 { j }"#);
684 } 745 }
685 746
686 #[test] 747 #[test]
@@ -688,7 +749,7 @@ fn main() {
688 check( 749 check(
689 "j", 750 "j",
690 r#" 751 r#"
691struct Foo { i<|>: i32 } 752struct Foo { i$0: i32 }
692 753
693impl Foo { 754impl Foo {
694 fn new(i: i32) -> Self { 755 fn new(i: i32) -> Self {
@@ -714,7 +775,7 @@ impl Foo {
714 check( 775 check(
715 "j", 776 "j",
716 r#" 777 r#"
717struct Foo { i<|>: i32 } 778struct Foo { i$0: i32 }
718 779
719impl Foo { 780impl Foo {
720 fn new(i: i32) -> Self { 781 fn new(i: i32) -> Self {
@@ -743,7 +804,7 @@ impl Foo {
743struct Foo { i: i32 } 804struct Foo { i: i32 }
744 805
745impl Foo { 806impl Foo {
746 fn new(i<|>: i32) -> Self { 807 fn new(i$0: i32) -> Self {
747 Self { i } 808 Self { i }
748 } 809 }
749} 810}
@@ -765,7 +826,7 @@ impl Foo {
765 check( 826 check(
766 "j", 827 "j",
767 r#" 828 r#"
768struct Foo { i<|>: i32 } 829struct Foo { i$0: i32 }
769struct Bar { i: i32 } 830struct Bar { i: i32 }
770 831
771impl Bar { 832impl Bar {
@@ -794,7 +855,7 @@ impl Bar {
794 r#" 855 r#"
795struct Foo { i: i32 } 856struct Foo { i: i32 }
796 857
797fn baz(i<|>: i32) -> Self { 858fn baz(i$0: i32) -> Self {
798 let x = Foo { i }; 859 let x = Foo { i };
799 { 860 {
800 let i = 0; 861 let i = 0;
@@ -825,7 +886,7 @@ fn baz(j: i32) -> Self {
825mod bar; 886mod bar;
826 887
827//- /bar.rs 888//- /bar.rs
828mod foo<|>; 889mod foo$0;
829 890
830//- /bar/foo.rs 891//- /bar/foo.rs
831// empty 892// empty
@@ -883,7 +944,7 @@ fn main() {}
883pub struct FooContent; 944pub struct FooContent;
884 945
885//- /bar.rs 946//- /bar.rs
886use crate::foo<|>::FooContent; 947use crate::foo$0::FooContent;
887"#, 948"#,
888 expect![[r#" 949 expect![[r#"
889 RangeInfo { 950 RangeInfo {
@@ -943,9 +1004,9 @@ use crate::foo<|>::FooContent;
943 "foo2", 1004 "foo2",
944 r#" 1005 r#"
945//- /lib.rs 1006//- /lib.rs
946mod fo<|>o; 1007mod fo$0o;
947//- /foo/mod.rs 1008//- /foo/mod.rs
948// emtpy 1009// empty
949"#, 1010"#,
950 expect![[r#" 1011 expect![[r#"
951 RangeInfo { 1012 RangeInfo {
@@ -992,10 +1053,10 @@ mod fo<|>o;
992 "bar", 1053 "bar",
993 r#" 1054 r#"
994//- /lib.rs 1055//- /lib.rs
995mod outer { mod fo<|>o; } 1056mod outer { mod fo$0o; }
996 1057
997//- /outer/foo.rs 1058//- /outer/foo.rs
998// emtpy 1059// empty
999"#, 1060"#,
1000 expect![[r#" 1061 expect![[r#"
1001 RangeInfo { 1062 RangeInfo {
@@ -1041,7 +1102,7 @@ mod outer { mod fo<|>o; }
1041 check( 1102 check(
1042 "baz", 1103 "baz",
1043 r#" 1104 r#"
1044mod <|>foo { pub fn bar() {} } 1105mod $0foo { pub fn bar() {} }
1045 1106
1046fn main() { foo::bar(); } 1107fn main() { foo::bar(); }
1047"#, 1108"#,
@@ -1065,7 +1126,7 @@ fn f() {
1065} 1126}
1066 1127
1067//- /bar.rs 1128//- /bar.rs
1068pub mod foo<|>; 1129pub mod foo$0;
1069 1130
1070//- /bar/foo.rs 1131//- /bar/foo.rs
1071// pub fn fun() {} 1132// pub fn fun() {}
@@ -1128,7 +1189,7 @@ pub mod foo<|>;
1128 "Baz", 1189 "Baz",
1129 r#" 1190 r#"
1130mod foo { 1191mod foo {
1131 pub enum Foo { Bar<|> } 1192 pub enum Foo { Bar$0 }
1132} 1193}
1133 1194
1134fn func(f: foo::Foo) { 1195fn func(f: foo::Foo) {
@@ -1157,7 +1218,7 @@ fn func(f: foo::Foo) {
1157 "baz", 1218 "baz",
1158 r#" 1219 r#"
1159mod foo { 1220mod foo {
1160 pub struct Foo { pub bar<|>: uint } 1221 pub struct Foo { pub bar$0: uint }
1161} 1222}
1162 1223
1163fn foo(f: foo::Foo) { 1224fn foo(f: foo::Foo) {
@@ -1178,13 +1239,14 @@ fn foo(f: foo::Foo) {
1178 1239
1179 #[test] 1240 #[test]
1180 fn test_parameter_to_self() { 1241 fn test_parameter_to_self() {
1242 mark::check!(rename_to_self);
1181 check( 1243 check(
1182 "self", 1244 "self",
1183 r#" 1245 r#"
1184struct Foo { i: i32 } 1246struct Foo { i: i32 }
1185 1247
1186impl Foo { 1248impl Foo {
1187 fn f(foo<|>: &mut Foo) -> i32 { 1249 fn f(foo$0: &mut Foo) -> i32 {
1188 foo.i 1250 foo.i
1189 } 1251 }
1190} 1252}
@@ -1205,7 +1267,7 @@ impl Foo {
1205struct Foo { i: i32 } 1267struct Foo { i: i32 }
1206 1268
1207impl Foo { 1269impl Foo {
1208 fn f(foo<|>: Foo) -> i32 { 1270 fn f(foo$0: Foo) -> i32 {
1209 foo.i 1271 foo.i
1210 } 1272 }
1211} 1273}
@@ -1229,7 +1291,7 @@ impl Foo {
1229 r#" 1291 r#"
1230struct Foo { i: i32 } 1292struct Foo { i: i32 }
1231 1293
1232fn f(foo<|>: &mut Foo) -> i32 { 1294fn f(foo$0: &mut Foo) -> i32 {
1233 foo.i 1295 foo.i
1234} 1296}
1235"#, 1297"#,
@@ -1242,7 +1304,7 @@ struct Foo { i: i32 }
1242struct Bar; 1304struct Bar;
1243 1305
1244impl Bar { 1306impl Bar {
1245 fn f(foo<|>: &mut Foo) -> i32 { 1307 fn f(foo$0: &mut Foo) -> i32 {
1246 foo.i 1308 foo.i
1247 } 1309 }
1248} 1310}
@@ -1258,7 +1320,7 @@ impl Bar {
1258 r#" 1320 r#"
1259struct Foo { i: i32 } 1321struct Foo { i: i32 }
1260impl Foo { 1322impl Foo {
1261 fn f(x: (), foo<|>: &mut Foo) -> i32 { 1323 fn f(x: (), foo$0: &mut Foo) -> i32 {
1262 foo.i 1324 foo.i
1263 } 1325 }
1264} 1326}
@@ -1274,7 +1336,7 @@ impl Foo {
1274 r#" 1336 r#"
1275struct Foo { i: i32 } 1337struct Foo { i: i32 }
1276impl &Foo { 1338impl &Foo {
1277 fn f(foo<|>: &Foo) -> i32 { 1339 fn f(foo$0: &Foo) -> i32 {
1278 foo.i 1340 foo.i
1279 } 1341 }
1280} 1342}
@@ -1298,7 +1360,7 @@ impl &Foo {
1298struct Foo { i: i32 } 1360struct Foo { i: i32 }
1299 1361
1300impl Foo { 1362impl Foo {
1301 fn f(&mut <|>self) -> i32 { 1363 fn f(&mut $0self) -> i32 {
1302 self.i 1364 self.i
1303 } 1365 }
1304} 1366}
@@ -1323,7 +1385,7 @@ impl Foo {
1323struct Foo { i: i32 } 1385struct Foo { i: i32 }
1324 1386
1325impl Foo { 1387impl Foo {
1326 fn f(<|>self) -> i32 { 1388 fn f($0self) -> i32 {
1327 self.i 1389 self.i
1328 } 1390 }
1329} 1391}
@@ -1350,7 +1412,7 @@ struct Foo { i: i32 }
1350impl Foo { 1412impl Foo {
1351 fn f(&self) -> i32 { 1413 fn f(&self) -> i32 {
1352 let self_var = 1; 1414 let self_var = 1;
1353 self<|>.i 1415 self$0.i
1354 } 1416 }
1355} 1417}
1356"#, 1418"#,
@@ -1373,7 +1435,7 @@ impl Foo {
1373 check( 1435 check(
1374 "bar", 1436 "bar",
1375 r#" 1437 r#"
1376struct Foo { i<|>: i32 } 1438struct Foo { i$0: i32 }
1377 1439
1378fn foo(bar: i32) -> Foo { 1440fn foo(bar: i32) -> Foo {
1379 Foo { i: bar } 1441 Foo { i: bar }
@@ -1394,7 +1456,7 @@ fn foo(bar: i32) -> Foo {
1394 check( 1456 check(
1395 "baz", 1457 "baz",
1396 r#" 1458 r#"
1397struct Foo { i<|>: i32 } 1459struct Foo { i$0: i32 }
1398 1460
1399fn foo(foo: Foo) { 1461fn foo(foo: Foo) {
1400 let Foo { i: baz } = foo; 1462 let Foo { i: baz } = foo;
@@ -1433,7 +1495,7 @@ struct Foo {
1433 1495
1434fn foo(foo: Foo) { 1496fn foo(foo: Foo) {
1435 let Foo { i: b } = foo; 1497 let Foo { i: b } = foo;
1436 let _ = b<|>; 1498 let _ = b$0;
1437} 1499}
1438"#, 1500"#,
1439 expected_fixture, 1501 expected_fixture,
@@ -1447,7 +1509,7 @@ struct Foo {
1447 1509
1448fn foo(foo: Foo) { 1510fn foo(foo: Foo) {
1449 let Foo { i } = foo; 1511 let Foo { i } = foo;
1450 let _ = i<|>; 1512 let _ = i$0;
1451} 1513}
1452"#, 1514"#,
1453 expected_fixture, 1515 expected_fixture,
@@ -1464,7 +1526,7 @@ struct Foo {
1464} 1526}
1465 1527
1466fn foo(Foo { i }: foo) -> i32 { 1528fn foo(Foo { i }: foo) -> i32 {
1467 i<|> 1529 i$0
1468} 1530}
1469"#, 1531"#,
1470 r#" 1532 r#"
@@ -1481,6 +1543,7 @@ fn foo(Foo { i: bar }: foo) -> i32 {
1481 1543
1482 #[test] 1544 #[test]
1483 fn test_rename_lifetimes() { 1545 fn test_rename_lifetimes() {
1546 mark::check!(rename_lifetime);
1484 check( 1547 check(
1485 "'yeeee", 1548 "'yeeee",
1486 r#" 1549 r#"
@@ -1488,7 +1551,7 @@ trait Foo<'a> {
1488 fn foo() -> &'a (); 1551 fn foo() -> &'a ();
1489} 1552}
1490impl<'a> Foo<'a> for &'a () { 1553impl<'a> Foo<'a> for &'a () {
1491 fn foo() -> &'a<|> () { 1554 fn foo() -> &'a$0 () {
1492 unimplemented!() 1555 unimplemented!()
1493 } 1556 }
1494} 1557}
@@ -1520,7 +1583,7 @@ fn main() {
1520 let test_variable = CustomOption::Some(22); 1583 let test_variable = CustomOption::Some(22);
1521 1584
1522 match test_variable { 1585 match test_variable {
1523 CustomOption::Some(foo<|>) if foo == 11 => {} 1586 CustomOption::Some(foo$0) if foo == 11 => {}
1524 _ => (), 1587 _ => (),
1525 } 1588 }
1526}"#, 1589}"#,
@@ -1549,7 +1612,7 @@ fn main() {
1549fn foo<'a>() -> &'a () { 1612fn foo<'a>() -> &'a () {
1550 'a: { 1613 'a: {
1551 'b: loop { 1614 'b: loop {
1552 break 'a<|>; 1615 break 'a$0;
1553 } 1616 }
1554 } 1617 }
1555} 1618}
@@ -1565,4 +1628,24 @@ fn foo<'a>() -> &'a () {
1565"#, 1628"#,
1566 ) 1629 )
1567 } 1630 }
1631
1632 #[test]
1633 fn test_self_to_self() {
1634 mark::check!(rename_self_to_self);
1635 check(
1636 "self",
1637 r#"
1638struct Foo;
1639impl Foo {
1640 fn foo(self$0) {}
1641}
1642"#,
1643 r#"
1644struct Foo;
1645impl Foo {
1646 fn foo(self) {}
1647}
1648"#,
1649 )
1650 }
1568} 1651}