@@ -3,7 +3,7 @@ use std::iter;
3
3
use hir:: Semantics ;
4
4
use ide_db:: { helpers:: pick_best_token, RootDatabase } ;
5
5
use itertools:: Itertools ;
6
- use syntax:: { ast, ted, AstNode , NodeOrToken , SyntaxKind , SyntaxKind :: * , SyntaxNode , WalkEvent , T } ;
6
+ use syntax:: { ast, ted, AstNode , NodeOrToken , SyntaxKind , SyntaxNode , WalkEvent , T } ;
7
7
8
8
use crate :: FilePosition ;
9
9
@@ -31,29 +31,29 @@ pub(crate) fn expand_macro(db: &RootDatabase, position: FilePosition) -> Option<
31
31
SyntaxKind :: IDENT => 1 ,
32
32
_ => 0 ,
33
33
} ) ?;
34
+ let descended = sema. descend_into_macros ( tok. clone ( ) ) ;
35
+ if let Some ( attr) = descended. ancestors ( ) . find_map ( ast:: Attr :: cast) {
36
+ if let Some ( ( path, tt) ) = attr. as_simple_call ( ) {
37
+ if path == "derive" {
38
+ let mut tt = tt. syntax ( ) . children_with_tokens ( ) . skip ( 1 ) . join ( "" ) ;
39
+ tt. pop ( ) ;
40
+ return sema
41
+ . expand_derive_macro ( & attr)
42
+ . map ( insert_whitespaces)
43
+ . map ( |expansion| ExpandedMacro { name : tt, expansion } ) ;
44
+ }
45
+ }
46
+ }
34
47
let mut expanded = None ;
35
48
let mut name = None ;
36
49
for node in tok. ancestors ( ) {
37
- if let Some ( attr) = ast:: Attr :: cast ( node. clone ( ) ) {
38
- if let Some ( ( path, tt) ) = attr. as_simple_call ( ) {
39
- if path == "derive" {
40
- let mut tt = tt. syntax ( ) . children_with_tokens ( ) . skip ( 1 ) . join ( "" ) ;
41
- tt. pop ( ) ;
42
- name = Some ( tt) ;
43
- expanded = sema. expand_derive_macro ( & attr) ;
44
- break ;
45
- }
46
- }
47
- }
48
-
49
50
if let Some ( item) = ast:: Item :: cast ( node. clone ( ) ) {
50
51
if let Some ( def) = sema. resolve_attr_macro_call ( & item) {
51
52
name = def. name ( db) . map ( |name| name. to_string ( ) ) ;
52
53
expanded = expand_attr_macro_recur ( & sema, & item) ;
53
54
break ;
54
55
}
55
56
}
56
-
57
57
if let Some ( mac) = ast:: MacroCall :: cast ( node) {
58
58
name = Some ( mac. path ( ) ?. segment ( ) ?. name_ref ( ) ?. to_string ( ) ) ;
59
59
expanded = expand_macro_recur ( & sema, & mac) ;
@@ -107,24 +107,26 @@ fn expand<T: AstNode>(
107
107
// FIXME: It would also be cool to share logic here and in the mbe tests,
108
108
// which are pretty unreadable at the moment.
109
109
fn insert_whitespaces ( syn : SyntaxNode ) -> String {
110
+ use SyntaxKind :: * ;
110
111
let mut res = String :: new ( ) ;
111
- let mut token_iter = syn
112
- . preorder_with_tokens ( )
113
- . filter_map ( |event| {
114
- if let WalkEvent :: Enter ( NodeOrToken :: Token ( token) ) = event {
115
- Some ( token)
116
- } else {
117
- None
118
- }
119
- } )
120
- . peekable ( ) ;
121
112
122
113
let mut indent = 0 ;
123
114
let mut last: Option < SyntaxKind > = None ;
124
115
125
- while let Some ( token) = token_iter. next ( ) {
126
- let mut is_next = |f : fn ( SyntaxKind ) -> bool , default| -> bool {
127
- token_iter. peek ( ) . map ( |it| f ( it. kind ( ) ) ) . unwrap_or ( default)
116
+ for event in syn. preorder_with_tokens ( ) {
117
+ let token = match event {
118
+ WalkEvent :: Enter ( NodeOrToken :: Token ( token) ) => token,
119
+ WalkEvent :: Leave ( NodeOrToken :: Node ( node) )
120
+ if matches ! ( node. kind( ) , ATTR | MATCH_ARM | STRUCT | ENUM | UNION | FN | IMPL ) =>
121
+ {
122
+ res. push ( '\n' ) ;
123
+ res. extend ( iter:: repeat ( " " ) . take ( 2 * indent) ) ;
124
+ continue ;
125
+ }
126
+ _ => continue ,
127
+ } ;
128
+ let is_next = |f : fn ( SyntaxKind ) -> bool , default| -> bool {
129
+ token. next_token ( ) . map ( |it| f ( it. kind ( ) ) ) . unwrap_or ( default)
128
130
} ;
129
131
let is_last =
130
132
|f : fn ( SyntaxKind ) -> bool , default| -> bool { last. map ( f) . unwrap_or ( default) } ;
@@ -182,6 +184,7 @@ mod tests {
182
184
183
185
use crate :: fixture;
184
186
187
+ #[ track_caller]
185
188
fn check ( ra_fixture : & str , expect : Expect ) {
186
189
let ( analysis, pos) = fixture:: position ( ra_fixture) ;
187
190
let expansion = analysis. expand_macro ( pos) . unwrap ( ) . unwrap ( ) ;
@@ -207,6 +210,7 @@ f$0oo!();
207
210
expect ! [ [ r#"
208
211
foo
209
212
fn b(){}
213
+
210
214
"# ] ] ,
211
215
) ;
212
216
}
@@ -226,11 +230,12 @@ macro_rules! foo {
226
230
f$0oo!();
227
231
"# ,
228
232
expect ! [ [ r#"
229
- foo
230
- fn some_thing() -> u32 {
231
- let a = 0;
232
- a+10
233
- }"# ] ] ,
233
+ foo
234
+ fn some_thing() -> u32 {
235
+ let a = 0;
236
+ a+10
237
+ }
238
+ "# ] ] ,
234
239
) ;
235
240
}
236
241
@@ -343,7 +348,6 @@ fn main() {
343
348
fn macro_expand_derive ( ) {
344
349
check (
345
350
r#"
346
-
347
351
#[rustc_builtin_macro]
348
352
pub macro Clone {}
349
353
@@ -353,6 +357,28 @@ struct Foo {}
353
357
expect ! [ [ r#"
354
358
Clone
355
359
impl< >crate::clone::Clone for Foo< >{}
360
+
361
+ "# ] ] ,
362
+ ) ;
363
+ }
364
+
365
+ #[ test]
366
+ fn macro_expand_derive2 ( ) {
367
+ check (
368
+ r#"
369
+ #[rustc_builtin_macro]
370
+ pub macro Clone {}
371
+ #[rustc_builtin_macro]
372
+ pub macro Copy {}
373
+
374
+ #[derive(Cop$0y)]
375
+ #[derive(Clone)]
376
+ struct Foo {}
377
+ "# ,
378
+ expect ! [ [ r#"
379
+ Copy
380
+ impl< >crate::marker::Copy for Foo< >{}
381
+
356
382
"# ] ] ,
357
383
) ;
358
384
}
0 commit comments