diff options
Diffstat (limited to 'crates/hir_def')
-rw-r--r-- | crates/hir_def/src/attr.rs | 64 |
1 files changed, 48 insertions, 16 deletions
diff --git a/crates/hir_def/src/attr.rs b/crates/hir_def/src/attr.rs index e4c84afbf..739e3f5e3 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 | ||
381 | pub struct AttrSourceMap { | 424 | pub struct AttrSourceMap { |
382 | attrs: Vec<Either<ast::Attr, ast::Comment>>, | 425 | attrs: Vec<InFile<Either<ast::Attr, ast::Comment>>>, |
383 | } | 426 | } |
384 | 427 | ||
385 | impl AttrSourceMap { | 428 | impl 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 | /// |