aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_analysis/src/imp.rs
diff options
context:
space:
mode:
authorbors[bot] <bors[bot]@users.noreply.github.com>2019-01-06 14:51:10 +0000
committerbors[bot] <bors[bot]@users.noreply.github.com>2019-01-06 14:51:10 +0000
commitcf0ce14351af03c620aca784ee2c03aad86b866e (patch)
treebffd84981df9cca1143807796dc6772ddcfe8e0b /crates/ra_analysis/src/imp.rs
parenteaf553dade9a28b41631387d7c88b09fd0ba64e2 (diff)
parent733383446fc229a35d4432d14c295c5a01e5a87f (diff)
Merge #429
429: Reorganize hir public API in terms of code model r=matklad a=matklad Recently, I've been thinking about introducing "object orient code model" API for rust: a set of APIs with types like `Function`, `Module`, etc, with methods like `get_containing_declaration()`, `get_type()`, etc. Here's how a similar API might look like in .Net land: https://docs.microsoft.com/en-us/dotnet/api/microsoft.codeanalysis.semanticmodel?view=roslyn-dotnet https://docs.microsoft.com/en-us/dotnet/api/microsoft.codeanalysis.imethodsymbol?view=roslyn-dotnet The main feature of such API is that it can be powered by different backends. For example, one can imagine a backend based on salsa, and a backend which reads all the data from a specially prepared JSON file. The "OO" bit is interesting mostly in this "can swap implementations via dynamic dispatch" aspect, the actual API could have a more database/ECS flavored feeling. It's not clear at this moment how exactly should we implement such a dynamically (or if we even need dynamism in the first pace) swapable API in Rust, but I'd love to experiment with this a bit. For starters, I propose creating a `code_model_api` which contains various definition types and their public methods (mandatory implemented as one-liners, so that the API has a header-file feel). Specifically, I propose that each type is a wrapper around some integer ID, and that all methods of it accept a `&db` argument. The actual impl goes elsewhere: into the db queries or, absent a better place, into the `code_model_api_impl`. In the first commit, I've moved the simplest type, `Crate`, over to this pattern. I *think* that we, at least initially, will be used types from `code_model_api` *inside* `hir` as well, but this is not required: we might pick a different implementation down the line, while preserving the API. Long term I'd love to replace the `db: &impl HirDatabase` argument by a `mp: &dyn ModelProvider`, implement `ModelProvider` for `T: HirDatabase`, and move `code_model_api` into the separate crate, which does not depend on `hir`. @flodiebold you've recently done some `Def`s work, would do you think of this plan? Could it become a good API in the future, or is it just a useless boilerplate duplicating method signatures between `code_model_api` and `code_model_impl`? Co-authored-by: Aleksey Kladov <[email protected]>
Diffstat (limited to 'crates/ra_analysis/src/imp.rs')
-rw-r--r--crates/ra_analysis/src/imp.rs30
1 files changed, 13 insertions, 17 deletions
diff --git a/crates/ra_analysis/src/imp.rs b/crates/ra_analysis/src/imp.rs
index 5988fb779..07a966290 100644
--- a/crates/ra_analysis/src/imp.rs
+++ b/crates/ra_analysis/src/imp.rs
@@ -105,39 +105,35 @@ impl db::RootDatabase {
105 &self, 105 &self,
106 position: FilePosition, 106 position: FilePosition,
107 ) -> Cancelable<Vec<NavigationTarget>> { 107 ) -> Cancelable<Vec<NavigationTarget>> {
108 let descr = match source_binder::module_from_position(self, position)? { 108 let module = match source_binder::module_from_position(self, position)? {
109 None => return Ok(Vec::new()), 109 None => return Ok(Vec::new()),
110 Some(it) => it, 110 Some(it) => it,
111 }; 111 };
112 let (file_id, decl) = match descr.parent_link_source(self) { 112 let (file_id, ast_module) = match module.declaration_source(self)? {
113 None => return Ok(Vec::new()), 113 None => return Ok(Vec::new()),
114 Some(it) => it, 114 Some(it) => it,
115 }; 115 };
116 let decl = decl.borrowed(); 116 let ast_module = ast_module.borrowed();
117 let decl_name = decl.name().unwrap(); 117 let name = ast_module.name().unwrap();
118 Ok(vec![NavigationTarget { 118 Ok(vec![NavigationTarget {
119 file_id, 119 file_id,
120 name: decl_name.text(), 120 name: name.text(),
121 range: decl_name.syntax().range(), 121 range: name.syntax().range(),
122 kind: MODULE, 122 kind: MODULE,
123 ptr: None, 123 ptr: None,
124 }]) 124 }])
125 } 125 }
126 /// Returns `Vec` for the same reason as `parent_module` 126 /// Returns `Vec` for the same reason as `parent_module`
127 pub(crate) fn crate_for(&self, file_id: FileId) -> Cancelable<Vec<CrateId>> { 127 pub(crate) fn crate_for(&self, file_id: FileId) -> Cancelable<Vec<CrateId>> {
128 let descr = match source_binder::module_from_file_id(self, file_id)? { 128 let module = match source_binder::module_from_file_id(self, file_id)? {
129 Some(it) => it,
129 None => return Ok(Vec::new()), 130 None => return Ok(Vec::new()),
131 };
132 let krate = match module.krate(self)? {
130 Some(it) => it, 133 Some(it) => it,
134 None => return Ok(Vec::new()),
131 }; 135 };
132 let root = descr.crate_root(); 136 Ok(vec![krate.crate_id()])
133 let file_id = root.file_id();
134
135 let crate_graph = self.crate_graph();
136 let crate_id = crate_graph.crate_id_for_crate_root(file_id);
137 Ok(crate_id.into_iter().collect())
138 }
139 pub(crate) fn crate_root(&self, crate_id: CrateId) -> FileId {
140 self.crate_graph().crate_root(crate_id)
141 } 137 }
142 pub(crate) fn find_all_refs( 138 pub(crate) fn find_all_refs(
143 &self, 139 &self,
@@ -209,7 +205,7 @@ impl db::RootDatabase {
209 }) 205 })
210 .collect::<Vec<_>>(); 206 .collect::<Vec<_>>();
211 if let Some(m) = source_binder::module_from_file_id(self, file_id)? { 207 if let Some(m) = source_binder::module_from_file_id(self, file_id)? {
212 for (name_node, problem) in m.problems(self) { 208 for (name_node, problem) in m.problems(self)? {
213 let source_root = self.file_source_root(file_id); 209 let source_root = self.file_source_root(file_id);
214 let diag = match problem { 210 let diag = match problem {
215 Problem::UnresolvedModule { candidate } => { 211 Problem::UnresolvedModule { candidate } => {