diff options
36 files changed, 939 insertions, 977 deletions
diff --git a/crates/ra_db/src/input.rs b/crates/ra_db/src/input.rs index b5d63e820..9825d52cf 100644 --- a/crates/ra_db/src/input.rs +++ b/crates/ra_db/src/input.rs | |||
@@ -160,6 +160,7 @@ pub trait FilesDatabase: salsa::Database { | |||
160 | /// Contents of the source root. | 160 | /// Contents of the source root. |
161 | #[salsa::input] | 161 | #[salsa::input] |
162 | fn source_root(&self, id: SourceRootId) -> Arc<SourceRoot>; | 162 | fn source_root(&self, id: SourceRootId) -> Arc<SourceRoot>; |
163 | fn source_root_crates(&self, id: SourceRootId) -> Arc<Vec<CrateId>>; | ||
163 | /// The set of "local" (that is, from the current workspace) roots. | 164 | /// The set of "local" (that is, from the current workspace) roots. |
164 | /// Files in local roots are assumed to change frequently. | 165 | /// Files in local roots are assumed to change frequently. |
165 | #[salsa::input] | 166 | #[salsa::input] |
@@ -173,6 +174,17 @@ pub trait FilesDatabase: salsa::Database { | |||
173 | fn crate_graph(&self) -> Arc<CrateGraph>; | 174 | fn crate_graph(&self) -> Arc<CrateGraph>; |
174 | } | 175 | } |
175 | 176 | ||
177 | fn source_root_crates(db: &impl FilesDatabase, id: SourceRootId) -> Arc<Vec<CrateId>> { | ||
178 | let root = db.source_root(id); | ||
179 | let graph = db.crate_graph(); | ||
180 | let res = root | ||
181 | .files | ||
182 | .values() | ||
183 | .filter_map(|&it| graph.crate_id_for_crate_root(it)) | ||
184 | .collect::<Vec<_>>(); | ||
185 | Arc::new(res) | ||
186 | } | ||
187 | |||
176 | #[cfg(test)] | 188 | #[cfg(test)] |
177 | mod tests { | 189 | mod tests { |
178 | use super::{CrateGraph, FileId, SmolStr}; | 190 | use super::{CrateGraph, FileId, SmolStr}; |
diff --git a/crates/ra_db/src/lib.rs b/crates/ra_db/src/lib.rs index 32d7e09b9..84759c75a 100644 --- a/crates/ra_db/src/lib.rs +++ b/crates/ra_db/src/lib.rs | |||
@@ -13,7 +13,7 @@ pub use crate::{ | |||
13 | cancellation::Canceled, | 13 | cancellation::Canceled, |
14 | input::{ | 14 | input::{ |
15 | FilesDatabase, FileId, CrateId, SourceRoot, SourceRootId, CrateGraph, Dependency, | 15 | FilesDatabase, FileId, CrateId, SourceRoot, SourceRootId, CrateGraph, Dependency, |
16 | FileTextQuery, FileSourceRootQuery, SourceRootQuery, LocalRootsQuery, LibraryRootsQuery, CrateGraphQuery, | 16 | FileTextQuery, FileSourceRootQuery, SourceRootQuery, SourceRootCratesQuery, LocalRootsQuery, LibraryRootsQuery, CrateGraphQuery, |
17 | FileRelativePathQuery | 17 | FileRelativePathQuery |
18 | }, | 18 | }, |
19 | loc2id::LocationIntener, | 19 | loc2id::LocationIntener, |
diff --git a/crates/ra_hir/src/adt.rs b/crates/ra_hir/src/adt.rs index ab1c428db..6b13b464d 100644 --- a/crates/ra_hir/src/adt.rs +++ b/crates/ra_hir/src/adt.rs | |||
@@ -3,25 +3,35 @@ | |||
3 | 3 | ||
4 | use std::sync::Arc; | 4 | use std::sync::Arc; |
5 | 5 | ||
6 | use ra_syntax::{ | 6 | use ra_syntax::ast::{self, NameOwner, StructFlavor}; |
7 | SyntaxNode, | ||
8 | ast::{self, NameOwner, StructFlavor, AstNode} | ||
9 | }; | ||
10 | 7 | ||
11 | use crate::{ | 8 | use crate::{ |
12 | DefId, DefLoc, Name, AsName, Struct, Enum, EnumVariant, | 9 | Name, AsName, Struct, Enum, EnumVariant, Crate, |
13 | HirDatabase, DefKind, | 10 | HirDatabase, |
14 | SourceItemId, | ||
15 | type_ref::TypeRef, | 11 | type_ref::TypeRef, |
12 | ids::LocationCtx, | ||
16 | }; | 13 | }; |
17 | 14 | ||
18 | impl Struct { | 15 | #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] |
19 | pub(crate) fn new(def_id: DefId) -> Self { | 16 | pub enum AdtDef { |
20 | Struct { def_id } | 17 | Struct(Struct), |
18 | Enum(Enum), | ||
19 | } | ||
20 | impl_froms!(AdtDef: Struct, Enum); | ||
21 | |||
22 | impl AdtDef { | ||
23 | pub(crate) fn krate(self, db: &impl HirDatabase) -> Option<Crate> { | ||
24 | match self { | ||
25 | AdtDef::Struct(s) => s.module(db), | ||
26 | AdtDef::Enum(e) => e.module(db), | ||
27 | } | ||
28 | .krate(db) | ||
21 | } | 29 | } |
30 | } | ||
22 | 31 | ||
32 | impl Struct { | ||
23 | pub(crate) fn variant_data(&self, db: &impl HirDatabase) -> Arc<VariantData> { | 33 | pub(crate) fn variant_data(&self, db: &impl HirDatabase) -> Arc<VariantData> { |
24 | db.struct_data(self.def_id).variant_data.clone() | 34 | db.struct_data((*self).into()).variant_data.clone() |
25 | } | 35 | } |
26 | } | 36 | } |
27 | 37 | ||
@@ -39,38 +49,12 @@ impl StructData { | |||
39 | StructData { name, variant_data } | 49 | StructData { name, variant_data } |
40 | } | 50 | } |
41 | 51 | ||
42 | pub(crate) fn struct_data_query(db: &impl HirDatabase, def_id: DefId) -> Arc<StructData> { | 52 | pub(crate) fn struct_data_query(db: &impl HirDatabase, struct_: Struct) -> Arc<StructData> { |
43 | let def_loc = def_id.loc(db); | 53 | let (_, struct_def) = struct_.source(db); |
44 | assert!(def_loc.kind == DefKind::Struct); | 54 | Arc::new(StructData::new(&*struct_def)) |
45 | let syntax = db.file_item(def_loc.source_item_id); | ||
46 | let struct_def = | ||
47 | ast::StructDef::cast(&syntax).expect("struct def should point to StructDef node"); | ||
48 | Arc::new(StructData::new(struct_def)) | ||
49 | } | 55 | } |
50 | } | 56 | } |
51 | 57 | ||
52 | fn get_def_id( | ||
53 | db: &impl HirDatabase, | ||
54 | same_file_loc: &DefLoc, | ||
55 | node: &SyntaxNode, | ||
56 | expected_kind: DefKind, | ||
57 | ) -> DefId { | ||
58 | let file_id = same_file_loc.source_item_id.file_id; | ||
59 | let file_items = db.file_items(file_id); | ||
60 | |||
61 | let item_id = file_items.id_of(file_id, node); | ||
62 | let source_item_id = SourceItemId { | ||
63 | item_id: Some(item_id), | ||
64 | ..same_file_loc.source_item_id | ||
65 | }; | ||
66 | let loc = DefLoc { | ||
67 | kind: expected_kind, | ||
68 | source_item_id, | ||
69 | ..*same_file_loc | ||
70 | }; | ||
71 | loc.id(db) | ||
72 | } | ||
73 | |||
74 | #[derive(Debug, Clone, PartialEq, Eq)] | 58 | #[derive(Debug, Clone, PartialEq, Eq)] |
75 | pub struct EnumData { | 59 | pub struct EnumData { |
76 | pub(crate) name: Option<Name>, | 60 | pub(crate) name: Option<Name>, |
@@ -83,27 +67,24 @@ impl EnumData { | |||
83 | EnumData { name, variants } | 67 | EnumData { name, variants } |
84 | } | 68 | } |
85 | 69 | ||
86 | pub(crate) fn enum_data_query(db: &impl HirDatabase, def_id: DefId) -> Arc<EnumData> { | 70 | pub(crate) fn enum_data_query(db: &impl HirDatabase, e: Enum) -> Arc<EnumData> { |
87 | let def_loc = def_id.loc(db); | 71 | let (file_id, enum_def) = e.source(db); |
88 | assert!(def_loc.kind == DefKind::Enum); | 72 | let module = e.module(db); |
89 | let syntax = db.file_item(def_loc.source_item_id); | 73 | let ctx = LocationCtx::new(db, module, file_id); |
90 | let enum_def = ast::EnumDef::cast(&syntax).expect("enum def should point to EnumDef node"); | ||
91 | let variants = if let Some(vl) = enum_def.variant_list() { | 74 | let variants = if let Some(vl) = enum_def.variant_list() { |
92 | vl.variants() | 75 | vl.variants() |
93 | .filter_map(|variant_def| { | 76 | .filter_map(|variant_def| { |
94 | let name = variant_def.name().map(|n| n.as_name()); | 77 | let name = variant_def.name()?.as_name(); |
95 | 78 | let var = EnumVariant { | |
96 | name.map(|n| { | 79 | id: ctx.to_def(variant_def), |
97 | let def_id = | 80 | }; |
98 | get_def_id(db, &def_loc, variant_def.syntax(), DefKind::EnumVariant); | 81 | Some((name, var)) |
99 | (n, EnumVariant::new(def_id)) | ||
100 | }) | ||
101 | }) | 82 | }) |
102 | .collect() | 83 | .collect() |
103 | } else { | 84 | } else { |
104 | Vec::new() | 85 | Vec::new() |
105 | }; | 86 | }; |
106 | Arc::new(EnumData::new(enum_def, variants)) | 87 | Arc::new(EnumData::new(&*enum_def, variants)) |
107 | } | 88 | } |
108 | } | 89 | } |
109 | 90 | ||
@@ -128,21 +109,15 @@ impl EnumVariantData { | |||
128 | 109 | ||
129 | pub(crate) fn enum_variant_data_query( | 110 | pub(crate) fn enum_variant_data_query( |
130 | db: &impl HirDatabase, | 111 | db: &impl HirDatabase, |
131 | def_id: DefId, | 112 | var: EnumVariant, |
132 | ) -> Arc<EnumVariantData> { | 113 | ) -> Arc<EnumVariantData> { |
133 | let def_loc = def_id.loc(db); | 114 | let (file_id, variant_def) = var.source(db); |
134 | assert!(def_loc.kind == DefKind::EnumVariant); | 115 | let enum_def = variant_def.parent_enum(); |
135 | let syntax = db.file_item(def_loc.source_item_id); | 116 | let ctx = LocationCtx::new(db, var.module(db), file_id); |
136 | let variant_def = ast::EnumVariant::cast(&syntax) | 117 | let e = Enum { |
137 | .expect("enum variant def should point to EnumVariant node"); | 118 | id: ctx.to_def(enum_def), |
138 | let enum_node = syntax | 119 | }; |
139 | .parent() | 120 | Arc::new(EnumVariantData::new(&*variant_def, e)) |
140 | .expect("enum variant should have enum variant list ancestor") | ||
141 | .parent() | ||
142 | .expect("enum variant list should have enum ancestor"); | ||
143 | let enum_def_id = get_def_id(db, &def_loc, enum_node, DefKind::Enum); | ||
144 | |||
145 | Arc::new(EnumVariantData::new(variant_def, Enum::new(enum_def_id))) | ||
146 | } | 121 | } |
147 | } | 122 | } |
148 | 123 | ||
diff --git a/crates/ra_hir/src/code_model_api.rs b/crates/ra_hir/src/code_model_api.rs index 3ff07bd60..6739627b4 100644 --- a/crates/ra_hir/src/code_model_api.rs +++ b/crates/ra_hir/src/code_model_api.rs | |||
@@ -5,22 +5,23 @@ use ra_db::{CrateId, FileId}; | |||
5 | use ra_syntax::{ast::self, TreeArc, SyntaxNode}; | 5 | use ra_syntax::{ast::self, TreeArc, SyntaxNode}; |
6 | 6 | ||
7 | use crate::{ | 7 | use crate::{ |
8 | Name, DefId, Path, PerNs, ScopesWithSyntaxMapping, Ty, HirFileId, | 8 | Name, Path, PerNs, 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 | db::HirDatabase, |
12 | expr::BodySyntaxMapping, | 12 | expr::BodySyntaxMapping, |
13 | ty::InferenceResult, | 13 | ty::{InferenceResult, VariantDef}, |
14 | adt::VariantData, | 14 | adt::VariantData, |
15 | generics::GenericParams, | 15 | generics::GenericParams, |
16 | code_model_impl::def_id_to_ast, | 16 | docs::{Documentation, Docs, docs_from_ast}, |
17 | docs::{Documentation, Docs, docs_from_ast} | 17 | module_tree::ModuleId, |
18 | ids::{FunctionId, StructId, EnumId, EnumVariantId, AstItemDef, ConstId, StaticId, TraitId, TypeId}, | ||
18 | }; | 19 | }; |
19 | 20 | ||
20 | /// hir::Crate describes a single crate. It's the main interface with which | 21 | /// hir::Crate describes a single crate. It's the main interface with which |
21 | /// a crate's dependencies interact. Mostly, it should be just a proxy for the | 22 | /// a crate's dependencies interact. Mostly, it should be just a proxy for the |
22 | /// root module. | 23 | /// root module. |
23 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | 24 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] |
24 | pub struct Crate { | 25 | pub struct Crate { |
25 | pub(crate) crate_id: CrateId, | 26 | pub(crate) crate_id: CrateId, |
26 | } | 27 | } |
@@ -45,22 +46,40 @@ impl Crate { | |||
45 | 46 | ||
46 | #[derive(Debug)] | 47 | #[derive(Debug)] |
47 | pub enum Def { | 48 | pub enum Def { |
49 | Item, | ||
50 | } | ||
51 | |||
52 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | ||
53 | pub struct Module { | ||
54 | pub(crate) krate: CrateId, | ||
55 | pub(crate) module_id: ModuleId, | ||
56 | } | ||
57 | |||
58 | /// The defs which can be visible in the module. | ||
59 | #[derive(Debug, Clone, Copy, PartialEq, Eq)] | ||
60 | pub enum ModuleDef { | ||
48 | Module(Module), | 61 | Module(Module), |
62 | Function(Function), | ||
49 | Struct(Struct), | 63 | Struct(Struct), |
50 | Enum(Enum), | 64 | Enum(Enum), |
65 | // Can't be directly declared, but can be imported. | ||
51 | EnumVariant(EnumVariant), | 66 | EnumVariant(EnumVariant), |
52 | Function(Function), | ||
53 | Const(Const), | 67 | Const(Const), |
54 | Static(Static), | 68 | Static(Static), |
55 | Trait(Trait), | 69 | Trait(Trait), |
56 | Type(Type), | 70 | Type(Type), |
57 | Item, | ||
58 | } | ||
59 | |||
60 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
61 | pub struct Module { | ||
62 | pub(crate) def_id: DefId, | ||
63 | } | 71 | } |
72 | impl_froms!( | ||
73 | ModuleDef: Module, | ||
74 | Function, | ||
75 | Struct, | ||
76 | Enum, | ||
77 | EnumVariant, | ||
78 | Const, | ||
79 | Static, | ||
80 | Trait, | ||
81 | Type | ||
82 | ); | ||
64 | 83 | ||
65 | pub enum ModuleSource { | 84 | pub enum ModuleSource { |
66 | SourceFile(TreeArc<ast::SourceFile>), | 85 | SourceFile(TreeArc<ast::SourceFile>), |
@@ -149,7 +168,7 @@ impl Module { | |||
149 | self.scope_impl(db) | 168 | self.scope_impl(db) |
150 | } | 169 | } |
151 | 170 | ||
152 | pub fn resolve_path(&self, db: &impl HirDatabase, path: &Path) -> PerNs<DefId> { | 171 | pub fn resolve_path(&self, db: &impl HirDatabase, path: &Path) -> PerNs<ModuleDef> { |
153 | self.resolve_path_impl(db, path) | 172 | self.resolve_path_impl(db, path) |
154 | } | 173 | } |
155 | 174 | ||
@@ -160,7 +179,7 @@ impl Module { | |||
160 | 179 | ||
161 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | 180 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] |
162 | pub struct StructField { | 181 | pub struct StructField { |
163 | parent: DefId, | 182 | parent: VariantDef, |
164 | name: Name, | 183 | name: Name, |
165 | } | 184 | } |
166 | 185 | ||
@@ -174,38 +193,38 @@ impl StructField { | |||
174 | } | 193 | } |
175 | } | 194 | } |
176 | 195 | ||
177 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | 196 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] |
178 | pub struct Struct { | 197 | pub struct Struct { |
179 | pub(crate) def_id: DefId, | 198 | pub(crate) id: StructId, |
180 | } | 199 | } |
181 | 200 | ||
182 | impl Struct { | 201 | impl Struct { |
183 | pub fn def_id(&self) -> DefId { | 202 | pub fn source(&self, db: &impl HirDatabase) -> (HirFileId, TreeArc<ast::StructDef>) { |
184 | self.def_id | 203 | self.id.source(db) |
204 | } | ||
205 | |||
206 | pub fn module(&self, db: &impl HirDatabase) -> Module { | ||
207 | self.id.module(db) | ||
185 | } | 208 | } |
186 | 209 | ||
187 | pub fn name(&self, db: &impl HirDatabase) -> Option<Name> { | 210 | pub fn name(&self, db: &impl HirDatabase) -> Option<Name> { |
188 | db.struct_data(self.def_id).name.clone() | 211 | db.struct_data(*self).name.clone() |
189 | } | 212 | } |
190 | 213 | ||
191 | pub fn fields(&self, db: &impl HirDatabase) -> Vec<StructField> { | 214 | pub fn fields(&self, db: &impl HirDatabase) -> Vec<StructField> { |
192 | db.struct_data(self.def_id) | 215 | db.struct_data(*self) |
193 | .variant_data | 216 | .variant_data |
194 | .fields() | 217 | .fields() |
195 | .iter() | 218 | .iter() |
196 | .map(|it| StructField { | 219 | .map(|it| StructField { |
197 | parent: self.def_id, | 220 | parent: (*self).into(), |
198 | name: it.name.clone(), | 221 | name: it.name.clone(), |
199 | }) | 222 | }) |
200 | .collect() | 223 | .collect() |
201 | } | 224 | } |
202 | 225 | ||
203 | pub fn source(&self, db: &impl HirDatabase) -> (HirFileId, TreeArc<ast::StructDef>) { | ||
204 | def_id_to_ast(db, self.def_id) | ||
205 | } | ||
206 | |||
207 | pub fn generic_params(&self, db: &impl HirDatabase) -> Arc<GenericParams> { | 226 | pub fn generic_params(&self, db: &impl HirDatabase) -> Arc<GenericParams> { |
208 | db.generic_params(self.def_id) | 227 | db.generic_params((*self).into()) |
209 | } | 228 | } |
210 | } | 229 | } |
211 | 230 | ||
@@ -215,34 +234,30 @@ impl Docs for Struct { | |||
215 | } | 234 | } |
216 | } | 235 | } |
217 | 236 | ||
218 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | 237 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] |
219 | pub struct Enum { | 238 | pub struct Enum { |
220 | pub(crate) def_id: DefId, | 239 | pub(crate) id: EnumId, |
221 | } | 240 | } |
222 | 241 | ||
223 | impl Enum { | 242 | impl Enum { |
224 | pub(crate) fn new(def_id: DefId) -> Self { | 243 | pub fn source(&self, db: &impl HirDatabase) -> (HirFileId, TreeArc<ast::EnumDef>) { |
225 | Enum { def_id } | 244 | self.id.source(db) |
226 | } | 245 | } |
227 | 246 | ||
228 | pub fn def_id(&self) -> DefId { | 247 | pub fn module(&self, db: &impl HirDatabase) -> Module { |
229 | self.def_id | 248 | self.id.module(db) |
230 | } | 249 | } |
231 | 250 | ||
232 | pub fn name(&self, db: &impl HirDatabase) -> Option<Name> { | 251 | pub fn name(&self, db: &impl HirDatabase) -> Option<Name> { |
233 | db.enum_data(self.def_id).name.clone() | 252 | db.enum_data(*self).name.clone() |
234 | } | 253 | } |
235 | 254 | ||
236 | pub fn variants(&self, db: &impl HirDatabase) -> Vec<(Name, EnumVariant)> { | 255 | pub fn variants(&self, db: &impl HirDatabase) -> Vec<(Name, EnumVariant)> { |
237 | db.enum_data(self.def_id).variants.clone() | 256 | db.enum_data(*self).variants.clone() |
238 | } | ||
239 | |||
240 | pub fn source(&self, db: &impl HirDatabase) -> (HirFileId, TreeArc<ast::EnumDef>) { | ||
241 | def_id_to_ast(db, self.def_id) | ||
242 | } | 257 | } |
243 | 258 | ||
244 | pub fn generic_params(&self, db: &impl HirDatabase) -> Arc<GenericParams> { | 259 | pub fn generic_params(&self, db: &impl HirDatabase) -> Arc<GenericParams> { |
245 | db.generic_params(self.def_id) | 260 | db.generic_params((*self).into()) |
246 | } | 261 | } |
247 | } | 262 | } |
248 | 263 | ||
@@ -252,30 +267,28 @@ impl Docs for Enum { | |||
252 | } | 267 | } |
253 | } | 268 | } |
254 | 269 | ||
255 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | 270 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] |
256 | pub struct EnumVariant { | 271 | pub struct EnumVariant { |
257 | pub(crate) def_id: DefId, | 272 | pub(crate) id: EnumVariantId, |
258 | } | 273 | } |
259 | 274 | ||
260 | impl EnumVariant { | 275 | impl EnumVariant { |
261 | pub(crate) fn new(def_id: DefId) -> Self { | 276 | pub fn source(&self, db: &impl HirDatabase) -> (HirFileId, TreeArc<ast::EnumVariant>) { |
262 | EnumVariant { def_id } | 277 | self.id.source(db) |
263 | } | 278 | } |
264 | 279 | pub fn module(&self, db: &impl HirDatabase) -> Module { | |
265 | pub fn def_id(&self) -> DefId { | 280 | self.id.module(db) |
266 | self.def_id | ||
267 | } | 281 | } |
268 | |||
269 | pub fn parent_enum(&self, db: &impl HirDatabase) -> Enum { | 282 | pub fn parent_enum(&self, db: &impl HirDatabase) -> Enum { |
270 | db.enum_variant_data(self.def_id).parent_enum.clone() | 283 | db.enum_variant_data(*self).parent_enum.clone() |
271 | } | 284 | } |
272 | 285 | ||
273 | pub fn name(&self, db: &impl HirDatabase) -> Option<Name> { | 286 | pub fn name(&self, db: &impl HirDatabase) -> Option<Name> { |
274 | db.enum_variant_data(self.def_id).name.clone() | 287 | db.enum_variant_data(*self).name.clone() |
275 | } | 288 | } |
276 | 289 | ||
277 | pub fn variant_data(&self, db: &impl HirDatabase) -> Arc<VariantData> { | 290 | pub fn variant_data(&self, db: &impl HirDatabase) -> Arc<VariantData> { |
278 | db.enum_variant_data(self.def_id).variant_data.clone() | 291 | db.enum_variant_data(*self).variant_data.clone() |
279 | } | 292 | } |
280 | 293 | ||
281 | pub fn fields(&self, db: &impl HirDatabase) -> Vec<StructField> { | 294 | pub fn fields(&self, db: &impl HirDatabase) -> Vec<StructField> { |
@@ -283,15 +296,11 @@ impl EnumVariant { | |||
283 | .fields() | 296 | .fields() |
284 | .iter() | 297 | .iter() |
285 | .map(|it| StructField { | 298 | .map(|it| StructField { |
286 | parent: self.def_id, | 299 | parent: (*self).into(), |
287 | name: it.name.clone(), | 300 | name: it.name.clone(), |
288 | }) | 301 | }) |
289 | .collect() | 302 | .collect() |
290 | } | 303 | } |
291 | |||
292 | pub fn source(&self, db: &impl HirDatabase) -> (HirFileId, TreeArc<ast::EnumVariant>) { | ||
293 | def_id_to_ast(db, self.def_id) | ||
294 | } | ||
295 | } | 304 | } |
296 | 305 | ||
297 | impl Docs for EnumVariant { | 306 | impl Docs for EnumVariant { |
@@ -300,9 +309,9 @@ impl Docs for EnumVariant { | |||
300 | } | 309 | } |
301 | } | 310 | } |
302 | 311 | ||
303 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | 312 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] |
304 | pub struct Function { | 313 | pub struct Function { |
305 | pub(crate) def_id: DefId, | 314 | pub(crate) id: FunctionId, |
306 | } | 315 | } |
307 | 316 | ||
308 | pub use crate::code_model_impl::function::ScopeEntryWithSyntax; | 317 | pub use crate::code_model_impl::function::ScopeEntryWithSyntax; |
@@ -339,21 +348,21 @@ impl FnSignature { | |||
339 | } | 348 | } |
340 | 349 | ||
341 | impl Function { | 350 | impl Function { |
342 | pub fn def_id(&self) -> DefId { | 351 | pub fn source(&self, db: &impl HirDatabase) -> (HirFileId, TreeArc<ast::FnDef>) { |
343 | self.def_id | 352 | self.id.source(db) |
344 | } | 353 | } |
345 | 354 | ||
346 | pub fn source(&self, db: &impl HirDatabase) -> (HirFileId, TreeArc<ast::FnDef>) { | 355 | pub fn module(&self, db: &impl HirDatabase) -> Module { |
347 | def_id_to_ast(db, self.def_id) | 356 | self.id.module(db) |
348 | } | 357 | } |
349 | 358 | ||
350 | pub fn body_syntax_mapping(&self, db: &impl HirDatabase) -> Arc<BodySyntaxMapping> { | 359 | pub fn body_syntax_mapping(&self, db: &impl HirDatabase) -> Arc<BodySyntaxMapping> { |
351 | db.body_syntax_mapping(self.def_id) | 360 | db.body_syntax_mapping(*self) |
352 | } | 361 | } |
353 | 362 | ||
354 | pub fn scopes(&self, db: &impl HirDatabase) -> ScopesWithSyntaxMapping { | 363 | pub fn scopes(&self, db: &impl HirDatabase) -> ScopesWithSyntaxMapping { |
355 | let scopes = db.fn_scopes(self.def_id); | 364 | let scopes = db.fn_scopes(*self); |
356 | let syntax_mapping = db.body_syntax_mapping(self.def_id); | 365 | let syntax_mapping = db.body_syntax_mapping(*self); |
357 | ScopesWithSyntaxMapping { | 366 | ScopesWithSyntaxMapping { |
358 | scopes, | 367 | scopes, |
359 | syntax_mapping, | 368 | syntax_mapping, |
@@ -361,15 +370,15 @@ impl Function { | |||
361 | } | 370 | } |
362 | 371 | ||
363 | pub fn signature(&self, db: &impl HirDatabase) -> Arc<FnSignature> { | 372 | pub fn signature(&self, db: &impl HirDatabase) -> Arc<FnSignature> { |
364 | db.fn_signature(self.def_id) | 373 | db.fn_signature(*self) |
365 | } | 374 | } |
366 | 375 | ||
367 | pub fn infer(&self, db: &impl HirDatabase) -> Arc<InferenceResult> { | 376 | pub fn infer(&self, db: &impl HirDatabase) -> Arc<InferenceResult> { |
368 | db.infer(self.def_id) | 377 | db.infer(*self) |
369 | } | 378 | } |
370 | 379 | ||
371 | pub fn generic_params(&self, db: &impl HirDatabase) -> Arc<GenericParams> { | 380 | pub fn generic_params(&self, db: &impl HirDatabase) -> Arc<GenericParams> { |
372 | db.generic_params(self.def_id) | 381 | db.generic_params((*self).into()) |
373 | } | 382 | } |
374 | } | 383 | } |
375 | 384 | ||
@@ -379,18 +388,14 @@ impl Docs for Function { | |||
379 | } | 388 | } |
380 | } | 389 | } |
381 | 390 | ||
382 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | 391 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] |
383 | pub struct Const { | 392 | pub struct Const { |
384 | pub(crate) def_id: DefId, | 393 | pub(crate) id: ConstId, |
385 | } | 394 | } |
386 | 395 | ||
387 | impl Const { | 396 | impl Const { |
388 | pub(crate) fn new(def_id: DefId) -> Const { | ||
389 | Const { def_id } | ||
390 | } | ||
391 | |||
392 | pub fn source(&self, db: &impl HirDatabase) -> (HirFileId, TreeArc<ast::ConstDef>) { | 397 | pub fn source(&self, db: &impl HirDatabase) -> (HirFileId, TreeArc<ast::ConstDef>) { |
393 | def_id_to_ast(db, self.def_id) | 398 | self.id.source(db) |
394 | } | 399 | } |
395 | } | 400 | } |
396 | 401 | ||
@@ -400,18 +405,14 @@ impl Docs for Const { | |||
400 | } | 405 | } |
401 | } | 406 | } |
402 | 407 | ||
403 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | 408 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] |
404 | pub struct Static { | 409 | pub struct Static { |
405 | pub(crate) def_id: DefId, | 410 | pub(crate) id: StaticId, |
406 | } | 411 | } |
407 | 412 | ||
408 | impl Static { | 413 | impl Static { |
409 | pub(crate) fn new(def_id: DefId) -> Static { | ||
410 | Static { def_id } | ||
411 | } | ||
412 | |||
413 | pub fn source(&self, db: &impl HirDatabase) -> (HirFileId, TreeArc<ast::StaticDef>) { | 414 | pub fn source(&self, db: &impl HirDatabase) -> (HirFileId, TreeArc<ast::StaticDef>) { |
414 | def_id_to_ast(db, self.def_id) | 415 | self.id.source(db) |
415 | } | 416 | } |
416 | } | 417 | } |
417 | 418 | ||
@@ -421,22 +422,18 @@ impl Docs for Static { | |||
421 | } | 422 | } |
422 | } | 423 | } |
423 | 424 | ||
424 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | 425 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] |
425 | pub struct Trait { | 426 | pub struct Trait { |
426 | pub(crate) def_id: DefId, | 427 | pub(crate) id: TraitId, |
427 | } | 428 | } |
428 | 429 | ||
429 | impl Trait { | 430 | impl Trait { |
430 | pub(crate) fn new(def_id: DefId) -> Trait { | ||
431 | Trait { def_id } | ||
432 | } | ||
433 | |||
434 | pub fn source(&self, db: &impl HirDatabase) -> (HirFileId, TreeArc<ast::TraitDef>) { | 431 | pub fn source(&self, db: &impl HirDatabase) -> (HirFileId, TreeArc<ast::TraitDef>) { |
435 | def_id_to_ast(db, self.def_id) | 432 | self.id.source(db) |
436 | } | 433 | } |
437 | 434 | ||
438 | pub fn generic_params(&self, db: &impl HirDatabase) -> Arc<GenericParams> { | 435 | pub fn generic_params(&self, db: &impl HirDatabase) -> Arc<GenericParams> { |
439 | db.generic_params(self.def_id) | 436 | db.generic_params((*self).into()) |
440 | } | 437 | } |
441 | } | 438 | } |
442 | 439 | ||
@@ -446,22 +443,18 @@ impl Docs for Trait { | |||
446 | } | 443 | } |
447 | } | 444 | } |
448 | 445 | ||
449 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | 446 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] |
450 | pub struct Type { | 447 | pub struct Type { |
451 | pub(crate) def_id: DefId, | 448 | pub(crate) id: TypeId, |
452 | } | 449 | } |
453 | 450 | ||
454 | impl Type { | 451 | impl Type { |
455 | pub(crate) fn new(def_id: DefId) -> Type { | ||
456 | Type { def_id } | ||
457 | } | ||
458 | |||
459 | pub fn source(&self, db: &impl HirDatabase) -> (HirFileId, TreeArc<ast::TypeDef>) { | 452 | pub fn source(&self, db: &impl HirDatabase) -> (HirFileId, TreeArc<ast::TypeDef>) { |
460 | def_id_to_ast(db, self.def_id) | 453 | self.id.source(db) |
461 | } | 454 | } |
462 | 455 | ||
463 | pub fn generic_params(&self, db: &impl HirDatabase) -> Arc<GenericParams> { | 456 | pub fn generic_params(&self, db: &impl HirDatabase) -> Arc<GenericParams> { |
464 | db.generic_params(self.def_id) | 457 | db.generic_params((*self).into()) |
465 | } | 458 | } |
466 | } | 459 | } |
467 | 460 | ||
diff --git a/crates/ra_hir/src/code_model_impl.rs b/crates/ra_hir/src/code_model_impl.rs index 0cea9f7b6..1f28fab74 100644 --- a/crates/ra_hir/src/code_model_impl.rs +++ b/crates/ra_hir/src/code_model_impl.rs | |||
@@ -1,18 +1,3 @@ | |||
1 | mod krate; // `crate` is invalid ident :( | 1 | mod krate; // `crate` is invalid ident :( |
2 | mod module; | 2 | mod module; |
3 | pub(crate) mod function; | 3 | pub(crate) mod function; |
4 | |||
5 | use ra_syntax::{AstNode, TreeArc}; | ||
6 | |||
7 | use crate::{HirDatabase, DefId, HirFileId}; | ||
8 | |||
9 | pub(crate) fn def_id_to_ast<N: AstNode>( | ||
10 | db: &impl HirDatabase, | ||
11 | def_id: DefId, | ||
12 | ) -> (HirFileId, TreeArc<N>) { | ||
13 | let (file_id, syntax) = def_id.source(db); | ||
14 | let ast = N::cast(&syntax) | ||
15 | .unwrap_or_else(|| panic!("def points to wrong source {:?} {:?}", def_id, syntax)) | ||
16 | .to_owned(); | ||
17 | (file_id, ast) | ||
18 | } | ||
diff --git a/crates/ra_hir/src/code_model_impl/function.rs b/crates/ra_hir/src/code_model_impl/function.rs index c68c6bfbf..e0dd4d629 100644 --- a/crates/ra_hir/src/code_model_impl/function.rs +++ b/crates/ra_hir/src/code_model_impl/function.rs | |||
@@ -2,41 +2,32 @@ mod scope; | |||
2 | 2 | ||
3 | use std::sync::Arc; | 3 | use std::sync::Arc; |
4 | 4 | ||
5 | use ra_syntax::{TreeArc, ast::{self, NameOwner}}; | 5 | use ra_syntax::ast::{self, NameOwner}; |
6 | 6 | ||
7 | use crate::{ | 7 | use crate::{ |
8 | DefId, HirDatabase, Name, AsName, Function, FnSignature, Module, | 8 | HirDatabase, Name, AsName, Function, FnSignature, |
9 | type_ref::{TypeRef, Mutability}, | 9 | type_ref::{TypeRef, Mutability}, |
10 | expr::Body, | 10 | expr::Body, |
11 | impl_block::ImplBlock, | 11 | impl_block::ImplBlock, |
12 | code_model_impl::def_id_to_ast, | ||
13 | }; | 12 | }; |
14 | 13 | ||
15 | pub use self::scope::{FnScopes, ScopesWithSyntaxMapping, ScopeEntryWithSyntax}; | 14 | pub use self::scope::{FnScopes, ScopesWithSyntaxMapping, ScopeEntryWithSyntax}; |
16 | 15 | ||
17 | impl Function { | 16 | impl Function { |
18 | pub(crate) fn new(def_id: DefId) -> Function { | ||
19 | Function { def_id } | ||
20 | } | ||
21 | |||
22 | pub(crate) fn body(&self, db: &impl HirDatabase) -> Arc<Body> { | 17 | pub(crate) fn body(&self, db: &impl HirDatabase) -> Arc<Body> { |
23 | db.body_hir(self.def_id) | 18 | db.body_hir(*self) |
24 | } | ||
25 | |||
26 | pub(crate) fn module(&self, db: &impl HirDatabase) -> Module { | ||
27 | self.def_id.module(db) | ||
28 | } | 19 | } |
29 | 20 | ||
30 | /// The containing impl block, if this is a method. | 21 | /// The containing impl block, if this is a method. |
31 | pub(crate) fn impl_block(&self, db: &impl HirDatabase) -> Option<ImplBlock> { | 22 | pub(crate) fn impl_block(&self, db: &impl HirDatabase) -> Option<ImplBlock> { |
32 | self.def_id.impl_block(db) | 23 | let module_impls = db.impls_in_module(self.module(db)); |
24 | ImplBlock::containing(module_impls, (*self).into()) | ||
33 | } | 25 | } |
34 | } | 26 | } |
35 | 27 | ||
36 | impl FnSignature { | 28 | impl FnSignature { |
37 | pub(crate) fn fn_signature_query(db: &impl HirDatabase, def_id: DefId) -> Arc<FnSignature> { | 29 | pub(crate) fn fn_signature_query(db: &impl HirDatabase, func: Function) -> Arc<FnSignature> { |
38 | // FIXME: we're using def_id_to_ast here to avoid returning Cancelable... this is a bit hacky | 30 | let (_, node) = func.source(db); |
39 | let node: TreeArc<ast::FnDef> = def_id_to_ast(db, def_id).1; | ||
40 | let name = node | 31 | let name = node |
41 | .name() | 32 | .name() |
42 | .map(|n| n.as_name()) | 33 | .map(|n| n.as_name()) |
diff --git a/crates/ra_hir/src/code_model_impl/krate.rs b/crates/ra_hir/src/code_model_impl/krate.rs index 8c6e34873..cdd30b402 100644 --- a/crates/ra_hir/src/code_model_impl/krate.rs +++ b/crates/ra_hir/src/code_model_impl/krate.rs | |||
@@ -1,7 +1,7 @@ | |||
1 | use ra_db::CrateId; | 1 | use ra_db::CrateId; |
2 | 2 | ||
3 | use crate::{ | 3 | use crate::{ |
4 | HirFileId, Crate, CrateDependency, AsName, DefLoc, DefKind, Module, SourceItemId, | 4 | Crate, CrateDependency, AsName, Module, |
5 | db::HirDatabase, | 5 | db::HirDatabase, |
6 | }; | 6 | }; |
7 | 7 | ||
@@ -21,27 +21,13 @@ impl Crate { | |||
21 | .collect() | 21 | .collect() |
22 | } | 22 | } |
23 | pub(crate) fn root_module_impl(&self, db: &impl HirDatabase) -> Option<Module> { | 23 | pub(crate) fn root_module_impl(&self, db: &impl HirDatabase) -> Option<Module> { |
24 | let crate_graph = db.crate_graph(); | 24 | let module_tree = db.module_tree(self.crate_id); |
25 | let file_id = crate_graph.crate_root(self.crate_id); | 25 | let module_id = module_tree.modules().next()?; |
26 | let source_root_id = db.file_source_root(file_id); | ||
27 | let file_id = HirFileId::from(file_id); | ||
28 | let module_tree = db.module_tree(source_root_id); | ||
29 | // FIXME: teach module tree about crate roots instead of guessing | ||
30 | let source = SourceItemId { | ||
31 | file_id, | ||
32 | item_id: None, | ||
33 | }; | ||
34 | let module_id = module_tree.find_module_by_source(source)?; | ||
35 | 26 | ||
36 | let def_loc = DefLoc { | 27 | let module = Module { |
37 | kind: DefKind::Module, | 28 | krate: self.crate_id, |
38 | source_root_id, | ||
39 | module_id, | 29 | module_id, |
40 | source_item_id: module_id.source(&module_tree), | ||
41 | }; | 30 | }; |
42 | let def_id = def_loc.id(db); | ||
43 | |||
44 | let module = Module::new(def_id); | ||
45 | Some(module) | 31 | Some(module) |
46 | } | 32 | } |
47 | } | 33 | } |
diff --git a/crates/ra_hir/src/code_model_impl/module.rs b/crates/ra_hir/src/code_model_impl/module.rs index d94079f11..6419d3934 100644 --- a/crates/ra_hir/src/code_model_impl/module.rs +++ b/crates/ra_hir/src/code_model_impl/module.rs | |||
@@ -1,52 +1,33 @@ | |||
1 | use ra_db::{SourceRootId, FileId}; | 1 | use ra_db::FileId; |
2 | use ra_syntax::{ast, SyntaxNode, AstNode, TreeArc}; | 2 | use ra_syntax::{ast, SyntaxNode, TreeArc}; |
3 | 3 | ||
4 | use crate::{ | 4 | use crate::{ |
5 | Module, ModuleSource, Problem, | 5 | Module, ModuleSource, Problem, ModuleDef, |
6 | Crate, DefId, DefLoc, DefKind, Name, Path, PathKind, PerNs, Def, | 6 | Crate, Name, Path, PathKind, PerNs, |
7 | module_tree::ModuleId, | 7 | module_tree::ModuleId, |
8 | nameres::{ModuleScope, lower::ImportId}, | 8 | nameres::{ModuleScope, lower::ImportId}, |
9 | db::HirDatabase, | 9 | db::HirDatabase, |
10 | }; | 10 | }; |
11 | 11 | ||
12 | impl Module { | 12 | impl Module { |
13 | pub(crate) fn new(def_id: DefId) -> Self { | 13 | fn with_module_id(&self, module_id: ModuleId) -> Module { |
14 | crate::code_model_api::Module { def_id } | 14 | Module { |
15 | } | ||
16 | |||
17 | pub(crate) fn from_module_id( | ||
18 | db: &impl HirDatabase, | ||
19 | source_root_id: SourceRootId, | ||
20 | module_id: ModuleId, | ||
21 | ) -> Self { | ||
22 | let module_tree = db.module_tree(source_root_id); | ||
23 | let def_loc = DefLoc { | ||
24 | kind: DefKind::Module, | ||
25 | source_root_id, | ||
26 | module_id, | 15 | module_id, |
27 | source_item_id: module_id.source(&module_tree), | 16 | krate: self.krate, |
28 | }; | 17 | } |
29 | let def_id = def_loc.id(db); | ||
30 | Module::new(def_id) | ||
31 | } | 18 | } |
32 | 19 | ||
33 | pub(crate) fn name_impl(&self, db: &impl HirDatabase) -> Option<Name> { | 20 | pub(crate) fn name_impl(&self, db: &impl HirDatabase) -> Option<Name> { |
34 | let loc = self.def_id.loc(db); | 21 | let module_tree = db.module_tree(self.krate); |
35 | let module_tree = db.module_tree(loc.source_root_id); | 22 | let link = self.module_id.parent_link(&module_tree)?; |
36 | let link = loc.module_id.parent_link(&module_tree)?; | ||
37 | Some(link.name(&module_tree).clone()) | 23 | Some(link.name(&module_tree).clone()) |
38 | } | 24 | } |
39 | 25 | ||
40 | pub(crate) fn definition_source_impl(&self, db: &impl HirDatabase) -> (FileId, ModuleSource) { | 26 | pub(crate) fn definition_source_impl(&self, db: &impl HirDatabase) -> (FileId, ModuleSource) { |
41 | let loc = self.def_id.loc(db); | 27 | let module_tree = db.module_tree(self.krate); |
42 | let file_id = loc.source_item_id.file_id.as_original_file(); | 28 | let source = self.module_id.source(&module_tree); |
43 | let syntax_node = db.file_item(loc.source_item_id); | 29 | let module_source = ModuleSource::from_source_item_id(db, source); |
44 | let module_source = if let Some(source_file) = ast::SourceFile::cast(&syntax_node) { | 30 | let file_id = source.file_id.as_original_file(); |
45 | ModuleSource::SourceFile(source_file.to_owned()) | ||
46 | } else { | ||
47 | let module = ast::Module::cast(&syntax_node).unwrap(); | ||
48 | ModuleSource::Module(module.to_owned()) | ||
49 | }; | ||
50 | (file_id, module_source) | 31 | (file_id, module_source) |
51 | } | 32 | } |
52 | 33 | ||
@@ -54,9 +35,8 @@ impl Module { | |||
54 | &self, | 35 | &self, |
55 | db: &impl HirDatabase, | 36 | db: &impl HirDatabase, |
56 | ) -> Option<(FileId, TreeArc<ast::Module>)> { | 37 | ) -> Option<(FileId, TreeArc<ast::Module>)> { |
57 | let loc = self.def_id.loc(db); | 38 | let module_tree = db.module_tree(self.krate); |
58 | let module_tree = db.module_tree(loc.source_root_id); | 39 | let link = self.module_id.parent_link(&module_tree)?; |
59 | let link = loc.module_id.parent_link(&module_tree)?; | ||
60 | let file_id = link | 40 | let file_id = link |
61 | .owner(&module_tree) | 41 | .owner(&module_tree) |
62 | .source(&module_tree) | 42 | .source(&module_tree) |
@@ -71,85 +51,67 @@ impl Module { | |||
71 | db: &impl HirDatabase, | 51 | db: &impl HirDatabase, |
72 | import: ImportId, | 52 | import: ImportId, |
73 | ) -> TreeArc<ast::PathSegment> { | 53 | ) -> TreeArc<ast::PathSegment> { |
74 | let loc = self.def_id.loc(db); | 54 | let source_map = db.lower_module_source_map(self.clone()); |
75 | let source_map = db.lower_module_source_map(loc.source_root_id, loc.module_id); | ||
76 | let (_, source) = self.definition_source(db); | 55 | let (_, source) = self.definition_source(db); |
77 | source_map.get(&source, import) | 56 | source_map.get(&source, import) |
78 | } | 57 | } |
79 | 58 | ||
80 | pub(crate) fn krate_impl(&self, db: &impl HirDatabase) -> Option<Crate> { | 59 | pub(crate) fn krate_impl(&self, _db: &impl HirDatabase) -> Option<Crate> { |
81 | let root = self.crate_root(db); | 60 | Some(Crate::new(self.krate)) |
82 | let loc = root.def_id.loc(db); | ||
83 | let file_id = loc.source_item_id.file_id.as_original_file(); | ||
84 | |||
85 | let crate_graph = db.crate_graph(); | ||
86 | let crate_id = crate_graph.crate_id_for_crate_root(file_id)?; | ||
87 | Some(Crate::new(crate_id)) | ||
88 | } | 61 | } |
89 | 62 | ||
90 | pub(crate) fn crate_root_impl(&self, db: &impl HirDatabase) -> Module { | 63 | pub(crate) fn crate_root_impl(&self, db: &impl HirDatabase) -> Module { |
91 | let loc = self.def_id.loc(db); | 64 | let module_tree = db.module_tree(self.krate); |
92 | let module_tree = db.module_tree(loc.source_root_id); | 65 | let module_id = self.module_id.crate_root(&module_tree); |
93 | let module_id = loc.module_id.crate_root(&module_tree); | 66 | self.with_module_id(module_id) |
94 | Module::from_module_id(db, loc.source_root_id, module_id) | ||
95 | } | 67 | } |
96 | 68 | ||
97 | /// Finds a child module with the specified name. | 69 | /// Finds a child module with the specified name. |
98 | pub(crate) fn child_impl(&self, db: &impl HirDatabase, name: &Name) -> Option<Module> { | 70 | pub(crate) fn child_impl(&self, db: &impl HirDatabase, name: &Name) -> Option<Module> { |
99 | let loc = self.def_id.loc(db); | 71 | let module_tree = db.module_tree(self.krate); |
100 | let module_tree = db.module_tree(loc.source_root_id); | 72 | let child_id = self.module_id.child(&module_tree, name)?; |
101 | let child_id = loc.module_id.child(&module_tree, name)?; | 73 | Some(self.with_module_id(child_id)) |
102 | Some(Module::from_module_id(db, loc.source_root_id, child_id)) | ||
103 | } | 74 | } |
104 | 75 | ||
105 | /// Iterates over all child modules. | 76 | /// Iterates over all child modules. |
106 | pub(crate) fn children_impl(&self, db: &impl HirDatabase) -> impl Iterator<Item = Module> { | 77 | pub(crate) fn children_impl(&self, db: &impl HirDatabase) -> impl Iterator<Item = Module> { |
107 | // FIXME this should be implementable without collecting into a vec, but | 78 | let module_tree = db.module_tree(self.krate); |
108 | // it's kind of hard since the iterator needs to keep a reference to the | 79 | let children = self |
109 | // module tree. | ||
110 | let loc = self.def_id.loc(db); | ||
111 | let module_tree = db.module_tree(loc.source_root_id); | ||
112 | let children = loc | ||
113 | .module_id | 80 | .module_id |
114 | .children(&module_tree) | 81 | .children(&module_tree) |
115 | .map(|(_, module_id)| Module::from_module_id(db, loc.source_root_id, module_id)) | 82 | .map(|(_, module_id)| self.with_module_id(module_id)) |
116 | .collect::<Vec<_>>(); | 83 | .collect::<Vec<_>>(); |
117 | children.into_iter() | 84 | children.into_iter() |
118 | } | 85 | } |
119 | 86 | ||
120 | pub(crate) fn parent_impl(&self, db: &impl HirDatabase) -> Option<Module> { | 87 | pub(crate) fn parent_impl(&self, db: &impl HirDatabase) -> Option<Module> { |
121 | let loc = self.def_id.loc(db); | 88 | let module_tree = db.module_tree(self.krate); |
122 | let module_tree = db.module_tree(loc.source_root_id); | 89 | let parent_id = self.module_id.parent(&module_tree)?; |
123 | let parent_id = loc.module_id.parent(&module_tree)?; | 90 | Some(self.with_module_id(parent_id)) |
124 | Some(Module::from_module_id(db, loc.source_root_id, parent_id)) | ||
125 | } | 91 | } |
126 | 92 | ||
127 | /// Returns a `ModuleScope`: a set of items, visible in this module. | 93 | /// Returns a `ModuleScope`: a set of items, visible in this module. |
128 | pub(crate) fn scope_impl(&self, db: &impl HirDatabase) -> ModuleScope { | 94 | pub(crate) fn scope_impl(&self, db: &impl HirDatabase) -> ModuleScope { |
129 | let loc = self.def_id.loc(db); | 95 | let item_map = db.item_map(self.krate); |
130 | let item_map = db.item_map(loc.source_root_id); | 96 | item_map.per_module[&self.module_id].clone() |
131 | item_map.per_module[&loc.module_id].clone() | ||
132 | } | 97 | } |
133 | 98 | ||
134 | pub(crate) fn resolve_path_impl(&self, db: &impl HirDatabase, path: &Path) -> PerNs<DefId> { | 99 | pub(crate) fn resolve_path_impl(&self, db: &impl HirDatabase, path: &Path) -> PerNs<ModuleDef> { |
135 | let mut curr_per_ns = PerNs::types( | 100 | let mut curr_per_ns: PerNs<ModuleDef> = PerNs::types(match path.kind { |
136 | match path.kind { | 101 | PathKind::Crate => self.crate_root(db).into(), |
137 | PathKind::Crate => self.crate_root(db), | 102 | PathKind::Self_ | PathKind::Plain => self.clone().into(), |
138 | PathKind::Self_ | PathKind::Plain => self.clone(), | 103 | PathKind::Super => { |
139 | PathKind::Super => { | 104 | if let Some(p) = self.parent(db) { |
140 | if let Some(p) = self.parent(db) { | 105 | p.into() |
141 | p | 106 | } else { |
142 | } else { | ||
143 | return PerNs::none(); | ||
144 | } | ||
145 | } | ||
146 | PathKind::Abs => { | ||
147 | // TODO: absolute use is not supported | ||
148 | return PerNs::none(); | 107 | return PerNs::none(); |
149 | } | 108 | } |
150 | } | 109 | } |
151 | .def_id, | 110 | PathKind::Abs => { |
152 | ); | 111 | // TODO: absolute use is not supported |
112 | return PerNs::none(); | ||
113 | } | ||
114 | }); | ||
153 | 115 | ||
154 | for segment in path.segments.iter() { | 116 | for segment in path.segments.iter() { |
155 | let curr = match curr_per_ns.as_ref().take_types() { | 117 | let curr = match curr_per_ns.as_ref().take_types() { |
@@ -164,15 +126,16 @@ impl Module { | |||
164 | } | 126 | } |
165 | }; | 127 | }; |
166 | // resolve segment in curr | 128 | // resolve segment in curr |
167 | curr_per_ns = match curr.resolve(db) { | 129 | |
168 | Def::Module(m) => { | 130 | curr_per_ns = match curr { |
131 | ModuleDef::Module(m) => { | ||
169 | let scope = m.scope(db); | 132 | let scope = m.scope(db); |
170 | match scope.get(&segment.name) { | 133 | match scope.get(&segment.name) { |
171 | Some(r) => r.def_id, | 134 | Some(r) => r.def_id.clone(), |
172 | None => PerNs::none(), | 135 | None => PerNs::none(), |
173 | } | 136 | } |
174 | } | 137 | } |
175 | Def::Enum(e) => { | 138 | ModuleDef::Enum(e) => { |
176 | // enum variant | 139 | // enum variant |
177 | let matching_variant = e | 140 | let matching_variant = e |
178 | .variants(db) | 141 | .variants(db) |
@@ -180,7 +143,7 @@ impl Module { | |||
180 | .find(|(n, _variant)| n == &segment.name); | 143 | .find(|(n, _variant)| n == &segment.name); |
181 | 144 | ||
182 | match matching_variant { | 145 | match matching_variant { |
183 | Some((_n, variant)) => PerNs::both(variant.def_id(), e.def_id()), | 146 | Some((_n, variant)) => PerNs::both(variant.into(), (*e).into()), |
184 | None => PerNs::none(), | 147 | None => PerNs::none(), |
185 | } | 148 | } |
186 | } | 149 | } |
@@ -199,8 +162,7 @@ impl Module { | |||
199 | &self, | 162 | &self, |
200 | db: &impl HirDatabase, | 163 | db: &impl HirDatabase, |
201 | ) -> Vec<(TreeArc<SyntaxNode>, Problem)> { | 164 | ) -> Vec<(TreeArc<SyntaxNode>, Problem)> { |
202 | let loc = self.def_id.loc(db); | 165 | let module_tree = db.module_tree(self.krate); |
203 | let module_tree = db.module_tree(loc.source_root_id); | 166 | self.module_id.problems(&module_tree, db) |
204 | loc.module_id.problems(&module_tree, db) | ||
205 | } | 167 | } |
206 | } | 168 | } |
diff --git a/crates/ra_hir/src/db.rs b/crates/ra_hir/src/db.rs index cc03da1e2..5304f5d31 100644 --- a/crates/ra_hir/src/db.rs +++ b/crates/ra_hir/src/db.rs | |||
@@ -1,20 +1,21 @@ | |||
1 | use std::sync::Arc; | 1 | use std::sync::Arc; |
2 | 2 | ||
3 | use ra_syntax::{SyntaxNode, TreeArc, SourceFile}; | 3 | use ra_syntax::{SyntaxNode, TreeArc, SourceFile}; |
4 | use ra_db::{SourceRootId, SyntaxDatabase, salsa}; | 4 | use ra_db::{SyntaxDatabase, CrateId, salsa}; |
5 | 5 | ||
6 | use crate::{ | 6 | use crate::{ |
7 | HirInterner, DefId, MacroCallId, Name, HirFileId, | 7 | MacroCallId, Name, HirFileId, |
8 | SourceFileItems, SourceItemId, Crate, | 8 | SourceFileItems, SourceItemId, Crate, Module, HirInterner, |
9 | query_definitions, | 9 | query_definitions, |
10 | FnSignature, FnScopes, | 10 | Function, FnSignature, FnScopes, |
11 | Struct, Enum, EnumVariant, | ||
11 | macros::MacroExpansion, | 12 | macros::MacroExpansion, |
12 | module_tree::{ModuleId, ModuleTree}, | 13 | module_tree::ModuleTree, |
13 | nameres::{ItemMap, lower::{LoweredModule, ImportSourceMap}}, | 14 | nameres::{ItemMap, lower::{LoweredModule, ImportSourceMap}}, |
14 | ty::{InferenceResult, Ty, method_resolution::CrateImplBlocks}, | 15 | ty::{InferenceResult, Ty, method_resolution::CrateImplBlocks, TypableDef, VariantDef}, |
15 | adt::{StructData, EnumData, EnumVariantData}, | 16 | adt::{StructData, EnumData, EnumVariantData}, |
16 | impl_block::ModuleImplBlocks, | 17 | impl_block::ModuleImplBlocks, |
17 | generics::GenericParams, | 18 | generics::{GenericParams, GenericDef}, |
18 | }; | 19 | }; |
19 | 20 | ||
20 | #[salsa::query_group] | 21 | #[salsa::query_group] |
@@ -26,25 +27,25 @@ pub trait HirDatabase: SyntaxDatabase + AsRef<HirInterner> { | |||
26 | fn expand_macro_invocation(&self, invoc: MacroCallId) -> Option<Arc<MacroExpansion>>; | 27 | fn expand_macro_invocation(&self, invoc: MacroCallId) -> Option<Arc<MacroExpansion>>; |
27 | 28 | ||
28 | #[salsa::invoke(query_definitions::fn_scopes)] | 29 | #[salsa::invoke(query_definitions::fn_scopes)] |
29 | fn fn_scopes(&self, def_id: DefId) -> Arc<FnScopes>; | 30 | fn fn_scopes(&self, func: Function) -> Arc<FnScopes>; |
30 | 31 | ||
31 | #[salsa::invoke(crate::adt::StructData::struct_data_query)] | 32 | #[salsa::invoke(crate::adt::StructData::struct_data_query)] |
32 | fn struct_data(&self, def_id: DefId) -> Arc<StructData>; | 33 | fn struct_data(&self, s: Struct) -> Arc<StructData>; |
33 | 34 | ||
34 | #[salsa::invoke(crate::adt::EnumData::enum_data_query)] | 35 | #[salsa::invoke(crate::adt::EnumData::enum_data_query)] |
35 | fn enum_data(&self, def_id: DefId) -> Arc<EnumData>; | 36 | fn enum_data(&self, e: Enum) -> Arc<EnumData>; |
36 | 37 | ||
37 | #[salsa::invoke(crate::adt::EnumVariantData::enum_variant_data_query)] | 38 | #[salsa::invoke(crate::adt::EnumVariantData::enum_variant_data_query)] |
38 | fn enum_variant_data(&self, def_id: DefId) -> Arc<EnumVariantData>; | 39 | fn enum_variant_data(&self, var: EnumVariant) -> Arc<EnumVariantData>; |
39 | 40 | ||
40 | #[salsa::invoke(crate::ty::infer)] | 41 | #[salsa::invoke(crate::ty::infer)] |
41 | fn infer(&self, def_id: DefId) -> Arc<InferenceResult>; | 42 | fn infer(&self, func: Function) -> Arc<InferenceResult>; |
42 | 43 | ||
43 | #[salsa::invoke(crate::ty::type_for_def)] | 44 | #[salsa::invoke(crate::ty::type_for_def)] |
44 | fn type_for_def(&self, def_id: DefId) -> Ty; | 45 | fn type_for_def(&self, def: TypableDef) -> Ty; |
45 | 46 | ||
46 | #[salsa::invoke(crate::ty::type_for_field)] | 47 | #[salsa::invoke(crate::ty::type_for_field)] |
47 | fn type_for_field(&self, def_id: DefId, field: Name) -> Option<Ty>; | 48 | fn type_for_field(&self, def: VariantDef, field: Name) -> Option<Ty>; |
48 | 49 | ||
49 | #[salsa::invoke(query_definitions::file_items)] | 50 | #[salsa::invoke(query_definitions::file_items)] |
50 | fn file_items(&self, file_id: HirFileId) -> Arc<SourceFileItems>; | 51 | fn file_items(&self, file_id: HirFileId) -> Arc<SourceFileItems>; |
@@ -56,51 +57,35 @@ pub trait HirDatabase: SyntaxDatabase + AsRef<HirInterner> { | |||
56 | fn submodules(&self, source: SourceItemId) -> Arc<Vec<crate::module_tree::Submodule>>; | 57 | fn submodules(&self, source: SourceItemId) -> Arc<Vec<crate::module_tree::Submodule>>; |
57 | 58 | ||
58 | #[salsa::invoke(crate::nameres::lower::LoweredModule::lower_module_query)] | 59 | #[salsa::invoke(crate::nameres::lower::LoweredModule::lower_module_query)] |
59 | fn lower_module( | 60 | fn lower_module(&self, module: Module) -> (Arc<LoweredModule>, Arc<ImportSourceMap>); |
60 | &self, | ||
61 | source_root_id: SourceRootId, | ||
62 | module_id: ModuleId, | ||
63 | ) -> (Arc<LoweredModule>, Arc<ImportSourceMap>); | ||
64 | 61 | ||
65 | #[salsa::invoke(crate::nameres::lower::LoweredModule::lower_module_module_query)] | 62 | #[salsa::invoke(crate::nameres::lower::LoweredModule::lower_module_module_query)] |
66 | fn lower_module_module( | 63 | fn lower_module_module(&self, module: Module) -> Arc<LoweredModule>; |
67 | &self, | ||
68 | source_root_id: SourceRootId, | ||
69 | module_id: ModuleId, | ||
70 | ) -> Arc<LoweredModule>; | ||
71 | 64 | ||
72 | #[salsa::invoke(crate::nameres::lower::LoweredModule::lower_module_source_map_query)] | 65 | #[salsa::invoke(crate::nameres::lower::LoweredModule::lower_module_source_map_query)] |
73 | fn lower_module_source_map( | 66 | fn lower_module_source_map(&self, module: Module) -> Arc<ImportSourceMap>; |
74 | &self, | ||
75 | source_root_id: SourceRootId, | ||
76 | module_id: ModuleId, | ||
77 | ) -> Arc<ImportSourceMap>; | ||
78 | 67 | ||
79 | #[salsa::invoke(query_definitions::item_map)] | 68 | #[salsa::invoke(query_definitions::item_map)] |
80 | fn item_map(&self, source_root_id: SourceRootId) -> Arc<ItemMap>; | 69 | fn item_map(&self, crate_id: CrateId) -> Arc<ItemMap>; |
81 | 70 | ||
82 | #[salsa::invoke(crate::module_tree::ModuleTree::module_tree_query)] | 71 | #[salsa::invoke(crate::module_tree::ModuleTree::module_tree_query)] |
83 | fn module_tree(&self, source_root_id: SourceRootId) -> Arc<ModuleTree>; | 72 | fn module_tree(&self, crate_id: CrateId) -> Arc<ModuleTree>; |
84 | 73 | ||
85 | #[salsa::invoke(crate::impl_block::impls_in_module)] | 74 | #[salsa::invoke(crate::impl_block::impls_in_module)] |
86 | fn impls_in_module( | 75 | fn impls_in_module(&self, module: Module) -> Arc<ModuleImplBlocks>; |
87 | &self, | ||
88 | source_root_id: SourceRootId, | ||
89 | module_id: ModuleId, | ||
90 | ) -> Arc<ModuleImplBlocks>; | ||
91 | 76 | ||
92 | #[salsa::invoke(crate::ty::method_resolution::CrateImplBlocks::impls_in_crate_query)] | 77 | #[salsa::invoke(crate::ty::method_resolution::CrateImplBlocks::impls_in_crate_query)] |
93 | fn impls_in_crate(&self, krate: Crate) -> Arc<CrateImplBlocks>; | 78 | fn impls_in_crate(&self, krate: Crate) -> Arc<CrateImplBlocks>; |
94 | 79 | ||
95 | #[salsa::invoke(crate::expr::body_hir)] | 80 | #[salsa::invoke(crate::expr::body_hir)] |
96 | fn body_hir(&self, def_id: DefId) -> Arc<crate::expr::Body>; | 81 | fn body_hir(&self, func: Function) -> Arc<crate::expr::Body>; |
97 | 82 | ||
98 | #[salsa::invoke(crate::expr::body_syntax_mapping)] | 83 | #[salsa::invoke(crate::expr::body_syntax_mapping)] |
99 | fn body_syntax_mapping(&self, def_id: DefId) -> Arc<crate::expr::BodySyntaxMapping>; | 84 | fn body_syntax_mapping(&self, func: Function) -> Arc<crate::expr::BodySyntaxMapping>; |
100 | 85 | ||
101 | #[salsa::invoke(crate::generics::GenericParams::generic_params_query)] | 86 | #[salsa::invoke(crate::generics::GenericParams::generic_params_query)] |
102 | fn generic_params(&self, def_id: DefId) -> Arc<GenericParams>; | 87 | fn generic_params(&self, def: GenericDef) -> Arc<GenericParams>; |
103 | 88 | ||
104 | #[salsa::invoke(crate::FnSignature::fn_signature_query)] | 89 | #[salsa::invoke(crate::FnSignature::fn_signature_query)] |
105 | fn fn_signature(&self, def_id: DefId) -> Arc<FnSignature>; | 90 | fn fn_signature(&self, func: Function) -> Arc<FnSignature>; |
106 | } | 91 | } |
diff --git a/crates/ra_hir/src/expr.rs b/crates/ra_hir/src/expr.rs index 1a3821692..29469af2c 100644 --- a/crates/ra_hir/src/expr.rs +++ b/crates/ra_hir/src/expr.rs | |||
@@ -9,7 +9,11 @@ use ra_syntax::{ | |||
9 | ast::{self, LoopBodyOwner, ArgListOwner, NameOwner, LiteralFlavor} | 9 | ast::{self, LoopBodyOwner, ArgListOwner, NameOwner, LiteralFlavor} |
10 | }; | 10 | }; |
11 | 11 | ||
12 | use crate::{Path, type_ref::{Mutability, TypeRef}, Name, HirDatabase, DefId, Def, name::AsName}; | 12 | use crate::{ |
13 | Path, Name, HirDatabase, Function, | ||
14 | name::AsName, | ||
15 | type_ref::{Mutability, TypeRef}, | ||
16 | }; | ||
13 | use crate::ty::primitive::{UintTy, UncertainIntTy, UncertainFloatTy}; | 17 | use crate::ty::primitive::{UintTy, UncertainIntTy, UncertainFloatTy}; |
14 | 18 | ||
15 | #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] | 19 | #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] |
@@ -435,8 +439,8 @@ impl Pat { | |||
435 | 439 | ||
436 | // Queries | 440 | // Queries |
437 | 441 | ||
438 | pub(crate) fn body_hir(db: &impl HirDatabase, def_id: DefId) -> Arc<Body> { | 442 | pub(crate) fn body_hir(db: &impl HirDatabase, func: Function) -> Arc<Body> { |
439 | Arc::clone(&body_syntax_mapping(db, def_id).body) | 443 | Arc::clone(&body_syntax_mapping(db, func).body) |
440 | } | 444 | } |
441 | 445 | ||
442 | struct ExprCollector { | 446 | struct ExprCollector { |
@@ -955,14 +959,8 @@ pub(crate) fn collect_fn_body_syntax(node: &ast::FnDef) -> BodySyntaxMapping { | |||
955 | collector.into_body_syntax_mapping(params, body) | 959 | collector.into_body_syntax_mapping(params, body) |
956 | } | 960 | } |
957 | 961 | ||
958 | pub(crate) fn body_syntax_mapping(db: &impl HirDatabase, def_id: DefId) -> Arc<BodySyntaxMapping> { | 962 | pub(crate) fn body_syntax_mapping(db: &impl HirDatabase, func: Function) -> Arc<BodySyntaxMapping> { |
959 | let def = def_id.resolve(db); | 963 | let (_, fn_def) = func.source(db); |
960 | 964 | let body_syntax_mapping = collect_fn_body_syntax(&fn_def); | |
961 | let body_syntax_mapping = match def { | ||
962 | Def::Function(f) => collect_fn_body_syntax(&f.source(db).1), | ||
963 | // TODO: consts, etc. | ||
964 | _ => panic!("Trying to get body for item type without body"), | ||
965 | }; | ||
966 | |||
967 | Arc::new(body_syntax_mapping) | 965 | Arc::new(body_syntax_mapping) |
968 | } | 966 | } |
diff --git a/crates/ra_hir/src/generics.rs b/crates/ra_hir/src/generics.rs index d8248ad49..64c20a462 100644 --- a/crates/ra_hir/src/generics.rs +++ b/crates/ra_hir/src/generics.rs | |||
@@ -5,9 +5,9 @@ | |||
5 | 5 | ||
6 | use std::sync::Arc; | 6 | use std::sync::Arc; |
7 | 7 | ||
8 | use ra_syntax::ast::{TypeParamList, AstNode, NameOwner}; | 8 | use ra_syntax::ast::{self, NameOwner, TypeParamsOwner}; |
9 | 9 | ||
10 | use crate::{db::HirDatabase, DefId, Name, AsName}; | 10 | use crate::{db::HirDatabase, 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)] |
@@ -22,26 +22,53 @@ pub struct GenericParams { | |||
22 | pub(crate) params: Vec<GenericParam>, | 22 | pub(crate) params: Vec<GenericParam>, |
23 | } | 23 | } |
24 | 24 | ||
25 | #[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)] | ||
26 | pub enum GenericDef { | ||
27 | Function(Function), | ||
28 | Struct(Struct), | ||
29 | Enum(Enum), | ||
30 | Trait(Trait), | ||
31 | Type(Type), | ||
32 | } | ||
33 | impl_froms!(GenericDef: Function, Struct, Enum, Trait, Type); | ||
34 | |||
25 | impl GenericParams { | 35 | impl GenericParams { |
26 | pub(crate) fn generic_params_query(db: &impl HirDatabase, def_id: DefId) -> Arc<GenericParams> { | 36 | pub(crate) fn generic_params_query( |
27 | let (_file_id, node) = def_id.source(db); | 37 | db: &impl HirDatabase, |
38 | def: GenericDef, | ||
39 | ) -> Arc<GenericParams> { | ||
28 | let mut generics = GenericParams::default(); | 40 | let mut generics = GenericParams::default(); |
29 | if let Some(type_param_list) = node.children().find_map(TypeParamList::cast) { | 41 | match def { |
30 | for (idx, type_param) in type_param_list.type_params().enumerate() { | 42 | GenericDef::Function(it) => generics.fill(&*it.source(db).1), |
31 | let name = type_param | 43 | GenericDef::Struct(it) => generics.fill(&*it.source(db).1), |
32 | .name() | 44 | GenericDef::Enum(it) => generics.fill(&*it.source(db).1), |
33 | .map(AsName::as_name) | 45 | GenericDef::Trait(it) => generics.fill(&*it.source(db).1), |
34 | .unwrap_or_else(Name::missing); | 46 | GenericDef::Type(it) => generics.fill(&*it.source(db).1), |
35 | let param = GenericParam { | ||
36 | idx: idx as u32, | ||
37 | name, | ||
38 | }; | ||
39 | generics.params.push(param); | ||
40 | } | ||
41 | } | 47 | } |
48 | |||
42 | Arc::new(generics) | 49 | Arc::new(generics) |
43 | } | 50 | } |
44 | 51 | ||
52 | fn fill(&mut self, node: &impl TypeParamsOwner) { | ||
53 | if let Some(params) = node.type_param_list() { | ||
54 | self.fill_params(params) | ||
55 | } | ||
56 | } | ||
57 | |||
58 | fn fill_params(&mut self, params: &ast::TypeParamList) { | ||
59 | for (idx, type_param) in params.type_params().enumerate() { | ||
60 | let name = type_param | ||
61 | .name() | ||
62 | .map(AsName::as_name) | ||
63 | .unwrap_or_else(Name::missing); | ||
64 | let param = GenericParam { | ||
65 | idx: idx as u32, | ||
66 | name, | ||
67 | }; | ||
68 | self.params.push(param); | ||
69 | } | ||
70 | } | ||
71 | |||
45 | pub(crate) fn find_by_name(&self, name: &Name) -> Option<&GenericParam> { | 72 | pub(crate) fn find_by_name(&self, name: &Name) -> Option<&GenericParam> { |
46 | self.params.iter().find(|p| &p.name == name) | 73 | self.params.iter().find(|p| &p.name == name) |
47 | } | 74 | } |
diff --git a/crates/ra_hir/src/ids.rs b/crates/ra_hir/src/ids.rs index 43f0e81f9..b125a1518 100644 --- a/crates/ra_hir/src/ids.rs +++ b/crates/ra_hir/src/ids.rs | |||
@@ -1,22 +1,41 @@ | |||
1 | use ra_db::{SourceRootId, LocationIntener, FileId}; | 1 | use std::{ |
2 | marker::PhantomData, | ||
3 | hash::{Hash, Hasher}, | ||
4 | }; | ||
5 | |||
6 | use ra_db::{LocationIntener, FileId}; | ||
2 | use ra_syntax::{TreeArc, SyntaxNode, SourceFile, AstNode, ast}; | 7 | use ra_syntax::{TreeArc, SyntaxNode, SourceFile, AstNode, ast}; |
3 | use ra_arena::{Arena, RawId, impl_arena_id}; | 8 | use ra_arena::{Arena, RawId, ArenaId, impl_arena_id}; |
4 | 9 | ||
5 | use crate::{ | 10 | use crate::{ |
6 | HirDatabase, Def, Function, Struct, Enum, EnumVariant, ImplBlock, Crate, | 11 | HirDatabase, |
7 | Module, Trait, Type, Static, Const, | 12 | Module, |
8 | module_tree::ModuleId, | ||
9 | }; | 13 | }; |
10 | 14 | ||
11 | #[derive(Debug, Default)] | 15 | #[derive(Debug, Default)] |
12 | pub struct HirInterner { | 16 | pub struct HirInterner { |
13 | defs: LocationIntener<DefLoc, DefId>, | ||
14 | macros: LocationIntener<MacroCallLoc, MacroCallId>, | 17 | macros: LocationIntener<MacroCallLoc, MacroCallId>, |
18 | fns: LocationIntener<ItemLoc<ast::FnDef>, FunctionId>, | ||
19 | structs: LocationIntener<ItemLoc<ast::StructDef>, StructId>, | ||
20 | enums: LocationIntener<ItemLoc<ast::EnumDef>, EnumId>, | ||
21 | enum_variants: LocationIntener<ItemLoc<ast::EnumVariant>, EnumVariantId>, | ||
22 | consts: LocationIntener<ItemLoc<ast::ConstDef>, ConstId>, | ||
23 | statics: LocationIntener<ItemLoc<ast::StaticDef>, StaticId>, | ||
24 | traits: LocationIntener<ItemLoc<ast::TraitDef>, TraitId>, | ||
25 | types: LocationIntener<ItemLoc<ast::TypeDef>, TypeId>, | ||
15 | } | 26 | } |
16 | 27 | ||
17 | impl HirInterner { | 28 | impl HirInterner { |
18 | pub fn len(&self) -> usize { | 29 | pub fn len(&self) -> usize { |
19 | self.defs.len() + self.macros.len() | 30 | self.macros.len() |
31 | + self.fns.len() | ||
32 | + self.structs.len() | ||
33 | + self.enums.len() | ||
34 | + self.enum_variants.len() | ||
35 | + self.consts.len() | ||
36 | + self.statics.len() | ||
37 | + self.traits.len() | ||
38 | + self.types.len() | ||
20 | } | 39 | } |
21 | } | 40 | } |
22 | 41 | ||
@@ -110,10 +129,9 @@ impl From<MacroCallId> for HirFileId { | |||
110 | pub struct MacroCallId(RawId); | 129 | pub struct MacroCallId(RawId); |
111 | impl_arena_id!(MacroCallId); | 130 | impl_arena_id!(MacroCallId); |
112 | 131 | ||
113 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | 132 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] |
114 | pub struct MacroCallLoc { | 133 | pub struct MacroCallLoc { |
115 | pub(crate) source_root_id: SourceRootId, | 134 | pub(crate) module: Module, |
116 | pub(crate) module_id: ModuleId, | ||
117 | pub(crate) source_item_id: SourceItemId, | 135 | pub(crate) source_item_id: SourceItemId, |
118 | } | 136 | } |
119 | 137 | ||
@@ -130,117 +148,161 @@ impl MacroCallLoc { | |||
130 | } | 148 | } |
131 | } | 149 | } |
132 | 150 | ||
133 | /// Def's are a core concept of hir. A `Def` is an Item (function, module, etc) | 151 | #[derive(Debug)] |
134 | /// in a specific module. | 152 | pub struct ItemLoc<N: AstNode> { |
135 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | 153 | pub(crate) module: Module, |
136 | pub struct DefId(RawId); | 154 | raw: SourceItemId, |
137 | impl_arena_id!(DefId); | 155 | _ty: PhantomData<N>, |
138 | |||
139 | #[derive(Clone, Debug, PartialEq, Eq, Hash)] | ||
140 | pub struct DefLoc { | ||
141 | pub(crate) kind: DefKind, | ||
142 | pub(crate) source_root_id: SourceRootId, | ||
143 | pub(crate) module_id: ModuleId, | ||
144 | pub(crate) source_item_id: SourceItemId, | ||
145 | } | 156 | } |
146 | 157 | ||
147 | #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] | 158 | impl<N: AstNode> PartialEq for ItemLoc<N> { |
148 | pub(crate) enum DefKind { | 159 | fn eq(&self, other: &Self) -> bool { |
149 | Module, | 160 | self.module == other.module && self.raw == other.raw |
150 | Function, | 161 | } |
151 | Struct, | 162 | } |
152 | Enum, | 163 | impl<N: AstNode> Eq for ItemLoc<N> {} |
153 | EnumVariant, | 164 | impl<N: AstNode> Hash for ItemLoc<N> { |
154 | Const, | 165 | fn hash<H: Hasher>(&self, hasher: &mut H) { |
155 | Static, | 166 | self.module.hash(hasher); |
156 | Trait, | 167 | self.raw.hash(hasher); |
157 | Type, | 168 | } |
158 | Item, | ||
159 | |||
160 | /// The constructor of a struct. E.g. if we have `struct Foo(usize)`, the | ||
161 | /// name `Foo` needs to resolve to different types depending on whether we | ||
162 | /// are in the types or values namespace: As a type, `Foo` of course refers | ||
163 | /// to the struct `Foo`; as a value, `Foo` is a callable type with signature | ||
164 | /// `(usize) -> Foo`. The cleanest approach to handle this seems to be to | ||
165 | /// have different defs in the two namespaces. | ||
166 | /// | ||
167 | /// rustc does the same; note that it even creates a struct constructor if | ||
168 | /// the struct isn't a tuple struct (see `CtorKind::Fictive` in rustc). | ||
169 | StructCtor, | ||
170 | } | 169 | } |
171 | 170 | ||
172 | impl DefId { | 171 | impl<N: AstNode> Clone for ItemLoc<N> { |
173 | pub(crate) fn loc(self, db: &impl AsRef<HirInterner>) -> DefLoc { | 172 | fn clone(&self) -> ItemLoc<N> { |
174 | db.as_ref().defs.id2loc(self) | 173 | ItemLoc { |
174 | module: self.module, | ||
175 | raw: self.raw, | ||
176 | _ty: PhantomData, | ||
177 | } | ||
175 | } | 178 | } |
179 | } | ||
176 | 180 | ||
177 | pub fn resolve(self, db: &impl HirDatabase) -> Def { | 181 | #[derive(Clone, Copy)] |
178 | let loc = self.loc(db); | 182 | pub(crate) struct LocationCtx<DB> { |
179 | match loc.kind { | 183 | db: DB, |
180 | DefKind::Module => { | 184 | module: Module, |
181 | let module = Module::from_module_id(db, loc.source_root_id, loc.module_id); | 185 | file_id: HirFileId, |
182 | Def::Module(module) | 186 | } |
183 | } | ||
184 | DefKind::Function => { | ||
185 | let function = Function::new(self); | ||
186 | Def::Function(function) | ||
187 | } | ||
188 | DefKind::Struct => { | ||
189 | let struct_def = Struct::new(self); | ||
190 | Def::Struct(struct_def) | ||
191 | } | ||
192 | DefKind::Enum => Def::Enum(Enum::new(self)), | ||
193 | DefKind::EnumVariant => Def::EnumVariant(EnumVariant::new(self)), | ||
194 | DefKind::Const => { | ||
195 | let def = Const::new(self); | ||
196 | Def::Const(def) | ||
197 | } | ||
198 | DefKind::Static => { | ||
199 | let def = Static::new(self); | ||
200 | Def::Static(def) | ||
201 | } | ||
202 | DefKind::Trait => { | ||
203 | let def = Trait::new(self); | ||
204 | Def::Trait(def) | ||
205 | } | ||
206 | DefKind::Type => { | ||
207 | let def = Type::new(self); | ||
208 | Def::Type(def) | ||
209 | } | ||
210 | 187 | ||
211 | DefKind::StructCtor => Def::Item, | 188 | impl<'a, DB: HirDatabase> LocationCtx<&'a DB> { |
212 | DefKind::Item => Def::Item, | 189 | pub(crate) fn new(db: &'a DB, module: Module, file_id: HirFileId) -> LocationCtx<&'a DB> { |
190 | LocationCtx { | ||
191 | db, | ||
192 | module, | ||
193 | file_id, | ||
213 | } | 194 | } |
214 | } | 195 | } |
196 | pub(crate) fn to_def<N, DEF>(self, ast: &N) -> DEF | ||
197 | where | ||
198 | N: AstNode, | ||
199 | DEF: AstItemDef<N>, | ||
200 | { | ||
201 | DEF::from_ast(self, ast) | ||
202 | } | ||
203 | } | ||
204 | |||
205 | pub(crate) trait AstItemDef<N: AstNode>: ArenaId + Clone { | ||
206 | fn interner(interner: &HirInterner) -> &LocationIntener<ItemLoc<N>, Self>; | ||
207 | fn from_ast(ctx: LocationCtx<&impl HirDatabase>, ast: &N) -> Self { | ||
208 | let items = ctx.db.file_items(ctx.file_id); | ||
209 | let raw = SourceItemId { | ||
210 | file_id: ctx.file_id, | ||
211 | item_id: Some(items.id_of(ctx.file_id, ast.syntax())), | ||
212 | }; | ||
213 | let loc = ItemLoc { | ||
214 | module: ctx.module, | ||
215 | raw, | ||
216 | _ty: PhantomData, | ||
217 | }; | ||
218 | |||
219 | Self::interner(ctx.db.as_ref()).loc2id(&loc) | ||
220 | } | ||
221 | fn source(self, db: &impl HirDatabase) -> (HirFileId, TreeArc<N>) { | ||
222 | let int = Self::interner(db.as_ref()); | ||
223 | let loc = int.id2loc(self); | ||
224 | let syntax = db.file_item(loc.raw); | ||
225 | let ast = N::cast(&syntax) | ||
226 | .unwrap_or_else(|| panic!("invalid ItemLoc: {:?}", loc.raw)) | ||
227 | .to_owned(); | ||
228 | (loc.raw.file_id, ast) | ||
229 | } | ||
230 | fn module(self, db: &impl HirDatabase) -> Module { | ||
231 | let int = Self::interner(db.as_ref()); | ||
232 | let loc = int.id2loc(self); | ||
233 | loc.module | ||
234 | } | ||
235 | } | ||
236 | |||
237 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | ||
238 | pub struct FunctionId(RawId); | ||
239 | impl_arena_id!(FunctionId); | ||
240 | impl AstItemDef<ast::FnDef> for FunctionId { | ||
241 | fn interner(interner: &HirInterner) -> &LocationIntener<ItemLoc<ast::FnDef>, Self> { | ||
242 | &interner.fns | ||
243 | } | ||
244 | } | ||
245 | |||
246 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | ||
247 | pub struct StructId(RawId); | ||
248 | impl_arena_id!(StructId); | ||
249 | impl AstItemDef<ast::StructDef> for StructId { | ||
250 | fn interner(interner: &HirInterner) -> &LocationIntener<ItemLoc<ast::StructDef>, Self> { | ||
251 | &interner.structs | ||
252 | } | ||
253 | } | ||
215 | 254 | ||
216 | pub(crate) fn source(self, db: &impl HirDatabase) -> (HirFileId, TreeArc<SyntaxNode>) { | 255 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] |
217 | let loc = self.loc(db); | 256 | pub struct EnumId(RawId); |
218 | let syntax = db.file_item(loc.source_item_id); | 257 | impl_arena_id!(EnumId); |
219 | (loc.source_item_id.file_id, syntax) | 258 | impl AstItemDef<ast::EnumDef> for EnumId { |
259 | fn interner(interner: &HirInterner) -> &LocationIntener<ItemLoc<ast::EnumDef>, Self> { | ||
260 | &interner.enums | ||
220 | } | 261 | } |
262 | } | ||
221 | 263 | ||
222 | /// For a module, returns that module; for any other def, returns the containing module. | 264 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] |
223 | pub fn module(self, db: &impl HirDatabase) -> Module { | 265 | pub struct EnumVariantId(RawId); |
224 | let loc = self.loc(db); | 266 | impl_arena_id!(EnumVariantId); |
225 | Module::from_module_id(db, loc.source_root_id, loc.module_id) | 267 | impl AstItemDef<ast::EnumVariant> for EnumVariantId { |
268 | fn interner(interner: &HirInterner) -> &LocationIntener<ItemLoc<ast::EnumVariant>, Self> { | ||
269 | &interner.enum_variants | ||
226 | } | 270 | } |
271 | } | ||
227 | 272 | ||
228 | /// Returns the containing crate. | 273 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] |
229 | pub fn krate(&self, db: &impl HirDatabase) -> Option<Crate> { | 274 | pub struct ConstId(RawId); |
230 | self.module(db).krate(db) | 275 | impl_arena_id!(ConstId); |
276 | impl AstItemDef<ast::ConstDef> for ConstId { | ||
277 | fn interner(interner: &HirInterner) -> &LocationIntener<ItemLoc<ast::ConstDef>, Self> { | ||
278 | &interner.consts | ||
231 | } | 279 | } |
280 | } | ||
232 | 281 | ||
233 | /// Returns the containing impl block, if this is an impl item. | 282 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] |
234 | pub fn impl_block(self, db: &impl HirDatabase) -> Option<ImplBlock> { | 283 | pub struct StaticId(RawId); |
235 | let loc = self.loc(db); | 284 | impl_arena_id!(StaticId); |
236 | let module_impls = db.impls_in_module(loc.source_root_id, loc.module_id); | 285 | impl AstItemDef<ast::StaticDef> for StaticId { |
237 | ImplBlock::containing(module_impls, self) | 286 | fn interner(interner: &HirInterner) -> &LocationIntener<ItemLoc<ast::StaticDef>, Self> { |
287 | &interner.statics | ||
288 | } | ||
289 | } | ||
290 | |||
291 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | ||
292 | pub struct TraitId(RawId); | ||
293 | impl_arena_id!(TraitId); | ||
294 | impl AstItemDef<ast::TraitDef> for TraitId { | ||
295 | fn interner(interner: &HirInterner) -> &LocationIntener<ItemLoc<ast::TraitDef>, Self> { | ||
296 | &interner.traits | ||
238 | } | 297 | } |
239 | } | 298 | } |
240 | 299 | ||
241 | impl DefLoc { | 300 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] |
242 | pub(crate) fn id(&self, db: &impl AsRef<HirInterner>) -> DefId { | 301 | pub struct TypeId(RawId); |
243 | db.as_ref().defs.loc2id(&self) | 302 | impl_arena_id!(TypeId); |
303 | impl AstItemDef<ast::TypeDef> for TypeId { | ||
304 | fn interner(interner: &HirInterner) -> &LocationIntener<ItemLoc<ast::TypeDef>, Self> { | ||
305 | &interner.types | ||
244 | } | 306 | } |
245 | } | 307 | } |
246 | 308 | ||
diff --git a/crates/ra_hir/src/impl_block.rs b/crates/ra_hir/src/impl_block.rs index 551d0d149..222e47349 100644 --- a/crates/ra_hir/src/impl_block.rs +++ b/crates/ra_hir/src/impl_block.rs | |||
@@ -3,14 +3,13 @@ use rustc_hash::FxHashMap; | |||
3 | 3 | ||
4 | use ra_arena::{Arena, RawId, impl_arena_id}; | 4 | use ra_arena::{Arena, RawId, impl_arena_id}; |
5 | use ra_syntax::ast::{self, AstNode}; | 5 | use ra_syntax::ast::{self, AstNode}; |
6 | use ra_db::{SourceRootId}; | ||
7 | 6 | ||
8 | use crate::{ | 7 | use crate::{ |
9 | DefId, DefLoc, DefKind, SourceItemId, SourceFileItems, | 8 | Const, Type, |
10 | Function, HirInterner, | 9 | Function, HirFileId, |
11 | db::HirDatabase, | 10 | db::HirDatabase, |
12 | type_ref::TypeRef, | 11 | type_ref::TypeRef, |
13 | module_tree::ModuleId, | 12 | ids::LocationCtx, |
14 | }; | 13 | }; |
15 | 14 | ||
16 | use crate::code_model_api::{Module, ModuleSource}; | 15 | use crate::code_model_api::{Module, ModuleSource}; |
@@ -24,9 +23,9 @@ pub struct ImplBlock { | |||
24 | impl ImplBlock { | 23 | impl ImplBlock { |
25 | pub(crate) fn containing( | 24 | pub(crate) fn containing( |
26 | module_impl_blocks: Arc<ModuleImplBlocks>, | 25 | module_impl_blocks: Arc<ModuleImplBlocks>, |
27 | def_id: DefId, | 26 | item: ImplItem, |
28 | ) -> Option<ImplBlock> { | 27 | ) -> Option<ImplBlock> { |
29 | let impl_id = *module_impl_blocks.impls_by_def.get(&def_id)?; | 28 | let impl_id = *module_impl_blocks.impls_by_def.get(&item)?; |
30 | Some(ImplBlock { | 29 | Some(ImplBlock { |
31 | module_impl_blocks, | 30 | module_impl_blocks, |
32 | impl_id, | 31 | impl_id, |
@@ -66,39 +65,25 @@ pub struct ImplData { | |||
66 | 65 | ||
67 | impl ImplData { | 66 | impl ImplData { |
68 | pub(crate) fn from_ast( | 67 | pub(crate) fn from_ast( |
69 | db: &impl AsRef<HirInterner>, | 68 | db: &impl HirDatabase, |
70 | file_items: &SourceFileItems, | 69 | file_id: HirFileId, |
71 | module: &Module, | 70 | module: Module, |
72 | node: &ast::ImplBlock, | 71 | node: &ast::ImplBlock, |
73 | ) -> Self { | 72 | ) -> Self { |
74 | let target_trait = node.target_trait().map(TypeRef::from_ast); | 73 | let target_trait = node.target_trait().map(TypeRef::from_ast); |
75 | let target_type = TypeRef::from_ast_opt(node.target_type()); | 74 | let target_type = TypeRef::from_ast_opt(node.target_type()); |
76 | let module_loc = module.def_id.loc(db); | 75 | let ctx = LocationCtx::new(db, module, file_id); |
77 | let items = if let Some(item_list) = node.item_list() { | 76 | let items = if let Some(item_list) = node.item_list() { |
78 | item_list | 77 | item_list |
79 | .impl_items() | 78 | .impl_items() |
80 | .map(|item_node| { | 79 | .map(|item_node| match item_node.kind() { |
81 | let kind = match item_node.kind() { | 80 | ast::ImplItemKind::FnDef(it) => { |
82 | ast::ImplItemKind::FnDef(..) => DefKind::Function, | 81 | ImplItem::Method(Function { id: ctx.to_def(it) }) |
83 | ast::ImplItemKind::ConstDef(..) => DefKind::Item, | ||
84 | ast::ImplItemKind::TypeDef(..) => DefKind::Item, | ||
85 | }; | ||
86 | let item_id = file_items.id_of_unchecked(item_node.syntax()); | ||
87 | let source_item_id = SourceItemId { | ||
88 | file_id: module_loc.source_item_id.file_id, | ||
89 | item_id: Some(item_id), | ||
90 | }; | ||
91 | let def_loc = DefLoc { | ||
92 | kind, | ||
93 | source_item_id, | ||
94 | ..module_loc | ||
95 | }; | ||
96 | let def_id = def_loc.id(db); | ||
97 | match item_node.kind() { | ||
98 | ast::ImplItemKind::FnDef(..) => ImplItem::Method(Function::new(def_id)), | ||
99 | ast::ImplItemKind::ConstDef(..) => ImplItem::Const(def_id), | ||
100 | ast::ImplItemKind::TypeDef(..) => ImplItem::Type(def_id), | ||
101 | } | 82 | } |
83 | ast::ImplItemKind::ConstDef(it) => { | ||
84 | ImplItem::Const(Const { id: ctx.to_def(it) }) | ||
85 | } | ||
86 | ast::ImplItemKind::TypeDef(it) => ImplItem::Type(Type { id: ctx.to_def(it) }), | ||
102 | }) | 87 | }) |
103 | .collect() | 88 | .collect() |
104 | } else { | 89 | } else { |
@@ -124,22 +109,19 @@ impl ImplData { | |||
124 | } | 109 | } |
125 | } | 110 | } |
126 | 111 | ||
127 | #[derive(Debug, Clone, PartialEq, Eq)] | 112 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] |
113 | //TODO: rename to ImplDef? | ||
128 | pub enum ImplItem { | 114 | pub enum ImplItem { |
129 | Method(Function), | 115 | Method(Function), |
130 | // these don't have their own types yet | 116 | Const(Const), |
131 | Const(DefId), | 117 | Type(Type), |
132 | Type(DefId), | ||
133 | // Existential | 118 | // Existential |
134 | } | 119 | } |
120 | impl_froms!(ImplItem: Const, Type); | ||
135 | 121 | ||
136 | impl ImplItem { | 122 | impl From<Function> for ImplItem { |
137 | pub fn def_id(&self) -> DefId { | 123 | fn from(func: Function) -> ImplItem { |
138 | match self { | 124 | ImplItem::Method(func) |
139 | ImplItem::Method(f) => f.def_id(), | ||
140 | ImplItem::Const(def_id) => *def_id, | ||
141 | ImplItem::Type(def_id) => *def_id, | ||
142 | } | ||
143 | } | 125 | } |
144 | } | 126 | } |
145 | 127 | ||
@@ -155,7 +137,7 @@ impl_arena_id!(ImplId); | |||
155 | #[derive(Debug, PartialEq, Eq)] | 137 | #[derive(Debug, PartialEq, Eq)] |
156 | pub struct ModuleImplBlocks { | 138 | pub struct ModuleImplBlocks { |
157 | pub(crate) impls: Arena<ImplId, ImplData>, | 139 | pub(crate) impls: Arena<ImplId, ImplData>, |
158 | impls_by_def: FxHashMap<DefId, ImplId>, | 140 | impls_by_def: FxHashMap<ImplItem, ImplId>, |
159 | } | 141 | } |
160 | 142 | ||
161 | impl ModuleImplBlocks { | 143 | impl ModuleImplBlocks { |
@@ -168,6 +150,7 @@ impl ModuleImplBlocks { | |||
168 | 150 | ||
169 | fn collect(&mut self, db: &impl HirDatabase, module: Module) { | 151 | fn collect(&mut self, db: &impl HirDatabase, module: Module) { |
170 | let (file_id, module_source) = module.definition_source(db); | 152 | let (file_id, module_source) = module.definition_source(db); |
153 | let file_id: HirFileId = file_id.into(); | ||
171 | let node = match &module_source { | 154 | let node = match &module_source { |
172 | ModuleSource::SourceFile(node) => node.syntax(), | 155 | ModuleSource::SourceFile(node) => node.syntax(), |
173 | ModuleSource::Module(node) => node | 156 | ModuleSource::Module(node) => node |
@@ -176,25 +159,18 @@ impl ModuleImplBlocks { | |||
176 | .syntax(), | 159 | .syntax(), |
177 | }; | 160 | }; |
178 | 161 | ||
179 | let source_file_items = db.file_items(file_id.into()); | ||
180 | |||
181 | for impl_block_ast in node.children().filter_map(ast::ImplBlock::cast) { | 162 | for impl_block_ast in node.children().filter_map(ast::ImplBlock::cast) { |
182 | let impl_block = ImplData::from_ast(db, &source_file_items, &module, impl_block_ast); | 163 | let impl_block = ImplData::from_ast(db, file_id, module, impl_block_ast); |
183 | let id = self.impls.alloc(impl_block); | 164 | let id = self.impls.alloc(impl_block); |
184 | for impl_item in &self.impls[id].items { | 165 | for &impl_item in &self.impls[id].items { |
185 | self.impls_by_def.insert(impl_item.def_id(), id); | 166 | self.impls_by_def.insert(impl_item, id); |
186 | } | 167 | } |
187 | } | 168 | } |
188 | } | 169 | } |
189 | } | 170 | } |
190 | 171 | ||
191 | pub(crate) fn impls_in_module( | 172 | pub(crate) fn impls_in_module(db: &impl HirDatabase, module: Module) -> Arc<ModuleImplBlocks> { |
192 | db: &impl HirDatabase, | ||
193 | source_root_id: SourceRootId, | ||
194 | module_id: ModuleId, | ||
195 | ) -> Arc<ModuleImplBlocks> { | ||
196 | let mut result = ModuleImplBlocks::new(); | 173 | let mut result = ModuleImplBlocks::new(); |
197 | let module = Module::from_module_id(db, source_root_id, module_id); | ||
198 | result.collect(db, module); | 174 | result.collect(db, module); |
199 | Arc::new(result) | 175 | Arc::new(result) |
200 | } | 176 | } |
diff --git a/crates/ra_hir/src/lib.rs b/crates/ra_hir/src/lib.rs index 87b5a8b8a..596f9c38c 100644 --- a/crates/ra_hir/src/lib.rs +++ b/crates/ra_hir/src/lib.rs | |||
@@ -5,6 +5,18 @@ | |||
5 | //! to a particular crate instance. That is, it has cfg flags and features | 5 | //! to a particular crate instance. That is, it has cfg flags and features |
6 | //! applied. So, the relation between syntax and HIR is many-to-one. | 6 | //! applied. So, the relation between syntax and HIR is many-to-one. |
7 | 7 | ||
8 | macro_rules! impl_froms { | ||
9 | ($e:ident: $($v:ident), *) => { | ||
10 | $( | ||
11 | impl From<$v> for $e { | ||
12 | fn from(it: $v) -> $e { | ||
13 | $e::$v(it) | ||
14 | } | ||
15 | } | ||
16 | )* | ||
17 | } | ||
18 | } | ||
19 | |||
8 | pub mod db; | 20 | pub mod db; |
9 | #[cfg(test)] | 21 | #[cfg(test)] |
10 | mod mock; | 22 | mod mock; |
@@ -34,25 +46,26 @@ mod marks; | |||
34 | use crate::{ | 46 | use crate::{ |
35 | db::HirDatabase, | 47 | db::HirDatabase, |
36 | name::{AsName, KnownName}, | 48 | name::{AsName, KnownName}, |
37 | ids::{DefKind, SourceItemId, SourceFileItems}, | 49 | ids::{SourceItemId, SourceFileItems}, |
38 | }; | 50 | }; |
39 | 51 | ||
40 | pub use self::{ | 52 | pub use self::{ |
41 | path::{Path, PathKind}, | 53 | path::{Path, PathKind}, |
42 | name::Name, | 54 | name::Name, |
43 | ids::{HirFileId, DefId, DefLoc, MacroCallId, MacroCallLoc, HirInterner}, | 55 | ids::{HirFileId, MacroCallId, MacroCallLoc, HirInterner}, |
44 | macros::{MacroDef, MacroInput, MacroExpansion}, | 56 | macros::{MacroDef, MacroInput, MacroExpansion}, |
45 | nameres::{ItemMap, PerNs, Namespace, Resolution}, | 57 | nameres::{ItemMap, PerNs, Namespace, Resolution}, |
46 | ty::Ty, | 58 | ty::Ty, |
47 | impl_block::{ImplBlock, ImplItem}, | 59 | impl_block::{ImplBlock, ImplItem}, |
48 | code_model_impl::function::{FnScopes, ScopesWithSyntaxMapping}, | 60 | code_model_impl::function::{FnScopes, ScopesWithSyntaxMapping}, |
49 | docs::{Docs, Documentation} | 61 | docs::{Docs, Documentation}, |
62 | adt::AdtDef, | ||
50 | }; | 63 | }; |
51 | 64 | ||
52 | pub use self::code_model_api::{ | 65 | pub use self::code_model_api::{ |
53 | Crate, CrateDependency, | 66 | Crate, CrateDependency, |
54 | Def, | 67 | Def, |
55 | Module, ModuleSource, Problem, | 68 | Module, ModuleDef, ModuleSource, Problem, |
56 | Struct, Enum, EnumVariant, | 69 | Struct, Enum, EnumVariant, |
57 | Function, FnSignature, ScopeEntryWithSyntax, | 70 | Function, FnSignature, ScopeEntryWithSyntax, |
58 | StructField, | 71 | StructField, |
diff --git a/crates/ra_hir/src/mock.rs b/crates/ra_hir/src/mock.rs index 4145c8048..361366f6a 100644 --- a/crates/ra_hir/src/mock.rs +++ b/crates/ra_hir/src/mock.rs | |||
@@ -35,10 +35,6 @@ impl MockDatabase { | |||
35 | let file_id = db.add_file(WORKSPACE, &mut source_root, "/main.rs", text); | 35 | let file_id = db.add_file(WORKSPACE, &mut source_root, "/main.rs", text); |
36 | db.query_mut(ra_db::SourceRootQuery) | 36 | db.query_mut(ra_db::SourceRootQuery) |
37 | .set(WORKSPACE, Arc::new(source_root.clone())); | 37 | .set(WORKSPACE, Arc::new(source_root.clone())); |
38 | |||
39 | let mut crate_graph = CrateGraph::default(); | ||
40 | crate_graph.add_crate_root(file_id); | ||
41 | db.set_crate_graph(crate_graph); | ||
42 | (db, source_root, file_id) | 38 | (db, source_root, file_id) |
43 | } | 39 | } |
44 | 40 | ||
@@ -97,6 +93,8 @@ impl MockDatabase { | |||
97 | text: &str, | 93 | text: &str, |
98 | ) -> FileId { | 94 | ) -> FileId { |
99 | assert!(path.starts_with('/')); | 95 | assert!(path.starts_with('/')); |
96 | let is_crate_root = path == "/lib.rs" || path == "/main.rs"; | ||
97 | |||
100 | let path = RelativePathBuf::from_path(&path[1..]).unwrap(); | 98 | let path = RelativePathBuf::from_path(&path[1..]).unwrap(); |
101 | let file_id = FileId(self.file_counter); | 99 | let file_id = FileId(self.file_counter); |
102 | self.file_counter += 1; | 100 | self.file_counter += 1; |
@@ -107,6 +105,12 @@ impl MockDatabase { | |||
107 | self.query_mut(ra_db::FileSourceRootQuery) | 105 | self.query_mut(ra_db::FileSourceRootQuery) |
108 | .set(file_id, source_root_id); | 106 | .set(file_id, source_root_id); |
109 | source_root.files.insert(path, file_id); | 107 | source_root.files.insert(path, file_id); |
108 | |||
109 | if is_crate_root { | ||
110 | let mut crate_graph = CrateGraph::default(); | ||
111 | crate_graph.add_crate_root(file_id); | ||
112 | self.set_crate_graph(crate_graph); | ||
113 | } | ||
110 | file_id | 114 | file_id |
111 | } | 115 | } |
112 | 116 | ||
@@ -202,6 +206,7 @@ salsa::database_storage! { | |||
202 | fn file_relative_path() for ra_db::FileRelativePathQuery; | 206 | fn file_relative_path() for ra_db::FileRelativePathQuery; |
203 | fn file_source_root() for ra_db::FileSourceRootQuery; | 207 | fn file_source_root() for ra_db::FileSourceRootQuery; |
204 | fn source_root() for ra_db::SourceRootQuery; | 208 | fn source_root() for ra_db::SourceRootQuery; |
209 | fn source_root_crates() for ra_db::SourceRootCratesQuery; | ||
205 | fn local_roots() for ra_db::LocalRootsQuery; | 210 | fn local_roots() for ra_db::LocalRootsQuery; |
206 | fn library_roots() for ra_db::LibraryRootsQuery; | 211 | fn library_roots() for ra_db::LibraryRootsQuery; |
207 | fn crate_graph() for ra_db::CrateGraphQuery; | 212 | fn crate_graph() for ra_db::CrateGraphQuery; |
diff --git a/crates/ra_hir/src/module_tree.rs b/crates/ra_hir/src/module_tree.rs index b201bf69b..c00834c4c 100644 --- a/crates/ra_hir/src/module_tree.rs +++ b/crates/ra_hir/src/module_tree.rs | |||
@@ -3,7 +3,7 @@ use std::sync::Arc; | |||
3 | use rustc_hash::{FxHashMap, FxHashSet}; | 3 | use rustc_hash::{FxHashMap, FxHashSet}; |
4 | use arrayvec::ArrayVec; | 4 | use arrayvec::ArrayVec; |
5 | use relative_path::RelativePathBuf; | 5 | use relative_path::RelativePathBuf; |
6 | use ra_db::{FileId, SourceRootId, SourceRoot}; | 6 | use ra_db::{FileId, SourceRoot, CrateId}; |
7 | use ra_syntax::{ | 7 | use ra_syntax::{ |
8 | SyntaxNode, TreeArc, | 8 | SyntaxNode, TreeArc, |
9 | algo::generate, | 9 | algo::generate, |
@@ -126,13 +126,10 @@ struct LinkData { | |||
126 | } | 126 | } |
127 | 127 | ||
128 | impl ModuleTree { | 128 | impl ModuleTree { |
129 | pub(crate) fn module_tree_query( | 129 | pub(crate) fn module_tree_query(db: &impl HirDatabase, crate_id: CrateId) -> Arc<ModuleTree> { |
130 | db: &impl HirDatabase, | ||
131 | source_root: SourceRootId, | ||
132 | ) -> Arc<ModuleTree> { | ||
133 | db.check_canceled(); | 130 | db.check_canceled(); |
134 | let mut res = ModuleTree::default(); | 131 | let mut res = ModuleTree::default(); |
135 | res.init(db, source_root); | 132 | res.init_crate(db, crate_id); |
136 | Arc::new(res) | 133 | Arc::new(res) |
137 | } | 134 | } |
138 | 135 | ||
@@ -145,24 +142,21 @@ impl ModuleTree { | |||
145 | Some(res) | 142 | Some(res) |
146 | } | 143 | } |
147 | 144 | ||
148 | fn init(&mut self, db: &impl HirDatabase, source_root: SourceRootId) { | 145 | fn init_crate(&mut self, db: &impl HirDatabase, crate_id: CrateId) { |
146 | let crate_graph = db.crate_graph(); | ||
147 | let file_id = crate_graph.crate_root(crate_id); | ||
148 | let source_root_id = db.file_source_root(file_id); | ||
149 | |||
149 | let mut roots = FxHashMap::default(); | 150 | let mut roots = FxHashMap::default(); |
150 | let mut visited = FxHashSet::default(); | 151 | let mut visited = FxHashSet::default(); |
151 | 152 | ||
152 | let source_root = db.source_root(source_root); | 153 | let source_root = db.source_root(source_root_id); |
153 | for &file_id in source_root.files.values() { | 154 | let source = SourceItemId { |
154 | let source = SourceItemId { | 155 | file_id: file_id.into(), |
155 | file_id: file_id.into(), | 156 | item_id: None, |
156 | item_id: None, | 157 | }; |
157 | }; | 158 | let module_id = self.init_subtree(db, &source_root, &mut visited, &mut roots, None, source); |
158 | if visited.contains(&source) { | 159 | roots.insert(file_id, module_id); |
159 | continue; // TODO: use explicit crate_roots here | ||
160 | } | ||
161 | assert!(!roots.contains_key(&file_id)); | ||
162 | let module_id = | ||
163 | self.init_subtree(db, &source_root, &mut visited, &mut roots, None, source); | ||
164 | roots.insert(file_id, module_id); | ||
165 | } | ||
166 | } | 160 | } |
167 | 161 | ||
168 | fn init_subtree( | 162 | fn init_subtree( |
diff --git a/crates/ra_hir/src/nameres.rs b/crates/ra_hir/src/nameres.rs index 1d163edf7..a3bc98958 100644 --- a/crates/ra_hir/src/nameres.rs +++ b/crates/ra_hir/src/nameres.rs | |||
@@ -16,19 +16,19 @@ | |||
16 | //! structure itself is modified. | 16 | //! structure itself is modified. |
17 | pub(crate) mod lower; | 17 | pub(crate) mod lower; |
18 | 18 | ||
19 | use crate::nameres::lower::*; | ||
20 | |||
21 | use std::sync::Arc; | 19 | use std::sync::Arc; |
22 | 20 | ||
21 | use ra_db::CrateId; | ||
23 | use rustc_hash::{FxHashMap, FxHashSet}; | 22 | use rustc_hash::{FxHashMap, FxHashSet}; |
24 | use ra_db::SourceRootId; | ||
25 | 23 | ||
26 | use crate::{ | 24 | use crate::{ |
27 | DefId, DefLoc, DefKind, | 25 | Module, ModuleDef, |
28 | Path, PathKind, | 26 | Path, PathKind, |
29 | HirDatabase, Crate, | 27 | HirDatabase, Crate, |
30 | Name, | 28 | Name, |
31 | module_tree::{ModuleId, ModuleTree}, | 29 | module_tree::{ModuleId, ModuleTree}, |
30 | //FIXME: deglobify | ||
31 | nameres::lower::*, | ||
32 | }; | 32 | }; |
33 | 33 | ||
34 | /// `ItemMap` is the result of name resolution. It contains, for each | 34 | /// `ItemMap` is the result of name resolution. It contains, for each |
@@ -58,7 +58,7 @@ impl ModuleScope { | |||
58 | #[derive(Debug, Clone, PartialEq, Eq)] | 58 | #[derive(Debug, Clone, PartialEq, Eq)] |
59 | pub struct Resolution { | 59 | pub struct Resolution { |
60 | /// None for unresolved | 60 | /// None for unresolved |
61 | pub def_id: PerNs<DefId>, | 61 | pub def_id: PerNs<ModuleDef>, |
62 | /// ident by which this is imported into local scope. | 62 | /// ident by which this is imported into local scope. |
63 | pub import: Option<ImportId>, | 63 | pub import: Option<ImportId>, |
64 | } | 64 | } |
@@ -152,7 +152,7 @@ impl<T> PerNs<T> { | |||
152 | pub(crate) struct Resolver<'a, DB> { | 152 | pub(crate) struct Resolver<'a, DB> { |
153 | db: &'a DB, | 153 | db: &'a DB, |
154 | input: &'a FxHashMap<ModuleId, Arc<LoweredModule>>, | 154 | input: &'a FxHashMap<ModuleId, Arc<LoweredModule>>, |
155 | source_root: SourceRootId, | 155 | krate: CrateId, |
156 | module_tree: Arc<ModuleTree>, | 156 | module_tree: Arc<ModuleTree>, |
157 | processed_imports: FxHashSet<(ModuleId, ImportId)>, | 157 | processed_imports: FxHashSet<(ModuleId, ImportId)>, |
158 | result: ItemMap, | 158 | result: ItemMap, |
@@ -165,13 +165,13 @@ where | |||
165 | pub(crate) fn new( | 165 | pub(crate) fn new( |
166 | db: &'a DB, | 166 | db: &'a DB, |
167 | input: &'a FxHashMap<ModuleId, Arc<LoweredModule>>, | 167 | input: &'a FxHashMap<ModuleId, Arc<LoweredModule>>, |
168 | source_root: SourceRootId, | 168 | krate: CrateId, |
169 | module_tree: Arc<ModuleTree>, | ||
170 | ) -> Resolver<'a, DB> { | 169 | ) -> Resolver<'a, DB> { |
170 | let module_tree = db.module_tree(krate); | ||
171 | Resolver { | 171 | Resolver { |
172 | db, | 172 | db, |
173 | input, | 173 | input, |
174 | source_root, | 174 | krate, |
175 | module_tree, | 175 | module_tree, |
176 | processed_imports: FxHashSet::default(), | 176 | processed_imports: FxHashSet::default(), |
177 | result: ItemMap::default(), | 177 | result: ItemMap::default(), |
@@ -210,7 +210,7 @@ where | |||
210 | let krate = Crate::new(crate_id); | 210 | let krate = Crate::new(crate_id); |
211 | for dep in krate.dependencies(self.db) { | 211 | for dep in krate.dependencies(self.db) { |
212 | if let Some(module) = dep.krate.root_module(self.db) { | 212 | if let Some(module) = dep.krate.root_module(self.db) { |
213 | let def_id = module.def_id; | 213 | let def_id = module.into(); |
214 | self.add_module_item( | 214 | self.add_module_item( |
215 | &mut module_items, | 215 | &mut module_items, |
216 | dep.name.clone(), | 216 | dep.name.clone(), |
@@ -244,20 +244,22 @@ where | |||
244 | 244 | ||
245 | // Populate modules | 245 | // Populate modules |
246 | for (name, module_id) in module_id.children(&self.module_tree) { | 246 | for (name, module_id) in module_id.children(&self.module_tree) { |
247 | let def_loc = DefLoc { | 247 | let module = Module { |
248 | kind: DefKind::Module, | ||
249 | source_root_id: self.source_root, | ||
250 | module_id, | 248 | module_id, |
251 | source_item_id: module_id.source(&self.module_tree), | 249 | krate: self.krate, |
252 | }; | 250 | }; |
253 | let def_id = def_loc.id(self.db); | 251 | self.add_module_item(&mut module_items, name, PerNs::types(module.into())); |
254 | self.add_module_item(&mut module_items, name, PerNs::types(def_id)); | ||
255 | } | 252 | } |
256 | 253 | ||
257 | self.result.per_module.insert(module_id, module_items); | 254 | self.result.per_module.insert(module_id, module_items); |
258 | } | 255 | } |
259 | 256 | ||
260 | fn add_module_item(&self, module_items: &mut ModuleScope, name: Name, def_id: PerNs<DefId>) { | 257 | fn add_module_item( |
258 | &self, | ||
259 | module_items: &mut ModuleScope, | ||
260 | name: Name, | ||
261 | def_id: PerNs<ModuleDef>, | ||
262 | ) { | ||
261 | let resolution = Resolution { | 263 | let resolution = Resolution { |
262 | def_id, | 264 | def_id, |
263 | import: None, | 265 | import: None, |
@@ -329,17 +331,11 @@ where | |||
329 | ); | 331 | ); |
330 | return false; | 332 | return false; |
331 | }; | 333 | }; |
332 | curr = match type_def_id.loc(self.db) { | 334 | curr = match type_def_id { |
333 | DefLoc { | 335 | ModuleDef::Module(module) => { |
334 | kind: DefKind::Module, | 336 | if module.krate == self.krate { |
335 | module_id: target_module_id, | 337 | module.module_id |
336 | source_root_id, | ||
337 | .. | ||
338 | } => { | ||
339 | if source_root_id == self.source_root { | ||
340 | target_module_id | ||
341 | } else { | 338 | } else { |
342 | let module = crate::code_model_api::Module::new(type_def_id); | ||
343 | let path = Path { | 339 | let path = Path { |
344 | segments: import.path.segments[i + 1..].iter().cloned().collect(), | 340 | segments: import.path.segments[i + 1..].iter().cloned().collect(), |
345 | kind: PathKind::Crate, | 341 | kind: PathKind::Crate, |
@@ -359,7 +355,7 @@ where | |||
359 | "resolved import {:?} ({:?}) cross-source root to {:?}", | 355 | "resolved import {:?} ({:?}) cross-source root to {:?}", |
360 | last_segment.name, | 356 | last_segment.name, |
361 | import, | 357 | import, |
362 | def_id.map(|did| did.loc(self.db)) | 358 | def_id, |
363 | ); | 359 | ); |
364 | return true; | 360 | return true; |
365 | } else { | 361 | } else { |
@@ -372,7 +368,7 @@ where | |||
372 | log::debug!( | 368 | log::debug!( |
373 | "path segment {:?} resolved to non-module {:?}, but is not last", | 369 | "path segment {:?} resolved to non-module {:?}, but is not last", |
374 | segment.name, | 370 | segment.name, |
375 | type_def_id.loc(self.db) | 371 | type_def_id, |
376 | ); | 372 | ); |
377 | return true; // this resolved to a non-module, so the path won't ever resolve | 373 | return true; // this resolved to a non-module, so the path won't ever resolve |
378 | } | 374 | } |
@@ -382,7 +378,7 @@ where | |||
382 | "resolved import {:?} ({:?}) within source root to {:?}", | 378 | "resolved import {:?} ({:?}) within source root to {:?}", |
383 | segment.name, | 379 | segment.name, |
384 | import, | 380 | import, |
385 | def_id.map(|did| did.loc(self.db)) | 381 | def_id, |
386 | ); | 382 | ); |
387 | self.update(module_id, |items| { | 383 | self.update(module_id, |items| { |
388 | let res = Resolution { | 384 | let res = Resolution { |
diff --git a/crates/ra_hir/src/nameres/lower.rs b/crates/ra_hir/src/nameres/lower.rs index 4eea6ff1d..b4fe99ea7 100644 --- a/crates/ra_hir/src/nameres/lower.rs +++ b/crates/ra_hir/src/nameres/lower.rs | |||
@@ -1,17 +1,17 @@ | |||
1 | use std::sync::Arc; | 1 | use std::sync::Arc; |
2 | 2 | ||
3 | use ra_syntax::{ | 3 | use ra_syntax::{ |
4 | SyntaxKind, AstNode, SourceFile, TreeArc, AstPtr, | 4 | AstNode, SourceFile, TreeArc, AstPtr, |
5 | ast::{self, ModuleItemOwner, NameOwner}, | 5 | ast::{self, ModuleItemOwner, NameOwner}, |
6 | }; | 6 | }; |
7 | use ra_db::SourceRootId; | ||
8 | use ra_arena::{Arena, RawId, impl_arena_id, map::ArenaMap}; | 7 | use ra_arena::{Arena, RawId, impl_arena_id, map::ArenaMap}; |
9 | use rustc_hash::FxHashMap; | 8 | use rustc_hash::FxHashMap; |
10 | 9 | ||
11 | use crate::{ | 10 | use crate::{ |
12 | SourceItemId, Path, ModuleSource, HirDatabase, Name, SourceFileItems, | 11 | SourceItemId, Path, ModuleSource, HirDatabase, Name, |
13 | HirFileId, MacroCallLoc, AsName, PerNs, DefId, DefKind, DefLoc, | 12 | HirFileId, MacroCallLoc, AsName, PerNs, Function, |
14 | module_tree::ModuleId | 13 | ModuleDef, Module, Struct, Enum, Const, Static, Trait, Type, |
14 | ids::LocationCtx, | ||
15 | }; | 15 | }; |
16 | 16 | ||
17 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | 17 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] |
@@ -32,7 +32,7 @@ pub(super) struct ImportData { | |||
32 | /// can avoid redoing name resolution. | 32 | /// can avoid redoing name resolution. |
33 | #[derive(Debug, Default, PartialEq, Eq)] | 33 | #[derive(Debug, Default, PartialEq, Eq)] |
34 | pub struct LoweredModule { | 34 | pub struct LoweredModule { |
35 | pub(crate) declarations: FxHashMap<Name, PerNs<DefId>>, | 35 | pub(crate) declarations: FxHashMap<Name, PerNs<ModuleDef>>, |
36 | pub(super) imports: Arena<ImportId, ImportData>, | 36 | pub(super) imports: Arena<ImportId, ImportData>, |
37 | } | 37 | } |
38 | 38 | ||
@@ -59,37 +59,31 @@ impl ImportSourceMap { | |||
59 | impl LoweredModule { | 59 | impl LoweredModule { |
60 | pub(crate) fn lower_module_module_query( | 60 | pub(crate) fn lower_module_module_query( |
61 | db: &impl HirDatabase, | 61 | db: &impl HirDatabase, |
62 | source_root_id: SourceRootId, | 62 | module: Module, |
63 | module_id: ModuleId, | ||
64 | ) -> Arc<LoweredModule> { | 63 | ) -> Arc<LoweredModule> { |
65 | db.lower_module(source_root_id, module_id).0 | 64 | db.lower_module(module).0 |
66 | } | 65 | } |
67 | 66 | ||
68 | pub(crate) fn lower_module_source_map_query( | 67 | pub(crate) fn lower_module_source_map_query( |
69 | db: &impl HirDatabase, | 68 | db: &impl HirDatabase, |
70 | source_root_id: SourceRootId, | 69 | module: Module, |
71 | module_id: ModuleId, | ||
72 | ) -> Arc<ImportSourceMap> { | 70 | ) -> Arc<ImportSourceMap> { |
73 | db.lower_module(source_root_id, module_id).1 | 71 | db.lower_module(module).1 |
74 | } | 72 | } |
75 | 73 | ||
76 | pub(crate) fn lower_module_query( | 74 | pub(crate) fn lower_module_query( |
77 | db: &impl HirDatabase, | 75 | db: &impl HirDatabase, |
78 | source_root_id: SourceRootId, | 76 | module: Module, |
79 | module_id: ModuleId, | ||
80 | ) -> (Arc<LoweredModule>, Arc<ImportSourceMap>) { | 77 | ) -> (Arc<LoweredModule>, Arc<ImportSourceMap>) { |
81 | let module_tree = db.module_tree(source_root_id); | 78 | let (file_id, source) = module.definition_source(db); |
82 | let source = module_id.source(&module_tree); | 79 | let file_id: HirFileId = file_id.into(); |
83 | let file_id = source.file_id; | ||
84 | let source = ModuleSource::from_source_item_id(db, source); | ||
85 | let mut source_map = ImportSourceMap::default(); | 80 | let mut source_map = ImportSourceMap::default(); |
86 | let mut res = LoweredModule::default(); | 81 | let mut res = LoweredModule::default(); |
87 | match source { | 82 | match source { |
88 | ModuleSource::SourceFile(it) => res.fill( | 83 | ModuleSource::SourceFile(it) => res.fill( |
89 | &mut source_map, | 84 | &mut source_map, |
90 | db, | 85 | db, |
91 | source_root_id, | 86 | module, |
92 | module_id, | ||
93 | file_id, | 87 | file_id, |
94 | &mut it.items_with_macros(), | 88 | &mut it.items_with_macros(), |
95 | ), | 89 | ), |
@@ -98,8 +92,7 @@ impl LoweredModule { | |||
98 | res.fill( | 92 | res.fill( |
99 | &mut source_map, | 93 | &mut source_map, |
100 | db, | 94 | db, |
101 | source_root_id, | 95 | module, |
102 | module_id, | ||
103 | file_id, | 96 | file_id, |
104 | &mut item_list.items_with_macros(), | 97 | &mut item_list.items_with_macros(), |
105 | ) | 98 | ) |
@@ -113,8 +106,7 @@ impl LoweredModule { | |||
113 | &mut self, | 106 | &mut self, |
114 | source_map: &mut ImportSourceMap, | 107 | source_map: &mut ImportSourceMap, |
115 | db: &impl HirDatabase, | 108 | db: &impl HirDatabase, |
116 | source_root_id: SourceRootId, | 109 | module: Module, |
117 | module_id: ModuleId, | ||
118 | file_id: HirFileId, | 110 | file_id: HirFileId, |
119 | items: &mut Iterator<Item = ast::ItemOrMacro>, | 111 | items: &mut Iterator<Item = ast::ItemOrMacro>, |
120 | ) { | 112 | ) { |
@@ -123,21 +115,12 @@ impl LoweredModule { | |||
123 | for item in items { | 115 | for item in items { |
124 | match item { | 116 | match item { |
125 | ast::ItemOrMacro::Item(it) => { | 117 | ast::ItemOrMacro::Item(it) => { |
126 | self.add_def_id( | 118 | self.add_def_id(source_map, db, module, file_id, it); |
127 | source_map, | ||
128 | db, | ||
129 | source_root_id, | ||
130 | module_id, | ||
131 | file_id, | ||
132 | &file_items, | ||
133 | it, | ||
134 | ); | ||
135 | } | 119 | } |
136 | ast::ItemOrMacro::Macro(macro_call) => { | 120 | ast::ItemOrMacro::Macro(macro_call) => { |
137 | let item_id = file_items.id_of_unchecked(macro_call.syntax()); | 121 | let item_id = file_items.id_of_unchecked(macro_call.syntax()); |
138 | let loc = MacroCallLoc { | 122 | let loc = MacroCallLoc { |
139 | source_root_id, | 123 | module, |
140 | module_id, | ||
141 | source_item_id: SourceItemId { | 124 | source_item_id: SourceItemId { |
142 | file_id, | 125 | file_id, |
143 | item_id: Some(item_id), | 126 | item_id: Some(item_id), |
@@ -145,18 +128,9 @@ impl LoweredModule { | |||
145 | }; | 128 | }; |
146 | let id = loc.id(db); | 129 | let id = loc.id(db); |
147 | let file_id = HirFileId::from(id); | 130 | let file_id = HirFileId::from(id); |
148 | let file_items = db.file_items(file_id); | ||
149 | //FIXME: expand recursively | 131 | //FIXME: expand recursively |
150 | for item in db.hir_source_file(file_id).items() { | 132 | for item in db.hir_source_file(file_id).items() { |
151 | self.add_def_id( | 133 | self.add_def_id(source_map, db, module, file_id, item); |
152 | source_map, | ||
153 | db, | ||
154 | source_root_id, | ||
155 | module_id, | ||
156 | file_id, | ||
157 | &file_items, | ||
158 | item, | ||
159 | ); | ||
160 | } | 134 | } |
161 | } | 135 | } |
162 | } | 136 | } |
@@ -167,41 +141,74 @@ impl LoweredModule { | |||
167 | &mut self, | 141 | &mut self, |
168 | source_map: &mut ImportSourceMap, | 142 | source_map: &mut ImportSourceMap, |
169 | db: &impl HirDatabase, | 143 | db: &impl HirDatabase, |
170 | source_root_id: SourceRootId, | 144 | module: Module, |
171 | module_id: ModuleId, | ||
172 | file_id: HirFileId, | 145 | file_id: HirFileId, |
173 | file_items: &SourceFileItems, | ||
174 | item: &ast::ModuleItem, | 146 | item: &ast::ModuleItem, |
175 | ) { | 147 | ) { |
176 | let name = match item.kind() { | 148 | let ctx = LocationCtx::new(db, module, file_id); |
177 | ast::ModuleItemKind::StructDef(it) => it.name(), | 149 | match item.kind() { |
178 | ast::ModuleItemKind::EnumDef(it) => it.name(), | 150 | ast::ModuleItemKind::StructDef(it) => { |
179 | ast::ModuleItemKind::FnDef(it) => it.name(), | 151 | if let Some(name) = it.name() { |
180 | ast::ModuleItemKind::TraitDef(it) => it.name(), | 152 | let s = Struct { id: ctx.to_def(it) }; |
181 | ast::ModuleItemKind::TypeDef(it) => it.name(), | 153 | let s: ModuleDef = s.into(); |
154 | self.declarations.insert(name.as_name(), PerNs::both(s, s)); | ||
155 | } | ||
156 | } | ||
157 | ast::ModuleItemKind::EnumDef(it) => { | ||
158 | if let Some(name) = it.name() { | ||
159 | let e = Enum { id: ctx.to_def(it) }; | ||
160 | let e: ModuleDef = e.into(); | ||
161 | self.declarations.insert(name.as_name(), PerNs::types(e)); | ||
162 | } | ||
163 | } | ||
164 | ast::ModuleItemKind::FnDef(it) => { | ||
165 | if let Some(name) = it.name() { | ||
166 | let func = Function { id: ctx.to_def(it) }; | ||
167 | self.declarations | ||
168 | .insert(name.as_name(), PerNs::values(func.into())); | ||
169 | } | ||
170 | } | ||
171 | ast::ModuleItemKind::TraitDef(it) => { | ||
172 | if let Some(name) = it.name() { | ||
173 | let t = Trait { id: ctx.to_def(it) }; | ||
174 | self.declarations | ||
175 | .insert(name.as_name(), PerNs::types(t.into())); | ||
176 | } | ||
177 | } | ||
178 | ast::ModuleItemKind::TypeDef(it) => { | ||
179 | if let Some(name) = it.name() { | ||
180 | let t = Type { id: ctx.to_def(it) }; | ||
181 | self.declarations | ||
182 | .insert(name.as_name(), PerNs::types(t.into())); | ||
183 | } | ||
184 | } | ||
182 | ast::ModuleItemKind::ImplBlock(_) => { | 185 | ast::ModuleItemKind::ImplBlock(_) => { |
183 | // impls don't define items | 186 | // impls don't define items |
184 | return; | ||
185 | } | 187 | } |
186 | ast::ModuleItemKind::UseItem(it) => { | 188 | ast::ModuleItemKind::UseItem(it) => { |
187 | self.add_use_item(source_map, it); | 189 | self.add_use_item(source_map, it); |
188 | return; | ||
189 | } | 190 | } |
190 | ast::ModuleItemKind::ExternCrateItem(_) => { | 191 | ast::ModuleItemKind::ExternCrateItem(_) => { |
191 | // TODO | 192 | // TODO |
192 | return; | ||
193 | } | 193 | } |
194 | ast::ModuleItemKind::ConstDef(it) => it.name(), | 194 | ast::ModuleItemKind::ConstDef(it) => { |
195 | ast::ModuleItemKind::StaticDef(it) => it.name(), | 195 | if let Some(name) = it.name() { |
196 | let c = Const { id: ctx.to_def(it) }; | ||
197 | self.declarations | ||
198 | .insert(name.as_name(), PerNs::values(c.into())); | ||
199 | } | ||
200 | } | ||
201 | ast::ModuleItemKind::StaticDef(it) => { | ||
202 | if let Some(name) = it.name() { | ||
203 | let s = Static { id: ctx.to_def(it) }; | ||
204 | self.declarations | ||
205 | .insert(name.as_name(), PerNs::values(s.into())); | ||
206 | } | ||
207 | } | ||
196 | ast::ModuleItemKind::Module(_) => { | 208 | ast::ModuleItemKind::Module(_) => { |
197 | // modules are handled separately direclty by nameres | 209 | // modules are handled separately direclty by nameres |
198 | return; | ||
199 | } | 210 | } |
200 | }; | 211 | }; |
201 | if let Some(name) = name { | ||
202 | let def_id = assign_def_id(db, source_root_id, module_id, file_id, file_items, item); | ||
203 | self.declarations.insert(name.as_name(), def_id); | ||
204 | } | ||
205 | } | 212 | } |
206 | 213 | ||
207 | fn add_use_item(&mut self, source_map: &mut ImportSourceMap, item: &ast::UseItem) { | 214 | fn add_use_item(&mut self, source_map: &mut ImportSourceMap, item: &ast::UseItem) { |
@@ -216,46 +223,3 @@ impl LoweredModule { | |||
216 | }) | 223 | }) |
217 | } | 224 | } |
218 | } | 225 | } |
219 | |||
220 | fn assign_def_id( | ||
221 | db: &impl HirDatabase, | ||
222 | source_root_id: SourceRootId, | ||
223 | module_id: ModuleId, | ||
224 | file_id: HirFileId, | ||
225 | file_items: &SourceFileItems, | ||
226 | item: &ast::ModuleItem, | ||
227 | ) -> PerNs<DefId> { | ||
228 | // depending on the item kind, the location can define something in | ||
229 | // the values namespace, the types namespace, or both | ||
230 | let kind = DefKind::for_syntax_kind(item.syntax().kind()); | ||
231 | let def_id = kind.map(|k| { | ||
232 | let item_id = file_items.id_of_unchecked(item.syntax()); | ||
233 | let def_loc = DefLoc { | ||
234 | kind: k, | ||
235 | source_root_id, | ||
236 | module_id, | ||
237 | source_item_id: SourceItemId { | ||
238 | file_id, | ||
239 | item_id: Some(item_id), | ||
240 | }, | ||
241 | }; | ||
242 | def_loc.id(db) | ||
243 | }); | ||
244 | def_id | ||
245 | } | ||
246 | |||
247 | impl DefKind { | ||
248 | fn for_syntax_kind(kind: SyntaxKind) -> PerNs<DefKind> { | ||
249 | match kind { | ||
250 | SyntaxKind::FN_DEF => PerNs::values(DefKind::Function), | ||
251 | SyntaxKind::MODULE => PerNs::types(DefKind::Module), | ||
252 | SyntaxKind::STRUCT_DEF => PerNs::both(DefKind::Struct, DefKind::StructCtor), | ||
253 | SyntaxKind::ENUM_DEF => PerNs::types(DefKind::Enum), | ||
254 | SyntaxKind::TRAIT_DEF => PerNs::types(DefKind::Trait), | ||
255 | SyntaxKind::TYPE_DEF => PerNs::types(DefKind::Type), | ||
256 | SyntaxKind::CONST_DEF => PerNs::values(DefKind::Const), | ||
257 | SyntaxKind::STATIC_DEF => PerNs::values(DefKind::Static), | ||
258 | _ => PerNs::none(), | ||
259 | } | ||
260 | } | ||
261 | } | ||
diff --git a/crates/ra_hir/src/nameres/tests.rs b/crates/ra_hir/src/nameres/tests.rs index e92007453..9322bf08c 100644 --- a/crates/ra_hir/src/nameres/tests.rs +++ b/crates/ra_hir/src/nameres/tests.rs | |||
@@ -1,6 +1,6 @@ | |||
1 | use std::sync::Arc; | 1 | use std::sync::Arc; |
2 | 2 | ||
3 | use ra_db::{FilesDatabase, CrateGraph, SourceRootId, salsa::Database}; | 3 | use ra_db::{CrateGraph, SourceRootId, salsa::Database}; |
4 | use relative_path::RelativePath; | 4 | use relative_path::RelativePath; |
5 | use test_utils::{assert_eq_text, covers}; | 5 | use test_utils::{assert_eq_text, covers}; |
6 | 6 | ||
@@ -13,10 +13,10 @@ use crate::{ | |||
13 | 13 | ||
14 | fn item_map(fixture: &str) -> (Arc<ItemMap>, ModuleId) { | 14 | fn item_map(fixture: &str) -> (Arc<ItemMap>, ModuleId) { |
15 | let (db, pos) = MockDatabase::with_position(fixture); | 15 | let (db, pos) = MockDatabase::with_position(fixture); |
16 | let source_root = db.file_source_root(pos.file_id); | ||
17 | let module = crate::source_binder::module_from_position(&db, pos).unwrap(); | 16 | let module = crate::source_binder::module_from_position(&db, pos).unwrap(); |
18 | let module_id = module.def_id.loc(&db).module_id; | 17 | let krate = module.krate(&db).unwrap(); |
19 | (db.item_map(source_root), module_id) | 18 | let module_id = module.module_id; |
19 | (db.item_map(krate.crate_id), module_id) | ||
20 | } | 20 | } |
21 | 21 | ||
22 | fn check_module_item_map(map: &ItemMap, module_id: ModuleId, expected: &str) { | 22 | fn check_module_item_map(map: &ItemMap, module_id: ModuleId, expected: &str) { |
@@ -238,14 +238,13 @@ fn item_map_across_crates() { | |||
238 | 238 | ||
239 | db.set_crate_graph(crate_graph); | 239 | db.set_crate_graph(crate_graph); |
240 | 240 | ||
241 | let source_root = db.file_source_root(main_id); | ||
242 | let module = crate::source_binder::module_from_file_id(&db, main_id).unwrap(); | 241 | let module = crate::source_binder::module_from_file_id(&db, main_id).unwrap(); |
243 | let module_id = module.def_id.loc(&db).module_id; | 242 | let krate = module.krate(&db).unwrap(); |
244 | let item_map = db.item_map(source_root); | 243 | let item_map = db.item_map(krate.crate_id); |
245 | 244 | ||
246 | check_module_item_map( | 245 | check_module_item_map( |
247 | &item_map, | 246 | &item_map, |
248 | module_id, | 247 | module.module_id, |
249 | " | 248 | " |
250 | Baz: t v | 249 | Baz: t v |
251 | test_crate: t | 250 | test_crate: t |
@@ -292,12 +291,12 @@ fn import_across_source_roots() { | |||
292 | db.set_crate_graph(crate_graph); | 291 | db.set_crate_graph(crate_graph); |
293 | 292 | ||
294 | let module = crate::source_binder::module_from_file_id(&db, main_id).unwrap(); | 293 | let module = crate::source_binder::module_from_file_id(&db, main_id).unwrap(); |
295 | let module_id = module.def_id.loc(&db).module_id; | 294 | let krate = module.krate(&db).unwrap(); |
296 | let item_map = db.item_map(source_root); | 295 | let item_map = db.item_map(krate.crate_id); |
297 | 296 | ||
298 | check_module_item_map( | 297 | check_module_item_map( |
299 | &item_map, | 298 | &item_map, |
300 | module_id, | 299 | module.module_id, |
301 | " | 300 | " |
302 | C: t v | 301 | C: t v |
303 | test_crate: t | 302 | test_crate: t |
@@ -333,14 +332,13 @@ fn reexport_across_crates() { | |||
333 | 332 | ||
334 | db.set_crate_graph(crate_graph); | 333 | db.set_crate_graph(crate_graph); |
335 | 334 | ||
336 | let source_root = db.file_source_root(main_id); | ||
337 | let module = crate::source_binder::module_from_file_id(&db, main_id).unwrap(); | 335 | let module = crate::source_binder::module_from_file_id(&db, main_id).unwrap(); |
338 | let module_id = module.def_id.loc(&db).module_id; | 336 | let krate = module.krate(&db).unwrap(); |
339 | let item_map = db.item_map(source_root); | 337 | let item_map = db.item_map(krate.crate_id); |
340 | 338 | ||
341 | check_module_item_map( | 339 | check_module_item_map( |
342 | &item_map, | 340 | &item_map, |
343 | module_id, | 341 | module.module_id, |
344 | " | 342 | " |
345 | Baz: t v | 343 | Baz: t v |
346 | test_crate: t | 344 | test_crate: t |
@@ -350,10 +348,11 @@ fn reexport_across_crates() { | |||
350 | 348 | ||
351 | fn check_item_map_is_not_recomputed(initial: &str, file_change: &str) { | 349 | fn check_item_map_is_not_recomputed(initial: &str, file_change: &str) { |
352 | let (mut db, pos) = MockDatabase::with_position(initial); | 350 | let (mut db, pos) = MockDatabase::with_position(initial); |
353 | let source_root = db.file_source_root(pos.file_id); | 351 | let module = crate::source_binder::module_from_file_id(&db, pos.file_id).unwrap(); |
352 | let krate = module.krate(&db).unwrap(); | ||
354 | { | 353 | { |
355 | let events = db.log_executed(|| { | 354 | let events = db.log_executed(|| { |
356 | db.item_map(source_root); | 355 | db.item_map(krate.crate_id); |
357 | }); | 356 | }); |
358 | assert!(format!("{:?}", events).contains("item_map")) | 357 | assert!(format!("{:?}", events).contains("item_map")) |
359 | } | 358 | } |
@@ -362,7 +361,7 @@ fn check_item_map_is_not_recomputed(initial: &str, file_change: &str) { | |||
362 | 361 | ||
363 | { | 362 | { |
364 | let events = db.log_executed(|| { | 363 | let events = db.log_executed(|| { |
365 | db.item_map(source_root); | 364 | db.item_map(krate.crate_id); |
366 | }); | 365 | }); |
367 | assert!( | 366 | assert!( |
368 | !format!("{:?}", events).contains("item_map"), | 367 | !format!("{:?}", events).contains("item_map"), |
diff --git a/crates/ra_hir/src/query_definitions.rs b/crates/ra_hir/src/query_definitions.rs index 074153862..cf8c7e435 100644 --- a/crates/ra_hir/src/query_definitions.rs +++ b/crates/ra_hir/src/query_definitions.rs | |||
@@ -7,17 +7,17 @@ use rustc_hash::FxHashMap; | |||
7 | use ra_syntax::{ | 7 | use ra_syntax::{ |
8 | AstNode, SyntaxNode, TreeArc, | 8 | AstNode, SyntaxNode, TreeArc, |
9 | }; | 9 | }; |
10 | use ra_db::SourceRootId; | 10 | use ra_db::{CrateId}; |
11 | 11 | ||
12 | use crate::{ | 12 | use crate::{ |
13 | SourceFileItems, SourceItemId, DefId, HirFileId, | 13 | SourceFileItems, SourceItemId, HirFileId, |
14 | FnScopes, | 14 | Function, FnScopes, Module, |
15 | db::HirDatabase, | 15 | db::HirDatabase, |
16 | nameres::{ItemMap, Resolver}, | 16 | nameres::{ItemMap, Resolver}, |
17 | }; | 17 | }; |
18 | 18 | ||
19 | pub(super) fn fn_scopes(db: &impl HirDatabase, def_id: DefId) -> Arc<FnScopes> { | 19 | pub(super) fn fn_scopes(db: &impl HirDatabase, func: Function) -> Arc<FnScopes> { |
20 | let body = db.body_hir(def_id); | 20 | let body = db.body_hir(func); |
21 | let res = FnScopes::new(body); | 21 | let res = FnScopes::new(body); |
22 | Arc::new(res) | 22 | Arc::new(res) |
23 | } | 23 | } |
@@ -41,15 +41,23 @@ pub(super) fn file_item( | |||
41 | } | 41 | } |
42 | } | 42 | } |
43 | 43 | ||
44 | pub(super) fn item_map(db: &impl HirDatabase, source_root: SourceRootId) -> Arc<ItemMap> { | 44 | pub(super) fn item_map(db: &impl HirDatabase, crate_id: CrateId) -> Arc<ItemMap> { |
45 | let start = Instant::now(); | 45 | let start = Instant::now(); |
46 | let module_tree = db.module_tree(source_root); | 46 | let module_tree = db.module_tree(crate_id); |
47 | let input = module_tree | 47 | let input = module_tree |
48 | .modules() | 48 | .modules() |
49 | .map(|id| (id, db.lower_module_module(source_root, id))) | 49 | .map(|module_id| { |
50 | ( | ||
51 | module_id, | ||
52 | db.lower_module_module(Module { | ||
53 | krate: crate_id, | ||
54 | module_id, | ||
55 | }), | ||
56 | ) | ||
57 | }) | ||
50 | .collect::<FxHashMap<_, _>>(); | 58 | .collect::<FxHashMap<_, _>>(); |
51 | 59 | ||
52 | let resolver = Resolver::new(db, &input, source_root, module_tree); | 60 | let resolver = Resolver::new(db, &input, crate_id); |
53 | let res = resolver.resolve(); | 61 | let res = resolver.resolve(); |
54 | let elapsed = start.elapsed(); | 62 | let elapsed = start.elapsed(); |
55 | log::info!("item_map: {:?}", elapsed); | 63 | log::info!("item_map: {:?}", elapsed); |
diff --git a/crates/ra_hir/src/source_binder.rs b/crates/ra_hir/src/source_binder.rs index bde0be37b..dbe040805 100644 --- a/crates/ra_hir/src/source_binder.rs +++ b/crates/ra_hir/src/source_binder.rs | |||
@@ -13,8 +13,9 @@ use ra_syntax::{ | |||
13 | }; | 13 | }; |
14 | 14 | ||
15 | use crate::{ | 15 | use crate::{ |
16 | HirDatabase, Function, SourceItemId, | 16 | HirDatabase, Function, SourceItemId, ModuleDef, |
17 | DefKind, DefLoc, AsName, Module, | 17 | AsName, Module, |
18 | ids::LocationCtx, | ||
18 | }; | 19 | }; |
19 | 20 | ||
20 | /// Locates the module by `FileId`. Picks topmost module in the file. | 21 | /// Locates the module by `FileId`. Picks topmost module in the file. |
@@ -84,9 +85,13 @@ pub fn module_from_child_node( | |||
84 | 85 | ||
85 | fn module_from_source(db: &impl HirDatabase, source: SourceItemId) -> Option<Module> { | 86 | fn module_from_source(db: &impl HirDatabase, source: SourceItemId) -> Option<Module> { |
86 | let source_root_id = db.file_source_root(source.file_id.as_original_file()); | 87 | let source_root_id = db.file_source_root(source.file_id.as_original_file()); |
87 | let module_tree = db.module_tree(source_root_id); | 88 | db.source_root_crates(source_root_id) |
88 | let module_id = module_tree.find_module_by_source(source)?; | 89 | .iter() |
89 | Some(Module::from_module_id(db, source_root_id, module_id)) | 90 | .find_map(|&krate| { |
91 | let module_tree = db.module_tree(krate); | ||
92 | let module_id = module_tree.find_module_by_source(source)?; | ||
93 | Some(Module { krate, module_id }) | ||
94 | }) | ||
90 | } | 95 | } |
91 | 96 | ||
92 | pub fn function_from_position(db: &impl HirDatabase, position: FilePosition) -> Option<Function> { | 97 | pub fn function_from_position(db: &impl HirDatabase, position: FilePosition) -> Option<Function> { |
@@ -101,30 +106,21 @@ pub fn function_from_source( | |||
101 | fn_def: &ast::FnDef, | 106 | fn_def: &ast::FnDef, |
102 | ) -> Option<Function> { | 107 | ) -> Option<Function> { |
103 | let module = module_from_child_node(db, file_id, fn_def.syntax())?; | 108 | let module = module_from_child_node(db, file_id, fn_def.syntax())?; |
104 | let res = function_from_module(db, &module, fn_def); | 109 | let res = function_from_module(db, module, fn_def); |
105 | Some(res) | 110 | Some(res) |
106 | } | 111 | } |
107 | 112 | ||
108 | pub fn function_from_module( | 113 | pub fn function_from_module( |
109 | db: &impl HirDatabase, | 114 | db: &impl HirDatabase, |
110 | module: &Module, | 115 | module: Module, |
111 | fn_def: &ast::FnDef, | 116 | fn_def: &ast::FnDef, |
112 | ) -> Function { | 117 | ) -> Function { |
113 | let loc = module.def_id.loc(db); | 118 | let (file_id, _) = module.definition_source(db); |
114 | let file_id = loc.source_item_id.file_id; | 119 | let file_id = file_id.into(); |
115 | let file_items = db.file_items(file_id); | 120 | let ctx = LocationCtx::new(db, module, file_id); |
116 | let item_id = file_items.id_of(file_id, fn_def.syntax()); | 121 | Function { |
117 | let source_item_id = SourceItemId { | 122 | id: ctx.to_def(fn_def), |
118 | file_id, | 123 | } |
119 | item_id: Some(item_id), | ||
120 | }; | ||
121 | let def_loc = DefLoc { | ||
122 | kind: DefKind::Function, | ||
123 | source_root_id: loc.source_root_id, | ||
124 | module_id: loc.module_id, | ||
125 | source_item_id, | ||
126 | }; | ||
127 | Function::new(def_loc.id(db)) | ||
128 | } | 124 | } |
129 | 125 | ||
130 | pub fn function_from_child_node( | 126 | pub fn function_from_child_node( |
@@ -141,15 +137,18 @@ pub fn macro_symbols(db: &impl HirDatabase, file_id: FileId) -> Vec<(SmolStr, Te | |||
141 | Some(it) => it, | 137 | Some(it) => it, |
142 | None => return Vec::new(), | 138 | None => return Vec::new(), |
143 | }; | 139 | }; |
144 | let loc = module.def_id.loc(db); | 140 | let items = db.lower_module_module(module); |
145 | let items = db.lower_module_module(loc.source_root_id, loc.module_id); | ||
146 | let mut res = Vec::new(); | 141 | let mut res = Vec::new(); |
147 | 142 | ||
148 | for macro_call_id in items | 143 | for macro_call_id in items |
149 | .declarations | 144 | .declarations |
150 | .iter() | 145 | .iter() |
151 | .filter_map(|(_, it)| it.take_types()) | 146 | .filter_map(|(_, it)| it.clone().take_types()) |
152 | .filter_map(|it| it.loc(db).source_item_id.file_id.as_macro_call_id()) | 147 | .filter_map(|it| match it { |
148 | ModuleDef::Trait(it) => Some(it), | ||
149 | _ => None, | ||
150 | }) | ||
151 | .filter_map(|it| it.source(db).0.as_macro_call_id()) | ||
153 | { | 152 | { |
154 | if let Some(exp) = db.expand_macro_invocation(macro_call_id) { | 153 | if let Some(exp) = db.expand_macro_invocation(macro_call_id) { |
155 | let loc = macro_call_id.loc(db); | 154 | let loc = macro_call_id.loc(db); |
diff --git a/crates/ra_hir/src/ty.rs b/crates/ra_hir/src/ty.rs index e690ae158..c7f77e7a3 100644 --- a/crates/ra_hir/src/ty.rs +++ b/crates/ra_hir/src/ty.rs | |||
@@ -24,15 +24,14 @@ use std::ops::Index; | |||
24 | use std::sync::Arc; | 24 | use std::sync::Arc; |
25 | use std::{fmt, mem}; | 25 | use std::{fmt, mem}; |
26 | 26 | ||
27 | use log; | ||
28 | use ena::unify::{InPlaceUnificationTable, UnifyKey, UnifyValue, NoError}; | 27 | use ena::unify::{InPlaceUnificationTable, UnifyKey, UnifyValue, NoError}; |
29 | use ra_arena::map::ArenaMap; | 28 | use ra_arena::map::ArenaMap; |
30 | use join_to_string::join; | 29 | use join_to_string::join; |
31 | use rustc_hash::FxHashMap; | 30 | use rustc_hash::FxHashMap; |
32 | 31 | ||
33 | use crate::{ | 32 | use crate::{ |
34 | Def, DefId, Module, Function, Struct, StructField, Enum, EnumVariant, Path, Name, ImplBlock, | 33 | Module, Function, Struct, StructField, Enum, EnumVariant, Path, Name, ImplBlock, |
35 | FnSignature, FnScopes, | 34 | FnSignature, FnScopes, ModuleDef, AdtDef, |
36 | db::HirDatabase, | 35 | db::HirDatabase, |
37 | type_ref::{TypeRef, Mutability}, | 36 | type_ref::{TypeRef, Mutability}, |
38 | name::KnownName, | 37 | name::KnownName, |
@@ -184,7 +183,7 @@ pub enum Ty { | |||
184 | /// Structures, enumerations and unions. | 183 | /// Structures, enumerations and unions. |
185 | Adt { | 184 | Adt { |
186 | /// The DefId of the struct/enum. | 185 | /// The DefId of the struct/enum. |
187 | def_id: DefId, | 186 | def_id: AdtDef, |
188 | /// The name, for displaying. | 187 | /// The name, for displaying. |
189 | name: Name, | 188 | name: Name, |
190 | /// Substitutions for the generic parameters of the type. | 189 | /// Substitutions for the generic parameters of the type. |
@@ -381,12 +380,16 @@ impl Ty { | |||
381 | } | 380 | } |
382 | 381 | ||
383 | // Resolve in module (in type namespace) | 382 | // Resolve in module (in type namespace) |
384 | let resolved = match module.resolve_path(db, path).take_types() { | 383 | let typable: TypableDef = match module |
385 | Some(r) => r, | 384 | .resolve_path(db, path) |
385 | .take_types() | ||
386 | .and_then(|it| it.into()) | ||
387 | { | ||
386 | None => return Ty::Unknown, | 388 | None => return Ty::Unknown, |
389 | Some(it) => it, | ||
387 | }; | 390 | }; |
388 | let ty = db.type_for_def(resolved); | 391 | let ty = db.type_for_def(typable); |
389 | let substs = Ty::substs_from_path(db, module, impl_block, generics, path, resolved); | 392 | let substs = Ty::substs_from_path(db, module, impl_block, generics, path, typable); |
390 | ty.apply_substs(substs) | 393 | ty.apply_substs(substs) |
391 | } | 394 | } |
392 | 395 | ||
@@ -399,20 +402,18 @@ impl Ty { | |||
399 | impl_block: Option<&ImplBlock>, | 402 | impl_block: Option<&ImplBlock>, |
400 | outer_generics: &GenericParams, | 403 | outer_generics: &GenericParams, |
401 | path: &Path, | 404 | path: &Path, |
402 | resolved: DefId, | 405 | resolved: TypableDef, |
403 | ) -> Substs { | 406 | ) -> Substs { |
404 | let mut substs = Vec::new(); | 407 | let mut substs = Vec::new(); |
405 | let def = resolved.resolve(db); | ||
406 | let last = path | 408 | let last = path |
407 | .segments | 409 | .segments |
408 | .last() | 410 | .last() |
409 | .expect("path should have at least one segment"); | 411 | .expect("path should have at least one segment"); |
410 | let (def_generics, segment) = match def { | 412 | let (def_generics, segment) = match resolved { |
411 | Def::Struct(s) => (s.generic_params(db), last), | 413 | TypableDef::Function(func) => (func.generic_params(db), last), |
412 | Def::Enum(e) => (e.generic_params(db), last), | 414 | TypableDef::Struct(s) => (s.generic_params(db), last), |
413 | Def::Function(f) => (f.generic_params(db), last), | 415 | TypableDef::Enum(e) => (e.generic_params(db), last), |
414 | Def::Trait(t) => (t.generic_params(db), last), | 416 | TypableDef::EnumVariant(var) => { |
415 | Def::EnumVariant(ev) => { | ||
416 | // the generic args for an enum variant may be either specified | 417 | // the generic args for an enum variant may be either specified |
417 | // on the segment referring to the enum, or on the segment | 418 | // on the segment referring to the enum, or on the segment |
418 | // referring to the variant. So `Option::<T>::None` and | 419 | // referring to the variant. So `Option::<T>::None` and |
@@ -426,9 +427,8 @@ impl Ty { | |||
426 | // Option::None::<T> | 427 | // Option::None::<T> |
427 | last | 428 | last |
428 | }; | 429 | }; |
429 | (ev.parent_enum(db).generic_params(db), segment) | 430 | (var.parent_enum(db).generic_params(db), segment) |
430 | } | 431 | } |
431 | _ => return Substs::empty(), | ||
432 | }; | 432 | }; |
433 | // substs_from_path | 433 | // substs_from_path |
434 | if let Some(generic_args) = &segment.args_and_bindings { | 434 | if let Some(generic_args) = &segment.args_and_bindings { |
@@ -639,7 +639,7 @@ fn make_substs(generics: &GenericParams) -> Substs { | |||
639 | fn type_for_struct(db: &impl HirDatabase, s: Struct) -> Ty { | 639 | fn type_for_struct(db: &impl HirDatabase, s: Struct) -> Ty { |
640 | let generics = s.generic_params(db); | 640 | let generics = s.generic_params(db); |
641 | Ty::Adt { | 641 | Ty::Adt { |
642 | def_id: s.def_id(), | 642 | def_id: s.into(), |
643 | name: s.name(db).unwrap_or_else(Name::missing), | 643 | name: s.name(db).unwrap_or_else(Name::missing), |
644 | substs: make_substs(&generics), | 644 | substs: make_substs(&generics), |
645 | } | 645 | } |
@@ -648,7 +648,7 @@ fn type_for_struct(db: &impl HirDatabase, s: Struct) -> Ty { | |||
648 | pub(crate) fn type_for_enum(db: &impl HirDatabase, s: Enum) -> Ty { | 648 | pub(crate) fn type_for_enum(db: &impl HirDatabase, s: Enum) -> Ty { |
649 | let generics = s.generic_params(db); | 649 | let generics = s.generic_params(db); |
650 | Ty::Adt { | 650 | Ty::Adt { |
651 | def_id: s.def_id(), | 651 | def_id: s.into(), |
652 | name: s.name(db).unwrap_or_else(Name::missing), | 652 | name: s.name(db).unwrap_or_else(Name::missing), |
653 | substs: make_substs(&generics), | 653 | substs: make_substs(&generics), |
654 | } | 654 | } |
@@ -660,66 +660,74 @@ pub(crate) fn type_for_enum_variant(db: &impl HirDatabase, ev: EnumVariant) -> T | |||
660 | type_for_enum(db, enum_parent) | 660 | type_for_enum(db, enum_parent) |
661 | } | 661 | } |
662 | 662 | ||
663 | pub(super) fn type_for_def(db: &impl HirDatabase, def_id: DefId) -> Ty { | 663 | #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] |
664 | let def = def_id.resolve(db); | 664 | pub enum TypableDef { |
665 | Function(Function), | ||
666 | Struct(Struct), | ||
667 | Enum(Enum), | ||
668 | EnumVariant(EnumVariant), | ||
669 | } | ||
670 | impl_froms!(TypableDef: Function, Struct, Enum, EnumVariant); | ||
671 | |||
672 | impl From<ModuleDef> for Option<TypableDef> { | ||
673 | fn from(def: ModuleDef) -> Option<TypableDef> { | ||
674 | let res = match def { | ||
675 | ModuleDef::Function(f) => f.into(), | ||
676 | ModuleDef::Struct(s) => s.into(), | ||
677 | ModuleDef::Enum(e) => e.into(), | ||
678 | ModuleDef::EnumVariant(v) => v.into(), | ||
679 | ModuleDef::Const(_) | ||
680 | | ModuleDef::Static(_) | ||
681 | | ModuleDef::Module(_) | ||
682 | | ModuleDef::Trait(_) | ||
683 | | ModuleDef::Type(_) => return None, | ||
684 | }; | ||
685 | Some(res) | ||
686 | } | ||
687 | } | ||
688 | |||
689 | pub(super) fn type_for_def(db: &impl HirDatabase, def: TypableDef) -> Ty { | ||
665 | match def { | 690 | match def { |
666 | Def::Module(..) => { | 691 | TypableDef::Function(f) => type_for_fn(db, f), |
667 | log::debug!("trying to get type for module {:?}", def_id); | 692 | TypableDef::Struct(s) => type_for_struct(db, s), |
668 | Ty::Unknown | 693 | TypableDef::Enum(e) => type_for_enum(db, e), |
669 | } | 694 | TypableDef::EnumVariant(v) => type_for_enum_variant(db, v), |
670 | Def::Function(f) => type_for_fn(db, f), | ||
671 | Def::Struct(s) => type_for_struct(db, s), | ||
672 | Def::Enum(e) => type_for_enum(db, e), | ||
673 | Def::EnumVariant(ev) => type_for_enum_variant(db, ev), | ||
674 | _ => { | ||
675 | log::debug!( | ||
676 | "trying to get type for item of unknown type {:?} {:?}", | ||
677 | def_id, | ||
678 | def | ||
679 | ); | ||
680 | Ty::Unknown | ||
681 | } | ||
682 | } | 695 | } |
683 | } | 696 | } |
684 | 697 | ||
685 | pub(super) fn type_for_field(db: &impl HirDatabase, def_id: DefId, field: Name) -> Option<Ty> { | 698 | #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] |
686 | let def = def_id.resolve(db); | 699 | pub enum VariantDef { |
687 | let (variant_data, generics) = match def { | 700 | Struct(Struct), |
688 | Def::Struct(s) => (s.variant_data(db), s.generic_params(db)), | 701 | EnumVariant(EnumVariant), |
689 | Def::EnumVariant(ev) => (ev.variant_data(db), ev.parent_enum(db).generic_params(db)), | 702 | } |
690 | // TODO: unions | 703 | impl_froms!(VariantDef: Struct, EnumVariant); |
691 | Def::Enum(_) => { | 704 | |
692 | // this can happen in (invalid) code, but enums don't have fields themselves | 705 | pub(super) fn type_for_field(db: &impl HirDatabase, def: VariantDef, field: Name) -> Option<Ty> { |
693 | return None; | 706 | let (variant_data, generics, module) = match def { |
694 | } | 707 | VariantDef::Struct(s) => (s.variant_data(db), s.generic_params(db), s.module(db)), |
695 | _ => panic!( | 708 | VariantDef::EnumVariant(var) => ( |
696 | "trying to get type for field {:?} in non-struct/variant {:?}", | 709 | var.variant_data(db), |
697 | field, def_id | 710 | var.parent_enum(db).generic_params(db), |
711 | var.module(db), | ||
698 | ), | 712 | ), |
699 | }; | 713 | }; |
700 | let module = def_id.module(db); | 714 | // We can't have an impl block ere, right? |
701 | let impl_block = def_id.impl_block(db); | 715 | // let impl_block = def_id.impl_block(db); |
702 | let type_ref = variant_data.get_field_type_ref(&field)?; | 716 | let type_ref = variant_data.get_field_type_ref(&field)?; |
703 | Some(Ty::from_hir( | 717 | Some(Ty::from_hir(db, &module, None, &generics, &type_ref)) |
704 | db, | ||
705 | &module, | ||
706 | impl_block.as_ref(), | ||
707 | &generics, | ||
708 | &type_ref, | ||
709 | )) | ||
710 | } | 718 | } |
711 | 719 | ||
712 | /// The result of type inference: A mapping from expressions and patterns to types. | 720 | /// The result of type inference: A mapping from expressions and patterns to types. |
713 | #[derive(Clone, PartialEq, Eq, Debug)] | 721 | #[derive(Clone, PartialEq, Eq, Debug)] |
714 | pub struct InferenceResult { | 722 | pub struct InferenceResult { |
715 | /// For each method call expr, record the function it resolved to. | 723 | /// For each method call expr, record the function it resolved to. |
716 | method_resolutions: FxHashMap<ExprId, DefId>, | 724 | method_resolutions: FxHashMap<ExprId, Function>, |
717 | type_of_expr: ArenaMap<ExprId, Ty>, | 725 | type_of_expr: ArenaMap<ExprId, Ty>, |
718 | type_of_pat: ArenaMap<PatId, Ty>, | 726 | type_of_pat: ArenaMap<PatId, Ty>, |
719 | } | 727 | } |
720 | 728 | ||
721 | impl InferenceResult { | 729 | impl InferenceResult { |
722 | pub fn method_resolution(&self, expr: ExprId) -> Option<DefId> { | 730 | pub fn method_resolution(&self, expr: ExprId) -> Option<Function> { |
723 | self.method_resolutions.get(&expr).map(|it| *it) | 731 | self.method_resolutions.get(&expr).map(|it| *it) |
724 | } | 732 | } |
725 | } | 733 | } |
@@ -749,7 +757,7 @@ struct InferenceContext<'a, D: HirDatabase> { | |||
749 | module: Module, | 757 | module: Module, |
750 | impl_block: Option<ImplBlock>, | 758 | impl_block: Option<ImplBlock>, |
751 | var_unification_table: InPlaceUnificationTable<TypeVarId>, | 759 | var_unification_table: InPlaceUnificationTable<TypeVarId>, |
752 | method_resolutions: FxHashMap<ExprId, DefId>, | 760 | method_resolutions: FxHashMap<ExprId, Function>, |
753 | type_of_expr: ArenaMap<ExprId, Ty>, | 761 | type_of_expr: ArenaMap<ExprId, Ty>, |
754 | type_of_pat: ArenaMap<PatId, Ty>, | 762 | type_of_pat: ArenaMap<PatId, Ty>, |
755 | /// The return type of the function being inferred. | 763 | /// The return type of the function being inferred. |
@@ -875,8 +883,8 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
875 | self.type_of_expr.insert(expr, ty); | 883 | self.type_of_expr.insert(expr, ty); |
876 | } | 884 | } |
877 | 885 | ||
878 | fn write_method_resolution(&mut self, expr: ExprId, def_id: DefId) { | 886 | fn write_method_resolution(&mut self, expr: ExprId, func: Function) { |
879 | self.method_resolutions.insert(expr, def_id); | 887 | self.method_resolutions.insert(expr, func); |
880 | } | 888 | } |
881 | 889 | ||
882 | fn write_pat_ty(&mut self, pat: PatId, ty: Ty) { | 890 | fn write_pat_ty(&mut self, pat: PatId, ty: Ty) { |
@@ -1063,20 +1071,30 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
1063 | }; | 1071 | }; |
1064 | 1072 | ||
1065 | // resolve in module | 1073 | // resolve in module |
1066 | let resolved = self.module.resolve_path(self.db, &path).take_values()?; | 1074 | let typable: Option<TypableDef> = self |
1067 | let ty = self.db.type_for_def(resolved); | 1075 | .module |
1076 | .resolve_path(self.db, &path) | ||
1077 | .take_values()? | ||
1078 | .into(); | ||
1079 | let typable = typable?; | ||
1080 | let ty = self.db.type_for_def(typable); | ||
1068 | let ty = self.insert_type_vars(ty); | 1081 | let ty = self.insert_type_vars(ty); |
1069 | Some(ty) | 1082 | Some(ty) |
1070 | } | 1083 | } |
1071 | 1084 | ||
1072 | fn resolve_variant(&mut self, path: Option<&Path>) -> (Ty, Option<DefId>) { | 1085 | fn resolve_variant(&mut self, path: Option<&Path>) -> (Ty, Option<VariantDef>) { |
1073 | let path = match path { | 1086 | let path = match path { |
1074 | Some(path) => path, | 1087 | Some(path) => path, |
1075 | None => return (Ty::Unknown, None), | 1088 | None => return (Ty::Unknown, None), |
1076 | }; | 1089 | }; |
1077 | let def_id = match self.module.resolve_path(self.db, &path).take_types() { | 1090 | let typable: Option<TypableDef> = self |
1078 | Some(def_id) => def_id, | 1091 | .module |
1079 | _ => return (Ty::Unknown, None), | 1092 | .resolve_path(self.db, &path) |
1093 | .take_types() | ||
1094 | .and_then(|it| it.into()); | ||
1095 | let def = match typable { | ||
1096 | None => return (Ty::Unknown, None), | ||
1097 | Some(it) => it, | ||
1080 | }; | 1098 | }; |
1081 | // TODO remove the duplication between here and `Ty::from_path`? | 1099 | // TODO remove the duplication between here and `Ty::from_path`? |
1082 | // TODO provide generics of function | 1100 | // TODO provide generics of function |
@@ -1087,38 +1105,34 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
1087 | self.impl_block.as_ref(), | 1105 | self.impl_block.as_ref(), |
1088 | &generics, | 1106 | &generics, |
1089 | path, | 1107 | path, |
1090 | def_id, | 1108 | def, |
1091 | ); | 1109 | ); |
1092 | match def_id.resolve(self.db) { | 1110 | match def { |
1093 | Def::Struct(s) => { | 1111 | TypableDef::Struct(s) => { |
1094 | let ty = type_for_struct(self.db, s); | 1112 | let ty = type_for_struct(self.db, s); |
1095 | let ty = self.insert_type_vars(ty.apply_substs(substs)); | 1113 | let ty = self.insert_type_vars(ty.apply_substs(substs)); |
1096 | (ty, Some(def_id)) | 1114 | (ty, Some(s.into())) |
1097 | } | 1115 | } |
1098 | Def::EnumVariant(ev) => { | 1116 | TypableDef::EnumVariant(var) => { |
1099 | let ty = type_for_enum_variant(self.db, ev); | 1117 | let ty = type_for_enum_variant(self.db, var); |
1100 | let ty = self.insert_type_vars(ty.apply_substs(substs)); | 1118 | let ty = self.insert_type_vars(ty.apply_substs(substs)); |
1101 | (ty, Some(def_id)) | 1119 | (ty, Some(var.into())) |
1102 | } | 1120 | } |
1103 | _ => (Ty::Unknown, None), | 1121 | TypableDef::Enum(_) | TypableDef::Function(_) => (Ty::Unknown, None), |
1104 | } | 1122 | } |
1105 | } | 1123 | } |
1106 | 1124 | ||
1107 | fn resolve_fields(&mut self, path: Option<&Path>) -> Option<(Ty, Vec<StructField>)> { | 1125 | fn resolve_fields(&mut self, path: Option<&Path>) -> Option<(Ty, Vec<StructField>)> { |
1108 | let (ty, def_id) = self.resolve_variant(path); | 1126 | let (ty, def) = self.resolve_variant(path); |
1109 | let def_id = def_id?; | 1127 | match def? { |
1110 | let def = def_id.resolve(self.db); | 1128 | VariantDef::Struct(s) => { |
1111 | |||
1112 | match def { | ||
1113 | Def::Struct(s) => { | ||
1114 | let fields = s.fields(self.db); | 1129 | let fields = s.fields(self.db); |
1115 | Some((ty, fields)) | 1130 | Some((ty, fields)) |
1116 | } | 1131 | } |
1117 | Def::EnumVariant(ev) => { | 1132 | VariantDef::EnumVariant(var) => { |
1118 | let fields = ev.fields(self.db); | 1133 | let fields = var.fields(self.db); |
1119 | Some((ty, fields)) | 1134 | Some((ty, fields)) |
1120 | } | 1135 | } |
1121 | _ => None, | ||
1122 | } | 1136 | } |
1123 | } | 1137 | } |
1124 | 1138 | ||
@@ -1216,6 +1230,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
1216 | .module | 1230 | .module |
1217 | .resolve_path(self.db, &path) | 1231 | .resolve_path(self.db, &path) |
1218 | .take_values() | 1232 | .take_values() |
1233 | .and_then(|module_def| module_def.into()) | ||
1219 | .map_or(Ty::Unknown, |resolved| self.db.type_for_def(resolved)), | 1234 | .map_or(Ty::Unknown, |resolved| self.db.type_for_def(resolved)), |
1220 | Pat::Bind { | 1235 | Pat::Bind { |
1221 | mode, | 1236 | mode, |
@@ -1336,9 +1351,9 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
1336 | let receiver_ty = self.infer_expr(*receiver, &Expectation::none()); | 1351 | let receiver_ty = self.infer_expr(*receiver, &Expectation::none()); |
1337 | let resolved = receiver_ty.clone().lookup_method(self.db, method_name); | 1352 | let resolved = receiver_ty.clone().lookup_method(self.db, method_name); |
1338 | let method_ty = match resolved { | 1353 | let method_ty = match resolved { |
1339 | Some(def_id) => { | 1354 | Some(func) => { |
1340 | self.write_method_resolution(expr, def_id); | 1355 | self.write_method_resolution(expr, func); |
1341 | self.db.type_for_def(def_id) | 1356 | self.db.type_for_def(func.into()) |
1342 | } | 1357 | } |
1343 | None => Ty::Unknown, | 1358 | None => Ty::Unknown, |
1344 | }; | 1359 | }; |
@@ -1407,7 +1422,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
1407 | for field in fields { | 1422 | for field in fields { |
1408 | let field_ty = if let Some(def_id) = def_id { | 1423 | let field_ty = if let Some(def_id) = def_id { |
1409 | self.db | 1424 | self.db |
1410 | .type_for_field(def_id, field.name.clone()) | 1425 | .type_for_field(def_id.into(), field.name.clone()) |
1411 | .unwrap_or(Ty::Unknown) | 1426 | .unwrap_or(Ty::Unknown) |
1412 | .subst(&substs) | 1427 | .subst(&substs) |
1413 | } else { | 1428 | } else { |
@@ -1431,10 +1446,12 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
1431 | i.and_then(|i| fields.get(i).cloned()) | 1446 | i.and_then(|i| fields.get(i).cloned()) |
1432 | } | 1447 | } |
1433 | Ty::Adt { | 1448 | Ty::Adt { |
1434 | def_id, ref substs, .. | 1449 | def_id: AdtDef::Struct(s), |
1450 | ref substs, | ||
1451 | .. | ||
1435 | } => self | 1452 | } => self |
1436 | .db | 1453 | .db |
1437 | .type_for_field(def_id, name.clone()) | 1454 | .type_for_field(s.into(), name.clone()) |
1438 | .map(|ty| ty.subst(substs)), | 1455 | .map(|ty| ty.subst(substs)), |
1439 | _ => None, | 1456 | _ => None, |
1440 | }) | 1457 | }) |
@@ -1607,16 +1624,15 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
1607 | } | 1624 | } |
1608 | } | 1625 | } |
1609 | 1626 | ||
1610 | pub fn infer(db: &impl HirDatabase, def_id: DefId) -> Arc<InferenceResult> { | 1627 | pub fn infer(db: &impl HirDatabase, func: Function) -> Arc<InferenceResult> { |
1611 | db.check_canceled(); | 1628 | db.check_canceled(); |
1612 | let function = Function::new(def_id); // TODO: consts also need inference | 1629 | let body = func.body(db); |
1613 | let body = function.body(db); | 1630 | let scopes = db.fn_scopes(func); |
1614 | let scopes = db.fn_scopes(def_id); | 1631 | let module = func.module(db); |
1615 | let module = function.module(db); | 1632 | let impl_block = func.impl_block(db); |
1616 | let impl_block = function.impl_block(db); | ||
1617 | let mut ctx = InferenceContext::new(db, body, scopes, module, impl_block); | 1633 | let mut ctx = InferenceContext::new(db, body, scopes, module, impl_block); |
1618 | 1634 | ||
1619 | let signature = function.signature(db); | 1635 | let signature = func.signature(db); |
1620 | ctx.collect_fn_signature(&signature); | 1636 | ctx.collect_fn_signature(&signature); |
1621 | 1637 | ||
1622 | ctx.infer_body(); | 1638 | ctx.infer_body(); |
diff --git a/crates/ra_hir/src/ty/method_resolution.rs b/crates/ra_hir/src/ty/method_resolution.rs index 9f65c5fe1..9a571c2aa 100644 --- a/crates/ra_hir/src/ty/method_resolution.rs +++ b/crates/ra_hir/src/ty/method_resolution.rs | |||
@@ -6,19 +6,17 @@ use std::sync::Arc; | |||
6 | 6 | ||
7 | use rustc_hash::FxHashMap; | 7 | use rustc_hash::FxHashMap; |
8 | 8 | ||
9 | use ra_db::SourceRootId; | ||
10 | |||
11 | use crate::{ | 9 | use crate::{ |
12 | HirDatabase, DefId, module_tree::ModuleId, Module, Crate, Name, Function, | 10 | HirDatabase, module_tree::ModuleId, Module, Crate, Name, Function, |
13 | impl_block::{ImplId, ImplBlock, ImplItem}, | 11 | impl_block::{ImplId, ImplBlock, ImplItem}, |
14 | generics::GenericParams | 12 | generics::GenericParams, |
13 | ty::{AdtDef, Ty} | ||
15 | }; | 14 | }; |
16 | use super::Ty; | ||
17 | 15 | ||
18 | /// This is used as a key for indexing impls. | 16 | /// This is used as a key for indexing impls. |
19 | #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] | 17 | #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] |
20 | pub enum TyFingerprint { | 18 | pub enum TyFingerprint { |
21 | Adt(DefId), | 19 | Adt(AdtDef), |
22 | // we'll also want to index impls for primitive types etc. | 20 | // we'll also want to index impls for primitive types etc. |
23 | } | 21 | } |
24 | 22 | ||
@@ -37,7 +35,7 @@ impl TyFingerprint { | |||
37 | #[derive(Debug, PartialEq, Eq)] | 35 | #[derive(Debug, PartialEq, Eq)] |
38 | pub struct CrateImplBlocks { | 36 | pub struct CrateImplBlocks { |
39 | /// To make sense of the ModuleIds, we need the source root. | 37 | /// To make sense of the ModuleIds, we need the source root. |
40 | source_root_id: SourceRootId, | 38 | krate: Crate, |
41 | impls: FxHashMap<TyFingerprint, Vec<(ModuleId, ImplId)>>, | 39 | impls: FxHashMap<TyFingerprint, Vec<(ModuleId, ImplId)>>, |
42 | } | 40 | } |
43 | 41 | ||
@@ -53,14 +51,17 @@ impl CrateImplBlocks { | |||
53 | .into_iter() | 51 | .into_iter() |
54 | .flat_map(|i| i.iter()) | 52 | .flat_map(|i| i.iter()) |
55 | .map(move |(module_id, impl_id)| { | 53 | .map(move |(module_id, impl_id)| { |
56 | let module_impl_blocks = db.impls_in_module(self.source_root_id, *module_id); | 54 | let module = Module { |
55 | krate: self.krate.crate_id, | ||
56 | module_id: *module_id, | ||
57 | }; | ||
58 | let module_impl_blocks = db.impls_in_module(module); | ||
57 | ImplBlock::from_id(module_impl_blocks, *impl_id) | 59 | ImplBlock::from_id(module_impl_blocks, *impl_id) |
58 | }) | 60 | }) |
59 | } | 61 | } |
60 | 62 | ||
61 | fn collect_recursive(&mut self, db: &impl HirDatabase, module: Module) { | 63 | fn collect_recursive(&mut self, db: &impl HirDatabase, module: &Module) { |
62 | let module_id = module.def_id.loc(db).module_id; | 64 | let module_impl_blocks = db.impls_in_module(module.clone()); |
63 | let module_impl_blocks = db.impls_in_module(self.source_root_id, module_id); | ||
64 | 65 | ||
65 | for (impl_id, impl_data) in module_impl_blocks.impls.iter() { | 66 | for (impl_id, impl_data) in module_impl_blocks.impls.iter() { |
66 | let impl_block = ImplBlock::from_id(Arc::clone(&module_impl_blocks), impl_id); | 67 | let impl_block = ImplBlock::from_id(Arc::clone(&module_impl_blocks), impl_id); |
@@ -81,13 +82,13 @@ impl CrateImplBlocks { | |||
81 | self.impls | 82 | self.impls |
82 | .entry(target_ty_fp) | 83 | .entry(target_ty_fp) |
83 | .or_insert_with(Vec::new) | 84 | .or_insert_with(Vec::new) |
84 | .push((module_id, impl_id)); | 85 | .push((module.module_id, impl_id)); |
85 | } | 86 | } |
86 | } | 87 | } |
87 | } | 88 | } |
88 | 89 | ||
89 | for child in module.children(db) { | 90 | for child in module.children(db) { |
90 | self.collect_recursive(db, child); | 91 | self.collect_recursive(db, &child); |
91 | } | 92 | } |
92 | } | 93 | } |
93 | 94 | ||
@@ -95,15 +96,12 @@ impl CrateImplBlocks { | |||
95 | db: &impl HirDatabase, | 96 | db: &impl HirDatabase, |
96 | krate: Crate, | 97 | krate: Crate, |
97 | ) -> Arc<CrateImplBlocks> { | 98 | ) -> Arc<CrateImplBlocks> { |
98 | let crate_graph = db.crate_graph(); | ||
99 | let file_id = crate_graph.crate_root(krate.crate_id); | ||
100 | let source_root_id = db.file_source_root(file_id); | ||
101 | let mut crate_impl_blocks = CrateImplBlocks { | 99 | let mut crate_impl_blocks = CrateImplBlocks { |
102 | source_root_id, | 100 | krate: krate.clone(), |
103 | impls: FxHashMap::default(), | 101 | impls: FxHashMap::default(), |
104 | }; | 102 | }; |
105 | if let Some(module) = krate.root_module(db) { | 103 | if let Some(module) = krate.root_module(db) { |
106 | crate_impl_blocks.collect_recursive(db, module); | 104 | crate_impl_blocks.collect_recursive(db, &module); |
107 | } | 105 | } |
108 | Arc::new(crate_impl_blocks) | 106 | Arc::new(crate_impl_blocks) |
109 | } | 107 | } |
@@ -120,11 +118,11 @@ impl Ty { | |||
120 | // TODO: cache this as a query? | 118 | // TODO: cache this as a query? |
121 | // - if so, what signature? (TyFingerprint, Name)? | 119 | // - if so, what signature? (TyFingerprint, Name)? |
122 | // - or maybe cache all names and def_ids of methods per fingerprint? | 120 | // - or maybe cache all names and def_ids of methods per fingerprint? |
123 | pub fn lookup_method(self, db: &impl HirDatabase, name: &Name) -> Option<DefId> { | 121 | pub fn lookup_method(self, db: &impl HirDatabase, name: &Name) -> Option<Function> { |
124 | self.iterate_methods(db, |f| { | 122 | self.iterate_methods(db, |f| { |
125 | let sig = f.signature(db); | 123 | let sig = f.signature(db); |
126 | if sig.name() == name && sig.has_self_param() { | 124 | if sig.name() == name && sig.has_self_param() { |
127 | Some(f.def_id()) | 125 | Some(f) |
128 | } else { | 126 | } else { |
129 | None | 127 | None |
130 | } | 128 | } |
diff --git a/crates/ra_hir/src/ty/snapshots/tests__infer_struct.snap b/crates/ra_hir/src/ty/snapshots/tests__infer_struct.snap index c4a2d5cf8..8747fae18 100644 --- a/crates/ra_hir/src/ty/snapshots/tests__infer_struct.snap +++ b/crates/ra_hir/src/ty/snapshots/tests__infer_struct.snap | |||
@@ -1,19 +1,19 @@ | |||
1 | --- | 1 | --- |
2 | created: "2019-01-22T14:45:00.058678600+00:00" | 2 | created: "2019-01-24T14:51:32.808861856+00:00" |
3 | creator: insta@0.4.0 | 3 | creator: insta@0.5.2 |
4 | expression: "&result" | 4 | expression: "&result" |
5 | source: "crates\\ra_hir\\src\\ty\\tests.rs" | 5 | source: crates/ra_hir/src/ty/tests.rs |
6 | --- | 6 | --- |
7 | [72; 154) '{ ...a.c; }': () | 7 | [72; 154) '{ ...a.c; }': () |
8 | [82; 83) 'c': [unknown] | 8 | [82; 83) 'c': [unknown] |
9 | [86; 87) 'C': [unknown] | 9 | [86; 87) 'C': C |
10 | [86; 90) 'C(1)': [unknown] | 10 | [86; 90) 'C(1)': [unknown] |
11 | [88; 89) '1': i32 | 11 | [88; 89) '1': i32 |
12 | [96; 97) 'B': [unknown] | 12 | [96; 97) 'B': B |
13 | [107; 108) 'a': A | 13 | [107; 108) 'a': A |
14 | [114; 133) 'A { b:...C(1) }': A | 14 | [114; 133) 'A { b:...C(1) }': A |
15 | [121; 122) 'B': B | 15 | [121; 122) 'B': B |
16 | [127; 128) 'C': [unknown] | 16 | [127; 128) 'C': C |
17 | [127; 131) 'C(1)': C | 17 | [127; 131) 'C(1)': C |
18 | [129; 130) '1': i32 | 18 | [129; 130) '1': i32 |
19 | [139; 140) 'a': A | 19 | [139; 140) 'a': A |
diff --git a/crates/ra_ide_api/src/completion/complete_dot.rs b/crates/ra_ide_api/src/completion/complete_dot.rs index 07007d03f..6a9358d33 100644 --- a/crates/ra_ide_api/src/completion/complete_dot.rs +++ b/crates/ra_ide_api/src/completion/complete_dot.rs | |||
@@ -1,4 +1,4 @@ | |||
1 | use hir::{Ty, Def}; | 1 | use hir::{Ty, AdtDef}; |
2 | 2 | ||
3 | use crate::completion::{CompletionContext, Completions, CompletionItem, CompletionItemKind}; | 3 | use crate::completion::{CompletionContext, Completions, CompletionItem, CompletionItemKind}; |
4 | use crate::completion::completion_item::CompletionKind; | 4 | use crate::completion::completion_item::CompletionKind; |
@@ -28,8 +28,8 @@ fn complete_fields(acc: &mut Completions, ctx: &CompletionContext, receiver: Ty) | |||
28 | Ty::Adt { | 28 | Ty::Adt { |
29 | def_id, ref substs, .. | 29 | def_id, ref substs, .. |
30 | } => { | 30 | } => { |
31 | match def_id.resolve(ctx.db) { | 31 | match def_id { |
32 | Def::Struct(s) => { | 32 | AdtDef::Struct(s) => { |
33 | for field in s.fields(ctx.db) { | 33 | for field in s.fields(ctx.db) { |
34 | CompletionItem::new( | 34 | CompletionItem::new( |
35 | CompletionKind::Reference, | 35 | CompletionKind::Reference, |
@@ -41,8 +41,9 @@ fn complete_fields(acc: &mut Completions, ctx: &CompletionContext, receiver: Ty) | |||
41 | .add_to(acc); | 41 | .add_to(acc); |
42 | } | 42 | } |
43 | } | 43 | } |
44 | |||
44 | // TODO unions | 45 | // TODO unions |
45 | _ => {} | 46 | AdtDef::Enum(_) => (), |
46 | } | 47 | } |
47 | } | 48 | } |
48 | Ty::Tuple(fields) => { | 49 | Ty::Tuple(fields) => { |
diff --git a/crates/ra_ide_api/src/completion/complete_path.rs b/crates/ra_ide_api/src/completion/complete_path.rs index e44b76c4a..e72586e2e 100644 --- a/crates/ra_ide_api/src/completion/complete_path.rs +++ b/crates/ra_ide_api/src/completion/complete_path.rs | |||
@@ -13,8 +13,8 @@ pub(super) fn complete_path(acc: &mut Completions, ctx: &CompletionContext) { | |||
13 | Some(it) => it, | 13 | Some(it) => it, |
14 | None => return, | 14 | None => return, |
15 | }; | 15 | }; |
16 | match def_id.resolve(ctx.db) { | 16 | match def_id { |
17 | hir::Def::Module(module) => { | 17 | hir::ModuleDef::Module(module) => { |
18 | let module_scope = module.scope(ctx.db); | 18 | let module_scope = module.scope(ctx.db); |
19 | for (name, res) in module_scope.entries() { | 19 | for (name, res) in module_scope.entries() { |
20 | CompletionItem::new( | 20 | CompletionItem::new( |
@@ -26,7 +26,7 @@ pub(super) fn complete_path(acc: &mut Completions, ctx: &CompletionContext) { | |||
26 | .add_to(acc); | 26 | .add_to(acc); |
27 | } | 27 | } |
28 | } | 28 | } |
29 | hir::Def::Enum(e) => { | 29 | hir::ModuleDef::Enum(e) => { |
30 | e.variants(ctx.db) | 30 | e.variants(ctx.db) |
31 | .into_iter() | 31 | .into_iter() |
32 | .for_each(|(variant_name, variant)| { | 32 | .for_each(|(variant_name, variant)| { |
diff --git a/crates/ra_ide_api/src/completion/completion_context.rs b/crates/ra_ide_api/src/completion/completion_context.rs index ca2069e2a..578af6e5b 100644 --- a/crates/ra_ide_api/src/completion/completion_context.rs +++ b/crates/ra_ide_api/src/completion/completion_context.rs | |||
@@ -127,7 +127,7 @@ impl<'a> CompletionContext<'a> { | |||
127 | .ancestors() | 127 | .ancestors() |
128 | .take_while(|it| it.kind() != SOURCE_FILE && it.kind() != MODULE) | 128 | .take_while(|it| it.kind() != SOURCE_FILE && it.kind() != MODULE) |
129 | .find_map(ast::FnDef::cast); | 129 | .find_map(ast::FnDef::cast); |
130 | match (&self.module, self.function_syntax) { | 130 | match (self.module, self.function_syntax) { |
131 | (Some(module), Some(fn_def)) => { | 131 | (Some(module), Some(fn_def)) => { |
132 | let function = source_binder::function_from_module(self.db, module, fn_def); | 132 | let function = source_binder::function_from_module(self.db, module, fn_def); |
133 | self.function = Some(function); | 133 | self.function = Some(function); |
diff --git a/crates/ra_ide_api/src/completion/completion_item.rs b/crates/ra_ide_api/src/completion/completion_item.rs index 18c151932..3ba6c33ee 100644 --- a/crates/ra_ide_api/src/completion/completion_item.rs +++ b/crates/ra_ide_api/src/completion/completion_item.rs | |||
@@ -1,6 +1,4 @@ | |||
1 | use hir::{Docs, Documentation, PerNs}; | 1 | use hir::{Docs, Documentation}; |
2 | |||
3 | use crate::completion::completion_context::CompletionContext; | ||
4 | use ra_syntax::{ | 2 | use ra_syntax::{ |
5 | ast::{self, AstNode}, | 3 | ast::{self, AstNode}, |
6 | TextRange, | 4 | TextRange, |
@@ -8,6 +6,8 @@ use ra_syntax::{ | |||
8 | use ra_text_edit::TextEdit; | 6 | use ra_text_edit::TextEdit; |
9 | use test_utils::tested_by; | 7 | use test_utils::tested_by; |
10 | 8 | ||
9 | use crate::completion::completion_context::CompletionContext; | ||
10 | |||
11 | /// `CompletionItem` describes a single completion variant in the editor pop-up. | 11 | /// `CompletionItem` describes a single completion variant in the editor pop-up. |
12 | /// It is basically a POD with various properties. To construct a | 12 | /// It is basically a POD with various properties. To construct a |
13 | /// `CompletionItem`, use `new` method and the `Builder` struct. | 13 | /// `CompletionItem`, use `new` method and the `Builder` struct. |
@@ -209,41 +209,24 @@ impl Builder { | |||
209 | ctx: &CompletionContext, | 209 | ctx: &CompletionContext, |
210 | resolution: &hir::Resolution, | 210 | resolution: &hir::Resolution, |
211 | ) -> Builder { | 211 | ) -> Builder { |
212 | let resolved = resolution.def_id.map(|d| d.resolve(ctx.db)); | 212 | let def = resolution |
213 | let (kind, docs) = match resolved { | 213 | .def_id |
214 | PerNs { | 214 | .take_types() |
215 | types: Some(hir::Def::Module(..)), | 215 | .or(resolution.def_id.take_values()); |
216 | .. | 216 | let def = match def { |
217 | } => (CompletionItemKind::Module, None), | 217 | None => return self, |
218 | PerNs { | 218 | Some(it) => it, |
219 | types: Some(hir::Def::Struct(s)), | 219 | }; |
220 | .. | 220 | let (kind, docs) = match def { |
221 | } => (CompletionItemKind::Struct, s.docs(ctx.db)), | 221 | hir::ModuleDef::Module(_) => (CompletionItemKind::Module, None), |
222 | PerNs { | 222 | hir::ModuleDef::Function(func) => return self.from_function(ctx, func), |
223 | types: Some(hir::Def::Enum(e)), | 223 | hir::ModuleDef::Struct(it) => (CompletionItemKind::Struct, it.docs(ctx.db)), |
224 | .. | 224 | hir::ModuleDef::Enum(it) => (CompletionItemKind::Enum, it.docs(ctx.db)), |
225 | } => (CompletionItemKind::Enum, e.docs(ctx.db)), | 225 | hir::ModuleDef::EnumVariant(it) => (CompletionItemKind::EnumVariant, it.docs(ctx.db)), |
226 | PerNs { | 226 | hir::ModuleDef::Const(it) => (CompletionItemKind::Const, it.docs(ctx.db)), |
227 | types: Some(hir::Def::Trait(t)), | 227 | hir::ModuleDef::Static(it) => (CompletionItemKind::Static, it.docs(ctx.db)), |
228 | .. | 228 | hir::ModuleDef::Trait(it) => (CompletionItemKind::Trait, it.docs(ctx.db)), |
229 | } => (CompletionItemKind::Trait, t.docs(ctx.db)), | 229 | hir::ModuleDef::Type(it) => (CompletionItemKind::TypeAlias, it.docs(ctx.db)), |
230 | PerNs { | ||
231 | types: Some(hir::Def::Type(t)), | ||
232 | .. | ||
233 | } => (CompletionItemKind::TypeAlias, t.docs(ctx.db)), | ||
234 | PerNs { | ||
235 | values: Some(hir::Def::Const(c)), | ||
236 | .. | ||
237 | } => (CompletionItemKind::Const, c.docs(ctx.db)), | ||
238 | PerNs { | ||
239 | values: Some(hir::Def::Static(s)), | ||
240 | .. | ||
241 | } => (CompletionItemKind::Static, s.docs(ctx.db)), | ||
242 | PerNs { | ||
243 | values: Some(hir::Def::Function(function)), | ||
244 | .. | ||
245 | } => return self.from_function(ctx, function), | ||
246 | _ => return self, | ||
247 | }; | 230 | }; |
248 | self.kind = Some(kind); | 231 | self.kind = Some(kind); |
249 | self.documentation = docs; | 232 | self.documentation = docs; |
diff --git a/crates/ra_ide_api/src/db.rs b/crates/ra_ide_api/src/db.rs index ba0eb1cb8..bff6b7237 100644 --- a/crates/ra_ide_api/src/db.rs +++ b/crates/ra_ide_api/src/db.rs | |||
@@ -72,6 +72,7 @@ salsa::database_storage! { | |||
72 | fn file_relative_path() for ra_db::FileRelativePathQuery; | 72 | fn file_relative_path() for ra_db::FileRelativePathQuery; |
73 | fn file_source_root() for ra_db::FileSourceRootQuery; | 73 | fn file_source_root() for ra_db::FileSourceRootQuery; |
74 | fn source_root() for ra_db::SourceRootQuery; | 74 | fn source_root() for ra_db::SourceRootQuery; |
75 | fn source_root_crates() for ra_db::SourceRootCratesQuery; | ||
75 | fn local_roots() for ra_db::LocalRootsQuery; | 76 | fn local_roots() for ra_db::LocalRootsQuery; |
76 | fn library_roots() for ra_db::LibraryRootsQuery; | 77 | fn library_roots() for ra_db::LibraryRootsQuery; |
77 | fn crate_graph() for ra_db::CrateGraphQuery; | 78 | fn crate_graph() for ra_db::CrateGraphQuery; |
diff --git a/crates/ra_ide_api/src/goto_definition.rs b/crates/ra_ide_api/src/goto_definition.rs index b1becca03..46bdde00d 100644 --- a/crates/ra_ide_api/src/goto_definition.rs +++ b/crates/ra_ide_api/src/goto_definition.rs | |||
@@ -63,13 +63,11 @@ pub(crate) fn reference_definition( | |||
63 | let infer_result = function.infer(db); | 63 | let infer_result = function.infer(db); |
64 | let syntax_mapping = function.body_syntax_mapping(db); | 64 | let syntax_mapping = function.body_syntax_mapping(db); |
65 | let expr = ast::Expr::cast(method_call.syntax()).unwrap(); | 65 | let expr = ast::Expr::cast(method_call.syntax()).unwrap(); |
66 | if let Some(def_id) = syntax_mapping | 66 | if let Some(func) = syntax_mapping |
67 | .node_expr(expr) | 67 | .node_expr(expr) |
68 | .and_then(|it| infer_result.method_resolution(it)) | 68 | .and_then(|it| infer_result.method_resolution(it)) |
69 | { | 69 | { |
70 | if let Some(target) = NavigationTarget::from_def(db, def_id.resolve(db)) { | 70 | return Exact(NavigationTarget::from_function(db, func)); |
71 | return Exact(target); | ||
72 | } | ||
73 | }; | 71 | }; |
74 | } | 72 | } |
75 | } | 73 | } |
@@ -84,7 +82,7 @@ pub(crate) fn reference_definition( | |||
84 | { | 82 | { |
85 | let resolved = module.resolve_path(db, &path); | 83 | let resolved = module.resolve_path(db, &path); |
86 | if let Some(def_id) = resolved.take_types().or(resolved.take_values()) { | 84 | if let Some(def_id) = resolved.take_types().or(resolved.take_values()) { |
87 | if let Some(target) = NavigationTarget::from_def(db, def_id.resolve(db)) { | 85 | if let Some(target) = NavigationTarget::from_def(db, def_id) { |
88 | return Exact(target); | 86 | return Exact(target); |
89 | } | 87 | } |
90 | } | 88 | } |
diff --git a/crates/ra_ide_api/src/navigation_target.rs b/crates/ra_ide_api/src/navigation_target.rs index 21c15c0c0..c5be8e01b 100644 --- a/crates/ra_ide_api/src/navigation_target.rs +++ b/crates/ra_ide_api/src/navigation_target.rs | |||
@@ -3,7 +3,7 @@ use ra_syntax::{ | |||
3 | SyntaxNode, AstNode, SmolStr, TextRange, ast, | 3 | SyntaxNode, AstNode, SmolStr, TextRange, ast, |
4 | SyntaxKind::{self, NAME}, | 4 | SyntaxKind::{self, NAME}, |
5 | }; | 5 | }; |
6 | use hir::{Def, ModuleSource}; | 6 | use hir::{ModuleSource}; |
7 | 7 | ||
8 | use crate::{FileSymbol, db::RootDatabase}; | 8 | use crate::{FileSymbol, db::RootDatabase}; |
9 | 9 | ||
@@ -96,45 +96,69 @@ impl NavigationTarget { | |||
96 | NavigationTarget::from_module(db, module) | 96 | NavigationTarget::from_module(db, module) |
97 | } | 97 | } |
98 | 98 | ||
99 | pub(crate) fn from_function(db: &RootDatabase, func: hir::Function) -> NavigationTarget { | ||
100 | let (file_id, fn_def) = func.source(db); | ||
101 | NavigationTarget::from_named(file_id.original_file(db), &*fn_def) | ||
102 | } | ||
103 | |||
99 | // TODO once Def::Item is gone, this should be able to always return a NavigationTarget | 104 | // TODO once Def::Item is gone, this should be able to always return a NavigationTarget |
100 | pub(crate) fn from_def(db: &RootDatabase, def: Def) -> Option<NavigationTarget> { | 105 | pub(crate) fn from_def( |
101 | let res = match def { | 106 | db: &RootDatabase, |
102 | Def::Struct(s) => { | 107 | module_def: hir::ModuleDef, |
108 | ) -> Option<NavigationTarget> { | ||
109 | match module_def { | ||
110 | hir::ModuleDef::Module(module) => Some(NavigationTarget::from_module(db, module)), | ||
111 | hir::ModuleDef::Function(func) => Some(NavigationTarget::from_function(db, func)), | ||
112 | hir::ModuleDef::Struct(s) => { | ||
103 | let (file_id, node) = s.source(db); | 113 | let (file_id, node) = s.source(db); |
104 | NavigationTarget::from_named(file_id.original_file(db), &*node) | 114 | Some(NavigationTarget::from_named( |
115 | file_id.original_file(db), | ||
116 | &*node, | ||
117 | )) | ||
105 | } | 118 | } |
106 | Def::Enum(e) => { | 119 | hir::ModuleDef::Const(s) => { |
107 | let (file_id, node) = e.source(db); | 120 | let (file_id, node) = s.source(db); |
108 | NavigationTarget::from_named(file_id.original_file(db), &*node) | 121 | Some(NavigationTarget::from_named( |
109 | } | 122 | file_id.original_file(db), |
110 | Def::EnumVariant(ev) => { | 123 | &*node, |
111 | let (file_id, node) = ev.source(db); | 124 | )) |
112 | NavigationTarget::from_named(file_id.original_file(db), &*node) | ||
113 | } | 125 | } |
114 | Def::Function(f) => { | 126 | hir::ModuleDef::Static(s) => { |
115 | let (file_id, node) = f.source(db); | 127 | let (file_id, node) = s.source(db); |
116 | NavigationTarget::from_named(file_id.original_file(db), &*node) | 128 | Some(NavigationTarget::from_named( |
129 | file_id.original_file(db), | ||
130 | &*node, | ||
131 | )) | ||
117 | } | 132 | } |
118 | Def::Trait(f) => { | 133 | hir::ModuleDef::Enum(e) => { |
119 | let (file_id, node) = f.source(db); | 134 | let (file_id, node) = e.source(db); |
120 | NavigationTarget::from_named(file_id.original_file(db), &*node) | 135 | Some(NavigationTarget::from_named( |
136 | file_id.original_file(db), | ||
137 | &*node, | ||
138 | )) | ||
121 | } | 139 | } |
122 | Def::Type(f) => { | 140 | hir::ModuleDef::EnumVariant(var) => { |
123 | let (file_id, node) = f.source(db); | 141 | let (file_id, node) = var.source(db); |
124 | NavigationTarget::from_named(file_id.original_file(db), &*node) | 142 | Some(NavigationTarget::from_named( |
143 | file_id.original_file(db), | ||
144 | &*node, | ||
145 | )) | ||
125 | } | 146 | } |
126 | Def::Static(f) => { | 147 | hir::ModuleDef::Trait(e) => { |
127 | let (file_id, node) = f.source(db); | 148 | let (file_id, node) = e.source(db); |
128 | NavigationTarget::from_named(file_id.original_file(db), &*node) | 149 | Some(NavigationTarget::from_named( |
150 | file_id.original_file(db), | ||
151 | &*node, | ||
152 | )) | ||
129 | } | 153 | } |
130 | Def::Const(f) => { | 154 | hir::ModuleDef::Type(e) => { |
131 | let (file_id, node) = f.source(db); | 155 | let (file_id, node) = e.source(db); |
132 | NavigationTarget::from_named(file_id.original_file(db), &*node) | 156 | Some(NavigationTarget::from_named( |
157 | file_id.original_file(db), | ||
158 | &*node, | ||
159 | )) | ||
133 | } | 160 | } |
134 | Def::Module(m) => NavigationTarget::from_module(db, m), | 161 | } |
135 | Def::Item => return None, | ||
136 | }; | ||
137 | Some(res) | ||
138 | } | 162 | } |
139 | 163 | ||
140 | #[cfg(test)] | 164 | #[cfg(test)] |
diff --git a/crates/ra_ide_api/src/rename.rs b/crates/ra_ide_api/src/rename.rs index 53dc273c6..5b767addd 100644 --- a/crates/ra_ide_api/src/rename.rs +++ b/crates/ra_ide_api/src/rename.rs | |||
@@ -57,7 +57,6 @@ fn rename_mod( | |||
57 | ) -> Option<SourceChange> { | 57 | ) -> Option<SourceChange> { |
58 | let mut source_file_edits = Vec::new(); | 58 | let mut source_file_edits = Vec::new(); |
59 | let mut file_system_edits = Vec::new(); | 59 | let mut file_system_edits = Vec::new(); |
60 | |||
61 | if let Some(module) = module_from_declaration(db, position.file_id, &ast_module) { | 60 | if let Some(module) = module_from_declaration(db, position.file_id, &ast_module) { |
62 | let (file_id, module_source) = module.definition_source(db); | 61 | let (file_id, module_source) = module.definition_source(db); |
63 | match module_source { | 62 | match module_source { |
@@ -223,11 +222,15 @@ mod tests { | |||
223 | fn test_rename_mod() { | 222 | fn test_rename_mod() { |
224 | let (analysis, position) = analysis_and_position( | 223 | let (analysis, position) = analysis_and_position( |
225 | " | 224 | " |
226 | //- /bar.rs | 225 | //- /lib.rs |
227 | mod fo<|>o; | 226 | mod bar; |
228 | //- /bar/foo.rs | 227 | |
229 | // emtpy | 228 | //- /bar.rs |
230 | ", | 229 | mod foo<|>; |
230 | |||
231 | //- /bar/foo.rs | ||
232 | // emtpy | ||
233 | ", | ||
231 | ); | 234 | ); |
232 | let new_name = "foo2"; | 235 | let new_name = "foo2"; |
233 | let source_change = analysis.rename(position, new_name).unwrap(); | 236 | let source_change = analysis.rename(position, new_name).unwrap(); |
@@ -238,11 +241,11 @@ mod tests { | |||
238 | fn test_rename_mod_in_dir() { | 241 | fn test_rename_mod_in_dir() { |
239 | let (analysis, position) = analysis_and_position( | 242 | let (analysis, position) = analysis_and_position( |
240 | " | 243 | " |
241 | //- /lib.rs | 244 | //- /lib.rs |
242 | mod fo<|>o; | 245 | mod fo<|>o; |
243 | //- /foo/mod.rs | 246 | //- /foo/mod.rs |
244 | // emtpy | 247 | // emtpy |
245 | ", | 248 | ", |
246 | ); | 249 | ); |
247 | let new_name = "foo2"; | 250 | let new_name = "foo2"; |
248 | let source_change = analysis.rename(position, new_name).unwrap(); | 251 | let source_change = analysis.rename(position, new_name).unwrap(); |
diff --git a/crates/ra_ide_api/src/snapshots/tests__rename_mod.snap b/crates/ra_ide_api/src/snapshots/tests__rename_mod.snap index 3267d1ac5..890426db7 100644 --- a/crates/ra_ide_api/src/snapshots/tests__rename_mod.snap +++ b/crates/ra_ide_api/src/snapshots/tests__rename_mod.snap | |||
@@ -1,8 +1,8 @@ | |||
1 | --- | 1 | --- |
2 | created: "2019-01-22T14:45:00.975229300+00:00" | 2 | created: "2019-01-24T08:39:53.759318522+00:00" |
3 | creator: insta@0.4.0 | 3 | creator: insta@0.5.2 |
4 | expression: "&source_change" | 4 | expression: "&source_change" |
5 | source: "crates\\ra_ide_api\\src\\rename.rs" | 5 | source: crates/ra_ide_api/src/rename.rs |
6 | --- | 6 | --- |
7 | Some( | 7 | Some( |
8 | SourceChange { | 8 | SourceChange { |
@@ -10,7 +10,7 @@ Some( | |||
10 | source_file_edits: [ | 10 | source_file_edits: [ |
11 | SourceFileEdit { | 11 | SourceFileEdit { |
12 | file_id: FileId( | 12 | file_id: FileId( |
13 | 1 | 13 | 2 |
14 | ), | 14 | ), |
15 | edit: TextEdit { | 15 | edit: TextEdit { |
16 | atoms: [ | 16 | atoms: [ |
@@ -25,7 +25,7 @@ Some( | |||
25 | file_system_edits: [ | 25 | file_system_edits: [ |
26 | MoveFile { | 26 | MoveFile { |
27 | src: FileId( | 27 | src: FileId( |
28 | 2 | 28 | 3 |
29 | ), | 29 | ), |
30 | dst_source_root: SourceRootId( | 30 | dst_source_root: SourceRootId( |
31 | 0 | 31 | 0 |
diff --git a/crates/ra_syntax/src/ast.rs b/crates/ra_syntax/src/ast.rs index b92cc082e..165b308d1 100644 --- a/crates/ra_syntax/src/ast.rs +++ b/crates/ra_syntax/src/ast.rs | |||
@@ -431,6 +431,13 @@ impl StructDef { | |||
431 | } | 431 | } |
432 | 432 | ||
433 | impl EnumVariant { | 433 | impl EnumVariant { |
434 | pub fn parent_enum(&self) -> &EnumDef { | ||
435 | self.syntax() | ||
436 | .parent() | ||
437 | .and_then(|it| it.parent()) | ||
438 | .and_then(EnumDef::cast) | ||
439 | .expect("EnumVariants are always nested in Enums") | ||
440 | } | ||
434 | pub fn flavor(&self) -> StructFlavor { | 441 | pub fn flavor(&self) -> StructFlavor { |
435 | StructFlavor::from_node(self) | 442 | StructFlavor::from_node(self) |
436 | } | 443 | } |
diff --git a/crates/ra_syntax/src/ast/generated.rs b/crates/ra_syntax/src/ast/generated.rs index e39b58827..bb223e0dc 100644 --- a/crates/ra_syntax/src/ast/generated.rs +++ b/crates/ra_syntax/src/ast/generated.rs | |||
@@ -3649,6 +3649,7 @@ impl ast::VisibilityOwner for TraitDef {} | |||
3649 | impl ast::NameOwner for TraitDef {} | 3649 | impl ast::NameOwner for TraitDef {} |
3650 | impl ast::AttrsOwner for TraitDef {} | 3650 | impl ast::AttrsOwner for TraitDef {} |
3651 | impl ast::DocCommentsOwner for TraitDef {} | 3651 | impl ast::DocCommentsOwner for TraitDef {} |
3652 | impl ast::TypeParamsOwner for TraitDef {} | ||
3652 | impl TraitDef {} | 3653 | impl TraitDef {} |
3653 | 3654 | ||
3654 | // TrueKw | 3655 | // TrueKw |
diff --git a/crates/ra_syntax/src/grammar.ron b/crates/ra_syntax/src/grammar.ron index c5297e46d..dedefea59 100644 --- a/crates/ra_syntax/src/grammar.ron +++ b/crates/ra_syntax/src/grammar.ron | |||
@@ -280,7 +280,7 @@ Grammar( | |||
280 | ], options: [["variant_list", "EnumVariantList"]] ), | 280 | ], options: [["variant_list", "EnumVariantList"]] ), |
281 | "EnumVariantList": ( collections: [["variants", "EnumVariant"]] ), | 281 | "EnumVariantList": ( collections: [["variants", "EnumVariant"]] ), |
282 | "EnumVariant": ( traits: ["NameOwner", "DocCommentsOwner"], options: ["Expr"] ), | 282 | "EnumVariant": ( traits: ["NameOwner", "DocCommentsOwner"], options: ["Expr"] ), |
283 | "TraitDef": ( traits: ["VisibilityOwner", "NameOwner", "AttrsOwner", "DocCommentsOwner"] ), | 283 | "TraitDef": ( traits: ["VisibilityOwner", "NameOwner", "AttrsOwner", "DocCommentsOwner", "TypeParamsOwner"] ), |
284 | "Module": ( | 284 | "Module": ( |
285 | traits: ["VisibilityOwner", "NameOwner", "AttrsOwner", "DocCommentsOwner" ], | 285 | traits: ["VisibilityOwner", "NameOwner", "AttrsOwner", "DocCommentsOwner" ], |
286 | options: [ "ItemList" ] | 286 | options: [ "ItemList" ] |
@@ -489,7 +489,7 @@ Grammar( | |||
489 | ), | 489 | ), |
490 | 490 | ||
491 | "RefPat": ( options: [ "Pat" ]), | 491 | "RefPat": ( options: [ "Pat" ]), |
492 | "BindPat": ( | 492 | "BindPat": ( |
493 | options: [ "Pat" ], | 493 | options: [ "Pat" ], |
494 | traits: ["NameOwner"] | 494 | traits: ["NameOwner"] |
495 | ), | 495 | ), |