]> git.lizzy.rs Git - rust.git/blobdiff - crates/ide/src/expand_macro.rs
fix: Fix expand_macro always expanding the first listed derive
[rust.git] / crates / ide / src / expand_macro.rs
index c234eb3db6bd289d8044de2865de5a4f0dc1239f..7bb6b24a23deefa1dd1cf56ffc505fc9af55fa1d 100644 (file)
@@ -3,8 +3,7 @@
     helpers::{insert_whitespace_into_node::insert_ws_into, pick_best_token},
     RootDatabase,
 };
-use itertools::Itertools;
-use syntax::{ast, ted, AstNode, SyntaxKind, SyntaxNode};
+use syntax::{ast, ted, AstNode, NodeOrToken, SyntaxKind, SyntaxNode, T};
 
 use crate::FilePosition;
 
@@ -43,7 +42,7 @@ pub(crate) fn expand_macro(db: &RootDatabase, position: FilePosition) -> Option<
 
     let derive = sema.descend_into_macros(tok.clone()).into_iter().find_map(|descended| {
         let hir_file = sema.hir_file_for(&descended.parent()?);
-        if !hir_file.is_derive_attr_macro(db) {
+        if !hir_file.is_derive_attr_pseudo_expansion(db) {
             return None;
         }
 
@@ -52,7 +51,17 @@ pub(crate) fn expand_macro(db: &RootDatabase, position: FilePosition) -> Option<
         let token = hir::InFile::new(hir_file, descended).upmap(db)?.value;
         let attr = token.ancestors().find_map(ast::Attr::cast)?;
         let expansions = sema.expand_derive_macro(&attr)?;
-        Some(ExpandedMacro { name, expansion: expansions.into_iter().map(insert_ws_into).join("") })
+        let idx = attr
+            .token_tree()?
+            .token_trees_and_tokens()
+            .filter_map(NodeOrToken::into_token)
+            .take_while(|it| it != &token)
+            .filter(|it| it.kind() == T![,])
+            .count();
+        Some(ExpandedMacro {
+            name,
+            expansion: expansions.get(idx).cloned().map(insert_ws_into)?.to_string(),
+        })
     });
 
     if derive.is_some() {
@@ -370,9 +379,20 @@ fn macro_expand_derive_multi() {
 struct Foo {}
 "#,
             expect![[r#"
-                Copy, Clone
+                Copy
                 impl < >core::marker::Copy for Foo< >{}
 
+            "#]],
+        );
+        check(
+            r#"
+//- minicore: copy, clone, derive
+
+#[derive(Copy, Cl$0one)]
+struct Foo {}
+"#,
+            expect![[r#"
+                Clone
                 impl < >core::clone::Clone for Foo< >{}
 
             "#]],