internal: prepare to move rename to base_db

It's better to handle magical cases upper in the stack, because it
allows for better re-use of the general implementation below. So, we
pull the `self` case up here.

The end goal is to put `Definition::rename` to the `ide_db`, because
it's a generally re-usable functionality useful for different ide
features, alongside with the search which is already there.
This commit is contained in:
Aleksey Kladov 2021-06-14 17:19:41 +03:00
parent d4ab49c533
commit 721feb1832

View File

@ -86,6 +86,18 @@ pub(crate) fn rename_with_semantics(
let syntax = source_file.syntax(); let syntax = source_file.syntax();
let def = find_definition(sema, syntax, position)?; let def = find_definition(sema, syntax, position)?;
if let Definition::Local(local) = def {
if let Some(self_param) = local.as_self_param(sema.db) {
cov_mark::hit!(rename_self_to_param);
return rename_self_to_param(sema, local, self_param, new_name);
}
if new_name == "self" {
cov_mark::hit!(rename_to_self);
return rename_to_self(sema, local);
}
}
match def { match def {
Definition::ModuleDef(hir::ModuleDef::Module(module)) => rename_mod(sema, module, new_name), Definition::ModuleDef(hir::ModuleDef::Module(module)) => rename_mod(sema, module, new_name),
Definition::SelfType(_) => bail!("Cannot rename `Self`"), Definition::SelfType(_) => bail!("Cannot rename `Self`"),
@ -113,26 +125,26 @@ pub(crate) fn will_rename_file(
enum IdentifierKind { enum IdentifierKind {
Ident, Ident,
Lifetime, Lifetime,
ToSelf,
Underscore, Underscore,
} }
fn check_identifier(new_name: &str) -> RenameResult<IdentifierKind> { impl IdentifierKind {
match lex_single_syntax_kind(new_name) { fn classify(new_name: &str) -> RenameResult<IdentifierKind> {
Some(res) => match res { match lex_single_syntax_kind(new_name) {
(SyntaxKind::IDENT, _) => Ok(IdentifierKind::Ident), Some(res) => match res {
(T![_], _) => Ok(IdentifierKind::Underscore), (SyntaxKind::IDENT, _) => Ok(IdentifierKind::Ident),
(T![self], _) => Ok(IdentifierKind::ToSelf), (T![_], _) => Ok(IdentifierKind::Underscore),
(SyntaxKind::LIFETIME_IDENT, _) if new_name != "'static" && new_name != "'_" => { (SyntaxKind::LIFETIME_IDENT, _) if new_name != "'static" && new_name != "'_" => {
Ok(IdentifierKind::Lifetime) Ok(IdentifierKind::Lifetime)
} }
(SyntaxKind::LIFETIME_IDENT, _) => { (SyntaxKind::LIFETIME_IDENT, _) => {
bail!("Invalid name `{}`: not a lifetime identifier", new_name) bail!("Invalid name `{}`: not a lifetime identifier", new_name)
} }
(_, Some(syntax_error)) => bail!("Invalid name `{}`: {}", new_name, syntax_error), (_, Some(syntax_error)) => bail!("Invalid name `{}`: {}", new_name, syntax_error),
(_, None) => bail!("Invalid name `{}`: not an identifier", new_name), (_, None) => bail!("Invalid name `{}`: not an identifier", new_name),
}, },
None => bail!("Invalid name `{}`: not an identifier", new_name), None => bail!("Invalid name `{}`: not an identifier", new_name),
}
} }
} }
@ -182,7 +194,7 @@ fn rename_mod(
module: hir::Module, module: hir::Module,
new_name: &str, new_name: &str,
) -> RenameResult<SourceChange> { ) -> RenameResult<SourceChange> {
if IdentifierKind::Ident != check_identifier(new_name)? { if IdentifierKind::classify(new_name)? != IdentifierKind::Ident {
bail!("Invalid name `{0}`: cannot rename module to {0}", new_name); bail!("Invalid name `{0}`: cannot rename module to {0}", new_name);
} }
@ -227,14 +239,14 @@ fn rename_reference(
mut def: Definition, mut def: Definition,
new_name: &str, new_name: &str,
) -> RenameResult<SourceChange> { ) -> RenameResult<SourceChange> {
let ident_kind = check_identifier(new_name)?; let ident_kind = IdentifierKind::classify(new_name)?;
if matches!( if matches!(
def, // is target a lifetime? def, // is target a lifetime?
Definition::GenericParam(hir::GenericParam::LifetimeParam(_)) | Definition::Label(_) Definition::GenericParam(hir::GenericParam::LifetimeParam(_)) | Definition::Label(_)
) { ) {
match ident_kind { match ident_kind {
IdentifierKind::Ident | IdentifierKind::ToSelf | IdentifierKind::Underscore => { IdentifierKind::Ident | IdentifierKind::Underscore => {
cov_mark::hit!(rename_not_a_lifetime_ident_ref); cov_mark::hit!(rename_not_a_lifetime_ident_ref);
bail!("Invalid name `{}`: not a lifetime identifier", new_name); bail!("Invalid name `{}`: not a lifetime identifier", new_name);
} }
@ -246,25 +258,6 @@ fn rename_reference(
cov_mark::hit!(rename_not_an_ident_ref); cov_mark::hit!(rename_not_an_ident_ref);
bail!("Invalid name `{}`: not an identifier", new_name); bail!("Invalid name `{}`: not an identifier", new_name);
} }
(IdentifierKind::ToSelf, Definition::Local(local)) => {
if local.is_self(sema.db) {
// no-op
cov_mark::hit!(rename_self_to_self);
return Ok(SourceChange::default());
} else {
cov_mark::hit!(rename_to_self);
return rename_to_self(sema, local);
}
}
(ident_kind, Definition::Local(local)) => {
if let Some(self_param) = local.as_self_param(sema.db) {
cov_mark::hit!(rename_self_to_param);
return rename_self_to_param(sema, local, self_param, new_name, ident_kind);
} else {
cov_mark::hit!(rename_local);
}
}
(IdentifierKind::ToSelf, _) => bail!("Invalid name `{}`: not an identifier", new_name),
(IdentifierKind::Ident, _) => cov_mark::hit!(rename_non_local), (IdentifierKind::Ident, _) => cov_mark::hit!(rename_non_local),
(IdentifierKind::Underscore, _) => (), (IdentifierKind::Underscore, _) => (),
} }
@ -383,8 +376,15 @@ fn rename_self_to_param(
local: hir::Local, local: hir::Local,
self_param: hir::SelfParam, self_param: hir::SelfParam,
new_name: &str, new_name: &str,
identifier_kind: IdentifierKind,
) -> RenameResult<SourceChange> { ) -> RenameResult<SourceChange> {
if new_name == "self" {
// Let's do nothing rather than complain.
cov_mark::hit!(rename_self_to_self);
return Ok(SourceChange::default());
}
let identifier_kind = IdentifierKind::classify(new_name)?;
let InFile { file_id, value: self_param } = let InFile { file_id, value: self_param } =
self_param.source(sema.db).ok_or_else(|| format_err!("cannot find function source"))?; self_param.source(sema.db).ok_or_else(|| format_err!("cannot find function source"))?;
@ -879,7 +879,6 @@ fn test_rename_mod_invalid() {
#[test] #[test]
fn test_rename_for_local() { fn test_rename_for_local() {
cov_mark::check!(rename_local);
check( check(
"k", "k",
r#" r#"