diff options
Diffstat (limited to 'crates/ide/src/references')
-rw-r--r-- | crates/ide/src/references/rename.rs | 433 |
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 |
2 | use std::{ | 2 | use std::{ |
3 | convert::TryInto, | 3 | convert::TryInto, |
4 | error::Error, | ||
5 | fmt::{self, Display}, | 4 | fmt::{self, Display}, |
6 | }; | 5 | }; |
7 | 6 | ||
8 | use hir::{Module, ModuleDef, ModuleSource, Semantics}; | 7 | use hir::{Module, ModuleDef, ModuleSource, Semantics}; |
9 | use ide_db::base_db::{AnchoredPathBuf, FileId, FileRange, SourceDatabaseExt}; | ||
10 | use ide_db::{ | 8 | use 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 | }; |
14 | use syntax::{ | 14 | use 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 | }; |
19 | use test_utils::mark; | 19 | use test_utils::mark; |
20 | use text_edit::TextEdit; | 20 | use text_edit::TextEdit; |
21 | 21 | ||
22 | use crate::{ | 22 | use 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 | ||
27 | type RenameResult<T> = Result<T, RenameError>; | ||
27 | #[derive(Debug)] | 28 | #[derive(Debug)] |
28 | pub struct RenameError(pub(crate) String); | 29 | pub struct RenameError(pub(crate) String); |
29 | 30 | ||
@@ -33,26 +34,30 @@ impl fmt::Display for RenameError { | |||
33 | } | 34 | } |
34 | } | 35 | } |
35 | 36 | ||
36 | impl Error for RenameError {} | 37 | macro_rules! format_err { |
38 | ($fmt:expr) => {RenameError(format!($fmt))}; | ||
39 | ($fmt:expr, $($arg:tt)+) => {RenameError(format!($fmt, $($arg)+))} | ||
40 | } | ||
41 | |||
42 | macro_rules! bail { | ||
43 | ($($tokens:tt)*) => {return Err(format_err!($($tokens)*))} | ||
44 | } | ||
37 | 45 | ||
38 | pub(crate) fn prepare_rename( | 46 | pub(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)] | ||
112 | enum IdentifierKind { | ||
113 | Ident, | ||
114 | Lifetime, | ||
115 | ToSelf, | ||
116 | Underscore, | ||
117 | } | ||
118 | |||
119 | fn 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 | |||
130 | fn find_module_at_offset( | 138 | fn 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 | ||
158 | fn source_edit_from_reference( | 166 | fn 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 | |||
174 | fn 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 | ||
193 | fn edit_text_range_for_record_field_expr_or_pat( | 216 | fn 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#" |
554 | fn main() { | 615 | fn 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#" |
592 | macro_rules! foo {($i:ident) => {$i} } | 653 | macro_rules! foo {($i:ident) => {$i} } |
593 | fn main() { | 654 | fn 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() { | |||
613 | macro_rules! foo {($i:ident) => {$i} } | 674 | macro_rules! foo {($i:ident) => {$i} } |
614 | fn main() { | 675 | fn 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() { | |||
634 | macro_rules! define_fn {($id:ident) => { fn $id{} }} | 695 | macro_rules! define_fn {($id:ident) => { fn $id{} }} |
635 | define_fn!(foo); | 696 | define_fn!(foo); |
636 | fn main() { | 697 | fn 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#" |
655 | macro_rules! define_fn {($id:ident) => { fn $id{} }} | 716 | macro_rules! define_fn {($id:ident) => { fn $id{} }} |
656 | define_fn!(fo<|>o); | 717 | define_fn!(fo$0o); |
657 | fn main() { | 718 | fn 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#" |
691 | struct Foo { i<|>: i32 } | 752 | struct Foo { i$0: i32 } |
692 | 753 | ||
693 | impl Foo { | 754 | impl 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#" |
717 | struct Foo { i<|>: i32 } | 778 | struct Foo { i$0: i32 } |
718 | 779 | ||
719 | impl Foo { | 780 | impl Foo { |
720 | fn new(i: i32) -> Self { | 781 | fn new(i: i32) -> Self { |
@@ -743,7 +804,7 @@ impl Foo { | |||
743 | struct Foo { i: i32 } | 804 | struct Foo { i: i32 } |
744 | 805 | ||
745 | impl Foo { | 806 | impl 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#" |
768 | struct Foo { i<|>: i32 } | 829 | struct Foo { i$0: i32 } |
769 | struct Bar { i: i32 } | 830 | struct Bar { i: i32 } |
770 | 831 | ||
771 | impl Bar { | 832 | impl Bar { |
@@ -794,7 +855,7 @@ impl Bar { | |||
794 | r#" | 855 | r#" |
795 | struct Foo { i: i32 } | 856 | struct Foo { i: i32 } |
796 | 857 | ||
797 | fn baz(i<|>: i32) -> Self { | 858 | fn 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 { | |||
825 | mod bar; | 886 | mod bar; |
826 | 887 | ||
827 | //- /bar.rs | 888 | //- /bar.rs |
828 | mod foo<|>; | 889 | mod foo$0; |
829 | 890 | ||
830 | //- /bar/foo.rs | 891 | //- /bar/foo.rs |
831 | // empty | 892 | // empty |
@@ -883,7 +944,7 @@ fn main() {} | |||
883 | pub struct FooContent; | 944 | pub struct FooContent; |
884 | 945 | ||
885 | //- /bar.rs | 946 | //- /bar.rs |
886 | use crate::foo<|>::FooContent; | 947 | use 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 |
946 | mod fo<|>o; | 1007 | mod 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 |
995 | mod outer { mod fo<|>o; } | 1056 | mod 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#" |
1044 | mod <|>foo { pub fn bar() {} } | 1105 | mod $0foo { pub fn bar() {} } |
1045 | 1106 | ||
1046 | fn main() { foo::bar(); } | 1107 | fn main() { foo::bar(); } |
1047 | "#, | 1108 | "#, |
@@ -1065,7 +1126,7 @@ fn f() { | |||
1065 | } | 1126 | } |
1066 | 1127 | ||
1067 | //- /bar.rs | 1128 | //- /bar.rs |
1068 | pub mod foo<|>; | 1129 | pub 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#" |
1130 | mod foo { | 1191 | mod foo { |
1131 | pub enum Foo { Bar<|> } | 1192 | pub enum Foo { Bar$0 } |
1132 | } | 1193 | } |
1133 | 1194 | ||
1134 | fn func(f: foo::Foo) { | 1195 | fn func(f: foo::Foo) { |
@@ -1157,7 +1218,7 @@ fn func(f: foo::Foo) { | |||
1157 | "baz", | 1218 | "baz", |
1158 | r#" | 1219 | r#" |
1159 | mod foo { | 1220 | mod foo { |
1160 | pub struct Foo { pub bar<|>: uint } | 1221 | pub struct Foo { pub bar$0: uint } |
1161 | } | 1222 | } |
1162 | 1223 | ||
1163 | fn foo(f: foo::Foo) { | 1224 | fn 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#" |
1184 | struct Foo { i: i32 } | 1246 | struct Foo { i: i32 } |
1185 | 1247 | ||
1186 | impl Foo { | 1248 | impl 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 { | |||
1205 | struct Foo { i: i32 } | 1267 | struct Foo { i: i32 } |
1206 | 1268 | ||
1207 | impl Foo { | 1269 | impl 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#" |
1230 | struct Foo { i: i32 } | 1292 | struct Foo { i: i32 } |
1231 | 1293 | ||
1232 | fn f(foo<|>: &mut Foo) -> i32 { | 1294 | fn f(foo$0: &mut Foo) -> i32 { |
1233 | foo.i | 1295 | foo.i |
1234 | } | 1296 | } |
1235 | "#, | 1297 | "#, |
@@ -1242,7 +1304,7 @@ struct Foo { i: i32 } | |||
1242 | struct Bar; | 1304 | struct Bar; |
1243 | 1305 | ||
1244 | impl Bar { | 1306 | impl 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#" |
1259 | struct Foo { i: i32 } | 1321 | struct Foo { i: i32 } |
1260 | impl Foo { | 1322 | impl 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#" |
1275 | struct Foo { i: i32 } | 1337 | struct Foo { i: i32 } |
1276 | impl &Foo { | 1338 | impl &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 { | |||
1298 | struct Foo { i: i32 } | 1360 | struct Foo { i: i32 } |
1299 | 1361 | ||
1300 | impl Foo { | 1362 | impl 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 { | |||
1323 | struct Foo { i: i32 } | 1385 | struct Foo { i: i32 } |
1324 | 1386 | ||
1325 | impl Foo { | 1387 | impl 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 } | |||
1350 | impl Foo { | 1412 | impl 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#" |
1376 | struct Foo { i<|>: i32 } | 1438 | struct Foo { i$0: i32 } |
1377 | 1439 | ||
1378 | fn foo(bar: i32) -> Foo { | 1440 | fn 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#" |
1397 | struct Foo { i<|>: i32 } | 1459 | struct Foo { i$0: i32 } |
1398 | 1460 | ||
1399 | fn foo(foo: Foo) { | 1461 | fn foo(foo: Foo) { |
1400 | let Foo { i: baz } = foo; | 1462 | let Foo { i: baz } = foo; |
@@ -1433,7 +1495,7 @@ struct Foo { | |||
1433 | 1495 | ||
1434 | fn foo(foo: Foo) { | 1496 | fn 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 | ||
1448 | fn foo(foo: Foo) { | 1510 | fn 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 | ||
1466 | fn foo(Foo { i }: foo) -> i32 { | 1528 | fn 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 | } |
1490 | impl<'a> Foo<'a> for &'a () { | 1553 | impl<'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() { | |||
1549 | fn foo<'a>() -> &'a () { | 1612 | fn 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#" | ||
1638 | struct Foo; | ||
1639 | impl Foo { | ||
1640 | fn foo(self$0) {} | ||
1641 | } | ||
1642 | "#, | ||
1643 | r#" | ||
1644 | struct Foo; | ||
1645 | impl Foo { | ||
1646 | fn foo(self) {} | ||
1647 | } | ||
1648 | "#, | ||
1649 | ) | ||
1650 | } | ||
1568 | } | 1651 | } |