diff options
author | Aleksey Kladov <[email protected]> | 2020-02-18 17:35:10 +0000 |
---|---|---|
committer | Aleksey Kladov <[email protected]> | 2020-02-26 11:55:50 +0000 |
commit | c3a4c4429de83450654795534e64e878a774a088 (patch) | |
tree | 12d89798f61b276f8bd640db07276a7d4e92b1c2 /crates/ra_ide/src/references/classify.rs | |
parent | 04deae3dba7c9b7054f7a1d64e4b93a05aecc132 (diff) |
Refactor primary IDE API
This introduces the new type -- Semantics.
Semantics maps SyntaxNodes to various semantic info, such as type,
name resolution or macro expansions.
To do so, Semantics maintains a HashMap which maps every node it saw
to the file from which the node originated. This is enough to get all
the necessary hir bits just from syntax.
Diffstat (limited to 'crates/ra_ide/src/references/classify.rs')
-rw-r--r-- | crates/ra_ide/src/references/classify.rs | 30 |
1 files changed, 13 insertions, 17 deletions
diff --git a/crates/ra_ide/src/references/classify.rs b/crates/ra_ide/src/references/classify.rs index 478e18871..91b21429a 100644 --- a/crates/ra_ide/src/references/classify.rs +++ b/crates/ra_ide/src/references/classify.rs | |||
@@ -1,34 +1,32 @@ | |||
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::{InFile, PathResolution, SourceBinder}; | 3 | use hir::{PathResolution, Semantics}; |
4 | use ra_ide_db::defs::NameDefinition; | ||
5 | use ra_ide_db::RootDatabase; | ||
4 | use ra_prof::profile; | 6 | use ra_prof::profile; |
5 | use ra_syntax::{ast, AstNode}; | 7 | use ra_syntax::{ast, AstNode}; |
6 | use test_utils::tested_by; | 8 | use test_utils::tested_by; |
7 | 9 | ||
8 | use super::NameDefinition; | 10 | pub use ra_ide_db::defs::{from_module_def, from_struct_field}; |
9 | use ra_ide_db::RootDatabase; | ||
10 | |||
11 | pub use ra_ide_db::defs::{classify_name, from_module_def, from_struct_field}; | ||
12 | 11 | ||
13 | pub(crate) fn classify_name_ref( | 12 | pub(crate) fn classify_name_ref( |
14 | sb: &mut SourceBinder<RootDatabase>, | 13 | sema: &Semantics<RootDatabase>, |
15 | name_ref: InFile<&ast::NameRef>, | 14 | name_ref: &ast::NameRef, |
16 | ) -> Option<NameDefinition> { | 15 | ) -> Option<NameDefinition> { |
17 | let _p = profile("classify_name_ref"); | 16 | let _p = profile("classify_name_ref"); |
18 | 17 | ||
19 | let parent = name_ref.value.syntax().parent()?; | 18 | let parent = name_ref.syntax().parent()?; |
20 | let analyzer = sb.analyze(name_ref.map(|it| it.syntax()), None); | ||
21 | 19 | ||
22 | if let Some(method_call) = ast::MethodCallExpr::cast(parent.clone()) { | 20 | if let Some(method_call) = ast::MethodCallExpr::cast(parent.clone()) { |
23 | tested_by!(goto_def_for_methods); | 21 | tested_by!(goto_def_for_methods); |
24 | if let Some(func) = analyzer.resolve_method_call(&method_call) { | 22 | if let Some(func) = sema.resolve_method_call(&method_call) { |
25 | return Some(from_module_def(func.into())); | 23 | return Some(from_module_def(func.into())); |
26 | } | 24 | } |
27 | } | 25 | } |
28 | 26 | ||
29 | if let Some(field_expr) = ast::FieldExpr::cast(parent.clone()) { | 27 | if let Some(field_expr) = ast::FieldExpr::cast(parent.clone()) { |
30 | tested_by!(goto_def_for_fields); | 28 | tested_by!(goto_def_for_fields); |
31 | if let Some(field) = analyzer.resolve_field(&field_expr) { | 29 | if let Some(field) = sema.resolve_field(&field_expr) { |
32 | return Some(from_struct_field(field)); | 30 | return Some(from_struct_field(field)); |
33 | } | 31 | } |
34 | } | 32 | } |
@@ -36,22 +34,20 @@ pub(crate) fn classify_name_ref( | |||
36 | if let Some(record_field) = ast::RecordField::cast(parent.clone()) { | 34 | if let Some(record_field) = ast::RecordField::cast(parent.clone()) { |
37 | tested_by!(goto_def_for_record_fields); | 35 | tested_by!(goto_def_for_record_fields); |
38 | tested_by!(goto_def_for_field_init_shorthand); | 36 | tested_by!(goto_def_for_field_init_shorthand); |
39 | if let Some(field_def) = analyzer.resolve_record_field(&record_field) { | 37 | if let Some(field_def) = sema.resolve_record_field(&record_field) { |
40 | return Some(from_struct_field(field_def)); | 38 | return Some(from_struct_field(field_def)); |
41 | } | 39 | } |
42 | } | 40 | } |
43 | 41 | ||
44 | if let Some(macro_call) = parent.ancestors().find_map(ast::MacroCall::cast) { | 42 | if let Some(macro_call) = parent.ancestors().find_map(ast::MacroCall::cast) { |
45 | tested_by!(goto_def_for_macros); | 43 | tested_by!(goto_def_for_macros); |
46 | if let Some(macro_def) = | 44 | if let Some(macro_def) = sema.resolve_macro_call(¯o_call) { |
47 | analyzer.resolve_macro_call(sb.db, name_ref.with_value(¯o_call)) | ||
48 | { | ||
49 | return Some(NameDefinition::Macro(macro_def)); | 45 | return Some(NameDefinition::Macro(macro_def)); |
50 | } | 46 | } |
51 | } | 47 | } |
52 | 48 | ||
53 | let path = name_ref.value.syntax().ancestors().find_map(ast::Path::cast)?; | 49 | let path = name_ref.syntax().ancestors().find_map(ast::Path::cast)?; |
54 | let resolved = analyzer.resolve_path(sb.db, &path)?; | 50 | let resolved = sema.resolve_path(&path)?; |
55 | let res = match resolved { | 51 | let res = match resolved { |
56 | PathResolution::Def(def) => from_module_def(def), | 52 | PathResolution::Def(def) => from_module_def(def), |
57 | PathResolution::AssocItem(item) => { | 53 | PathResolution::AssocItem(item) => { |