aboutsummaryrefslogtreecommitdiff
path: root/crates/hir_def
diff options
context:
space:
mode:
Diffstat (limited to 'crates/hir_def')
-rw-r--r--crates/hir_def/src/attr.rs64
1 files changed, 48 insertions, 16 deletions
diff --git a/crates/hir_def/src/attr.rs b/crates/hir_def/src/attr.rs
index 8d925c0c1..1cab0e363 100644
--- a/crates/hir_def/src/attr.rs
+++ b/crates/hir_def/src/attr.rs
@@ -283,8 +283,51 @@ impl Attrs {
283 /// Constructs a map that maps the lowered `Attr`s in this `Attrs` back to its original syntax nodes. 283 /// Constructs a map that maps the lowered `Attr`s in this `Attrs` back to its original syntax nodes.
284 /// 284 ///
285 /// `owner` must be the original owner of the attributes. 285 /// `owner` must be the original owner of the attributes.
286 pub fn source_map(&self, owner: &dyn ast::AttrsOwner) -> AttrSourceMap { 286 // FIXME: figure out a better api that doesnt require the for_module hack
287 AttrSourceMap { attrs: collect_attrs(owner).collect() } 287 pub fn source_map(&self, owner: InFile<&dyn ast::AttrsOwner>) -> AttrSourceMap {
288 // FIXME: This doesn't work correctly for modules, as the attributes there can have up to
289 // two different owners
290 AttrSourceMap {
291 attrs: collect_attrs(owner.value)
292 .map(|attr| InFile::new(owner.file_id, attr))
293 .collect(),
294 }
295 }
296
297 pub fn source_map_for_module(
298 &self,
299 db: &dyn DefDatabase,
300 module: crate::ModuleId,
301 ) -> AttrSourceMap {
302 let def_map = module.def_map(db);
303 let mod_data = &def_map[module.local_id];
304 let attrs = match mod_data.declaration_source(db) {
305 Some(it) => {
306 let mut attrs: Vec<_> = collect_attrs(&it.value as &dyn ast::AttrsOwner)
307 .map(|attr| InFile::new(it.file_id, attr))
308 .collect();
309 if let InFile { file_id, value: ModuleSource::SourceFile(file) } =
310 mod_data.definition_source(db)
311 {
312 attrs.extend(
313 collect_attrs(&file as &dyn ast::AttrsOwner)
314 .map(|attr| InFile::new(file_id, attr)),
315 )
316 }
317 attrs
318 }
319 None => {
320 let InFile { file_id, value } = mod_data.definition_source(db);
321 match &value {
322 ModuleSource::SourceFile(file) => collect_attrs(file as &dyn ast::AttrsOwner),
323 ModuleSource::Module(module) => collect_attrs(module as &dyn ast::AttrsOwner),
324 ModuleSource::BlockExpr(block) => collect_attrs(block as &dyn ast::AttrsOwner),
325 }
326 .map(|attr| InFile::new(file_id, attr))
327 .collect()
328 }
329 };
330 AttrSourceMap { attrs }
288 } 331 }
289 332
290 pub fn by_key(&self, key: &'static str) -> AttrQuery<'_> { 333 pub fn by_key(&self, key: &'static str) -> AttrQuery<'_> {
@@ -379,7 +422,7 @@ fn inner_attributes(
379} 422}
380 423
381pub struct AttrSourceMap { 424pub struct AttrSourceMap {
382 attrs: Vec<Either<ast::Attr, ast::Comment>>, 425 attrs: Vec<InFile<Either<ast::Attr, ast::Comment>>>,
383} 426}
384 427
385impl AttrSourceMap { 428impl AttrSourceMap {
@@ -389,10 +432,11 @@ impl AttrSourceMap {
389 /// 432 ///
390 /// Note that the returned syntax node might be a `#[cfg_attr]`, or a doc comment, instead of 433 /// Note that the returned syntax node might be a `#[cfg_attr]`, or a doc comment, instead of
391 /// the attribute represented by `Attr`. 434 /// the attribute represented by `Attr`.
392 pub fn source_of(&self, attr: &Attr) -> &Either<ast::Attr, ast::Comment> { 435 pub fn source_of(&self, attr: &Attr) -> InFile<&Either<ast::Attr, ast::Comment>> {
393 self.attrs 436 self.attrs
394 .get(attr.index as usize) 437 .get(attr.index as usize)
395 .unwrap_or_else(|| panic!("cannot find `Attr` at index {}", attr.index)) 438 .unwrap_or_else(|| panic!("cannot find `Attr` at index {}", attr.index))
439 .as_ref()
396 } 440 }
397} 441}
398 442
@@ -428,18 +472,6 @@ impl Attr {
428 Some(Attr { index, path, input }) 472 Some(Attr { index, path, input })
429 } 473 }
430 474
431 /// Maps this lowered `Attr` back to its original syntax node.
432 ///
433 /// `owner` must be the original owner of the attribute.
434 ///
435 /// Note that the returned syntax node might be a `#[cfg_attr]`, or a doc comment, instead of
436 /// the attribute represented by `Attr`.
437 pub fn to_src(&self, owner: &dyn ast::AttrsOwner) -> Either<ast::Attr, ast::Comment> {
438 collect_attrs(owner).nth(self.index as usize).unwrap_or_else(|| {
439 panic!("cannot find `Attr` at index {} in {}", self.index, owner.syntax())
440 })
441 }
442
443 /// Parses this attribute as a `#[derive]`, returns an iterator that yields all contained paths 475 /// Parses this attribute as a `#[derive]`, returns an iterator that yields all contained paths
444 /// to derive macros. 476 /// to derive macros.
445 /// 477 ///