From ea5cc8d07ac28a2110b894d154468c3fa46d7040 Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Sat, 19 Dec 2020 01:09:48 +0100 Subject: More accurate `#[derive]` parsing This now allows full paths to the derive macro --- crates/hir_def/src/attr.rs | 46 +++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 43 insertions(+), 3 deletions(-) (limited to 'crates/hir_def/src/attr.rs') 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}; use base_db::CrateId; use cfg::{CfgExpr, CfgOptions}; use either::Either; -use hir_expand::{hygiene::Hygiene, AstId, InFile}; +use hir_expand::{hygiene::Hygiene, name::AsName, AstId, InFile}; use itertools::Itertools; use mbe::ast_to_token_tree; use syntax::{ @@ -19,7 +19,7 @@ use crate::{ db::DefDatabase, item_tree::{ItemTreeId, ItemTreeNode}, nameres::ModuleSource, - path::ModPath, + path::{ModPath, PathKind}, src::HasChildSource, AdtId, AttrDefId, Lookup, }; @@ -357,6 +357,46 @@ impl Attr { }; Some(Attr { path, input }) } + + /// Parses this attribute as a `#[derive]`, returns an iterator that yields all contained paths + /// to derive macros. + /// + /// Returns `None` when the attribute is not a well-formed `#[derive]` attribute. + pub(crate) fn parse_derive(&self) -> Option> { + if self.path.as_ident() != Some(&hir_expand::name![derive]) { + return None; + } + + match &self.input { + Some(AttrInput::TokenTree(args)) => { + let mut counter = 0; + let paths = args + .token_trees + .iter() + .group_by(move |tt| { + match tt { + tt::TokenTree::Leaf(tt::Leaf::Punct(p)) if p.char == ',' => { + counter += 1; + } + _ => {} + } + counter + }) + .into_iter() + .map(|(_, tts)| { + let segments = tts.filter_map(|tt| match tt { + tt::TokenTree::Leaf(tt::Leaf::Ident(id)) => Some(id.as_name()), + _ => None, + }); + ModPath::from_segments(PathKind::Plain, segments) + }) + .collect::>(); + + Some(paths.into_iter()) + } + _ => None, + } + } } #[derive(Debug, Clone, Copy)] @@ -384,7 +424,7 @@ impl<'a> AttrQuery<'a> { self.attrs().next().is_some() } - fn attrs(self) -> impl Iterator { + pub(crate) fn attrs(self) -> impl Iterator { let key = self.key; self.attrs .iter() -- cgit v1.2.3