Skip to main content

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