diff options
Diffstat (limited to 'crates/hir_def/src/attr.rs')
-rw-r--r-- | crates/hir_def/src/attr.rs | 46 |
1 files changed, 43 insertions, 3 deletions
diff --git a/crates/hir_def/src/attr.rs b/crates/hir_def/src/attr.rs index 1b9c64ee5..18525406c 100644 --- a/crates/hir_def/src/attr.rs +++ b/crates/hir_def/src/attr.rs | |||
@@ -5,7 +5,7 @@ use std::{ops, sync::Arc}; | |||
5 | use base_db::CrateId; | 5 | use base_db::CrateId; |
6 | use cfg::{CfgExpr, CfgOptions}; | 6 | use cfg::{CfgExpr, CfgOptions}; |
7 | use either::Either; | 7 | use either::Either; |
8 | use hir_expand::{hygiene::Hygiene, AstId, InFile}; | 8 | use hir_expand::{hygiene::Hygiene, name::AsName, AstId, InFile}; |
9 | use itertools::Itertools; | 9 | use itertools::Itertools; |
10 | use mbe::ast_to_token_tree; | 10 | use mbe::ast_to_token_tree; |
11 | use syntax::{ | 11 | use syntax::{ |
@@ -19,7 +19,7 @@ use crate::{ | |||
19 | db::DefDatabase, | 19 | db::DefDatabase, |
20 | item_tree::{ItemTreeId, ItemTreeNode}, | 20 | item_tree::{ItemTreeId, ItemTreeNode}, |
21 | nameres::ModuleSource, | 21 | nameres::ModuleSource, |
22 | path::ModPath, | 22 | path::{ModPath, PathKind}, |
23 | src::HasChildSource, | 23 | src::HasChildSource, |
24 | AdtId, AttrDefId, Lookup, | 24 | AdtId, AttrDefId, Lookup, |
25 | }; | 25 | }; |
@@ -357,6 +357,46 @@ impl Attr { | |||
357 | }; | 357 | }; |
358 | Some(Attr { path, input }) | 358 | Some(Attr { path, input }) |
359 | } | 359 | } |
360 | |||
361 | /// Parses this attribute as a `#[derive]`, returns an iterator that yields all contained paths | ||
362 | /// to derive macros. | ||
363 | /// | ||
364 | /// Returns `None` when the attribute is not a well-formed `#[derive]` attribute. | ||
365 | pub(crate) fn parse_derive(&self) -> Option<impl Iterator<Item = ModPath>> { | ||
366 | if self.path.as_ident() != Some(&hir_expand::name![derive]) { | ||
367 | return None; | ||
368 | } | ||
369 | |||
370 | match &self.input { | ||
371 | Some(AttrInput::TokenTree(args)) => { | ||
372 | let mut counter = 0; | ||
373 | let paths = args | ||
374 | .token_trees | ||
375 | .iter() | ||
376 | .group_by(move |tt| { | ||
377 | match tt { | ||
378 | tt::TokenTree::Leaf(tt::Leaf::Punct(p)) if p.char == ',' => { | ||
379 | counter += 1; | ||
380 | } | ||
381 | _ => {} | ||
382 | } | ||
383 | counter | ||
384 | }) | ||
385 | .into_iter() | ||
386 | .map(|(_, tts)| { | ||
387 | let segments = tts.filter_map(|tt| match tt { | ||
388 | tt::TokenTree::Leaf(tt::Leaf::Ident(id)) => Some(id.as_name()), | ||
389 | _ => None, | ||
390 | }); | ||
391 | ModPath::from_segments(PathKind::Plain, segments) | ||
392 | }) | ||
393 | .collect::<Vec<_>>(); | ||
394 | |||
395 | Some(paths.into_iter()) | ||
396 | } | ||
397 | _ => None, | ||
398 | } | ||
399 | } | ||
360 | } | 400 | } |
361 | 401 | ||
362 | #[derive(Debug, Clone, Copy)] | 402 | #[derive(Debug, Clone, Copy)] |
@@ -384,7 +424,7 @@ impl<'a> AttrQuery<'a> { | |||
384 | self.attrs().next().is_some() | 424 | self.attrs().next().is_some() |
385 | } | 425 | } |
386 | 426 | ||
387 | fn attrs(self) -> impl Iterator<Item = &'a Attr> { | 427 | pub(crate) fn attrs(self) -> impl Iterator<Item = &'a Attr> { |
388 | let key = self.key; | 428 | let key = self.key; |
389 | self.attrs | 429 | self.attrs |
390 | .iter() | 430 | .iter() |