diff options
Diffstat (limited to 'crates/ra_hir/src/code_model_api.rs')
-rw-r--r-- | crates/ra_hir/src/code_model_api.rs | 162 |
1 files changed, 105 insertions, 57 deletions
diff --git a/crates/ra_hir/src/code_model_api.rs b/crates/ra_hir/src/code_model_api.rs index 637ebb7ec..4447c608a 100644 --- a/crates/ra_hir/src/code_model_api.rs +++ b/crates/ra_hir/src/code_model_api.rs | |||
@@ -1,10 +1,10 @@ | |||
1 | use std::sync::Arc; | 1 | use std::sync::Arc; |
2 | 2 | ||
3 | use ra_db::{CrateId, SourceRootId, Edition}; | 3 | use ra_db::{CrateId, SourceRootId, Edition, FileId}; |
4 | use ra_syntax::{ast::self, TreeArc}; | 4 | use ra_syntax::{ast::self, TreeArc}; |
5 | 5 | ||
6 | use crate::{ | 6 | use crate::{ |
7 | Name, AsName, Ty, HirFileId, Either, | 7 | Name, AsName, AstId, Ty, HirFileId, Either, |
8 | HirDatabase, DefDatabase, | 8 | HirDatabase, DefDatabase, |
9 | type_ref::TypeRef, | 9 | type_ref::TypeRef, |
10 | nameres::{ModuleScope, Namespace, ImportId, CrateModuleId}, | 10 | nameres::{ModuleScope, Namespace, ImportId, CrateModuleId}, |
@@ -107,29 +107,66 @@ pub enum ModuleSource { | |||
107 | Module(TreeArc<ast::Module>), | 107 | Module(TreeArc<ast::Module>), |
108 | } | 108 | } |
109 | 109 | ||
110 | impl ModuleSource { | ||
111 | pub(crate) fn new( | ||
112 | db: &impl DefDatabase, | ||
113 | file_id: Option<FileId>, | ||
114 | decl_id: Option<AstId<ast::Module>>, | ||
115 | ) -> ModuleSource { | ||
116 | match (file_id, decl_id) { | ||
117 | (Some(file_id), _) => { | ||
118 | let source_file = db.parse(file_id); | ||
119 | ModuleSource::SourceFile(source_file) | ||
120 | } | ||
121 | (None, Some(item_id)) => { | ||
122 | let module = item_id.to_node(db); | ||
123 | assert!(module.item_list().is_some(), "expected inline module"); | ||
124 | ModuleSource::Module(module.to_owned()) | ||
125 | } | ||
126 | (None, None) => panic!(), | ||
127 | } | ||
128 | } | ||
129 | } | ||
130 | |||
110 | impl Module { | 131 | impl Module { |
111 | /// Name of this module. | 132 | /// Name of this module. |
112 | pub fn name(&self, db: &impl HirDatabase) -> Option<Name> { | 133 | pub fn name(self, db: &impl HirDatabase) -> Option<Name> { |
113 | self.name_impl(db) | 134 | let def_map = db.crate_def_map(self.krate); |
135 | let parent = def_map[self.module_id].parent?; | ||
136 | def_map[parent].children.iter().find_map(|(name, module_id)| { | ||
137 | if *module_id == self.module_id { | ||
138 | Some(name.clone()) | ||
139 | } else { | ||
140 | None | ||
141 | } | ||
142 | }) | ||
114 | } | 143 | } |
115 | 144 | ||
116 | /// Returns a node which defines this module. That is, a file or a `mod foo {}` with items. | 145 | /// Returns a node which defines this module. That is, a file or a `mod foo {}` with items. |
117 | pub fn definition_source(&self, db: &impl DefDatabase) -> (HirFileId, ModuleSource) { | 146 | pub fn definition_source(self, db: &impl DefDatabase) -> (HirFileId, ModuleSource) { |
118 | self.definition_source_impl(db) | 147 | let def_map = db.crate_def_map(self.krate); |
148 | let decl_id = def_map[self.module_id].declaration; | ||
149 | let file_id = def_map[self.module_id].definition; | ||
150 | let module_source = ModuleSource::new(db, file_id, decl_id); | ||
151 | let file_id = file_id.map(HirFileId::from).unwrap_or_else(|| decl_id.unwrap().file_id()); | ||
152 | (file_id, module_source) | ||
119 | } | 153 | } |
120 | 154 | ||
121 | /// Returns a node which declares this module, either a `mod foo;` or a `mod foo {}`. | 155 | /// Returns a node which declares this module, either a `mod foo;` or a `mod foo {}`. |
122 | /// `None` for the crate root. | 156 | /// `None` for the crate root. |
123 | pub fn declaration_source( | 157 | pub fn declaration_source( |
124 | &self, | 158 | self, |
125 | db: &impl HirDatabase, | 159 | db: &impl HirDatabase, |
126 | ) -> Option<(HirFileId, TreeArc<ast::Module>)> { | 160 | ) -> Option<(HirFileId, TreeArc<ast::Module>)> { |
127 | self.declaration_source_impl(db) | 161 | let def_map = db.crate_def_map(self.krate); |
162 | let decl = def_map[self.module_id].declaration?; | ||
163 | let ast = decl.to_node(db); | ||
164 | Some((decl.file_id(), ast)) | ||
128 | } | 165 | } |
129 | 166 | ||
130 | /// Returns the syntax of the last path segment corresponding to this import | 167 | /// Returns the syntax of the last path segment corresponding to this import |
131 | pub fn import_source( | 168 | pub fn import_source( |
132 | &self, | 169 | self, |
133 | db: &impl HirDatabase, | 170 | db: &impl HirDatabase, |
134 | import: ImportId, | 171 | import: ImportId, |
135 | ) -> Either<TreeArc<ast::UseTree>, TreeArc<ast::ExternCrateItem>> { | 172 | ) -> Either<TreeArc<ast::UseTree>, TreeArc<ast::ExternCrateItem>> { |
@@ -139,33 +176,44 @@ impl Module { | |||
139 | } | 176 | } |
140 | 177 | ||
141 | /// Returns the crate this module is part of. | 178 | /// Returns the crate this module is part of. |
142 | pub fn krate(&self, _db: &impl DefDatabase) -> Option<Crate> { | 179 | pub fn krate(self, _db: &impl DefDatabase) -> Option<Crate> { |
143 | Some(self.krate) | 180 | Some(self.krate) |
144 | } | 181 | } |
145 | 182 | ||
146 | /// Topmost parent of this module. Every module has a `crate_root`, but some | 183 | /// Topmost parent of this module. Every module has a `crate_root`, but some |
147 | /// might be missing `krate`. This can happen if a module's file is not included | 184 | /// might be missing `krate`. This can happen if a module's file is not included |
148 | /// in the module tree of any target in `Cargo.toml`. | 185 | /// in the module tree of any target in `Cargo.toml`. |
149 | pub fn crate_root(&self, db: &impl DefDatabase) -> Module { | 186 | pub fn crate_root(self, db: &impl DefDatabase) -> Module { |
150 | self.crate_root_impl(db) | 187 | let def_map = db.crate_def_map(self.krate); |
188 | self.with_module_id(def_map.root()) | ||
151 | } | 189 | } |
152 | 190 | ||
153 | /// Finds a child module with the specified name. | 191 | /// Finds a child module with the specified name. |
154 | pub fn child(&self, db: &impl HirDatabase, name: &Name) -> Option<Module> { | 192 | pub fn child(self, db: &impl HirDatabase, name: &Name) -> Option<Module> { |
155 | self.child_impl(db, name) | 193 | let def_map = db.crate_def_map(self.krate); |
194 | let child_id = def_map[self.module_id].children.get(name)?; | ||
195 | Some(self.with_module_id(*child_id)) | ||
156 | } | 196 | } |
157 | 197 | ||
158 | /// Iterates over all child modules. | 198 | /// Iterates over all child modules. |
159 | pub fn children(&self, db: &impl DefDatabase) -> impl Iterator<Item = Module> { | 199 | pub fn children(self, db: &impl DefDatabase) -> impl Iterator<Item = Module> { |
160 | self.children_impl(db) | 200 | let def_map = db.crate_def_map(self.krate); |
201 | let children = def_map[self.module_id] | ||
202 | .children | ||
203 | .iter() | ||
204 | .map(|(_, module_id)| self.with_module_id(*module_id)) | ||
205 | .collect::<Vec<_>>(); | ||
206 | children.into_iter() | ||
161 | } | 207 | } |
162 | 208 | ||
163 | /// Finds a parent module. | 209 | /// Finds a parent module. |
164 | pub fn parent(&self, db: &impl DefDatabase) -> Option<Module> { | 210 | pub fn parent(self, db: &impl DefDatabase) -> Option<Module> { |
165 | self.parent_impl(db) | 211 | let def_map = db.crate_def_map(self.krate); |
212 | let parent_id = def_map[self.module_id].parent?; | ||
213 | Some(self.with_module_id(parent_id)) | ||
166 | } | 214 | } |
167 | 215 | ||
168 | pub fn path_to_root(&self, db: &impl HirDatabase) -> Vec<Module> { | 216 | pub fn path_to_root(self, db: &impl HirDatabase) -> Vec<Module> { |
169 | let mut res = vec![self.clone()]; | 217 | let mut res = vec![self.clone()]; |
170 | let mut curr = self.clone(); | 218 | let mut curr = self.clone(); |
171 | while let Some(next) = curr.parent(db) { | 219 | while let Some(next) = curr.parent(db) { |
@@ -176,11 +224,11 @@ impl Module { | |||
176 | } | 224 | } |
177 | 225 | ||
178 | /// Returns a `ModuleScope`: a set of items, visible in this module. | 226 | /// Returns a `ModuleScope`: a set of items, visible in this module. |
179 | pub fn scope(&self, db: &impl HirDatabase) -> ModuleScope { | 227 | pub fn scope(self, db: &impl HirDatabase) -> ModuleScope { |
180 | db.crate_def_map(self.krate)[self.module_id].scope.clone() | 228 | db.crate_def_map(self.krate)[self.module_id].scope.clone() |
181 | } | 229 | } |
182 | 230 | ||
183 | pub fn diagnostics(&self, db: &impl HirDatabase, sink: &mut DiagnosticSink) { | 231 | pub fn diagnostics(self, db: &impl HirDatabase, sink: &mut DiagnosticSink) { |
184 | db.crate_def_map(self.krate).add_diagnostics(db, self.module_id, sink); | 232 | db.crate_def_map(self.krate).add_diagnostics(db, self.module_id, sink); |
185 | for decl in self.declarations(db) { | 233 | for decl in self.declarations(db) { |
186 | match decl { | 234 | match decl { |
@@ -200,7 +248,7 @@ impl Module { | |||
200 | } | 248 | } |
201 | } | 249 | } |
202 | 250 | ||
203 | pub(crate) fn resolver(&self, db: &impl DefDatabase) -> Resolver { | 251 | pub(crate) fn resolver(self, db: &impl DefDatabase) -> Resolver { |
204 | let def_map = db.crate_def_map(self.krate); | 252 | let def_map = db.crate_def_map(self.krate); |
205 | Resolver::default().push_module_scope(def_map, self.module_id) | 253 | Resolver::default().push_module_scope(def_map, self.module_id) |
206 | } | 254 | } |
@@ -225,6 +273,10 @@ impl Module { | |||
225 | .map(|(impl_id, _)| ImplBlock::from_id(self, impl_id)) | 273 | .map(|(impl_id, _)| ImplBlock::from_id(self, impl_id)) |
226 | .collect() | 274 | .collect() |
227 | } | 275 | } |
276 | |||
277 | fn with_module_id(&self, module_id: CrateModuleId) -> Module { | ||
278 | Module { module_id, krate: self.krate } | ||
279 | } | ||
228 | } | 280 | } |
229 | 281 | ||
230 | impl Docs for Module { | 282 | impl Docs for Module { |
@@ -278,49 +330,49 @@ pub struct Struct { | |||
278 | } | 330 | } |
279 | 331 | ||
280 | impl Struct { | 332 | impl Struct { |
281 | pub fn source(&self, db: &impl DefDatabase) -> (HirFileId, TreeArc<ast::StructDef>) { | 333 | pub fn source(self, db: &impl DefDatabase) -> (HirFileId, TreeArc<ast::StructDef>) { |
282 | self.id.source(db) | 334 | self.id.source(db) |
283 | } | 335 | } |
284 | 336 | ||
285 | pub fn module(&self, db: &impl HirDatabase) -> Module { | 337 | pub fn module(self, db: &impl HirDatabase) -> Module { |
286 | self.id.module(db) | 338 | self.id.module(db) |
287 | } | 339 | } |
288 | 340 | ||
289 | pub fn name(&self, db: &impl HirDatabase) -> Option<Name> { | 341 | pub fn name(self, db: &impl HirDatabase) -> Option<Name> { |
290 | db.struct_data(*self).name.clone() | 342 | db.struct_data(self).name.clone() |
291 | } | 343 | } |
292 | 344 | ||
293 | pub fn fields(&self, db: &impl HirDatabase) -> Vec<StructField> { | 345 | pub fn fields(self, db: &impl HirDatabase) -> Vec<StructField> { |
294 | db.struct_data(*self) | 346 | db.struct_data(self) |
295 | .variant_data | 347 | .variant_data |
296 | .fields() | 348 | .fields() |
297 | .into_iter() | 349 | .into_iter() |
298 | .flat_map(|it| it.iter()) | 350 | .flat_map(|it| it.iter()) |
299 | .map(|(id, _)| StructField { parent: (*self).into(), id }) | 351 | .map(|(id, _)| StructField { parent: self.into(), id }) |
300 | .collect() | 352 | .collect() |
301 | } | 353 | } |
302 | 354 | ||
303 | pub fn field(&self, db: &impl HirDatabase, name: &Name) -> Option<StructField> { | 355 | pub fn field(self, db: &impl HirDatabase, name: &Name) -> Option<StructField> { |
304 | db.struct_data(*self) | 356 | db.struct_data(self) |
305 | .variant_data | 357 | .variant_data |
306 | .fields() | 358 | .fields() |
307 | .into_iter() | 359 | .into_iter() |
308 | .flat_map(|it| it.iter()) | 360 | .flat_map(|it| it.iter()) |
309 | .find(|(_id, data)| data.name == *name) | 361 | .find(|(_id, data)| data.name == *name) |
310 | .map(|(id, _)| StructField { parent: (*self).into(), id }) | 362 | .map(|(id, _)| StructField { parent: self.into(), id }) |
311 | } | 363 | } |
312 | 364 | ||
313 | pub fn ty(&self, db: &impl HirDatabase) -> Ty { | 365 | pub fn ty(self, db: &impl HirDatabase) -> Ty { |
314 | db.type_for_def((*self).into(), Namespace::Types) | 366 | db.type_for_def(self.into(), Namespace::Types) |
315 | } | 367 | } |
316 | 368 | ||
317 | pub fn constructor_ty(&self, db: &impl HirDatabase) -> Ty { | 369 | pub fn constructor_ty(self, db: &impl HirDatabase) -> Ty { |
318 | db.type_for_def((*self).into(), Namespace::Values) | 370 | db.type_for_def(self.into(), Namespace::Values) |
319 | } | 371 | } |
320 | 372 | ||
321 | // FIXME move to a more general type | 373 | // FIXME move to a more general type |
322 | /// Builds a resolver for type references inside this struct. | 374 | /// Builds a resolver for type references inside this struct. |
323 | pub(crate) fn resolver(&self, db: &impl HirDatabase) -> Resolver { | 375 | pub(crate) fn resolver(self, db: &impl HirDatabase) -> Resolver { |
324 | // take the outer scope... | 376 | // take the outer scope... |
325 | let r = self.module(db).resolver(db); | 377 | let r = self.module(db).resolver(db); |
326 | // ...and add generic params, if present | 378 | // ...and add generic params, if present |
@@ -342,21 +394,21 @@ pub struct Union { | |||
342 | } | 394 | } |
343 | 395 | ||
344 | impl Union { | 396 | impl Union { |
345 | pub fn source(&self, db: &impl DefDatabase) -> (HirFileId, TreeArc<ast::StructDef>) { | 397 | pub fn source(self, db: &impl DefDatabase) -> (HirFileId, TreeArc<ast::StructDef>) { |
346 | self.id.source(db) | 398 | self.id.source(db) |
347 | } | 399 | } |
348 | 400 | ||
349 | pub fn name(&self, db: &impl HirDatabase) -> Option<Name> { | 401 | pub fn name(self, db: &impl HirDatabase) -> Option<Name> { |
350 | db.struct_data(Struct { id: self.id }).name.clone() | 402 | db.struct_data(Struct { id: self.id }).name.clone() |
351 | } | 403 | } |
352 | 404 | ||
353 | pub fn module(&self, db: &impl HirDatabase) -> Module { | 405 | pub fn module(self, db: &impl HirDatabase) -> Module { |
354 | self.id.module(db) | 406 | self.id.module(db) |
355 | } | 407 | } |
356 | 408 | ||
357 | // FIXME move to a more general type | 409 | // FIXME move to a more general type |
358 | /// Builds a resolver for type references inside this union. | 410 | /// Builds a resolver for type references inside this union. |
359 | pub(crate) fn resolver(&self, db: &impl HirDatabase) -> Resolver { | 411 | pub(crate) fn resolver(self, db: &impl HirDatabase) -> Resolver { |
360 | // take the outer scope... | 412 | // take the outer scope... |
361 | let r = self.module(db).resolver(db); | 413 | let r = self.module(db).resolver(db); |
362 | // ...and add generic params, if present | 414 | // ...and add generic params, if present |
@@ -378,41 +430,37 @@ pub struct Enum { | |||
378 | } | 430 | } |
379 | 431 | ||
380 | impl Enum { | 432 | impl Enum { |
381 | pub fn source(&self, db: &impl DefDatabase) -> (HirFileId, TreeArc<ast::EnumDef>) { | 433 | pub fn source(self, db: &impl DefDatabase) -> (HirFileId, TreeArc<ast::EnumDef>) { |
382 | self.id.source(db) | 434 | self.id.source(db) |
383 | } | 435 | } |
384 | 436 | ||
385 | pub fn module(&self, db: &impl HirDatabase) -> Module { | 437 | pub fn module(self, db: &impl HirDatabase) -> Module { |
386 | self.id.module(db) | 438 | self.id.module(db) |
387 | } | 439 | } |
388 | 440 | ||
389 | pub fn name(&self, db: &impl HirDatabase) -> Option<Name> { | 441 | pub fn name(self, db: &impl HirDatabase) -> Option<Name> { |
390 | db.enum_data(*self).name.clone() | 442 | db.enum_data(self).name.clone() |
391 | } | 443 | } |
392 | 444 | ||
393 | pub fn variants(&self, db: &impl DefDatabase) -> Vec<EnumVariant> { | 445 | pub fn variants(self, db: &impl DefDatabase) -> Vec<EnumVariant> { |
394 | db.enum_data(*self) | 446 | db.enum_data(self).variants.iter().map(|(id, _)| EnumVariant { parent: self, id }).collect() |
395 | .variants | ||
396 | .iter() | ||
397 | .map(|(id, _)| EnumVariant { parent: *self, id }) | ||
398 | .collect() | ||
399 | } | 447 | } |
400 | 448 | ||
401 | pub fn variant(&self, db: &impl DefDatabase, name: &Name) -> Option<EnumVariant> { | 449 | pub fn variant(self, db: &impl DefDatabase, name: &Name) -> Option<EnumVariant> { |
402 | db.enum_data(*self) | 450 | db.enum_data(self) |
403 | .variants | 451 | .variants |
404 | .iter() | 452 | .iter() |
405 | .find(|(_id, data)| data.name.as_ref() == Some(name)) | 453 | .find(|(_id, data)| data.name.as_ref() == Some(name)) |
406 | .map(|(id, _)| EnumVariant { parent: *self, id }) | 454 | .map(|(id, _)| EnumVariant { parent: self, id }) |
407 | } | 455 | } |
408 | 456 | ||
409 | pub fn ty(&self, db: &impl HirDatabase) -> Ty { | 457 | pub fn ty(self, db: &impl HirDatabase) -> Ty { |
410 | db.type_for_def((*self).into(), Namespace::Types) | 458 | db.type_for_def(self.into(), Namespace::Types) |
411 | } | 459 | } |
412 | 460 | ||
413 | // FIXME: move to a more general type | 461 | // FIXME: move to a more general type |
414 | /// Builds a resolver for type references inside this struct. | 462 | /// Builds a resolver for type references inside this struct. |
415 | pub(crate) fn resolver(&self, db: &impl HirDatabase) -> Resolver { | 463 | pub(crate) fn resolver(self, db: &impl HirDatabase) -> Resolver { |
416 | // take the outer scope... | 464 | // take the outer scope... |
417 | let r = self.module(db).resolver(db); | 465 | let r = self.module(db).resolver(db); |
418 | // ...and add generic params, if present | 466 | // ...and add generic params, if present |