Wrap remaining self/super/crate in Name{Ref}

This commit is contained in:
Lukas Wirth 2021-01-15 21:07:38 +01:00
parent 8a869e870a
commit 98718e0544
28 changed files with 237 additions and 169 deletions

View file

@ -400,15 +400,13 @@ impl TryToNav for hir::GenericParam {
impl ToNav for hir::Local {
fn to_nav(&self, db: &RootDatabase) -> NavigationTarget {
let src = self.source(db);
let (node, focus_range) = match &src.value {
Either::Left(bind_pat) => (
bind_pat.syntax().clone(),
bind_pat
.name()
.map(|it| src.with_value(&it.syntax().clone()).original_file_range(db).range),
),
Either::Right(it) => (it.syntax().clone(), it.self_token().map(|it| it.text_range())),
let (node, name) = match &src.value {
Either::Left(bind_pat) => (bind_pat.syntax().clone(), bind_pat.name()),
Either::Right(it) => (it.syntax().clone(), it.name()),
};
let focus_range =
name.map(|it| src.with_value(&it.syntax().clone()).original_file_range(db).range);
let full_range = src.with_value(&node).original_file_range(db);
let name = match self.name(db) {
Some(it) => it.to_string().into(),

View file

@ -55,11 +55,6 @@ pub(crate) fn goto_definition(
} else {
reference_definition(&sema, Either::Left(&lt)).to_vec()
},
ast::SelfParam(self_param) => {
let def = NameClass::classify_self_param(&sema, &self_param)?.referenced_or_defined(sema.db);
let nav = def.try_to_nav(sema.db)?;
vec![nav]
},
_ => return None,
}
};

View file

@ -98,7 +98,6 @@ pub(crate) fn hover(
ast::NameRef(name_ref) => NameRefClass::classify(&sema, &name_ref).map(|d| d.referenced(sema.db)),
ast::Lifetime(lifetime) => NameClass::classify_lifetime(&sema, &lifetime)
.map_or_else(|| NameRefClass::classify_lifetime(&sema, &lifetime).map(|d| d.referenced(sema.db)), |d| d.defined(sema.db)),
ast::SelfParam(self_param) => NameClass::classify_self_param(&sema, &self_param).and_then(|d| d.defined(sema.db)),
_ => None,
}
};
@ -3223,7 +3222,7 @@ impl Foo {
}
"#,
expect![[r#"
*&self*
*self*
```rust
&Foo
@ -3243,7 +3242,7 @@ impl Foo {
}
"#,
expect![[r#"
*self: Arc<Foo>*
*self*
```rust
Arc<Foo>

View file

@ -1,12 +1,9 @@
//! FIXME: write short doc here
use std::{
convert::TryInto,
fmt::{self, Display},
};
use std::fmt::{self, Display};
use hir::{Module, ModuleDef, ModuleSource, Semantics};
use ide_db::{
base_db::{AnchoredPathBuf, FileId, FileRange, SourceDatabaseExt},
base_db::{AnchoredPathBuf, FileId, FileRange},
defs::{Definition, NameClass, NameRefClass},
search::FileReference,
RootDatabase,
@ -14,14 +11,14 @@ use ide_db::{
use syntax::{
algo::find_node_at_offset,
ast::{self, NameOwner},
lex_single_syntax_kind, match_ast, AstNode, SyntaxKind, SyntaxNode, SyntaxToken, T,
lex_single_syntax_kind, match_ast, AstNode, SyntaxKind, SyntaxNode, T,
};
use test_utils::mark;
use text_edit::TextEdit;
use crate::{
FilePosition, FileSystemEdit, RangeInfo, ReferenceKind, ReferenceSearchResult, SourceChange,
TextRange, TextSize,
TextRange,
};
type RenameResult<T> = Result<T, RenameError>;
@ -52,10 +49,6 @@ pub(crate) fn prepare_rename(
let syntax = source_file.syntax();
if let Some(module) = find_module_at_offset(&sema, position, syntax) {
rename_mod(&sema, position, module, "dummy")
} else if let Some(self_token) =
syntax.token_at_offset(position.offset).find(|t| t.kind() == T![self])
{
rename_self_to_param(&sema, position, self_token, "dummy")
} else {
let RangeInfo { range, .. } = find_all_refs(&sema, position)?;
Ok(RangeInfo::new(range, SourceChange::default()))
@ -82,10 +75,6 @@ pub(crate) fn rename_with_semantics(
if let Some(module) = find_module_at_offset(&sema, position, syntax) {
rename_mod(&sema, position, module, new_name)
} else if let Some(self_token) =
syntax.token_at_offset(position.offset).find(|t| t.kind() == T![self])
{
rename_self_to_param(&sema, position, self_token, new_name)
} else {
rename_reference(&sema, position, new_name)
}
@ -108,7 +97,7 @@ pub(crate) fn will_rename_file(
Some(change)
}
#[derive(Debug, PartialEq)]
#[derive(Copy, Clone, Debug, PartialEq)]
enum IdentifierKind {
Ident,
Lifetime,
@ -375,53 +364,50 @@ fn text_edit_from_self_param(
fn rename_self_to_param(
sema: &Semantics<RootDatabase>,
position: FilePosition,
self_token: SyntaxToken,
new_name: &str,
ident_kind: IdentifierKind,
range: TextRange,
refs: ReferenceSearchResult,
) -> Result<RangeInfo<SourceChange>, RenameError> {
let ident_kind = check_identifier(new_name)?;
match ident_kind {
IdentifierKind::Lifetime => bail!("Invalid name `{}`: not an identifier", new_name),
IdentifierKind::ToSelf => {
// no-op
mark::hit!(rename_self_to_self);
return Ok(RangeInfo::new(self_token.text_range(), SourceChange::default()));
return Ok(RangeInfo::new(range, SourceChange::default()));
}
_ => (),
}
let source_file = sema.parse(position.file_id);
let syn = source_file.syntax();
let text = sema.db.file_text(position.file_id);
let fn_def = find_node_at_offset::<ast::Fn>(syn, position.offset)
.ok_or_else(|| format_err!("No surrounding method declaration found"))?;
let search_range = fn_def.syntax().text_range();
let mut source_change = SourceChange::default();
for (idx, _) in text.match_indices("self") {
let offset: TextSize = idx.try_into().unwrap();
if !search_range.contains_inclusive(offset) {
continue;
}
if let Some(ref usage) = syn.token_at_offset(offset).find(|t| t.kind() == T![self]) {
let edit = if let Some(ref self_param) = ast::SelfParam::cast(usage.parent()) {
text_edit_from_self_param(syn, self_param, new_name)
.ok_or_else(|| format_err!("No target type found"))?
} else {
TextEdit::replace(usage.text_range(), String::from(new_name))
};
if let Some(self_param) = fn_def.param_list().and_then(|it| it.self_param()) {
if self_param
.syntax()
.text_range()
.contains_range(refs.declaration().nav.focus_or_full_range())
{
let edit = text_edit_from_self_param(syn, &self_param, new_name)
.ok_or_else(|| format_err!("No target type found"))?;
source_change.insert_source_edit(position.file_id, edit);
source_change.extend(refs.references().iter().map(|(&file_id, references)| {
source_edit_from_references(sema, file_id, &references, new_name)
}));
if source_change.source_file_edits.len() > 1 && ident_kind == IdentifierKind::Underscore
{
bail!("Cannot rename reference to `_` as it is being referenced multiple times");
}
return Ok(RangeInfo::new(range, source_change));
}
}
if source_change.source_file_edits.len() > 1 && ident_kind == IdentifierKind::Underscore {
bail!("Cannot rename reference to `_` as it is being referenced multiple times");
}
let range = ast::SelfParam::cast(self_token.parent())
.map_or(self_token.text_range(), |p| p.syntax().text_range());
Ok(RangeInfo::new(range, source_change))
Err(format_err!("Method has no self param"))
}
fn rename_reference(
@ -444,8 +430,9 @@ fn rename_reference(
mark::hit!(rename_not_an_ident_ref);
bail!("Invalid name `{}`: not an identifier", new_name)
}
(IdentifierKind::ToSelf, ReferenceKind::SelfParam) => {
unreachable!("rename_self_to_param should've been called instead")
(_, ReferenceKind::SelfParam) => {
mark::hit!(rename_self_to_param);
return rename_self_to_param(sema, position, new_name, ident_kind, range, refs);
}
(IdentifierKind::ToSelf, _) => {
mark::hit!(rename_to_self);
@ -1350,6 +1337,7 @@ impl Foo {
#[test]
fn test_owned_self_to_parameter() {
mark::check!(rename_self_to_param);
check(
"foo",
r#"

View file

@ -68,7 +68,8 @@ pub(super) fn element(
NAME_REF => {
let name_ref = element.into_node().and_then(ast::NameRef::cast).unwrap();
highlight_func_by_name_ref(sema, &name_ref).unwrap_or_else(|| {
match NameRefClass::classify(sema, &name_ref) {
let is_self = name_ref.self_token().is_some();
let h = match NameRefClass::classify(sema, &name_ref) {
Some(name_kind) => match name_kind {
NameRefClass::ExternCrate(_) => HlTag::Symbol(SymbolKind::Module).into(),
NameRefClass::Definition(def) => {
@ -108,6 +109,11 @@ pub(super) fn element(
highlight_name_ref_by_syntax(name_ref, sema)
}
None => HlTag::UnresolvedReference.into(),
};
if h.tag == HlTag::Symbol(SymbolKind::Module) && is_self {
HlTag::Symbol(SymbolKind::SelfParam).into()
} else {
h
}
})
}
@ -225,18 +231,8 @@ pub(super) fn element(
T![for] if !is_child_of_impl(&element) => h | HlMod::ControlFlow,
T![unsafe] => h | HlMod::Unsafe,
T![true] | T![false] => HlTag::BoolLiteral.into(),
T![self] => {
let self_param = element.parent().and_then(ast::SelfParam::cast);
if let Some(NameClass::Definition(def)) = self_param
.and_then(|self_param| NameClass::classify_self_param(sema, &self_param))
{
highlight_def(db, def) | HlMod::Definition
} else if element.ancestors().any(|it| it.kind() == USE_TREE) {
HlTag::Symbol(SymbolKind::SelfParam).into()
} else {
return None;
}
}
// self is handled as either a Name or NameRef already
T![self] => return None,
T![ref] => element
.parent()
.and_then(ast::IdentPat::cast)