@@ -3,7 +3,7 @@ use std::iter;
33use hir:: Semantics ;
44use ide_db:: { helpers:: pick_best_token, RootDatabase } ;
55use 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 } ;
77
88use crate :: FilePosition ;
99
@@ -31,29 +31,29 @@ pub(crate) fn expand_macro(db: &RootDatabase, position: FilePosition) -> Option<
3131 SyntaxKind :: IDENT => 1 ,
3232 _ => 0 ,
3333 } ) ?;
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+ }
3447 let mut expanded = None ;
3548 let mut name = None ;
3649 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-
4950 if let Some ( item) = ast:: Item :: cast ( node. clone ( ) ) {
5051 if let Some ( def) = sema. resolve_attr_macro_call ( & item) {
5152 name = def. name ( db) . map ( |name| name. to_string ( ) ) ;
5253 expanded = expand_attr_macro_recur ( & sema, & item) ;
5354 break ;
5455 }
5556 }
56-
5757 if let Some ( mac) = ast:: MacroCall :: cast ( node) {
5858 name = Some ( mac. path ( ) ?. segment ( ) ?. name_ref ( ) ?. to_string ( ) ) ;
5959 expanded = expand_macro_recur ( & sema, & mac) ;
@@ -107,24 +107,26 @@ fn expand<T: AstNode>(
107107// FIXME: It would also be cool to share logic here and in the mbe tests,
108108// which are pretty unreadable at the moment.
109109fn insert_whitespaces ( syn : SyntaxNode ) -> String {
110+ use SyntaxKind :: * ;
110111 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 ( ) ;
121112
122113 let mut indent = 0 ;
123114 let mut last: Option < SyntaxKind > = None ;
124115
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)
128130 } ;
129131 let is_last =
130132 |f : fn ( SyntaxKind ) -> bool , default| -> bool { last. map ( f) . unwrap_or ( default) } ;
@@ -182,6 +184,7 @@ mod tests {
182184
183185 use crate :: fixture;
184186
187+ #[ track_caller]
185188 fn check ( ra_fixture : & str , expect : Expect ) {
186189 let ( analysis, pos) = fixture:: position ( ra_fixture) ;
187190 let expansion = analysis. expand_macro ( pos) . unwrap ( ) . unwrap ( ) ;
@@ -207,6 +210,7 @@ f$0oo!();
207210 expect ! [ [ r#"
208211 foo
209212 fn b(){}
213+
210214 "# ] ] ,
211215 ) ;
212216 }
@@ -226,11 +230,12 @@ macro_rules! foo {
226230f$0oo!();
227231 "# ,
228232 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+ "# ] ] ,
234239 ) ;
235240 }
236241
@@ -343,7 +348,6 @@ fn main() {
343348 fn macro_expand_derive ( ) {
344349 check (
345350 r#"
346-
347351#[rustc_builtin_macro]
348352pub macro Clone {}
349353
@@ -353,6 +357,28 @@ struct Foo {}
353357 expect ! [ [ r#"
354358 Clone
355359 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+
356382 "# ] ] ,
357383 ) ;
358384 }
0 commit comments