diff options
Diffstat (limited to 'crates/hir_def')
-rw-r--r-- | crates/hir_def/src/attr.rs | 312 | ||||
-rw-r--r-- | crates/hir_def/src/db.rs | 6 |
2 files changed, 192 insertions, 126 deletions
diff --git a/crates/hir_def/src/attr.rs b/crates/hir_def/src/attr.rs index beeaaf117..2c10f46d8 100644 --- a/crates/hir_def/src/attr.rs +++ b/crates/hir_def/src/attr.rs | |||
@@ -21,7 +21,7 @@ use crate::{ | |||
21 | item_tree::{ItemTreeId, ItemTreeNode}, | 21 | item_tree::{ItemTreeId, ItemTreeNode}, |
22 | nameres::ModuleSource, | 22 | nameres::ModuleSource, |
23 | path::{ModPath, PathKind}, | 23 | path::{ModPath, PathKind}, |
24 | src::HasChildSource, | 24 | src::{HasChildSource, HasSource}, |
25 | AdtId, AttrDefId, EnumId, GenericParamId, HasModule, LocalEnumVariantId, LocalFieldId, Lookup, | 25 | AdtId, AttrDefId, EnumId, GenericParamId, HasModule, LocalEnumVariantId, LocalFieldId, Lookup, |
26 | VariantId, | 26 | VariantId, |
27 | }; | 27 | }; |
@@ -51,6 +51,12 @@ pub(crate) struct RawAttrs { | |||
51 | #[derive(Default, Debug, Clone, PartialEq, Eq)] | 51 | #[derive(Default, Debug, Clone, PartialEq, Eq)] |
52 | pub struct Attrs(RawAttrs); | 52 | pub struct Attrs(RawAttrs); |
53 | 53 | ||
54 | #[derive(Debug, Clone, PartialEq, Eq)] | ||
55 | pub struct AttrsWithOwner { | ||
56 | attrs: Attrs, | ||
57 | owner: AttrDefId, | ||
58 | } | ||
59 | |||
54 | impl ops::Deref for RawAttrs { | 60 | impl ops::Deref for RawAttrs { |
55 | type Target = [Attr]; | 61 | type Target = [Attr]; |
56 | 62 | ||
@@ -73,6 +79,14 @@ impl ops::Deref for Attrs { | |||
73 | } | 79 | } |
74 | } | 80 | } |
75 | 81 | ||
82 | impl ops::Deref for AttrsWithOwner { | ||
83 | type Target = Attrs; | ||
84 | |||
85 | fn deref(&self) -> &Attrs { | ||
86 | &self.attrs | ||
87 | } | ||
88 | } | ||
89 | |||
76 | impl RawAttrs { | 90 | impl RawAttrs { |
77 | pub(crate) const EMPTY: Self = Self { entries: None }; | 91 | pub(crate) const EMPTY: Self = Self { entries: None }; |
78 | 92 | ||
@@ -169,78 +183,6 @@ impl RawAttrs { | |||
169 | impl Attrs { | 183 | impl Attrs { |
170 | pub const EMPTY: Self = Self(RawAttrs::EMPTY); | 184 | pub const EMPTY: Self = Self(RawAttrs::EMPTY); |
171 | 185 | ||
172 | pub(crate) fn attrs_query(db: &dyn DefDatabase, def: AttrDefId) -> Attrs { | ||
173 | let raw_attrs = match def { | ||
174 | AttrDefId::ModuleId(module) => { | ||
175 | let def_map = module.def_map(db); | ||
176 | let mod_data = &def_map[module.local_id]; | ||
177 | match mod_data.declaration_source(db) { | ||
178 | Some(it) => { | ||
179 | let raw_attrs = RawAttrs::from_attrs_owner( | ||
180 | db, | ||
181 | it.as_ref().map(|it| it as &dyn ast::AttrsOwner), | ||
182 | ); | ||
183 | match mod_data.definition_source(db) { | ||
184 | InFile { file_id, value: ModuleSource::SourceFile(file) } => raw_attrs | ||
185 | .merge(RawAttrs::from_attrs_owner(db, InFile::new(file_id, &file))), | ||
186 | _ => raw_attrs, | ||
187 | } | ||
188 | } | ||
189 | None => RawAttrs::from_attrs_owner( | ||
190 | db, | ||
191 | mod_data.definition_source(db).as_ref().map(|src| match src { | ||
192 | ModuleSource::SourceFile(file) => file as &dyn ast::AttrsOwner, | ||
193 | ModuleSource::Module(module) => module as &dyn ast::AttrsOwner, | ||
194 | ModuleSource::BlockExpr(block) => block as &dyn ast::AttrsOwner, | ||
195 | }), | ||
196 | ), | ||
197 | } | ||
198 | } | ||
199 | AttrDefId::FieldId(it) => { | ||
200 | return db.fields_attrs(it.parent)[it.local_id].clone(); | ||
201 | } | ||
202 | AttrDefId::EnumVariantId(it) => { | ||
203 | return db.variants_attrs(it.parent)[it.local_id].clone(); | ||
204 | } | ||
205 | AttrDefId::AdtId(it) => match it { | ||
206 | AdtId::StructId(it) => attrs_from_item_tree(it.lookup(db).id, db), | ||
207 | AdtId::EnumId(it) => attrs_from_item_tree(it.lookup(db).id, db), | ||
208 | AdtId::UnionId(it) => attrs_from_item_tree(it.lookup(db).id, db), | ||
209 | }, | ||
210 | AttrDefId::TraitId(it) => attrs_from_item_tree(it.lookup(db).id, db), | ||
211 | AttrDefId::MacroDefId(it) => it | ||
212 | .ast_id() | ||
213 | .left() | ||
214 | .map_or_else(Default::default, |ast_id| attrs_from_ast(ast_id, db)), | ||
215 | AttrDefId::ImplId(it) => attrs_from_item_tree(it.lookup(db).id, db), | ||
216 | AttrDefId::ConstId(it) => attrs_from_item_tree(it.lookup(db).id, db), | ||
217 | AttrDefId::StaticId(it) => attrs_from_item_tree(it.lookup(db).id, db), | ||
218 | AttrDefId::FunctionId(it) => attrs_from_item_tree(it.lookup(db).id, db), | ||
219 | AttrDefId::TypeAliasId(it) => attrs_from_item_tree(it.lookup(db).id, db), | ||
220 | AttrDefId::GenericParamId(it) => match it { | ||
221 | GenericParamId::TypeParamId(it) => { | ||
222 | let src = it.parent.child_source(db); | ||
223 | RawAttrs::from_attrs_owner( | ||
224 | db, | ||
225 | src.with_value( | ||
226 | src.value[it.local_id].as_ref().either(|it| it as _, |it| it as _), | ||
227 | ), | ||
228 | ) | ||
229 | } | ||
230 | GenericParamId::LifetimeParamId(it) => { | ||
231 | let src = it.parent.child_source(db); | ||
232 | RawAttrs::from_attrs_owner(db, src.with_value(&src.value[it.local_id])) | ||
233 | } | ||
234 | GenericParamId::ConstParamId(it) => { | ||
235 | let src = it.parent.child_source(db); | ||
236 | RawAttrs::from_attrs_owner(db, src.with_value(&src.value[it.local_id])) | ||
237 | } | ||
238 | }, | ||
239 | }; | ||
240 | |||
241 | raw_attrs.filter(db, def.krate(db)) | ||
242 | } | ||
243 | |||
244 | pub(crate) fn variants_attrs_query( | 186 | pub(crate) fn variants_attrs_query( |
245 | db: &dyn DefDatabase, | 187 | db: &dyn DefDatabase, |
246 | e: EnumId, | 188 | e: EnumId, |
@@ -281,56 +223,6 @@ impl Attrs { | |||
281 | Arc::new(res) | 223 | Arc::new(res) |
282 | } | 224 | } |
283 | 225 | ||
284 | /// Constructs a map that maps the lowered `Attr`s in this `Attrs` back to its original syntax nodes. | ||
285 | /// | ||
286 | /// `owner` must be the original owner of the attributes. | ||
287 | // FIXME: figure out a better api that doesnt require the for_module hack | ||
288 | pub fn source_map(&self, owner: InFile<&dyn ast::AttrsOwner>) -> AttrSourceMap { | ||
289 | // FIXME: This doesn't work correctly for modules, as the attributes there can have up to | ||
290 | // two different owners | ||
291 | AttrSourceMap { | ||
292 | attrs: collect_attrs(owner.value) | ||
293 | .map(|attr| InFile::new(owner.file_id, attr)) | ||
294 | .collect(), | ||
295 | } | ||
296 | } | ||
297 | |||
298 | pub fn source_map_for_module( | ||
299 | &self, | ||
300 | db: &dyn DefDatabase, | ||
301 | module: crate::ModuleId, | ||
302 | ) -> AttrSourceMap { | ||
303 | let def_map = module.def_map(db); | ||
304 | let mod_data = &def_map[module.local_id]; | ||
305 | let attrs = match mod_data.declaration_source(db) { | ||
306 | Some(it) => { | ||
307 | let mut attrs: Vec<_> = collect_attrs(&it.value as &dyn ast::AttrsOwner) | ||
308 | .map(|attr| InFile::new(it.file_id, attr)) | ||
309 | .collect(); | ||
310 | if let InFile { file_id, value: ModuleSource::SourceFile(file) } = | ||
311 | mod_data.definition_source(db) | ||
312 | { | ||
313 | attrs.extend( | ||
314 | collect_attrs(&file as &dyn ast::AttrsOwner) | ||
315 | .map(|attr| InFile::new(file_id, attr)), | ||
316 | ) | ||
317 | } | ||
318 | attrs | ||
319 | } | ||
320 | None => { | ||
321 | let InFile { file_id, value } = mod_data.definition_source(db); | ||
322 | match &value { | ||
323 | ModuleSource::SourceFile(file) => collect_attrs(file as &dyn ast::AttrsOwner), | ||
324 | ModuleSource::Module(module) => collect_attrs(module as &dyn ast::AttrsOwner), | ||
325 | ModuleSource::BlockExpr(block) => collect_attrs(block as &dyn ast::AttrsOwner), | ||
326 | } | ||
327 | .map(|attr| InFile::new(file_id, attr)) | ||
328 | .collect() | ||
329 | } | ||
330 | }; | ||
331 | AttrSourceMap { attrs } | ||
332 | } | ||
333 | |||
334 | pub fn by_key(&self, key: &'static str) -> AttrQuery<'_> { | 226 | pub fn by_key(&self, key: &'static str) -> AttrQuery<'_> { |
335 | AttrQuery { attrs: self, key } | 227 | AttrQuery { attrs: self, key } |
336 | } | 228 | } |
@@ -387,6 +279,180 @@ impl Attrs { | |||
387 | } | 279 | } |
388 | } | 280 | } |
389 | 281 | ||
282 | impl AttrsWithOwner { | ||
283 | pub(crate) fn attrs_query(db: &dyn DefDatabase, def: AttrDefId) -> Self { | ||
284 | // FIXME: this should use `Trace` to avoid duplication in `source_map` below | ||
285 | let raw_attrs = match def { | ||
286 | AttrDefId::ModuleId(module) => { | ||
287 | let def_map = module.def_map(db); | ||
288 | let mod_data = &def_map[module.local_id]; | ||
289 | match mod_data.declaration_source(db) { | ||
290 | Some(it) => { | ||
291 | let raw_attrs = RawAttrs::from_attrs_owner( | ||
292 | db, | ||
293 | it.as_ref().map(|it| it as &dyn ast::AttrsOwner), | ||
294 | ); | ||
295 | match mod_data.definition_source(db) { | ||
296 | InFile { file_id, value: ModuleSource::SourceFile(file) } => raw_attrs | ||
297 | .merge(RawAttrs::from_attrs_owner(db, InFile::new(file_id, &file))), | ||
298 | _ => raw_attrs, | ||
299 | } | ||
300 | } | ||
301 | None => RawAttrs::from_attrs_owner( | ||
302 | db, | ||
303 | mod_data.definition_source(db).as_ref().map(|src| match src { | ||
304 | ModuleSource::SourceFile(file) => file as &dyn ast::AttrsOwner, | ||
305 | ModuleSource::Module(module) => module as &dyn ast::AttrsOwner, | ||
306 | ModuleSource::BlockExpr(block) => block as &dyn ast::AttrsOwner, | ||
307 | }), | ||
308 | ), | ||
309 | } | ||
310 | } | ||
311 | AttrDefId::FieldId(it) => { | ||
312 | return Self { attrs: db.fields_attrs(it.parent)[it.local_id].clone(), owner: def }; | ||
313 | } | ||
314 | AttrDefId::EnumVariantId(it) => { | ||
315 | return Self { | ||
316 | attrs: db.variants_attrs(it.parent)[it.local_id].clone(), | ||
317 | owner: def, | ||
318 | }; | ||
319 | } | ||
320 | AttrDefId::AdtId(it) => match it { | ||
321 | AdtId::StructId(it) => attrs_from_item_tree(it.lookup(db).id, db), | ||
322 | AdtId::EnumId(it) => attrs_from_item_tree(it.lookup(db).id, db), | ||
323 | AdtId::UnionId(it) => attrs_from_item_tree(it.lookup(db).id, db), | ||
324 | }, | ||
325 | AttrDefId::TraitId(it) => attrs_from_item_tree(it.lookup(db).id, db), | ||
326 | AttrDefId::MacroDefId(it) => it | ||
327 | .ast_id() | ||
328 | .left() | ||
329 | .map_or_else(Default::default, |ast_id| attrs_from_ast(ast_id, db)), | ||
330 | AttrDefId::ImplId(it) => attrs_from_item_tree(it.lookup(db).id, db), | ||
331 | AttrDefId::ConstId(it) => attrs_from_item_tree(it.lookup(db).id, db), | ||
332 | AttrDefId::StaticId(it) => attrs_from_item_tree(it.lookup(db).id, db), | ||
333 | AttrDefId::FunctionId(it) => attrs_from_item_tree(it.lookup(db).id, db), | ||
334 | AttrDefId::TypeAliasId(it) => attrs_from_item_tree(it.lookup(db).id, db), | ||
335 | AttrDefId::GenericParamId(it) => match it { | ||
336 | GenericParamId::TypeParamId(it) => { | ||
337 | let src = it.parent.child_source(db); | ||
338 | RawAttrs::from_attrs_owner( | ||
339 | db, | ||
340 | src.with_value( | ||
341 | src.value[it.local_id].as_ref().either(|it| it as _, |it| it as _), | ||
342 | ), | ||
343 | ) | ||
344 | } | ||
345 | GenericParamId::LifetimeParamId(it) => { | ||
346 | let src = it.parent.child_source(db); | ||
347 | RawAttrs::from_attrs_owner(db, src.with_value(&src.value[it.local_id])) | ||
348 | } | ||
349 | GenericParamId::ConstParamId(it) => { | ||
350 | let src = it.parent.child_source(db); | ||
351 | RawAttrs::from_attrs_owner(db, src.with_value(&src.value[it.local_id])) | ||
352 | } | ||
353 | }, | ||
354 | }; | ||
355 | |||
356 | let attrs = raw_attrs.filter(db, def.krate(db)); | ||
357 | Self { attrs, owner: def } | ||
358 | } | ||
359 | |||
360 | pub fn source_map(&self, db: &dyn DefDatabase) -> AttrSourceMap { | ||
361 | let owner = match self.owner { | ||
362 | AttrDefId::ModuleId(module) => { | ||
363 | // Modules can have 2 attribute owners (the `mod x;` item, and the module file itself). | ||
364 | |||
365 | let def_map = module.def_map(db); | ||
366 | let mod_data = &def_map[module.local_id]; | ||
367 | let attrs = match mod_data.declaration_source(db) { | ||
368 | Some(it) => { | ||
369 | let mut attrs: Vec<_> = collect_attrs(&it.value as &dyn ast::AttrsOwner) | ||
370 | .map(|attr| InFile::new(it.file_id, attr)) | ||
371 | .collect(); | ||
372 | if let InFile { file_id, value: ModuleSource::SourceFile(file) } = | ||
373 | mod_data.definition_source(db) | ||
374 | { | ||
375 | attrs.extend( | ||
376 | collect_attrs(&file as &dyn ast::AttrsOwner) | ||
377 | .map(|attr| InFile::new(file_id, attr)), | ||
378 | ) | ||
379 | } | ||
380 | attrs | ||
381 | } | ||
382 | None => { | ||
383 | let InFile { file_id, value } = mod_data.definition_source(db); | ||
384 | match &value { | ||
385 | ModuleSource::SourceFile(file) => { | ||
386 | collect_attrs(file as &dyn ast::AttrsOwner) | ||
387 | } | ||
388 | ModuleSource::Module(module) => { | ||
389 | collect_attrs(module as &dyn ast::AttrsOwner) | ||
390 | } | ||
391 | ModuleSource::BlockExpr(block) => { | ||
392 | collect_attrs(block as &dyn ast::AttrsOwner) | ||
393 | } | ||
394 | } | ||
395 | .map(|attr| InFile::new(file_id, attr)) | ||
396 | .collect() | ||
397 | } | ||
398 | }; | ||
399 | return AttrSourceMap { attrs }; | ||
400 | } | ||
401 | AttrDefId::FieldId(id) => { | ||
402 | id.parent.child_source(db).map(|source| match &source[id.local_id] { | ||
403 | Either::Left(field) => ast::AttrsOwnerNode::new(field.clone()), | ||
404 | Either::Right(field) => ast::AttrsOwnerNode::new(field.clone()), | ||
405 | }) | ||
406 | } | ||
407 | AttrDefId::AdtId(adt) => match adt { | ||
408 | AdtId::StructId(id) => id.lookup(db).source(db).map(ast::AttrsOwnerNode::new), | ||
409 | AdtId::UnionId(id) => id.lookup(db).source(db).map(ast::AttrsOwnerNode::new), | ||
410 | AdtId::EnumId(id) => id.lookup(db).source(db).map(ast::AttrsOwnerNode::new), | ||
411 | }, | ||
412 | AttrDefId::FunctionId(id) => id.lookup(db).source(db).map(ast::AttrsOwnerNode::new), | ||
413 | AttrDefId::EnumVariantId(id) => id | ||
414 | .parent | ||
415 | .child_source(db) | ||
416 | .map(|source| ast::AttrsOwnerNode::new(source[id.local_id].clone())), | ||
417 | AttrDefId::StaticId(id) => id.lookup(db).source(db).map(ast::AttrsOwnerNode::new), | ||
418 | AttrDefId::ConstId(id) => id.lookup(db).source(db).map(ast::AttrsOwnerNode::new), | ||
419 | AttrDefId::TraitId(id) => id.lookup(db).source(db).map(ast::AttrsOwnerNode::new), | ||
420 | AttrDefId::TypeAliasId(id) => id.lookup(db).source(db).map(ast::AttrsOwnerNode::new), | ||
421 | AttrDefId::MacroDefId(id) => match id.ast_id() { | ||
422 | Either::Left(it) => { | ||
423 | it.with_value(ast::AttrsOwnerNode::new(it.to_node(db.upcast()))) | ||
424 | } | ||
425 | Either::Right(it) => { | ||
426 | it.with_value(ast::AttrsOwnerNode::new(it.to_node(db.upcast()))) | ||
427 | } | ||
428 | }, | ||
429 | AttrDefId::ImplId(id) => id.lookup(db).source(db).map(ast::AttrsOwnerNode::new), | ||
430 | AttrDefId::GenericParamId(id) => match id { | ||
431 | GenericParamId::TypeParamId(id) => { | ||
432 | id.parent.child_source(db).map(|source| match &source[id.local_id] { | ||
433 | Either::Left(id) => ast::AttrsOwnerNode::new(id.clone()), | ||
434 | Either::Right(id) => ast::AttrsOwnerNode::new(id.clone()), | ||
435 | }) | ||
436 | } | ||
437 | GenericParamId::LifetimeParamId(id) => id | ||
438 | .parent | ||
439 | .child_source(db) | ||
440 | .map(|source| ast::AttrsOwnerNode::new(source[id.local_id].clone())), | ||
441 | GenericParamId::ConstParamId(id) => id | ||
442 | .parent | ||
443 | .child_source(db) | ||
444 | .map(|source| ast::AttrsOwnerNode::new(source[id.local_id].clone())), | ||
445 | }, | ||
446 | }; | ||
447 | |||
448 | AttrSourceMap { | ||
449 | attrs: collect_attrs(&owner.value) | ||
450 | .map(|attr| InFile::new(owner.file_id, attr)) | ||
451 | .collect(), | ||
452 | } | ||
453 | } | ||
454 | } | ||
455 | |||
390 | fn inner_attributes( | 456 | fn inner_attributes( |
391 | syntax: &SyntaxNode, | 457 | syntax: &SyntaxNode, |
392 | ) -> Option<(impl Iterator<Item = ast::Attr>, impl Iterator<Item = ast::Comment>)> { | 458 | ) -> Option<(impl Iterator<Item = ast::Attr>, impl Iterator<Item = ast::Comment>)> { |
diff --git a/crates/hir_def/src/db.rs b/crates/hir_def/src/db.rs index 276caf5b3..53df85089 100644 --- a/crates/hir_def/src/db.rs +++ b/crates/hir_def/src/db.rs | |||
@@ -8,7 +8,7 @@ use syntax::SmolStr; | |||
8 | 8 | ||
9 | use crate::{ | 9 | use crate::{ |
10 | adt::{EnumData, StructData}, | 10 | adt::{EnumData, StructData}, |
11 | attr::Attrs, | 11 | attr::{Attrs, AttrsWithOwner}, |
12 | body::{scope::ExprScopes, Body, BodySourceMap}, | 12 | body::{scope::ExprScopes, Body, BodySourceMap}, |
13 | data::{ConstData, FunctionData, ImplData, StaticData, TraitData, TypeAliasData}, | 13 | data::{ConstData, FunctionData, ImplData, StaticData, TraitData, TypeAliasData}, |
14 | generics::GenericParams, | 14 | generics::GenericParams, |
@@ -120,8 +120,8 @@ pub trait DefDatabase: InternDatabase + AstDatabase + Upcast<dyn AstDatabase> { | |||
120 | #[salsa::invoke(Attrs::fields_attrs_query)] | 120 | #[salsa::invoke(Attrs::fields_attrs_query)] |
121 | fn fields_attrs(&self, def: VariantId) -> Arc<ArenaMap<LocalFieldId, Attrs>>; | 121 | fn fields_attrs(&self, def: VariantId) -> Arc<ArenaMap<LocalFieldId, Attrs>>; |
122 | 122 | ||
123 | #[salsa::invoke(Attrs::attrs_query)] | 123 | #[salsa::invoke(AttrsWithOwner::attrs_query)] |
124 | fn attrs(&self, def: AttrDefId) -> Attrs; | 124 | fn attrs(&self, def: AttrDefId) -> AttrsWithOwner; |
125 | 125 | ||
126 | #[salsa::invoke(LangItems::crate_lang_items_query)] | 126 | #[salsa::invoke(LangItems::crate_lang_items_query)] |
127 | fn crate_lang_items(&self, krate: CrateId) -> Arc<LangItems>; | 127 | fn crate_lang_items(&self, krate: CrateId) -> Arc<LangItems>; |