aboutsummaryrefslogtreecommitdiff
path: root/crates/hir_def/src/attr.rs
diff options
context:
space:
mode:
authorJonas Schievink <[email protected]>2020-12-19 00:09:48 +0000
committerJonas Schievink <[email protected]>2020-12-19 00:10:56 +0000
commitea5cc8d07ac28a2110b894d154468c3fa46d7040 (patch)
treed03e228616092a32a75c7c8af624d4e9c7f7fb2f /crates/hir_def/src/attr.rs
parentc7b7c37ea5f25806d8c523e309b7ee9be27f2cde (diff)
More accurate `#[derive]` parsing
This now allows full paths to the derive macro
Diffstat (limited to 'crates/hir_def/src/attr.rs')
-rw-r--r--crates/hir_def/src/attr.rs46
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};
5use base_db::CrateId; 5use base_db::CrateId;
6use cfg::{CfgExpr, CfgOptions}; 6use cfg::{CfgExpr, CfgOptions};
7use either::Either; 7use either::Either;
8use hir_expand::{hygiene::Hygiene, AstId, InFile}; 8use hir_expand::{hygiene::Hygiene, name::AsName, AstId, InFile};
9use itertools::Itertools; 9use itertools::Itertools;
10use mbe::ast_to_token_tree; 10use mbe::ast_to_token_tree;
11use syntax::{ 11use 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()