@@ -5,6 +5,7 @@ mod source_to_def;
5
5
use std:: { cell:: RefCell , fmt} ;
6
6
7
7
use base_db:: { FileId , FileRange } ;
8
+ use either:: Either ;
8
9
use hir_def:: {
9
10
body,
10
11
resolver:: { self , HasResolver , Resolver , TypeNs } ,
@@ -909,42 +910,54 @@ impl<'db> SemanticsImpl<'db> {
909
910
return None ;
910
911
}
911
912
912
- let attr_def =
913
- ast:: Attr :: to_def ( self , self . find_file ( attr. syntax ( ) ) . with_value ( attr. clone ( ) ) ) ?;
914
-
915
- let mut derive_paths = attr_def. parse_path_comma_token_tree ( ) ?;
916
- let derives = self . resolve_derive_macro ( & attr) ?;
913
+ let file = self . find_file ( attr. syntax ( ) ) ;
914
+ let adt = attr. syntax ( ) . parent ( ) . and_then ( ast:: Adt :: cast) ?;
917
915
918
- let derive_idx = tt
919
- . syntax ( )
920
- . children_with_tokens ( )
921
- . filter_map ( SyntaxElement :: into_token)
922
- . take_while ( |tok| tok != syntax)
923
- . filter ( |t| t. kind ( ) == T ! [ , ] )
924
- . count ( ) ;
925
- let path_segment_idx = syntax
926
- . siblings_with_tokens ( Direction :: Prev )
927
- . filter_map ( SyntaxElement :: into_token)
928
- . take_while ( |tok| matches ! ( tok. kind( ) , T ![ : ] | T ![ ident] ) )
929
- . filter ( |tok| tok. kind ( ) == T ! [ ident] )
930
- . count ( ) ;
931
-
932
- let mut mod_path = derive_paths. nth ( derive_idx) ?;
933
-
934
- if path_segment_idx < mod_path. len ( ) {
935
- // the path for the given ident is a qualifier, resolve to module if possible
936
- while path_segment_idx < mod_path. len ( ) {
937
- mod_path. pop_segment ( ) ;
916
+ let res = self . with_ctx ( |ctx| {
917
+ let attr_def = ctx. attr_to_def ( file. with_value ( attr. clone ( ) ) ) ?;
918
+ let derives = ctx
919
+ . attr_to_derive_macro_call ( file. with_value ( & adt) , file. with_value ( attr. clone ( ) ) ) ?;
920
+
921
+ let mut derive_paths = attr_def. parse_path_comma_token_tree ( ) ?;
922
+
923
+ let derive_idx = tt
924
+ . syntax ( )
925
+ . children_with_tokens ( )
926
+ . filter_map ( SyntaxElement :: into_token)
927
+ . take_while ( |tok| tok != syntax)
928
+ . filter ( |t| t. kind ( ) == T ! [ , ] )
929
+ . count ( ) ;
930
+ let path_segment_idx = syntax
931
+ . siblings_with_tokens ( Direction :: Prev )
932
+ . filter_map ( SyntaxElement :: into_token)
933
+ . take_while ( |tok| matches ! ( tok. kind( ) , T ![ : ] | T ![ ident] ) )
934
+ . filter ( |tok| tok. kind ( ) == T ! [ ident] )
935
+ . count ( ) ;
936
+
937
+ let mut mod_path = derive_paths. nth ( derive_idx) ?;
938
+
939
+ if path_segment_idx < mod_path. len ( ) {
940
+ // the path for the given ident is a qualifier, resolve to module if possible
941
+ while path_segment_idx < mod_path. len ( ) {
942
+ mod_path. pop_segment ( ) ;
943
+ }
944
+ Some ( Either :: Left ( mod_path) )
945
+ } else {
946
+ // otherwise fetch the derive
947
+ Some ( Either :: Right ( derives[ derive_idx] ) )
938
948
}
939
- resolve_hir_path (
949
+ } ) ?;
950
+
951
+ match res {
952
+ Either :: Left ( path) => resolve_hir_path (
940
953
self . db ,
941
954
& self . scope ( attr. syntax ( ) ) . resolver ,
942
- & Path :: from_known_path ( mod_path , [ ] ) ,
955
+ & Path :: from_known_path ( path , [ ] ) ,
943
956
)
944
- . filter ( |res| matches ! ( res, PathResolution :: Def ( ModuleDef :: Module ( _) ) ) )
945
- } else {
946
- // otherwise fetch the derive
947
- derives . get ( derive_idx ) ? . map ( PathResolution :: Macro )
957
+ . filter ( |res| matches ! ( res, PathResolution :: Def ( ModuleDef :: Module ( _) ) ) ) ,
958
+ Either :: Right ( derive ) => derive
959
+ . map ( |call| MacroDef { id : self . db . lookup_intern_macro_call ( call ) . def } )
960
+ . map ( PathResolution :: Macro ) ,
948
961
}
949
962
}
950
963
0 commit comments