diff options
author | Aleksey Kladov <aleksey.kladov@gmail.com> | 2020-02-18 17:35:10 +0000 |
---|---|---|
committer | Aleksey Kladov <aleksey.kladov@gmail.com> | 2020-02-26 11:55:50 +0000 |
commit | c3a4c4429de83450654795534e64e878a774a088 (patch) | |
tree | 12d89798f61b276f8bd640db07276a7d4e92b1c2 /crates/ra_ide_db/src | |
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_db/src')
-rw-r--r-- | crates/ra_ide_db/src/defs.rs | 50 | ||||
-rw-r--r-- | crates/ra_ide_db/src/imports_locator.rs | 26 |
2 files changed, 27 insertions, 49 deletions
diff --git a/crates/ra_ide_db/src/defs.rs b/crates/ra_ide_db/src/defs.rs index 04c214624..e10e72f71 100644 --- a/crates/ra_ide_db/src/defs.rs +++ b/crates/ra_ide_db/src/defs.rs | |||
@@ -6,8 +6,8 @@ | |||
6 | // FIXME: this badly needs rename/rewrite (matklad, 2020-02-06). | 6 | // FIXME: this badly needs rename/rewrite (matklad, 2020-02-06). |
7 | 7 | ||
8 | use hir::{ | 8 | use hir::{ |
9 | Adt, FieldSource, HasSource, ImplBlock, InFile, Local, MacroDef, Module, ModuleDef, | 9 | Adt, FieldSource, HasSource, ImplBlock, Local, MacroDef, Module, ModuleDef, Semantics, |
10 | SourceBinder, StructField, TypeParam, | 10 | StructField, TypeParam, |
11 | }; | 11 | }; |
12 | use ra_prof::profile; | 12 | use ra_prof::profile; |
13 | use ra_syntax::{ | 13 | use ra_syntax::{ |
@@ -68,78 +68,62 @@ impl NameDefinition { | |||
68 | } | 68 | } |
69 | } | 69 | } |
70 | 70 | ||
71 | pub fn classify_name( | 71 | pub fn classify_name(sema: &Semantics<RootDatabase>, name: &ast::Name) -> Option<NameDefinition> { |
72 | sb: &mut SourceBinder<RootDatabase>, | ||
73 | name: InFile<&ast::Name>, | ||
74 | ) -> Option<NameDefinition> { | ||
75 | let _p = profile("classify_name"); | 72 | let _p = profile("classify_name"); |
76 | let parent = name.value.syntax().parent()?; | 73 | let parent = name.syntax().parent()?; |
77 | 74 | ||
78 | match_ast! { | 75 | match_ast! { |
79 | match parent { | 76 | match parent { |
80 | ast::BindPat(it) => { | 77 | ast::BindPat(it) => { |
81 | let src = name.with_value(it); | 78 | let local = sema.to_def(&it)?; |
82 | let local = sb.to_def(src)?; | ||
83 | Some(NameDefinition::Local(local)) | 79 | Some(NameDefinition::Local(local)) |
84 | }, | 80 | }, |
85 | ast::RecordFieldDef(it) => { | 81 | ast::RecordFieldDef(it) => { |
86 | let src = name.with_value(it); | 82 | let field: hir::StructField = sema.to_def(&it)?; |
87 | let field: hir::StructField = sb.to_def(src)?; | ||
88 | Some(from_struct_field(field)) | 83 | Some(from_struct_field(field)) |
89 | }, | 84 | }, |
90 | ast::Module(it) => { | 85 | ast::Module(it) => { |
91 | let def = sb.to_def(name.with_value(it))?; | 86 | let def = sema.to_def(&it)?; |
92 | Some(from_module_def(def.into())) | 87 | Some(from_module_def(def.into())) |
93 | }, | 88 | }, |
94 | ast::StructDef(it) => { | 89 | ast::StructDef(it) => { |
95 | let src = name.with_value(it); | 90 | let def: hir::Struct = sema.to_def(&it)?; |
96 | let def: hir::Struct = sb.to_def(src)?; | ||
97 | Some(from_module_def(def.into())) | 91 | Some(from_module_def(def.into())) |
98 | }, | 92 | }, |
99 | ast::EnumDef(it) => { | 93 | ast::EnumDef(it) => { |
100 | let src = name.with_value(it); | 94 | let def: hir::Enum = sema.to_def(&it)?; |
101 | let def: hir::Enum = sb.to_def(src)?; | ||
102 | Some(from_module_def(def.into())) | 95 | Some(from_module_def(def.into())) |
103 | }, | 96 | }, |
104 | ast::TraitDef(it) => { | 97 | ast::TraitDef(it) => { |
105 | let src = name.with_value(it); | 98 | let def: hir::Trait = sema.to_def(&it)?; |
106 | let def: hir::Trait = sb.to_def(src)?; | ||
107 | Some(from_module_def(def.into())) | 99 | Some(from_module_def(def.into())) |
108 | }, | 100 | }, |
109 | ast::StaticDef(it) => { | 101 | ast::StaticDef(it) => { |
110 | let src = name.with_value(it); | 102 | let def: hir::Static = sema.to_def(&it)?; |
111 | let def: hir::Static = sb.to_def(src)?; | ||
112 | Some(from_module_def(def.into())) | 103 | Some(from_module_def(def.into())) |
113 | }, | 104 | }, |
114 | ast::EnumVariant(it) => { | 105 | ast::EnumVariant(it) => { |
115 | let src = name.with_value(it); | 106 | let def: hir::EnumVariant = sema.to_def(&it)?; |
116 | let def: hir::EnumVariant = sb.to_def(src)?; | ||
117 | Some(from_module_def(def.into())) | 107 | Some(from_module_def(def.into())) |
118 | }, | 108 | }, |
119 | ast::FnDef(it) => { | 109 | ast::FnDef(it) => { |
120 | let src = name.with_value(it); | 110 | let def: hir::Function = sema.to_def(&it)?; |
121 | let def: hir::Function = sb.to_def(src)?; | ||
122 | Some(from_module_def(def.into())) | 111 | Some(from_module_def(def.into())) |
123 | }, | 112 | }, |
124 | ast::ConstDef(it) => { | 113 | ast::ConstDef(it) => { |
125 | let src = name.with_value(it); | 114 | let def: hir::Const = sema.to_def(&it)?; |
126 | let def: hir::Const = sb.to_def(src)?; | ||
127 | Some(from_module_def(def.into())) | 115 | Some(from_module_def(def.into())) |
128 | }, | 116 | }, |
129 | ast::TypeAliasDef(it) => { | 117 | ast::TypeAliasDef(it) => { |
130 | let src = name.with_value(it); | 118 | let def: hir::TypeAlias = sema.to_def(&it)?; |
131 | let def: hir::TypeAlias = sb.to_def(src)?; | ||
132 | Some(from_module_def(def.into())) | 119 | Some(from_module_def(def.into())) |
133 | }, | 120 | }, |
134 | ast::MacroCall(it) => { | 121 | ast::MacroCall(it) => { |
135 | let src = name.with_value(it); | 122 | let def = sema.to_def(&it)?; |
136 | let def = sb.to_def(src.clone())?; | ||
137 | |||
138 | Some(NameDefinition::Macro(def)) | 123 | Some(NameDefinition::Macro(def)) |
139 | }, | 124 | }, |
140 | ast::TypeParam(it) => { | 125 | ast::TypeParam(it) => { |
141 | let src = name.with_value(it); | 126 | let def = sema.to_def(&it)?; |
142 | let def = sb.to_def(src)?; | ||
143 | Some(NameDefinition::TypeParam(def)) | 127 | Some(NameDefinition::TypeParam(def)) |
144 | }, | 128 | }, |
145 | _ => None, | 129 | _ => None, |
diff --git a/crates/ra_ide_db/src/imports_locator.rs b/crates/ra_ide_db/src/imports_locator.rs index b8dd358a9..e590d2a5c 100644 --- a/crates/ra_ide_db/src/imports_locator.rs +++ b/crates/ra_ide_db/src/imports_locator.rs | |||
@@ -1,7 +1,7 @@ | |||
1 | //! This module contains an import search funcionality that is provided to the ra_assists module. | 1 | //! This module contains an import search funcionality that is provided to the ra_assists module. |
2 | //! Later, this should be moved away to a separate crate that is accessible from the ra_assists module. | 2 | //! Later, this should be moved away to a separate crate that is accessible from the ra_assists module. |
3 | 3 | ||
4 | use hir::{db::HirDatabase, ModuleDef, SourceBinder}; | 4 | use hir::{ModuleDef, Semantics}; |
5 | use ra_prof::profile; | 5 | use ra_prof::profile; |
6 | use ra_syntax::{ast, AstNode, SyntaxKind::NAME}; | 6 | use ra_syntax::{ast, AstNode, SyntaxKind::NAME}; |
7 | 7 | ||
@@ -12,17 +12,17 @@ use crate::{ | |||
12 | }; | 12 | }; |
13 | 13 | ||
14 | pub struct ImportsLocator<'a> { | 14 | pub struct ImportsLocator<'a> { |
15 | source_binder: SourceBinder<'a, RootDatabase>, | 15 | sema: Semantics<'a, RootDatabase>, |
16 | } | 16 | } |
17 | 17 | ||
18 | impl<'a> ImportsLocator<'a> { | 18 | impl<'a> ImportsLocator<'a> { |
19 | pub fn new(db: &'a RootDatabase) -> Self { | 19 | pub fn new(db: &'a RootDatabase) -> Self { |
20 | Self { source_binder: SourceBinder::new(db) } | 20 | Self { sema: Semantics::new(db) } |
21 | } | 21 | } |
22 | 22 | ||
23 | pub fn find_imports(&mut self, name_to_import: &str) -> Vec<ModuleDef> { | 23 | pub fn find_imports(&mut self, name_to_import: &str) -> Vec<ModuleDef> { |
24 | let _p = profile("search_for_imports"); | 24 | let _p = profile("search_for_imports"); |
25 | let db = self.source_binder.db; | 25 | let db = self.sema.db; |
26 | 26 | ||
27 | let project_results = { | 27 | let project_results = { |
28 | let mut query = Query::new(name_to_import.to_string()); | 28 | let mut query = Query::new(name_to_import.to_string()); |
@@ -41,7 +41,7 @@ impl<'a> ImportsLocator<'a> { | |||
41 | project_results | 41 | project_results |
42 | .into_iter() | 42 | .into_iter() |
43 | .chain(lib_results.into_iter()) | 43 | .chain(lib_results.into_iter()) |
44 | .filter_map(|import_candidate| self.get_name_definition(db, &import_candidate)) | 44 | .filter_map(|import_candidate| self.get_name_definition(&import_candidate)) |
45 | .filter_map(|name_definition_to_import| match name_definition_to_import { | 45 | .filter_map(|name_definition_to_import| match name_definition_to_import { |
46 | NameDefinition::ModuleDef(module_def) => Some(module_def), | 46 | NameDefinition::ModuleDef(module_def) => Some(module_def), |
47 | _ => None, | 47 | _ => None, |
@@ -49,22 +49,16 @@ impl<'a> ImportsLocator<'a> { | |||
49 | .collect() | 49 | .collect() |
50 | } | 50 | } |
51 | 51 | ||
52 | fn get_name_definition( | 52 | fn get_name_definition(&mut self, import_candidate: &FileSymbol) -> Option<NameDefinition> { |
53 | &mut self, | ||
54 | db: &impl HirDatabase, | ||
55 | import_candidate: &FileSymbol, | ||
56 | ) -> Option<NameDefinition> { | ||
57 | let _p = profile("get_name_definition"); | 53 | let _p = profile("get_name_definition"); |
58 | let file_id = import_candidate.file_id.into(); | 54 | let file_id = import_candidate.file_id; |
59 | let candidate_node = import_candidate.ptr.to_node(&db.parse_or_expand(file_id)?); | 55 | |
56 | let candidate_node = import_candidate.ptr.to_node(self.sema.parse(file_id).syntax()); | ||
60 | let candidate_name_node = if candidate_node.kind() != NAME { | 57 | let candidate_name_node = if candidate_node.kind() != NAME { |
61 | candidate_node.children().find(|it| it.kind() == NAME)? | 58 | candidate_node.children().find(|it| it.kind() == NAME)? |
62 | } else { | 59 | } else { |
63 | candidate_node | 60 | candidate_node |
64 | }; | 61 | }; |
65 | classify_name( | 62 | classify_name(&self.sema, &ast::Name::cast(candidate_name_node)?) |
66 | &mut self.source_binder, | ||
67 | hir::InFile { file_id, value: &ast::Name::cast(candidate_name_node)? }, | ||
68 | ) | ||
69 | } | 63 | } |
70 | } | 64 | } |