diff options
Diffstat (limited to 'crates/ra_ide')
-rw-r--r-- | crates/ra_ide/src/completion/complete_dot.rs | 39 | ||||
-rw-r--r-- | crates/ra_ide/src/goto_definition.rs | 6 | ||||
-rw-r--r-- | crates/ra_ide/src/hover.rs | 2 | ||||
-rw-r--r-- | crates/ra_ide/src/references.rs | 8 | ||||
-rw-r--r-- | crates/ra_ide/src/references/classify.rs | 39 | ||||
-rw-r--r-- | crates/ra_ide/src/syntax_highlighting.rs | 30 |
6 files changed, 95 insertions, 29 deletions
diff --git a/crates/ra_ide/src/completion/complete_dot.rs b/crates/ra_ide/src/completion/complete_dot.rs index a6e0158b2..9145aa183 100644 --- a/crates/ra_ide/src/completion/complete_dot.rs +++ b/crates/ra_ide/src/completion/complete_dot.rs | |||
@@ -545,4 +545,43 @@ mod tests { | |||
545 | "### | 545 | "### |
546 | ) | 546 | ) |
547 | } | 547 | } |
548 | |||
549 | #[test] | ||
550 | fn test_super_super_completion() { | ||
551 | assert_debug_snapshot!( | ||
552 | do_ref_completion( | ||
553 | r" | ||
554 | mod a { | ||
555 | const A: usize = 0; | ||
556 | |||
557 | mod b { | ||
558 | const B: usize = 0; | ||
559 | |||
560 | mod c { | ||
561 | use super::super::<|> | ||
562 | } | ||
563 | } | ||
564 | } | ||
565 | ", | ||
566 | ), | ||
567 | @r###" | ||
568 | [ | ||
569 | CompletionItem { | ||
570 | label: "A", | ||
571 | source_range: [217; 217), | ||
572 | delete: [217; 217), | ||
573 | insert: "A", | ||
574 | kind: Const, | ||
575 | }, | ||
576 | CompletionItem { | ||
577 | label: "b", | ||
578 | source_range: [217; 217), | ||
579 | delete: [217; 217), | ||
580 | insert: "b", | ||
581 | kind: Module, | ||
582 | }, | ||
583 | ] | ||
584 | "### | ||
585 | ); | ||
586 | } | ||
548 | } | 587 | } |
diff --git a/crates/ra_ide/src/goto_definition.rs b/crates/ra_ide/src/goto_definition.rs index e67585203..76ee232a3 100644 --- a/crates/ra_ide/src/goto_definition.rs +++ b/crates/ra_ide/src/goto_definition.rs | |||
@@ -76,6 +76,8 @@ pub(crate) fn reference_definition( | |||
76 | 76 | ||
77 | let name_kind = classify_name_ref(sema, name_ref); | 77 | let name_kind = classify_name_ref(sema, name_ref); |
78 | if let Some(def) = name_kind { | 78 | if let Some(def) = name_kind { |
79 | let def = def.definition(); | ||
80 | |||
79 | return match def.try_to_nav(sema.db) { | 81 | return match def.try_to_nav(sema.db) { |
80 | Some(nav) => ReferenceResult::Exact(nav), | 82 | Some(nav) => ReferenceResult::Exact(nav), |
81 | None => ReferenceResult::Approximate(Vec::new()), | 83 | None => ReferenceResult::Approximate(Vec::new()), |
@@ -795,8 +797,8 @@ mod tests { | |||
795 | Foo { x<|> }; | 797 | Foo { x<|> }; |
796 | } | 798 | } |
797 | ", | 799 | ", |
798 | "x RECORD_FIELD_DEF FileId(1) [13; 19) [13; 14)", | 800 | "x BIND_PAT FileId(1) [42; 43)", |
799 | "x: i32|x", | 801 | "x", |
800 | ) | 802 | ) |
801 | } | 803 | } |
802 | } | 804 | } |
diff --git a/crates/ra_ide/src/hover.rs b/crates/ra_ide/src/hover.rs index 5073bb1cf..b31956626 100644 --- a/crates/ra_ide/src/hover.rs +++ b/crates/ra_ide/src/hover.rs | |||
@@ -153,7 +153,7 @@ pub(crate) fn hover(db: &RootDatabase, position: FilePosition) -> Option<RangeIn | |||
153 | if let Some((node, name_kind)) = match_ast! { | 153 | if let Some((node, name_kind)) = match_ast! { |
154 | match (token.parent()) { | 154 | match (token.parent()) { |
155 | ast::NameRef(name_ref) => { | 155 | ast::NameRef(name_ref) => { |
156 | classify_name_ref(&sema, &name_ref).map(|d| (name_ref.syntax().clone(), d)) | 156 | classify_name_ref(&sema, &name_ref).map(|d| (name_ref.syntax().clone(), d.definition())) |
157 | }, | 157 | }, |
158 | ast::Name(name) => { | 158 | ast::Name(name) => { |
159 | classify_name(&sema, &name).map(|d| (name.syntax().clone(), d.definition())) | 159 | classify_name(&sema, &name).map(|d| (name.syntax().clone(), d.definition())) |
diff --git a/crates/ra_ide/src/references.rs b/crates/ra_ide/src/references.rs index f763013ae..2eb047c96 100644 --- a/crates/ra_ide/src/references.rs +++ b/crates/ra_ide/src/references.rs | |||
@@ -27,7 +27,10 @@ use test_utils::tested_by; | |||
27 | 27 | ||
28 | use crate::{display::TryToNav, FilePosition, FileRange, NavigationTarget, RangeInfo}; | 28 | use crate::{display::TryToNav, FilePosition, FileRange, NavigationTarget, RangeInfo}; |
29 | 29 | ||
30 | pub(crate) use self::{classify::classify_name_ref, rename::rename}; | 30 | pub(crate) use self::{ |
31 | classify::{classify_name_ref, NameRefClass}, | ||
32 | rename::rename, | ||
33 | }; | ||
31 | pub(crate) use ra_ide_db::defs::{classify_name, NameDefinition}; | 34 | pub(crate) use ra_ide_db::defs::{classify_name, NameDefinition}; |
32 | 35 | ||
33 | pub use self::search_scope::SearchScope; | 36 | pub use self::search_scope::SearchScope; |
@@ -160,7 +163,7 @@ fn find_name( | |||
160 | return Some(RangeInfo::new(range, (name.text().to_string(), def))); | 163 | return Some(RangeInfo::new(range, (name.text().to_string(), def))); |
161 | } | 164 | } |
162 | let name_ref = find_node_at_offset::<ast::NameRef>(&syntax, position.offset)?; | 165 | let name_ref = find_node_at_offset::<ast::NameRef>(&syntax, position.offset)?; |
163 | let def = classify_name_ref(sema, &name_ref)?; | 166 | let def = classify_name_ref(sema, &name_ref)?.definition(); |
164 | let range = name_ref.syntax().text_range(); | 167 | let range = name_ref.syntax().text_range(); |
165 | Some(RangeInfo::new(range, (name_ref.text().to_string(), def))) | 168 | Some(RangeInfo::new(range, (name_ref.text().to_string(), def))) |
166 | } | 169 | } |
@@ -212,6 +215,7 @@ fn process_definition( | |||
212 | // See https://github.com/rust-lang/rust/pull/68198#issuecomment-574269098 | 215 | // See https://github.com/rust-lang/rust/pull/68198#issuecomment-574269098 |
213 | 216 | ||
214 | if let Some(d) = classify_name_ref(&sema, &name_ref) { | 217 | if let Some(d) = classify_name_ref(&sema, &name_ref) { |
218 | let d = d.definition(); | ||
215 | if d == def { | 219 | if d == def { |
216 | let kind = | 220 | let kind = |
217 | if is_record_lit_name_ref(&name_ref) || is_call_expr_name_ref(&name_ref) { | 221 | if is_record_lit_name_ref(&name_ref) || is_call_expr_name_ref(&name_ref) { |
diff --git a/crates/ra_ide/src/references/classify.rs b/crates/ra_ide/src/references/classify.rs index fdd07d8d1..571236fdc 100644 --- a/crates/ra_ide/src/references/classify.rs +++ b/crates/ra_ide/src/references/classify.rs | |||
@@ -1,18 +1,30 @@ | |||
1 | //! Functions that are used to classify an element from its definition or reference. | 1 | //! Functions that are used to classify an element from its definition or reference. |
2 | 2 | ||
3 | use hir::{PathResolution, Semantics}; | 3 | use hir::{Local, PathResolution, Semantics}; |
4 | use ra_ide_db::defs::NameDefinition; | 4 | use ra_ide_db::defs::NameDefinition; |
5 | use ra_ide_db::RootDatabase; | 5 | use ra_ide_db::RootDatabase; |
6 | use ra_prof::profile; | 6 | use ra_prof::profile; |
7 | use ra_syntax::{ast, AstNode}; | 7 | use ra_syntax::{ast, AstNode}; |
8 | use test_utils::tested_by; | 8 | use test_utils::tested_by; |
9 | 9 | ||
10 | pub use ra_ide_db::defs::{from_module_def, from_struct_field}; | 10 | pub enum NameRefClass { |
11 | NameDefinition(NameDefinition), | ||
12 | FieldShorthand { local: Local, field: NameDefinition }, | ||
13 | } | ||
14 | |||
15 | impl NameRefClass { | ||
16 | pub fn definition(self) -> NameDefinition { | ||
17 | match self { | ||
18 | NameRefClass::NameDefinition(def) => def, | ||
19 | NameRefClass::FieldShorthand { local, field: _ } => NameDefinition::Local(local), | ||
20 | } | ||
21 | } | ||
22 | } | ||
11 | 23 | ||
12 | pub(crate) fn classify_name_ref( | 24 | pub(crate) fn classify_name_ref( |
13 | sema: &Semantics<RootDatabase>, | 25 | sema: &Semantics<RootDatabase>, |
14 | name_ref: &ast::NameRef, | 26 | name_ref: &ast::NameRef, |
15 | ) -> Option<NameDefinition> { | 27 | ) -> Option<NameRefClass> { |
16 | let _p = profile("classify_name_ref"); | 28 | let _p = profile("classify_name_ref"); |
17 | 29 | ||
18 | let parent = name_ref.syntax().parent()?; | 30 | let parent = name_ref.syntax().parent()?; |
@@ -20,48 +32,53 @@ pub(crate) fn classify_name_ref( | |||
20 | if let Some(method_call) = ast::MethodCallExpr::cast(parent.clone()) { | 32 | if let Some(method_call) = ast::MethodCallExpr::cast(parent.clone()) { |
21 | tested_by!(goto_def_for_methods); | 33 | tested_by!(goto_def_for_methods); |
22 | if let Some(func) = sema.resolve_method_call(&method_call) { | 34 | if let Some(func) = sema.resolve_method_call(&method_call) { |
23 | return Some(from_module_def(func.into())); | 35 | return Some(NameRefClass::NameDefinition(NameDefinition::ModuleDef(func.into()))); |
24 | } | 36 | } |
25 | } | 37 | } |
26 | 38 | ||
27 | if let Some(field_expr) = ast::FieldExpr::cast(parent.clone()) { | 39 | if let Some(field_expr) = ast::FieldExpr::cast(parent.clone()) { |
28 | tested_by!(goto_def_for_fields); | 40 | tested_by!(goto_def_for_fields); |
29 | if let Some(field) = sema.resolve_field(&field_expr) { | 41 | if let Some(field) = sema.resolve_field(&field_expr) { |
30 | return Some(from_struct_field(field)); | 42 | return Some(NameRefClass::NameDefinition(NameDefinition::StructField(field))); |
31 | } | 43 | } |
32 | } | 44 | } |
33 | 45 | ||
34 | if let Some(record_field) = ast::RecordField::cast(parent.clone()) { | 46 | if let Some(record_field) = ast::RecordField::cast(parent.clone()) { |
35 | tested_by!(goto_def_for_record_fields); | 47 | tested_by!(goto_def_for_record_fields); |
36 | tested_by!(goto_def_for_field_init_shorthand); | 48 | tested_by!(goto_def_for_field_init_shorthand); |
37 | if let Some(field_def) = sema.resolve_record_field(&record_field) { | 49 | if let Some((field, local)) = sema.resolve_record_field(&record_field) { |
38 | return Some(from_struct_field(field_def)); | 50 | let field = NameDefinition::StructField(field); |
51 | let res = match local { | ||
52 | None => NameRefClass::NameDefinition(field), | ||
53 | Some(local) => NameRefClass::FieldShorthand { field, local }, | ||
54 | }; | ||
55 | return Some(res); | ||
39 | } | 56 | } |
40 | } | 57 | } |
41 | 58 | ||
42 | if let Some(macro_call) = parent.ancestors().find_map(ast::MacroCall::cast) { | 59 | if let Some(macro_call) = parent.ancestors().find_map(ast::MacroCall::cast) { |
43 | tested_by!(goto_def_for_macros); | 60 | tested_by!(goto_def_for_macros); |
44 | if let Some(macro_def) = sema.resolve_macro_call(¯o_call) { | 61 | if let Some(macro_def) = sema.resolve_macro_call(¯o_call) { |
45 | return Some(NameDefinition::Macro(macro_def)); | 62 | return Some(NameRefClass::NameDefinition(NameDefinition::Macro(macro_def))); |
46 | } | 63 | } |
47 | } | 64 | } |
48 | 65 | ||
49 | let path = name_ref.syntax().ancestors().find_map(ast::Path::cast)?; | 66 | let path = name_ref.syntax().ancestors().find_map(ast::Path::cast)?; |
50 | let resolved = sema.resolve_path(&path)?; | 67 | let resolved = sema.resolve_path(&path)?; |
51 | let res = match resolved { | 68 | let res = match resolved { |
52 | PathResolution::Def(def) => from_module_def(def), | 69 | PathResolution::Def(def) => NameDefinition::ModuleDef(def), |
53 | PathResolution::AssocItem(item) => { | 70 | PathResolution::AssocItem(item) => { |
54 | let def = match item { | 71 | let def = match item { |
55 | hir::AssocItem::Function(it) => it.into(), | 72 | hir::AssocItem::Function(it) => it.into(), |
56 | hir::AssocItem::Const(it) => it.into(), | 73 | hir::AssocItem::Const(it) => it.into(), |
57 | hir::AssocItem::TypeAlias(it) => it.into(), | 74 | hir::AssocItem::TypeAlias(it) => it.into(), |
58 | }; | 75 | }; |
59 | from_module_def(def) | 76 | NameDefinition::ModuleDef(def) |
60 | } | 77 | } |
61 | PathResolution::Local(local) => NameDefinition::Local(local), | 78 | PathResolution::Local(local) => NameDefinition::Local(local), |
62 | PathResolution::TypeParam(par) => NameDefinition::TypeParam(par), | 79 | PathResolution::TypeParam(par) => NameDefinition::TypeParam(par), |
63 | PathResolution::Macro(def) => NameDefinition::Macro(def), | 80 | PathResolution::Macro(def) => NameDefinition::Macro(def), |
64 | PathResolution::SelfType(impl_def) => NameDefinition::SelfType(impl_def), | 81 | PathResolution::SelfType(impl_def) => NameDefinition::SelfType(impl_def), |
65 | }; | 82 | }; |
66 | Some(res) | 83 | Some(NameRefClass::NameDefinition(res)) |
67 | } | 84 | } |
diff --git a/crates/ra_ide/src/syntax_highlighting.rs b/crates/ra_ide/src/syntax_highlighting.rs index 28117b4d8..b89501aff 100644 --- a/crates/ra_ide/src/syntax_highlighting.rs +++ b/crates/ra_ide/src/syntax_highlighting.rs | |||
@@ -19,7 +19,11 @@ use ra_syntax::{ | |||
19 | }; | 19 | }; |
20 | use rustc_hash::FxHashMap; | 20 | use rustc_hash::FxHashMap; |
21 | 21 | ||
22 | use crate::{call_info::call_info_for_token, references::classify_name_ref, Analysis, FileId}; | 22 | use crate::{ |
23 | call_info::call_info_for_token, | ||
24 | references::{classify_name_ref, NameRefClass}, | ||
25 | Analysis, FileId, | ||
26 | }; | ||
23 | 27 | ||
24 | pub(crate) use html::highlight_as_html; | 28 | pub(crate) use html::highlight_as_html; |
25 | pub use tags::{Highlight, HighlightModifier, HighlightModifiers, HighlightTag}; | 29 | pub use tags::{Highlight, HighlightModifier, HighlightModifiers, HighlightTag}; |
@@ -186,24 +190,24 @@ fn highlight_element( | |||
186 | } | 190 | } |
187 | 191 | ||
188 | // Highlight references like the definitions they resolve to | 192 | // Highlight references like the definitions they resolve to |
189 | |||
190 | // Special-case field init shorthand | ||
191 | NAME_REF if element.parent().and_then(ast::RecordField::cast).is_some() => { | ||
192 | HighlightTag::Field.into() | ||
193 | } | ||
194 | NAME_REF if element.ancestors().any(|it| it.kind() == ATTR) => return None, | 193 | NAME_REF if element.ancestors().any(|it| it.kind() == ATTR) => return None, |
195 | NAME_REF => { | 194 | NAME_REF => { |
196 | let name_ref = element.into_node().and_then(ast::NameRef::cast).unwrap(); | 195 | let name_ref = element.into_node().and_then(ast::NameRef::cast).unwrap(); |
197 | let name_kind = classify_name_ref(sema, &name_ref)?; | 196 | let name_kind = classify_name_ref(sema, &name_ref)?; |
198 | 197 | ||
199 | if let NameDefinition::Local(local) = &name_kind { | 198 | match name_kind { |
200 | if let Some(name) = local.name(db) { | 199 | NameRefClass::NameDefinition(def) => { |
201 | let shadow_count = bindings_shadow_count.entry(name.clone()).or_default(); | 200 | if let NameDefinition::Local(local) = &def { |
202 | binding_hash = Some(calc_binding_hash(&name, *shadow_count)) | 201 | if let Some(name) = local.name(db) { |
202 | let shadow_count = | ||
203 | bindings_shadow_count.entry(name.clone()).or_default(); | ||
204 | binding_hash = Some(calc_binding_hash(&name, *shadow_count)) | ||
205 | } | ||
206 | }; | ||
207 | highlight_name(db, def) | ||
203 | } | 208 | } |
204 | }; | 209 | NameRefClass::FieldShorthand { .. } => HighlightTag::Field.into(), |
205 | 210 | } | |
206 | highlight_name(db, name_kind) | ||
207 | } | 211 | } |
208 | 212 | ||
209 | // Simple token-based highlighting | 213 | // Simple token-based highlighting |