Allow renaming when there are multiple definitions (due to macros) even when some cannot rename

This commit is contained in:
Chayim Refael Friedman 2025-08-05 00:10:21 +03:00
parent 978393bae8
commit 47845d6097

View File

@ -27,6 +27,27 @@ pub use ide_db::rename::RenameError;
type RenameResult<T> = Result<T, RenameError>;
/// This is similar to `collect::<Result<Vec<_>, _>>`, but unlike it, it succeeds if there is *any* `Ok` item.
fn ok_if_any<T, E>(iter: impl Iterator<Item = Result<T, E>>) -> Result<Vec<T>, E> {
let mut err = None;
let oks = iter
.filter_map(|item| match item {
Ok(it) => Some(it),
Err(it) => {
err = Some(it);
None
}
})
.collect::<Vec<_>>();
if !oks.is_empty() {
Ok(oks)
} else if let Some(err) = err {
Err(err)
} else {
Ok(Vec::new())
}
}
/// Prepares a rename. The sole job of this function is to return the TextRange of the thing that is
/// being targeted for a rename.
pub(crate) fn prepare_rename(
@ -95,7 +116,8 @@ pub(crate) fn rename(
alias_fallback(syntax, position, &new_name.display(db, edition).to_string());
let ops: RenameResult<Vec<SourceChange>> = match alias_fallback {
Some(_) => defs
Some(_) => ok_if_any(
defs
// FIXME: This can use the `ide_db::rename_reference` (or def.rename) method once we can
// properly find "direct" usages/references.
.map(|(.., def, new_name, _)| {
@ -130,10 +152,9 @@ pub(crate) fn rename(
}));
Ok(source_change)
})
.collect(),
None => defs
.map(|(.., def, new_name, rename_def)| {
}),
),
None => ok_if_any(defs.map(|(.., def, new_name, rename_def)| {
if let Definition::Local(local) = def {
if let Some(self_param) = local.as_self_param(sema.db) {
cov_mark::hit!(rename_self_to_param);
@ -145,8 +166,7 @@ pub(crate) fn rename(
}
}
def.rename(&sema, new_name.as_str(), rename_def)
})
.collect(),
})),
};
ops?.into_iter()
@ -320,7 +340,7 @@ fn find_definitions(
})
});
let res: RenameResult<Vec<_>> = symbols.filter_map(Result::transpose).collect();
let res: RenameResult<Vec<_>> = ok_if_any(symbols.filter_map(Result::transpose));
match res {
Ok(v) => {
// remove duplicates, comparing `Definition`s