mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-08-30 23:27:24 +00:00
Wrap remaining self/super/crate in Name{Ref}
This commit is contained in:
parent
8a869e870a
commit
98718e0544
28 changed files with 237 additions and 169 deletions
|
@ -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(),
|
||||
|
|
|
@ -55,11 +55,6 @@ pub(crate) fn goto_definition(
|
|||
} else {
|
||||
reference_definition(&sema, Either::Left(<)).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,
|
||||
}
|
||||
};
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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#"
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue