@@ -32,19 +32,32 @@ pub(crate) fn expand_macro(db: &RootDatabase, position: FilePosition) -> Option<
32
32
_ => 0 ,
33
33
} ) ?;
34
34
35
- let descended = sema. descend_into_macros_single ( tok. clone ( ) ) ;
36
- if let Some ( attr) = descended. ancestors ( ) . find_map ( ast:: Attr :: cast) {
37
- if let Some ( ( path, tt) ) = attr. as_simple_call ( ) {
38
- if path == "derive" {
39
- let mut tt = tt. syntax ( ) . children_with_tokens ( ) . skip ( 1 ) . join ( "" ) ;
40
- tt. pop ( ) ;
41
- let expansions = sema. expand_derive_macro ( & attr) ?;
42
- return Some ( ExpandedMacro {
43
- name : tt,
44
- expansion : expansions. into_iter ( ) . map ( insert_whitespaces) . join ( "" ) ,
45
- } ) ;
46
- }
35
+ // due to how Rust Analyzer works internally, we need to special case derive attributes,
36
+ // otherwise they might not get found, e.g. here with the cursor at $0 `#[attr]` would expand:
37
+ // ```
38
+ // #[attr]
39
+ // #[derive($0Foo)]
40
+ // struct Bar;
41
+ // ```
42
+
43
+ let derive = sema. descend_into_macros ( tok. clone ( ) ) . iter ( ) . find_map ( |descended| {
44
+ let attr = descended. ancestors ( ) . find_map ( ast:: Attr :: cast) ?;
45
+ let ( path, tt) = attr. as_simple_call ( ) ?;
46
+ if path == "derive" {
47
+ let mut tt = tt. syntax ( ) . children_with_tokens ( ) . skip ( 1 ) . join ( "" ) ;
48
+ tt. pop ( ) ;
49
+ let expansions = sema. expand_derive_macro ( & attr) ?;
50
+ Some ( ExpandedMacro {
51
+ name : tt,
52
+ expansion : expansions. into_iter ( ) . map ( insert_whitespaces) . join ( "" ) ,
53
+ } )
54
+ } else {
55
+ None
47
56
}
57
+ } ) ;
58
+
59
+ if derive. is_some ( ) {
60
+ return derive;
48
61
}
49
62
50
63
// FIXME: Intermix attribute and bang! expansions
@@ -353,9 +366,12 @@ fn main() {
353
366
fn macro_expand_derive ( ) {
354
367
check (
355
368
r#"
369
+ //- proc_macros: identity
370
+
356
371
#[rustc_builtin_macro]
357
372
pub macro Clone {}
358
373
374
+ #[proc_macros::identity]
359
375
#[derive(C$0lone)]
360
376
struct Foo {}
361
377
"# ,
0 commit comments