diff options
Diffstat (limited to 'crates/ide/src')
-rw-r--r-- | crates/ide/src/display/navigation_target.rs | 14 | ||||
-rw-r--r-- | crates/ide/src/goto_definition.rs | 5 | ||||
-rw-r--r-- | crates/ide/src/hover.rs | 5 | ||||
-rw-r--r-- | crates/ide/src/references/rename.rs | 76 | ||||
-rw-r--r-- | crates/ide/src/syntax_highlighting/highlight.rs | 22 |
5 files changed, 49 insertions, 73 deletions
diff --git a/crates/ide/src/display/navigation_target.rs b/crates/ide/src/display/navigation_target.rs index 685052e7f..00e601244 100644 --- a/crates/ide/src/display/navigation_target.rs +++ b/crates/ide/src/display/navigation_target.rs | |||
@@ -400,15 +400,13 @@ impl TryToNav for hir::GenericParam { | |||
400 | impl ToNav for hir::Local { | 400 | impl ToNav for hir::Local { |
401 | fn to_nav(&self, db: &RootDatabase) -> NavigationTarget { | 401 | fn to_nav(&self, db: &RootDatabase) -> NavigationTarget { |
402 | let src = self.source(db); | 402 | let src = self.source(db); |
403 | let (node, focus_range) = match &src.value { | 403 | let (node, name) = match &src.value { |
404 | Either::Left(bind_pat) => ( | 404 | Either::Left(bind_pat) => (bind_pat.syntax().clone(), bind_pat.name()), |
405 | bind_pat.syntax().clone(), | 405 | Either::Right(it) => (it.syntax().clone(), it.name()), |
406 | bind_pat | ||
407 | .name() | ||
408 | .map(|it| src.with_value(&it.syntax().clone()).original_file_range(db).range), | ||
409 | ), | ||
410 | Either::Right(it) => (it.syntax().clone(), it.self_token().map(|it| it.text_range())), | ||
411 | }; | 406 | }; |
407 | let focus_range = | ||
408 | name.map(|it| src.with_value(&it.syntax().clone()).original_file_range(db).range); | ||
409 | |||
412 | let full_range = src.with_value(&node).original_file_range(db); | 410 | let full_range = src.with_value(&node).original_file_range(db); |
413 | let name = match self.name(db) { | 411 | let name = match self.name(db) { |
414 | Some(it) => it.to_string().into(), | 412 | Some(it) => it.to_string().into(), |
diff --git a/crates/ide/src/goto_definition.rs b/crates/ide/src/goto_definition.rs index 988a5668f..a1d2bce1d 100644 --- a/crates/ide/src/goto_definition.rs +++ b/crates/ide/src/goto_definition.rs | |||
@@ -55,11 +55,6 @@ pub(crate) fn goto_definition( | |||
55 | } else { | 55 | } else { |
56 | reference_definition(&sema, Either::Left(<)).to_vec() | 56 | reference_definition(&sema, Either::Left(<)).to_vec() |
57 | }, | 57 | }, |
58 | ast::SelfParam(self_param) => { | ||
59 | let def = NameClass::classify_self_param(&sema, &self_param)?.referenced_or_defined(sema.db); | ||
60 | let nav = def.try_to_nav(sema.db)?; | ||
61 | vec![nav] | ||
62 | }, | ||
63 | _ => return None, | 58 | _ => return None, |
64 | } | 59 | } |
65 | }; | 60 | }; |
diff --git a/crates/ide/src/hover.rs b/crates/ide/src/hover.rs index 6022bd275..2024acd94 100644 --- a/crates/ide/src/hover.rs +++ b/crates/ide/src/hover.rs | |||
@@ -98,7 +98,6 @@ pub(crate) fn hover( | |||
98 | ast::NameRef(name_ref) => NameRefClass::classify(&sema, &name_ref).map(|d| d.referenced(sema.db)), | 98 | ast::NameRef(name_ref) => NameRefClass::classify(&sema, &name_ref).map(|d| d.referenced(sema.db)), |
99 | ast::Lifetime(lifetime) => NameClass::classify_lifetime(&sema, &lifetime) | 99 | ast::Lifetime(lifetime) => NameClass::classify_lifetime(&sema, &lifetime) |
100 | .map_or_else(|| NameRefClass::classify_lifetime(&sema, &lifetime).map(|d| d.referenced(sema.db)), |d| d.defined(sema.db)), | 100 | .map_or_else(|| NameRefClass::classify_lifetime(&sema, &lifetime).map(|d| d.referenced(sema.db)), |d| d.defined(sema.db)), |
101 | ast::SelfParam(self_param) => NameClass::classify_self_param(&sema, &self_param).and_then(|d| d.defined(sema.db)), | ||
102 | _ => None, | 101 | _ => None, |
103 | } | 102 | } |
104 | }; | 103 | }; |
@@ -3223,7 +3222,7 @@ impl Foo { | |||
3223 | } | 3222 | } |
3224 | "#, | 3223 | "#, |
3225 | expect![[r#" | 3224 | expect![[r#" |
3226 | *&self* | 3225 | *self* |
3227 | 3226 | ||
3228 | ```rust | 3227 | ```rust |
3229 | &Foo | 3228 | &Foo |
@@ -3243,7 +3242,7 @@ impl Foo { | |||
3243 | } | 3242 | } |
3244 | "#, | 3243 | "#, |
3245 | expect![[r#" | 3244 | expect![[r#" |
3246 | *self: Arc<Foo>* | 3245 | *self* |
3247 | 3246 | ||
3248 | ```rust | 3247 | ```rust |
3249 | Arc<Foo> | 3248 | Arc<Foo> |
diff --git a/crates/ide/src/references/rename.rs b/crates/ide/src/references/rename.rs index 9ac4af026..4df189c98 100644 --- a/crates/ide/src/references/rename.rs +++ b/crates/ide/src/references/rename.rs | |||
@@ -1,12 +1,9 @@ | |||
1 | //! FIXME: write short doc here | 1 | //! FIXME: write short doc here |
2 | use std::{ | 2 | use std::fmt::{self, Display}; |
3 | convert::TryInto, | ||
4 | fmt::{self, Display}, | ||
5 | }; | ||
6 | 3 | ||
7 | use hir::{Module, ModuleDef, ModuleSource, Semantics}; | 4 | use hir::{Module, ModuleDef, ModuleSource, Semantics}; |
8 | use ide_db::{ | 5 | use ide_db::{ |
9 | base_db::{AnchoredPathBuf, FileId, FileRange, SourceDatabaseExt}, | 6 | base_db::{AnchoredPathBuf, FileId, FileRange}, |
10 | defs::{Definition, NameClass, NameRefClass}, | 7 | defs::{Definition, NameClass, NameRefClass}, |
11 | search::FileReference, | 8 | search::FileReference, |
12 | RootDatabase, | 9 | RootDatabase, |
@@ -14,14 +11,14 @@ use ide_db::{ | |||
14 | use syntax::{ | 11 | use syntax::{ |
15 | algo::find_node_at_offset, | 12 | algo::find_node_at_offset, |
16 | ast::{self, NameOwner}, | 13 | ast::{self, NameOwner}, |
17 | lex_single_syntax_kind, match_ast, AstNode, SyntaxKind, SyntaxNode, SyntaxToken, T, | 14 | lex_single_syntax_kind, match_ast, AstNode, SyntaxKind, SyntaxNode, T, |
18 | }; | 15 | }; |
19 | use test_utils::mark; | 16 | use test_utils::mark; |
20 | use text_edit::TextEdit; | 17 | use text_edit::TextEdit; |
21 | 18 | ||
22 | use crate::{ | 19 | use crate::{ |
23 | FilePosition, FileSystemEdit, RangeInfo, ReferenceKind, ReferenceSearchResult, SourceChange, | 20 | FilePosition, FileSystemEdit, RangeInfo, ReferenceKind, ReferenceSearchResult, SourceChange, |
24 | TextRange, TextSize, | 21 | TextRange, |
25 | }; | 22 | }; |
26 | 23 | ||
27 | type RenameResult<T> = Result<T, RenameError>; | 24 | type RenameResult<T> = Result<T, RenameError>; |
@@ -52,10 +49,6 @@ pub(crate) fn prepare_rename( | |||
52 | let syntax = source_file.syntax(); | 49 | let syntax = source_file.syntax(); |
53 | if let Some(module) = find_module_at_offset(&sema, position, syntax) { | 50 | if let Some(module) = find_module_at_offset(&sema, position, syntax) { |
54 | rename_mod(&sema, position, module, "dummy") | 51 | rename_mod(&sema, position, module, "dummy") |
55 | } else if let Some(self_token) = | ||
56 | syntax.token_at_offset(position.offset).find(|t| t.kind() == T![self]) | ||
57 | { | ||
58 | rename_self_to_param(&sema, position, self_token, "dummy") | ||
59 | } else { | 52 | } else { |
60 | let RangeInfo { range, .. } = find_all_refs(&sema, position)?; | 53 | let RangeInfo { range, .. } = find_all_refs(&sema, position)?; |
61 | Ok(RangeInfo::new(range, SourceChange::default())) | 54 | Ok(RangeInfo::new(range, SourceChange::default())) |
@@ -82,10 +75,6 @@ pub(crate) fn rename_with_semantics( | |||
82 | 75 | ||
83 | if let Some(module) = find_module_at_offset(&sema, position, syntax) { | 76 | if let Some(module) = find_module_at_offset(&sema, position, syntax) { |
84 | rename_mod(&sema, position, module, new_name) | 77 | rename_mod(&sema, position, module, new_name) |
85 | } else if let Some(self_token) = | ||
86 | syntax.token_at_offset(position.offset).find(|t| t.kind() == T![self]) | ||
87 | { | ||
88 | rename_self_to_param(&sema, position, self_token, new_name) | ||
89 | } else { | 78 | } else { |
90 | rename_reference(&sema, position, new_name) | 79 | rename_reference(&sema, position, new_name) |
91 | } | 80 | } |
@@ -108,7 +97,7 @@ pub(crate) fn will_rename_file( | |||
108 | Some(change) | 97 | Some(change) |
109 | } | 98 | } |
110 | 99 | ||
111 | #[derive(Debug, PartialEq)] | 100 | #[derive(Copy, Clone, Debug, PartialEq)] |
112 | enum IdentifierKind { | 101 | enum IdentifierKind { |
113 | Ident, | 102 | Ident, |
114 | Lifetime, | 103 | Lifetime, |
@@ -375,53 +364,50 @@ fn text_edit_from_self_param( | |||
375 | fn rename_self_to_param( | 364 | fn rename_self_to_param( |
376 | sema: &Semantics<RootDatabase>, | 365 | sema: &Semantics<RootDatabase>, |
377 | position: FilePosition, | 366 | position: FilePosition, |
378 | self_token: SyntaxToken, | ||
379 | new_name: &str, | 367 | new_name: &str, |
368 | ident_kind: IdentifierKind, | ||
369 | range: TextRange, | ||
370 | refs: ReferenceSearchResult, | ||
380 | ) -> Result<RangeInfo<SourceChange>, RenameError> { | 371 | ) -> Result<RangeInfo<SourceChange>, RenameError> { |
381 | let ident_kind = check_identifier(new_name)?; | ||
382 | match ident_kind { | 372 | match ident_kind { |
383 | IdentifierKind::Lifetime => bail!("Invalid name `{}`: not an identifier", new_name), | 373 | IdentifierKind::Lifetime => bail!("Invalid name `{}`: not an identifier", new_name), |
384 | IdentifierKind::ToSelf => { | 374 | IdentifierKind::ToSelf => { |
385 | // no-op | 375 | // no-op |
386 | mark::hit!(rename_self_to_self); | 376 | mark::hit!(rename_self_to_self); |
387 | return Ok(RangeInfo::new(self_token.text_range(), SourceChange::default())); | 377 | return Ok(RangeInfo::new(range, SourceChange::default())); |
388 | } | 378 | } |
389 | _ => (), | 379 | _ => (), |
390 | } | 380 | } |
391 | let source_file = sema.parse(position.file_id); | 381 | let source_file = sema.parse(position.file_id); |
392 | let syn = source_file.syntax(); | 382 | let syn = source_file.syntax(); |
393 | 383 | ||
394 | let text = sema.db.file_text(position.file_id); | ||
395 | let fn_def = find_node_at_offset::<ast::Fn>(syn, position.offset) | 384 | let fn_def = find_node_at_offset::<ast::Fn>(syn, position.offset) |
396 | .ok_or_else(|| format_err!("No surrounding method declaration found"))?; | 385 | .ok_or_else(|| format_err!("No surrounding method declaration found"))?; |
397 | let search_range = fn_def.syntax().text_range(); | ||
398 | 386 | ||
399 | let mut source_change = SourceChange::default(); | 387 | let mut source_change = SourceChange::default(); |
400 | 388 | if let Some(self_param) = fn_def.param_list().and_then(|it| it.self_param()) { | |
401 | for (idx, _) in text.match_indices("self") { | 389 | if self_param |
402 | let offset: TextSize = idx.try_into().unwrap(); | 390 | .syntax() |
403 | if !search_range.contains_inclusive(offset) { | 391 | .text_range() |
404 | continue; | 392 | .contains_range(refs.declaration().nav.focus_or_full_range()) |
405 | } | 393 | { |
406 | if let Some(ref usage) = syn.token_at_offset(offset).find(|t| t.kind() == T![self]) { | 394 | let edit = text_edit_from_self_param(syn, &self_param, new_name) |
407 | let edit = if let Some(ref self_param) = ast::SelfParam::cast(usage.parent()) { | 395 | .ok_or_else(|| format_err!("No target type found"))?; |
408 | text_edit_from_self_param(syn, self_param, new_name) | ||
409 | .ok_or_else(|| format_err!("No target type found"))? | ||
410 | } else { | ||
411 | TextEdit::replace(usage.text_range(), String::from(new_name)) | ||
412 | }; | ||
413 | source_change.insert_source_edit(position.file_id, edit); | 396 | source_change.insert_source_edit(position.file_id, edit); |
414 | } | ||
415 | } | ||
416 | 397 | ||
417 | if source_change.source_file_edits.len() > 1 && ident_kind == IdentifierKind::Underscore { | 398 | source_change.extend(refs.references().iter().map(|(&file_id, references)| { |
418 | bail!("Cannot rename reference to `_` as it is being referenced multiple times"); | 399 | source_edit_from_references(sema, file_id, &references, new_name) |
419 | } | 400 | })); |
420 | 401 | ||
421 | let range = ast::SelfParam::cast(self_token.parent()) | 402 | if source_change.source_file_edits.len() > 1 && ident_kind == IdentifierKind::Underscore |
422 | .map_or(self_token.text_range(), |p| p.syntax().text_range()); | 403 | { |
404 | bail!("Cannot rename reference to `_` as it is being referenced multiple times"); | ||
405 | } | ||
423 | 406 | ||
424 | Ok(RangeInfo::new(range, source_change)) | 407 | return Ok(RangeInfo::new(range, source_change)); |
408 | } | ||
409 | } | ||
410 | Err(format_err!("Method has no self param")) | ||
425 | } | 411 | } |
426 | 412 | ||
427 | fn rename_reference( | 413 | fn rename_reference( |
@@ -444,8 +430,9 @@ fn rename_reference( | |||
444 | mark::hit!(rename_not_an_ident_ref); | 430 | mark::hit!(rename_not_an_ident_ref); |
445 | bail!("Invalid name `{}`: not an identifier", new_name) | 431 | bail!("Invalid name `{}`: not an identifier", new_name) |
446 | } | 432 | } |
447 | (IdentifierKind::ToSelf, ReferenceKind::SelfParam) => { | 433 | (_, ReferenceKind::SelfParam) => { |
448 | unreachable!("rename_self_to_param should've been called instead") | 434 | mark::hit!(rename_self_to_param); |
435 | return rename_self_to_param(sema, position, new_name, ident_kind, range, refs); | ||
449 | } | 436 | } |
450 | (IdentifierKind::ToSelf, _) => { | 437 | (IdentifierKind::ToSelf, _) => { |
451 | mark::hit!(rename_to_self); | 438 | mark::hit!(rename_to_self); |
@@ -1350,6 +1337,7 @@ impl Foo { | |||
1350 | 1337 | ||
1351 | #[test] | 1338 | #[test] |
1352 | fn test_owned_self_to_parameter() { | 1339 | fn test_owned_self_to_parameter() { |
1340 | mark::check!(rename_self_to_param); | ||
1353 | check( | 1341 | check( |
1354 | "foo", | 1342 | "foo", |
1355 | r#" | 1343 | r#" |
diff --git a/crates/ide/src/syntax_highlighting/highlight.rs b/crates/ide/src/syntax_highlighting/highlight.rs index 87578e70a..8625ef5df 100644 --- a/crates/ide/src/syntax_highlighting/highlight.rs +++ b/crates/ide/src/syntax_highlighting/highlight.rs | |||
@@ -68,7 +68,8 @@ pub(super) fn element( | |||
68 | NAME_REF => { | 68 | NAME_REF => { |
69 | let name_ref = element.into_node().and_then(ast::NameRef::cast).unwrap(); | 69 | let name_ref = element.into_node().and_then(ast::NameRef::cast).unwrap(); |
70 | highlight_func_by_name_ref(sema, &name_ref).unwrap_or_else(|| { | 70 | highlight_func_by_name_ref(sema, &name_ref).unwrap_or_else(|| { |
71 | match NameRefClass::classify(sema, &name_ref) { | 71 | let is_self = name_ref.self_token().is_some(); |
72 | let h = match NameRefClass::classify(sema, &name_ref) { | ||
72 | Some(name_kind) => match name_kind { | 73 | Some(name_kind) => match name_kind { |
73 | NameRefClass::ExternCrate(_) => HlTag::Symbol(SymbolKind::Module).into(), | 74 | NameRefClass::ExternCrate(_) => HlTag::Symbol(SymbolKind::Module).into(), |
74 | NameRefClass::Definition(def) => { | 75 | NameRefClass::Definition(def) => { |
@@ -108,6 +109,11 @@ pub(super) fn element( | |||
108 | highlight_name_ref_by_syntax(name_ref, sema) | 109 | highlight_name_ref_by_syntax(name_ref, sema) |
109 | } | 110 | } |
110 | None => HlTag::UnresolvedReference.into(), | 111 | None => HlTag::UnresolvedReference.into(), |
112 | }; | ||
113 | if h.tag == HlTag::Symbol(SymbolKind::Module) && is_self { | ||
114 | HlTag::Symbol(SymbolKind::SelfParam).into() | ||
115 | } else { | ||
116 | h | ||
111 | } | 117 | } |
112 | }) | 118 | }) |
113 | } | 119 | } |
@@ -225,18 +231,8 @@ pub(super) fn element( | |||
225 | T![for] if !is_child_of_impl(&element) => h | HlMod::ControlFlow, | 231 | T![for] if !is_child_of_impl(&element) => h | HlMod::ControlFlow, |
226 | T![unsafe] => h | HlMod::Unsafe, | 232 | T![unsafe] => h | HlMod::Unsafe, |
227 | T![true] | T![false] => HlTag::BoolLiteral.into(), | 233 | T![true] | T![false] => HlTag::BoolLiteral.into(), |
228 | T![self] => { | 234 | // self is handled as either a Name or NameRef already |
229 | let self_param = element.parent().and_then(ast::SelfParam::cast); | 235 | T![self] => return None, |
230 | if let Some(NameClass::Definition(def)) = self_param | ||
231 | .and_then(|self_param| NameClass::classify_self_param(sema, &self_param)) | ||
232 | { | ||
233 | highlight_def(db, def) | HlMod::Definition | ||
234 | } else if element.ancestors().any(|it| it.kind() == USE_TREE) { | ||
235 | HlTag::Symbol(SymbolKind::SelfParam).into() | ||
236 | } else { | ||
237 | return None; | ||
238 | } | ||
239 | } | ||
240 | T![ref] => element | 236 | T![ref] => element |
241 | .parent() | 237 | .parent() |
242 | .and_then(ast::IdentPat::cast) | 238 | .and_then(ast::IdentPat::cast) |