@@ -5,7 +5,7 @@ use std::{ops, sync::Arc};
55use base_db:: CrateId ;
66use cfg:: { CfgExpr , CfgOptions } ;
77use either:: Either ;
8- use hir_expand:: { hygiene:: Hygiene , AstId , InFile } ;
8+ use hir_expand:: { hygiene:: Hygiene , name :: AsName , AstId , InFile } ;
99use itertools:: Itertools ;
1010use mbe:: ast_to_token_tree;
1111use syntax:: {
@@ -19,7 +19,7 @@ use crate::{
1919 db:: DefDatabase ,
2020 item_tree:: { ItemTreeId , ItemTreeNode } ,
2121 nameres:: ModuleSource ,
22- path:: ModPath ,
22+ path:: { ModPath , PathKind } ,
2323 src:: HasChildSource ,
2424 AdtId , AttrDefId , Lookup ,
2525} ;
@@ -357,6 +357,46 @@ impl Attr {
357357 } ;
358358 Some ( Attr { path, input } )
359359 }
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+ }
360400}
361401
362402#[ derive( Debug , Clone , Copy ) ]
@@ -384,7 +424,7 @@ impl<'a> AttrQuery<'a> {
384424 self . attrs ( ) . next ( ) . is_some ( )
385425 }
386426
387- fn attrs ( self ) -> impl Iterator < Item = & ' a Attr > {
427+ pub ( crate ) fn attrs ( self ) -> impl Iterator < Item = & ' a Attr > {
388428 let key = self . key ;
389429 self . attrs
390430 . iter ( )
0 commit comments