ide/
rename.rs

1//! Renaming functionality.
2//!
3//! This is mostly front-end for [`ide_db::rename`], but it also includes the
4//! tests. This module also implements a couple of magic tricks, like renaming
5//! `self` and to `self` (to switch between associated function and method).
6
7use hir::{AsAssocItem, FindPathConfig, HasContainer, HirDisplay, InFile, Name, Semantics, sym};
8use ide_db::{
9    FileId, FileRange, RootDatabase,
10    defs::{Definition, NameClass, NameRefClass},
11    rename::{IdentifierKind, RenameDefinition, bail, format_err, source_edit_from_references},
12    source_change::SourceChangeBuilder,
13};
14use itertools::Itertools;
15use std::fmt::Write;
16use stdx::{always, format_to, never};
17use syntax::{
18    AstNode, SyntaxKind, SyntaxNode, TextRange, TextSize,
19    ast::{self, HasArgList, prec::ExprPrecedence},
20};
21
22use ide_db::text_edit::TextEdit;
23
24use crate::{FilePosition, RangeInfo, SourceChange};
25
26pub use ide_db::rename::RenameError;
27
28type RenameResult<T> = Result<T, RenameError>;
29
30pub struct RenameConfig {
31    pub prefer_no_std: bool,
32    pub prefer_prelude: bool,
33    pub prefer_absolute: bool,
34}
35
36impl RenameConfig {
37    fn find_path_config(&self) -> FindPathConfig {
38        FindPathConfig {
39            prefer_no_std: self.prefer_no_std,
40            prefer_prelude: self.prefer_prelude,
41            prefer_absolute: self.prefer_absolute,
42            allow_unstable: true,
43        }
44    }
45}
46
47/// This is similar to `collect::<Result<Vec<_>, _>>`, but unlike it, it succeeds if there is *any* `Ok` item.
48fn ok_if_any<T, E>(iter: impl Iterator<Item = Result<T, E>>) -> Result<Vec<T>, E> {
49    let mut err = None;
50    let oks = iter
51        .filter_map(|item| match item {
52            Ok(it) => Some(it),
53            Err(it) => {
54                err = Some(it);
55                None
56            }
57        })
58        .collect::<Vec<_>>();
59    if !oks.is_empty() {
60        Ok(oks)
61    } else if let Some(err) = err {
62        Err(err)
63    } else {
64        Ok(Vec::new())
65    }
66}
67
68/// Prepares a rename. The sole job of this function is to return the TextRange of the thing that is
69/// being targeted for a rename.
70pub(crate) fn prepare_rename(
71    db: &RootDatabase,
72    position: FilePosition,
73) -> RenameResult<RangeInfo<()>> {
74    let sema = Semantics::new(db);
75    let source_file = sema.parse_guess_edition(position.file_id);
76    let syntax = source_file.syntax();
77
78    let res = find_definitions(&sema, syntax, position, &Name::new_symbol_root(sym::underscore))?
79        .filter(|(_, _, def, _, _)| def.range_for_rename(&sema).is_some())
80        .map(|(frange, kind, _, _, _)| {
81            always!(
82                frange.range.contains_inclusive(position.offset)
83                    && frange.file_id == position.file_id
84            );
85
86            Ok(match kind {
87                SyntaxKind::LIFETIME => {
88                    TextRange::new(frange.range.start() + TextSize::from(1), frange.range.end())
89                }
90                _ => frange.range,
91            })
92        })
93        .reduce(|acc, cur| match (acc, cur) {
94            // ensure all ranges are the same
95            (Ok(acc_inner), Ok(cur_inner)) if acc_inner == cur_inner => Ok(acc_inner),
96            (e @ Err(_), _) | (_, e @ Err(_)) => e,
97            _ => bail!("inconsistent text range"),
98        });
99
100    match res {
101        // ensure at least one definition was found
102        Some(res) => res.map(|range| RangeInfo::new(range, ())),
103        None => bail!("No references found at position"),
104    }
105}
106
107// Feature: Rename
108//
109// Renames the item below the cursor and all of its references
110//
111// | Editor  | Shortcut |
112// |---------|----------|
113// | VS Code | <kbd>F2</kbd> |
114//
115// ![Rename](https://user-images.githubusercontent.com/48062697/113065582-055aae80-91b1-11eb-8ade-2b58e6d81883.gif)
116pub(crate) fn rename(
117    db: &RootDatabase,
118    position: FilePosition,
119    new_name: &str,
120    config: &RenameConfig,
121) -> RenameResult<SourceChange> {
122    let sema = Semantics::new(db);
123    let file_id = sema
124        .attach_first_edition(position.file_id)
125        .ok_or_else(|| format_err!("No references found at position"))?;
126    let source_file = sema.parse(file_id);
127    let syntax = source_file.syntax();
128
129    let edition = file_id.edition(db);
130    let (new_name, kind) = IdentifierKind::classify(edition, new_name)?;
131
132    let defs = find_definitions(&sema, syntax, position, &new_name)?;
133    let alias_fallback =
134        alias_fallback(syntax, position, &new_name.display(db, edition).to_string());
135
136    let ops: RenameResult<Vec<SourceChange>> = match alias_fallback {
137        Some(_) => ok_if_any(
138            defs
139                // FIXME: This can use the `ide_db::rename_reference` (or def.rename) method once we can
140                // properly find "direct" usages/references.
141                .map(|(.., def, new_name, _)| {
142                    match kind {
143                        IdentifierKind::Ident => (),
144                        IdentifierKind::Lifetime => {
145                            bail!("Cannot alias reference to a lifetime identifier")
146                        }
147                        IdentifierKind::Underscore => bail!("Cannot alias reference to `_`"),
148                        IdentifierKind::LowercaseSelf => {
149                            bail!("Cannot rename alias reference to `self`")
150                        }
151                    };
152                    let mut usages = def.usages(&sema).all();
153
154                    // FIXME: hack - removes the usage that triggered this rename operation.
155                    match usages.references.get_mut(&file_id).and_then(|refs| {
156                        refs.iter()
157                            .position(|ref_| ref_.range.contains_inclusive(position.offset))
158                            .map(|idx| refs.remove(idx))
159                    }) {
160                        Some(_) => (),
161                        None => never!(),
162                    };
163
164                    let mut source_change = SourceChange::default();
165                    source_change.extend(usages.references.get_mut(&file_id).iter().map(|refs| {
166                        (
167                            position.file_id,
168                            source_edit_from_references(db, refs, def, &new_name, edition),
169                        )
170                    }));
171
172                    Ok(source_change)
173                }),
174        ),
175        None => ok_if_any(defs.map(|(.., def, new_name, rename_def)| {
176            if let Definition::Local(local) = def {
177                if let Some(self_param) = local.as_self_param(sema.db) {
178                    cov_mark::hit!(rename_self_to_param);
179                    return rename_self_to_param(
180                        &sema,
181                        local,
182                        self_param,
183                        &new_name,
184                        kind,
185                        config.find_path_config(),
186                    );
187                }
188                if kind == IdentifierKind::LowercaseSelf {
189                    cov_mark::hit!(rename_to_self);
190                    return rename_to_self(&sema, local);
191                }
192            }
193            def.rename(&sema, new_name.as_str(), rename_def)
194        })),
195    };
196
197    ops?.into_iter()
198        .chain(alias_fallback)
199        .reduce(|acc, elem| acc.merge(elem))
200        .ok_or_else(|| format_err!("No references found at position"))
201}
202
203/// Called by the client when it is about to rename a file.
204pub(crate) fn will_rename_file(
205    db: &RootDatabase,
206    file_id: FileId,
207    new_name_stem: &str,
208) -> Option<SourceChange> {
209    let sema = Semantics::new(db);
210    let module = sema.file_to_module_def(file_id)?;
211    let def = Definition::Module(module);
212    let mut change = def.rename(&sema, new_name_stem, RenameDefinition::Yes).ok()?;
213    change.file_system_edits.clear();
214    Some(change)
215}
216
217// FIXME: Should support `extern crate`.
218fn alias_fallback(
219    syntax: &SyntaxNode,
220    FilePosition { file_id, offset }: FilePosition,
221    new_name: &str,
222) -> Option<SourceChange> {
223    let use_tree = syntax
224        .token_at_offset(offset)
225        .flat_map(|syntax| syntax.parent_ancestors())
226        .find_map(ast::UseTree::cast)?;
227
228    let last_path_segment = use_tree.path()?.segments().last()?.name_ref()?;
229    if !last_path_segment.syntax().text_range().contains_inclusive(offset) {
230        return None;
231    };
232
233    let mut builder = SourceChangeBuilder::new(file_id);
234
235    match use_tree.rename() {
236        Some(rename) => {
237            let offset = rename.syntax().text_range();
238            builder.replace(offset, format!("as {new_name}"));
239        }
240        None => {
241            let offset = use_tree.syntax().text_range().end();
242            builder.insert(offset, format!(" as {new_name}"));
243        }
244    }
245
246    Some(builder.finish())
247}
248
249fn find_definitions(
250    sema: &Semantics<'_, RootDatabase>,
251    syntax: &SyntaxNode,
252    FilePosition { file_id, offset }: FilePosition,
253    new_name: &Name,
254) -> RenameResult<impl Iterator<Item = (FileRange, SyntaxKind, Definition, Name, RenameDefinition)>>
255{
256    let maybe_format_args =
257        syntax.token_at_offset(offset).find(|t| matches!(t.kind(), SyntaxKind::STRING));
258
259    if let Some((range, _, _, Some(resolution))) =
260        maybe_format_args.and_then(|token| sema.check_for_format_args_template(token, offset))
261    {
262        return Ok(vec![(
263            FileRange { file_id, range },
264            SyntaxKind::STRING,
265            Definition::from(resolution),
266            new_name.clone(),
267            RenameDefinition::Yes,
268        )]
269        .into_iter());
270    }
271
272    let original_ident = syntax
273        .token_at_offset(offset)
274        .max_by_key(|t| {
275            t.kind().is_any_identifier() || matches!(t.kind(), SyntaxKind::LIFETIME_IDENT)
276        })
277        .map(|t| {
278            if t.kind() == SyntaxKind::LIFETIME_IDENT {
279                Name::new_lifetime(t.text())
280            } else {
281                Name::new_root(t.text())
282            }
283        })
284        .ok_or_else(|| format_err!("No references found at position"))?;
285    let symbols =
286        sema.find_namelike_at_offset_with_descend(syntax, offset).map(|name_like| {
287            let kind = name_like.syntax().kind();
288            let range = sema
289                .original_range_opt(name_like.syntax())
290                .ok_or_else(|| format_err!("No references found at position"))?;
291            let res = match &name_like {
292                // renaming aliases would rename the item being aliased as the HIR doesn't track aliases yet
293                ast::NameLike::Name(name)
294                    if name
295                        .syntax()
296                        .parent().is_some_and(|it| ast::Rename::can_cast(it.kind()))
297                        // FIXME: uncomment this once we resolve to usages to extern crate declarations
298                        // && name
299                        //     .syntax()
300                        //     .ancestors()
301                        //     .nth(2)
302                        //     .map_or(true, |it| !ast::ExternCrate::can_cast(it.kind()))
303                        =>
304                {
305                    bail!("Renaming aliases is currently unsupported")
306                }
307                ast::NameLike::Name(name) => NameClass::classify(sema, name)
308                    .map(|class| match class {
309                        NameClass::Definition(it) | NameClass::ConstReference(it) => it,
310                        NameClass::PatFieldShorthand { local_def, field_ref: _, adt_subst: _ } => {
311                            Definition::Local(local_def)
312                        }
313                    })
314                    .ok_or_else(|| format_err!("No references found at position")),
315                ast::NameLike::NameRef(name_ref) => {
316                    NameRefClass::classify(sema, name_ref)
317                        .map(|class| match class {
318                            NameRefClass::Definition(def, _) => def,
319                            NameRefClass::FieldShorthand { local_ref, field_ref: _, adt_subst: _ } => {
320                                Definition::Local(local_ref)
321                            }
322                            NameRefClass::ExternCrateShorthand { decl, .. } => {
323                                Definition::ExternCrateDecl(decl)
324                            }
325                        })
326                        // FIXME: uncomment this once we resolve to usages to extern crate declarations
327                        .filter(|def| !matches!(def, Definition::ExternCrateDecl(..)))
328                        .ok_or_else(|| format_err!("No references found at position"))
329                        .and_then(|def| {
330                            // if the name differs from the definitions name it has to be an alias
331                            if def
332                                .name(sema.db).is_some_and(|it| it.as_str() != name_ref.text().trim_start_matches("r#"))
333                            {
334                                Err(format_err!("Renaming aliases is currently unsupported"))
335                            } else {
336                                Ok(def)
337                            }
338                        })
339                }
340                ast::NameLike::Lifetime(lifetime) => {
341                    NameRefClass::classify_lifetime(sema, lifetime)
342                        .and_then(|class| match class {
343                            NameRefClass::Definition(def, _) => Some(def),
344                            _ => None,
345                        })
346                        .or_else(|| {
347                            NameClass::classify_lifetime(sema, lifetime).and_then(|it| match it {
348                                NameClass::Definition(it) => Some(it),
349                                _ => None,
350                            })
351                        })
352                        .ok_or_else(|| format_err!("No references found at position"))
353                }
354            };
355            res.map(|def| {
356                let n = def.name(sema.db)?;
357                if n == original_ident {
358                    Some((range, kind, def, new_name.clone(), RenameDefinition::Yes))
359                } else if let Some(suffix) =  n.as_str().strip_prefix(original_ident.as_str()) {
360                    Some((range, kind, def, Name::new_root(&format!("{}{suffix}", new_name.as_str())), RenameDefinition::No))
361                } else {
362                     n.as_str().strip_suffix(original_ident.as_str().trim_start_matches('\''))
363                        .map(|prefix| (range, kind, def, Name::new_root(&format!("{prefix}{}", new_name.as_str())), RenameDefinition::No))
364                }
365            })
366        });
367
368    let res: RenameResult<Vec<_>> = ok_if_any(symbols.filter_map(Result::transpose));
369    match res {
370        Ok(v) => {
371            // remove duplicates, comparing `Definition`s
372            Ok(v.into_iter()
373                .unique_by(|&(.., def, _, _)| def)
374                .map(|(a, b, c, d, e)| (a.into_file_id(sema.db), b, c, d, e))
375                .collect::<Vec<_>>()
376                .into_iter())
377        }
378        Err(e) => Err(e),
379    }
380}
381
382fn transform_assoc_fn_into_method_call(
383    sema: &Semantics<'_, RootDatabase>,
384    source_change: &mut SourceChange,
385    f: hir::Function,
386) {
387    let calls = Definition::Function(f).usages(sema).all();
388    for (_file_id, calls) in calls {
389        for call in calls {
390            let Some(fn_name) = call.name.as_name_ref() else { continue };
391            let Some(path) = fn_name.syntax().parent().and_then(ast::PathSegment::cast) else {
392                continue;
393            };
394            let path = path.parent_path();
395            // The `PathExpr` is the direct parent, above it is the `CallExpr`.
396            let Some(call) =
397                path.syntax().parent().and_then(|it| ast::CallExpr::cast(it.parent()?))
398            else {
399                continue;
400            };
401
402            let Some(arg_list) = call.arg_list() else { continue };
403            let mut args = arg_list.args();
404            let Some(mut self_arg) = args.next() else { continue };
405            let second_arg = args.next();
406
407            // Strip (de)references, as they will be taken automatically by auto(de)ref.
408            loop {
409                let self_ = match &self_arg {
410                    ast::Expr::RefExpr(self_) => self_.expr(),
411                    ast::Expr::ParenExpr(self_) => self_.expr(),
412                    ast::Expr::PrefixExpr(self_)
413                        if self_.op_kind() == Some(ast::UnaryOp::Deref) =>
414                    {
415                        self_.expr()
416                    }
417                    _ => break,
418                };
419                self_arg = match self_ {
420                    Some(it) => it,
421                    None => break,
422                };
423            }
424
425            let self_needs_parens =
426                self_arg.precedence().needs_parentheses_in(ExprPrecedence::Postfix);
427
428            let replace_start = path.syntax().text_range().start();
429            let replace_end = match second_arg {
430                Some(second_arg) => second_arg.syntax().text_range().start(),
431                None => arg_list
432                    .r_paren_token()
433                    .map(|it| it.text_range().start())
434                    .unwrap_or_else(|| arg_list.syntax().text_range().end()),
435            };
436            let replace_range = TextRange::new(replace_start, replace_end);
437            let macro_file = sema.hir_file_for(fn_name.syntax());
438            let Some((replace_range, _)) =
439                InFile::new(macro_file, replace_range).original_node_file_range_opt(sema.db)
440            else {
441                continue;
442            };
443
444            let Some(macro_mapped_self) = sema.original_range_opt(self_arg.syntax()) else {
445                continue;
446            };
447            let mut replacement = String::new();
448            if self_needs_parens {
449                replacement.push('(');
450            }
451            replacement.push_str(macro_mapped_self.text(sema.db));
452            if self_needs_parens {
453                replacement.push(')');
454            }
455            replacement.push('.');
456            format_to!(replacement, "{fn_name}");
457            replacement.push('(');
458
459            source_change.insert_source_edit(
460                replace_range.file_id.file_id(sema.db),
461                TextEdit::replace(replace_range.range, replacement),
462            );
463        }
464    }
465}
466
467fn rename_to_self(
468    sema: &Semantics<'_, RootDatabase>,
469    local: hir::Local,
470) -> RenameResult<SourceChange> {
471    if never!(local.is_self(sema.db)) {
472        bail!("rename_to_self invoked on self");
473    }
474
475    let fn_def = match local.parent(sema.db) {
476        hir::DefWithBody::Function(func) => func,
477        _ => bail!("Cannot rename local to self outside of function"),
478    };
479
480    if fn_def.self_param(sema.db).is_some() {
481        bail!("Method already has a self parameter");
482    }
483
484    let params = fn_def.assoc_fn_params(sema.db);
485    let first_param = params
486        .first()
487        .ok_or_else(|| format_err!("Cannot rename local to self unless it is a parameter"))?;
488    match first_param.as_local(sema.db) {
489        Some(plocal) => {
490            if plocal != local {
491                bail!("Only the first parameter may be renamed to self");
492            }
493        }
494        None => bail!("rename_to_self invoked on destructuring parameter"),
495    }
496
497    let assoc_item = fn_def
498        .as_assoc_item(sema.db)
499        .ok_or_else(|| format_err!("Cannot rename parameter to self for free function"))?;
500    let impl_ = match assoc_item.container(sema.db) {
501        hir::AssocItemContainer::Trait(_) => {
502            bail!("Cannot rename parameter to self for trait functions");
503        }
504        hir::AssocItemContainer::Impl(impl_) => impl_,
505    };
506    let first_param_ty = first_param.ty();
507    let impl_ty = impl_.self_ty(sema.db);
508    let (ty, self_param) = if impl_ty.remove_ref().is_some() {
509        // if the impl is a ref to the type we can just match the `&T` with self directly
510        (first_param_ty.clone(), "self")
511    } else {
512        first_param_ty.remove_ref().map_or((first_param_ty.clone(), "self"), |ty| {
513            (ty, if first_param_ty.is_mutable_reference() { "&mut self" } else { "&self" })
514        })
515    };
516
517    if ty != impl_ty {
518        bail!("Parameter type differs from impl block type");
519    }
520
521    let InFile { file_id, value: param_source } = sema
522        .source(first_param.clone())
523        .ok_or_else(|| format_err!("No source for parameter found"))?;
524
525    let def = Definition::Local(local);
526    let usages = def.usages(sema).all();
527    let mut source_change = SourceChange::default();
528    source_change.extend(usages.iter().map(|(file_id, references)| {
529        (
530            file_id.file_id(sema.db),
531            source_edit_from_references(
532                sema.db,
533                references,
534                def,
535                &Name::new_symbol_root(sym::self_),
536                file_id.edition(sema.db),
537            ),
538        )
539    }));
540    source_change.insert_source_edit(
541        file_id.original_file(sema.db).file_id(sema.db),
542        TextEdit::replace(param_source.syntax().text_range(), String::from(self_param)),
543    );
544    transform_assoc_fn_into_method_call(sema, &mut source_change, fn_def);
545    Ok(source_change)
546}
547
548#[derive(Debug, Clone, Copy, PartialEq, Eq)]
549enum CallReceiverAdjust {
550    Deref,
551    Ref,
552    RefMut,
553    None,
554}
555
556fn method_to_assoc_fn_call_self_adjust(
557    sema: &Semantics<'_, RootDatabase>,
558    self_arg: &ast::Expr,
559) -> CallReceiverAdjust {
560    let mut result = CallReceiverAdjust::None;
561    let self_adjust = sema.expr_adjustments(self_arg);
562    if let Some(self_adjust) = self_adjust {
563        let mut i = 0;
564        while i < self_adjust.len() {
565            if matches!(self_adjust[i].kind, hir::Adjust::Deref(..))
566                && matches!(
567                    self_adjust.get(i + 1),
568                    Some(hir::Adjustment { kind: hir::Adjust::Borrow(..), .. })
569                )
570            {
571                // Deref then ref (reborrow), skip them.
572                i += 2;
573                continue;
574            }
575
576            match self_adjust[i].kind {
577                hir::Adjust::Deref(_) if result == CallReceiverAdjust::None => {
578                    // Autoref takes precedence over deref, because if given a `&Type` the compiler will deref
579                    // it automatically.
580                    result = CallReceiverAdjust::Deref;
581                }
582                hir::Adjust::Borrow(hir::AutoBorrow::Ref(mutability)) => {
583                    match (result, mutability) {
584                        (CallReceiverAdjust::RefMut, hir::Mutability::Shared) => {}
585                        (_, hir::Mutability::Mut) => result = CallReceiverAdjust::RefMut,
586                        (_, hir::Mutability::Shared) => result = CallReceiverAdjust::Ref,
587                    }
588                }
589                _ => {}
590            }
591
592            i += 1;
593        }
594    }
595    result
596}
597
598fn transform_method_call_into_assoc_fn(
599    sema: &Semantics<'_, RootDatabase>,
600    source_change: &mut SourceChange,
601    f: hir::Function,
602    find_path_config: FindPathConfig,
603) {
604    let calls = Definition::Function(f).usages(sema).all();
605    for (_file_id, calls) in calls {
606        for call in calls {
607            let Some(fn_name) = call.name.as_name_ref() else { continue };
608            let Some(method_call) = fn_name.syntax().parent().and_then(ast::MethodCallExpr::cast)
609            else {
610                continue;
611            };
612            let Some(mut self_arg) = method_call.receiver() else {
613                continue;
614            };
615
616            let Some(scope) = sema.scope(fn_name.syntax()) else {
617                continue;
618            };
619            let self_adjust = method_to_assoc_fn_call_self_adjust(sema, &self_arg);
620
621            // Strip parentheses, function arguments have higher precedence than any operator.
622            while let ast::Expr::ParenExpr(it) = &self_arg {
623                self_arg = match it.expr() {
624                    Some(it) => it,
625                    None => break,
626                };
627            }
628
629            let needs_comma = method_call.arg_list().is_some_and(|it| it.args().next().is_some());
630
631            let self_needs_parens = self_adjust != CallReceiverAdjust::None
632                && self_arg.precedence().needs_parentheses_in(ExprPrecedence::Prefix);
633
634            let replace_start = method_call.syntax().text_range().start();
635            let replace_end = method_call
636                .arg_list()
637                .and_then(|it| it.l_paren_token())
638                .map(|it| it.text_range().end())
639                .unwrap_or_else(|| method_call.syntax().text_range().end());
640            let replace_range = TextRange::new(replace_start, replace_end);
641            let macro_file = sema.hir_file_for(fn_name.syntax());
642            let Some((replace_range, _)) =
643                InFile::new(macro_file, replace_range).original_node_file_range_opt(sema.db)
644            else {
645                continue;
646            };
647
648            let fn_container_path = match f.container(sema.db) {
649                hir::ItemContainer::Trait(trait_) => {
650                    // FIXME: We always put it as `Trait::function`. Is it better to use `Type::function` (but
651                    // that could conflict with an inherent method)? Or maybe `<Type as Trait>::function`?
652                    // Or let the user decide?
653                    let Some(path) = scope.module().find_path(
654                        sema.db,
655                        hir::ItemInNs::Types(trait_.into()),
656                        find_path_config,
657                    ) else {
658                        continue;
659                    };
660                    path.display(sema.db, replace_range.file_id.edition(sema.db)).to_string()
661                }
662                hir::ItemContainer::Impl(impl_) => {
663                    let ty = impl_.self_ty(sema.db);
664                    match ty.as_adt() {
665                        Some(adt) => {
666                            let Some(path) = scope.module().find_path(
667                                sema.db,
668                                hir::ItemInNs::Types(adt.into()),
669                                find_path_config,
670                            ) else {
671                                continue;
672                            };
673                            path.display(sema.db, replace_range.file_id.edition(sema.db))
674                                .to_string()
675                        }
676                        None => {
677                            let Ok(mut ty) =
678                                ty.display_source_code(sema.db, scope.module().into(), false)
679                            else {
680                                continue;
681                            };
682                            ty.insert(0, '<');
683                            ty.push('>');
684                            ty
685                        }
686                    }
687                }
688                _ => continue,
689            };
690
691            let Some(macro_mapped_self) = sema.original_range_opt(self_arg.syntax()) else {
692                continue;
693            };
694            let mut replacement = String::new();
695            replacement.push_str(&fn_container_path);
696            replacement.push_str("::");
697            format_to!(replacement, "{fn_name}");
698            replacement.push('(');
699            replacement.push_str(match self_adjust {
700                CallReceiverAdjust::Deref => "*",
701                CallReceiverAdjust::Ref => "&",
702                CallReceiverAdjust::RefMut => "&mut ",
703                CallReceiverAdjust::None => "",
704            });
705            if self_needs_parens {
706                replacement.push('(');
707            }
708            replacement.push_str(macro_mapped_self.text(sema.db));
709            if self_needs_parens {
710                replacement.push(')');
711            }
712            if needs_comma {
713                replacement.push_str(", ");
714            }
715
716            source_change.insert_source_edit(
717                replace_range.file_id.file_id(sema.db),
718                TextEdit::replace(replace_range.range, replacement),
719            );
720        }
721    }
722}
723
724fn rename_self_to_param(
725    sema: &Semantics<'_, RootDatabase>,
726    local: hir::Local,
727    self_param: hir::SelfParam,
728    new_name: &Name,
729    identifier_kind: IdentifierKind,
730    find_path_config: FindPathConfig,
731) -> RenameResult<SourceChange> {
732    if identifier_kind == IdentifierKind::LowercaseSelf {
733        // Let's do nothing rather than complain.
734        cov_mark::hit!(rename_self_to_self);
735        return Ok(SourceChange::default());
736    }
737
738    let fn_def = match local.parent(sema.db) {
739        hir::DefWithBody::Function(func) => func,
740        _ => bail!("Cannot rename local to self outside of function"),
741    };
742
743    let InFile { file_id, value: self_param } =
744        sema.source(self_param).ok_or_else(|| format_err!("cannot find function source"))?;
745
746    let def = Definition::Local(local);
747    let usages = def.usages(sema).all();
748    let edit = text_edit_from_self_param(
749        &self_param,
750        new_name.display(sema.db, file_id.edition(sema.db)).to_string(),
751    )
752    .ok_or_else(|| format_err!("No target type found"))?;
753    if usages.len() > 1 && identifier_kind == IdentifierKind::Underscore {
754        bail!("Cannot rename reference to `_` as it is being referenced multiple times");
755    }
756    let mut source_change = SourceChange::default();
757    source_change.insert_source_edit(file_id.original_file(sema.db).file_id(sema.db), edit);
758    source_change.extend(usages.iter().map(|(file_id, references)| {
759        (
760            file_id.file_id(sema.db),
761            source_edit_from_references(
762                sema.db,
763                references,
764                def,
765                new_name,
766                file_id.edition(sema.db),
767            ),
768        )
769    }));
770    transform_method_call_into_assoc_fn(sema, &mut source_change, fn_def, find_path_config);
771    Ok(source_change)
772}
773
774fn text_edit_from_self_param(self_param: &ast::SelfParam, new_name: String) -> Option<TextEdit> {
775    let mut replacement_text = new_name;
776    replacement_text.push_str(": ");
777
778    if self_param.amp_token().is_some() {
779        replacement_text.push('&');
780    }
781    if let Some(lifetime) = self_param.lifetime() {
782        write!(replacement_text, "{lifetime} ").unwrap();
783    }
784    if self_param.amp_token().and(self_param.mut_token()).is_some() {
785        replacement_text.push_str("mut ");
786    }
787
788    replacement_text.push_str("Self");
789
790    Some(TextEdit::replace(self_param.syntax().text_range(), replacement_text))
791}
792
793#[cfg(test)]
794mod tests {
795    use expect_test::{Expect, expect};
796    use ide_db::source_change::SourceChange;
797    use ide_db::text_edit::TextEdit;
798    use itertools::Itertools;
799    use stdx::trim_indent;
800    use test_utils::assert_eq_text;
801
802    use crate::fixture;
803
804    use super::{RangeInfo, RenameConfig, RenameError};
805
806    const TEST_CONFIG: RenameConfig =
807        RenameConfig { prefer_no_std: false, prefer_prelude: true, prefer_absolute: false };
808
809    #[track_caller]
810    fn check(
811        new_name: &str,
812        #[rust_analyzer::rust_fixture] ra_fixture_before: &str,
813        #[rust_analyzer::rust_fixture] ra_fixture_after: &str,
814    ) {
815        let ra_fixture_after = &trim_indent(ra_fixture_after);
816        let (analysis, position) = fixture::position(ra_fixture_before);
817        if !ra_fixture_after.starts_with("error: ")
818            && let Err(err) = analysis.prepare_rename(position).unwrap()
819        {
820            panic!("Prepare rename to '{new_name}' was failed: {err}")
821        }
822        let rename_result = analysis
823            .rename(position, new_name, &TEST_CONFIG)
824            .unwrap_or_else(|err| panic!("Rename to '{new_name}' was cancelled: {err}"));
825        match rename_result {
826            Ok(source_change) => {
827                let mut text_edit_builder = TextEdit::builder();
828                let (&file_id, edit) = match source_change.source_file_edits.len() {
829                    0 => return,
830                    1 => source_change.source_file_edits.iter().next().unwrap(),
831                    _ => panic!(),
832                };
833                for indel in edit.0.iter() {
834                    text_edit_builder.replace(indel.delete, indel.insert.clone());
835                }
836                let mut result = analysis.file_text(file_id).unwrap().to_string();
837                text_edit_builder.finish().apply(&mut result);
838                assert_eq_text!(ra_fixture_after, &*result);
839            }
840            Err(err) => {
841                if ra_fixture_after.starts_with("error:") {
842                    let error_message =
843                        ra_fixture_after.chars().skip("error:".len()).collect::<String>();
844                    assert_eq!(error_message.trim(), err.to_string());
845                } else {
846                    panic!("Rename to '{new_name}' failed unexpectedly: {err}")
847                }
848            }
849        };
850    }
851
852    #[track_caller]
853    fn check_conflicts(new_name: &str, #[rust_analyzer::rust_fixture] ra_fixture: &str) {
854        let (analysis, position, conflicts) = fixture::annotations(ra_fixture);
855        let source_change = analysis.rename(position, new_name, &TEST_CONFIG).unwrap().unwrap();
856        let expected_conflicts = conflicts
857            .into_iter()
858            .map(|(file_range, _)| (file_range.file_id, file_range.range))
859            .sorted_unstable_by_key(|(file_id, range)| (*file_id, range.start()))
860            .collect_vec();
861        let found_conflicts = source_change
862            .source_file_edits
863            .iter()
864            .filter(|(_, (edit, _))| edit.change_annotation().is_some())
865            .flat_map(|(file_id, (edit, _))| {
866                edit.into_iter().map(move |edit| (*file_id, edit.delete))
867            })
868            .sorted_unstable_by_key(|(file_id, range)| (*file_id, range.start()))
869            .collect_vec();
870        assert_eq!(
871            expected_conflicts, found_conflicts,
872            "rename conflicts mismatch: {source_change:#?}"
873        );
874    }
875
876    fn check_expect(
877        new_name: &str,
878        #[rust_analyzer::rust_fixture] ra_fixture: &str,
879        expect: Expect,
880    ) {
881        let (analysis, position) = fixture::position(ra_fixture);
882        let source_change = analysis
883            .rename(position, new_name, &TEST_CONFIG)
884            .unwrap()
885            .expect("Expect returned a RenameError");
886        expect.assert_eq(&filter_expect(source_change))
887    }
888
889    fn check_expect_will_rename_file(
890        new_name: &str,
891        #[rust_analyzer::rust_fixture] ra_fixture: &str,
892        expect: Expect,
893    ) {
894        let (analysis, position) = fixture::position(ra_fixture);
895        let source_change = analysis
896            .will_rename_file(position.file_id, new_name)
897            .unwrap()
898            .expect("Expect returned a RenameError");
899        expect.assert_eq(&filter_expect(source_change))
900    }
901
902    fn check_prepare(#[rust_analyzer::rust_fixture] ra_fixture: &str, expect: Expect) {
903        let (analysis, position) = fixture::position(ra_fixture);
904        let result = analysis
905            .prepare_rename(position)
906            .unwrap_or_else(|err| panic!("PrepareRename was cancelled: {err}"));
907        match result {
908            Ok(RangeInfo { range, info: () }) => {
909                let source = analysis.file_text(position.file_id).unwrap();
910                expect.assert_eq(&format!("{range:?}: {}", &source[range]))
911            }
912            Err(RenameError(err)) => expect.assert_eq(&err),
913        };
914    }
915
916    fn filter_expect(source_change: SourceChange) -> String {
917        let source_file_edits = source_change
918            .source_file_edits
919            .into_iter()
920            .map(|(id, (text_edit, _))| (id, text_edit.into_iter().collect::<Vec<_>>()))
921            .collect::<Vec<_>>();
922
923        format!(
924            "source_file_edits: {:#?}\nfile_system_edits: {:#?}\n",
925            source_file_edits, source_change.file_system_edits
926        )
927    }
928
929    #[test]
930    fn rename_will_shadow() {
931        check_conflicts(
932            "new_name",
933            r#"
934fn foo() {
935    let mut new_name = 123;
936    let old_name$0 = 456;
937     // ^^^^^^^^
938    new_name = 789 + new_name;
939}
940        "#,
941        );
942    }
943
944    #[test]
945    fn rename_will_be_shadowed() {
946        check_conflicts(
947            "new_name",
948            r#"
949fn foo() {
950    let mut old_name$0 = 456;
951         // ^^^^^^^^
952    let new_name = 123;
953    old_name = 789 + old_name;
954 // ^^^^^^^^         ^^^^^^^^
955}
956        "#,
957        );
958    }
959
960    #[test]
961    fn test_prepare_rename_namelikes() {
962        check_prepare(r"fn name$0<'lifetime>() {}", expect![[r#"3..7: name"#]]);
963        check_prepare(r"fn name<'lifetime$0>() {}", expect![[r#"9..17: lifetime"#]]);
964        check_prepare(r"fn name<'lifetime>() { name$0(); }", expect![[r#"23..27: name"#]]);
965    }
966
967    #[test]
968    fn test_prepare_rename_in_macro() {
969        check_prepare(
970            r"macro_rules! foo {
971    ($ident:ident) => {
972        pub struct $ident;
973    }
974}
975foo!(Foo$0);",
976            expect![[r#"83..86: Foo"#]],
977        );
978    }
979
980    #[test]
981    fn test_prepare_rename_keyword() {
982        check_prepare(r"struct$0 Foo;", expect![[r#"No references found at position"#]]);
983    }
984
985    #[test]
986    fn test_prepare_rename_tuple_field() {
987        check_prepare(
988            r#"
989struct Foo(i32);
990
991fn baz() {
992    let mut x = Foo(4);
993    x.0$0 = 5;
994}
995"#,
996            expect![[r#"No references found at position"#]],
997        );
998    }
999
1000    #[test]
1001    fn test_prepare_rename_builtin() {
1002        check_prepare(
1003            r#"
1004fn foo() {
1005    let x: i32$0 = 0;
1006}
1007"#,
1008            expect![[r#"No references found at position"#]],
1009        );
1010    }
1011
1012    #[test]
1013    fn test_prepare_rename_self() {
1014        check_prepare(
1015            r#"
1016struct Foo {}
1017
1018impl Foo {
1019    fn foo(self) -> Self$0 {
1020        self
1021    }
1022}
1023"#,
1024            expect![[r#"No references found at position"#]],
1025        );
1026    }
1027
1028    #[test]
1029    fn test_rename_to_underscore() {
1030        check("_", r#"fn main() { let i$0 = 1; }"#, r#"fn main() { let _ = 1; }"#);
1031    }
1032
1033    #[test]
1034    fn test_rename_to_raw_identifier() {
1035        check("r#fn", r#"fn main() { let i$0 = 1; }"#, r#"fn main() { let r#fn = 1; }"#);
1036    }
1037
1038    #[test]
1039    fn test_rename_to_invalid_identifier1() {
1040        check(
1041            "invalid!",
1042            r#"fn main() { let i$0 = 1; }"#,
1043            "error: Invalid name `invalid!`: not an identifier",
1044        );
1045    }
1046
1047    #[test]
1048    fn test_rename_to_invalid_identifier2() {
1049        check(
1050            "multiple tokens",
1051            r#"fn main() { let i$0 = 1; }"#,
1052            "error: Invalid name `multiple tokens`: not an identifier",
1053        );
1054    }
1055
1056    #[test]
1057    fn test_rename_to_invalid_identifier3() {
1058        check(
1059            "super",
1060            r#"fn main() { let i$0 = 1; }"#,
1061            "error: Invalid name `super`: cannot rename to a keyword",
1062        );
1063    }
1064
1065    #[test]
1066    fn test_rename_to_invalid_identifier_lifetime() {
1067        cov_mark::check!(rename_not_an_ident_ref);
1068        check(
1069            "'foo",
1070            r#"fn main() { let i$0 = 1; }"#,
1071            "error: Invalid name `'foo`: not an identifier",
1072        );
1073    }
1074
1075    #[test]
1076    fn test_rename_to_invalid_identifier_lifetime2() {
1077        check(
1078            "_",
1079            r#"fn main<'a>(_: &'a$0 ()) {}"#,
1080            r#"error: Invalid name `_`: not a lifetime identifier"#,
1081        );
1082    }
1083
1084    #[test]
1085    fn test_rename_accepts_lifetime_without_apostrophe() {
1086        check("foo", r#"fn main<'a>(_: &'a$0 ()) {}"#, r#"fn main<'foo>(_: &'foo ()) {}"#);
1087    }
1088
1089    #[test]
1090    fn test_rename_to_underscore_invalid() {
1091        cov_mark::check!(rename_underscore_multiple);
1092        check(
1093            "_",
1094            r#"fn main(foo$0: ()) {foo;}"#,
1095            "error: Cannot rename reference to `_` as it is being referenced multiple times",
1096        );
1097    }
1098
1099    #[test]
1100    fn test_rename_mod_invalid() {
1101        check(
1102            "'foo",
1103            r#"mod foo$0 {}"#,
1104            "error: Invalid name `'foo`: cannot rename module to 'foo",
1105        );
1106    }
1107
1108    #[test]
1109    fn test_rename_mod_invalid_raw_ident() {
1110        check(
1111            "r#self",
1112            r#"mod foo$0 {}"#,
1113            "error: Invalid name `self`: cannot rename module to self",
1114        );
1115    }
1116
1117    #[test]
1118    fn test_rename_for_local() {
1119        check(
1120            "k",
1121            r#"
1122fn main() {
1123    let mut i = 1;
1124    let j = 1;
1125    i = i$0 + j;
1126
1127    { i = 0; }
1128
1129    i = 5;
1130}
1131"#,
1132            r#"
1133fn main() {
1134    let mut k = 1;
1135    let j = 1;
1136    k = k + j;
1137
1138    { k = 0; }
1139
1140    k = 5;
1141}
1142"#,
1143        );
1144    }
1145
1146    #[test]
1147    fn test_rename_unresolved_reference() {
1148        check(
1149            "new_name",
1150            r#"fn main() { let _ = unresolved_ref$0; }"#,
1151            "error: No references found at position",
1152        );
1153    }
1154
1155    #[test]
1156    fn test_rename_macro_multiple_occurrences() {
1157        check(
1158            "Baaah",
1159            r#"macro_rules! foo {
1160    ($ident:ident) => {
1161        const $ident: () = ();
1162        struct $ident {}
1163    };
1164}
1165
1166foo!($0Foo);
1167const _: () = Foo;
1168const _: Foo = Foo {};
1169    "#,
1170            r#"
1171macro_rules! foo {
1172    ($ident:ident) => {
1173        const $ident: () = ();
1174        struct $ident {}
1175    };
1176}
1177
1178foo!(Baaah);
1179const _: () = Baaah;
1180const _: Baaah = Baaah {};
1181    "#,
1182        )
1183    }
1184
1185    #[test]
1186    fn test_rename_for_macro_args() {
1187        check(
1188            "b",
1189            r#"
1190macro_rules! foo {($i:ident) => {$i} }
1191fn main() {
1192    let a$0 = "test";
1193    foo!(a);
1194}
1195"#,
1196            r#"
1197macro_rules! foo {($i:ident) => {$i} }
1198fn main() {
1199    let b = "test";
1200    foo!(b);
1201}
1202"#,
1203        );
1204    }
1205
1206    #[test]
1207    fn test_rename_for_macro_args_rev() {
1208        check(
1209            "b",
1210            r#"
1211macro_rules! foo {($i:ident) => {$i} }
1212fn main() {
1213    let a = "test";
1214    foo!(a$0);
1215}
1216"#,
1217            r#"
1218macro_rules! foo {($i:ident) => {$i} }
1219fn main() {
1220    let b = "test";
1221    foo!(b);
1222}
1223"#,
1224        );
1225    }
1226
1227    #[test]
1228    fn test_rename_for_macro_define_fn() {
1229        check(
1230            "bar",
1231            r#"
1232macro_rules! define_fn {($id:ident) => { fn $id{} }}
1233define_fn!(foo);
1234fn main() {
1235    fo$0o();
1236}
1237"#,
1238            r#"
1239macro_rules! define_fn {($id:ident) => { fn $id{} }}
1240define_fn!(bar);
1241fn main() {
1242    bar();
1243}
1244"#,
1245        );
1246    }
1247
1248    #[test]
1249    fn test_rename_for_macro_define_fn_rev() {
1250        check(
1251            "bar",
1252            r#"
1253macro_rules! define_fn {($id:ident) => { fn $id{} }}
1254define_fn!(fo$0o);
1255fn main() {
1256    foo();
1257}
1258"#,
1259            r#"
1260macro_rules! define_fn {($id:ident) => { fn $id{} }}
1261define_fn!(bar);
1262fn main() {
1263    bar();
1264}
1265"#,
1266        );
1267    }
1268
1269    #[test]
1270    fn test_rename_for_param_inside() {
1271        check("j", r#"fn foo(i : u32) -> u32 { i$0 }"#, r#"fn foo(j : u32) -> u32 { j }"#);
1272    }
1273
1274    #[test]
1275    fn test_rename_refs_for_fn_param() {
1276        check("j", r#"fn foo(i$0 : u32) -> u32 { i }"#, r#"fn foo(j : u32) -> u32 { j }"#);
1277    }
1278
1279    #[test]
1280    fn test_rename_for_mut_param() {
1281        check("j", r#"fn foo(mut i$0 : u32) -> u32 { i }"#, r#"fn foo(mut j : u32) -> u32 { j }"#);
1282    }
1283
1284    #[test]
1285    fn test_rename_struct_field() {
1286        check(
1287            "foo",
1288            r#"
1289struct Foo { field$0: i32 }
1290
1291impl Foo {
1292    fn new(i: i32) -> Self {
1293        Self { field: i }
1294    }
1295}
1296"#,
1297            r#"
1298struct Foo { foo: i32 }
1299
1300impl Foo {
1301    fn new(i: i32) -> Self {
1302        Self { foo: i }
1303    }
1304}
1305"#,
1306        );
1307    }
1308
1309    #[test]
1310    fn test_rename_field_in_field_shorthand() {
1311        cov_mark::check!(test_rename_field_in_field_shorthand);
1312        check(
1313            "field",
1314            r#"
1315struct Foo { foo$0: i32 }
1316
1317impl Foo {
1318    fn new(foo: i32) -> Self {
1319        Self { foo }
1320    }
1321}
1322"#,
1323            r#"
1324struct Foo { field: i32 }
1325
1326impl Foo {
1327    fn new(foo: i32) -> Self {
1328        Self { field: foo }
1329    }
1330}
1331"#,
1332        );
1333    }
1334
1335    #[test]
1336    fn test_rename_local_in_field_shorthand() {
1337        cov_mark::check!(test_rename_local_in_field_shorthand);
1338        check(
1339            "j",
1340            r#"
1341struct Foo { i: i32 }
1342
1343impl Foo {
1344    fn new(i$0: i32) -> Self {
1345        Self { i }
1346    }
1347}
1348"#,
1349            r#"
1350struct Foo { i: i32 }
1351
1352impl Foo {
1353    fn new(j: i32) -> Self {
1354        Self { i: j }
1355    }
1356}
1357"#,
1358        );
1359    }
1360
1361    #[test]
1362    fn test_field_shorthand_correct_struct() {
1363        check(
1364            "j",
1365            r#"
1366struct Foo { i$0: i32 }
1367struct Bar { i: i32 }
1368
1369impl Bar {
1370    fn new(i: i32) -> Self {
1371        Self { i }
1372    }
1373}
1374"#,
1375            r#"
1376struct Foo { j: i32 }
1377struct Bar { i: i32 }
1378
1379impl Bar {
1380    fn new(i: i32) -> Self {
1381        Self { i }
1382    }
1383}
1384"#,
1385        );
1386    }
1387
1388    #[test]
1389    fn test_shadow_local_for_struct_shorthand() {
1390        check(
1391            "j",
1392            r#"
1393struct Foo { i: i32 }
1394
1395fn baz(i$0: i32) -> Self {
1396     let x = Foo { i };
1397     {
1398         let i = 0;
1399         Foo { i }
1400     }
1401}
1402"#,
1403            r#"
1404struct Foo { i: i32 }
1405
1406fn baz(j: i32) -> Self {
1407     let x = Foo { i: j };
1408     {
1409         let i = 0;
1410         Foo { i }
1411     }
1412}
1413"#,
1414        );
1415    }
1416
1417    #[test]
1418    fn test_rename_mod() {
1419        check_expect(
1420            "foo2",
1421            r#"
1422//- /lib.rs
1423mod bar;
1424
1425//- /bar.rs
1426mod foo$0;
1427
1428//- /bar/foo.rs
1429// empty
1430"#,
1431            expect![[r#"
1432                source_file_edits: [
1433                    (
1434                        FileId(
1435                            1,
1436                        ),
1437                        [
1438                            Indel {
1439                                insert: "foo2",
1440                                delete: 4..7,
1441                            },
1442                        ],
1443                    ),
1444                ]
1445                file_system_edits: [
1446                    MoveFile {
1447                        src: FileId(
1448                            2,
1449                        ),
1450                        dst: AnchoredPathBuf {
1451                            anchor: FileId(
1452                                2,
1453                            ),
1454                            path: "foo2.rs",
1455                        },
1456                    },
1457                ]
1458            "#]],
1459        );
1460    }
1461
1462    #[test]
1463    fn test_rename_mod_in_use_tree() {
1464        check_expect(
1465            "quux",
1466            r#"
1467//- /main.rs
1468pub mod foo;
1469pub mod bar;
1470fn main() {}
1471
1472//- /foo.rs
1473pub struct FooContent;
1474
1475//- /bar.rs
1476use crate::foo$0::FooContent;
1477"#,
1478            expect![[r#"
1479                source_file_edits: [
1480                    (
1481                        FileId(
1482                            0,
1483                        ),
1484                        [
1485                            Indel {
1486                                insert: "quux",
1487                                delete: 8..11,
1488                            },
1489                        ],
1490                    ),
1491                    (
1492                        FileId(
1493                            2,
1494                        ),
1495                        [
1496                            Indel {
1497                                insert: "quux",
1498                                delete: 11..14,
1499                            },
1500                        ],
1501                    ),
1502                ]
1503                file_system_edits: [
1504                    MoveFile {
1505                        src: FileId(
1506                            1,
1507                        ),
1508                        dst: AnchoredPathBuf {
1509                            anchor: FileId(
1510                                1,
1511                            ),
1512                            path: "quux.rs",
1513                        },
1514                    },
1515                ]
1516            "#]],
1517        );
1518    }
1519
1520    #[test]
1521    fn test_rename_mod_in_dir() {
1522        check_expect(
1523            "foo2",
1524            r#"
1525//- /lib.rs
1526mod fo$0o;
1527//- /foo/mod.rs
1528// empty
1529"#,
1530            expect![[r#"
1531                source_file_edits: [
1532                    (
1533                        FileId(
1534                            0,
1535                        ),
1536                        [
1537                            Indel {
1538                                insert: "foo2",
1539                                delete: 4..7,
1540                            },
1541                        ],
1542                    ),
1543                ]
1544                file_system_edits: [
1545                    MoveDir {
1546                        src: AnchoredPathBuf {
1547                            anchor: FileId(
1548                                1,
1549                            ),
1550                            path: "../foo",
1551                        },
1552                        src_id: FileId(
1553                            1,
1554                        ),
1555                        dst: AnchoredPathBuf {
1556                            anchor: FileId(
1557                                1,
1558                            ),
1559                            path: "../foo2",
1560                        },
1561                    },
1562                ]
1563            "#]],
1564        );
1565    }
1566
1567    #[test]
1568    fn test_rename_unusually_nested_mod() {
1569        check_expect(
1570            "bar",
1571            r#"
1572//- /lib.rs
1573mod outer { mod fo$0o; }
1574
1575//- /outer/foo.rs
1576// empty
1577"#,
1578            expect![[r#"
1579                source_file_edits: [
1580                    (
1581                        FileId(
1582                            0,
1583                        ),
1584                        [
1585                            Indel {
1586                                insert: "bar",
1587                                delete: 16..19,
1588                            },
1589                        ],
1590                    ),
1591                ]
1592                file_system_edits: [
1593                    MoveFile {
1594                        src: FileId(
1595                            1,
1596                        ),
1597                        dst: AnchoredPathBuf {
1598                            anchor: FileId(
1599                                1,
1600                            ),
1601                            path: "bar.rs",
1602                        },
1603                    },
1604                ]
1605            "#]],
1606        );
1607    }
1608
1609    #[test]
1610    fn test_module_rename_in_path() {
1611        check(
1612            "baz",
1613            r#"
1614mod $0foo {
1615    pub use self::bar as qux;
1616    pub fn bar() {}
1617}
1618
1619fn main() { foo::bar(); }
1620"#,
1621            r#"
1622mod baz {
1623    pub use self::bar as qux;
1624    pub fn bar() {}
1625}
1626
1627fn main() { baz::bar(); }
1628"#,
1629        );
1630    }
1631
1632    #[test]
1633    fn test_rename_mod_filename_and_path() {
1634        check_expect(
1635            "foo2",
1636            r#"
1637//- /lib.rs
1638mod bar;
1639fn f() {
1640    bar::foo::fun()
1641}
1642
1643//- /bar.rs
1644pub mod foo$0;
1645
1646//- /bar/foo.rs
1647// pub fn fun() {}
1648"#,
1649            expect![[r#"
1650                source_file_edits: [
1651                    (
1652                        FileId(
1653                            0,
1654                        ),
1655                        [
1656                            Indel {
1657                                insert: "foo2",
1658                                delete: 27..30,
1659                            },
1660                        ],
1661                    ),
1662                    (
1663                        FileId(
1664                            1,
1665                        ),
1666                        [
1667                            Indel {
1668                                insert: "foo2",
1669                                delete: 8..11,
1670                            },
1671                        ],
1672                    ),
1673                ]
1674                file_system_edits: [
1675                    MoveFile {
1676                        src: FileId(
1677                            2,
1678                        ),
1679                        dst: AnchoredPathBuf {
1680                            anchor: FileId(
1681                                2,
1682                            ),
1683                            path: "foo2.rs",
1684                        },
1685                    },
1686                ]
1687            "#]],
1688        );
1689    }
1690
1691    #[test]
1692    fn test_rename_mod_recursive() {
1693        check_expect(
1694            "foo2",
1695            r#"
1696//- /lib.rs
1697mod foo$0;
1698
1699//- /foo.rs
1700mod bar;
1701mod corge;
1702
1703//- /foo/bar.rs
1704mod qux;
1705
1706//- /foo/bar/qux.rs
1707mod quux;
1708
1709//- /foo/bar/qux/quux/mod.rs
1710// empty
1711
1712//- /foo/corge.rs
1713// empty
1714"#,
1715            expect![[r#"
1716                source_file_edits: [
1717                    (
1718                        FileId(
1719                            0,
1720                        ),
1721                        [
1722                            Indel {
1723                                insert: "foo2",
1724                                delete: 4..7,
1725                            },
1726                        ],
1727                    ),
1728                ]
1729                file_system_edits: [
1730                    MoveFile {
1731                        src: FileId(
1732                            1,
1733                        ),
1734                        dst: AnchoredPathBuf {
1735                            anchor: FileId(
1736                                1,
1737                            ),
1738                            path: "foo2.rs",
1739                        },
1740                    },
1741                    MoveDir {
1742                        src: AnchoredPathBuf {
1743                            anchor: FileId(
1744                                1,
1745                            ),
1746                            path: "foo",
1747                        },
1748                        src_id: FileId(
1749                            1,
1750                        ),
1751                        dst: AnchoredPathBuf {
1752                            anchor: FileId(
1753                                1,
1754                            ),
1755                            path: "foo2",
1756                        },
1757                    },
1758                ]
1759            "#]],
1760        )
1761    }
1762    #[test]
1763    fn test_rename_mod_ref_by_super() {
1764        check(
1765            "baz",
1766            r#"
1767        mod $0foo {
1768        struct X;
1769
1770        mod bar {
1771            use super::X;
1772        }
1773    }
1774            "#,
1775            r#"
1776        mod baz {
1777        struct X;
1778
1779        mod bar {
1780            use super::X;
1781        }
1782    }
1783            "#,
1784        )
1785    }
1786
1787    #[test]
1788    fn test_rename_mod_in_macro() {
1789        check(
1790            "bar",
1791            r#"
1792//- /foo.rs
1793
1794//- /lib.rs
1795macro_rules! submodule {
1796    ($name:ident) => {
1797        mod $name;
1798    };
1799}
1800
1801submodule!($0foo);
1802"#,
1803            r#"
1804macro_rules! submodule {
1805    ($name:ident) => {
1806        mod $name;
1807    };
1808}
1809
1810submodule!(bar);
1811"#,
1812        )
1813    }
1814
1815    #[test]
1816    fn test_rename_mod_for_crate_root() {
1817        check_expect_will_rename_file(
1818            "main",
1819            r#"
1820//- /lib.rs
1821use crate::foo as bar;
1822fn foo() {}
1823mod bar$0;
1824"#,
1825            expect![[r#"
1826                source_file_edits: []
1827                file_system_edits: []
1828            "#]],
1829        )
1830    }
1831
1832    #[test]
1833    fn test_rename_mod_to_raw_ident() {
1834        check_expect(
1835            "r#fn",
1836            r#"
1837//- /lib.rs
1838mod foo$0;
1839
1840fn main() { foo::bar::baz(); }
1841
1842//- /foo.rs
1843pub mod bar;
1844
1845//- /foo/bar.rs
1846pub fn baz() {}
1847"#,
1848            expect![[r#"
1849                source_file_edits: [
1850                    (
1851                        FileId(
1852                            0,
1853                        ),
1854                        [
1855                            Indel {
1856                                insert: "r#fn",
1857                                delete: 4..7,
1858                            },
1859                            Indel {
1860                                insert: "r#fn",
1861                                delete: 22..25,
1862                            },
1863                        ],
1864                    ),
1865                ]
1866                file_system_edits: [
1867                    MoveFile {
1868                        src: FileId(
1869                            1,
1870                        ),
1871                        dst: AnchoredPathBuf {
1872                            anchor: FileId(
1873                                1,
1874                            ),
1875                            path: "fn.rs",
1876                        },
1877                    },
1878                    MoveDir {
1879                        src: AnchoredPathBuf {
1880                            anchor: FileId(
1881                                1,
1882                            ),
1883                            path: "foo",
1884                        },
1885                        src_id: FileId(
1886                            1,
1887                        ),
1888                        dst: AnchoredPathBuf {
1889                            anchor: FileId(
1890                                1,
1891                            ),
1892                            path: "fn",
1893                        },
1894                    },
1895                ]
1896            "#]],
1897        );
1898    }
1899
1900    #[test]
1901    fn test_rename_mod_from_raw_ident() {
1902        check_expect(
1903            "foo",
1904            r#"
1905//- /lib.rs
1906mod r#fn$0;
1907
1908fn main() { r#fn::bar::baz(); }
1909
1910//- /fn.rs
1911pub mod bar;
1912
1913//- /fn/bar.rs
1914pub fn baz() {}
1915"#,
1916            expect![[r#"
1917                source_file_edits: [
1918                    (
1919                        FileId(
1920                            0,
1921                        ),
1922                        [
1923                            Indel {
1924                                insert: "foo",
1925                                delete: 4..8,
1926                            },
1927                            Indel {
1928                                insert: "foo",
1929                                delete: 23..27,
1930                            },
1931                        ],
1932                    ),
1933                ]
1934                file_system_edits: [
1935                    MoveFile {
1936                        src: FileId(
1937                            1,
1938                        ),
1939                        dst: AnchoredPathBuf {
1940                            anchor: FileId(
1941                                1,
1942                            ),
1943                            path: "foo.rs",
1944                        },
1945                    },
1946                    MoveDir {
1947                        src: AnchoredPathBuf {
1948                            anchor: FileId(
1949                                1,
1950                            ),
1951                            path: "fn",
1952                        },
1953                        src_id: FileId(
1954                            1,
1955                        ),
1956                        dst: AnchoredPathBuf {
1957                            anchor: FileId(
1958                                1,
1959                            ),
1960                            path: "foo",
1961                        },
1962                    },
1963                ]
1964            "#]],
1965        );
1966    }
1967
1968    #[test]
1969    fn test_rename_each_usage_gets_appropriate_rawness() {
1970        check_expect(
1971            "dyn",
1972            r#"
1973//- /a.rs crate:a edition:2015
1974pub fn foo() {}
1975
1976//- /b.rs crate:b edition:2018 deps:a new_source_root:local
1977fn bar() {
1978    a::foo$0();
1979}
1980    "#,
1981            expect![[r#"
1982                source_file_edits: [
1983                    (
1984                        FileId(
1985                            0,
1986                        ),
1987                        [
1988                            Indel {
1989                                insert: "dyn",
1990                                delete: 7..10,
1991                            },
1992                        ],
1993                    ),
1994                    (
1995                        FileId(
1996                            1,
1997                        ),
1998                        [
1999                            Indel {
2000                                insert: "r#dyn",
2001                                delete: 18..21,
2002                            },
2003                        ],
2004                    ),
2005                ]
2006                file_system_edits: []
2007            "#]],
2008        );
2009
2010        check_expect(
2011            "dyn",
2012            r#"
2013//- /a.rs crate:a edition:2018
2014pub fn foo() {}
2015
2016//- /b.rs crate:b edition:2015 deps:a new_source_root:local
2017fn bar() {
2018    a::foo$0();
2019}
2020    "#,
2021            expect![[r#"
2022                source_file_edits: [
2023                    (
2024                        FileId(
2025                            0,
2026                        ),
2027                        [
2028                            Indel {
2029                                insert: "r#dyn",
2030                                delete: 7..10,
2031                            },
2032                        ],
2033                    ),
2034                    (
2035                        FileId(
2036                            1,
2037                        ),
2038                        [
2039                            Indel {
2040                                insert: "dyn",
2041                                delete: 18..21,
2042                            },
2043                        ],
2044                    ),
2045                ]
2046                file_system_edits: []
2047            "#]],
2048        );
2049
2050        check_expect(
2051            "r#dyn",
2052            r#"
2053//- /a.rs crate:a edition:2018
2054pub fn foo$0() {}
2055
2056//- /b.rs crate:b edition:2015 deps:a new_source_root:local
2057fn bar() {
2058    a::foo();
2059}
2060    "#,
2061            expect![[r#"
2062                source_file_edits: [
2063                    (
2064                        FileId(
2065                            0,
2066                        ),
2067                        [
2068                            Indel {
2069                                insert: "r#dyn",
2070                                delete: 7..10,
2071                            },
2072                        ],
2073                    ),
2074                    (
2075                        FileId(
2076                            1,
2077                        ),
2078                        [
2079                            Indel {
2080                                insert: "dyn",
2081                                delete: 18..21,
2082                            },
2083                        ],
2084                    ),
2085                ]
2086                file_system_edits: []
2087            "#]],
2088        );
2089    }
2090
2091    #[test]
2092    fn rename_raw_identifier() {
2093        check_expect(
2094            "abc",
2095            r#"
2096//- /a.rs crate:a edition:2015
2097pub fn dyn() {}
2098
2099fn foo() {
2100    dyn$0();
2101}
2102
2103//- /b.rs crate:b edition:2018 deps:a new_source_root:local
2104fn bar() {
2105    a::r#dyn();
2106}
2107    "#,
2108            expect![[r#"
2109                source_file_edits: [
2110                    (
2111                        FileId(
2112                            0,
2113                        ),
2114                        [
2115                            Indel {
2116                                insert: "abc",
2117                                delete: 7..10,
2118                            },
2119                            Indel {
2120                                insert: "abc",
2121                                delete: 32..35,
2122                            },
2123                        ],
2124                    ),
2125                    (
2126                        FileId(
2127                            1,
2128                        ),
2129                        [
2130                            Indel {
2131                                insert: "abc",
2132                                delete: 18..23,
2133                            },
2134                        ],
2135                    ),
2136                ]
2137                file_system_edits: []
2138            "#]],
2139        );
2140
2141        check_expect(
2142            "abc",
2143            r#"
2144//- /a.rs crate:a edition:2018
2145pub fn r#dyn() {}
2146
2147fn foo() {
2148    r#dyn$0();
2149}
2150
2151//- /b.rs crate:b edition:2015 deps:a new_source_root:local
2152fn bar() {
2153    a::dyn();
2154}
2155    "#,
2156            expect![[r#"
2157                source_file_edits: [
2158                    (
2159                        FileId(
2160                            0,
2161                        ),
2162                        [
2163                            Indel {
2164                                insert: "abc",
2165                                delete: 7..12,
2166                            },
2167                            Indel {
2168                                insert: "abc",
2169                                delete: 34..39,
2170                            },
2171                        ],
2172                    ),
2173                    (
2174                        FileId(
2175                            1,
2176                        ),
2177                        [
2178                            Indel {
2179                                insert: "abc",
2180                                delete: 18..21,
2181                            },
2182                        ],
2183                    ),
2184                ]
2185                file_system_edits: []
2186            "#]],
2187        );
2188    }
2189
2190    #[test]
2191    fn test_enum_variant_from_module_1() {
2192        cov_mark::check!(rename_non_local);
2193        check(
2194            "Baz",
2195            r#"
2196mod foo {
2197    pub enum Foo { Bar$0 }
2198}
2199
2200fn func(f: foo::Foo) {
2201    match f {
2202        foo::Foo::Bar => {}
2203    }
2204}
2205"#,
2206            r#"
2207mod foo {
2208    pub enum Foo { Baz }
2209}
2210
2211fn func(f: foo::Foo) {
2212    match f {
2213        foo::Foo::Baz => {}
2214    }
2215}
2216"#,
2217        );
2218    }
2219
2220    #[test]
2221    fn test_enum_variant_from_module_2() {
2222        check(
2223            "baz",
2224            r#"
2225mod foo {
2226    pub struct Foo { pub bar$0: uint }
2227}
2228
2229fn foo(f: foo::Foo) {
2230    let _ = f.bar;
2231}
2232"#,
2233            r#"
2234mod foo {
2235    pub struct Foo { pub baz: uint }
2236}
2237
2238fn foo(f: foo::Foo) {
2239    let _ = f.baz;
2240}
2241"#,
2242        );
2243    }
2244
2245    #[test]
2246    fn test_parameter_to_self() {
2247        cov_mark::check!(rename_to_self);
2248        check(
2249            "self",
2250            r#"
2251struct Foo { i: i32 }
2252
2253impl Foo {
2254    fn f(foo$0: &mut Foo) -> i32 {
2255        foo.i
2256    }
2257}
2258"#,
2259            r#"
2260struct Foo { i: i32 }
2261
2262impl Foo {
2263    fn f(&mut self) -> i32 {
2264        self.i
2265    }
2266}
2267"#,
2268        );
2269        check(
2270            "self",
2271            r#"
2272struct Foo { i: i32 }
2273
2274impl Foo {
2275    fn f(foo$0: Foo) -> i32 {
2276        foo.i
2277    }
2278}
2279"#,
2280            r#"
2281struct Foo { i: i32 }
2282
2283impl Foo {
2284    fn f(self) -> i32 {
2285        self.i
2286    }
2287}
2288"#,
2289        );
2290    }
2291
2292    #[test]
2293    fn test_parameter_to_self_error_no_impl() {
2294        check(
2295            "self",
2296            r#"
2297struct Foo { i: i32 }
2298
2299fn f(foo$0: &mut Foo) -> i32 {
2300    foo.i
2301}
2302"#,
2303            "error: Cannot rename parameter to self for free function",
2304        );
2305        check(
2306            "self",
2307            r#"
2308struct Foo { i: i32 }
2309struct Bar;
2310
2311impl Bar {
2312    fn f(foo$0: &mut Foo) -> i32 {
2313        foo.i
2314    }
2315}
2316"#,
2317            "error: Parameter type differs from impl block type",
2318        );
2319    }
2320
2321    #[test]
2322    fn test_parameter_to_self_error_not_first() {
2323        check(
2324            "self",
2325            r#"
2326struct Foo { i: i32 }
2327impl Foo {
2328    fn f(x: (), foo$0: &mut Foo) -> i32 {
2329        foo.i
2330    }
2331}
2332"#,
2333            "error: Only the first parameter may be renamed to self",
2334        );
2335    }
2336
2337    #[test]
2338    fn test_parameter_to_self_impl_ref() {
2339        check(
2340            "self",
2341            r#"
2342struct Foo { i: i32 }
2343impl &Foo {
2344    fn f(foo$0: &Foo) -> i32 {
2345        foo.i
2346    }
2347}
2348"#,
2349            r#"
2350struct Foo { i: i32 }
2351impl &Foo {
2352    fn f(self) -> i32 {
2353        self.i
2354    }
2355}
2356"#,
2357        );
2358    }
2359
2360    #[test]
2361    fn test_self_to_parameter() {
2362        check(
2363            "foo",
2364            r#"
2365struct Foo { i: i32 }
2366
2367impl Foo {
2368    fn f(&mut $0self) -> i32 {
2369        self.i
2370    }
2371}
2372"#,
2373            r#"
2374struct Foo { i: i32 }
2375
2376impl Foo {
2377    fn f(foo: &mut Self) -> i32 {
2378        foo.i
2379    }
2380}
2381"#,
2382        );
2383    }
2384
2385    #[test]
2386    fn test_owned_self_to_parameter() {
2387        cov_mark::check!(rename_self_to_param);
2388        check(
2389            "foo",
2390            r#"
2391struct Foo { i: i32 }
2392
2393impl Foo {
2394    fn f($0self) -> i32 {
2395        self.i
2396    }
2397}
2398"#,
2399            r#"
2400struct Foo { i: i32 }
2401
2402impl Foo {
2403    fn f(foo: Self) -> i32 {
2404        foo.i
2405    }
2406}
2407"#,
2408        );
2409    }
2410
2411    #[test]
2412    fn test_owned_self_to_parameter_with_lifetime() {
2413        cov_mark::check!(rename_self_to_param);
2414        check(
2415            "foo",
2416            r#"
2417struct Foo<'a> { i: &'a i32 }
2418
2419impl<'a> Foo<'a> {
2420    fn f(&'a $0self) -> i32 {
2421        self.i
2422    }
2423}
2424"#,
2425            r#"
2426struct Foo<'a> { i: &'a i32 }
2427
2428impl<'a> Foo<'a> {
2429    fn f(foo: &'a Self) -> i32 {
2430        foo.i
2431    }
2432}
2433"#,
2434        );
2435    }
2436
2437    #[test]
2438    fn test_self_outside_of_methods() {
2439        check(
2440            "foo",
2441            r#"
2442fn f($0self) -> i32 {
2443    self.i
2444}
2445"#,
2446            r#"
2447fn f(foo: Self) -> i32 {
2448    foo.i
2449}
2450"#,
2451        );
2452    }
2453
2454    #[test]
2455    fn no_type_value_ns_confuse() {
2456        // Test that we don't rename items from different namespaces.
2457        check(
2458            "bar",
2459            r#"
2460struct foo {}
2461fn f(foo$0: i32) -> i32 {
2462    use foo as _;
2463}
2464"#,
2465            r#"
2466struct foo {}
2467fn f(bar: i32) -> i32 {
2468    use foo as _;
2469}
2470"#,
2471        );
2472    }
2473
2474    #[test]
2475    fn test_self_in_path_to_parameter() {
2476        check(
2477            "foo",
2478            r#"
2479struct Foo { i: i32 }
2480
2481impl Foo {
2482    fn f(&self) -> i32 {
2483        let self_var = 1;
2484        self$0.i
2485    }
2486}
2487"#,
2488            r#"
2489struct Foo { i: i32 }
2490
2491impl Foo {
2492    fn f(foo: &Self) -> i32 {
2493        let self_var = 1;
2494        foo.i
2495    }
2496}
2497"#,
2498        );
2499    }
2500
2501    #[test]
2502    fn test_rename_field_put_init_shorthand() {
2503        cov_mark::check!(test_rename_field_put_init_shorthand);
2504        check(
2505            "bar",
2506            r#"
2507struct Foo { i$0: i32 }
2508
2509fn foo(bar: i32) -> Foo {
2510    Foo { i: bar }
2511}
2512"#,
2513            r#"
2514struct Foo { bar: i32 }
2515
2516fn foo(bar: i32) -> Foo {
2517    Foo { bar }
2518}
2519"#,
2520        );
2521    }
2522
2523    #[test]
2524    fn test_rename_local_simple() {
2525        check(
2526            "i",
2527            r#"
2528fn foo(bar$0: i32) -> i32 {
2529    bar
2530}
2531"#,
2532            r#"
2533fn foo(i: i32) -> i32 {
2534    i
2535}
2536"#,
2537        );
2538    }
2539
2540    #[test]
2541    fn test_rename_local_put_init_shorthand() {
2542        cov_mark::check!(test_rename_local_put_init_shorthand);
2543        check(
2544            "i",
2545            r#"
2546struct Foo { i: i32 }
2547
2548fn foo(bar$0: i32) -> Foo {
2549    Foo { i: bar }
2550}
2551"#,
2552            r#"
2553struct Foo { i: i32 }
2554
2555fn foo(i: i32) -> Foo {
2556    Foo { i }
2557}
2558"#,
2559        );
2560    }
2561
2562    #[test]
2563    fn test_struct_field_pat_into_shorthand() {
2564        cov_mark::check!(test_rename_field_put_init_shorthand_pat);
2565        check(
2566            "baz",
2567            r#"
2568struct Foo { i$0: i32 }
2569
2570fn foo(foo: Foo) {
2571    let Foo { i: ref baz @ qux } = foo;
2572    let _ = qux;
2573}
2574"#,
2575            r#"
2576struct Foo { baz: i32 }
2577
2578fn foo(foo: Foo) {
2579    let Foo { baz: ref baz @ qux } = foo;
2580    let _ = qux;
2581}
2582"#,
2583        );
2584        check(
2585            "baz",
2586            r#"
2587struct Foo { i$0: i32 }
2588
2589fn foo(foo: Foo) {
2590    let Foo { i: ref baz } = foo;
2591    let _ = qux;
2592}
2593"#,
2594            r#"
2595struct Foo { baz: i32 }
2596
2597fn foo(foo: Foo) {
2598    let Foo { ref baz } = foo;
2599    let _ = qux;
2600}
2601"#,
2602        );
2603    }
2604
2605    #[test]
2606    fn test_struct_local_pat_into_shorthand() {
2607        cov_mark::check!(test_rename_local_put_init_shorthand_pat);
2608        check(
2609            "field",
2610            r#"
2611struct Foo { field: i32 }
2612
2613fn foo(foo: Foo) {
2614    let Foo { field: qux$0 } = foo;
2615    let _ = qux;
2616}
2617"#,
2618            r#"
2619struct Foo { field: i32 }
2620
2621fn foo(foo: Foo) {
2622    let Foo { field } = foo;
2623    let _ = field;
2624}
2625"#,
2626        );
2627        check(
2628            "field",
2629            r#"
2630struct Foo { field: i32 }
2631
2632fn foo(foo: Foo) {
2633    let Foo { field: x @ qux$0 } = foo;
2634    let _ = qux;
2635}
2636"#,
2637            r#"
2638struct Foo { field: i32 }
2639
2640fn foo(foo: Foo) {
2641    let Foo { field: x @ field } = foo;
2642    let _ = field;
2643}
2644"#,
2645        );
2646    }
2647
2648    #[test]
2649    fn test_rename_binding_in_destructure_pat() {
2650        let expected_fixture = r#"
2651struct Foo {
2652    i: i32,
2653}
2654
2655fn foo(foo: Foo) {
2656    let Foo { i: bar } = foo;
2657    let _ = bar;
2658}
2659"#;
2660        check(
2661            "bar",
2662            r#"
2663struct Foo {
2664    i: i32,
2665}
2666
2667fn foo(foo: Foo) {
2668    let Foo { i: b } = foo;
2669    let _ = b$0;
2670}
2671"#,
2672            expected_fixture,
2673        );
2674        check(
2675            "bar",
2676            r#"
2677struct Foo {
2678    i: i32,
2679}
2680
2681fn foo(foo: Foo) {
2682    let Foo { i } = foo;
2683    let _ = i$0;
2684}
2685"#,
2686            expected_fixture,
2687        );
2688    }
2689
2690    #[test]
2691    fn test_rename_binding_in_destructure_param_pat() {
2692        check(
2693            "bar",
2694            r#"
2695struct Foo {
2696    i: i32
2697}
2698
2699fn foo(Foo { i }: Foo) -> i32 {
2700    i$0
2701}
2702"#,
2703            r#"
2704struct Foo {
2705    i: i32
2706}
2707
2708fn foo(Foo { i: bar }: Foo) -> i32 {
2709    bar
2710}
2711"#,
2712        )
2713    }
2714
2715    #[test]
2716    fn test_struct_field_complex_ident_pat() {
2717        cov_mark::check!(rename_record_pat_field_name_split);
2718        check(
2719            "baz",
2720            r#"
2721struct Foo { i$0: i32 }
2722
2723fn foo(foo: Foo) {
2724    let Foo { ref i } = foo;
2725}
2726"#,
2727            r#"
2728struct Foo { baz: i32 }
2729
2730fn foo(foo: Foo) {
2731    let Foo { baz: ref i } = foo;
2732}
2733"#,
2734        );
2735    }
2736
2737    #[test]
2738    fn test_rename_lifetimes() {
2739        check(
2740            "'yeeee",
2741            r#"
2742trait Foo<'a> {
2743    fn foo() -> &'a ();
2744}
2745impl<'a> Foo<'a> for &'a () {
2746    fn foo() -> &'a$0 () {
2747        unimplemented!()
2748    }
2749}
2750"#,
2751            r#"
2752trait Foo<'a> {
2753    fn foo() -> &'a ();
2754}
2755impl<'yeeee> Foo<'yeeee> for &'yeeee () {
2756    fn foo() -> &'yeeee () {
2757        unimplemented!()
2758    }
2759}
2760"#,
2761        )
2762    }
2763
2764    #[test]
2765    fn test_rename_bind_pat() {
2766        check(
2767            "new_name",
2768            r#"
2769fn main() {
2770    enum CustomOption<T> {
2771        None,
2772        Some(T),
2773    }
2774
2775    let test_variable = CustomOption::Some(22);
2776
2777    match test_variable {
2778        CustomOption::Some(foo$0) if foo == 11 => {}
2779        _ => (),
2780    }
2781}"#,
2782            r#"
2783fn main() {
2784    enum CustomOption<T> {
2785        None,
2786        Some(T),
2787    }
2788
2789    let test_variable = CustomOption::Some(22);
2790
2791    match test_variable {
2792        CustomOption::Some(new_name) if new_name == 11 => {}
2793        _ => (),
2794    }
2795}"#,
2796        );
2797    }
2798
2799    #[test]
2800    fn test_rename_label() {
2801        check(
2802            "'foo",
2803            r#"
2804fn foo<'a>() -> &'a () {
2805    'a: {
2806        'b: loop {
2807            break 'a$0;
2808        }
2809    }
2810}
2811"#,
2812            r#"
2813fn foo<'a>() -> &'a () {
2814    'foo: {
2815        'b: loop {
2816            break 'foo;
2817        }
2818    }
2819}
2820"#,
2821        )
2822    }
2823
2824    #[test]
2825    fn test_rename_label_new_name_without_apostrophe() {
2826        check(
2827            "foo",
2828            r#"
2829fn main() {
2830    'outer$0: loop {
2831        'inner: loop {
2832            break 'outer;
2833        }
2834    }
2835}
2836        "#,
2837            r#"
2838fn main() {
2839    'foo: loop {
2840        'inner: loop {
2841            break 'foo;
2842        }
2843    }
2844}
2845        "#,
2846        );
2847    }
2848
2849    #[test]
2850    fn test_self_to_self() {
2851        cov_mark::check!(rename_self_to_self);
2852        check(
2853            "self",
2854            r#"
2855struct Foo;
2856impl Foo {
2857    fn foo(self$0) {}
2858}
2859"#,
2860            r#"
2861struct Foo;
2862impl Foo {
2863    fn foo(self) {}
2864}
2865"#,
2866        )
2867    }
2868
2869    #[test]
2870    fn test_rename_field_in_pat_in_macro_doesnt_shorthand() {
2871        // ideally we would be able to make this emit a short hand, but I doubt this is easily possible
2872        check(
2873            "baz",
2874            r#"
2875macro_rules! foo {
2876    ($pattern:pat) => {
2877        let $pattern = loop {};
2878    };
2879}
2880struct Foo {
2881    bar$0: u32,
2882}
2883fn foo() {
2884    foo!(Foo { bar: baz });
2885}
2886"#,
2887            r#"
2888macro_rules! foo {
2889    ($pattern:pat) => {
2890        let $pattern = loop {};
2891    };
2892}
2893struct Foo {
2894    baz: u32,
2895}
2896fn foo() {
2897    foo!(Foo { baz: baz });
2898}
2899"#,
2900        )
2901    }
2902
2903    #[test]
2904    fn test_rename_tuple_field() {
2905        check(
2906            "foo",
2907            r#"
2908struct Foo(i32);
2909
2910fn baz() {
2911    let mut x = Foo(4);
2912    x.0$0 = 5;
2913}
2914"#,
2915            "error: No references found at position",
2916        );
2917    }
2918
2919    #[test]
2920    fn test_rename_builtin() {
2921        check(
2922            "foo",
2923            r#"
2924fn foo() {
2925    let x: i32$0 = 0;
2926}
2927"#,
2928            "error: Cannot rename builtin type",
2929        );
2930    }
2931
2932    #[test]
2933    fn test_rename_self() {
2934        check(
2935            "foo",
2936            r#"
2937struct Foo {}
2938
2939impl Foo {
2940    fn foo(self) -> Self$0 {
2941        self
2942    }
2943}
2944"#,
2945            "error: No references found at position",
2946        );
2947    }
2948
2949    #[test]
2950    fn test_rename_ignores_self_ty() {
2951        check(
2952            "Fo0",
2953            r#"
2954struct $0Foo;
2955
2956impl Foo where Self: {}
2957"#,
2958            r#"
2959struct Fo0;
2960
2961impl Fo0 where Self: {}
2962"#,
2963        );
2964    }
2965
2966    #[test]
2967    fn test_rename_fails_on_aliases() {
2968        check(
2969            "Baz",
2970            r#"
2971struct Foo;
2972use Foo as Bar$0;
2973"#,
2974            "error: Renaming aliases is currently unsupported",
2975        );
2976        check(
2977            "Baz",
2978            r#"
2979struct Foo;
2980use Foo as Bar;
2981use Bar$0;
2982"#,
2983            "error: Renaming aliases is currently unsupported",
2984        );
2985    }
2986
2987    #[test]
2988    fn test_rename_trait_method() {
2989        let res = r"
2990trait Foo {
2991    fn foo(&self) {
2992        self.foo();
2993    }
2994}
2995
2996impl Foo for () {
2997    fn foo(&self) {
2998        self.foo();
2999    }
3000}";
3001        check(
3002            "foo",
3003            r#"
3004trait Foo {
3005    fn bar$0(&self) {
3006        self.bar();
3007    }
3008}
3009
3010impl Foo for () {
3011    fn bar(&self) {
3012        self.bar();
3013    }
3014}"#,
3015            res,
3016        );
3017        check(
3018            "foo",
3019            r#"
3020trait Foo {
3021    fn bar(&self) {
3022        self.bar$0();
3023    }
3024}
3025
3026impl Foo for () {
3027    fn bar(&self) {
3028        self.bar();
3029    }
3030}"#,
3031            res,
3032        );
3033        check(
3034            "foo",
3035            r#"
3036trait Foo {
3037    fn bar(&self) {
3038        self.bar();
3039    }
3040}
3041
3042impl Foo for () {
3043    fn bar$0(&self) {
3044        self.bar();
3045    }
3046}"#,
3047            res,
3048        );
3049        check(
3050            "foo",
3051            r#"
3052trait Foo {
3053    fn bar(&self) {
3054        self.bar();
3055    }
3056}
3057
3058impl Foo for () {
3059    fn bar(&self) {
3060        self.bar$0();
3061    }
3062}"#,
3063            res,
3064        );
3065    }
3066
3067    #[test]
3068    fn test_rename_trait_method_prefix_of_second() {
3069        check(
3070            "qux",
3071            r#"
3072trait Foo {
3073    fn foo$0() {}
3074    fn foobar() {}
3075}
3076"#,
3077            r#"
3078trait Foo {
3079    fn qux() {}
3080    fn foobar() {}
3081}
3082"#,
3083        );
3084    }
3085
3086    #[test]
3087    fn test_rename_trait_const() {
3088        let res = r"
3089trait Foo {
3090    const FOO: ();
3091}
3092
3093impl Foo for () {
3094    const FOO: ();
3095}
3096fn f() { <()>::FOO; }";
3097        check(
3098            "FOO",
3099            r#"
3100trait Foo {
3101    const BAR$0: ();
3102}
3103
3104impl Foo for () {
3105    const BAR: ();
3106}
3107fn f() { <()>::BAR; }"#,
3108            res,
3109        );
3110        check(
3111            "FOO",
3112            r#"
3113trait Foo {
3114    const BAR: ();
3115}
3116
3117impl Foo for () {
3118    const BAR$0: ();
3119}
3120fn f() { <()>::BAR; }"#,
3121            res,
3122        );
3123        check(
3124            "FOO",
3125            r#"
3126trait Foo {
3127    const BAR: ();
3128}
3129
3130impl Foo for () {
3131    const BAR: ();
3132}
3133fn f() { <()>::BAR$0; }"#,
3134            res,
3135        );
3136    }
3137
3138    #[test]
3139    fn defs_from_macros_arent_renamed() {
3140        check(
3141            "lol",
3142            r#"
3143macro_rules! m { () => { fn f() {} } }
3144m!();
3145fn main() { f$0()  }
3146"#,
3147            "error: No identifier available to rename",
3148        )
3149    }
3150
3151    #[test]
3152    fn attributed_item() {
3153        check(
3154            "function",
3155            r#"
3156//- proc_macros: identity
3157
3158#[proc_macros::identity]
3159fn func$0() {
3160    func();
3161}
3162"#,
3163            r#"
3164
3165#[proc_macros::identity]
3166fn function() {
3167    function();
3168}
3169"#,
3170        )
3171    }
3172
3173    #[test]
3174    fn in_macro_multi_mapping() {
3175        check(
3176            "a",
3177            r#"
3178fn foo() {
3179    macro_rules! match_ast2 {
3180        ($node:ident {
3181            $( $res:expr, )*
3182        }) => {{
3183            $( if $node { $res } else )*
3184            { loop {} }
3185        }};
3186    }
3187    let $0d = 3;
3188    match_ast2! {
3189        d {
3190            d,
3191            d,
3192        }
3193    };
3194}
3195"#,
3196            r#"
3197fn foo() {
3198    macro_rules! match_ast2 {
3199        ($node:ident {
3200            $( $res:expr, )*
3201        }) => {{
3202            $( if $node { $res } else )*
3203            { loop {} }
3204        }};
3205    }
3206    let a = 3;
3207    match_ast2! {
3208        a {
3209            a,
3210            a,
3211        }
3212    };
3213}
3214"#,
3215        )
3216    }
3217
3218    #[test]
3219    fn rename_multi_local() {
3220        check(
3221            "bar",
3222            r#"
3223fn foo((foo$0 | foo | foo): ()) {
3224    foo;
3225    let foo;
3226}
3227"#,
3228            r#"
3229fn foo((bar | bar | bar): ()) {
3230    bar;
3231    let foo;
3232}
3233"#,
3234        );
3235        check(
3236            "bar",
3237            r#"
3238fn foo((foo | foo$0 | foo): ()) {
3239    foo;
3240    let foo;
3241}
3242"#,
3243            r#"
3244fn foo((bar | bar | bar): ()) {
3245    bar;
3246    let foo;
3247}
3248"#,
3249        );
3250        check(
3251            "bar",
3252            r#"
3253fn foo((foo | foo | foo): ()) {
3254    foo$0;
3255    let foo;
3256}
3257"#,
3258            r#"
3259fn foo((bar | bar | bar): ()) {
3260    bar;
3261    let foo;
3262}
3263"#,
3264        );
3265    }
3266
3267    #[test]
3268    fn regression_13498() {
3269        check(
3270            "Testing",
3271            r"
3272mod foo {
3273    pub struct Test$0;
3274}
3275
3276use foo::Test as Tester;
3277
3278fn main() {
3279    let t = Tester;
3280}
3281",
3282            r"
3283mod foo {
3284    pub struct Testing;
3285}
3286
3287use foo::Testing as Tester;
3288
3289fn main() {
3290    let t = Tester;
3291}
3292",
3293        )
3294    }
3295
3296    #[test]
3297    fn extern_crate() {
3298        check_prepare(
3299            r"
3300//- /lib.rs crate:main deps:foo
3301extern crate foo$0;
3302use foo as qux;
3303//- /foo.rs crate:foo
3304",
3305            expect![[r#"No references found at position"#]],
3306        );
3307        // FIXME: replace above check_prepare with this once we resolve to usages to extern crate declarations
3308        //         check(
3309        //             "bar",
3310        //             r"
3311        // //- /lib.rs crate:main deps:foo
3312        // extern crate foo$0;
3313        // use foo as qux;
3314        // //- /foo.rs crate:foo
3315        // ",
3316        //             r"
3317        // extern crate foo as bar;
3318        // use bar as qux;
3319        // ",
3320        //         );
3321    }
3322
3323    #[test]
3324    fn extern_crate_rename() {
3325        check_prepare(
3326            r"
3327//- /lib.rs crate:main deps:foo
3328extern crate foo as qux$0;
3329use qux as frob;
3330//- /foo.rs crate:foo
3331",
3332            expect!["Renaming aliases is currently unsupported"],
3333        );
3334        // FIXME: replace above check_prepare with this once we resolve to usages to extern crate
3335        // declarations
3336        //         check(
3337        //             "bar",
3338        //             r"
3339        // //- /lib.rs crate:main deps:foo
3340        // extern crate foo as qux$0;
3341        // use qux as frob;
3342        // //- /foo.rs crate:foo
3343        // ",
3344        //             r"
3345        // extern crate foo as bar;
3346        // use bar as frob;
3347        // ",
3348        //         );
3349    }
3350
3351    #[test]
3352    fn extern_crate_self() {
3353        check_prepare(
3354            r"
3355extern crate self$0;
3356use self as qux;
3357",
3358            expect!["No references found at position"],
3359        );
3360        // FIXME: replace above check_prepare with this once we resolve to usages to extern crate declarations
3361        //         check(
3362        //             "bar",
3363        //             r"
3364        // extern crate self$0;
3365        // use self as qux;
3366        // ",
3367        //             r"
3368        // extern crate self as bar;
3369        // use self as qux;
3370        // ",
3371        //         );
3372    }
3373
3374    #[test]
3375    fn extern_crate_self_rename() {
3376        check_prepare(
3377            r"
3378//- /lib.rs crate:main deps:foo
3379extern crate self as qux$0;
3380use qux as frob;
3381//- /foo.rs crate:foo
3382",
3383            expect!["Renaming aliases is currently unsupported"],
3384        );
3385        // FIXME: replace above check_prepare with this once we resolve to usages to extern crate declarations
3386        //         check(
3387        //             "bar",
3388        //             r"
3389        // //- /lib.rs crate:main deps:foo
3390        // extern crate self as qux$0;
3391        // use qux as frob;
3392        // //- /foo.rs crate:foo
3393        // ",
3394        //             r"
3395        // extern crate self as bar;
3396        // use bar as frob;
3397        // ",
3398        //         );
3399    }
3400
3401    #[test]
3402    fn disallow_renaming_for_non_local_definition() {
3403        check(
3404            "Baz",
3405            r#"
3406//- /lib.rs crate:lib new_source_root:library
3407pub struct S;
3408//- /main.rs crate:main deps:lib new_source_root:local
3409use lib::S;
3410fn main() { let _: S$0; }
3411"#,
3412            "error: Cannot rename a non-local definition",
3413        );
3414    }
3415
3416    #[test]
3417    fn disallow_renaming_for_builtin_macros() {
3418        check(
3419            "Baz",
3420            r#"
3421//- minicore: derive, hash
3422//- /main.rs crate:main
3423use core::hash::Hash;
3424#[derive(H$0ash)]
3425struct A;
3426            "#,
3427            "error: Cannot rename a non-local definition",
3428        );
3429    }
3430
3431    #[test]
3432    fn implicit_format_args() {
3433        check(
3434            "fbar",
3435            r#"
3436//- minicore: fmt
3437fn test() {
3438    let foo = "foo";
3439    format_args!("hello {foo} {foo$0} {}", foo);
3440}
3441"#,
3442            r#"
3443fn test() {
3444    let fbar = "foo";
3445    format_args!("hello {fbar} {fbar} {}", fbar);
3446}
3447"#,
3448        );
3449    }
3450
3451    #[test]
3452    fn implicit_format_args2() {
3453        check(
3454            "fo",
3455            r#"
3456//- minicore: fmt
3457fn test() {
3458    let foo = "foo";
3459    format_args!("hello {foo} {foo$0} {}", foo);
3460}
3461"#,
3462            r#"
3463fn test() {
3464    let fo = "foo";
3465    format_args!("hello {fo} {fo} {}", fo);
3466}
3467"#,
3468        );
3469    }
3470
3471    #[test]
3472    fn asm_operand() {
3473        check(
3474            "bose",
3475            r#"
3476//- minicore: asm
3477fn test() {
3478    core::arch::asm!(
3479        "push {base}",
3480        base$0 = const 0
3481    );
3482}
3483"#,
3484            r#"
3485fn test() {
3486    core::arch::asm!(
3487        "push {bose}",
3488        bose = const 0
3489    );
3490}
3491"#,
3492        );
3493    }
3494
3495    #[test]
3496    fn asm_operand2() {
3497        check(
3498            "bose",
3499            r#"
3500//- minicore: asm
3501fn test() {
3502    core::arch::asm!(
3503        "push {base$0}",
3504        "push {base}",
3505        boo = const 0,
3506        virtual_free = sym VIRTUAL_FREE,
3507        base = const 0,
3508        boo = const 0,
3509    );
3510}
3511"#,
3512            r#"
3513fn test() {
3514    core::arch::asm!(
3515        "push {bose}",
3516        "push {bose}",
3517        boo = const 0,
3518        virtual_free = sym VIRTUAL_FREE,
3519        bose = const 0,
3520        boo = const 0,
3521    );
3522}
3523"#,
3524        );
3525    }
3526
3527    #[test]
3528    fn rename_path_inside_use_tree() {
3529        check(
3530            "Baz",
3531            r#"
3532//- /main.rs crate:main
3533mod module;
3534mod foo { pub struct Foo; }
3535mod bar { use super::Foo; }
3536
3537use foo::Foo$0;
3538
3539fn main() { let _: Foo; }
3540//- /module.rs
3541use crate::foo::Foo;
3542"#,
3543            r#"
3544mod module;
3545mod foo { pub struct Foo; }
3546mod bar { use super::Baz; }
3547
3548use foo::Foo as Baz;
3549
3550fn main() { let _: Baz; }
3551"#,
3552        )
3553    }
3554
3555    #[test]
3556    fn rename_path_inside_use_tree_foreign() {
3557        check(
3558            "Baz",
3559            r#"
3560//- /lib.rs crate:lib new_source_root:library
3561pub struct S;
3562//- /main.rs crate:main deps:lib new_source_root:local
3563use lib::S$0;
3564fn main() { let _: S; }
3565"#,
3566            r#"
3567use lib::S as Baz;
3568fn main() { let _: Baz; }
3569"#,
3570        );
3571    }
3572
3573    #[test]
3574    fn rename_type_param_ref_in_use_bound() {
3575        check(
3576            "U",
3577            r#"
3578fn foo<T>() -> impl use<T$0> Trait {}
3579"#,
3580            r#"
3581fn foo<U>() -> impl use<U> Trait {}
3582"#,
3583        );
3584    }
3585
3586    #[test]
3587    fn rename_type_param_in_use_bound() {
3588        check(
3589            "U",
3590            r#"
3591fn foo<T$0>() -> impl use<T> Trait {}
3592"#,
3593            r#"
3594fn foo<U>() -> impl use<U> Trait {}
3595"#,
3596        );
3597    }
3598
3599    #[test]
3600    fn rename_lifetime_param_ref_in_use_bound() {
3601        check(
3602            "u",
3603            r#"
3604fn foo<'t>() -> impl use<'t$0> Trait {}
3605"#,
3606            r#"
3607fn foo<'u>() -> impl use<'u> Trait {}
3608"#,
3609        );
3610    }
3611
3612    #[test]
3613    fn rename_lifetime_param_in_use_bound() {
3614        check(
3615            "u",
3616            r#"
3617fn foo<'t$0>() -> impl use<'t> Trait {}
3618"#,
3619            r#"
3620fn foo<'u>() -> impl use<'u> Trait {}
3621"#,
3622        );
3623    }
3624
3625    #[test]
3626    fn rename_parent_type_param_in_use_bound() {
3627        check(
3628            "U",
3629            r#"
3630trait Trait<T> {
3631    fn foo() -> impl use<T$0> Trait {}
3632}
3633"#,
3634            r#"
3635trait Trait<U> {
3636    fn foo() -> impl use<U> Trait {}
3637}
3638"#,
3639        );
3640    }
3641
3642    #[test]
3643    fn rename_macro_generated_type_from_type_with_a_suffix() {
3644        check(
3645            "Bar",
3646            r#"
3647//- proc_macros: generate_suffixed_type
3648#[proc_macros::generate_suffixed_type]
3649struct Foo$0;
3650fn usage(_: FooSuffix) {}
3651usage(FooSuffix);
3652"#,
3653            r#"
3654#[proc_macros::generate_suffixed_type]
3655struct Bar;
3656fn usage(_: BarSuffix) {}
3657usage(BarSuffix);
3658"#,
3659        );
3660    }
3661
3662    #[test]
3663    // FIXME
3664    #[should_panic]
3665    fn rename_macro_generated_type_from_type_usage_with_a_suffix() {
3666        check(
3667            "Bar",
3668            r#"
3669//- proc_macros: generate_suffixed_type
3670#[proc_macros::generate_suffixed_type]
3671struct Foo;
3672fn usage(_: FooSuffix) {}
3673usage(FooSuffix);
3674fn other_place() { Foo$0; }
3675"#,
3676            r#"
3677#[proc_macros::generate_suffixed_type]
3678struct Bar;
3679fn usage(_: BarSuffix) {}
3680usage(BarSuffix);
3681fn other_place() { Bar; }
3682"#,
3683        );
3684    }
3685
3686    #[test]
3687    fn rename_macro_generated_type_from_variant_with_a_suffix() {
3688        check(
3689            "Bar",
3690            r#"
3691//- proc_macros: generate_suffixed_type
3692#[proc_macros::generate_suffixed_type]
3693enum Quux {
3694    Foo$0,
3695}
3696fn usage(_: FooSuffix) {}
3697usage(FooSuffix);
3698"#,
3699            r#"
3700#[proc_macros::generate_suffixed_type]
3701enum Quux {
3702    Bar,
3703}
3704fn usage(_: BarSuffix) {}
3705usage(BarSuffix);
3706"#,
3707        );
3708    }
3709
3710    #[test]
3711    // FIXME
3712    #[should_panic]
3713    fn rename_macro_generated_type_from_variant_usage_with_a_suffix() {
3714        check(
3715            "Bar",
3716            r#"
3717//- proc_macros: generate_suffixed_type
3718#[proc_macros::generate_suffixed_type]
3719enum Quux {
3720    Foo,
3721}
3722fn usage(_: FooSuffix) {}
3723usage(FooSuffix);
3724fn other_place() { Quux::Foo$0; }
3725"#,
3726            r#"
3727#[proc_macros::generate_suffixed_type]
3728enum Quux {
3729    Bar,
3730}
3731fn usage(_: BarSuffix) {}
3732usage(BartSuffix);
3733fn other_place() { Quux::Bar$0; }
3734"#,
3735        );
3736    }
3737
3738    #[test]
3739    fn rename_to_self_callers() {
3740        check(
3741            "self",
3742            r#"
3743//- minicore: add
3744struct Foo;
3745impl core::ops::Add for Foo {
3746    type Target = Foo;
3747    fn add(self, _: Self) -> Foo { Foo }
3748}
3749
3750impl Foo {
3751    fn foo(th$0is: &Self) {}
3752}
3753
3754fn bar(v: &Foo) {
3755    Foo::foo(v);
3756}
3757
3758fn baz() {
3759    Foo::foo(&Foo);
3760    Foo::foo(Foo + Foo);
3761}
3762        "#,
3763            r#"
3764struct Foo;
3765impl core::ops::Add for Foo {
3766    type Target = Foo;
3767    fn add(self, _: Self) -> Foo { Foo }
3768}
3769
3770impl Foo {
3771    fn foo(&self) {}
3772}
3773
3774fn bar(v: &Foo) {
3775    v.foo();
3776}
3777
3778fn baz() {
3779    Foo.foo();
3780    (Foo + Foo).foo();
3781}
3782        "#,
3783        );
3784        // Multiple arguments:
3785        check(
3786            "self",
3787            r#"
3788struct Foo;
3789
3790impl Foo {
3791    fn foo(th$0is: &Self, v: i32) {}
3792}
3793
3794fn bar(v: Foo) {
3795    Foo::foo(&v, 123);
3796}
3797        "#,
3798            r#"
3799struct Foo;
3800
3801impl Foo {
3802    fn foo(&self, v: i32) {}
3803}
3804
3805fn bar(v: Foo) {
3806    v.foo(123);
3807}
3808        "#,
3809        );
3810    }
3811
3812    #[test]
3813    fn rename_to_self_callers_in_macro() {
3814        check(
3815            "self",
3816            r#"
3817struct Foo;
3818
3819impl Foo {
3820    fn foo(th$0is: &Self, v: i32) {}
3821}
3822
3823macro_rules! m { ($it:expr) => { $it } }
3824fn bar(v: Foo) {
3825    m!(Foo::foo(&v, 123));
3826}
3827        "#,
3828            r#"
3829struct Foo;
3830
3831impl Foo {
3832    fn foo(&self, v: i32) {}
3833}
3834
3835macro_rules! m { ($it:expr) => { $it } }
3836fn bar(v: Foo) {
3837    m!(v.foo( 123));
3838}
3839        "#,
3840        );
3841    }
3842
3843    #[test]
3844    fn rename_from_self_callers() {
3845        check(
3846            "this",
3847            r#"
3848//- minicore: add
3849struct Foo;
3850impl Foo {
3851    fn foo(&sel$0f) {}
3852}
3853impl core::ops::Add for Foo {
3854    type Output = Foo;
3855
3856    fn add(self, _rhs: Self) -> Self::Output {
3857        Foo
3858    }
3859}
3860
3861fn bar(v: &Foo) {
3862    v.foo();
3863    (Foo + Foo).foo();
3864}
3865
3866mod baz {
3867    fn baz(v: super::Foo) {
3868        v.foo();
3869    }
3870}
3871        "#,
3872            r#"
3873struct Foo;
3874impl Foo {
3875    fn foo(this: &Self) {}
3876}
3877impl core::ops::Add for Foo {
3878    type Output = Foo;
3879
3880    fn add(self, _rhs: Self) -> Self::Output {
3881        Foo
3882    }
3883}
3884
3885fn bar(v: &Foo) {
3886    Foo::foo(v);
3887    Foo::foo(&(Foo + Foo));
3888}
3889
3890mod baz {
3891    fn baz(v: super::Foo) {
3892        crate::Foo::foo(&v);
3893    }
3894}
3895        "#,
3896        );
3897        // Multiple args:
3898        check(
3899            "this",
3900            r#"
3901struct Foo;
3902impl Foo {
3903    fn foo(&sel$0f, _v: i32) {}
3904}
3905
3906fn bar() {
3907    Foo.foo(1);
3908}
3909        "#,
3910            r#"
3911struct Foo;
3912impl Foo {
3913    fn foo(this: &Self, _v: i32) {}
3914}
3915
3916fn bar() {
3917    Foo::foo(&Foo, 1);
3918}
3919        "#,
3920        );
3921    }
3922}