aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--crates/ra_hir/src/adt.rs19
-rw-r--r--crates/ra_hir/src/code_model_api.rs117
-rw-r--r--crates/ra_hir/src/code_model_impl/function.rs11
-rw-r--r--crates/ra_hir/src/code_model_impl/krate.rs10
-rw-r--r--crates/ra_hir/src/code_model_impl/module.rs16
-rw-r--r--crates/ra_hir/src/db.rs53
-rw-r--r--crates/ra_hir/src/expr.rs141
-rw-r--r--crates/ra_hir/src/expr/scope.rs57
-rw-r--r--crates/ra_hir/src/generics.rs5
-rw-r--r--crates/ra_hir/src/ids.rs14
-rw-r--r--crates/ra_hir/src/impl_block.rs77
-rw-r--r--crates/ra_hir/src/lib.rs6
-rw-r--r--crates/ra_hir/src/macros.rs34
-rw-r--r--crates/ra_hir/src/mock.rs6
-rw-r--r--crates/ra_hir/src/module_tree.rs22
-rw-r--r--crates/ra_hir/src/nameres.rs63
-rw-r--r--crates/ra_hir/src/nameres/lower.rs18
-rw-r--r--crates/ra_hir/src/nameres/tests.rs29
-rw-r--r--crates/ra_hir/src/path.rs13
-rw-r--r--crates/ra_hir/src/query_definitions.rs9
-rw-r--r--crates/ra_hir/src/resolve.rs226
-rw-r--r--crates/ra_hir/src/source_binder.rs82
-rw-r--r--crates/ra_hir/src/ty.rs272
-rw-r--r--crates/ra_hir/src/ty/method_resolution.rs65
-rw-r--r--crates/ra_hir/src/ty/snapshots/tests__infer_function_generics.snap8
-rw-r--r--crates/ra_hir/src/ty/snapshots/tests__infer_generic_chain.snap8
-rw-r--r--crates/ra_hir/src/ty/snapshots/tests__infer_type_param.snap14
-rw-r--r--crates/ra_ide_api/src/completion/complete_path.rs29
-rw-r--r--crates/ra_ide_api/src/completion/complete_scope.rs90
-rw-r--r--crates/ra_ide_api/src/completion/completion_context.rs5
-rw-r--r--crates/ra_ide_api/src/completion/completion_item.rs40
-rw-r--r--crates/ra_ide_api/src/completion/snapshots/completion_item__generic_params.snap40
-rw-r--r--crates/ra_ide_api/src/completion/snapshots/completion_item__generic_params_in_struct.snap36
-rw-r--r--crates/ra_ide_api/src/completion/snapshots/completion_item__self_in_methods.snap18
-rw-r--r--crates/ra_ide_api/src/db.rs3
-rw-r--r--crates/ra_ide_api/src/extend_selection.rs4
-rw-r--r--crates/ra_ide_api/src/goto_definition.rs50
-rw-r--r--crates/ra_ide_api/src/impls.rs84
-rw-r--r--crates/ra_ide_api/src/navigation_target.rs11
-rw-r--r--crates/ra_ide_api/src/snapshots/tests__highlight_query_group_macro.snap6
-rw-r--r--crates/ra_ide_api/src/snapshots/tests__highlights_code_inside_macros.snap48
-rw-r--r--crates/ra_ide_api/src/syntax_highlighting.rs1
-rw-r--r--crates/ra_lsp_server/src/conv.rs1
-rw-r--r--crates/ra_syntax/src/ast/generated.rs33
-rw-r--r--crates/ra_syntax/src/grammar.ron5
-rw-r--r--crates/ra_syntax/tests/data/parser/ok/0046_extern_inner_attributes.rs (renamed from crates/ra_syntax/tests/data/parser/ok/0045_extern_inner_attributes.rs)0
-rw-r--r--crates/ra_syntax/tests/data/parser/ok/0046_extern_inner_attributes.txt (renamed from crates/ra_syntax/tests/data/parser/ok/0045_extern_inner_attributes.txt)0
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::{
12use crate::{ 12use 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
35impl Struct { 35impl 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>
68impl EnumVariant { 71impl 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
95impl EnumData { 98impl 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
202impl StructField { 205impl 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};
5use ra_syntax::{ast::self, TreeArc, SyntaxNode}; 5use ra_syntax::{ast::self, TreeArc, SyntaxNode};
6 6
7use crate::{ 7use 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
186impl Docs for Module { 188impl 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
239impl Struct { 241impl 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
287impl Docs for Struct { 304impl Docs for Struct {
@@ -296,7 +313,7 @@ pub struct Enum {
296} 313}
297 314
298impl Enum { 315impl 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
336impl Docs for Enum { 368impl Docs for Enum {
@@ -346,13 +378,16 @@ pub struct EnumVariant {
346} 378}
347 379
348impl EnumVariant { 380impl 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
432impl Function { 467impl 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
471impl Docs for Function { 528impl Docs for Function {
@@ -480,7 +537,7 @@ pub struct Const {
480} 537}
481 538
482impl Const { 539impl 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
499impl Static { 556impl 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
516impl Trait { 573impl 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
537impl Type { 594impl 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};
5use crate::{ 5use 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
12impl Function { 12impl 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
24impl FnSignature { 22impl 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 @@
1use crate::{ 1use crate::{
2 Crate, CrateDependency, AsName, Module, 2 Crate, CrateDependency, AsName, Module, PersistentHirDatabase,
3 db::HirDatabase,
4}; 3};
5 4
6impl Crate { 5impl 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
13impl Module { 13impl 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)]
23pub trait HirDatabase: SourceDatabase + AsRef<HirInterner> { 23pub 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>; 84pub 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
12use crate::{ 12use 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
19pub use self::scope::{ExprScopes, ScopesWithSyntaxMapping, ScopeEntryWithSyntax}; 19pub use self::scope::{ExprScopes, ScopesWithSyntaxMapping, ScopeEntryWithSyntax};
20 20
21mod scope; 21pub(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)]
24pub struct ExprId(RawId); 24pub 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)]
29pub struct Body { 29pub 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?
79pub 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
84pub 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
67impl Index<ExprId> for Body { 98impl Index<ExprId> for Body {
@@ -448,23 +479,29 @@ pub(crate) fn body_hir(db: &impl HirDatabase, func: Function) -> Arc<Body> {
448} 479}
449 480
450struct ExprCollector { 481struct 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
459impl ExprCollector { 493impl 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
943pub(crate) fn collect_fn_body_syntax(node: &ast::FnDef) -> BodySyntaxMapping { 1013pub(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
984pub(crate) fn body_syntax_mapping(db: &impl HirDatabase, func: Function) -> Arc<BodySyntaxMapping> { 1022#[cfg(test)]
985 let (_, fn_def) = func.source(db); 1023pub(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};
12use crate::{ 12use 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
152impl ScopesWithSyntaxMapping { 143impl 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 {
336mod tests { 322mod 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
8use ra_syntax::ast::{self, NameOwner, TypeParamsOwner}; 8use ra_syntax::ast::{self, NameOwner, TypeParamsOwner};
9 9
10use crate::{db::HirDatabase, Name, AsName, Function, Struct, Enum, Trait, Type}; 10use 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)]
14pub struct GenericParam { 14pub 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
35impl GenericParams { 36impl 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};
10use crate::{ 10use 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);
62impl HirFileId { 63impl 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
183impl<'a, DB: HirDatabase> LocationCtx<&'a DB> { 187impl<'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
200pub(crate) trait AstItemDef<N: AstNode>: ArenaId + Clone { 204pub(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::{
7ast::{self, AstNode}}; 7ast::{self, AstNode}};
8 8
9use crate::{ 9use 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
17use crate::code_model_api::{Module, ModuleSource}; 19use 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
92impl ImplData { 121impl 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)]
164pub struct ModuleImplBlocks { 193pub 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
169impl ModuleImplBlocks { 199impl 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
200pub(crate) fn impls_in_module_with_source_map_query( 235pub(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
212pub(crate) fn impls_in_module(db: &impl HirDatabase, module: Module) -> Arc<ModuleImplBlocks> { 246pub(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
216pub(crate) fn impls_in_module_source_map_query( 253pub(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;
36mod expr; 36mod expr;
37mod generics; 37mod generics;
38mod docs; 38mod docs;
39mod resolve;
39 40
40mod code_model_api; 41mod code_model_api;
41mod code_model_impl; 42mod code_model_impl;
@@ -44,7 +45,7 @@ mod code_model_impl;
44mod marks; 45mod marks;
45 46
46use crate::{ 47use 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
65pub use self::code_model_api::{ 67pub 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
17use crate::{HirDatabase, MacroCallId}; 17use 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)]
21pub enum MacroDef { 21pub 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
187pub(crate) fn expand_macro_invocation( 159pub(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
12pub const WORKSPACE: SourceRootId = SourceRootId(0); 12pub 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)]
16pub(crate) struct MockDatabase { 20pub(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
14use crate::{ 14use 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
20impl ModuleSource { 21impl 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
48impl Submodule { 49impl 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
135impl ModuleTree { 136impl 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
296fn resolve_submodule( 304fn 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
25use crate::{ 25use 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)]
37pub struct ItemMap { 36pub 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)]
49pub struct ModuleScope { 48pub struct ModuleScope {
50 items: FxHashMap<Name, Resolution>, 49 pub(crate) items: FxHashMap<Name, Resolution>,
51} 50}
52 51
53impl ModuleScope { 52impl ModuleScope {
@@ -81,6 +80,15 @@ pub struct PerNs<T> {
81 pub values: Option<T>, 80 pub values: Option<T>,
82} 81}
83 82
83impl<T> Default for PerNs<T> {
84 fn default() -> Self {
85 PerNs {
86 types: None,
87 values: None,
88 }
89 }
90}
91
84impl<T> PerNs<T> { 92impl<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
167impl<'a, DB> Resolver<'a, DB> 186impl<'a, DB> Resolver<'a, DB>
168where 187where
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
332impl ItemMap { 354impl 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};
8use rustc_hash::FxHashMap; 8use rustc_hash::FxHashMap;
9 9
10use crate::{ 10use 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)]
22pub(super) struct ImportData { 22pub(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
59impl LoweredModule { 60impl 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;
5use test_utils::{assert_eq_text, covers}; 5use test_utils::{assert_eq_text, covers};
6 6
7use crate::{ 7use 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};
13use super::Resolution;
13 14
14fn item_map(fixture: &str) -> (Arc<ItemMap>, ModuleId) { 15fn 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]
94fn 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]
93fn use_trees() { 118fn 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 @@
1use std::sync::Arc; 1use std::sync::Arc;
2 2
3use ra_syntax::{ast, AstNode}; 3use ra_syntax::{ast::{self, NameOwner}, AstNode};
4 4
5use crate::{Name, AsName, type_ref::TypeRef}; 5use 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 {
164fn expand_use_tree<'a>( 164fn 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
7use crate::{ 7use crate::{
8 SourceFileItems, SourceItemId, HirFileId, 8 SourceFileItems, SourceItemId, HirFileId,
9 db::HirDatabase, 9 PersistentHirDatabase,
10}; 10};
11 11
12pub(super) fn file_items(db: &impl HirDatabase, file_id: HirFileId) -> Arc<SourceFileItems> { 12pub(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
18pub(super) fn file_item( 21pub(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.
2use std::sync::Arc;
3
4use rustc_hash::FxHashMap;
5
6use 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)]
18pub struct Resolver {
19 scopes: Vec<Scope>,
20}
21
22// TODO how to store these best
23#[derive(Debug, Clone)]
24pub(crate) struct ModuleItemMap {
25 item_map: Arc<ItemMap>,
26 module: Module,
27}
28
29#[derive(Debug, Clone)]
30pub(crate) struct ExprScope {
31 expr_scopes: Arc<ExprScopes>,
32 scope_id: ScopeId,
33}
34
35#[derive(Debug, Clone)]
36pub(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)]
48pub 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
58impl 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
118impl 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
148impl 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};
9use ra_syntax::{ 9use 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
15use crate::{ 15use 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
155pub 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
154pub fn macro_symbols(db: &impl HirDatabase, file_id: FileId) -> Vec<(SmolStr, TextRange)> { 168pub 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
206pub 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
240pub 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;
33use test_utils::tested_by; 33use test_utils::tested_by;
34 34
35use crate::{ 35use 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
302impl Ty { 303impl 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.
667fn type_for_fn(db: &impl HirDatabase, def: Function) -> Ty { 644fn 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
765pub(super) fn type_for_field(db: &impl HirDatabase, field: StructField) -> Ty { 735pub(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 {
814struct InferenceContext<'a, D: HirDatabase> { 784struct 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
907impl<'a, D: HirDatabase> InferenceContext<'a, D> { 875impl<'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> {
1730pub fn infer(db: &impl HirDatabase, func: Function) -> Arc<InferenceResult> { 1688pub 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;
7use rustc_hash::FxHashMap; 7use rustc_hash::FxHashMap;
8 8
9use crate::{ 9use 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)]
18pub enum TyFingerprint { 18pub 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
23impl TyFingerprint { 22impl 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
42impl CrateImplBlocks { 42impl 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---
2created: "2019-01-26T18:16:16.530712344+00:00" 2created: "2019-01-27T14:52:29.934503829+00:00"
3creator: [email protected] 3creator: [email protected]
4expression: "&result" 4expression: "&result"
5source: crates/ra_hir/src/ty/tests.rs 5source: 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---
2created: "2019-01-26T17:46:03.866825843+00:00" 2created: "2019-01-27T14:52:29.938713255+00:00"
3creator: [email protected] 3creator: [email protected]
4expression: "&result" 4expression: "&result"
5source: crates/ra_hir/src/ty/tests.rs 5source: 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---
2created: "2019-01-27T16:54:18.368427685+00:00" 2created: "2019-01-27T20:38:32.153717698+00:00"
3creator: [email protected] 3creator: [email protected]
4expression: "&result" 4expression: "&result"
5source: crates/ra_hir/src/ty/tests.rs 5source: 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 @@
1use join_to_string::join; 1use join_to_string::join;
2 2
3use hir::{Docs, Resolution};
4
3use crate::{ 5use crate::{
4 completion::{CompletionItem, CompletionItemKind, Completions, CompletionKind, CompletionContext}, 6 completion::{CompletionItem, CompletionItemKind, Completions, CompletionKind, CompletionContext},
5}; 7};
6 8
7use hir::Docs;
8
9pub(super) fn complete_path(acc: &mut Completions, ctx: &CompletionContext) { 9pub(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 @@
1use rustc_hash::FxHashSet; 1use crate::completion::{CompletionItem, Completions, CompletionKind, CompletionContext};
2use ra_syntax::ast::AstNode;
3use crate::completion::{CompletionItem, CompletionItemKind, Completions, CompletionKind, CompletionContext};
4 2
5pub(super) fn complete_scope(acc: &mut Completions, ctx: &CompletionContext) { 3pub(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
42fn 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};
8use hir::source_binder; 8use hir::{source_binder, Resolver};
9 9
10use crate::{db, FilePosition}; 10use 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 @@
1use hir::{Docs, Documentation}; 1use hir::{Docs, Documentation, PerNs, Resolution};
2use ra_syntax::TextRange; 2use ra_syntax::{
3 TextRange,
4};
3use ra_text_edit::TextEdit; 5use ra_text_edit::TextEdit;
4use test_utils::tested_by; 6use 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---
2created: "2019-02-01T22:20:40.580128393+00:00"
3creator: [email protected]
4expression: kind_completions
5source: 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---
2created: "2019-02-01T22:23:21.508620224+00:00"
3creator: [email protected]
4expression: kind_completions
5source: 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---
2created: "2019-01-23T05:27:32.422259+00:00" 2created: "2019-01-27T20:17:10.051725945+00:00"
3creator: insta@0.4.0 3creator: insta@0.5.2
4expression: kind_completions 4expression: kind_completions
5source: crates/ra_ide_api/src/completion/completion_item.rs 5source: 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)]
20pub(crate) struct RootDatabase { 21pub(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};
6use test_utils::tested_by; 6use test_utils::tested_by;
7use hir::Resolution;
7 8
8use crate::{FilePosition, NavigationTarget, db::RootDatabase, RangeInfo}; 9use 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
34fn 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
59fn 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 @@
1use ra_db::FileId; 1use ra_db::FileId;
2use ra_syntax::{ 2use 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};
6use hir::{ModuleSource, FieldSource}; 6use hir::{ModuleSource, FieldSource, Name};
7 7
8use crate::{FileSymbol, db::RootDatabase}; 8use 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---
2created: "2019-01-22T14:45:01.017117100+00:00" 2created: "2019-02-01T07:52:15.689836752+00:00"
3creator: insta@0.4.0 3creator: insta@0.5.3
4expression: "&highlights" 4expression: "&highlights"
5source: "crates\\ra_ide_api\\src\\syntax_highlighting.rs" 5source: 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---
2created: "2019-01-22T14:45:01.043047100+00:00" 2created: "2019-02-01T07:46:59.130146403+00:00"
3creator: insta@0.4.0 3creator: insta@0.5.3
4expression: "&highlights" 4expression: "&highlights"
5source: "crates\\ra_ide_api\\src\\syntax_highlighting.rs" 5source: 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)]
23pub struct Alias {
24 pub(crate) syntax: SyntaxNode,
25}
26unsafe impl TransparentNewType for Alias {
27 type Repr = rowan::SyntaxNode<RaTypes>;
28}
29
30impl 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
40impl ToOwned for Alias {
41 type Owned = TreeArc<Alias>;
42 fn to_owned(&self) -> TreeArc<Alias> { TreeArc::cast(self.syntax.to_owned()) }
43}
44
45
46impl ast::NameOwner for Alias {}
47impl 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