diff options
Diffstat (limited to 'crates')
47 files changed, 1277 insertions, 622 deletions
diff --git a/crates/ra_hir/src/adt.rs b/crates/ra_hir/src/adt.rs index 22bbad964..c549e2126 100644 --- a/crates/ra_hir/src/adt.rs +++ b/crates/ra_hir/src/adt.rs | |||
@@ -12,7 +12,7 @@ use ra_syntax::{ | |||
12 | use crate::{ | 12 | use crate::{ |
13 | Name, AsName, Struct, Enum, EnumVariant, Crate, | 13 | Name, AsName, Struct, Enum, EnumVariant, Crate, |
14 | HirDatabase, HirFileId, StructField, FieldSource, | 14 | HirDatabase, HirFileId, StructField, FieldSource, |
15 | type_ref::TypeRef, | 15 | type_ref::TypeRef, PersistentHirDatabase, |
16 | }; | 16 | }; |
17 | 17 | ||
18 | #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] | 18 | #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] |
@@ -33,7 +33,7 @@ impl AdtDef { | |||
33 | } | 33 | } |
34 | 34 | ||
35 | impl Struct { | 35 | impl Struct { |
36 | pub(crate) fn variant_data(&self, db: &impl HirDatabase) -> Arc<VariantData> { | 36 | pub(crate) fn variant_data(&self, db: &impl PersistentHirDatabase) -> Arc<VariantData> { |
37 | db.struct_data((*self).into()).variant_data.clone() | 37 | db.struct_data((*self).into()).variant_data.clone() |
38 | } | 38 | } |
39 | } | 39 | } |
@@ -52,7 +52,10 @@ impl StructData { | |||
52 | StructData { name, variant_data } | 52 | StructData { name, variant_data } |
53 | } | 53 | } |
54 | 54 | ||
55 | pub(crate) fn struct_data_query(db: &impl HirDatabase, struct_: Struct) -> Arc<StructData> { | 55 | pub(crate) fn struct_data_query( |
56 | db: &impl PersistentHirDatabase, | ||
57 | struct_: Struct, | ||
58 | ) -> Arc<StructData> { | ||
56 | let (_, struct_def) = struct_.source(db); | 59 | let (_, struct_def) = struct_.source(db); |
57 | Arc::new(StructData::new(&*struct_def)) | 60 | Arc::new(StructData::new(&*struct_def)) |
58 | } | 61 | } |
@@ -68,7 +71,7 @@ fn variants(enum_def: &ast::EnumDef) -> impl Iterator<Item = &ast::EnumVariant> | |||
68 | impl EnumVariant { | 71 | impl EnumVariant { |
69 | pub(crate) fn source_impl( | 72 | pub(crate) fn source_impl( |
70 | &self, | 73 | &self, |
71 | db: &impl HirDatabase, | 74 | db: &impl PersistentHirDatabase, |
72 | ) -> (HirFileId, TreeArc<ast::EnumVariant>) { | 75 | ) -> (HirFileId, TreeArc<ast::EnumVariant>) { |
73 | let (file_id, enum_def) = self.parent.source(db); | 76 | let (file_id, enum_def) = self.parent.source(db); |
74 | let var = variants(&*enum_def) | 77 | let var = variants(&*enum_def) |
@@ -79,7 +82,7 @@ impl EnumVariant { | |||
79 | .to_owned(); | 82 | .to_owned(); |
80 | (file_id, var) | 83 | (file_id, var) |
81 | } | 84 | } |
82 | pub(crate) fn variant_data(&self, db: &impl HirDatabase) -> Arc<VariantData> { | 85 | pub(crate) fn variant_data(&self, db: &impl PersistentHirDatabase) -> Arc<VariantData> { |
83 | db.enum_data(self.parent).variants[self.id] | 86 | db.enum_data(self.parent).variants[self.id] |
84 | .variant_data | 87 | .variant_data |
85 | .clone() | 88 | .clone() |
@@ -93,7 +96,7 @@ pub struct EnumData { | |||
93 | } | 96 | } |
94 | 97 | ||
95 | impl EnumData { | 98 | impl EnumData { |
96 | pub(crate) fn enum_data_query(db: &impl HirDatabase, e: Enum) -> Arc<EnumData> { | 99 | pub(crate) fn enum_data_query(db: &impl PersistentHirDatabase, e: Enum) -> Arc<EnumData> { |
97 | let (_file_id, enum_def) = e.source(db); | 100 | let (_file_id, enum_def) = e.source(db); |
98 | let name = enum_def.name().map(|n| n.as_name()); | 101 | let name = enum_def.name().map(|n| n.as_name()); |
99 | let variants = variants(&*enum_def) | 102 | let variants = variants(&*enum_def) |
@@ -191,7 +194,7 @@ impl VariantDef { | |||
191 | VariantDef::EnumVariant(it) => it.field(db, name), | 194 | VariantDef::EnumVariant(it) => it.field(db, name), |
192 | } | 195 | } |
193 | } | 196 | } |
194 | pub(crate) fn variant_data(self, db: &impl HirDatabase) -> Arc<VariantData> { | 197 | pub(crate) fn variant_data(self, db: &impl PersistentHirDatabase) -> Arc<VariantData> { |
195 | match self { | 198 | match self { |
196 | VariantDef::Struct(it) => it.variant_data(db), | 199 | VariantDef::Struct(it) => it.variant_data(db), |
197 | VariantDef::EnumVariant(it) => it.variant_data(db), | 200 | VariantDef::EnumVariant(it) => it.variant_data(db), |
@@ -200,7 +203,7 @@ impl VariantDef { | |||
200 | } | 203 | } |
201 | 204 | ||
202 | impl StructField { | 205 | impl StructField { |
203 | pub(crate) fn source_impl(&self, db: &impl HirDatabase) -> (HirFileId, FieldSource) { | 206 | pub(crate) fn source_impl(&self, db: &impl PersistentHirDatabase) -> (HirFileId, FieldSource) { |
204 | let var_data = self.parent.variant_data(db); | 207 | let var_data = self.parent.variant_data(db); |
205 | let fields = var_data.fields().unwrap(); | 208 | let fields = var_data.fields().unwrap(); |
206 | let ss; | 209 | let ss; |
diff --git a/crates/ra_hir/src/code_model_api.rs b/crates/ra_hir/src/code_model_api.rs index 9405aa8ad..92ab0f692 100644 --- a/crates/ra_hir/src/code_model_api.rs +++ b/crates/ra_hir/src/code_model_api.rs | |||
@@ -5,18 +5,19 @@ use ra_db::{CrateId, FileId}; | |||
5 | use ra_syntax::{ast::self, TreeArc, SyntaxNode}; | 5 | use ra_syntax::{ast::self, TreeArc, SyntaxNode}; |
6 | 6 | ||
7 | use crate::{ | 7 | use crate::{ |
8 | Name, Path, PerNs, ScopesWithSyntaxMapping, Ty, HirFileId, | 8 | Name, ScopesWithSyntaxMapping, Ty, HirFileId, |
9 | type_ref::TypeRef, | 9 | type_ref::TypeRef, |
10 | nameres::{ModuleScope, lower::ImportId}, | 10 | nameres::{ModuleScope, lower::ImportId}, |
11 | db::HirDatabase, | 11 | HirDatabase, PersistentHirDatabase, |
12 | expr::BodySyntaxMapping, | 12 | expr::{Body, BodySyntaxMapping}, |
13 | ty::{InferenceResult}, | 13 | ty::InferenceResult, |
14 | adt::{EnumVariantId, StructFieldId, VariantDef}, | 14 | adt::{EnumVariantId, StructFieldId, VariantDef}, |
15 | generics::GenericParams, | 15 | generics::GenericParams, |
16 | docs::{Documentation, Docs, docs_from_ast}, | 16 | docs::{Documentation, Docs, docs_from_ast}, |
17 | module_tree::ModuleId, | 17 | module_tree::ModuleId, |
18 | ids::{FunctionId, StructId, EnumId, AstItemDef, ConstId, StaticId, TraitId, TypeId}, | 18 | ids::{FunctionId, StructId, EnumId, AstItemDef, ConstId, StaticId, TraitId, TypeId}, |
19 | impl_block::ImplId, | 19 | impl_block::ImplId, |
20 | resolve::Resolver, | ||
20 | }; | 21 | }; |
21 | 22 | ||
22 | /// hir::Crate describes a single crate. It's the main interface with which | 23 | /// hir::Crate describes a single crate. It's the main interface with which |
@@ -37,10 +38,10 @@ impl Crate { | |||
37 | pub fn crate_id(&self) -> CrateId { | 38 | pub fn crate_id(&self) -> CrateId { |
38 | self.crate_id | 39 | self.crate_id |
39 | } | 40 | } |
40 | pub fn dependencies(&self, db: &impl HirDatabase) -> Vec<CrateDependency> { | 41 | pub fn dependencies(&self, db: &impl PersistentHirDatabase) -> Vec<CrateDependency> { |
41 | self.dependencies_impl(db) | 42 | self.dependencies_impl(db) |
42 | } | 43 | } |
43 | pub fn root_module(&self, db: &impl HirDatabase) -> Option<Module> { | 44 | pub fn root_module(&self, db: &impl PersistentHirDatabase) -> Option<Module> { |
44 | self.root_module_impl(db) | 45 | self.root_module_impl(db) |
45 | } | 46 | } |
46 | } | 47 | } |
@@ -105,7 +106,7 @@ impl Module { | |||
105 | } | 106 | } |
106 | 107 | ||
107 | /// Returns a node which defines this module. That is, a file or a `mod foo {}` with items. | 108 | /// Returns a node which defines this module. That is, a file or a `mod foo {}` with items. |
108 | pub fn definition_source(&self, db: &impl HirDatabase) -> (FileId, ModuleSource) { | 109 | pub fn definition_source(&self, db: &impl PersistentHirDatabase) -> (FileId, ModuleSource) { |
109 | self.definition_source_impl(db) | 110 | self.definition_source_impl(db) |
110 | } | 111 | } |
111 | 112 | ||
@@ -140,7 +141,7 @@ impl Module { | |||
140 | /// Topmost parent of this module. Every module has a `crate_root`, but some | 141 | /// Topmost parent of this module. Every module has a `crate_root`, but some |
141 | /// might be missing `krate`. This can happen if a module's file is not included | 142 | /// might be missing `krate`. This can happen if a module's file is not included |
142 | /// in the module tree of any target in Cargo.toml. | 143 | /// in the module tree of any target in Cargo.toml. |
143 | pub fn crate_root(&self, db: &impl HirDatabase) -> Module { | 144 | pub fn crate_root(&self, db: &impl PersistentHirDatabase) -> Module { |
144 | self.crate_root_impl(db) | 145 | self.crate_root_impl(db) |
145 | } | 146 | } |
146 | 147 | ||
@@ -150,12 +151,12 @@ impl Module { | |||
150 | } | 151 | } |
151 | 152 | ||
152 | /// Iterates over all child modules. | 153 | /// Iterates over all child modules. |
153 | pub fn children(&self, db: &impl HirDatabase) -> impl Iterator<Item = Module> { | 154 | pub fn children(&self, db: &impl PersistentHirDatabase) -> impl Iterator<Item = Module> { |
154 | self.children_impl(db) | 155 | self.children_impl(db) |
155 | } | 156 | } |
156 | 157 | ||
157 | /// Finds a parent module. | 158 | /// Finds a parent module. |
158 | pub fn parent(&self, db: &impl HirDatabase) -> Option<Module> { | 159 | pub fn parent(&self, db: &impl PersistentHirDatabase) -> Option<Module> { |
159 | self.parent_impl(db) | 160 | self.parent_impl(db) |
160 | } | 161 | } |
161 | 162 | ||
@@ -174,13 +175,14 @@ impl Module { | |||
174 | db.item_map(self.krate)[self.module_id].clone() | 175 | db.item_map(self.krate)[self.module_id].clone() |
175 | } | 176 | } |
176 | 177 | ||
177 | pub fn resolve_path(&self, db: &impl HirDatabase, path: &Path) -> PerNs<ModuleDef> { | ||
178 | db.item_map(self.krate).resolve_path(db, *self, path) | ||
179 | } | ||
180 | |||
181 | pub fn problems(&self, db: &impl HirDatabase) -> Vec<(TreeArc<SyntaxNode>, Problem)> { | 178 | pub fn problems(&self, db: &impl HirDatabase) -> Vec<(TreeArc<SyntaxNode>, Problem)> { |
182 | self.problems_impl(db) | 179 | self.problems_impl(db) |
183 | } | 180 | } |
181 | |||
182 | pub fn resolver(&self, db: &impl HirDatabase) -> Resolver { | ||
183 | let item_map = db.item_map(self.krate); | ||
184 | Resolver::default().push_module_scope(item_map, *self) | ||
185 | } | ||
184 | } | 186 | } |
185 | 187 | ||
186 | impl Docs for Module { | 188 | impl Docs for Module { |
@@ -209,7 +211,7 @@ impl StructField { | |||
209 | .clone() | 211 | .clone() |
210 | } | 212 | } |
211 | 213 | ||
212 | pub fn source(&self, db: &impl HirDatabase) -> (HirFileId, FieldSource) { | 214 | pub fn source(&self, db: &impl PersistentHirDatabase) -> (HirFileId, FieldSource) { |
213 | self.source_impl(db) | 215 | self.source_impl(db) |
214 | } | 216 | } |
215 | 217 | ||
@@ -237,7 +239,7 @@ pub struct Struct { | |||
237 | } | 239 | } |
238 | 240 | ||
239 | impl Struct { | 241 | impl Struct { |
240 | pub fn source(&self, db: &impl HirDatabase) -> (HirFileId, TreeArc<ast::StructDef>) { | 242 | pub fn source(&self, db: &impl PersistentHirDatabase) -> (HirFileId, TreeArc<ast::StructDef>) { |
241 | self.id.source(db) | 243 | self.id.source(db) |
242 | } | 244 | } |
243 | 245 | ||
@@ -275,13 +277,28 @@ impl Struct { | |||
275 | }) | 277 | }) |
276 | } | 278 | } |
277 | 279 | ||
278 | pub fn generic_params(&self, db: &impl HirDatabase) -> Arc<GenericParams> { | 280 | pub fn generic_params(&self, db: &impl PersistentHirDatabase) -> Arc<GenericParams> { |
279 | db.generic_params((*self).into()) | 281 | db.generic_params((*self).into()) |
280 | } | 282 | } |
281 | 283 | ||
282 | pub fn ty(&self, db: &impl HirDatabase) -> Ty { | 284 | pub fn ty(&self, db: &impl HirDatabase) -> Ty { |
283 | db.type_for_def((*self).into()) | 285 | db.type_for_def((*self).into()) |
284 | } | 286 | } |
287 | |||
288 | // TODO move to a more general type | ||
289 | /// Builds a resolver for type references inside this struct. | ||
290 | pub fn resolver(&self, db: &impl HirDatabase) -> Resolver { | ||
291 | // take the outer scope... | ||
292 | let r = self.module(db).resolver(db); | ||
293 | // ...and add generic params, if present | ||
294 | let p = self.generic_params(db); | ||
295 | let r = if !p.params.is_empty() { | ||
296 | r.push_generic_params_scope(p) | ||
297 | } else { | ||
298 | r | ||
299 | }; | ||
300 | r | ||
301 | } | ||
285 | } | 302 | } |
286 | 303 | ||
287 | impl Docs for Struct { | 304 | impl Docs for Struct { |
@@ -296,7 +313,7 @@ pub struct Enum { | |||
296 | } | 313 | } |
297 | 314 | ||
298 | impl Enum { | 315 | impl Enum { |
299 | pub fn source(&self, db: &impl HirDatabase) -> (HirFileId, TreeArc<ast::EnumDef>) { | 316 | pub fn source(&self, db: &impl PersistentHirDatabase) -> (HirFileId, TreeArc<ast::EnumDef>) { |
300 | self.id.source(db) | 317 | self.id.source(db) |
301 | } | 318 | } |
302 | 319 | ||
@@ -316,7 +333,7 @@ impl Enum { | |||
316 | .collect() | 333 | .collect() |
317 | } | 334 | } |
318 | 335 | ||
319 | pub fn variant(&self, db: &impl HirDatabase, name: &Name) -> Option<EnumVariant> { | 336 | pub fn variant(&self, db: &impl PersistentHirDatabase, name: &Name) -> Option<EnumVariant> { |
320 | db.enum_data(*self) | 337 | db.enum_data(*self) |
321 | .variants | 338 | .variants |
322 | .iter() | 339 | .iter() |
@@ -324,13 +341,28 @@ impl Enum { | |||
324 | .map(|(id, _)| EnumVariant { parent: *self, id }) | 341 | .map(|(id, _)| EnumVariant { parent: *self, id }) |
325 | } | 342 | } |
326 | 343 | ||
327 | pub fn generic_params(&self, db: &impl HirDatabase) -> Arc<GenericParams> { | 344 | pub fn generic_params(&self, db: &impl PersistentHirDatabase) -> Arc<GenericParams> { |
328 | db.generic_params((*self).into()) | 345 | db.generic_params((*self).into()) |
329 | } | 346 | } |
330 | 347 | ||
331 | pub fn ty(&self, db: &impl HirDatabase) -> Ty { | 348 | pub fn ty(&self, db: &impl HirDatabase) -> Ty { |
332 | db.type_for_def((*self).into()) | 349 | db.type_for_def((*self).into()) |
333 | } | 350 | } |
351 | |||
352 | // TODO move to a more general type | ||
353 | /// Builds a resolver for type references inside this struct. | ||
354 | pub fn resolver(&self, db: &impl HirDatabase) -> Resolver { | ||
355 | // take the outer scope... | ||
356 | let r = self.module(db).resolver(db); | ||
357 | // ...and add generic params, if present | ||
358 | let p = self.generic_params(db); | ||
359 | let r = if !p.params.is_empty() { | ||
360 | r.push_generic_params_scope(p) | ||
361 | } else { | ||
362 | r | ||
363 | }; | ||
364 | r | ||
365 | } | ||
334 | } | 366 | } |
335 | 367 | ||
336 | impl Docs for Enum { | 368 | impl Docs for Enum { |
@@ -346,13 +378,16 @@ pub struct EnumVariant { | |||
346 | } | 378 | } |
347 | 379 | ||
348 | impl EnumVariant { | 380 | impl EnumVariant { |
349 | pub fn source(&self, db: &impl HirDatabase) -> (HirFileId, TreeArc<ast::EnumVariant>) { | 381 | pub fn source( |
382 | &self, | ||
383 | db: &impl PersistentHirDatabase, | ||
384 | ) -> (HirFileId, TreeArc<ast::EnumVariant>) { | ||
350 | self.source_impl(db) | 385 | self.source_impl(db) |
351 | } | 386 | } |
352 | pub fn module(&self, db: &impl HirDatabase) -> Module { | 387 | pub fn module(&self, db: &impl HirDatabase) -> Module { |
353 | self.parent.module(db) | 388 | self.parent.module(db) |
354 | } | 389 | } |
355 | pub fn parent_enum(&self, _db: &impl HirDatabase) -> Enum { | 390 | pub fn parent_enum(&self, _db: &impl PersistentHirDatabase) -> Enum { |
356 | self.parent | 391 | self.parent |
357 | } | 392 | } |
358 | 393 | ||
@@ -430,7 +465,7 @@ impl FnSignature { | |||
430 | } | 465 | } |
431 | 466 | ||
432 | impl Function { | 467 | impl Function { |
433 | pub fn source(&self, db: &impl HirDatabase) -> (HirFileId, TreeArc<ast::FnDef>) { | 468 | pub fn source(&self, db: &impl PersistentHirDatabase) -> (HirFileId, TreeArc<ast::FnDef>) { |
434 | self.id.source(db) | 469 | self.id.source(db) |
435 | } | 470 | } |
436 | 471 | ||
@@ -446,6 +481,10 @@ impl Function { | |||
446 | db.body_syntax_mapping(*self) | 481 | db.body_syntax_mapping(*self) |
447 | } | 482 | } |
448 | 483 | ||
484 | pub fn body(&self, db: &impl HirDatabase) -> Arc<Body> { | ||
485 | db.body_hir(*self) | ||
486 | } | ||
487 | |||
449 | pub fn scopes(&self, db: &impl HirDatabase) -> ScopesWithSyntaxMapping { | 488 | pub fn scopes(&self, db: &impl HirDatabase) -> ScopesWithSyntaxMapping { |
450 | let scopes = db.expr_scopes(*self); | 489 | let scopes = db.expr_scopes(*self); |
451 | let syntax_mapping = db.body_syntax_mapping(*self); | 490 | let syntax_mapping = db.body_syntax_mapping(*self); |
@@ -463,9 +502,27 @@ impl Function { | |||
463 | db.infer(*self) | 502 | db.infer(*self) |
464 | } | 503 | } |
465 | 504 | ||
466 | pub fn generic_params(&self, db: &impl HirDatabase) -> Arc<GenericParams> { | 505 | pub fn generic_params(&self, db: &impl PersistentHirDatabase) -> Arc<GenericParams> { |
467 | db.generic_params((*self).into()) | 506 | db.generic_params((*self).into()) |
468 | } | 507 | } |
508 | |||
509 | // TODO move to a more general type for 'body-having' items | ||
510 | /// Builds a resolver for code inside this item. | ||
511 | pub fn resolver(&self, db: &impl HirDatabase) -> Resolver { | ||
512 | // take the outer scope... | ||
513 | let r = self | ||
514 | .impl_block(db) | ||
515 | .map(|ib| ib.resolver(db)) | ||
516 | .unwrap_or_else(|| self.module(db).resolver(db)); | ||
517 | // ...and add generic params, if present | ||
518 | let p = self.generic_params(db); | ||
519 | let r = if !p.params.is_empty() { | ||
520 | r.push_generic_params_scope(p) | ||
521 | } else { | ||
522 | r | ||
523 | }; | ||
524 | r | ||
525 | } | ||
469 | } | 526 | } |
470 | 527 | ||
471 | impl Docs for Function { | 528 | impl Docs for Function { |
@@ -480,7 +537,7 @@ pub struct Const { | |||
480 | } | 537 | } |
481 | 538 | ||
482 | impl Const { | 539 | impl Const { |
483 | pub fn source(&self, db: &impl HirDatabase) -> (HirFileId, TreeArc<ast::ConstDef>) { | 540 | pub fn source(&self, db: &impl PersistentHirDatabase) -> (HirFileId, TreeArc<ast::ConstDef>) { |
484 | self.id.source(db) | 541 | self.id.source(db) |
485 | } | 542 | } |
486 | } | 543 | } |
@@ -497,7 +554,7 @@ pub struct Static { | |||
497 | } | 554 | } |
498 | 555 | ||
499 | impl Static { | 556 | impl Static { |
500 | pub fn source(&self, db: &impl HirDatabase) -> (HirFileId, TreeArc<ast::StaticDef>) { | 557 | pub fn source(&self, db: &impl PersistentHirDatabase) -> (HirFileId, TreeArc<ast::StaticDef>) { |
501 | self.id.source(db) | 558 | self.id.source(db) |
502 | } | 559 | } |
503 | } | 560 | } |
@@ -514,11 +571,11 @@ pub struct Trait { | |||
514 | } | 571 | } |
515 | 572 | ||
516 | impl Trait { | 573 | impl Trait { |
517 | pub fn source(&self, db: &impl HirDatabase) -> (HirFileId, TreeArc<ast::TraitDef>) { | 574 | pub fn source(&self, db: &impl PersistentHirDatabase) -> (HirFileId, TreeArc<ast::TraitDef>) { |
518 | self.id.source(db) | 575 | self.id.source(db) |
519 | } | 576 | } |
520 | 577 | ||
521 | pub fn generic_params(&self, db: &impl HirDatabase) -> Arc<GenericParams> { | 578 | pub fn generic_params(&self, db: &impl PersistentHirDatabase) -> Arc<GenericParams> { |
522 | db.generic_params((*self).into()) | 579 | db.generic_params((*self).into()) |
523 | } | 580 | } |
524 | } | 581 | } |
@@ -535,11 +592,11 @@ pub struct Type { | |||
535 | } | 592 | } |
536 | 593 | ||
537 | impl Type { | 594 | impl Type { |
538 | pub fn source(&self, db: &impl HirDatabase) -> (HirFileId, TreeArc<ast::TypeDef>) { | 595 | pub fn source(&self, db: &impl PersistentHirDatabase) -> (HirFileId, TreeArc<ast::TypeDef>) { |
539 | self.id.source(db) | 596 | self.id.source(db) |
540 | } | 597 | } |
541 | 598 | ||
542 | pub fn generic_params(&self, db: &impl HirDatabase) -> Arc<GenericParams> { | 599 | pub fn generic_params(&self, db: &impl PersistentHirDatabase) -> Arc<GenericParams> { |
543 | db.generic_params((*self).into()) | 600 | db.generic_params((*self).into()) |
544 | } | 601 | } |
545 | } | 602 | } |
diff --git a/crates/ra_hir/src/code_model_impl/function.rs b/crates/ra_hir/src/code_model_impl/function.rs index 422643996..8326c02c7 100644 --- a/crates/ra_hir/src/code_model_impl/function.rs +++ b/crates/ra_hir/src/code_model_impl/function.rs | |||
@@ -5,14 +5,12 @@ use ra_syntax::ast::{self, NameOwner}; | |||
5 | use crate::{ | 5 | use crate::{ |
6 | HirDatabase, Name, AsName, Function, FnSignature, | 6 | HirDatabase, Name, AsName, Function, FnSignature, |
7 | type_ref::{TypeRef, Mutability}, | 7 | type_ref::{TypeRef, Mutability}, |
8 | expr::Body, | 8 | PersistentHirDatabase, |
9 | impl_block::ImplBlock, | 9 | impl_block::ImplBlock, |
10 | }; | 10 | }; |
11 | 11 | ||
12 | impl Function { | 12 | impl Function { |
13 | pub(crate) fn body(&self, db: &impl HirDatabase) -> Arc<Body> { | 13 | // TODO impl_block should probably also be part of the code model API? |
14 | db.body_hir(*self) | ||
15 | } | ||
16 | 14 | ||
17 | /// The containing impl block, if this is a method. | 15 | /// The containing impl block, if this is a method. |
18 | pub(crate) fn impl_block(&self, db: &impl HirDatabase) -> Option<ImplBlock> { | 16 | pub(crate) fn impl_block(&self, db: &impl HirDatabase) -> Option<ImplBlock> { |
@@ -22,7 +20,10 @@ impl Function { | |||
22 | } | 20 | } |
23 | 21 | ||
24 | impl FnSignature { | 22 | impl FnSignature { |
25 | pub(crate) fn fn_signature_query(db: &impl HirDatabase, func: Function) -> Arc<FnSignature> { | 23 | pub(crate) fn fn_signature_query( |
24 | db: &impl PersistentHirDatabase, | ||
25 | func: Function, | ||
26 | ) -> Arc<FnSignature> { | ||
26 | let (_, node) = func.source(db); | 27 | let (_, node) = func.source(db); |
27 | let name = node | 28 | let name = node |
28 | .name() | 29 | .name() |
diff --git a/crates/ra_hir/src/code_model_impl/krate.rs b/crates/ra_hir/src/code_model_impl/krate.rs index 86f29d959..1517434b8 100644 --- a/crates/ra_hir/src/code_model_impl/krate.rs +++ b/crates/ra_hir/src/code_model_impl/krate.rs | |||
@@ -1,10 +1,12 @@ | |||
1 | use crate::{ | 1 | use crate::{ |
2 | Crate, CrateDependency, AsName, Module, | 2 | Crate, CrateDependency, AsName, Module, PersistentHirDatabase, |
3 | db::HirDatabase, | ||
4 | }; | 3 | }; |
5 | 4 | ||
6 | impl Crate { | 5 | impl Crate { |
7 | pub(crate) fn dependencies_impl(&self, db: &impl HirDatabase) -> Vec<CrateDependency> { | 6 | pub(crate) fn dependencies_impl( |
7 | &self, | ||
8 | db: &impl PersistentHirDatabase, | ||
9 | ) -> Vec<CrateDependency> { | ||
8 | let crate_graph = db.crate_graph(); | 10 | let crate_graph = db.crate_graph(); |
9 | crate_graph | 11 | crate_graph |
10 | .dependencies(self.crate_id) | 12 | .dependencies(self.crate_id) |
@@ -17,7 +19,7 @@ impl Crate { | |||
17 | }) | 19 | }) |
18 | .collect() | 20 | .collect() |
19 | } | 21 | } |
20 | pub(crate) fn root_module_impl(&self, db: &impl HirDatabase) -> Option<Module> { | 22 | pub(crate) fn root_module_impl(&self, db: &impl PersistentHirDatabase) -> Option<Module> { |
21 | let module_tree = db.module_tree(*self); | 23 | let module_tree = db.module_tree(*self); |
22 | let module_id = module_tree.modules().next()?; | 24 | let module_id = module_tree.modules().next()?; |
23 | 25 | ||
diff --git a/crates/ra_hir/src/code_model_impl/module.rs b/crates/ra_hir/src/code_model_impl/module.rs index 4a3901b8b..f487b8532 100644 --- a/crates/ra_hir/src/code_model_impl/module.rs +++ b/crates/ra_hir/src/code_model_impl/module.rs | |||
@@ -7,7 +7,7 @@ use crate::{ | |||
7 | module_tree::ModuleId, | 7 | module_tree::ModuleId, |
8 | impl_block::ImplId, | 8 | impl_block::ImplId, |
9 | nameres::{lower::ImportId}, | 9 | nameres::{lower::ImportId}, |
10 | db::HirDatabase, | 10 | HirDatabase, PersistentHirDatabase, |
11 | }; | 11 | }; |
12 | 12 | ||
13 | impl Module { | 13 | impl Module { |
@@ -24,7 +24,10 @@ impl Module { | |||
24 | Some(link.name(&module_tree).clone()) | 24 | Some(link.name(&module_tree).clone()) |
25 | } | 25 | } |
26 | 26 | ||
27 | pub(crate) fn definition_source_impl(&self, db: &impl HirDatabase) -> (FileId, ModuleSource) { | 27 | pub(crate) fn definition_source_impl( |
28 | &self, | ||
29 | db: &impl PersistentHirDatabase, | ||
30 | ) -> (FileId, ModuleSource) { | ||
28 | let module_tree = db.module_tree(self.krate); | 31 | let module_tree = db.module_tree(self.krate); |
29 | let file_id = self.module_id.file_id(&module_tree); | 32 | let file_id = self.module_id.file_id(&module_tree); |
30 | let decl_id = self.module_id.decl_id(&module_tree); | 33 | let decl_id = self.module_id.decl_id(&module_tree); |
@@ -67,7 +70,7 @@ impl Module { | |||
67 | source_map.get(&source, impl_id) | 70 | source_map.get(&source, impl_id) |
68 | } | 71 | } |
69 | 72 | ||
70 | pub(crate) fn crate_root_impl(&self, db: &impl HirDatabase) -> Module { | 73 | pub(crate) fn crate_root_impl(&self, db: &impl PersistentHirDatabase) -> Module { |
71 | let module_tree = db.module_tree(self.krate); | 74 | let module_tree = db.module_tree(self.krate); |
72 | let module_id = self.module_id.crate_root(&module_tree); | 75 | let module_id = self.module_id.crate_root(&module_tree); |
73 | self.with_module_id(module_id) | 76 | self.with_module_id(module_id) |
@@ -81,7 +84,10 @@ impl Module { | |||
81 | } | 84 | } |
82 | 85 | ||
83 | /// Iterates over all child modules. | 86 | /// Iterates over all child modules. |
84 | pub(crate) fn children_impl(&self, db: &impl HirDatabase) -> impl Iterator<Item = Module> { | 87 | pub(crate) fn children_impl( |
88 | &self, | ||
89 | db: &impl PersistentHirDatabase, | ||
90 | ) -> impl Iterator<Item = Module> { | ||
85 | let module_tree = db.module_tree(self.krate); | 91 | let module_tree = db.module_tree(self.krate); |
86 | let children = self | 92 | let children = self |
87 | .module_id | 93 | .module_id |
@@ -91,7 +97,7 @@ impl Module { | |||
91 | children.into_iter() | 97 | children.into_iter() |
92 | } | 98 | } |
93 | 99 | ||
94 | pub(crate) fn parent_impl(&self, db: &impl HirDatabase) -> Option<Module> { | 100 | pub(crate) fn parent_impl(&self, db: &impl PersistentHirDatabase) -> Option<Module> { |
95 | let module_tree = db.module_tree(self.krate); | 101 | let module_tree = db.module_tree(self.krate); |
96 | let parent_id = self.module_id.parent(&module_tree)?; | 102 | let parent_id = self.module_id.parent(&module_tree)?; |
97 | Some(self.with_module_id(parent_id)) | 103 | Some(self.with_module_id(parent_id)) |
diff --git a/crates/ra_hir/src/db.rs b/crates/ra_hir/src/db.rs index 189649841..6b21fe744 100644 --- a/crates/ra_hir/src/db.rs +++ b/crates/ra_hir/src/db.rs | |||
@@ -19,32 +19,20 @@ use crate::{ | |||
19 | ids::SourceFileItemId, | 19 | ids::SourceFileItemId, |
20 | }; | 20 | }; |
21 | 21 | ||
22 | #[salsa::query_group(HirDatabaseStorage)] | 22 | #[salsa::query_group(PersistentHirDatabaseStorage)] |
23 | pub trait HirDatabase: SourceDatabase + AsRef<HirInterner> { | 23 | pub trait PersistentHirDatabase: SourceDatabase + AsRef<HirInterner> { |
24 | #[salsa::invoke(HirFileId::hir_parse)] | 24 | #[salsa::invoke(HirFileId::hir_parse)] |
25 | fn hir_parse(&self, file_id: HirFileId) -> TreeArc<SourceFile>; | 25 | fn hir_parse(&self, file_id: HirFileId) -> TreeArc<SourceFile>; |
26 | 26 | ||
27 | #[salsa::invoke(crate::macros::expand_macro_invocation)] | 27 | #[salsa::invoke(crate::macros::expand_macro_invocation)] |
28 | fn expand_macro_invocation(&self, invoc: MacroCallId) -> Option<Arc<MacroExpansion>>; | 28 | fn expand_macro_invocation(&self, invoc: MacroCallId) -> Option<Arc<MacroExpansion>>; |
29 | 29 | ||
30 | #[salsa::invoke(ExprScopes::expr_scopes_query)] | ||
31 | fn expr_scopes(&self, func: Function) -> Arc<ExprScopes>; | ||
32 | |||
33 | #[salsa::invoke(crate::adt::StructData::struct_data_query)] | 30 | #[salsa::invoke(crate::adt::StructData::struct_data_query)] |
34 | fn struct_data(&self, s: Struct) -> Arc<StructData>; | 31 | fn struct_data(&self, s: Struct) -> Arc<StructData>; |
35 | 32 | ||
36 | #[salsa::invoke(crate::adt::EnumData::enum_data_query)] | 33 | #[salsa::invoke(crate::adt::EnumData::enum_data_query)] |
37 | fn enum_data(&self, e: Enum) -> Arc<EnumData>; | 34 | fn enum_data(&self, e: Enum) -> Arc<EnumData>; |
38 | 35 | ||
39 | #[salsa::invoke(crate::ty::infer)] | ||
40 | fn infer(&self, func: Function) -> Arc<InferenceResult>; | ||
41 | |||
42 | #[salsa::invoke(crate::ty::type_for_def)] | ||
43 | fn type_for_def(&self, def: TypableDef) -> Ty; | ||
44 | |||
45 | #[salsa::invoke(crate::ty::type_for_field)] | ||
46 | fn type_for_field(&self, field: StructField) -> Ty; | ||
47 | |||
48 | #[salsa::invoke(query_definitions::file_items)] | 36 | #[salsa::invoke(query_definitions::file_items)] |
49 | fn file_items(&self, file_id: HirFileId) -> Arc<SourceFileItems>; | 37 | fn file_items(&self, file_id: HirFileId) -> Arc<SourceFileItems>; |
50 | 38 | ||
@@ -73,20 +61,38 @@ pub trait HirDatabase: SourceDatabase + AsRef<HirInterner> { | |||
73 | #[salsa::invoke(crate::module_tree::ModuleTree::module_tree_query)] | 61 | #[salsa::invoke(crate::module_tree::ModuleTree::module_tree_query)] |
74 | fn module_tree(&self, krate: Crate) -> Arc<ModuleTree>; | 62 | fn module_tree(&self, krate: Crate) -> Arc<ModuleTree>; |
75 | 63 | ||
64 | #[salsa::invoke(crate::impl_block::impls_in_module)] | ||
65 | fn impls_in_module(&self, module: Module) -> Arc<ModuleImplBlocks>; | ||
66 | |||
67 | #[salsa::invoke(crate::impl_block::impls_in_module_source_map_query)] | ||
68 | fn impls_in_module_source_map(&self, module: Module) -> Arc<ImplSourceMap>; | ||
69 | |||
76 | #[salsa::invoke(crate::impl_block::impls_in_module_with_source_map_query)] | 70 | #[salsa::invoke(crate::impl_block::impls_in_module_with_source_map_query)] |
77 | fn impls_in_module_with_source_map( | 71 | fn impls_in_module_with_source_map( |
78 | &self, | 72 | &self, |
79 | module: Module, | 73 | module: Module, |
80 | ) -> (Arc<ModuleImplBlocks>, Arc<ImplSourceMap>); | 74 | ) -> (Arc<ModuleImplBlocks>, Arc<ImplSourceMap>); |
81 | 75 | ||
82 | #[salsa::invoke(crate::impl_block::impls_in_module)] | 76 | #[salsa::invoke(crate::generics::GenericParams::generic_params_query)] |
83 | fn impls_in_module(&self, module: Module) -> Arc<ModuleImplBlocks>; | 77 | fn generic_params(&self, def: GenericDef) -> Arc<GenericParams>; |
84 | 78 | ||
85 | #[salsa::invoke(crate::impl_block::impls_in_module_source_map_query)] | 79 | #[salsa::invoke(crate::FnSignature::fn_signature_query)] |
86 | fn impls_in_module_source_map(&self, module: Module) -> Arc<ImplSourceMap>; | 80 | fn fn_signature(&self, func: Function) -> Arc<FnSignature>; |
81 | } | ||
87 | 82 | ||
88 | #[salsa::invoke(crate::ty::method_resolution::CrateImplBlocks::impls_in_crate_query)] | 83 | #[salsa::query_group(HirDatabaseStorage)] |
89 | fn impls_in_crate(&self, krate: Crate) -> Arc<CrateImplBlocks>; | 84 | pub trait HirDatabase: PersistentHirDatabase { |
85 | #[salsa::invoke(ExprScopes::expr_scopes_query)] | ||
86 | fn expr_scopes(&self, func: Function) -> Arc<ExprScopes>; | ||
87 | |||
88 | #[salsa::invoke(crate::ty::infer)] | ||
89 | fn infer(&self, func: Function) -> Arc<InferenceResult>; | ||
90 | |||
91 | #[salsa::invoke(crate::ty::type_for_def)] | ||
92 | fn type_for_def(&self, def: TypableDef) -> Ty; | ||
93 | |||
94 | #[salsa::invoke(crate::ty::type_for_field)] | ||
95 | fn type_for_field(&self, field: StructField) -> Ty; | ||
90 | 96 | ||
91 | #[salsa::invoke(crate::expr::body_hir)] | 97 | #[salsa::invoke(crate::expr::body_hir)] |
92 | fn body_hir(&self, func: Function) -> Arc<crate::expr::Body>; | 98 | fn body_hir(&self, func: Function) -> Arc<crate::expr::Body>; |
@@ -94,9 +100,6 @@ pub trait HirDatabase: SourceDatabase + AsRef<HirInterner> { | |||
94 | #[salsa::invoke(crate::expr::body_syntax_mapping)] | 100 | #[salsa::invoke(crate::expr::body_syntax_mapping)] |
95 | fn body_syntax_mapping(&self, func: Function) -> Arc<crate::expr::BodySyntaxMapping>; | 101 | fn body_syntax_mapping(&self, func: Function) -> Arc<crate::expr::BodySyntaxMapping>; |
96 | 102 | ||
97 | #[salsa::invoke(crate::generics::GenericParams::generic_params_query)] | 103 | #[salsa::invoke(crate::ty::method_resolution::CrateImplBlocks::impls_in_crate_query)] |
98 | fn generic_params(&self, def: GenericDef) -> Arc<GenericParams>; | 104 | fn impls_in_crate(&self, krate: Crate) -> Arc<CrateImplBlocks>; |
99 | |||
100 | #[salsa::invoke(crate::FnSignature::fn_signature_query)] | ||
101 | fn fn_signature(&self, func: Function) -> Arc<FnSignature>; | ||
102 | } | 105 | } |
diff --git a/crates/ra_hir/src/expr.rs b/crates/ra_hir/src/expr.rs index 37aa24677..f9f702ae2 100644 --- a/crates/ra_hir/src/expr.rs +++ b/crates/ra_hir/src/expr.rs | |||
@@ -10,7 +10,7 @@ use ra_syntax::{ | |||
10 | }; | 10 | }; |
11 | 11 | ||
12 | use crate::{ | 12 | use crate::{ |
13 | Path, Name, HirDatabase, Function, | 13 | Path, Name, HirDatabase, Function, Resolver, |
14 | name::AsName, | 14 | name::AsName, |
15 | type_ref::{Mutability, TypeRef}, | 15 | type_ref::{Mutability, TypeRef}, |
16 | }; | 16 | }; |
@@ -18,7 +18,7 @@ use crate::ty::primitive::{UintTy, UncertainIntTy, UncertainFloatTy}; | |||
18 | 18 | ||
19 | pub use self::scope::{ExprScopes, ScopesWithSyntaxMapping, ScopeEntryWithSyntax}; | 19 | pub use self::scope::{ExprScopes, ScopesWithSyntaxMapping, ScopeEntryWithSyntax}; |
20 | 20 | ||
21 | mod scope; | 21 | pub(crate) mod scope; |
22 | 22 | ||
23 | #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] | 23 | #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] |
24 | pub struct ExprId(RawId); | 24 | pub struct ExprId(RawId); |
@@ -27,6 +27,9 @@ impl_arena_id!(ExprId); | |||
27 | /// The body of an item (function, const etc.). | 27 | /// The body of an item (function, const etc.). |
28 | #[derive(Debug, Eq, PartialEq)] | 28 | #[derive(Debug, Eq, PartialEq)] |
29 | pub struct Body { | 29 | pub struct Body { |
30 | // TODO: this should be more general, consts & statics also have bodies | ||
31 | /// The Function of the item this body belongs to | ||
32 | owner: Function, | ||
30 | exprs: Arena<ExprId, Expr>, | 33 | exprs: Arena<ExprId, Expr>, |
31 | pats: Arena<PatId, Pat>, | 34 | pats: Arena<PatId, Pat>, |
32 | /// The patterns for the function's parameters. While the parameter types are | 35 | /// The patterns for the function's parameters. While the parameter types are |
@@ -62,6 +65,34 @@ impl Body { | |||
62 | pub fn body_expr(&self) -> ExprId { | 65 | pub fn body_expr(&self) -> ExprId { |
63 | self.body_expr | 66 | self.body_expr |
64 | } | 67 | } |
68 | |||
69 | pub fn owner(&self) -> Function { | ||
70 | self.owner | ||
71 | } | ||
72 | |||
73 | pub fn syntax_mapping(&self, db: &impl HirDatabase) -> Arc<BodySyntaxMapping> { | ||
74 | db.body_syntax_mapping(self.owner) | ||
75 | } | ||
76 | } | ||
77 | |||
78 | // needs arbitrary_self_types to be a method... or maybe move to the def? | ||
79 | pub fn resolver_for_expr(body: Arc<Body>, db: &impl HirDatabase, expr_id: ExprId) -> Resolver { | ||
80 | let scopes = db.expr_scopes(body.owner); | ||
81 | resolver_for_scope(body, db, scopes.scope_for(expr_id)) | ||
82 | } | ||
83 | |||
84 | pub fn resolver_for_scope( | ||
85 | body: Arc<Body>, | ||
86 | db: &impl HirDatabase, | ||
87 | scope_id: Option<scope::ScopeId>, | ||
88 | ) -> Resolver { | ||
89 | let mut r = body.owner.resolver(db); | ||
90 | let scopes = db.expr_scopes(body.owner); | ||
91 | let scope_chain = scopes.scope_chain_for(scope_id).collect::<Vec<_>>(); | ||
92 | for scope in scope_chain.into_iter().rev() { | ||
93 | r = r.push_expr_scope(Arc::clone(&scopes), scope); | ||
94 | } | ||
95 | r | ||
65 | } | 96 | } |
66 | 97 | ||
67 | impl Index<ExprId> for Body { | 98 | impl Index<ExprId> for Body { |
@@ -448,23 +479,29 @@ pub(crate) fn body_hir(db: &impl HirDatabase, func: Function) -> Arc<Body> { | |||
448 | } | 479 | } |
449 | 480 | ||
450 | struct ExprCollector { | 481 | struct ExprCollector { |
482 | owner: Function, | ||
451 | exprs: Arena<ExprId, Expr>, | 483 | exprs: Arena<ExprId, Expr>, |
452 | pats: Arena<PatId, Pat>, | 484 | pats: Arena<PatId, Pat>, |
453 | expr_syntax_mapping: FxHashMap<SyntaxNodePtr, ExprId>, | 485 | expr_syntax_mapping: FxHashMap<SyntaxNodePtr, ExprId>, |
454 | expr_syntax_mapping_back: ArenaMap<ExprId, SyntaxNodePtr>, | 486 | expr_syntax_mapping_back: ArenaMap<ExprId, SyntaxNodePtr>, |
455 | pat_syntax_mapping: FxHashMap<SyntaxNodePtr, PatId>, | 487 | pat_syntax_mapping: FxHashMap<SyntaxNodePtr, PatId>, |
456 | pat_syntax_mapping_back: ArenaMap<PatId, SyntaxNodePtr>, | 488 | pat_syntax_mapping_back: ArenaMap<PatId, SyntaxNodePtr>, |
489 | params: Vec<PatId>, | ||
490 | body_expr: Option<ExprId>, | ||
457 | } | 491 | } |
458 | 492 | ||
459 | impl ExprCollector { | 493 | impl ExprCollector { |
460 | fn new() -> Self { | 494 | fn new(owner: Function) -> Self { |
461 | ExprCollector { | 495 | ExprCollector { |
496 | owner, | ||
462 | exprs: Arena::default(), | 497 | exprs: Arena::default(), |
463 | pats: Arena::default(), | 498 | pats: Arena::default(), |
464 | expr_syntax_mapping: FxHashMap::default(), | 499 | expr_syntax_mapping: FxHashMap::default(), |
465 | expr_syntax_mapping_back: ArenaMap::default(), | 500 | expr_syntax_mapping_back: ArenaMap::default(), |
466 | pat_syntax_mapping: FxHashMap::default(), | 501 | pat_syntax_mapping: FxHashMap::default(), |
467 | pat_syntax_mapping_back: ArenaMap::default(), | 502 | pat_syntax_mapping_back: ArenaMap::default(), |
503 | params: Vec::new(), | ||
504 | body_expr: None, | ||
468 | } | 505 | } |
469 | } | 506 | } |
470 | 507 | ||
@@ -902,10 +939,7 @@ impl ExprCollector { | |||
902 | }); | 939 | }); |
903 | fields.extend(iter); | 940 | fields.extend(iter); |
904 | 941 | ||
905 | Pat::Struct { | 942 | Pat::Struct { path, args: fields } |
906 | path: path, | ||
907 | args: fields, | ||
908 | } | ||
909 | } | 943 | } |
910 | 944 | ||
911 | // TODO: implement | 945 | // TODO: implement |
@@ -923,12 +957,48 @@ impl ExprCollector { | |||
923 | } | 957 | } |
924 | } | 958 | } |
925 | 959 | ||
926 | fn into_body_syntax_mapping(self, params: Vec<PatId>, body_expr: ExprId) -> BodySyntaxMapping { | 960 | fn collect_fn_body(&mut self, node: &ast::FnDef) { |
961 | if let Some(param_list) = node.param_list() { | ||
962 | if let Some(self_param) = param_list.self_param() { | ||
963 | let self_param = SyntaxNodePtr::new( | ||
964 | self_param | ||
965 | .self_kw() | ||
966 | .expect("self param without self keyword") | ||
967 | .syntax(), | ||
968 | ); | ||
969 | let param_pat = self.alloc_pat( | ||
970 | Pat::Bind { | ||
971 | name: Name::self_param(), | ||
972 | mode: BindingAnnotation::Unannotated, | ||
973 | subpat: None, | ||
974 | }, | ||
975 | self_param, | ||
976 | ); | ||
977 | self.params.push(param_pat); | ||
978 | } | ||
979 | |||
980 | for param in param_list.params() { | ||
981 | let pat = if let Some(pat) = param.pat() { | ||
982 | pat | ||
983 | } else { | ||
984 | continue; | ||
985 | }; | ||
986 | let param_pat = self.collect_pat(pat); | ||
987 | self.params.push(param_pat); | ||
988 | } | ||
989 | }; | ||
990 | |||
991 | let body = self.collect_block_opt(node.body()); | ||
992 | self.body_expr = Some(body); | ||
993 | } | ||
994 | |||
995 | fn into_body_syntax_mapping(self) -> BodySyntaxMapping { | ||
927 | let body = Body { | 996 | let body = Body { |
997 | owner: self.owner, | ||
928 | exprs: self.exprs, | 998 | exprs: self.exprs, |
929 | pats: self.pats, | 999 | pats: self.pats, |
930 | params, | 1000 | params: self.params, |
931 | body_expr, | 1001 | body_expr: self.body_expr.expect("A body should have been collected"), |
932 | }; | 1002 | }; |
933 | BodySyntaxMapping { | 1003 | BodySyntaxMapping { |
934 | body: Arc::new(body), | 1004 | body: Arc::new(body), |
@@ -940,49 +1010,18 @@ impl ExprCollector { | |||
940 | } | 1010 | } |
941 | } | 1011 | } |
942 | 1012 | ||
943 | pub(crate) fn collect_fn_body_syntax(node: &ast::FnDef) -> BodySyntaxMapping { | 1013 | pub(crate) fn body_syntax_mapping(db: &impl HirDatabase, func: Function) -> Arc<BodySyntaxMapping> { |
944 | let mut collector = ExprCollector::new(); | 1014 | let mut collector = ExprCollector::new(func); |
945 | |||
946 | let params = if let Some(param_list) = node.param_list() { | ||
947 | let mut params = Vec::new(); | ||
948 | |||
949 | if let Some(self_param) = param_list.self_param() { | ||
950 | let self_param = SyntaxNodePtr::new( | ||
951 | self_param | ||
952 | .self_kw() | ||
953 | .expect("self param without self keyword") | ||
954 | .syntax(), | ||
955 | ); | ||
956 | let param = collector.alloc_pat( | ||
957 | Pat::Bind { | ||
958 | name: Name::self_param(), | ||
959 | mode: BindingAnnotation::Unannotated, | ||
960 | subpat: None, | ||
961 | }, | ||
962 | self_param, | ||
963 | ); | ||
964 | params.push(param); | ||
965 | } | ||
966 | 1015 | ||
967 | for param in param_list.params() { | 1016 | // TODO: consts, etc. |
968 | let pat = if let Some(pat) = param.pat() { | 1017 | collector.collect_fn_body(&func.source(db).1); |
969 | pat | ||
970 | } else { | ||
971 | continue; | ||
972 | }; | ||
973 | params.push(collector.collect_pat(pat)); | ||
974 | } | ||
975 | params | ||
976 | } else { | ||
977 | Vec::new() | ||
978 | }; | ||
979 | 1018 | ||
980 | let body = collector.collect_block_opt(node.body()); | 1019 | Arc::new(collector.into_body_syntax_mapping()) |
981 | collector.into_body_syntax_mapping(params, body) | ||
982 | } | 1020 | } |
983 | 1021 | ||
984 | pub(crate) fn body_syntax_mapping(db: &impl HirDatabase, func: Function) -> Arc<BodySyntaxMapping> { | 1022 | #[cfg(test)] |
985 | let (_, fn_def) = func.source(db); | 1023 | pub(crate) fn collect_fn_body_syntax(function: Function, node: &ast::FnDef) -> BodySyntaxMapping { |
986 | let body_syntax_mapping = collect_fn_body_syntax(&fn_def); | 1024 | let mut collector = ExprCollector::new(function); |
987 | Arc::new(body_syntax_mapping) | 1025 | collector.collect_fn_body(node); |
1026 | collector.into_body_syntax_mapping() | ||
988 | } | 1027 | } |
diff --git a/crates/ra_hir/src/expr/scope.rs b/crates/ra_hir/src/expr/scope.rs index f8b5ba581..9202e3671 100644 --- a/crates/ra_hir/src/expr/scope.rs +++ b/crates/ra_hir/src/expr/scope.rs | |||
@@ -12,7 +12,7 @@ use ra_arena::{Arena, RawId, impl_arena_id}; | |||
12 | use crate::{ | 12 | use crate::{ |
13 | Name, AsName, Function, | 13 | Name, AsName, Function, |
14 | expr::{PatId, ExprId, Pat, Expr, Body, Statement, BodySyntaxMapping}, | 14 | expr::{PatId, ExprId, Pat, Expr, Body, Statement, BodySyntaxMapping}, |
15 | db::HirDatabase, | 15 | HirDatabase, |
16 | }; | 16 | }; |
17 | 17 | ||
18 | #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] | 18 | #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] |
@@ -58,28 +58,19 @@ impl ExprScopes { | |||
58 | scopes | 58 | scopes |
59 | } | 59 | } |
60 | 60 | ||
61 | pub fn entries(&self, scope: ScopeId) -> &[ScopeEntry] { | 61 | pub fn body(&self) -> Arc<Body> { |
62 | &self.scopes[scope].entries | 62 | self.body.clone() |
63 | } | 63 | } |
64 | 64 | ||
65 | pub fn scope_chain_for<'a>(&'a self, expr: ExprId) -> impl Iterator<Item = ScopeId> + 'a { | 65 | pub fn entries(&self, scope: ScopeId) -> &[ScopeEntry] { |
66 | generate(self.scope_for(expr), move |&scope| { | 66 | &self.scopes[scope].entries |
67 | self.scopes[scope].parent | ||
68 | }) | ||
69 | } | 67 | } |
70 | 68 | ||
71 | pub fn resolve_local_name<'a>( | 69 | pub fn scope_chain_for<'a>( |
72 | &'a self, | 70 | &'a self, |
73 | context_expr: ExprId, | 71 | scope: Option<ScopeId>, |
74 | name: Name, | 72 | ) -> impl Iterator<Item = ScopeId> + 'a { |
75 | ) -> Option<&'a ScopeEntry> { | 73 | generate(scope, move |&scope| self.scopes[scope].parent) |
76 | let mut shadowed = FxHashSet::default(); | ||
77 | let ret = self | ||
78 | .scope_chain_for(context_expr) | ||
79 | .flat_map(|scope| self.entries(scope).iter()) | ||
80 | .filter(|entry| shadowed.insert(entry.name())) | ||
81 | .find(|entry| entry.name() == &name); | ||
82 | ret | ||
83 | } | 74 | } |
84 | 75 | ||
85 | fn root_scope(&mut self) -> ScopeId { | 76 | fn root_scope(&mut self) -> ScopeId { |
@@ -122,7 +113,7 @@ impl ExprScopes { | |||
122 | self.scope_for.insert(node, scope); | 113 | self.scope_for.insert(node, scope); |
123 | } | 114 | } |
124 | 115 | ||
125 | fn scope_for(&self, expr: ExprId) -> Option<ScopeId> { | 116 | pub fn scope_for(&self, expr: ExprId) -> Option<ScopeId> { |
126 | self.scope_for.get(&expr).map(|&scope| scope) | 117 | self.scope_for.get(&expr).map(|&scope| scope) |
127 | } | 118 | } |
128 | } | 119 | } |
@@ -150,18 +141,14 @@ impl ScopeEntryWithSyntax { | |||
150 | } | 141 | } |
151 | 142 | ||
152 | impl ScopesWithSyntaxMapping { | 143 | impl ScopesWithSyntaxMapping { |
153 | pub fn scope_chain<'a>(&'a self, node: &SyntaxNode) -> impl Iterator<Item = ScopeId> + 'a { | 144 | fn scope_chain<'a>(&'a self, node: &SyntaxNode) -> impl Iterator<Item = ScopeId> + 'a { |
154 | generate(self.scope_for(node), move |&scope| { | 145 | generate(self.scope_for(node), move |&scope| { |
155 | self.scopes.scopes[scope].parent | 146 | self.scopes.scopes[scope].parent |
156 | }) | 147 | }) |
157 | } | 148 | } |
158 | 149 | ||
159 | pub fn scope_chain_for_offset<'a>( | 150 | pub fn scope_for_offset<'a>(&'a self, offset: TextUnit) -> Option<ScopeId> { |
160 | &'a self, | 151 | self.scopes |
161 | offset: TextUnit, | ||
162 | ) -> impl Iterator<Item = ScopeId> + 'a { | ||
163 | let scope = self | ||
164 | .scopes | ||
165 | .scope_for | 152 | .scope_for |
166 | .iter() | 153 | .iter() |
167 | .filter_map(|(id, scope)| Some((self.syntax_mapping.expr_syntax(*id)?, scope))) | 154 | .filter_map(|(id, scope)| Some((self.syntax_mapping.expr_syntax(*id)?, scope))) |
@@ -172,13 +159,12 @@ impl ScopesWithSyntaxMapping { | |||
172 | ptr.range().len(), | 159 | ptr.range().len(), |
173 | ) | 160 | ) |
174 | }) | 161 | }) |
175 | .map(|(ptr, scope)| self.adjust(ptr, *scope, offset)); | 162 | .map(|(ptr, scope)| self.adjust(ptr, *scope, offset)) |
176 | |||
177 | generate(scope, move |&scope| self.scopes.scopes[scope].parent) | ||
178 | } | 163 | } |
179 | 164 | ||
180 | // XXX: during completion, cursor might be outside of any particular | 165 | // XXX: during completion, cursor might be outside of any particular |
181 | // expression. Try to figure out the correct scope... | 166 | // expression. Try to figure out the correct scope... |
167 | // TODO: move this to source binder? | ||
182 | fn adjust(&self, ptr: SyntaxNodePtr, original_scope: ScopeId, offset: TextUnit) -> ScopeId { | 168 | fn adjust(&self, ptr: SyntaxNodePtr, original_scope: ScopeId, offset: TextUnit) -> ScopeId { |
183 | let r = ptr.range(); | 169 | let r = ptr.range(); |
184 | let child_scopes = self | 170 | let child_scopes = self |
@@ -238,7 +224,7 @@ impl ScopesWithSyntaxMapping { | |||
238 | .collect() | 224 | .collect() |
239 | } | 225 | } |
240 | 226 | ||
241 | fn scope_for(&self, node: &SyntaxNode) -> Option<ScopeId> { | 227 | pub fn scope_for(&self, node: &SyntaxNode) -> Option<ScopeId> { |
242 | node.ancestors() | 228 | node.ancestors() |
243 | .map(SyntaxNodePtr::new) | 229 | .map(SyntaxNodePtr::new) |
244 | .filter_map(|ptr| self.syntax_mapping.syntax_expr(ptr)) | 230 | .filter_map(|ptr| self.syntax_mapping.syntax_expr(ptr)) |
@@ -336,6 +322,7 @@ pub struct ReferenceDescriptor { | |||
336 | mod tests { | 322 | mod tests { |
337 | use ra_syntax::{SourceFile, algo::find_node_at_offset}; | 323 | use ra_syntax::{SourceFile, algo::find_node_at_offset}; |
338 | use test_utils::{extract_offset, assert_eq_text}; | 324 | use test_utils::{extract_offset, assert_eq_text}; |
325 | use ra_arena::ArenaId; | ||
339 | 326 | ||
340 | use crate::expr; | 327 | use crate::expr; |
341 | 328 | ||
@@ -354,7 +341,10 @@ mod tests { | |||
354 | let file = SourceFile::parse(&code); | 341 | let file = SourceFile::parse(&code); |
355 | let marker: &ast::PathExpr = find_node_at_offset(file.syntax(), off).unwrap(); | 342 | let marker: &ast::PathExpr = find_node_at_offset(file.syntax(), off).unwrap(); |
356 | let fn_def: &ast::FnDef = find_node_at_offset(file.syntax(), off).unwrap(); | 343 | let fn_def: &ast::FnDef = find_node_at_offset(file.syntax(), off).unwrap(); |
357 | let body_hir = expr::collect_fn_body_syntax(fn_def); | 344 | let irrelevant_function = Function { |
345 | id: crate::ids::FunctionId::from_raw(0.into()), | ||
346 | }; | ||
347 | let body_hir = expr::collect_fn_body_syntax(irrelevant_function, fn_def); | ||
358 | let scopes = ExprScopes::new(Arc::clone(body_hir.body())); | 348 | let scopes = ExprScopes::new(Arc::clone(body_hir.body())); |
359 | let scopes = ScopesWithSyntaxMapping { | 349 | let scopes = ScopesWithSyntaxMapping { |
360 | scopes: Arc::new(scopes), | 350 | scopes: Arc::new(scopes), |
@@ -454,7 +444,10 @@ mod tests { | |||
454 | let fn_def: &ast::FnDef = find_node_at_offset(file.syntax(), off).unwrap(); | 444 | let fn_def: &ast::FnDef = find_node_at_offset(file.syntax(), off).unwrap(); |
455 | let name_ref: &ast::NameRef = find_node_at_offset(file.syntax(), off).unwrap(); | 445 | let name_ref: &ast::NameRef = find_node_at_offset(file.syntax(), off).unwrap(); |
456 | 446 | ||
457 | let body_hir = expr::collect_fn_body_syntax(fn_def); | 447 | let irrelevant_function = Function { |
448 | id: crate::ids::FunctionId::from_raw(0.into()), | ||
449 | }; | ||
450 | let body_hir = expr::collect_fn_body_syntax(irrelevant_function, fn_def); | ||
458 | let scopes = ExprScopes::new(Arc::clone(body_hir.body())); | 451 | let scopes = ExprScopes::new(Arc::clone(body_hir.body())); |
459 | let scopes = ScopesWithSyntaxMapping { | 452 | let scopes = ScopesWithSyntaxMapping { |
460 | scopes: Arc::new(scopes), | 453 | scopes: Arc::new(scopes), |
diff --git a/crates/ra_hir/src/generics.rs b/crates/ra_hir/src/generics.rs index 64c20a462..a82205f0b 100644 --- a/crates/ra_hir/src/generics.rs +++ b/crates/ra_hir/src/generics.rs | |||
@@ -7,11 +7,12 @@ use std::sync::Arc; | |||
7 | 7 | ||
8 | use ra_syntax::ast::{self, NameOwner, TypeParamsOwner}; | 8 | use ra_syntax::ast::{self, NameOwner, TypeParamsOwner}; |
9 | 9 | ||
10 | use crate::{db::HirDatabase, Name, AsName, Function, Struct, Enum, Trait, Type}; | 10 | use crate::{db::PersistentHirDatabase, Name, AsName, Function, Struct, Enum, Trait, Type}; |
11 | 11 | ||
12 | /// Data about a generic parameter (to a function, struct, impl, ...). | 12 | /// Data about a generic parameter (to a function, struct, impl, ...). |
13 | #[derive(Clone, PartialEq, Eq, Debug)] | 13 | #[derive(Clone, PartialEq, Eq, Debug)] |
14 | pub struct GenericParam { | 14 | pub struct GenericParam { |
15 | // TODO: give generic params proper IDs | ||
15 | pub(crate) idx: u32, | 16 | pub(crate) idx: u32, |
16 | pub(crate) name: Name, | 17 | pub(crate) name: Name, |
17 | } | 18 | } |
@@ -34,7 +35,7 @@ impl_froms!(GenericDef: Function, Struct, Enum, Trait, Type); | |||
34 | 35 | ||
35 | impl GenericParams { | 36 | impl GenericParams { |
36 | pub(crate) fn generic_params_query( | 37 | pub(crate) fn generic_params_query( |
37 | db: &impl HirDatabase, | 38 | db: &impl PersistentHirDatabase, |
38 | def: GenericDef, | 39 | def: GenericDef, |
39 | ) -> Arc<GenericParams> { | 40 | ) -> Arc<GenericParams> { |
40 | let mut generics = GenericParams::default(); | 41 | let mut generics = GenericParams::default(); |
diff --git a/crates/ra_hir/src/ids.rs b/crates/ra_hir/src/ids.rs index 0e4dc6261..95678bf70 100644 --- a/crates/ra_hir/src/ids.rs +++ b/crates/ra_hir/src/ids.rs | |||
@@ -10,6 +10,7 @@ use ra_arena::{Arena, RawId, ArenaId, impl_arena_id}; | |||
10 | use crate::{ | 10 | use crate::{ |
11 | HirDatabase, | 11 | HirDatabase, |
12 | Module, | 12 | Module, |
13 | PersistentHirDatabase, | ||
13 | }; | 14 | }; |
14 | 15 | ||
15 | #[derive(Debug, Default)] | 16 | #[derive(Debug, Default)] |
@@ -62,7 +63,7 @@ pub struct HirFileId(HirFileIdRepr); | |||
62 | impl HirFileId { | 63 | impl HirFileId { |
63 | /// For macro-expansion files, returns the file original source file the | 64 | /// For macro-expansion files, returns the file original source file the |
64 | /// expansionoriginated from. | 65 | /// expansionoriginated from. |
65 | pub fn original_file(self, db: &impl HirDatabase) -> FileId { | 66 | pub fn original_file(self, db: &impl PersistentHirDatabase) -> FileId { |
66 | match self.0 { | 67 | match self.0 { |
67 | HirFileIdRepr::File(file_id) => file_id, | 68 | HirFileIdRepr::File(file_id) => file_id, |
68 | HirFileIdRepr::Macro(macro_call_id) => { | 69 | HirFileIdRepr::Macro(macro_call_id) => { |
@@ -86,7 +87,10 @@ impl HirFileId { | |||
86 | } | 87 | } |
87 | } | 88 | } |
88 | 89 | ||
89 | pub(crate) fn hir_parse(db: &impl HirDatabase, file_id: HirFileId) -> TreeArc<SourceFile> { | 90 | pub(crate) fn hir_parse( |
91 | db: &impl PersistentHirDatabase, | ||
92 | file_id: HirFileId, | ||
93 | ) -> TreeArc<SourceFile> { | ||
90 | match file_id.0 { | 94 | match file_id.0 { |
91 | HirFileIdRepr::File(file_id) => db.parse(file_id), | 95 | HirFileIdRepr::File(file_id) => db.parse(file_id), |
92 | HirFileIdRepr::Macro(m) => { | 96 | HirFileIdRepr::Macro(m) => { |
@@ -180,7 +184,7 @@ pub(crate) struct LocationCtx<DB> { | |||
180 | file_id: HirFileId, | 184 | file_id: HirFileId, |
181 | } | 185 | } |
182 | 186 | ||
183 | impl<'a, DB: HirDatabase> LocationCtx<&'a DB> { | 187 | impl<'a, DB: PersistentHirDatabase> LocationCtx<&'a DB> { |
184 | pub(crate) fn new(db: &'a DB, module: Module, file_id: HirFileId) -> LocationCtx<&'a DB> { | 188 | pub(crate) fn new(db: &'a DB, module: Module, file_id: HirFileId) -> LocationCtx<&'a DB> { |
185 | LocationCtx { | 189 | LocationCtx { |
186 | db, | 190 | db, |
@@ -199,7 +203,7 @@ impl<'a, DB: HirDatabase> LocationCtx<&'a DB> { | |||
199 | 203 | ||
200 | pub(crate) trait AstItemDef<N: AstNode>: ArenaId + Clone { | 204 | pub(crate) trait AstItemDef<N: AstNode>: ArenaId + Clone { |
201 | fn interner(interner: &HirInterner) -> &LocationIntener<ItemLoc<N>, Self>; | 205 | fn interner(interner: &HirInterner) -> &LocationIntener<ItemLoc<N>, Self>; |
202 | fn from_ast(ctx: LocationCtx<&impl HirDatabase>, ast: &N) -> Self { | 206 | fn from_ast(ctx: LocationCtx<&impl PersistentHirDatabase>, ast: &N) -> Self { |
203 | let items = ctx.db.file_items(ctx.file_id); | 207 | let items = ctx.db.file_items(ctx.file_id); |
204 | let raw = SourceItemId { | 208 | let raw = SourceItemId { |
205 | file_id: ctx.file_id, | 209 | file_id: ctx.file_id, |
@@ -213,7 +217,7 @@ pub(crate) trait AstItemDef<N: AstNode>: ArenaId + Clone { | |||
213 | 217 | ||
214 | Self::interner(ctx.db.as_ref()).loc2id(&loc) | 218 | Self::interner(ctx.db.as_ref()).loc2id(&loc) |
215 | } | 219 | } |
216 | fn source(self, db: &impl HirDatabase) -> (HirFileId, TreeArc<N>) { | 220 | fn source(self, db: &impl PersistentHirDatabase) -> (HirFileId, TreeArc<N>) { |
217 | let int = Self::interner(db.as_ref()); | 221 | let int = Self::interner(db.as_ref()); |
218 | let loc = int.id2loc(self); | 222 | let loc = int.id2loc(self); |
219 | let syntax = db.file_item(loc.raw); | 223 | let syntax = db.file_item(loc.raw); |
diff --git a/crates/ra_hir/src/impl_block.rs b/crates/ra_hir/src/impl_block.rs index 5fc26324a..738c58fbe 100644 --- a/crates/ra_hir/src/impl_block.rs +++ b/crates/ra_hir/src/impl_block.rs | |||
@@ -7,11 +7,13 @@ use ra_syntax::{ | |||
7 | ast::{self, AstNode}}; | 7 | ast::{self, AstNode}}; |
8 | 8 | ||
9 | use crate::{ | 9 | use crate::{ |
10 | Const, Type, | 10 | Const, Type, Function, HirFileId, |
11 | Function, HirFileId, | 11 | HirDatabase, PersistentHirDatabase, |
12 | db::HirDatabase, | 12 | ModuleDef, Trait, Resolution, |
13 | type_ref::TypeRef, | 13 | type_ref::TypeRef, |
14 | ids::LocationCtx, | 14 | ids::LocationCtx, |
15 | resolve::Resolver, | ||
16 | ty::Ty, | ||
15 | }; | 17 | }; |
16 | 18 | ||
17 | use crate::code_model_api::{Module, ModuleSource}; | 19 | use crate::code_model_api::{Module, ModuleSource}; |
@@ -69,7 +71,11 @@ impl ImplBlock { | |||
69 | &self.module_impl_blocks.impls[self.impl_id] | 71 | &self.module_impl_blocks.impls[self.impl_id] |
70 | } | 72 | } |
71 | 73 | ||
72 | pub fn target_trait(&self) -> Option<&TypeRef> { | 74 | pub fn module(&self) -> Module { |
75 | self.module_impl_blocks.module.clone() | ||
76 | } | ||
77 | |||
78 | pub fn target_trait_ref(&self) -> Option<&TypeRef> { | ||
73 | self.impl_data().target_trait() | 79 | self.impl_data().target_trait() |
74 | } | 80 | } |
75 | 81 | ||
@@ -77,9 +83,32 @@ impl ImplBlock { | |||
77 | self.impl_data().target_type() | 83 | self.impl_data().target_type() |
78 | } | 84 | } |
79 | 85 | ||
86 | pub fn target_ty(&self, db: &impl HirDatabase) -> Ty { | ||
87 | Ty::from_hir(db, &self.resolver(db), self.target_type()) | ||
88 | } | ||
89 | |||
90 | pub fn target_trait(&self, db: &impl HirDatabase) -> Option<Trait> { | ||
91 | if let Some(TypeRef::Path(path)) = self.target_trait_ref() { | ||
92 | let resolver = self.resolver(db); | ||
93 | if let Some(Resolution::Def(ModuleDef::Trait(tr))) = | ||
94 | resolver.resolve_path(db, path).take_types() | ||
95 | { | ||
96 | return Some(tr); | ||
97 | } | ||
98 | } | ||
99 | None | ||
100 | } | ||
101 | |||
80 | pub fn items(&self) -> &[ImplItem] { | 102 | pub fn items(&self) -> &[ImplItem] { |
81 | self.impl_data().items() | 103 | self.impl_data().items() |
82 | } | 104 | } |
105 | |||
106 | pub fn resolver(&self, db: &impl HirDatabase) -> Resolver { | ||
107 | let r = self.module().resolver(db); | ||
108 | // TODO: add generics | ||
109 | let r = r.push_impl_block_scope(self.clone()); | ||
110 | r | ||
111 | } | ||
83 | } | 112 | } |
84 | 113 | ||
85 | #[derive(Debug, Clone, PartialEq, Eq)] | 114 | #[derive(Debug, Clone, PartialEq, Eq)] |
@@ -91,7 +120,7 @@ pub struct ImplData { | |||
91 | 120 | ||
92 | impl ImplData { | 121 | impl ImplData { |
93 | pub(crate) fn from_ast( | 122 | pub(crate) fn from_ast( |
94 | db: &impl HirDatabase, | 123 | db: &impl PersistentHirDatabase, |
95 | file_id: HirFileId, | 124 | file_id: HirFileId, |
96 | module: Module, | 125 | module: Module, |
97 | node: &ast::ImplBlock, | 126 | node: &ast::ImplBlock, |
@@ -162,20 +191,24 @@ impl_arena_id!(ImplId); | |||
162 | /// we don't need to do the second step again. | 191 | /// we don't need to do the second step again. |
163 | #[derive(Debug, PartialEq, Eq)] | 192 | #[derive(Debug, PartialEq, Eq)] |
164 | pub struct ModuleImplBlocks { | 193 | pub struct ModuleImplBlocks { |
194 | module: Module, | ||
165 | pub(crate) impls: Arena<ImplId, ImplData>, | 195 | pub(crate) impls: Arena<ImplId, ImplData>, |
166 | impls_by_def: FxHashMap<ImplItem, ImplId>, | 196 | impls_by_def: FxHashMap<ImplItem, ImplId>, |
167 | } | 197 | } |
168 | 198 | ||
169 | impl ModuleImplBlocks { | 199 | impl ModuleImplBlocks { |
170 | fn new() -> Self { | 200 | fn collect( |
171 | ModuleImplBlocks { | 201 | db: &impl PersistentHirDatabase, |
202 | module: Module, | ||
203 | source_map: &mut ImplSourceMap, | ||
204 | ) -> Self { | ||
205 | let mut m = ModuleImplBlocks { | ||
206 | module, | ||
172 | impls: Arena::default(), | 207 | impls: Arena::default(), |
173 | impls_by_def: FxHashMap::default(), | 208 | impls_by_def: FxHashMap::default(), |
174 | } | 209 | }; |
175 | } | ||
176 | 210 | ||
177 | fn collect(&mut self, db: &impl HirDatabase, module: Module, source_map: &mut ImplSourceMap) { | 211 | let (file_id, module_source) = m.module.definition_source(db); |
178 | let (file_id, module_source) = module.definition_source(db); | ||
179 | let file_id: HirFileId = file_id.into(); | 212 | let file_id: HirFileId = file_id.into(); |
180 | let node = match &module_source { | 213 | let node = match &module_source { |
181 | ModuleSource::SourceFile(node) => node.syntax(), | 214 | ModuleSource::SourceFile(node) => node.syntax(), |
@@ -186,35 +219,39 @@ impl ModuleImplBlocks { | |||
186 | }; | 219 | }; |
187 | 220 | ||
188 | for impl_block_ast in node.children().filter_map(ast::ImplBlock::cast) { | 221 | for impl_block_ast in node.children().filter_map(ast::ImplBlock::cast) { |
189 | let impl_block = ImplData::from_ast(db, file_id, module, impl_block_ast); | 222 | let impl_block = ImplData::from_ast(db, file_id, m.module, impl_block_ast); |
190 | let id = self.impls.alloc(impl_block); | 223 | let id = m.impls.alloc(impl_block); |
191 | for &impl_item in &self.impls[id].items { | 224 | for &impl_item in &m.impls[id].items { |
192 | self.impls_by_def.insert(impl_item, id); | 225 | m.impls_by_def.insert(impl_item, id); |
193 | } | 226 | } |
194 | 227 | ||
195 | source_map.insert(id, impl_block_ast); | 228 | source_map.insert(id, impl_block_ast); |
196 | } | 229 | } |
230 | |||
231 | m | ||
197 | } | 232 | } |
198 | } | 233 | } |
199 | 234 | ||
200 | pub(crate) fn impls_in_module_with_source_map_query( | 235 | pub(crate) fn impls_in_module_with_source_map_query( |
201 | db: &impl HirDatabase, | 236 | db: &impl PersistentHirDatabase, |
202 | module: Module, | 237 | module: Module, |
203 | ) -> (Arc<ModuleImplBlocks>, Arc<ImplSourceMap>) { | 238 | ) -> (Arc<ModuleImplBlocks>, Arc<ImplSourceMap>) { |
204 | let mut source_map = ImplSourceMap::default(); | 239 | let mut source_map = ImplSourceMap::default(); |
205 | 240 | ||
206 | let mut result = ModuleImplBlocks::new(); | 241 | let result = ModuleImplBlocks::collect(db, module, &mut source_map); |
207 | result.collect(db, module, &mut source_map); | ||
208 | 242 | ||
209 | (Arc::new(result), Arc::new(source_map)) | 243 | (Arc::new(result), Arc::new(source_map)) |
210 | } | 244 | } |
211 | 245 | ||
212 | pub(crate) fn impls_in_module(db: &impl HirDatabase, module: Module) -> Arc<ModuleImplBlocks> { | 246 | pub(crate) fn impls_in_module( |
247 | db: &impl PersistentHirDatabase, | ||
248 | module: Module, | ||
249 | ) -> Arc<ModuleImplBlocks> { | ||
213 | db.impls_in_module_with_source_map(module).0 | 250 | db.impls_in_module_with_source_map(module).0 |
214 | } | 251 | } |
215 | 252 | ||
216 | pub(crate) fn impls_in_module_source_map_query( | 253 | pub(crate) fn impls_in_module_source_map_query( |
217 | db: &impl HirDatabase, | 254 | db: &impl PersistentHirDatabase, |
218 | module: Module, | 255 | module: Module, |
219 | ) -> Arc<ImplSourceMap> { | 256 | ) -> Arc<ImplSourceMap> { |
220 | db.impls_in_module_with_source_map(module).1 | 257 | db.impls_in_module_with_source_map(module).1 |
diff --git a/crates/ra_hir/src/lib.rs b/crates/ra_hir/src/lib.rs index 0b9ee63bf..54da55598 100644 --- a/crates/ra_hir/src/lib.rs +++ b/crates/ra_hir/src/lib.rs | |||
@@ -36,6 +36,7 @@ mod impl_block; | |||
36 | mod expr; | 36 | mod expr; |
37 | mod generics; | 37 | mod generics; |
38 | mod docs; | 38 | mod docs; |
39 | mod resolve; | ||
39 | 40 | ||
40 | mod code_model_api; | 41 | mod code_model_api; |
41 | mod code_model_impl; | 42 | mod code_model_impl; |
@@ -44,7 +45,7 @@ mod code_model_impl; | |||
44 | mod marks; | 45 | mod marks; |
45 | 46 | ||
46 | use crate::{ | 47 | use crate::{ |
47 | db::HirDatabase, | 48 | db::{HirDatabase, PersistentHirDatabase}, |
48 | name::{AsName, KnownName}, | 49 | name::{AsName, KnownName}, |
49 | ids::{SourceItemId, SourceFileItems}, | 50 | ids::{SourceItemId, SourceFileItems}, |
50 | }; | 51 | }; |
@@ -54,12 +55,13 @@ pub use self::{ | |||
54 | name::Name, | 55 | name::Name, |
55 | ids::{HirFileId, MacroCallId, MacroCallLoc, HirInterner}, | 56 | ids::{HirFileId, MacroCallId, MacroCallLoc, HirInterner}, |
56 | macros::{MacroDef, MacroInput, MacroExpansion}, | 57 | macros::{MacroDef, MacroInput, MacroExpansion}, |
57 | nameres::{ItemMap, PerNs, Namespace, Resolution}, | 58 | nameres::{ItemMap, PerNs, Namespace}, |
58 | ty::Ty, | 59 | ty::Ty, |
59 | impl_block::{ImplBlock, ImplItem}, | 60 | impl_block::{ImplBlock, ImplItem}, |
60 | docs::{Docs, Documentation}, | 61 | docs::{Docs, Documentation}, |
61 | adt::AdtDef, | 62 | adt::AdtDef, |
62 | expr::{ExprScopes, ScopesWithSyntaxMapping}, | 63 | expr::{ExprScopes, ScopesWithSyntaxMapping}, |
64 | resolve::{Resolver, Resolution}, | ||
63 | }; | 65 | }; |
64 | 66 | ||
65 | pub use self::code_model_api::{ | 67 | pub use self::code_model_api::{ |
diff --git a/crates/ra_hir/src/macros.rs b/crates/ra_hir/src/macros.rs index 7ca34d434..cb8a9312e 100644 --- a/crates/ra_hir/src/macros.rs +++ b/crates/ra_hir/src/macros.rs | |||
@@ -14,12 +14,11 @@ use ra_syntax::{ | |||
14 | ast::{self, NameOwner}, | 14 | ast::{self, NameOwner}, |
15 | }; | 15 | }; |
16 | 16 | ||
17 | use crate::{HirDatabase, MacroCallId}; | 17 | use crate::{MacroCallId, PersistentHirDatabase}; |
18 | 18 | ||
19 | // Hard-coded defs for now :-( | 19 | // Hard-coded defs for now :-( |
20 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | 20 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] |
21 | pub enum MacroDef { | 21 | pub enum MacroDef { |
22 | CTry, | ||
23 | Vec, | 22 | Vec, |
24 | QueryGroup, | 23 | QueryGroup, |
25 | } | 24 | } |
@@ -38,9 +37,7 @@ impl MacroDef { | |||
38 | let def = { | 37 | let def = { |
39 | let path = macro_call.path()?; | 38 | let path = macro_call.path()?; |
40 | let name_ref = path.segment()?.name_ref()?; | 39 | let name_ref = path.segment()?.name_ref()?; |
41 | if name_ref.text() == "ctry" { | 40 | if name_ref.text() == "vec" { |
42 | MacroDef::CTry | ||
43 | } else if name_ref.text() == "vec" { | ||
44 | MacroDef::Vec | 41 | MacroDef::Vec |
45 | } else if name_ref.text() == "query_group" { | 42 | } else if name_ref.text() == "query_group" { |
46 | MacroDef::QueryGroup | 43 | MacroDef::QueryGroup |
@@ -60,35 +57,10 @@ impl MacroDef { | |||
60 | 57 | ||
61 | fn expand(self, input: MacroInput) -> Option<MacroExpansion> { | 58 | fn expand(self, input: MacroInput) -> Option<MacroExpansion> { |
62 | match self { | 59 | match self { |
63 | MacroDef::CTry => self.expand_ctry(input), | ||
64 | MacroDef::Vec => self.expand_vec(input), | 60 | MacroDef::Vec => self.expand_vec(input), |
65 | MacroDef::QueryGroup => self.expand_query_group(input), | 61 | MacroDef::QueryGroup => self.expand_query_group(input), |
66 | } | 62 | } |
67 | } | 63 | } |
68 | fn expand_ctry(self, input: MacroInput) -> Option<MacroExpansion> { | ||
69 | let text = format!( | ||
70 | r" | ||
71 | fn dummy() {{ | ||
72 | match {} {{ | ||
73 | None => return Ok(None), | ||
74 | Some(it) => it, | ||
75 | }} | ||
76 | }}", | ||
77 | input.text | ||
78 | ); | ||
79 | let file = SourceFile::parse(&text); | ||
80 | let match_expr = file.syntax().descendants().find_map(ast::MatchExpr::cast)?; | ||
81 | let match_arg = match_expr.expr()?; | ||
82 | let ptr = SyntaxNodePtr::new(match_arg.syntax()); | ||
83 | let src_range = TextRange::offset_len(0.into(), TextUnit::of_str(&input.text)); | ||
84 | let ranges_map = vec![(src_range, match_arg.syntax().range())]; | ||
85 | let res = MacroExpansion { | ||
86 | text, | ||
87 | ranges_map, | ||
88 | ptr, | ||
89 | }; | ||
90 | Some(res) | ||
91 | } | ||
92 | fn expand_vec(self, input: MacroInput) -> Option<MacroExpansion> { | 64 | fn expand_vec(self, input: MacroInput) -> Option<MacroExpansion> { |
93 | let text = format!(r"fn dummy() {{ {}; }}", input.text); | 65 | let text = format!(r"fn dummy() {{ {}; }}", input.text); |
94 | let file = SourceFile::parse(&text); | 66 | let file = SourceFile::parse(&text); |
@@ -185,7 +157,7 @@ impl MacroExpansion { | |||
185 | } | 157 | } |
186 | 158 | ||
187 | pub(crate) fn expand_macro_invocation( | 159 | pub(crate) fn expand_macro_invocation( |
188 | db: &impl HirDatabase, | 160 | db: &impl PersistentHirDatabase, |
189 | invoc: MacroCallId, | 161 | invoc: MacroCallId, |
190 | ) -> Option<Arc<MacroExpansion>> { | 162 | ) -> Option<Arc<MacroExpansion>> { |
191 | let loc = invoc.loc(db); | 163 | let loc = invoc.loc(db); |
diff --git a/crates/ra_hir/src/mock.rs b/crates/ra_hir/src/mock.rs index 7da15eca0..17bdd48c6 100644 --- a/crates/ra_hir/src/mock.rs +++ b/crates/ra_hir/src/mock.rs | |||
@@ -11,7 +11,11 @@ use crate::{db, HirInterner}; | |||
11 | 11 | ||
12 | pub const WORKSPACE: SourceRootId = SourceRootId(0); | 12 | pub const WORKSPACE: SourceRootId = SourceRootId(0); |
13 | 13 | ||
14 | #[salsa::database(ra_db::SourceDatabaseStorage, db::HirDatabaseStorage)] | 14 | #[salsa::database( |
15 | ra_db::SourceDatabaseStorage, | ||
16 | db::HirDatabaseStorage, | ||
17 | db::PersistentHirDatabaseStorage | ||
18 | )] | ||
15 | #[derive(Debug)] | 19 | #[derive(Debug)] |
16 | pub(crate) struct MockDatabase { | 20 | pub(crate) struct MockDatabase { |
17 | events: Mutex<Option<Vec<salsa::Event<MockDatabase>>>>, | 21 | events: Mutex<Option<Vec<salsa::Event<MockDatabase>>>>, |
diff --git a/crates/ra_hir/src/module_tree.rs b/crates/ra_hir/src/module_tree.rs index 1f327eeb2..a1aa3d8ce 100644 --- a/crates/ra_hir/src/module_tree.rs +++ b/crates/ra_hir/src/module_tree.rs | |||
@@ -13,13 +13,14 @@ use test_utils::tested_by; | |||
13 | 13 | ||
14 | use crate::{ | 14 | use crate::{ |
15 | Name, AsName, HirDatabase, SourceItemId, HirFileId, Problem, SourceFileItems, ModuleSource, | 15 | Name, AsName, HirDatabase, SourceItemId, HirFileId, Problem, SourceFileItems, ModuleSource, |
16 | PersistentHirDatabase, | ||
16 | Crate, | 17 | Crate, |
17 | ids::SourceFileItemId, | 18 | ids::SourceFileItemId, |
18 | }; | 19 | }; |
19 | 20 | ||
20 | impl ModuleSource { | 21 | impl ModuleSource { |
21 | pub(crate) fn new( | 22 | pub(crate) fn new( |
22 | db: &impl HirDatabase, | 23 | db: &impl PersistentHirDatabase, |
23 | file_id: HirFileId, | 24 | file_id: HirFileId, |
24 | decl_id: Option<SourceFileItemId>, | 25 | decl_id: Option<SourceFileItemId>, |
25 | ) -> ModuleSource { | 26 | ) -> ModuleSource { |
@@ -47,7 +48,7 @@ pub struct Submodule { | |||
47 | 48 | ||
48 | impl Submodule { | 49 | impl Submodule { |
49 | pub(crate) fn submodules_query( | 50 | pub(crate) fn submodules_query( |
50 | db: &impl HirDatabase, | 51 | db: &impl PersistentHirDatabase, |
51 | file_id: HirFileId, | 52 | file_id: HirFileId, |
52 | decl_id: Option<SourceFileItemId>, | 53 | decl_id: Option<SourceFileItemId>, |
53 | ) -> Arc<Vec<Submodule>> { | 54 | ) -> Arc<Vec<Submodule>> { |
@@ -133,7 +134,10 @@ struct LinkData { | |||
133 | } | 134 | } |
134 | 135 | ||
135 | impl ModuleTree { | 136 | impl ModuleTree { |
136 | pub(crate) fn module_tree_query(db: &impl HirDatabase, krate: Crate) -> Arc<ModuleTree> { | 137 | pub(crate) fn module_tree_query( |
138 | db: &impl PersistentHirDatabase, | ||
139 | krate: Crate, | ||
140 | ) -> Arc<ModuleTree> { | ||
137 | db.check_canceled(); | 141 | db.check_canceled(); |
138 | let mut res = ModuleTree::default(); | 142 | let mut res = ModuleTree::default(); |
139 | res.init_crate(db, krate); | 143 | res.init_crate(db, krate); |
@@ -156,7 +160,7 @@ impl ModuleTree { | |||
156 | Some(res) | 160 | Some(res) |
157 | } | 161 | } |
158 | 162 | ||
159 | fn init_crate(&mut self, db: &impl HirDatabase, krate: Crate) { | 163 | fn init_crate(&mut self, db: &impl PersistentHirDatabase, krate: Crate) { |
160 | let crate_graph = db.crate_graph(); | 164 | let crate_graph = db.crate_graph(); |
161 | let file_id = crate_graph.crate_root(krate.crate_id); | 165 | let file_id = crate_graph.crate_root(krate.crate_id); |
162 | let source_root_id = db.file_source_root(file_id); | 166 | let source_root_id = db.file_source_root(file_id); |
@@ -167,7 +171,7 @@ impl ModuleTree { | |||
167 | 171 | ||
168 | fn init_subtree( | 172 | fn init_subtree( |
169 | &mut self, | 173 | &mut self, |
170 | db: &impl HirDatabase, | 174 | db: &impl PersistentHirDatabase, |
171 | source_root: &SourceRoot, | 175 | source_root: &SourceRoot, |
172 | parent: Option<LinkId>, | 176 | parent: Option<LinkId>, |
173 | file_id: HirFileId, | 177 | file_id: HirFileId, |
@@ -287,14 +291,18 @@ impl LinkId { | |||
287 | pub(crate) fn name(self, tree: &ModuleTree) -> &Name { | 291 | pub(crate) fn name(self, tree: &ModuleTree) -> &Name { |
288 | &tree.links[self].name | 292 | &tree.links[self].name |
289 | } | 293 | } |
290 | pub(crate) fn source(self, tree: &ModuleTree, db: &impl HirDatabase) -> TreeArc<ast::Module> { | 294 | pub(crate) fn source( |
295 | self, | ||
296 | tree: &ModuleTree, | ||
297 | db: &impl PersistentHirDatabase, | ||
298 | ) -> TreeArc<ast::Module> { | ||
291 | let syntax_node = db.file_item(tree.links[self].source); | 299 | let syntax_node = db.file_item(tree.links[self].source); |
292 | ast::Module::cast(&syntax_node).unwrap().to_owned() | 300 | ast::Module::cast(&syntax_node).unwrap().to_owned() |
293 | } | 301 | } |
294 | } | 302 | } |
295 | 303 | ||
296 | fn resolve_submodule( | 304 | fn resolve_submodule( |
297 | db: &impl HirDatabase, | 305 | db: &impl PersistentHirDatabase, |
298 | file_id: HirFileId, | 306 | file_id: HirFileId, |
299 | name: &Name, | 307 | name: &Name, |
300 | is_root: bool, | 308 | is_root: bool, |
diff --git a/crates/ra_hir/src/nameres.rs b/crates/ra_hir/src/nameres.rs index 4573a72ba..04cc693b3 100644 --- a/crates/ra_hir/src/nameres.rs +++ b/crates/ra_hir/src/nameres.rs | |||
@@ -24,14 +24,13 @@ use rustc_hash::{FxHashMap, FxHashSet}; | |||
24 | 24 | ||
25 | use crate::{ | 25 | use crate::{ |
26 | Module, ModuleDef, | 26 | Module, ModuleDef, |
27 | Path, PathKind, | 27 | Path, PathKind, PersistentHirDatabase, |
28 | HirDatabase, Crate, | 28 | Crate, Name, |
29 | Name, | ||
30 | module_tree::{ModuleId, ModuleTree}, | 29 | module_tree::{ModuleId, ModuleTree}, |
31 | nameres::lower::{ImportId, LoweredModule, ImportData}, | 30 | nameres::lower::{ImportId, LoweredModule, ImportData}, |
32 | }; | 31 | }; |
33 | 32 | ||
34 | /// `ItemMap` is the result of name resolution. It contains, for each | 33 | /// `ItemMap` is the result of module name resolution. It contains, for each |
35 | /// module, the set of visible items. | 34 | /// module, the set of visible items. |
36 | #[derive(Default, Debug, PartialEq, Eq)] | 35 | #[derive(Default, Debug, PartialEq, Eq)] |
37 | pub struct ItemMap { | 36 | pub struct ItemMap { |
@@ -47,7 +46,7 @@ impl std::ops::Index<ModuleId> for ItemMap { | |||
47 | 46 | ||
48 | #[derive(Debug, Default, PartialEq, Eq, Clone)] | 47 | #[derive(Debug, Default, PartialEq, Eq, Clone)] |
49 | pub struct ModuleScope { | 48 | pub struct ModuleScope { |
50 | items: FxHashMap<Name, Resolution>, | 49 | pub(crate) items: FxHashMap<Name, Resolution>, |
51 | } | 50 | } |
52 | 51 | ||
53 | impl ModuleScope { | 52 | impl ModuleScope { |
@@ -81,6 +80,15 @@ pub struct PerNs<T> { | |||
81 | pub values: Option<T>, | 80 | pub values: Option<T>, |
82 | } | 81 | } |
83 | 82 | ||
83 | impl<T> Default for PerNs<T> { | ||
84 | fn default() -> Self { | ||
85 | PerNs { | ||
86 | types: None, | ||
87 | values: None, | ||
88 | } | ||
89 | } | ||
90 | } | ||
91 | |||
84 | impl<T> PerNs<T> { | 92 | impl<T> PerNs<T> { |
85 | pub fn none() -> PerNs<T> { | 93 | pub fn none() -> PerNs<T> { |
86 | PerNs { | 94 | PerNs { |
@@ -114,6 +122,10 @@ impl<T> PerNs<T> { | |||
114 | self.types.is_none() && self.values.is_none() | 122 | self.types.is_none() && self.values.is_none() |
115 | } | 123 | } |
116 | 124 | ||
125 | pub fn is_both(&self) -> bool { | ||
126 | self.types.is_some() && self.values.is_some() | ||
127 | } | ||
128 | |||
117 | pub fn take(self, namespace: Namespace) -> Option<T> { | 129 | pub fn take(self, namespace: Namespace) -> Option<T> { |
118 | match namespace { | 130 | match namespace { |
119 | Namespace::Types => self.types, | 131 | Namespace::Types => self.types, |
@@ -140,6 +152,13 @@ impl<T> PerNs<T> { | |||
140 | } | 152 | } |
141 | } | 153 | } |
142 | 154 | ||
155 | pub fn combine(self, other: PerNs<T>) -> PerNs<T> { | ||
156 | PerNs { | ||
157 | types: self.types.or(other.types), | ||
158 | values: self.values.or(other.values), | ||
159 | } | ||
160 | } | ||
161 | |||
143 | pub fn and_then<U>(self, f: impl Fn(T) -> Option<U>) -> PerNs<U> { | 162 | pub fn and_then<U>(self, f: impl Fn(T) -> Option<U>) -> PerNs<U> { |
144 | PerNs { | 163 | PerNs { |
145 | types: self.types.and_then(&f), | 164 | types: self.types.and_then(&f), |
@@ -166,7 +185,7 @@ struct Resolver<'a, DB> { | |||
166 | 185 | ||
167 | impl<'a, DB> Resolver<'a, DB> | 186 | impl<'a, DB> Resolver<'a, DB> |
168 | where | 187 | where |
169 | DB: HirDatabase, | 188 | DB: PersistentHirDatabase, |
170 | { | 189 | { |
171 | fn new( | 190 | fn new( |
172 | db: &'a DB, | 191 | db: &'a DB, |
@@ -232,10 +251,14 @@ where | |||
232 | }; | 251 | }; |
233 | } | 252 | } |
234 | for (import_id, import_data) in input.imports.iter() { | 253 | for (import_id, import_data) in input.imports.iter() { |
235 | if let Some(segment) = import_data.path.segments.iter().last() { | 254 | if let Some(last_segment) = import_data.path.segments.iter().last() { |
236 | if !import_data.is_glob { | 255 | if !import_data.is_glob { |
256 | let name = import_data | ||
257 | .alias | ||
258 | .clone() | ||
259 | .unwrap_or_else(|| last_segment.name.clone()); | ||
237 | module_items.items.insert( | 260 | module_items.items.insert( |
238 | segment.name.clone(), | 261 | name, |
239 | Resolution { | 262 | Resolution { |
240 | def: PerNs::none(), | 263 | def: PerNs::none(), |
241 | import: Some(import_id), | 264 | import: Some(import_id), |
@@ -300,19 +323,18 @@ where | |||
300 | 323 | ||
301 | if reached_fixedpoint == ReachedFixedPoint::Yes { | 324 | if reached_fixedpoint == ReachedFixedPoint::Yes { |
302 | let last_segment = import.path.segments.last().unwrap(); | 325 | let last_segment = import.path.segments.last().unwrap(); |
326 | let name = import | ||
327 | .alias | ||
328 | .clone() | ||
329 | .unwrap_or_else(|| last_segment.name.clone()); | ||
330 | log::debug!("resolved import {:?} ({:?}) to {:?}", name, import, def,); | ||
303 | self.update(module_id, |items| { | 331 | self.update(module_id, |items| { |
304 | let res = Resolution { | 332 | let res = Resolution { |
305 | def, | 333 | def, |
306 | import: Some(import_id), | 334 | import: Some(import_id), |
307 | }; | 335 | }; |
308 | items.items.insert(last_segment.name.clone(), res); | 336 | items.items.insert(name, res); |
309 | }); | 337 | }); |
310 | log::debug!( | ||
311 | "resolved import {:?} ({:?}) cross-source root to {:?}", | ||
312 | last_segment.name, | ||
313 | import, | ||
314 | def, | ||
315 | ); | ||
316 | } | 338 | } |
317 | reached_fixedpoint | 339 | reached_fixedpoint |
318 | } | 340 | } |
@@ -330,7 +352,7 @@ enum ReachedFixedPoint { | |||
330 | } | 352 | } |
331 | 353 | ||
332 | impl ItemMap { | 354 | impl ItemMap { |
333 | pub(crate) fn item_map_query(db: &impl HirDatabase, krate: Crate) -> Arc<ItemMap> { | 355 | pub(crate) fn item_map_query(db: &impl PersistentHirDatabase, krate: Crate) -> Arc<ItemMap> { |
334 | let start = time::Instant::now(); | 356 | let start = time::Instant::now(); |
335 | let module_tree = db.module_tree(krate); | 357 | let module_tree = db.module_tree(krate); |
336 | let input = module_tree | 358 | let input = module_tree |
@@ -352,7 +374,7 @@ impl ItemMap { | |||
352 | 374 | ||
353 | pub(crate) fn resolve_path( | 375 | pub(crate) fn resolve_path( |
354 | &self, | 376 | &self, |
355 | db: &impl HirDatabase, | 377 | db: &impl PersistentHirDatabase, |
356 | original_module: Module, | 378 | original_module: Module, |
357 | path: &Path, | 379 | path: &Path, |
358 | ) -> PerNs<ModuleDef> { | 380 | ) -> PerNs<ModuleDef> { |
@@ -363,7 +385,7 @@ impl ItemMap { | |||
363 | // the result. | 385 | // the result. |
364 | fn resolve_path_fp( | 386 | fn resolve_path_fp( |
365 | &self, | 387 | &self, |
366 | db: &impl HirDatabase, | 388 | db: &impl PersistentHirDatabase, |
367 | original_module: Module, | 389 | original_module: Module, |
368 | path: &Path, | 390 | path: &Path, |
369 | ) -> (PerNs<ModuleDef>, ReachedFixedPoint) { | 391 | ) -> (PerNs<ModuleDef>, ReachedFixedPoint) { |
@@ -403,10 +425,11 @@ impl ItemMap { | |||
403 | if module.krate != original_module.krate { | 425 | if module.krate != original_module.krate { |
404 | let path = Path { | 426 | let path = Path { |
405 | segments: path.segments[i..].iter().cloned().collect(), | 427 | segments: path.segments[i..].iter().cloned().collect(), |
406 | kind: PathKind::Crate, | 428 | kind: PathKind::Self_, |
407 | }; | 429 | }; |
408 | log::debug!("resolving {:?} in other crate", path); | 430 | log::debug!("resolving {:?} in other crate", path); |
409 | let def = module.resolve_path(db, &path); | 431 | let item_map = db.item_map(module.krate); |
432 | let def = item_map.resolve_path(db, *module, &path); | ||
410 | return (def, ReachedFixedPoint::Yes); | 433 | return (def, ReachedFixedPoint::Yes); |
411 | } | 434 | } |
412 | 435 | ||
diff --git a/crates/ra_hir/src/nameres/lower.rs b/crates/ra_hir/src/nameres/lower.rs index 8df11a5f4..df87f520f 100644 --- a/crates/ra_hir/src/nameres/lower.rs +++ b/crates/ra_hir/src/nameres/lower.rs | |||
@@ -8,10 +8,10 @@ use ra_arena::{Arena, RawId, impl_arena_id, map::ArenaMap}; | |||
8 | use rustc_hash::FxHashMap; | 8 | use rustc_hash::FxHashMap; |
9 | 9 | ||
10 | use crate::{ | 10 | use crate::{ |
11 | SourceItemId, Path, ModuleSource, HirDatabase, Name, | 11 | SourceItemId, Path, ModuleSource, Name, |
12 | HirFileId, MacroCallLoc, AsName, PerNs, Function, | 12 | HirFileId, MacroCallLoc, AsName, PerNs, Function, |
13 | ModuleDef, Module, Struct, Enum, Const, Static, Trait, Type, | 13 | ModuleDef, Module, Struct, Enum, Const, Static, Trait, Type, |
14 | ids::LocationCtx, | 14 | ids::LocationCtx, PersistentHirDatabase, |
15 | }; | 15 | }; |
16 | 16 | ||
17 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | 17 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] |
@@ -21,6 +21,7 @@ impl_arena_id!(ImportId); | |||
21 | #[derive(Debug, PartialEq, Eq)] | 21 | #[derive(Debug, PartialEq, Eq)] |
22 | pub(super) struct ImportData { | 22 | pub(super) struct ImportData { |
23 | pub(super) path: Path, | 23 | pub(super) path: Path, |
24 | pub(super) alias: Option<Name>, | ||
24 | pub(super) is_glob: bool, | 25 | pub(super) is_glob: bool, |
25 | } | 26 | } |
26 | 27 | ||
@@ -58,21 +59,21 @@ impl ImportSourceMap { | |||
58 | 59 | ||
59 | impl LoweredModule { | 60 | impl LoweredModule { |
60 | pub(crate) fn lower_module_module_query( | 61 | pub(crate) fn lower_module_module_query( |
61 | db: &impl HirDatabase, | 62 | db: &impl PersistentHirDatabase, |
62 | module: Module, | 63 | module: Module, |
63 | ) -> Arc<LoweredModule> { | 64 | ) -> Arc<LoweredModule> { |
64 | db.lower_module(module).0 | 65 | db.lower_module(module).0 |
65 | } | 66 | } |
66 | 67 | ||
67 | pub(crate) fn lower_module_source_map_query( | 68 | pub(crate) fn lower_module_source_map_query( |
68 | db: &impl HirDatabase, | 69 | db: &impl PersistentHirDatabase, |
69 | module: Module, | 70 | module: Module, |
70 | ) -> Arc<ImportSourceMap> { | 71 | ) -> Arc<ImportSourceMap> { |
71 | db.lower_module(module).1 | 72 | db.lower_module(module).1 |
72 | } | 73 | } |
73 | 74 | ||
74 | pub(crate) fn lower_module_query( | 75 | pub(crate) fn lower_module_query( |
75 | db: &impl HirDatabase, | 76 | db: &impl PersistentHirDatabase, |
76 | module: Module, | 77 | module: Module, |
77 | ) -> (Arc<LoweredModule>, Arc<ImportSourceMap>) { | 78 | ) -> (Arc<LoweredModule>, Arc<ImportSourceMap>) { |
78 | let (file_id, source) = module.definition_source(db); | 79 | let (file_id, source) = module.definition_source(db); |
@@ -105,7 +106,7 @@ impl LoweredModule { | |||
105 | fn fill( | 106 | fn fill( |
106 | &mut self, | 107 | &mut self, |
107 | source_map: &mut ImportSourceMap, | 108 | source_map: &mut ImportSourceMap, |
108 | db: &impl HirDatabase, | 109 | db: &impl PersistentHirDatabase, |
109 | module: Module, | 110 | module: Module, |
110 | file_id: HirFileId, | 111 | file_id: HirFileId, |
111 | items: &mut Iterator<Item = ast::ItemOrMacro>, | 112 | items: &mut Iterator<Item = ast::ItemOrMacro>, |
@@ -137,7 +138,7 @@ impl LoweredModule { | |||
137 | fn add_def_id( | 138 | fn add_def_id( |
138 | &mut self, | 139 | &mut self, |
139 | source_map: &mut ImportSourceMap, | 140 | source_map: &mut ImportSourceMap, |
140 | db: &impl HirDatabase, | 141 | db: &impl PersistentHirDatabase, |
141 | module: Module, | 142 | module: Module, |
142 | file_id: HirFileId, | 143 | file_id: HirFileId, |
143 | item: &ast::ModuleItem, | 144 | item: &ast::ModuleItem, |
@@ -209,9 +210,10 @@ impl LoweredModule { | |||
209 | } | 210 | } |
210 | 211 | ||
211 | fn add_use_item(&mut self, source_map: &mut ImportSourceMap, item: &ast::UseItem) { | 212 | fn add_use_item(&mut self, source_map: &mut ImportSourceMap, item: &ast::UseItem) { |
212 | Path::expand_use_item(item, |path, segment| { | 213 | Path::expand_use_item(item, |path, segment, alias| { |
213 | let import = self.imports.alloc(ImportData { | 214 | let import = self.imports.alloc(ImportData { |
214 | path, | 215 | path, |
216 | alias, | ||
215 | is_glob: segment.is_none(), | 217 | is_glob: segment.is_none(), |
216 | }); | 218 | }); |
217 | if let Some(segment) = segment { | 219 | if let Some(segment) = segment { |
diff --git a/crates/ra_hir/src/nameres/tests.rs b/crates/ra_hir/src/nameres/tests.rs index 9c5ca097e..81c8a4f12 100644 --- a/crates/ra_hir/src/nameres/tests.rs +++ b/crates/ra_hir/src/nameres/tests.rs | |||
@@ -5,11 +5,12 @@ use relative_path::RelativePath; | |||
5 | use test_utils::{assert_eq_text, covers}; | 5 | use test_utils::{assert_eq_text, covers}; |
6 | 6 | ||
7 | use crate::{ | 7 | use crate::{ |
8 | ItemMap, Resolution, | 8 | ItemMap, |
9 | db::HirDatabase, | 9 | PersistentHirDatabase, |
10 | mock::MockDatabase, | 10 | mock::MockDatabase, |
11 | module_tree::ModuleId, | 11 | module_tree::ModuleId, |
12 | }; | 12 | }; |
13 | use super::Resolution; | ||
13 | 14 | ||
14 | fn item_map(fixture: &str) -> (Arc<ItemMap>, ModuleId) { | 15 | fn item_map(fixture: &str) -> (Arc<ItemMap>, ModuleId) { |
15 | let (db, pos) = MockDatabase::with_position(fixture); | 16 | let (db, pos) = MockDatabase::with_position(fixture); |
@@ -90,6 +91,30 @@ fn item_map_smoke_test() { | |||
90 | } | 91 | } |
91 | 92 | ||
92 | #[test] | 93 | #[test] |
94 | fn use_as() { | ||
95 | let (item_map, module_id) = item_map( | ||
96 | " | ||
97 | //- /lib.rs | ||
98 | mod foo; | ||
99 | |||
100 | use crate::foo::Baz as Foo; | ||
101 | <|> | ||
102 | |||
103 | //- /foo/mod.rs | ||
104 | pub struct Baz; | ||
105 | ", | ||
106 | ); | ||
107 | check_module_item_map( | ||
108 | &item_map, | ||
109 | module_id, | ||
110 | " | ||
111 | Foo: t v | ||
112 | foo: t | ||
113 | ", | ||
114 | ); | ||
115 | } | ||
116 | |||
117 | #[test] | ||
93 | fn use_trees() { | 118 | fn use_trees() { |
94 | let (item_map, module_id) = item_map( | 119 | let (item_map, module_id) = item_map( |
95 | " | 120 | " |
diff --git a/crates/ra_hir/src/path.rs b/crates/ra_hir/src/path.rs index e13d84c57..cb0a04500 100644 --- a/crates/ra_hir/src/path.rs +++ b/crates/ra_hir/src/path.rs | |||
@@ -1,6 +1,6 @@ | |||
1 | use std::sync::Arc; | 1 | use std::sync::Arc; |
2 | 2 | ||
3 | use ra_syntax::{ast, AstNode}; | 3 | use ra_syntax::{ast::{self, NameOwner}, AstNode}; |
4 | 4 | ||
5 | use crate::{Name, AsName, type_ref::TypeRef}; | 5 | use crate::{Name, AsName, type_ref::TypeRef}; |
6 | 6 | ||
@@ -46,7 +46,7 @@ impl Path { | |||
46 | /// Calls `cb` with all paths, represented by this use item. | 46 | /// Calls `cb` with all paths, represented by this use item. |
47 | pub fn expand_use_item<'a>( | 47 | pub fn expand_use_item<'a>( |
48 | item: &'a ast::UseItem, | 48 | item: &'a ast::UseItem, |
49 | mut cb: impl FnMut(Path, Option<&'a ast::PathSegment>), | 49 | mut cb: impl FnMut(Path, Option<&'a ast::PathSegment>, Option<Name>), |
50 | ) { | 50 | ) { |
51 | if let Some(tree) = item.use_tree() { | 51 | if let Some(tree) = item.use_tree() { |
52 | expand_use_tree(None, tree, &mut cb); | 52 | expand_use_tree(None, tree, &mut cb); |
@@ -164,7 +164,7 @@ impl From<Name> for Path { | |||
164 | fn expand_use_tree<'a>( | 164 | fn expand_use_tree<'a>( |
165 | prefix: Option<Path>, | 165 | prefix: Option<Path>, |
166 | tree: &'a ast::UseTree, | 166 | tree: &'a ast::UseTree, |
167 | cb: &mut impl FnMut(Path, Option<&'a ast::PathSegment>), | 167 | cb: &mut impl FnMut(Path, Option<&'a ast::PathSegment>, Option<Name>), |
168 | ) { | 168 | ) { |
169 | if let Some(use_tree_list) = tree.use_tree_list() { | 169 | if let Some(use_tree_list) = tree.use_tree_list() { |
170 | let prefix = match tree.path() { | 170 | let prefix = match tree.path() { |
@@ -181,6 +181,7 @@ fn expand_use_tree<'a>( | |||
181 | expand_use_tree(prefix.clone(), child_tree, cb); | 181 | expand_use_tree(prefix.clone(), child_tree, cb); |
182 | } | 182 | } |
183 | } else { | 183 | } else { |
184 | let alias = tree.alias().and_then(|a| a.name()).map(|a| a.as_name()); | ||
184 | if let Some(ast_path) = tree.path() { | 185 | if let Some(ast_path) = tree.path() { |
185 | // Handle self in a path. | 186 | // Handle self in a path. |
186 | // E.g. `use something::{self, <...>}` | 187 | // E.g. `use something::{self, <...>}` |
@@ -188,7 +189,7 @@ fn expand_use_tree<'a>( | |||
188 | if let Some(segment) = ast_path.segment() { | 189 | if let Some(segment) = ast_path.segment() { |
189 | if segment.kind() == Some(ast::PathSegmentKind::SelfKw) { | 190 | if segment.kind() == Some(ast::PathSegmentKind::SelfKw) { |
190 | if let Some(prefix) = prefix { | 191 | if let Some(prefix) = prefix { |
191 | cb(prefix, Some(segment)); | 192 | cb(prefix, Some(segment), alias); |
192 | return; | 193 | return; |
193 | } | 194 | } |
194 | } | 195 | } |
@@ -196,9 +197,9 @@ fn expand_use_tree<'a>( | |||
196 | } | 197 | } |
197 | if let Some(path) = convert_path(prefix, ast_path) { | 198 | if let Some(path) = convert_path(prefix, ast_path) { |
198 | if tree.has_star() { | 199 | if tree.has_star() { |
199 | cb(path, None) | 200 | cb(path, None, alias) |
200 | } else if let Some(segment) = ast_path.segment() { | 201 | } else if let Some(segment) = ast_path.segment() { |
201 | cb(path, Some(segment)) | 202 | cb(path, Some(segment), alias) |
202 | }; | 203 | }; |
203 | } | 204 | } |
204 | // TODO: report errors somewhere | 205 | // TODO: report errors somewhere |
diff --git a/crates/ra_hir/src/query_definitions.rs b/crates/ra_hir/src/query_definitions.rs index 734a98282..b4d8da1e6 100644 --- a/crates/ra_hir/src/query_definitions.rs +++ b/crates/ra_hir/src/query_definitions.rs | |||
@@ -6,17 +6,20 @@ use ra_syntax::{ | |||
6 | 6 | ||
7 | use crate::{ | 7 | use crate::{ |
8 | SourceFileItems, SourceItemId, HirFileId, | 8 | SourceFileItems, SourceItemId, HirFileId, |
9 | db::HirDatabase, | 9 | PersistentHirDatabase, |
10 | }; | 10 | }; |
11 | 11 | ||
12 | pub(super) fn file_items(db: &impl HirDatabase, file_id: HirFileId) -> Arc<SourceFileItems> { | 12 | pub(super) fn file_items( |
13 | db: &impl PersistentHirDatabase, | ||
14 | file_id: HirFileId, | ||
15 | ) -> Arc<SourceFileItems> { | ||
13 | let source_file = db.hir_parse(file_id); | 16 | let source_file = db.hir_parse(file_id); |
14 | let res = SourceFileItems::new(file_id, &source_file); | 17 | let res = SourceFileItems::new(file_id, &source_file); |
15 | Arc::new(res) | 18 | Arc::new(res) |
16 | } | 19 | } |
17 | 20 | ||
18 | pub(super) fn file_item( | 21 | pub(super) fn file_item( |
19 | db: &impl HirDatabase, | 22 | db: &impl PersistentHirDatabase, |
20 | source_item_id: SourceItemId, | 23 | source_item_id: SourceItemId, |
21 | ) -> TreeArc<SyntaxNode> { | 24 | ) -> TreeArc<SyntaxNode> { |
22 | let source_file = db.hir_parse(source_item_id.file_id); | 25 | let source_file = db.hir_parse(source_item_id.file_id); |
diff --git a/crates/ra_hir/src/resolve.rs b/crates/ra_hir/src/resolve.rs new file mode 100644 index 000000000..6c87d0df7 --- /dev/null +++ b/crates/ra_hir/src/resolve.rs | |||
@@ -0,0 +1,226 @@ | |||
1 | //! Name resolution. | ||
2 | use std::sync::Arc; | ||
3 | |||
4 | use rustc_hash::FxHashMap; | ||
5 | |||
6 | use crate::{ | ||
7 | ModuleDef, Module, | ||
8 | db::HirDatabase, | ||
9 | name::{Name, KnownName}, | ||
10 | nameres::{PerNs, ItemMap}, | ||
11 | generics::GenericParams, | ||
12 | expr::{scope::{ExprScopes, ScopeId}, PatId, Body}, | ||
13 | impl_block::ImplBlock, | ||
14 | path::Path, | ||
15 | }; | ||
16 | |||
17 | #[derive(Debug, Clone, Default)] | ||
18 | pub struct Resolver { | ||
19 | scopes: Vec<Scope>, | ||
20 | } | ||
21 | |||
22 | // TODO how to store these best | ||
23 | #[derive(Debug, Clone)] | ||
24 | pub(crate) struct ModuleItemMap { | ||
25 | item_map: Arc<ItemMap>, | ||
26 | module: Module, | ||
27 | } | ||
28 | |||
29 | #[derive(Debug, Clone)] | ||
30 | pub(crate) struct ExprScope { | ||
31 | expr_scopes: Arc<ExprScopes>, | ||
32 | scope_id: ScopeId, | ||
33 | } | ||
34 | |||
35 | #[derive(Debug, Clone)] | ||
36 | pub(crate) enum Scope { | ||
37 | /// All the items and imported names of a module | ||
38 | ModuleScope(ModuleItemMap), | ||
39 | /// Brings the generic parameters of an item into scope | ||
40 | GenericParams(Arc<GenericParams>), | ||
41 | /// Brings `Self` into scope | ||
42 | ImplBlockScope(ImplBlock), | ||
43 | /// Local bindings | ||
44 | ExprScope(ExprScope), | ||
45 | } | ||
46 | |||
47 | #[derive(Debug, Clone, PartialEq, Eq)] | ||
48 | pub enum Resolution { | ||
49 | /// An item | ||
50 | Def(ModuleDef), | ||
51 | /// A local binding (only value namespace) | ||
52 | LocalBinding(PatId), | ||
53 | /// A generic parameter | ||
54 | GenericParam(u32), | ||
55 | SelfType(ImplBlock), | ||
56 | } | ||
57 | |||
58 | impl Resolver { | ||
59 | pub fn resolve_name(&self, name: &Name) -> PerNs<Resolution> { | ||
60 | let mut resolution = PerNs::none(); | ||
61 | for scope in self.scopes.iter().rev() { | ||
62 | resolution = resolution.combine(scope.resolve_name(name)); | ||
63 | if resolution.is_both() { | ||
64 | return resolution; | ||
65 | } | ||
66 | } | ||
67 | resolution | ||
68 | } | ||
69 | |||
70 | pub fn resolve_path(&self, db: &impl HirDatabase, path: &Path) -> PerNs<Resolution> { | ||
71 | if let Some(name) = path.as_ident() { | ||
72 | self.resolve_name(name) | ||
73 | } else if path.is_self() { | ||
74 | self.resolve_name(&Name::self_param()) | ||
75 | } else { | ||
76 | let (item_map, module) = match self.module() { | ||
77 | Some(m) => m, | ||
78 | _ => return PerNs::none(), | ||
79 | }; | ||
80 | let module_res = item_map.resolve_path(db, module, path); | ||
81 | module_res.map(|def| Resolution::Def(def)) | ||
82 | } | ||
83 | } | ||
84 | |||
85 | pub fn all_names(&self) -> FxHashMap<Name, PerNs<Resolution>> { | ||
86 | let mut names = FxHashMap::default(); | ||
87 | for scope in self.scopes.iter().rev() { | ||
88 | scope.collect_names(&mut |name, res| { | ||
89 | let current: &mut PerNs<Resolution> = names.entry(name).or_default(); | ||
90 | if current.types.is_none() { | ||
91 | current.types = res.types; | ||
92 | } | ||
93 | if current.values.is_none() { | ||
94 | current.values = res.values; | ||
95 | } | ||
96 | }); | ||
97 | } | ||
98 | names | ||
99 | } | ||
100 | |||
101 | fn module(&self) -> Option<(&ItemMap, Module)> { | ||
102 | self.scopes.iter().rev().find_map(|scope| match scope { | ||
103 | Scope::ModuleScope(m) => Some((&*m.item_map, m.module.clone())), | ||
104 | |||
105 | _ => None, | ||
106 | }) | ||
107 | } | ||
108 | |||
109 | /// The body from which any `LocalBinding` resolutions in this resolver come. | ||
110 | pub fn body(&self) -> Option<Arc<Body>> { | ||
111 | self.scopes.iter().rev().find_map(|scope| match scope { | ||
112 | Scope::ExprScope(expr_scope) => Some(expr_scope.expr_scopes.body()), | ||
113 | _ => None, | ||
114 | }) | ||
115 | } | ||
116 | } | ||
117 | |||
118 | impl Resolver { | ||
119 | pub(crate) fn push_scope(mut self, scope: Scope) -> Resolver { | ||
120 | self.scopes.push(scope); | ||
121 | self | ||
122 | } | ||
123 | |||
124 | pub(crate) fn push_generic_params_scope(self, params: Arc<GenericParams>) -> Resolver { | ||
125 | self.push_scope(Scope::GenericParams(params)) | ||
126 | } | ||
127 | |||
128 | pub(crate) fn push_impl_block_scope(self, impl_block: ImplBlock) -> Resolver { | ||
129 | self.push_scope(Scope::ImplBlockScope(impl_block)) | ||
130 | } | ||
131 | |||
132 | pub(crate) fn push_module_scope(self, item_map: Arc<ItemMap>, module: Module) -> Resolver { | ||
133 | self.push_scope(Scope::ModuleScope(ModuleItemMap { item_map, module })) | ||
134 | } | ||
135 | |||
136 | pub(crate) fn push_expr_scope( | ||
137 | self, | ||
138 | expr_scopes: Arc<ExprScopes>, | ||
139 | scope_id: ScopeId, | ||
140 | ) -> Resolver { | ||
141 | self.push_scope(Scope::ExprScope(ExprScope { | ||
142 | expr_scopes, | ||
143 | scope_id, | ||
144 | })) | ||
145 | } | ||
146 | } | ||
147 | |||
148 | impl Scope { | ||
149 | fn resolve_name(&self, name: &Name) -> PerNs<Resolution> { | ||
150 | match self { | ||
151 | Scope::ModuleScope(m) => { | ||
152 | if let Some(KnownName::SelfParam) = name.as_known_name() { | ||
153 | PerNs::types(Resolution::Def(m.module.into())) | ||
154 | } else { | ||
155 | match m.item_map[m.module.module_id].get(name) { | ||
156 | Some(res) => res.def.map(Resolution::Def), | ||
157 | None => PerNs::none(), | ||
158 | } | ||
159 | } | ||
160 | } | ||
161 | Scope::GenericParams(gp) => match gp.find_by_name(name) { | ||
162 | Some(gp) => PerNs::types(Resolution::GenericParam(gp.idx)), | ||
163 | None => PerNs::none(), | ||
164 | }, | ||
165 | Scope::ImplBlockScope(i) => { | ||
166 | if name.as_known_name() == Some(KnownName::SelfType) { | ||
167 | PerNs::types(Resolution::SelfType(i.clone())) | ||
168 | } else { | ||
169 | PerNs::none() | ||
170 | } | ||
171 | } | ||
172 | Scope::ExprScope(e) => { | ||
173 | let entry = e | ||
174 | .expr_scopes | ||
175 | .entries(e.scope_id) | ||
176 | .iter() | ||
177 | .find(|entry| entry.name() == name); | ||
178 | match entry { | ||
179 | Some(e) => PerNs::values(Resolution::LocalBinding(e.pat())), | ||
180 | None => PerNs::none(), | ||
181 | } | ||
182 | } | ||
183 | } | ||
184 | } | ||
185 | |||
186 | fn collect_names(&self, f: &mut FnMut(Name, PerNs<Resolution>)) { | ||
187 | match self { | ||
188 | Scope::ModuleScope(m) => { | ||
189 | // TODO: should we provide `self` here? | ||
190 | // f( | ||
191 | // Name::self_param(), | ||
192 | // PerNs::types(Resolution::Def { | ||
193 | // def: m.module.into(), | ||
194 | // }), | ||
195 | // ); | ||
196 | m.item_map[m.module.module_id] | ||
197 | .entries() | ||
198 | .for_each(|(name, res)| { | ||
199 | f(name.clone(), res.def.map(Resolution::Def)); | ||
200 | }) | ||
201 | } | ||
202 | Scope::GenericParams(gp) => { | ||
203 | for param in &gp.params { | ||
204 | f( | ||
205 | param.name.clone(), | ||
206 | PerNs::types(Resolution::GenericParam(param.idx)), | ||
207 | ) | ||
208 | } | ||
209 | } | ||
210 | Scope::ImplBlockScope(i) => { | ||
211 | f( | ||
212 | Name::self_type(), | ||
213 | PerNs::types(Resolution::SelfType(i.clone())), | ||
214 | ); | ||
215 | } | ||
216 | Scope::ExprScope(e) => { | ||
217 | e.expr_scopes.entries(e.scope_id).iter().for_each(|e| { | ||
218 | f( | ||
219 | e.name().clone(), | ||
220 | PerNs::values(Resolution::LocalBinding(e.pat())), | ||
221 | ); | ||
222 | }); | ||
223 | } | ||
224 | } | ||
225 | } | ||
226 | } | ||
diff --git a/crates/ra_hir/src/source_binder.rs b/crates/ra_hir/src/source_binder.rs index d1eaccf23..59f782277 100644 --- a/crates/ra_hir/src/source_binder.rs +++ b/crates/ra_hir/src/source_binder.rs | |||
@@ -9,13 +9,14 @@ use ra_db::{FileId, FilePosition}; | |||
9 | use ra_syntax::{ | 9 | use ra_syntax::{ |
10 | SmolStr, TextRange, SyntaxNode, | 10 | SmolStr, TextRange, SyntaxNode, |
11 | ast::{self, AstNode, NameOwner}, | 11 | ast::{self, AstNode, NameOwner}, |
12 | algo::find_node_at_offset, | 12 | algo::{find_node_at_offset, find_leaf_at_offset}, |
13 | }; | 13 | }; |
14 | 14 | ||
15 | use crate::{ | 15 | use crate::{ |
16 | HirDatabase, Function, ModuleDef, Struct, Enum, | 16 | HirDatabase, Function, ModuleDef, Struct, Enum, |
17 | AsName, Module, HirFileId, Crate, | 17 | AsName, Module, HirFileId, Crate, Trait, Resolver, |
18 | ids::{LocationCtx, SourceFileItemId}, | 18 | ids::{LocationCtx, SourceFileItemId}, |
19 | expr | ||
19 | }; | 20 | }; |
20 | 21 | ||
21 | /// Locates the module by `FileId`. Picks topmost module in the file. | 22 | /// Locates the module by `FileId`. Picks topmost module in the file. |
@@ -151,6 +152,19 @@ pub fn enum_from_module(db: &impl HirDatabase, module: Module, enum_def: &ast::E | |||
151 | } | 152 | } |
152 | } | 153 | } |
153 | 154 | ||
155 | pub fn trait_from_module( | ||
156 | db: &impl HirDatabase, | ||
157 | module: Module, | ||
158 | trait_def: &ast::TraitDef, | ||
159 | ) -> Trait { | ||
160 | let (file_id, _) = module.definition_source(db); | ||
161 | let file_id = file_id.into(); | ||
162 | let ctx = LocationCtx::new(db, module, file_id); | ||
163 | Trait { | ||
164 | id: ctx.to_def(trait_def), | ||
165 | } | ||
166 | } | ||
167 | |||
154 | pub fn macro_symbols(db: &impl HirDatabase, file_id: FileId) -> Vec<(SmolStr, TextRange)> { | 168 | pub fn macro_symbols(db: &impl HirDatabase, file_id: FileId) -> Vec<(SmolStr, TextRange)> { |
155 | let module = match module_from_file_id(db, file_id) { | 169 | let module = match module_from_file_id(db, file_id) { |
156 | Some(it) => it, | 170 | Some(it) => it, |
@@ -188,3 +202,67 @@ pub fn macro_symbols(db: &impl HirDatabase, file_id: FileId) -> Vec<(SmolStr, Te | |||
188 | 202 | ||
189 | res | 203 | res |
190 | } | 204 | } |
205 | |||
206 | pub fn resolver_for_position(db: &impl HirDatabase, position: FilePosition) -> Resolver { | ||
207 | let file_id = position.file_id; | ||
208 | let file = db.parse(file_id); | ||
209 | find_leaf_at_offset(file.syntax(), position.offset) | ||
210 | .find_map(|node| { | ||
211 | node.ancestors().find_map(|node| { | ||
212 | if ast::Expr::cast(node).is_some() || ast::Block::cast(node).is_some() { | ||
213 | if let Some(func) = function_from_child_node(db, file_id, node) { | ||
214 | let scopes = func.scopes(db); | ||
215 | let scope = scopes.scope_for_offset(position.offset); | ||
216 | Some(expr::resolver_for_scope(func.body(db), db, scope)) | ||
217 | } else { | ||
218 | // TODO const/static/array length | ||
219 | None | ||
220 | } | ||
221 | } else if let Some(module) = ast::Module::cast(node) { | ||
222 | Some(module_from_declaration(db, file_id, module)?.resolver(db)) | ||
223 | } else if let Some(_) = ast::SourceFile::cast(node) { | ||
224 | Some(module_from_source(db, file_id.into(), None)?.resolver(db)) | ||
225 | } else if let Some(s) = ast::StructDef::cast(node) { | ||
226 | let module = module_from_child_node(db, file_id, s.syntax())?; | ||
227 | Some(struct_from_module(db, module, s).resolver(db)) | ||
228 | } else if let Some(e) = ast::EnumDef::cast(node) { | ||
229 | let module = module_from_child_node(db, file_id, e.syntax())?; | ||
230 | Some(enum_from_module(db, module, e).resolver(db)) | ||
231 | } else { | ||
232 | // TODO add missing cases | ||
233 | None | ||
234 | } | ||
235 | }) | ||
236 | }) | ||
237 | .unwrap_or_default() | ||
238 | } | ||
239 | |||
240 | pub fn resolver_for_node(db: &impl HirDatabase, file_id: FileId, node: &SyntaxNode) -> Resolver { | ||
241 | node.ancestors() | ||
242 | .find_map(|node| { | ||
243 | if ast::Expr::cast(node).is_some() || ast::Block::cast(node).is_some() { | ||
244 | if let Some(func) = function_from_child_node(db, file_id, node) { | ||
245 | let scopes = func.scopes(db); | ||
246 | let scope = scopes.scope_for(&node); | ||
247 | Some(expr::resolver_for_scope(func.body(db), db, scope)) | ||
248 | } else { | ||
249 | // TODO const/static/array length | ||
250 | None | ||
251 | } | ||
252 | } else if let Some(module) = ast::Module::cast(node) { | ||
253 | Some(module_from_declaration(db, file_id, module)?.resolver(db)) | ||
254 | } else if let Some(_) = ast::SourceFile::cast(node) { | ||
255 | Some(module_from_source(db, file_id.into(), None)?.resolver(db)) | ||
256 | } else if let Some(s) = ast::StructDef::cast(node) { | ||
257 | let module = module_from_child_node(db, file_id, s.syntax())?; | ||
258 | Some(struct_from_module(db, module, s).resolver(db)) | ||
259 | } else if let Some(e) = ast::EnumDef::cast(node) { | ||
260 | let module = module_from_child_node(db, file_id, e.syntax())?; | ||
261 | Some(enum_from_module(db, module, e).resolver(db)) | ||
262 | } else { | ||
263 | // TODO add missing cases | ||
264 | None | ||
265 | } | ||
266 | }) | ||
267 | .unwrap_or_default() | ||
268 | } | ||
diff --git a/crates/ra_hir/src/ty.rs b/crates/ra_hir/src/ty.rs index 60c231e82..cc5afad75 100644 --- a/crates/ra_hir/src/ty.rs +++ b/crates/ra_hir/src/ty.rs | |||
@@ -33,15 +33,16 @@ use rustc_hash::FxHashMap; | |||
33 | use test_utils::tested_by; | 33 | use test_utils::tested_by; |
34 | 34 | ||
35 | use crate::{ | 35 | use crate::{ |
36 | Module, Function, Struct, StructField, Enum, EnumVariant, Path, Name, ImplBlock, | 36 | Function, Struct, StructField, Enum, EnumVariant, Path, Name, |
37 | FnSignature, ExprScopes, ModuleDef, AdtDef, | 37 | FnSignature, ModuleDef, AdtDef, |
38 | db::HirDatabase, | 38 | HirDatabase, |
39 | type_ref::{TypeRef, Mutability}, | 39 | type_ref::{TypeRef, Mutability}, |
40 | name::KnownName, | 40 | name::KnownName, |
41 | expr::{Body, Expr, BindingAnnotation, Literal, ExprId, Pat, PatId, UnaryOp, BinaryOp, Statement, FieldPat}, | 41 | expr::{Body, Expr, BindingAnnotation, Literal, ExprId, Pat, PatId, UnaryOp, BinaryOp, Statement, FieldPat, self}, |
42 | generics::GenericParams, | 42 | generics::GenericParams, |
43 | path::GenericArg, | 43 | path::GenericArg, |
44 | adt::VariantDef, | 44 | adt::VariantDef, |
45 | resolve::{Resolver, Resolution}, | ||
45 | }; | 46 | }; |
46 | 47 | ||
47 | /// The ID of a type variable. | 48 | /// The ID of a type variable. |
@@ -300,47 +301,38 @@ pub struct FnSig { | |||
300 | } | 301 | } |
301 | 302 | ||
302 | impl Ty { | 303 | impl Ty { |
303 | pub(crate) fn from_hir( | 304 | pub(crate) fn from_hir(db: &impl HirDatabase, resolver: &Resolver, type_ref: &TypeRef) -> Self { |
304 | db: &impl HirDatabase, | ||
305 | // TODO: the next three parameters basically describe the scope for name | ||
306 | // resolution; this should be refactored into something like a general | ||
307 | // resolver architecture | ||
308 | module: &Module, | ||
309 | impl_block: Option<&ImplBlock>, | ||
310 | generics: &GenericParams, | ||
311 | type_ref: &TypeRef, | ||
312 | ) -> Self { | ||
313 | match type_ref { | 305 | match type_ref { |
314 | TypeRef::Never => Ty::Never, | 306 | TypeRef::Never => Ty::Never, |
315 | TypeRef::Tuple(inner) => { | 307 | TypeRef::Tuple(inner) => { |
316 | let inner_tys = inner | 308 | let inner_tys = inner |
317 | .iter() | 309 | .iter() |
318 | .map(|tr| Ty::from_hir(db, module, impl_block, generics, tr)) | 310 | .map(|tr| Ty::from_hir(db, resolver, tr)) |
319 | .collect::<Vec<_>>(); | 311 | .collect::<Vec<_>>(); |
320 | Ty::Tuple(inner_tys.into()) | 312 | Ty::Tuple(inner_tys.into()) |
321 | } | 313 | } |
322 | TypeRef::Path(path) => Ty::from_hir_path(db, module, impl_block, generics, path), | 314 | TypeRef::Path(path) => Ty::from_hir_path(db, resolver, path), |
323 | TypeRef::RawPtr(inner, mutability) => { | 315 | TypeRef::RawPtr(inner, mutability) => { |
324 | let inner_ty = Ty::from_hir(db, module, impl_block, generics, inner); | 316 | let inner_ty = Ty::from_hir(db, resolver, inner); |
325 | Ty::RawPtr(Arc::new(inner_ty), *mutability) | 317 | Ty::RawPtr(Arc::new(inner_ty), *mutability) |
326 | } | 318 | } |
327 | TypeRef::Array(inner) => { | 319 | TypeRef::Array(inner) => { |
328 | let inner_ty = Ty::from_hir(db, module, impl_block, generics, inner); | 320 | let inner_ty = Ty::from_hir(db, resolver, inner); |
329 | Ty::Array(Arc::new(inner_ty)) | 321 | Ty::Array(Arc::new(inner_ty)) |
330 | } | 322 | } |
331 | TypeRef::Slice(inner) => { | 323 | TypeRef::Slice(inner) => { |
332 | let inner_ty = Ty::from_hir(db, module, impl_block, generics, inner); | 324 | let inner_ty = Ty::from_hir(db, resolver, inner); |
333 | Ty::Slice(Arc::new(inner_ty)) | 325 | Ty::Slice(Arc::new(inner_ty)) |
334 | } | 326 | } |
335 | TypeRef::Reference(inner, mutability) => { | 327 | TypeRef::Reference(inner, mutability) => { |
336 | let inner_ty = Ty::from_hir(db, module, impl_block, generics, inner); | 328 | let inner_ty = Ty::from_hir(db, resolver, inner); |
337 | Ty::Ref(Arc::new(inner_ty), *mutability) | 329 | Ty::Ref(Arc::new(inner_ty), *mutability) |
338 | } | 330 | } |
339 | TypeRef::Placeholder => Ty::Unknown, | 331 | TypeRef::Placeholder => Ty::Unknown, |
340 | TypeRef::Fn(params) => { | 332 | TypeRef::Fn(params) => { |
341 | let mut inner_tys = params | 333 | let mut inner_tys = params |
342 | .iter() | 334 | .iter() |
343 | .map(|tr| Ty::from_hir(db, module, impl_block, generics, tr)) | 335 | .map(|tr| Ty::from_hir(db, resolver, tr)) |
344 | .collect::<Vec<_>>(); | 336 | .collect::<Vec<_>>(); |
345 | let return_ty = inner_tys | 337 | let return_ty = inner_tys |
346 | .pop() | 338 | .pop() |
@@ -355,40 +347,13 @@ impl Ty { | |||
355 | } | 347 | } |
356 | } | 348 | } |
357 | 349 | ||
358 | pub(crate) fn from_hir_opt( | 350 | pub(crate) fn from_hir_path(db: &impl HirDatabase, resolver: &Resolver, path: &Path) -> Self { |
359 | db: &impl HirDatabase, | ||
360 | module: &Module, | ||
361 | impl_block: Option<&ImplBlock>, | ||
362 | generics: &GenericParams, | ||
363 | type_ref: Option<&TypeRef>, | ||
364 | ) -> Self { | ||
365 | type_ref.map_or(Ty::Unknown, |t| { | ||
366 | Ty::from_hir(db, module, impl_block, generics, t) | ||
367 | }) | ||
368 | } | ||
369 | |||
370 | pub(crate) fn from_hir_path( | ||
371 | db: &impl HirDatabase, | ||
372 | module: &Module, | ||
373 | impl_block: Option<&ImplBlock>, | ||
374 | generics: &GenericParams, | ||
375 | path: &Path, | ||
376 | ) -> Self { | ||
377 | if let Some(name) = path.as_ident() { | 351 | if let Some(name) = path.as_ident() { |
352 | // TODO handle primitive type names in resolver as well? | ||
378 | if let Some(int_ty) = primitive::UncertainIntTy::from_name(name) { | 353 | if let Some(int_ty) = primitive::UncertainIntTy::from_name(name) { |
379 | return Ty::Int(int_ty); | 354 | return Ty::Int(int_ty); |
380 | } else if let Some(float_ty) = primitive::UncertainFloatTy::from_name(name) { | 355 | } else if let Some(float_ty) = primitive::UncertainFloatTy::from_name(name) { |
381 | return Ty::Float(float_ty); | 356 | return Ty::Float(float_ty); |
382 | } else if name.as_known_name() == Some(KnownName::SelfType) { | ||
383 | // TODO pass the impl block's generics? | ||
384 | let generics = &GenericParams::default(); | ||
385 | return Ty::from_hir_opt( | ||
386 | db, | ||
387 | module, | ||
388 | None, | ||
389 | generics, | ||
390 | impl_block.map(|i| i.target_type()), | ||
391 | ); | ||
392 | } else if let Some(known) = name.as_known_name() { | 357 | } else if let Some(known) = name.as_known_name() { |
393 | match known { | 358 | match known { |
394 | KnownName::Bool => return Ty::Bool, | 359 | KnownName::Bool => return Ty::Bool, |
@@ -396,25 +361,40 @@ impl Ty { | |||
396 | KnownName::Str => return Ty::Str, | 361 | KnownName::Str => return Ty::Str, |
397 | _ => {} | 362 | _ => {} |
398 | } | 363 | } |
399 | } else if let Some(generic_param) = generics.find_by_name(&name) { | 364 | } |
365 | } | ||
366 | |||
367 | // Resolve the path (in type namespace) | ||
368 | let resolution = resolver.resolve_path(db, path).take_types(); | ||
369 | |||
370 | let def = match resolution { | ||
371 | Some(Resolution::Def(def)) => def, | ||
372 | Some(Resolution::LocalBinding(..)) => { | ||
373 | // this should never happen | ||
374 | panic!("path resolved to local binding in type ns"); | ||
375 | } | ||
376 | Some(Resolution::GenericParam(idx)) => { | ||
400 | return Ty::Param { | 377 | return Ty::Param { |
401 | idx: generic_param.idx, | 378 | idx, |
402 | name: generic_param.name.clone(), | 379 | // TODO: maybe return name in resolution? |
380 | name: path | ||
381 | .as_ident() | ||
382 | .expect("generic param should be single-segment path") | ||
383 | .clone(), | ||
403 | }; | 384 | }; |
404 | } | 385 | } |
405 | } | 386 | Some(Resolution::SelfType(impl_block)) => { |
387 | return impl_block.target_ty(db); | ||
388 | } | ||
389 | None => return Ty::Unknown, | ||
390 | }; | ||
406 | 391 | ||
407 | // Resolve in module (in type namespace) | 392 | let typable: TypableDef = match def.into() { |
408 | let typable: TypableDef = match module | ||
409 | .resolve_path(db, path) | ||
410 | .take_types() | ||
411 | .and_then(|it| it.into()) | ||
412 | { | ||
413 | None => return Ty::Unknown, | 393 | None => return Ty::Unknown, |
414 | Some(it) => it, | 394 | Some(it) => it, |
415 | }; | 395 | }; |
416 | let ty = db.type_for_def(typable); | 396 | let ty = db.type_for_def(typable); |
417 | let substs = Ty::substs_from_path(db, module, impl_block, generics, path, typable); | 397 | let substs = Ty::substs_from_path(db, resolver, path, typable); |
418 | ty.apply_substs(substs) | 398 | ty.apply_substs(substs) |
419 | } | 399 | } |
420 | 400 | ||
@@ -422,10 +402,7 @@ impl Ty { | |||
422 | /// `create_substs_for_ast_path` and `def_to_ty` in rustc. | 402 | /// `create_substs_for_ast_path` and `def_to_ty` in rustc. |
423 | fn substs_from_path( | 403 | fn substs_from_path( |
424 | db: &impl HirDatabase, | 404 | db: &impl HirDatabase, |
425 | // the scope of the segment... | 405 | resolver: &Resolver, |
426 | module: &Module, | ||
427 | impl_block: Option<&ImplBlock>, | ||
428 | outer_generics: &GenericParams, | ||
429 | path: &Path, | 406 | path: &Path, |
430 | resolved: TypableDef, | 407 | resolved: TypableDef, |
431 | ) -> Substs { | 408 | ) -> Substs { |
@@ -462,7 +439,7 @@ impl Ty { | |||
462 | for arg in generic_args.args.iter().take(param_count) { | 439 | for arg in generic_args.args.iter().take(param_count) { |
463 | match arg { | 440 | match arg { |
464 | GenericArg::Type(type_ref) => { | 441 | GenericArg::Type(type_ref) => { |
465 | let ty = Ty::from_hir(db, module, impl_block, outer_generics, type_ref); | 442 | let ty = Ty::from_hir(db, resolver, type_ref); |
466 | substs.push(ty); | 443 | substs.push(ty); |
467 | } | 444 | } |
468 | } | 445 | } |
@@ -666,24 +643,17 @@ impl fmt::Display for Ty { | |||
666 | /// function body. | 643 | /// function body. |
667 | fn type_for_fn(db: &impl HirDatabase, def: Function) -> Ty { | 644 | fn type_for_fn(db: &impl HirDatabase, def: Function) -> Ty { |
668 | let signature = def.signature(db); | 645 | let signature = def.signature(db); |
669 | let module = def.module(db); | 646 | let resolver = def.resolver(db); |
670 | let impl_block = def.impl_block(db); | ||
671 | let generics = def.generic_params(db); | 647 | let generics = def.generic_params(db); |
648 | let name = def.name(db); | ||
672 | let input = signature | 649 | let input = signature |
673 | .params() | 650 | .params() |
674 | .iter() | 651 | .iter() |
675 | .map(|tr| Ty::from_hir(db, &module, impl_block.as_ref(), &generics, tr)) | 652 | .map(|tr| Ty::from_hir(db, &resolver, tr)) |
676 | .collect::<Vec<_>>(); | 653 | .collect::<Vec<_>>(); |
677 | let output = Ty::from_hir( | 654 | let output = Ty::from_hir(db, &resolver, signature.ret_type()); |
678 | db, | ||
679 | &module, | ||
680 | impl_block.as_ref(), | ||
681 | &generics, | ||
682 | signature.ret_type(), | ||
683 | ); | ||
684 | let sig = Arc::new(FnSig { input, output }); | 655 | let sig = Arc::new(FnSig { input, output }); |
685 | let substs = make_substs(&generics); | 656 | let substs = make_substs(&generics); |
686 | let name = def.name(db); | ||
687 | Ty::FnDef { | 657 | Ty::FnDef { |
688 | def, | 658 | def, |
689 | sig, | 659 | sig, |
@@ -764,13 +734,13 @@ pub(super) fn type_for_def(db: &impl HirDatabase, def: TypableDef) -> Ty { | |||
764 | 734 | ||
765 | pub(super) fn type_for_field(db: &impl HirDatabase, field: StructField) -> Ty { | 735 | pub(super) fn type_for_field(db: &impl HirDatabase, field: StructField) -> Ty { |
766 | let parent_def = field.parent_def(db); | 736 | let parent_def = field.parent_def(db); |
767 | let (generics, module) = match parent_def { | 737 | let resolver = match parent_def { |
768 | VariantDef::Struct(it) => (it.generic_params(db), it.module(db)), | 738 | VariantDef::Struct(it) => it.resolver(db), |
769 | VariantDef::EnumVariant(it) => (it.parent_enum(db).generic_params(db), it.module(db)), | 739 | VariantDef::EnumVariant(it) => it.parent_enum(db).resolver(db), |
770 | }; | 740 | }; |
771 | let var_data = parent_def.variant_data(db); | 741 | let var_data = parent_def.variant_data(db); |
772 | let type_ref = &var_data.fields().unwrap()[field.id].type_ref; | 742 | let type_ref = &var_data.fields().unwrap()[field.id].type_ref; |
773 | Ty::from_hir(db, &module, None, &generics, type_ref) | 743 | Ty::from_hir(db, &resolver, type_ref) |
774 | } | 744 | } |
775 | 745 | ||
776 | /// The result of type inference: A mapping from expressions and patterns to types. | 746 | /// The result of type inference: A mapping from expressions and patterns to types. |
@@ -814,9 +784,7 @@ impl Index<PatId> for InferenceResult { | |||
814 | struct InferenceContext<'a, D: HirDatabase> { | 784 | struct InferenceContext<'a, D: HirDatabase> { |
815 | db: &'a D, | 785 | db: &'a D, |
816 | body: Arc<Body>, | 786 | body: Arc<Body>, |
817 | scopes: Arc<ExprScopes>, | 787 | resolver: Resolver, |
818 | module: Module, | ||
819 | impl_block: Option<ImplBlock>, | ||
820 | var_unification_table: InPlaceUnificationTable<TypeVarId>, | 788 | var_unification_table: InPlaceUnificationTable<TypeVarId>, |
821 | method_resolutions: FxHashMap<ExprId, Function>, | 789 | method_resolutions: FxHashMap<ExprId, Function>, |
822 | field_resolutions: FxHashMap<ExprId, StructField>, | 790 | field_resolutions: FxHashMap<ExprId, StructField>, |
@@ -905,13 +873,7 @@ fn binary_op_rhs_expectation(op: BinaryOp, lhs_ty: Ty) -> Ty { | |||
905 | } | 873 | } |
906 | 874 | ||
907 | impl<'a, D: HirDatabase> InferenceContext<'a, D> { | 875 | impl<'a, D: HirDatabase> InferenceContext<'a, D> { |
908 | fn new( | 876 | fn new(db: &'a D, body: Arc<Body>, resolver: Resolver) -> Self { |
909 | db: &'a D, | ||
910 | body: Arc<Body>, | ||
911 | scopes: Arc<ExprScopes>, | ||
912 | module: Module, | ||
913 | impl_block: Option<ImplBlock>, | ||
914 | ) -> Self { | ||
915 | InferenceContext { | 877 | InferenceContext { |
916 | method_resolutions: FxHashMap::default(), | 878 | method_resolutions: FxHashMap::default(), |
917 | field_resolutions: FxHashMap::default(), | 879 | field_resolutions: FxHashMap::default(), |
@@ -921,9 +883,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
921 | return_ty: Ty::Unknown, // set in collect_fn_signature | 883 | return_ty: Ty::Unknown, // set in collect_fn_signature |
922 | db, | 884 | db, |
923 | body, | 885 | body, |
924 | scopes, | 886 | resolver, |
925 | module, | ||
926 | impl_block, | ||
927 | } | 887 | } |
928 | } | 888 | } |
929 | 889 | ||
@@ -940,8 +900,8 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
940 | *ty = resolved; | 900 | *ty = resolved; |
941 | } | 901 | } |
942 | InferenceResult { | 902 | InferenceResult { |
943 | method_resolutions: mem::replace(&mut self.method_resolutions, Default::default()), | 903 | method_resolutions: self.method_resolutions, |
944 | field_resolutions: mem::replace(&mut self.field_resolutions, Default::default()), | 904 | field_resolutions: self.field_resolutions, |
945 | type_of_expr: expr_types, | 905 | type_of_expr: expr_types, |
946 | type_of_pat: pat_types, | 906 | type_of_pat: pat_types, |
947 | } | 907 | } |
@@ -964,13 +924,10 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
964 | } | 924 | } |
965 | 925 | ||
966 | fn make_ty(&mut self, type_ref: &TypeRef) -> Ty { | 926 | fn make_ty(&mut self, type_ref: &TypeRef) -> Ty { |
967 | // TODO provide generics of function | ||
968 | let generics = GenericParams::default(); | ||
969 | let ty = Ty::from_hir( | 927 | let ty = Ty::from_hir( |
970 | self.db, | 928 | self.db, |
971 | &self.module, | 929 | // TODO use right resolver for block |
972 | self.impl_block.as_ref(), | 930 | &self.resolver, |
973 | &generics, | ||
974 | type_ref, | 931 | type_ref, |
975 | ); | 932 | ); |
976 | let ty = self.insert_type_vars(ty); | 933 | let ty = self.insert_type_vars(ty); |
@@ -1147,38 +1104,31 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
1147 | }) | 1104 | }) |
1148 | } | 1105 | } |
1149 | 1106 | ||
1150 | fn infer_path_expr(&mut self, expr: ExprId, path: &Path) -> Option<Ty> { | 1107 | fn infer_path_expr(&mut self, resolver: &Resolver, path: &Path) -> Option<Ty> { |
1151 | if path.is_ident() || path.is_self() { | 1108 | let resolved = resolver.resolve_path(self.db, &path).take_values()?; |
1152 | // resolve locally | 1109 | match resolved { |
1153 | let name = path.as_ident().cloned().unwrap_or_else(Name::self_param); | 1110 | Resolution::Def(def) => { |
1154 | if let Some(scope_entry) = self.scopes.resolve_local_name(expr, name) { | 1111 | let typable: Option<TypableDef> = def.into(); |
1155 | let ty = self.type_of_pat.get(scope_entry.pat())?; | 1112 | let typable = typable?; |
1113 | let substs = Ty::substs_from_path(self.db, &self.resolver, path, typable); | ||
1114 | let ty = self.db.type_for_def(typable).apply_substs(substs); | ||
1115 | let ty = self.insert_type_vars(ty); | ||
1116 | Some(ty) | ||
1117 | } | ||
1118 | Resolution::LocalBinding(pat) => { | ||
1119 | let ty = self.type_of_pat.get(pat)?; | ||
1156 | let ty = self.resolve_ty_as_possible(&mut vec![], ty.clone()); | 1120 | let ty = self.resolve_ty_as_possible(&mut vec![], ty.clone()); |
1157 | return Some(ty); | 1121 | Some(ty) |
1158 | }; | 1122 | } |
1159 | }; | 1123 | Resolution::GenericParam(..) => { |
1160 | 1124 | // generic params can't refer to values... yet | |
1161 | // resolve in module | 1125 | None |
1162 | let typable: Option<TypableDef> = self | 1126 | } |
1163 | .module | 1127 | Resolution::SelfType(_) => { |
1164 | .resolve_path(self.db, &path) | 1128 | log::error!("path expr {:?} resolved to Self type in values ns", path); |
1165 | .take_values()? | 1129 | None |
1166 | .into(); | 1130 | } |
1167 | let typable = typable?; | 1131 | } |
1168 | let ty = self.db.type_for_def(typable); | ||
1169 | let generics = GenericParams::default(); | ||
1170 | let substs = Ty::substs_from_path( | ||
1171 | self.db, | ||
1172 | &self.module, | ||
1173 | self.impl_block.as_ref(), | ||
1174 | &generics, | ||
1175 | path, | ||
1176 | typable, | ||
1177 | ); | ||
1178 | let ty = ty.apply_substs(substs); | ||
1179 | let ty = self.insert_type_vars(ty); | ||
1180 | |||
1181 | Some(ty) | ||
1182 | } | 1132 | } |
1183 | 1133 | ||
1184 | fn resolve_variant(&mut self, path: Option<&Path>) -> (Ty, Option<VariantDef>) { | 1134 | fn resolve_variant(&mut self, path: Option<&Path>) -> (Ty, Option<VariantDef>) { |
@@ -1186,26 +1136,30 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
1186 | Some(path) => path, | 1136 | Some(path) => path, |
1187 | None => return (Ty::Unknown, None), | 1137 | None => return (Ty::Unknown, None), |
1188 | }; | 1138 | }; |
1189 | let typable: Option<TypableDef> = self | 1139 | let resolver = &self.resolver; |
1190 | .module | 1140 | let typable: Option<TypableDef> = match resolver.resolve_path(self.db, &path).take_types() { |
1191 | .resolve_path(self.db, &path) | 1141 | Some(Resolution::Def(def)) => def.into(), |
1192 | .take_types() | 1142 | Some(Resolution::LocalBinding(..)) => { |
1193 | .and_then(|it| it.into()); | 1143 | // this cannot happen |
1144 | log::error!("path resolved to local binding in type ns"); | ||
1145 | return (Ty::Unknown, None); | ||
1146 | } | ||
1147 | Some(Resolution::GenericParam(..)) => { | ||
1148 | // generic params can't be used in struct literals | ||
1149 | return (Ty::Unknown, None); | ||
1150 | } | ||
1151 | Some(Resolution::SelfType(..)) => { | ||
1152 | // TODO this is allowed in an impl for a struct, handle this | ||
1153 | return (Ty::Unknown, None); | ||
1154 | } | ||
1155 | None => return (Ty::Unknown, None), | ||
1156 | }; | ||
1194 | let def = match typable { | 1157 | let def = match typable { |
1195 | None => return (Ty::Unknown, None), | 1158 | None => return (Ty::Unknown, None), |
1196 | Some(it) => it, | 1159 | Some(it) => it, |
1197 | }; | 1160 | }; |
1198 | // TODO remove the duplication between here and `Ty::from_path`? | 1161 | // TODO remove the duplication between here and `Ty::from_path`? |
1199 | // TODO provide generics of function | 1162 | let substs = Ty::substs_from_path(self.db, resolver, path, def); |
1200 | let generics = GenericParams::default(); | ||
1201 | let substs = Ty::substs_from_path( | ||
1202 | self.db, | ||
1203 | &self.module, | ||
1204 | self.impl_block.as_ref(), | ||
1205 | &generics, | ||
1206 | path, | ||
1207 | def, | ||
1208 | ); | ||
1209 | match def { | 1163 | match def { |
1210 | TypableDef::Struct(s) => { | 1164 | TypableDef::Struct(s) => { |
1211 | let ty = type_for_struct(self.db, s); | 1165 | let ty = type_for_struct(self.db, s); |
@@ -1303,12 +1257,12 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
1303 | path: ref p, | 1257 | path: ref p, |
1304 | args: ref fields, | 1258 | args: ref fields, |
1305 | } => self.infer_struct_pat(p.as_ref(), fields, expected), | 1259 | } => self.infer_struct_pat(p.as_ref(), fields, expected), |
1306 | Pat::Path(path) => self | 1260 | Pat::Path(path) => { |
1307 | .module | 1261 | // TODO use correct resolver for the surrounding expression |
1308 | .resolve_path(self.db, &path) | 1262 | let resolver = self.resolver.clone(); |
1309 | .take_values() | 1263 | self.infer_path_expr(&resolver, &path) |
1310 | .and_then(|module_def| module_def.into()) | 1264 | .unwrap_or(Ty::Unknown) |
1311 | .map_or(Ty::Unknown, |resolved| self.db.type_for_def(resolved)), | 1265 | } |
1312 | Pat::Bind { | 1266 | Pat::Bind { |
1313 | mode, | 1267 | mode, |
1314 | name: _name, | 1268 | name: _name, |
@@ -1496,7 +1450,11 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
1496 | 1450 | ||
1497 | expected.ty | 1451 | expected.ty |
1498 | } | 1452 | } |
1499 | Expr::Path(p) => self.infer_path_expr(tgt_expr, p).unwrap_or(Ty::Unknown), | 1453 | Expr::Path(p) => { |
1454 | // TODO this could be more efficient... | ||
1455 | let resolver = expr::resolver_for_expr(self.body.clone(), self.db, tgt_expr); | ||
1456 | self.infer_path_expr(&resolver, p).unwrap_or(Ty::Unknown) | ||
1457 | } | ||
1500 | Expr::Continue => Ty::Never, | 1458 | Expr::Continue => Ty::Never, |
1501 | Expr::Break { expr } => { | 1459 | Expr::Break { expr } => { |
1502 | if let Some(expr) = expr { | 1460 | if let Some(expr) = expr { |
@@ -1730,10 +1688,8 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
1730 | pub fn infer(db: &impl HirDatabase, func: Function) -> Arc<InferenceResult> { | 1688 | pub fn infer(db: &impl HirDatabase, func: Function) -> Arc<InferenceResult> { |
1731 | db.check_canceled(); | 1689 | db.check_canceled(); |
1732 | let body = func.body(db); | 1690 | let body = func.body(db); |
1733 | let scopes = db.expr_scopes(func); | 1691 | let resolver = func.resolver(db); |
1734 | let module = func.module(db); | 1692 | let mut ctx = InferenceContext::new(db, body, resolver); |
1735 | let impl_block = func.impl_block(db); | ||
1736 | let mut ctx = InferenceContext::new(db, body, scopes, module, impl_block); | ||
1737 | 1693 | ||
1738 | let signature = func.signature(db); | 1694 | let signature = func.signature(db); |
1739 | ctx.collect_fn_signature(&signature); | 1695 | ctx.collect_fn_signature(&signature); |
diff --git a/crates/ra_hir/src/ty/method_resolution.rs b/crates/ra_hir/src/ty/method_resolution.rs index 37bc3f38c..2282286b0 100644 --- a/crates/ra_hir/src/ty/method_resolution.rs +++ b/crates/ra_hir/src/ty/method_resolution.rs | |||
@@ -7,17 +7,16 @@ use std::sync::Arc; | |||
7 | use rustc_hash::FxHashMap; | 7 | use rustc_hash::FxHashMap; |
8 | 8 | ||
9 | use crate::{ | 9 | use crate::{ |
10 | HirDatabase, module_tree::ModuleId, Module, Crate, Name, Function, | 10 | HirDatabase, module_tree::ModuleId, Module, Crate, Name, Function, Trait, |
11 | ids::TraitId, | ||
11 | impl_block::{ImplId, ImplBlock, ImplItem}, | 12 | impl_block::{ImplId, ImplBlock, ImplItem}, |
12 | generics::GenericParams, | 13 | ty::{AdtDef, Ty}, |
13 | ty::{AdtDef, Ty} | ||
14 | }; | 14 | }; |
15 | 15 | ||
16 | /// This is used as a key for indexing impls. | 16 | /// This is used as a key for indexing impls. |
17 | #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] | 17 | #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] |
18 | pub enum TyFingerprint { | 18 | pub enum TyFingerprint { |
19 | Adt(AdtDef), | 19 | Adt(AdtDef), // we'll also want to index impls for primitive types etc. |
20 | // we'll also want to index impls for primitive types etc. | ||
21 | } | 20 | } |
22 | 21 | ||
23 | impl TyFingerprint { | 22 | impl TyFingerprint { |
@@ -37,6 +36,7 @@ pub struct CrateImplBlocks { | |||
37 | /// To make sense of the ModuleIds, we need the source root. | 36 | /// To make sense of the ModuleIds, we need the source root. |
38 | krate: Crate, | 37 | krate: Crate, |
39 | impls: FxHashMap<TyFingerprint, Vec<(ModuleId, ImplId)>>, | 38 | impls: FxHashMap<TyFingerprint, Vec<(ModuleId, ImplId)>>, |
39 | impls_by_trait: FxHashMap<TraitId, Vec<(ModuleId, ImplId)>>, | ||
40 | } | 40 | } |
41 | 41 | ||
42 | impl CrateImplBlocks { | 42 | impl CrateImplBlocks { |
@@ -60,30 +60,46 @@ impl CrateImplBlocks { | |||
60 | }) | 60 | }) |
61 | } | 61 | } |
62 | 62 | ||
63 | pub fn lookup_impl_blocks_for_trait<'a>( | ||
64 | &'a self, | ||
65 | db: &'a impl HirDatabase, | ||
66 | tr: &Trait, | ||
67 | ) -> impl Iterator<Item = (Module, ImplBlock)> + 'a { | ||
68 | let id = tr.id; | ||
69 | self.impls_by_trait | ||
70 | .get(&id) | ||
71 | .into_iter() | ||
72 | .flat_map(|i| i.iter()) | ||
73 | .map(move |(module_id, impl_id)| { | ||
74 | let module = Module { | ||
75 | krate: self.krate, | ||
76 | module_id: *module_id, | ||
77 | }; | ||
78 | let module_impl_blocks = db.impls_in_module(module); | ||
79 | (module, ImplBlock::from_id(module_impl_blocks, *impl_id)) | ||
80 | }) | ||
81 | } | ||
82 | |||
63 | fn collect_recursive(&mut self, db: &impl HirDatabase, module: &Module) { | 83 | fn collect_recursive(&mut self, db: &impl HirDatabase, module: &Module) { |
64 | let module_impl_blocks = db.impls_in_module(module.clone()); | 84 | let module_impl_blocks = db.impls_in_module(module.clone()); |
65 | 85 | ||
66 | for (impl_id, impl_data) in module_impl_blocks.impls.iter() { | 86 | for (impl_id, _) in module_impl_blocks.impls.iter() { |
67 | let impl_block = ImplBlock::from_id(Arc::clone(&module_impl_blocks), impl_id); | 87 | let impl_block = ImplBlock::from_id(Arc::clone(&module_impl_blocks), impl_id); |
68 | 88 | ||
69 | if let Some(_target_trait) = impl_data.target_trait() { | 89 | let target_ty = impl_block.target_ty(db); |
70 | // ignore for now | 90 | |
71 | } else { | 91 | if let Some(target_ty_fp) = TyFingerprint::for_impl(&target_ty) { |
72 | // TODO provide generics of impl | 92 | self.impls |
73 | let generics = GenericParams::default(); | 93 | .entry(target_ty_fp) |
74 | let target_ty = Ty::from_hir( | 94 | .or_insert_with(Vec::new) |
75 | db, | 95 | .push((module.module_id, impl_id)); |
76 | &module, | 96 | } |
77 | Some(&impl_block), | 97 | |
78 | &generics, | 98 | if let Some(tr) = impl_block.target_trait(db) { |
79 | impl_data.target_type(), | 99 | self.impls_by_trait |
80 | ); | 100 | .entry(tr.id) |
81 | if let Some(target_ty_fp) = TyFingerprint::for_impl(&target_ty) { | 101 | .or_insert_with(Vec::new) |
82 | self.impls | 102 | .push((module.module_id, impl_id)); |
83 | .entry(target_ty_fp) | ||
84 | .or_insert_with(Vec::new) | ||
85 | .push((module.module_id, impl_id)); | ||
86 | } | ||
87 | } | 103 | } |
88 | } | 104 | } |
89 | 105 | ||
@@ -99,6 +115,7 @@ impl CrateImplBlocks { | |||
99 | let mut crate_impl_blocks = CrateImplBlocks { | 115 | let mut crate_impl_blocks = CrateImplBlocks { |
100 | krate: krate.clone(), | 116 | krate: krate.clone(), |
101 | impls: FxHashMap::default(), | 117 | impls: FxHashMap::default(), |
118 | impls_by_trait: FxHashMap::default(), | ||
102 | }; | 119 | }; |
103 | if let Some(module) = krate.root_module(db) { | 120 | if let Some(module) = krate.root_module(db) { |
104 | crate_impl_blocks.collect_recursive(db, &module); | 121 | crate_impl_blocks.collect_recursive(db, &module); |
diff --git a/crates/ra_hir/src/ty/snapshots/tests__infer_function_generics.snap b/crates/ra_hir/src/ty/snapshots/tests__infer_function_generics.snap index 8ff6e55a6..91c48897c 100644 --- a/crates/ra_hir/src/ty/snapshots/tests__infer_function_generics.snap +++ b/crates/ra_hir/src/ty/snapshots/tests__infer_function_generics.snap | |||
@@ -1,12 +1,12 @@ | |||
1 | --- | 1 | --- |
2 | created: "2019-01-26T18:16:16.530712344+00:00" | 2 | created: "2019-01-27T14:52:29.934503829+00:00" |
3 | creator: [email protected] | 3 | creator: [email protected] |
4 | expression: "&result" | 4 | expression: "&result" |
5 | source: crates/ra_hir/src/ty/tests.rs | 5 | source: crates/ra_hir/src/ty/tests.rs |
6 | --- | 6 | --- |
7 | [10; 11) 't': [unknown] | 7 | [10; 11) 't': T |
8 | [21; 26) '{ t }': [unknown] | 8 | [21; 26) '{ t }': T |
9 | [23; 24) 't': [unknown] | 9 | [23; 24) 't': T |
10 | [38; 98) '{ ...(1); }': () | 10 | [38; 98) '{ ...(1); }': () |
11 | [44; 46) 'id': fn id<u32>(T) -> T | 11 | [44; 46) 'id': fn id<u32>(T) -> T |
12 | [44; 52) 'id(1u32)': u32 | 12 | [44; 52) 'id(1u32)': u32 |
diff --git a/crates/ra_hir/src/ty/snapshots/tests__infer_generic_chain.snap b/crates/ra_hir/src/ty/snapshots/tests__infer_generic_chain.snap index f21bffa75..626f31252 100644 --- a/crates/ra_hir/src/ty/snapshots/tests__infer_generic_chain.snap +++ b/crates/ra_hir/src/ty/snapshots/tests__infer_generic_chain.snap | |||
@@ -1,5 +1,5 @@ | |||
1 | --- | 1 | --- |
2 | created: "2019-01-26T17:46:03.866825843+00:00" | 2 | created: "2019-01-27T14:52:29.938713255+00:00" |
3 | creator: [email protected] | 3 | creator: [email protected] |
4 | expression: "&result" | 4 | expression: "&result" |
5 | source: crates/ra_hir/src/ty/tests.rs | 5 | source: crates/ra_hir/src/ty/tests.rs |
@@ -8,9 +8,9 @@ source: crates/ra_hir/src/ty/tests.rs | |||
8 | [65; 87) '{ ... }': [unknown] | 8 | [65; 87) '{ ... }': [unknown] |
9 | [75; 79) 'self': A<[unknown]> | 9 | [75; 79) 'self': A<[unknown]> |
10 | [75; 81) 'self.x': [unknown] | 10 | [75; 81) 'self.x': [unknown] |
11 | [99; 100) 't': [unknown] | 11 | [99; 100) 't': T |
12 | [110; 115) '{ t }': [unknown] | 12 | [110; 115) '{ t }': T |
13 | [112; 113) 't': [unknown] | 13 | [112; 113) 't': T |
14 | [135; 261) '{ ....x() }': i128 | 14 | [135; 261) '{ ....x() }': i128 |
15 | [146; 147) 'x': i32 | 15 | [146; 147) 'x': i32 |
16 | [150; 151) '1': i32 | 16 | [150; 151) '1': i32 |
diff --git a/crates/ra_hir/src/ty/snapshots/tests__infer_type_param.snap b/crates/ra_hir/src/ty/snapshots/tests__infer_type_param.snap index a99323264..216d1e41f 100644 --- a/crates/ra_hir/src/ty/snapshots/tests__infer_type_param.snap +++ b/crates/ra_hir/src/ty/snapshots/tests__infer_type_param.snap | |||
@@ -1,15 +1,15 @@ | |||
1 | --- | 1 | --- |
2 | created: "2019-01-27T16:54:18.368427685+00:00" | 2 | created: "2019-01-27T20:38:32.153717698+00:00" |
3 | creator: [email protected] | 3 | creator: [email protected] |
4 | expression: "&result" | 4 | expression: "&result" |
5 | source: crates/ra_hir/src/ty/tests.rs | 5 | source: crates/ra_hir/src/ty/tests.rs |
6 | --- | 6 | --- |
7 | [10; 11) 'x': [unknown] | 7 | [10; 11) 'x': T |
8 | [21; 30) '{ x }': [unknown] | 8 | [21; 30) '{ x }': T |
9 | [27; 28) 'x': [unknown] | 9 | [27; 28) 'x': T |
10 | [44; 45) 'x': &[unknown] | 10 | [44; 45) 'x': &T |
11 | [56; 65) '{ x }': &[unknown] | 11 | [56; 65) '{ x }': &T |
12 | [62; 63) 'x': &[unknown] | 12 | [62; 63) 'x': &T |
13 | [77; 157) '{ ...(1); }': () | 13 | [77; 157) '{ ...(1); }': () |
14 | [87; 88) 'y': u32 | 14 | [87; 88) 'y': u32 |
15 | [91; 96) '10u32': u32 | 15 | [91; 96) '10u32': u32 |
diff --git a/crates/ra_ide_api/src/completion/complete_path.rs b/crates/ra_ide_api/src/completion/complete_path.rs index b33ddcde5..0b9948d4b 100644 --- a/crates/ra_ide_api/src/completion/complete_path.rs +++ b/crates/ra_ide_api/src/completion/complete_path.rs | |||
@@ -1,21 +1,21 @@ | |||
1 | use join_to_string::join; | 1 | use join_to_string::join; |
2 | 2 | ||
3 | use hir::{Docs, Resolution}; | ||
4 | |||
3 | use crate::{ | 5 | use crate::{ |
4 | completion::{CompletionItem, CompletionItemKind, Completions, CompletionKind, CompletionContext}, | 6 | completion::{CompletionItem, CompletionItemKind, Completions, CompletionKind, CompletionContext}, |
5 | }; | 7 | }; |
6 | 8 | ||
7 | use hir::Docs; | ||
8 | |||
9 | pub(super) fn complete_path(acc: &mut Completions, ctx: &CompletionContext) { | 9 | pub(super) fn complete_path(acc: &mut Completions, ctx: &CompletionContext) { |
10 | let (path, module) = match (&ctx.path_prefix, &ctx.module) { | 10 | let path = match &ctx.path_prefix { |
11 | (Some(path), Some(module)) => (path.clone(), module), | 11 | Some(path) => path.clone(), |
12 | _ => return, | 12 | _ => return, |
13 | }; | 13 | }; |
14 | let def_id = match module.resolve_path(ctx.db, &path).take_types() { | 14 | let def = match ctx.resolver.resolve_path(ctx.db, &path).take_types() { |
15 | Some(it) => it, | 15 | Some(Resolution::Def(def)) => def, |
16 | None => return, | 16 | _ => return, |
17 | }; | 17 | }; |
18 | match def_id { | 18 | match def { |
19 | hir::ModuleDef::Module(module) => { | 19 | hir::ModuleDef::Module(module) => { |
20 | let module_scope = module.scope(ctx.db); | 20 | let module_scope = module.scope(ctx.db); |
21 | for (name, res) in module_scope.entries() { | 21 | for (name, res) in module_scope.entries() { |
@@ -24,7 +24,7 @@ pub(super) fn complete_path(acc: &mut Completions, ctx: &CompletionContext) { | |||
24 | ctx.source_range(), | 24 | ctx.source_range(), |
25 | name.to_string(), | 25 | name.to_string(), |
26 | ) | 26 | ) |
27 | .from_resolution(ctx, res) | 27 | .from_resolution(ctx, &res.def.map(hir::Resolution::Def)) |
28 | .add_to(acc); | 28 | .add_to(acc); |
29 | } | 29 | } |
30 | } | 30 | } |
@@ -66,6 +66,17 @@ mod tests { | |||
66 | } | 66 | } |
67 | 67 | ||
68 | #[test] | 68 | #[test] |
69 | #[ignore] // should not complete foo, which currently doesn't work | ||
70 | fn dont_complete_current_use() { | ||
71 | check_reference_completion( | ||
72 | "dont_complete_current_use", | ||
73 | r" | ||
74 | use self::foo<|>; | ||
75 | ", | ||
76 | ); | ||
77 | } | ||
78 | |||
79 | #[test] | ||
69 | fn completes_mod_with_docs() { | 80 | fn completes_mod_with_docs() { |
70 | check_reference_completion( | 81 | check_reference_completion( |
71 | "mod_with_docs", | 82 | "mod_with_docs", |
diff --git a/crates/ra_ide_api/src/completion/complete_scope.rs b/crates/ra_ide_api/src/completion/complete_scope.rs index f837bb1db..44514ab2b 100644 --- a/crates/ra_ide_api/src/completion/complete_scope.rs +++ b/crates/ra_ide_api/src/completion/complete_scope.rs | |||
@@ -1,63 +1,20 @@ | |||
1 | use rustc_hash::FxHashSet; | 1 | use crate::completion::{CompletionItem, Completions, CompletionKind, CompletionContext}; |
2 | use ra_syntax::ast::AstNode; | ||
3 | use crate::completion::{CompletionItem, CompletionItemKind, Completions, CompletionKind, CompletionContext}; | ||
4 | 2 | ||
5 | pub(super) fn complete_scope(acc: &mut Completions, ctx: &CompletionContext) { | 3 | pub(super) fn complete_scope(acc: &mut Completions, ctx: &CompletionContext) { |
6 | if !ctx.is_trivial_path { | 4 | if !ctx.is_trivial_path { |
7 | return; | 5 | return; |
8 | } | 6 | } |
9 | let module = match &ctx.module { | 7 | let names = ctx.resolver.all_names(); |
10 | Some(it) => it, | ||
11 | None => return, | ||
12 | }; | ||
13 | if let Some(function) = &ctx.function { | ||
14 | let scopes = function.scopes(ctx.db); | ||
15 | complete_fn(acc, &scopes, ctx); | ||
16 | } | ||
17 | |||
18 | let module_scope = module.scope(ctx.db); | ||
19 | module_scope | ||
20 | .entries() | ||
21 | .filter(|(_name, res)| { | ||
22 | // For cases like `use self::foo<|>` don't suggest foo itself. | ||
23 | match res.import { | ||
24 | None => true, | ||
25 | Some(import) => { | ||
26 | let source = module.import_source(ctx.db, import); | ||
27 | !source.syntax().range().is_subrange(&ctx.leaf.range()) | ||
28 | } | ||
29 | } | ||
30 | }) | ||
31 | .for_each(|(name, res)| { | ||
32 | CompletionItem::new( | ||
33 | CompletionKind::Reference, | ||
34 | ctx.source_range(), | ||
35 | name.to_string(), | ||
36 | ) | ||
37 | .from_resolution(ctx, res) | ||
38 | .add_to(acc) | ||
39 | }); | ||
40 | } | ||
41 | 8 | ||
42 | fn complete_fn( | 9 | names.into_iter().for_each(|(name, res)| { |
43 | acc: &mut Completions, | 10 | CompletionItem::new( |
44 | scopes: &hir::ScopesWithSyntaxMapping, | 11 | CompletionKind::Reference, |
45 | ctx: &CompletionContext, | 12 | ctx.source_range(), |
46 | ) { | 13 | name.to_string(), |
47 | let mut shadowed = FxHashSet::default(); | 14 | ) |
48 | scopes | 15 | .from_resolution(ctx, &res) |
49 | .scope_chain_for_offset(ctx.offset) | 16 | .add_to(acc) |
50 | .flat_map(|scope| scopes.scopes.entries(scope).iter()) | 17 | }); |
51 | .filter(|entry| shadowed.insert(entry.name())) | ||
52 | .for_each(|entry| { | ||
53 | CompletionItem::new( | ||
54 | CompletionKind::Reference, | ||
55 | ctx.source_range(), | ||
56 | entry.name().to_string(), | ||
57 | ) | ||
58 | .kind(CompletionItemKind::Binding) | ||
59 | .add_to(acc) | ||
60 | }); | ||
61 | } | 18 | } |
62 | 19 | ||
63 | #[cfg(test)] | 20 | #[cfg(test)] |
@@ -116,6 +73,30 @@ mod tests { | |||
116 | } | 73 | } |
117 | 74 | ||
118 | #[test] | 75 | #[test] |
76 | fn completes_generic_params() { | ||
77 | check_reference_completion( | ||
78 | "generic_params", | ||
79 | r" | ||
80 | fn quux<T>() { | ||
81 | <|> | ||
82 | } | ||
83 | ", | ||
84 | ); | ||
85 | } | ||
86 | |||
87 | #[test] | ||
88 | fn completes_generic_params_in_struct() { | ||
89 | check_reference_completion( | ||
90 | "generic_params_in_struct", | ||
91 | r" | ||
92 | struct X<T> { | ||
93 | x: <|> | ||
94 | } | ||
95 | ", | ||
96 | ); | ||
97 | } | ||
98 | |||
99 | #[test] | ||
119 | fn completes_module_items() { | 100 | fn completes_module_items() { |
120 | check_reference_completion( | 101 | check_reference_completion( |
121 | "module_items", | 102 | "module_items", |
@@ -174,5 +155,4 @@ mod tests { | |||
174 | fn completes_self_in_methods() { | 155 | fn completes_self_in_methods() { |
175 | check_reference_completion("self_in_methods", r"impl S { fn foo(&self) { <|> } }") | 156 | check_reference_completion("self_in_methods", r"impl S { fn foo(&self) { <|> } }") |
176 | } | 157 | } |
177 | |||
178 | } | 158 | } |
diff --git a/crates/ra_ide_api/src/completion/completion_context.rs b/crates/ra_ide_api/src/completion/completion_context.rs index 578af6e5b..5d1851da6 100644 --- a/crates/ra_ide_api/src/completion/completion_context.rs +++ b/crates/ra_ide_api/src/completion/completion_context.rs | |||
@@ -5,7 +5,7 @@ use ra_syntax::{ | |||
5 | algo::{find_leaf_at_offset, find_covering_node, find_node_at_offset}, | 5 | algo::{find_leaf_at_offset, find_covering_node, find_node_at_offset}, |
6 | SyntaxKind::*, | 6 | SyntaxKind::*, |
7 | }; | 7 | }; |
8 | use hir::source_binder; | 8 | use hir::{source_binder, Resolver}; |
9 | 9 | ||
10 | use crate::{db, FilePosition}; | 10 | use crate::{db, FilePosition}; |
11 | 11 | ||
@@ -16,6 +16,7 @@ pub(crate) struct CompletionContext<'a> { | |||
16 | pub(super) db: &'a db::RootDatabase, | 16 | pub(super) db: &'a db::RootDatabase, |
17 | pub(super) offset: TextUnit, | 17 | pub(super) offset: TextUnit, |
18 | pub(super) leaf: &'a SyntaxNode, | 18 | pub(super) leaf: &'a SyntaxNode, |
19 | pub(super) resolver: Resolver, | ||
19 | pub(super) module: Option<hir::Module>, | 20 | pub(super) module: Option<hir::Module>, |
20 | pub(super) function: Option<hir::Function>, | 21 | pub(super) function: Option<hir::Function>, |
21 | pub(super) function_syntax: Option<&'a ast::FnDef>, | 22 | pub(super) function_syntax: Option<&'a ast::FnDef>, |
@@ -42,12 +43,14 @@ impl<'a> CompletionContext<'a> { | |||
42 | original_file: &'a SourceFile, | 43 | original_file: &'a SourceFile, |
43 | position: FilePosition, | 44 | position: FilePosition, |
44 | ) -> Option<CompletionContext<'a>> { | 45 | ) -> Option<CompletionContext<'a>> { |
46 | let resolver = source_binder::resolver_for_position(db, position); | ||
45 | let module = source_binder::module_from_position(db, position); | 47 | let module = source_binder::module_from_position(db, position); |
46 | let leaf = find_leaf_at_offset(original_file.syntax(), position.offset).left_biased()?; | 48 | let leaf = find_leaf_at_offset(original_file.syntax(), position.offset).left_biased()?; |
47 | let mut ctx = CompletionContext { | 49 | let mut ctx = CompletionContext { |
48 | db, | 50 | db, |
49 | leaf, | 51 | leaf, |
50 | offset: position.offset, | 52 | offset: position.offset, |
53 | resolver, | ||
51 | module, | 54 | module, |
52 | function: None, | 55 | function: None, |
53 | function_syntax: None, | 56 | function_syntax: None, |
diff --git a/crates/ra_ide_api/src/completion/completion_item.rs b/crates/ra_ide_api/src/completion/completion_item.rs index d3bc14894..bada6a33b 100644 --- a/crates/ra_ide_api/src/completion/completion_item.rs +++ b/crates/ra_ide_api/src/completion/completion_item.rs | |||
@@ -1,5 +1,7 @@ | |||
1 | use hir::{Docs, Documentation}; | 1 | use hir::{Docs, Documentation, PerNs, Resolution}; |
2 | use ra_syntax::TextRange; | 2 | use ra_syntax::{ |
3 | TextRange, | ||
4 | }; | ||
3 | use ra_text_edit::TextEdit; | 5 | use ra_text_edit::TextEdit; |
4 | use test_utils::tested_by; | 6 | use test_utils::tested_by; |
5 | 7 | ||
@@ -48,6 +50,7 @@ pub enum CompletionItemKind { | |||
48 | Trait, | 50 | Trait, |
49 | TypeAlias, | 51 | TypeAlias, |
50 | Method, | 52 | Method, |
53 | TypeParam, | ||
51 | } | 54 | } |
52 | 55 | ||
53 | #[derive(Debug, PartialEq, Eq, Copy, Clone)] | 56 | #[derive(Debug, PartialEq, Eq, Copy, Clone)] |
@@ -207,23 +210,34 @@ impl Builder { | |||
207 | pub(super) fn from_resolution( | 210 | pub(super) fn from_resolution( |
208 | mut self, | 211 | mut self, |
209 | ctx: &CompletionContext, | 212 | ctx: &CompletionContext, |
210 | resolution: &hir::Resolution, | 213 | resolution: &PerNs<Resolution>, |
211 | ) -> Builder { | 214 | ) -> Builder { |
212 | let def = resolution.def.take_types().or(resolution.def.take_values()); | 215 | use hir::ModuleDef::*; |
216 | |||
217 | let def = resolution | ||
218 | .as_ref() | ||
219 | .take_types() | ||
220 | .or(resolution.as_ref().take_values()); | ||
213 | let def = match def { | 221 | let def = match def { |
214 | None => return self, | 222 | None => return self, |
215 | Some(it) => it, | 223 | Some(it) => it, |
216 | }; | 224 | }; |
217 | let (kind, docs) = match def { | 225 | let (kind, docs) = match def { |
218 | hir::ModuleDef::Module(it) => (CompletionItemKind::Module, it.docs(ctx.db)), | 226 | Resolution::Def(Module(it)) => (CompletionItemKind::Module, it.docs(ctx.db)), |
219 | hir::ModuleDef::Function(func) => return self.from_function(ctx, func), | 227 | Resolution::Def(Function(func)) => return self.from_function(ctx, *func), |
220 | hir::ModuleDef::Struct(it) => (CompletionItemKind::Struct, it.docs(ctx.db)), | 228 | Resolution::Def(Struct(it)) => (CompletionItemKind::Struct, it.docs(ctx.db)), |
221 | hir::ModuleDef::Enum(it) => (CompletionItemKind::Enum, it.docs(ctx.db)), | 229 | Resolution::Def(Enum(it)) => (CompletionItemKind::Enum, it.docs(ctx.db)), |
222 | hir::ModuleDef::EnumVariant(it) => (CompletionItemKind::EnumVariant, it.docs(ctx.db)), | 230 | Resolution::Def(EnumVariant(it)) => (CompletionItemKind::EnumVariant, it.docs(ctx.db)), |
223 | hir::ModuleDef::Const(it) => (CompletionItemKind::Const, it.docs(ctx.db)), | 231 | Resolution::Def(Const(it)) => (CompletionItemKind::Const, it.docs(ctx.db)), |
224 | hir::ModuleDef::Static(it) => (CompletionItemKind::Static, it.docs(ctx.db)), | 232 | Resolution::Def(Static(it)) => (CompletionItemKind::Static, it.docs(ctx.db)), |
225 | hir::ModuleDef::Trait(it) => (CompletionItemKind::Trait, it.docs(ctx.db)), | 233 | Resolution::Def(Trait(it)) => (CompletionItemKind::Trait, it.docs(ctx.db)), |
226 | hir::ModuleDef::Type(it) => (CompletionItemKind::TypeAlias, it.docs(ctx.db)), | 234 | Resolution::Def(Type(it)) => (CompletionItemKind::TypeAlias, it.docs(ctx.db)), |
235 | Resolution::GenericParam(..) => (CompletionItemKind::TypeParam, None), | ||
236 | Resolution::LocalBinding(..) => (CompletionItemKind::Binding, None), | ||
237 | Resolution::SelfType(..) => ( | ||
238 | CompletionItemKind::TypeParam, // (does this need its own kind?) | ||
239 | None, | ||
240 | ), | ||
227 | }; | 241 | }; |
228 | self.kind = Some(kind); | 242 | self.kind = Some(kind); |
229 | self.documentation = docs; | 243 | self.documentation = docs; |
diff --git a/crates/ra_ide_api/src/completion/snapshots/completion_item__generic_params.snap b/crates/ra_ide_api/src/completion/snapshots/completion_item__generic_params.snap new file mode 100644 index 000000000..71cb55a5b --- /dev/null +++ b/crates/ra_ide_api/src/completion/snapshots/completion_item__generic_params.snap | |||
@@ -0,0 +1,40 @@ | |||
1 | --- | ||
2 | created: "2019-02-01T22:20:40.580128393+00:00" | ||
3 | creator: [email protected] | ||
4 | expression: kind_completions | ||
5 | source: crates/ra_ide_api/src/completion/completion_item.rs | ||
6 | --- | ||
7 | [ | ||
8 | CompletionItem { | ||
9 | completion_kind: Reference, | ||
10 | label: "T", | ||
11 | kind: Some( | ||
12 | TypeParam | ||
13 | ), | ||
14 | detail: None, | ||
15 | documentation: None, | ||
16 | lookup: None, | ||
17 | insert_text: None, | ||
18 | insert_text_format: PlainText, | ||
19 | source_range: [44; 44), | ||
20 | text_edit: None | ||
21 | }, | ||
22 | CompletionItem { | ||
23 | completion_kind: Reference, | ||
24 | label: "quux", | ||
25 | kind: Some( | ||
26 | Function | ||
27 | ), | ||
28 | detail: Some( | ||
29 | "fn quux<T>()" | ||
30 | ), | ||
31 | documentation: None, | ||
32 | lookup: None, | ||
33 | insert_text: Some( | ||
34 | "quux()$0" | ||
35 | ), | ||
36 | insert_text_format: Snippet, | ||
37 | source_range: [44; 44), | ||
38 | text_edit: None | ||
39 | } | ||
40 | ] | ||
diff --git a/crates/ra_ide_api/src/completion/snapshots/completion_item__generic_params_in_struct.snap b/crates/ra_ide_api/src/completion/snapshots/completion_item__generic_params_in_struct.snap new file mode 100644 index 000000000..a35c0cd13 --- /dev/null +++ b/crates/ra_ide_api/src/completion/snapshots/completion_item__generic_params_in_struct.snap | |||
@@ -0,0 +1,36 @@ | |||
1 | --- | ||
2 | created: "2019-02-01T22:23:21.508620224+00:00" | ||
3 | creator: [email protected] | ||
4 | expression: kind_completions | ||
5 | source: crates/ra_ide_api/src/completion/completion_item.rs | ||
6 | --- | ||
7 | [ | ||
8 | CompletionItem { | ||
9 | completion_kind: Reference, | ||
10 | label: "T", | ||
11 | kind: Some( | ||
12 | TypeParam | ||
13 | ), | ||
14 | detail: None, | ||
15 | documentation: None, | ||
16 | lookup: None, | ||
17 | insert_text: None, | ||
18 | insert_text_format: PlainText, | ||
19 | source_range: [46; 46), | ||
20 | text_edit: None | ||
21 | }, | ||
22 | CompletionItem { | ||
23 | completion_kind: Reference, | ||
24 | label: "X", | ||
25 | kind: Some( | ||
26 | Struct | ||
27 | ), | ||
28 | detail: None, | ||
29 | documentation: None, | ||
30 | lookup: None, | ||
31 | insert_text: None, | ||
32 | insert_text_format: PlainText, | ||
33 | source_range: [46; 46), | ||
34 | text_edit: None | ||
35 | } | ||
36 | ] | ||
diff --git a/crates/ra_ide_api/src/completion/snapshots/completion_item__self_in_methods.snap b/crates/ra_ide_api/src/completion/snapshots/completion_item__self_in_methods.snap index 6a49e325c..ba1d4abbd 100644 --- a/crates/ra_ide_api/src/completion/snapshots/completion_item__self_in_methods.snap +++ b/crates/ra_ide_api/src/completion/snapshots/completion_item__self_in_methods.snap | |||
@@ -1,12 +1,26 @@ | |||
1 | --- | 1 | --- |
2 | created: "2019-01-23T05:27:32.422259+00:00" | 2 | created: "2019-01-27T20:17:10.051725945+00:00" |
3 | creator: insta@0.4.0 | 3 | creator: insta@0.5.2 |
4 | expression: kind_completions | 4 | expression: kind_completions |
5 | source: crates/ra_ide_api/src/completion/completion_item.rs | 5 | source: crates/ra_ide_api/src/completion/completion_item.rs |
6 | --- | 6 | --- |
7 | [ | 7 | [ |
8 | CompletionItem { | 8 | CompletionItem { |
9 | completion_kind: Reference, | 9 | completion_kind: Reference, |
10 | label: "Self", | ||
11 | kind: Some( | ||
12 | TypeParam | ||
13 | ), | ||
14 | detail: None, | ||
15 | documentation: None, | ||
16 | lookup: None, | ||
17 | insert_text: None, | ||
18 | insert_text_format: PlainText, | ||
19 | source_range: [25; 25), | ||
20 | text_edit: None | ||
21 | }, | ||
22 | CompletionItem { | ||
23 | completion_kind: Reference, | ||
10 | label: "self", | 24 | label: "self", |
11 | kind: Some( | 25 | kind: Some( |
12 | Binding | 26 | Binding |
diff --git a/crates/ra_ide_api/src/db.rs b/crates/ra_ide_api/src/db.rs index 6850811d7..3a9089c22 100644 --- a/crates/ra_ide_api/src/db.rs +++ b/crates/ra_ide_api/src/db.rs | |||
@@ -14,7 +14,8 @@ use crate::{LineIndex, symbol_index::{self, SymbolsDatabase}}; | |||
14 | ra_db::SourceDatabaseStorage, | 14 | ra_db::SourceDatabaseStorage, |
15 | LineIndexDatabaseStorage, | 15 | LineIndexDatabaseStorage, |
16 | symbol_index::SymbolsDatabaseStorage, | 16 | symbol_index::SymbolsDatabaseStorage, |
17 | hir::db::HirDatabaseStorage | 17 | hir::db::HirDatabaseStorage, |
18 | hir::db::PersistentHirDatabaseStorage | ||
18 | )] | 19 | )] |
19 | #[derive(Debug)] | 20 | #[derive(Debug)] |
20 | pub(crate) struct RootDatabase { | 21 | pub(crate) struct RootDatabase { |
diff --git a/crates/ra_ide_api/src/extend_selection.rs b/crates/ra_ide_api/src/extend_selection.rs index cd2ebe471..f61feaf1b 100644 --- a/crates/ra_ide_api/src/extend_selection.rs +++ b/crates/ra_ide_api/src/extend_selection.rs | |||
@@ -47,11 +47,11 @@ mod tests { | |||
47 | let (analysis, frange) = single_file_with_range( | 47 | let (analysis, frange) = single_file_with_range( |
48 | " | 48 | " |
49 | fn main() { | 49 | fn main() { |
50 | ctry!(foo(|x| <|>x<|>)); | 50 | vec![foo(|x| <|>x<|>)]; |
51 | } | 51 | } |
52 | ", | 52 | ", |
53 | ); | 53 | ); |
54 | let r = analysis.extend_selection(frange).unwrap(); | 54 | let r = analysis.extend_selection(frange).unwrap(); |
55 | assert_eq!(r, TextRange::from_to(51.into(), 56.into())); | 55 | assert_eq!(r, TextRange::from_to(50.into(), 55.into())); |
56 | } | 56 | } |
57 | } | 57 | } |
diff --git a/crates/ra_ide_api/src/goto_definition.rs b/crates/ra_ide_api/src/goto_definition.rs index 2a20c20ee..88efcea2a 100644 --- a/crates/ra_ide_api/src/goto_definition.rs +++ b/crates/ra_ide_api/src/goto_definition.rs | |||
@@ -4,6 +4,7 @@ use ra_syntax::{ | |||
4 | algo::find_node_at_offset, | 4 | algo::find_node_at_offset, |
5 | }; | 5 | }; |
6 | use test_utils::tested_by; | 6 | use test_utils::tested_by; |
7 | use hir::Resolution; | ||
7 | 8 | ||
8 | use crate::{FilePosition, NavigationTarget, db::RootDatabase, RangeInfo}; | 9 | use crate::{FilePosition, NavigationTarget, db::RootDatabase, RangeInfo}; |
9 | 10 | ||
@@ -48,14 +49,7 @@ pub(crate) fn reference_definition( | |||
48 | if let Some(function) = | 49 | if let Some(function) = |
49 | hir::source_binder::function_from_child_node(db, file_id, name_ref.syntax()) | 50 | hir::source_binder::function_from_child_node(db, file_id, name_ref.syntax()) |
50 | { | 51 | { |
51 | let scope = function.scopes(db); | 52 | // Check if it is a method |
52 | // First try to resolve the symbol locally | ||
53 | if let Some(entry) = scope.resolve_local_name(name_ref) { | ||
54 | let nav = NavigationTarget::from_scope_entry(file_id, &entry); | ||
55 | return Exact(nav); | ||
56 | }; | ||
57 | |||
58 | // Next check if it is a method | ||
59 | if let Some(method_call) = name_ref | 53 | if let Some(method_call) = name_ref |
60 | .syntax() | 54 | .syntax() |
61 | .parent() | 55 | .parent() |
@@ -86,19 +80,37 @@ pub(crate) fn reference_definition( | |||
86 | }; | 80 | }; |
87 | } | 81 | } |
88 | } | 82 | } |
89 | // Then try module name resolution | 83 | // Try name resolution |
90 | if let Some(module) = hir::source_binder::module_from_child_node(db, file_id, name_ref.syntax()) | 84 | let resolver = hir::source_binder::resolver_for_node(db, file_id, name_ref.syntax()); |
85 | if let Some(path) = name_ref | ||
86 | .syntax() | ||
87 | .ancestors() | ||
88 | .find_map(ast::Path::cast) | ||
89 | .and_then(hir::Path::from_ast) | ||
91 | { | 90 | { |
92 | if let Some(path) = name_ref | 91 | let resolved = resolver.resolve_path(db, &path); |
93 | .syntax() | 92 | match resolved.clone().take_types().or(resolved.take_values()) { |
94 | .ancestors() | 93 | Some(Resolution::Def(def)) => return Exact(NavigationTarget::from_def(db, def)), |
95 | .find_map(ast::Path::cast) | 94 | Some(Resolution::LocalBinding(pat)) => { |
96 | .and_then(hir::Path::from_ast) | 95 | let body = resolver.body().expect("no body for local binding"); |
97 | { | 96 | let syntax_mapping = body.syntax_mapping(db); |
98 | let resolved = module.resolve_path(db, &path); | 97 | let ptr = syntax_mapping |
99 | if let Some(def_id) = resolved.take_types().or(resolved.take_values()) { | 98 | .pat_syntax(pat) |
100 | return Exact(NavigationTarget::from_def(db, def_id)); | 99 | .expect("pattern not found in syntax mapping"); |
100 | let name = path | ||
101 | .as_ident() | ||
102 | .cloned() | ||
103 | .expect("local binding from a multi-segment path"); | ||
104 | let nav = NavigationTarget::from_scope_entry(file_id, name, ptr); | ||
105 | return Exact(nav); | ||
106 | } | ||
107 | Some(Resolution::GenericParam(..)) => { | ||
108 | // TODO go to the generic param def | ||
109 | } | ||
110 | Some(Resolution::SelfType(_impl_block)) => { | ||
111 | // TODO go to the implemented type | ||
101 | } | 112 | } |
113 | None => {} | ||
102 | } | 114 | } |
103 | } | 115 | } |
104 | // If that fails try the index based approach. | 116 | // If that fails try the index based approach. |
diff --git a/crates/ra_ide_api/src/impls.rs b/crates/ra_ide_api/src/impls.rs index 469d56d63..91fa41f1f 100644 --- a/crates/ra_ide_api/src/impls.rs +++ b/crates/ra_ide_api/src/impls.rs | |||
@@ -15,9 +15,27 @@ pub(crate) fn goto_implementation( | |||
15 | let syntax = file.syntax(); | 15 | let syntax = file.syntax(); |
16 | 16 | ||
17 | let module = source_binder::module_from_position(db, position)?; | 17 | let module = source_binder::module_from_position(db, position)?; |
18 | let krate = module.krate(db)?; | ||
19 | 18 | ||
20 | let node = find_node_at_offset::<ast::NominalDef>(syntax, position.offset)?; | 19 | if let Some(nominal_def) = find_node_at_offset::<ast::NominalDef>(syntax, position.offset) { |
20 | return Some(RangeInfo::new( | ||
21 | nominal_def.syntax().range(), | ||
22 | impls_for_def(db, nominal_def, module)?, | ||
23 | )); | ||
24 | } else if let Some(trait_def) = find_node_at_offset::<ast::TraitDef>(syntax, position.offset) { | ||
25 | return Some(RangeInfo::new( | ||
26 | trait_def.syntax().range(), | ||
27 | impls_for_trait(db, trait_def, module)?, | ||
28 | )); | ||
29 | } | ||
30 | |||
31 | None | ||
32 | } | ||
33 | |||
34 | fn impls_for_def( | ||
35 | db: &RootDatabase, | ||
36 | node: &ast::NominalDef, | ||
37 | module: hir::Module, | ||
38 | ) -> Option<Vec<NavigationTarget>> { | ||
21 | let ty = match node.kind() { | 39 | let ty = match node.kind() { |
22 | ast::NominalDefKind::StructDef(def) => { | 40 | ast::NominalDefKind::StructDef(def) => { |
23 | source_binder::struct_from_module(db, module, &def).ty(db) | 41 | source_binder::struct_from_module(db, module, &def).ty(db) |
@@ -27,13 +45,33 @@ pub(crate) fn goto_implementation( | |||
27 | } | 45 | } |
28 | }; | 46 | }; |
29 | 47 | ||
48 | let krate = module.krate(db)?; | ||
30 | let impls = db.impls_in_crate(krate); | 49 | let impls = db.impls_in_crate(krate); |
31 | 50 | ||
32 | let navs = impls | 51 | Some( |
33 | .lookup_impl_blocks(db, &ty) | 52 | impls |
34 | .map(|(module, imp)| NavigationTarget::from_impl_block(db, module, &imp)); | 53 | .lookup_impl_blocks(db, &ty) |
54 | .map(|(module, imp)| NavigationTarget::from_impl_block(db, module, &imp)) | ||
55 | .collect(), | ||
56 | ) | ||
57 | } | ||
58 | |||
59 | fn impls_for_trait( | ||
60 | db: &RootDatabase, | ||
61 | node: &ast::TraitDef, | ||
62 | module: hir::Module, | ||
63 | ) -> Option<Vec<NavigationTarget>> { | ||
64 | let tr = source_binder::trait_from_module(db, module, node); | ||
35 | 65 | ||
36 | Some(RangeInfo::new(node.syntax().range(), navs.collect())) | 66 | let krate = module.krate(db)?; |
67 | let impls = db.impls_in_crate(krate); | ||
68 | |||
69 | Some( | ||
70 | impls | ||
71 | .lookup_impl_blocks_for_trait(db, &tr) | ||
72 | .map(|(module, imp)| NavigationTarget::from_impl_block(db, module, &imp)) | ||
73 | .collect(), | ||
74 | ) | ||
37 | } | 75 | } |
38 | 76 | ||
39 | #[cfg(test)] | 77 | #[cfg(test)] |
@@ -117,4 +155,38 @@ mod tests { | |||
117 | ], | 155 | ], |
118 | ); | 156 | ); |
119 | } | 157 | } |
158 | |||
159 | #[test] | ||
160 | fn goto_implementation_for_trait() { | ||
161 | check_goto( | ||
162 | " | ||
163 | //- /lib.rs | ||
164 | trait T<|> {} | ||
165 | struct Foo; | ||
166 | impl T for Foo {} | ||
167 | ", | ||
168 | &["impl IMPL_BLOCK FileId(1) [23; 40)"], | ||
169 | ); | ||
170 | } | ||
171 | |||
172 | #[test] | ||
173 | fn goto_implementation_for_trait_multiple_files() { | ||
174 | check_goto( | ||
175 | " | ||
176 | //- /lib.rs | ||
177 | trait T<|> {}; | ||
178 | struct Foo; | ||
179 | mod a; | ||
180 | mod b; | ||
181 | //- /a.rs | ||
182 | impl crate::T for crate::Foo {} | ||
183 | //- /b.rs | ||
184 | impl crate::T for crate::Foo {} | ||
185 | ", | ||
186 | &[ | ||
187 | "impl IMPL_BLOCK FileId(2) [0; 31)", | ||
188 | "impl IMPL_BLOCK FileId(3) [0; 31)", | ||
189 | ], | ||
190 | ); | ||
191 | } | ||
120 | } | 192 | } |
diff --git a/crates/ra_ide_api/src/navigation_target.rs b/crates/ra_ide_api/src/navigation_target.rs index 5ccb5cc2e..617908aed 100644 --- a/crates/ra_ide_api/src/navigation_target.rs +++ b/crates/ra_ide_api/src/navigation_target.rs | |||
@@ -1,9 +1,9 @@ | |||
1 | use ra_db::FileId; | 1 | use ra_db::FileId; |
2 | use ra_syntax::{ | 2 | use ra_syntax::{ |
3 | SyntaxNode, AstNode, SmolStr, TextRange, ast, | 3 | SyntaxNode, SyntaxNodePtr, AstNode, SmolStr, TextRange, ast, |
4 | SyntaxKind::{self, NAME}, | 4 | SyntaxKind::{self, NAME}, |
5 | }; | 5 | }; |
6 | use hir::{ModuleSource, FieldSource}; | 6 | use hir::{ModuleSource, FieldSource, Name}; |
7 | 7 | ||
8 | use crate::{FileSymbol, db::RootDatabase}; | 8 | use crate::{FileSymbol, db::RootDatabase}; |
9 | 9 | ||
@@ -58,12 +58,13 @@ impl NavigationTarget { | |||
58 | 58 | ||
59 | pub(crate) fn from_scope_entry( | 59 | pub(crate) fn from_scope_entry( |
60 | file_id: FileId, | 60 | file_id: FileId, |
61 | entry: &hir::ScopeEntryWithSyntax, | 61 | name: Name, |
62 | ptr: SyntaxNodePtr, | ||
62 | ) -> NavigationTarget { | 63 | ) -> NavigationTarget { |
63 | NavigationTarget { | 64 | NavigationTarget { |
64 | file_id, | 65 | file_id, |
65 | name: entry.name().to_string().into(), | 66 | name: name.to_string().into(), |
66 | full_range: entry.ptr().range(), | 67 | full_range: ptr.range(), |
67 | focus_range: None, | 68 | focus_range: None, |
68 | kind: NAME, | 69 | kind: NAME, |
69 | } | 70 | } |
diff --git a/crates/ra_ide_api/src/snapshots/tests__highlight_query_group_macro.snap b/crates/ra_ide_api/src/snapshots/tests__highlight_query_group_macro.snap index 062add083..0b802ac3d 100644 --- a/crates/ra_ide_api/src/snapshots/tests__highlight_query_group_macro.snap +++ b/crates/ra_ide_api/src/snapshots/tests__highlight_query_group_macro.snap | |||
@@ -1,8 +1,8 @@ | |||
1 | --- | 1 | --- |
2 | created: "2019-01-22T14:45:01.017117100+00:00" | 2 | created: "2019-02-01T07:52:15.689836752+00:00" |
3 | creator: insta@0.4.0 | 3 | creator: insta@0.5.3 |
4 | expression: "&highlights" | 4 | expression: "&highlights" |
5 | source: "crates\\ra_ide_api\\src\\syntax_highlighting.rs" | 5 | source: crates/ra_ide_api/src/syntax_highlighting.rs |
6 | --- | 6 | --- |
7 | [ | 7 | [ |
8 | HighlightedRange { | 8 | HighlightedRange { |
diff --git a/crates/ra_ide_api/src/snapshots/tests__highlights_code_inside_macros.snap b/crates/ra_ide_api/src/snapshots/tests__highlights_code_inside_macros.snap index fd8265abb..ae8923e75 100644 --- a/crates/ra_ide_api/src/snapshots/tests__highlights_code_inside_macros.snap +++ b/crates/ra_ide_api/src/snapshots/tests__highlights_code_inside_macros.snap | |||
@@ -1,8 +1,8 @@ | |||
1 | --- | 1 | --- |
2 | created: "2019-01-22T14:45:01.043047100+00:00" | 2 | created: "2019-02-01T07:46:59.130146403+00:00" |
3 | creator: insta@0.4.0 | 3 | creator: insta@0.5.3 |
4 | expression: "&highlights" | 4 | expression: "&highlights" |
5 | source: "crates\\ra_ide_api\\src\\syntax_highlighting.rs" | 5 | source: crates/ra_ide_api/src/syntax_highlighting.rs |
6 | --- | 6 | --- |
7 | [ | 7 | [ |
8 | HighlightedRange { | 8 | HighlightedRange { |
@@ -14,59 +14,31 @@ source: "crates\\ra_ide_api\\src\\syntax_highlighting.rs" | |||
14 | tag: "function" | 14 | tag: "function" |
15 | }, | 15 | }, |
16 | HighlightedRange { | 16 | HighlightedRange { |
17 | range: [41; 46), | 17 | range: [41; 45), |
18 | tag: "macro" | 18 | tag: "macro" |
19 | }, | 19 | }, |
20 | HighlightedRange { | 20 | HighlightedRange { |
21 | range: [49; 52), | 21 | range: [48; 51), |
22 | tag: "keyword" | 22 | tag: "keyword" |
23 | }, | 23 | }, |
24 | HighlightedRange { | 24 | HighlightedRange { |
25 | range: [57; 59), | 25 | range: [56; 58), |
26 | tag: "literal" | 26 | tag: "literal" |
27 | }, | 27 | }, |
28 | HighlightedRange { | 28 | HighlightedRange { |
29 | range: [82; 86), | 29 | range: [48; 51), |
30 | tag: "macro" | ||
31 | }, | ||
32 | HighlightedRange { | ||
33 | range: [89; 92), | ||
34 | tag: "keyword" | ||
35 | }, | ||
36 | HighlightedRange { | ||
37 | range: [97; 99), | ||
38 | tag: "literal" | ||
39 | }, | ||
40 | HighlightedRange { | ||
41 | range: [49; 52), | ||
42 | tag: "keyword" | ||
43 | }, | ||
44 | HighlightedRange { | ||
45 | range: [53; 54), | ||
46 | tag: "function" | ||
47 | }, | ||
48 | HighlightedRange { | ||
49 | range: [57; 59), | ||
50 | tag: "literal" | ||
51 | }, | ||
52 | HighlightedRange { | ||
53 | range: [61; 62), | ||
54 | tag: "text" | ||
55 | }, | ||
56 | HighlightedRange { | ||
57 | range: [89; 92), | ||
58 | tag: "keyword" | 30 | tag: "keyword" |
59 | }, | 31 | }, |
60 | HighlightedRange { | 32 | HighlightedRange { |
61 | range: [93; 94), | 33 | range: [52; 53), |
62 | tag: "function" | 34 | tag: "function" |
63 | }, | 35 | }, |
64 | HighlightedRange { | 36 | HighlightedRange { |
65 | range: [97; 99), | 37 | range: [56; 58), |
66 | tag: "literal" | 38 | tag: "literal" |
67 | }, | 39 | }, |
68 | HighlightedRange { | 40 | HighlightedRange { |
69 | range: [101; 102), | 41 | range: [60; 61), |
70 | tag: "text" | 42 | tag: "text" |
71 | } | 43 | } |
72 | ] | 44 | ] |
diff --git a/crates/ra_ide_api/src/syntax_highlighting.rs b/crates/ra_ide_api/src/syntax_highlighting.rs index 26bde495b..6c4391e1e 100644 --- a/crates/ra_ide_api/src/syntax_highlighting.rs +++ b/crates/ra_ide_api/src/syntax_highlighting.rs | |||
@@ -42,7 +42,6 @@ mod tests { | |||
42 | let (analysis, file_id) = single_file( | 42 | let (analysis, file_id) = single_file( |
43 | " | 43 | " |
44 | fn main() { | 44 | fn main() { |
45 | ctry!({ let x = 92; x}); | ||
46 | vec![{ let x = 92; x}]; | 45 | vec![{ let x = 92; x}]; |
47 | } | 46 | } |
48 | ", | 47 | ", |
diff --git a/crates/ra_lsp_server/src/conv.rs b/crates/ra_lsp_server/src/conv.rs index c033ecdea..17fa07340 100644 --- a/crates/ra_lsp_server/src/conv.rs +++ b/crates/ra_lsp_server/src/conv.rs | |||
@@ -70,6 +70,7 @@ impl Conv for CompletionItemKind { | |||
70 | CompletionItemKind::Const => Constant, | 70 | CompletionItemKind::Const => Constant, |
71 | CompletionItemKind::Static => Value, | 71 | CompletionItemKind::Static => Value, |
72 | CompletionItemKind::Method => Method, | 72 | CompletionItemKind::Method => Method, |
73 | CompletionItemKind::TypeParam => TypeParameter, | ||
73 | } | 74 | } |
74 | } | 75 | } |
75 | } | 76 | } |
diff --git a/crates/ra_syntax/src/ast/generated.rs b/crates/ra_syntax/src/ast/generated.rs index d0561c495..60480c699 100644 --- a/crates/ra_syntax/src/ast/generated.rs +++ b/crates/ra_syntax/src/ast/generated.rs | |||
@@ -17,6 +17,35 @@ use crate::{ | |||
17 | ast::{self, AstNode}, | 17 | ast::{self, AstNode}, |
18 | }; | 18 | }; |
19 | 19 | ||
20 | // Alias | ||
21 | #[derive(Debug, PartialEq, Eq, Hash)] | ||
22 | #[repr(transparent)] | ||
23 | pub struct Alias { | ||
24 | pub(crate) syntax: SyntaxNode, | ||
25 | } | ||
26 | unsafe impl TransparentNewType for Alias { | ||
27 | type Repr = rowan::SyntaxNode<RaTypes>; | ||
28 | } | ||
29 | |||
30 | impl AstNode for Alias { | ||
31 | fn cast(syntax: &SyntaxNode) -> Option<&Self> { | ||
32 | match syntax.kind() { | ||
33 | ALIAS => Some(Alias::from_repr(syntax.into_repr())), | ||
34 | _ => None, | ||
35 | } | ||
36 | } | ||
37 | fn syntax(&self) -> &SyntaxNode { &self.syntax } | ||
38 | } | ||
39 | |||
40 | impl ToOwned for Alias { | ||
41 | type Owned = TreeArc<Alias>; | ||
42 | fn to_owned(&self) -> TreeArc<Alias> { TreeArc::cast(self.syntax.to_owned()) } | ||
43 | } | ||
44 | |||
45 | |||
46 | impl ast::NameOwner for Alias {} | ||
47 | impl Alias {} | ||
48 | |||
20 | // ArgList | 49 | // ArgList |
21 | #[derive(Debug, PartialEq, Eq, Hash)] | 50 | #[derive(Debug, PartialEq, Eq, Hash)] |
22 | #[repr(transparent)] | 51 | #[repr(transparent)] |
@@ -4176,6 +4205,10 @@ impl UseTree { | |||
4176 | pub fn use_tree_list(&self) -> Option<&UseTreeList> { | 4205 | pub fn use_tree_list(&self) -> Option<&UseTreeList> { |
4177 | super::child_opt(self) | 4206 | super::child_opt(self) |
4178 | } | 4207 | } |
4208 | |||
4209 | pub fn alias(&self) -> Option<&Alias> { | ||
4210 | super::child_opt(self) | ||
4211 | } | ||
4179 | } | 4212 | } |
4180 | 4213 | ||
4181 | // UseTreeList | 4214 | // UseTreeList |
diff --git a/crates/ra_syntax/src/grammar.ron b/crates/ra_syntax/src/grammar.ron index 47334bdf0..a2ccd7cb9 100644 --- a/crates/ra_syntax/src/grammar.ron +++ b/crates/ra_syntax/src/grammar.ron | |||
@@ -593,7 +593,10 @@ Grammar( | |||
593 | options: [ "UseTree" ] | 593 | options: [ "UseTree" ] |
594 | ), | 594 | ), |
595 | "UseTree": ( | 595 | "UseTree": ( |
596 | options: [ "Path", "UseTreeList" ] | 596 | options: [ "Path", "UseTreeList", "Alias" ] |
597 | ), | ||
598 | "Alias": ( | ||
599 | traits: ["NameOwner"], | ||
597 | ), | 600 | ), |
598 | "UseTreeList": ( | 601 | "UseTreeList": ( |
599 | collections: [["use_trees", "UseTree"]] | 602 | collections: [["use_trees", "UseTree"]] |
diff --git a/crates/ra_syntax/tests/data/parser/ok/0045_extern_inner_attributes.rs b/crates/ra_syntax/tests/data/parser/ok/0046_extern_inner_attributes.rs index fe67e2df4..fe67e2df4 100644 --- a/crates/ra_syntax/tests/data/parser/ok/0045_extern_inner_attributes.rs +++ b/crates/ra_syntax/tests/data/parser/ok/0046_extern_inner_attributes.rs | |||
diff --git a/crates/ra_syntax/tests/data/parser/ok/0045_extern_inner_attributes.txt b/crates/ra_syntax/tests/data/parser/ok/0046_extern_inner_attributes.txt index c68e1b271..c68e1b271 100644 --- a/crates/ra_syntax/tests/data/parser/ok/0045_extern_inner_attributes.txt +++ b/crates/ra_syntax/tests/data/parser/ok/0046_extern_inner_attributes.txt | |||