]> git.lizzy.rs Git - rust.git/commitdiff
Make replace_derive_with_manual_impl work again
authorLukas Wirth <lukastw97@gmail.com>
Mon, 21 Feb 2022 11:57:57 +0000 (12:57 +0100)
committerLukas Wirth <lukastw97@gmail.com>
Tue, 22 Feb 2022 09:20:44 +0000 (10:20 +0100)
crates/hir/src/lib.rs
crates/hir_expand/src/lib.rs
crates/ide/src/expand_macro.rs
crates/ide_assists/src/handlers/auto_import.rs
crates/ide_assists/src/handlers/replace_derive_with_manual_impl.rs
crates/ide_assists/src/tests/generated.rs
crates/ide_db/src/helpers.rs
crates/ide_db/src/helpers/import_assets.rs
crates/syntax/src/ast/node_ext.rs

index f047971a11680e3bd14bc4397b751e813cc8cdd1..423b46cc61802f731ddeee331fda44f7e99ab8aa 100644 (file)
@@ -1792,6 +1792,13 @@ pub fn is_fn_like(&self) -> bool {
         }
     }
 
         }
     }
 
+    pub fn is_builtin_derive(&self) -> bool {
+        match self.id.kind {
+            MacroDefKind::BuiltInAttr(exp, _) => exp.is_derive(),
+            _ => false,
+        }
+    }
+
     pub fn is_attr(&self) -> bool {
         matches!(self.kind(), MacroKind::Attr)
     }
     pub fn is_attr(&self) -> bool {
         matches!(self.kind(), MacroKind::Attr)
     }
index 2c6378cd3eee669d74787a9877aa0d75fcb88e3a..8803dac0975375fe2b6c504436851055a0bd0602 100644 (file)
@@ -386,6 +386,17 @@ pub fn to_node(&self, db: &dyn db::AstDatabase) -> InFile<SyntaxNode> {
             MacroCallKind::Derive { ast_id, .. } => {
                 ast_id.with_value(ast_id.to_node(db).syntax().clone())
             }
             MacroCallKind::Derive { ast_id, .. } => {
                 ast_id.with_value(ast_id.to_node(db).syntax().clone())
             }
+            MacroCallKind::Attr { ast_id, is_derive: true, invoc_attr_index, .. } => {
+                ast_id.with_value(ast_id.to_node(db)).map(|it| {
+                    it.doc_comments_and_attrs()
+                        .nth(*invoc_attr_index as usize)
+                        .and_then(|it| match it {
+                            Either::Left(attr) => Some(attr.syntax().clone()),
+                            Either::Right(_) => None,
+                        })
+                        .unwrap_or_else(|| it.syntax().clone())
+                })
+            }
             MacroCallKind::Attr { ast_id, .. } => {
                 ast_id.with_value(ast_id.to_node(db).syntax().clone())
             }
             MacroCallKind::Attr { ast_id, .. } => {
                 ast_id.with_value(ast_id.to_node(db).syntax().clone())
             }
index c234eb3db6bd289d8044de2865de5a4f0dc1239f..f7326747253a0580eb1261e901f9fa4c52fb292e 100644 (file)
@@ -3,8 +3,7 @@
     helpers::{insert_whitespace_into_node::insert_ws_into, pick_best_token},
     RootDatabase,
 };
     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;
 
 
 use crate::FilePosition;
 
@@ -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)?;
         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() {
     });
 
     if derive.is_some() {
@@ -370,11 +379,9 @@ fn macro_expand_derive_multi() {
 struct Foo {}
 "#,
             expect![[r#"
 struct Foo {}
 "#,
             expect![[r#"
-                Copy, Clone
+                Copy
                 impl < >core::marker::Copy for Foo< >{}
 
                 impl < >core::marker::Copy for Foo< >{}
 
-                impl < >core::clone::Clone for Foo< >{}
-
             "#]],
         );
     }
             "#]],
         );
     }
index cac736ff850a0f8fe41fbd11b355fdde577c4885..9c0233b028f600c2ce86455f3affd0e8682736b5 100644 (file)
@@ -3,7 +3,7 @@
     insert_use::{insert_use, ImportScope},
     mod_path_to_ast,
 };
     insert_use::{insert_use, ImportScope},
     mod_path_to_ast,
 };
-use syntax::{ast, AstNode, AstToken, NodeOrToken, SyntaxElement};
+use syntax::{ast, AstNode, NodeOrToken, SyntaxElement};
 
 use crate::{AssistContext, AssistId, AssistKind, Assists, GroupLabel};
 
 
 use crate::{AssistContext, AssistId, AssistKind, Assists, GroupLabel};
 
@@ -139,9 +139,7 @@ pub(super) fn find_importable_node(ctx: &AssistContext) -> Option<(ImportAssets,
     {
         ImportAssets::for_ident_pat(&ctx.sema, &pat).zip(Some(pat.syntax().clone().into()))
     } else {
     {
         ImportAssets::for_ident_pat(&ctx.sema, &pat).zip(Some(pat.syntax().clone().into()))
     } else {
-        // FIXME: Descend?
-        let ident = ctx.find_token_at_offset()?;
-        ImportAssets::for_derive_ident(&ctx.sema, &ident).zip(Some(ident.syntax().clone().into()))
+        None
     }
 }
 
     }
 }
 
index b3723710a8631cd40a499349eff837d026188f0d..8ac05bf5ff51c460ecfa750cd319d3f645159b64 100644 (file)
@@ -1,13 +1,13 @@
-use hir::ModuleDef;
-use ide_db::helpers::insert_whitespace_into_node::insert_ws_into;
-use ide_db::helpers::{
-    get_path_at_cursor_in_tt, import_assets::NameToImport, mod_path_to_ast,
-    parse_tt_as_comma_sep_paths,
+use hir::{InFile, ModuleDef};
+use ide_db::{
+    helpers::{
+        import_assets::NameToImport, insert_whitespace_into_node::insert_ws_into, mod_path_to_ast,
+    },
+    items_locator,
 };
 };
-use ide_db::items_locator;
 use itertools::Itertools;
 use syntax::{
 use itertools::Itertools;
 use syntax::{
-    ast::{self, AstNode, AstToken, HasName},
+    ast::{self, AstNode, HasName},
     SyntaxKind::WHITESPACE,
 };
 
     SyntaxKind::WHITESPACE,
 };
 
@@ -25,6 +25,7 @@
 // Converts a `derive` impl into a manual one.
 //
 // ```
 // Converts a `derive` impl into a manual one.
 //
 // ```
+// # //- minicore: derive
 // # trait Debug { fn fmt(&self, f: &mut Formatter) -> Result<()>; }
 // #[derive(Deb$0ug, Display)]
 // struct S;
 // # trait Debug { fn fmt(&self, f: &mut Formatter) -> Result<()>; }
 // #[derive(Deb$0ug, Display)]
 // struct S;
@@ -45,20 +46,30 @@ pub(crate) fn replace_derive_with_manual_impl(
     acc: &mut Assists,
     ctx: &AssistContext,
 ) -> Option<()> {
     acc: &mut Assists,
     ctx: &AssistContext,
 ) -> Option<()> {
-    let attr = ctx.find_node_at_offset::<ast::Attr>()?;
-    let (name, args) = attr.as_simple_call()?;
-    if name != "derive" {
+    let attr = ctx.find_node_at_offset_with_descend::<ast::Attr>()?;
+    let path = attr.path()?;
+    let hir_file = ctx.sema.hir_file_for(attr.syntax());
+    if !hir_file.is_derive_attr_macro(ctx.db()) {
         return None;
     }
 
         return None;
     }
 
-    if !args.syntax().text_range().contains(ctx.offset()) {
-        cov_mark::hit!(outside_of_attr_args);
+    let InFile { file_id, value } = hir_file.call_node(ctx.db())?;
+    if file_id.is_macro() {
+        // FIXME: make this work in macro files
         return None;
     }
         return None;
     }
+    // collect the derive paths from the #[derive] expansion
+    let current_derives = ctx
+        .sema
+        .parse_or_expand(hir_file)?
+        .descendants()
+        .filter_map(ast::Attr::cast)
+        .filter_map(|attr| attr.path())
+        .collect::<Vec<_>>();
 
 
-    let ident = args.syntax().token_at_offset(ctx.offset()).find_map(ast::Ident::cast)?;
-    let trait_path = get_path_at_cursor_in_tt(&ident)?;
-    let adt = attr.syntax().parent().and_then(ast::Adt::cast)?;
+    let adt = value.parent().and_then(ast::Adt::cast)?;
+    let attr = ast::Attr::cast(value)?;
+    let args = attr.token_tree()?;
 
     let current_module = ctx.sema.scope(adt.syntax()).module()?;
     let current_crate = current_module.krate();
 
     let current_module = ctx.sema.scope(adt.syntax()).module()?;
     let current_crate = current_module.krate();
@@ -66,7 +77,7 @@ pub(crate) fn replace_derive_with_manual_impl(
     let found_traits = items_locator::items_with_name(
         &ctx.sema,
         current_crate,
     let found_traits = items_locator::items_with_name(
         &ctx.sema,
         current_crate,
-        NameToImport::exact_case_sensitive(trait_path.segments().last()?.to_string()),
+        NameToImport::exact_case_sensitive(path.segments().last()?.to_string()),
         items_locator::AssocItemSearch::Exclude,
         Some(items_locator::DEFAULT_QUERY_SEARCH_LIMIT.inner()),
     )
         items_locator::AssocItemSearch::Exclude,
         Some(items_locator::DEFAULT_QUERY_SEARCH_LIMIT.inner()),
     )
@@ -83,8 +94,6 @@ pub(crate) fn replace_derive_with_manual_impl(
     });
 
     let mut no_traits_found = true;
     });
 
     let mut no_traits_found = true;
-    let current_derives = parse_tt_as_comma_sep_paths(args.clone())?;
-    let current_derives = current_derives.as_slice();
     for (replace_trait_path, trait_) in found_traits.inspect(|_| no_traits_found = false) {
         add_assist(
             acc,
     for (replace_trait_path, trait_) in found_traits.inspect(|_| no_traits_found = false) {
         add_assist(
             acc,
@@ -92,14 +101,14 @@ pub(crate) fn replace_derive_with_manual_impl(
             &attr,
             &current_derives,
             &args,
             &attr,
             &current_derives,
             &args,
-            &trait_path,
+            &path,
             &replace_trait_path,
             Some(trait_),
             &adt,
         )?;
     }
     if no_traits_found {
             &replace_trait_path,
             Some(trait_),
             &adt,
         )?;
     }
     if no_traits_found {
-        add_assist(acc, ctx, &attr, &current_derives, &args, &trait_path, &trait_path, None, &adt)?;
+        add_assist(acc, ctx, &attr, &current_derives, &args, &path, &path, None, &adt)?;
     }
     Some(())
 }
     }
     Some(())
 }
@@ -128,7 +137,7 @@ fn add_assist(
             let impl_def_with_items =
                 impl_def_from_trait(&ctx.sema, adt, &annotated_name, trait_, replace_trait_path);
             update_attribute(builder, old_derives, old_tree, old_trait_path, attr);
             let impl_def_with_items =
                 impl_def_from_trait(&ctx.sema, adt, &annotated_name, trait_, replace_trait_path);
             update_attribute(builder, old_derives, old_tree, old_trait_path, attr);
-            let trait_path = format!("{}", replace_trait_path);
+            let trait_path = replace_trait_path.to_string();
             match (ctx.config.snippet_cap, impl_def_with_items) {
                 (None, _) => {
                     builder.insert(insert_pos, generate_trait_impl_text(adt, &trait_path, ""))
             match (ctx.config.snippet_cap, impl_def_with_items) {
                 (None, _) => {
                     builder.insert(insert_pos, generate_trait_impl_text(adt, &trait_path, ""))
@@ -258,7 +267,7 @@ fn add_custom_impl_debug_record_struct() {
         check_assist(
             replace_derive_with_manual_impl,
             r#"
         check_assist(
             replace_derive_with_manual_impl,
             r#"
-//- minicore: fmt
+//- minicore: fmt, derive
 #[derive(Debu$0g)]
 struct Foo {
     bar: String,
 #[derive(Debu$0g)]
 struct Foo {
     bar: String,
@@ -282,7 +291,7 @@ fn add_custom_impl_debug_tuple_struct() {
         check_assist(
             replace_derive_with_manual_impl,
             r#"
         check_assist(
             replace_derive_with_manual_impl,
             r#"
-//- minicore: fmt
+//- minicore: fmt, derive
 #[derive(Debu$0g)]
 struct Foo(String, usize);
 "#,
 #[derive(Debu$0g)]
 struct Foo(String, usize);
 "#,
@@ -301,7 +310,7 @@ fn add_custom_impl_debug_empty_struct() {
         check_assist(
             replace_derive_with_manual_impl,
             r#"
         check_assist(
             replace_derive_with_manual_impl,
             r#"
-//- minicore: fmt
+//- minicore: fmt, derive
 #[derive(Debu$0g)]
 struct Foo;
 "#,
 #[derive(Debu$0g)]
 struct Foo;
 "#,
@@ -321,7 +330,7 @@ fn add_custom_impl_debug_enum() {
         check_assist(
             replace_derive_with_manual_impl,
             r#"
         check_assist(
             replace_derive_with_manual_impl,
             r#"
-//- minicore: fmt
+//- minicore: fmt, derive
 #[derive(Debu$0g)]
 enum Foo {
     Bar,
 #[derive(Debu$0g)]
 enum Foo {
     Bar,
@@ -351,7 +360,7 @@ fn add_custom_impl_debug_tuple_enum() {
         check_assist(
             replace_derive_with_manual_impl,
             r#"
         check_assist(
             replace_derive_with_manual_impl,
             r#"
-//- minicore: fmt
+//- minicore: fmt, derive
 #[derive(Debu$0g)]
 enum Foo {
     Bar(usize, usize),
 #[derive(Debu$0g)]
 enum Foo {
     Bar(usize, usize),
@@ -380,7 +389,7 @@ fn add_custom_impl_debug_record_enum() {
         check_assist(
             replace_derive_with_manual_impl,
             r#"
         check_assist(
             replace_derive_with_manual_impl,
             r#"
-//- minicore: fmt
+//- minicore: fmt, derive
 #[derive(Debu$0g)]
 enum Foo {
     Bar {
 #[derive(Debu$0g)]
 enum Foo {
     Bar {
@@ -415,7 +424,7 @@ fn add_custom_impl_default_record_struct() {
         check_assist(
             replace_derive_with_manual_impl,
             r#"
         check_assist(
             replace_derive_with_manual_impl,
             r#"
-//- minicore: default
+//- minicore: default, derive
 #[derive(Defau$0lt)]
 struct Foo {
     foo: usize,
 #[derive(Defau$0lt)]
 struct Foo {
     foo: usize,
@@ -439,7 +448,7 @@ fn add_custom_impl_default_tuple_struct() {
         check_assist(
             replace_derive_with_manual_impl,
             r#"
         check_assist(
             replace_derive_with_manual_impl,
             r#"
-//- minicore: default
+//- minicore: default, derive
 #[derive(Defau$0lt)]
 struct Foo(usize);
 "#,
 #[derive(Defau$0lt)]
 struct Foo(usize);
 "#,
@@ -459,7 +468,7 @@ fn add_custom_impl_default_empty_struct() {
         check_assist(
             replace_derive_with_manual_impl,
             r#"
         check_assist(
             replace_derive_with_manual_impl,
             r#"
-//- minicore: default
+//- minicore: default, derive
 #[derive(Defau$0lt)]
 struct Foo;
 "#,
 #[derive(Defau$0lt)]
 struct Foo;
 "#,
@@ -480,7 +489,7 @@ fn add_custom_impl_hash_record_struct() {
         check_assist(
             replace_derive_with_manual_impl,
             r#"
         check_assist(
             replace_derive_with_manual_impl,
             r#"
-//- minicore: hash
+//- minicore: hash, derive
 #[derive(Has$0h)]
 struct Foo {
     bin: usize,
 #[derive(Has$0h)]
 struct Foo {
     bin: usize,
@@ -508,7 +517,7 @@ fn add_custom_impl_hash_tuple_struct() {
         check_assist(
             replace_derive_with_manual_impl,
             r#"
         check_assist(
             replace_derive_with_manual_impl,
             r#"
-//- minicore: hash
+//- minicore: hash, derive
 #[derive(Has$0h)]
 struct Foo(usize, usize);
 "#,
 #[derive(Has$0h)]
 struct Foo(usize, usize);
 "#,
@@ -530,7 +539,7 @@ fn add_custom_impl_hash_enum() {
         check_assist(
             replace_derive_with_manual_impl,
             r#"
         check_assist(
             replace_derive_with_manual_impl,
             r#"
-//- minicore: hash
+//- minicore: hash, derive
 #[derive(Has$0h)]
 enum Foo {
     Bar,
 #[derive(Has$0h)]
 enum Foo {
     Bar,
@@ -557,7 +566,7 @@ fn add_custom_impl_clone_record_struct() {
         check_assist(
             replace_derive_with_manual_impl,
             r#"
         check_assist(
             replace_derive_with_manual_impl,
             r#"
-//- minicore: clone
+//- minicore: clone, derive
 #[derive(Clo$0ne)]
 struct Foo {
     bin: usize,
 #[derive(Clo$0ne)]
 struct Foo {
     bin: usize,
@@ -584,7 +593,7 @@ fn add_custom_impl_clone_tuple_struct() {
         check_assist(
             replace_derive_with_manual_impl,
             r#"
         check_assist(
             replace_derive_with_manual_impl,
             r#"
-//- minicore: clone
+//- minicore: clone, derive
 #[derive(Clo$0ne)]
 struct Foo(usize, usize);
 "#,
 #[derive(Clo$0ne)]
 struct Foo(usize, usize);
 "#,
@@ -605,7 +614,7 @@ fn add_custom_impl_clone_empty_struct() {
         check_assist(
             replace_derive_with_manual_impl,
             r#"
         check_assist(
             replace_derive_with_manual_impl,
             r#"
-//- minicore: clone
+//- minicore: clone, derive
 #[derive(Clo$0ne)]
 struct Foo;
 "#,
 #[derive(Clo$0ne)]
 struct Foo;
 "#,
@@ -626,7 +635,7 @@ fn add_custom_impl_clone_enum() {
         check_assist(
             replace_derive_with_manual_impl,
             r#"
         check_assist(
             replace_derive_with_manual_impl,
             r#"
-//- minicore: clone
+//- minicore: clone, derive
 #[derive(Clo$0ne)]
 enum Foo {
     Bar,
 #[derive(Clo$0ne)]
 enum Foo {
     Bar,
@@ -656,7 +665,7 @@ fn add_custom_impl_clone_tuple_enum() {
         check_assist(
             replace_derive_with_manual_impl,
             r#"
         check_assist(
             replace_derive_with_manual_impl,
             r#"
-//- minicore: clone
+//- minicore: clone, derive
 #[derive(Clo$0ne)]
 enum Foo {
     Bar(String),
 #[derive(Clo$0ne)]
 enum Foo {
     Bar(String),
@@ -686,7 +695,7 @@ fn add_custom_impl_clone_record_enum() {
         check_assist(
             replace_derive_with_manual_impl,
             r#"
         check_assist(
             replace_derive_with_manual_impl,
             r#"
-//- minicore: clone
+//- minicore: clone, derive
 #[derive(Clo$0ne)]
 enum Foo {
     Bar {
 #[derive(Clo$0ne)]
 enum Foo {
     Bar {
@@ -720,7 +729,7 @@ fn add_custom_impl_partial_ord_record_struct() {
         check_assist(
             replace_derive_with_manual_impl,
             r#"
         check_assist(
             replace_derive_with_manual_impl,
             r#"
-//- minicore: ord
+//- minicore: ord, derive
 #[derive(Partial$0Ord)]
 struct Foo {
     bin: usize,
 #[derive(Partial$0Ord)]
 struct Foo {
     bin: usize,
@@ -745,7 +754,7 @@ fn add_custom_impl_partial_ord_record_struct_multi_field() {
         check_assist(
             replace_derive_with_manual_impl,
             r#"
         check_assist(
             replace_derive_with_manual_impl,
             r#"
-//- minicore: ord
+//- minicore: ord, derive
 #[derive(Partial$0Ord)]
 struct Foo {
     bin: usize,
 #[derive(Partial$0Ord)]
 struct Foo {
     bin: usize,
@@ -782,7 +791,7 @@ fn add_custom_impl_partial_ord_tuple_struct() {
         check_assist(
             replace_derive_with_manual_impl,
             r#"
         check_assist(
             replace_derive_with_manual_impl,
             r#"
-//- minicore: ord
+//- minicore: ord, derive
 #[derive(Partial$0Ord)]
 struct Foo(usize, usize, usize);
 "#,
 #[derive(Partial$0Ord)]
 struct Foo(usize, usize, usize);
 "#,
@@ -811,7 +820,7 @@ fn add_custom_impl_partial_eq_record_struct() {
         check_assist(
             replace_derive_with_manual_impl,
             r#"
         check_assist(
             replace_derive_with_manual_impl,
             r#"
-//- minicore: eq
+//- minicore: eq, derive
 #[derive(Partial$0Eq)]
 struct Foo {
     bin: usize,
 #[derive(Partial$0Eq)]
 struct Foo {
     bin: usize,
@@ -838,7 +847,7 @@ fn add_custom_impl_partial_eq_tuple_struct() {
         check_assist(
             replace_derive_with_manual_impl,
             r#"
         check_assist(
             replace_derive_with_manual_impl,
             r#"
-//- minicore: eq
+//- minicore: eq, derive
 #[derive(Partial$0Eq)]
 struct Foo(usize, usize);
 "#,
 #[derive(Partial$0Eq)]
 struct Foo(usize, usize);
 "#,
@@ -859,7 +868,7 @@ fn add_custom_impl_partial_eq_empty_struct() {
         check_assist(
             replace_derive_with_manual_impl,
             r#"
         check_assist(
             replace_derive_with_manual_impl,
             r#"
-//- minicore: eq
+//- minicore: eq, derive
 #[derive(Partial$0Eq)]
 struct Foo;
 "#,
 #[derive(Partial$0Eq)]
 struct Foo;
 "#,
@@ -880,7 +889,7 @@ fn add_custom_impl_partial_eq_enum() {
         check_assist(
             replace_derive_with_manual_impl,
             r#"
         check_assist(
             replace_derive_with_manual_impl,
             r#"
-//- minicore: eq
+//- minicore: eq, derive
 #[derive(Partial$0Eq)]
 enum Foo {
     Bar,
 #[derive(Partial$0Eq)]
 enum Foo {
     Bar,
@@ -907,7 +916,7 @@ fn add_custom_impl_partial_eq_tuple_enum() {
         check_assist(
             replace_derive_with_manual_impl,
             r#"
         check_assist(
             replace_derive_with_manual_impl,
             r#"
-//- minicore: eq
+//- minicore: eq, derive
 #[derive(Partial$0Eq)]
 enum Foo {
     Bar(String),
 #[derive(Partial$0Eq)]
 enum Foo {
     Bar(String),
@@ -937,7 +946,7 @@ fn add_custom_impl_partial_eq_record_enum() {
         check_assist(
             replace_derive_with_manual_impl,
             r#"
         check_assist(
             replace_derive_with_manual_impl,
             r#"
-//- minicore: eq
+//- minicore: eq, derive
 #[derive(Partial$0Eq)]
 enum Foo {
     Bar {
 #[derive(Partial$0Eq)]
 enum Foo {
     Bar {
@@ -981,6 +990,7 @@ fn add_custom_impl_all() {
         check_assist(
             replace_derive_with_manual_impl,
             r#"
         check_assist(
             replace_derive_with_manual_impl,
             r#"
+//- minicore: derive
 mod foo {
     pub trait Bar {
         type Qux;
 mod foo {
     pub trait Bar {
         type Qux;
@@ -1026,10 +1036,11 @@ fn foo() {
         )
     }
     #[test]
         )
     }
     #[test]
-    fn add_custom_impl_for_unique_input() {
+    fn add_custom_impl_for_unique_input_unknown() {
         check_assist(
             replace_derive_with_manual_impl,
             r#"
         check_assist(
             replace_derive_with_manual_impl,
             r#"
+//- minicore: derive
 #[derive(Debu$0g)]
 struct Foo {
     bar: String,
 #[derive(Debu$0g)]
 struct Foo {
     bar: String,
@@ -1052,6 +1063,7 @@ fn add_custom_impl_for_with_visibility_modifier() {
         check_assist(
             replace_derive_with_manual_impl,
             r#"
         check_assist(
             replace_derive_with_manual_impl,
             r#"
+//- minicore: derive
 #[derive(Debug$0)]
 pub struct Foo {
     bar: String,
 #[derive(Debug$0)]
 pub struct Foo {
     bar: String,
@@ -1074,6 +1086,7 @@ fn add_custom_impl_when_multiple_inputs() {
         check_assist(
             replace_derive_with_manual_impl,
             r#"
         check_assist(
             replace_derive_with_manual_impl,
             r#"
+//- minicore: derive
 #[derive(Display, Debug$0, Serialize)]
 struct Foo {}
             "#,
 #[derive(Display, Debug$0, Serialize)]
 struct Foo {}
             "#,
@@ -1093,7 +1106,7 @@ fn add_custom_impl_default_generic_record_struct() {
         check_assist(
             replace_derive_with_manual_impl,
             r#"
         check_assist(
             replace_derive_with_manual_impl,
             r#"
-//- minicore: default
+//- minicore: default, derive
 #[derive(Defau$0lt)]
 struct Foo<T, U> {
     foo: T,
 #[derive(Defau$0lt)]
 struct Foo<T, U> {
     foo: T,
@@ -1120,7 +1133,7 @@ fn add_custom_impl_clone_generic_tuple_struct_with_bounds() {
         check_assist(
             replace_derive_with_manual_impl,
             r#"
         check_assist(
             replace_derive_with_manual_impl,
             r#"
-//- minicore: clone
+//- minicore: clone, derive
 #[derive(Clo$0ne)]
 struct Foo<T: Clone>(T, usize);
 "#,
 #[derive(Clo$0ne)]
 struct Foo<T: Clone>(T, usize);
 "#,
@@ -1141,6 +1154,7 @@ fn test_ignore_derive_macro_without_input() {
         check_assist_not_applicable(
             replace_derive_with_manual_impl,
             r#"
         check_assist_not_applicable(
             replace_derive_with_manual_impl,
             r#"
+//- minicore: derive
 #[derive($0)]
 struct Foo {}
             "#,
 #[derive($0)]
 struct Foo {}
             "#,
@@ -1152,6 +1166,7 @@ fn test_ignore_if_cursor_on_param() {
         check_assist_not_applicable(
             replace_derive_with_manual_impl,
             r#"
         check_assist_not_applicable(
             replace_derive_with_manual_impl,
             r#"
+//- minicore: derive, fmt
 #[derive$0(Debug)]
 struct Foo {}
             "#,
 #[derive$0(Debug)]
 struct Foo {}
             "#,
@@ -1160,6 +1175,7 @@ struct Foo {}
         check_assist_not_applicable(
             replace_derive_with_manual_impl,
             r#"
         check_assist_not_applicable(
             replace_derive_with_manual_impl,
             r#"
+//- minicore: derive, fmt
 #[derive(Debug)$0]
 struct Foo {}
             "#,
 #[derive(Debug)$0]
 struct Foo {}
             "#,
@@ -1171,6 +1187,7 @@ fn test_ignore_if_not_derive() {
         check_assist_not_applicable(
             replace_derive_with_manual_impl,
             r#"
         check_assist_not_applicable(
             replace_derive_with_manual_impl,
             r#"
+//- minicore: derive
 #[allow(non_camel_$0case_types)]
 struct Foo {}
             "#,
 #[allow(non_camel_$0case_types)]
 struct Foo {}
             "#,
@@ -1179,10 +1196,10 @@ struct Foo {}
 
     #[test]
     fn works_at_start_of_file() {
 
     #[test]
     fn works_at_start_of_file() {
-        cov_mark::check!(outside_of_attr_args);
         check_assist_not_applicable(
             replace_derive_with_manual_impl,
             r#"
         check_assist_not_applicable(
             replace_derive_with_manual_impl,
             r#"
+//- minicore: derive, fmt
 $0#[derive(Debug)]
 struct S;
             "#,
 $0#[derive(Debug)]
 struct S;
             "#,
@@ -1194,7 +1211,7 @@ fn add_custom_impl_keep_path() {
         check_assist(
             replace_derive_with_manual_impl,
             r#"
         check_assist(
             replace_derive_with_manual_impl,
             r#"
-//- minicore: clone
+//- minicore: clone, derive
 #[derive(std::fmt::Debug, Clo$0ne)]
 pub struct Foo;
 "#,
 #[derive(std::fmt::Debug, Clo$0ne)]
 pub struct Foo;
 "#,
@@ -1216,7 +1233,7 @@ fn add_custom_impl_replace_path() {
         check_assist(
             replace_derive_with_manual_impl,
             r#"
         check_assist(
             replace_derive_with_manual_impl,
             r#"
-//- minicore: fmt
+//- minicore: fmt, derive
 #[derive(core::fmt::Deb$0ug, Clone)]
 pub struct Foo;
 "#,
 #[derive(core::fmt::Deb$0ug, Clone)]
 pub struct Foo;
 "#,
index 0ad4b3bc345c1e1454754e09b26c854a76ca7f90..485b807d0556d23118294d6e0b3323a5f598f004 100644 (file)
@@ -1766,6 +1766,7 @@ fn doctest_replace_derive_with_manual_impl() {
     check_doc_test(
         "replace_derive_with_manual_impl",
         r#####"
     check_doc_test(
         "replace_derive_with_manual_impl",
         r#####"
+//- minicore: derive
 trait Debug { fn fmt(&self, f: &mut Formatter) -> Result<()>; }
 #[derive(Deb$0ug, Display)]
 struct S;
 trait Debug { fn fmt(&self, f: &mut Formatter) -> Result<()>; }
 #[derive(Deb$0ug, Display)]
 struct S;
index c355016c5dfd054dac27f949f37eeb4a6882bab6..6357b6c30bb923b7b936315f76a9010e46a12dd0 100644 (file)
@@ -9,15 +9,14 @@
 pub mod rust_doc;
 pub mod format_string;
 
 pub mod rust_doc;
 pub mod format_string;
 
-use std::{collections::VecDeque, iter};
+use std::collections::VecDeque;
 
 use base_db::FileId;
 
 use base_db::FileId;
-use hir::{ItemInNs, MacroDef, ModuleDef, Name, PathResolution, Semantics};
+use hir::{ItemInNs, MacroDef, ModuleDef, Name, Semantics};
 use itertools::Itertools;
 use syntax::{
     ast::{self, make, HasLoopBody},
 use itertools::Itertools;
 use syntax::{
     ast::{self, make, HasLoopBody},
-    AstNode, AstToken, Direction, SyntaxElement, SyntaxKind, SyntaxToken, TokenAtOffset, WalkEvent,
-    T,
+    AstNode, SyntaxKind, SyntaxToken, TokenAtOffset, WalkEvent, T,
 };
 
 use crate::{defs::Definition, RootDatabase};
 };
 
 use crate::{defs::Definition, RootDatabase};
@@ -32,49 +31,6 @@ pub fn item_name(db: &RootDatabase, item: ItemInNs) -> Option<Name> {
     }
 }
 
     }
 }
 
-/// Parses and returns the derive path at the cursor position in the given attribute, if it is a derive.
-/// This special case is required because the derive macro is a compiler builtin that discards the input derives.
-///
-/// The returned path is synthesized from TokenTree tokens and as such cannot be used with the [`Semantics`].
-pub fn get_path_in_derive_attr(
-    sema: &hir::Semantics<RootDatabase>,
-    attr: &ast::Attr,
-    cursor: &ast::Ident,
-) -> Option<ast::Path> {
-    let path = attr.path()?;
-    let tt = attr.token_tree()?;
-    if !tt.syntax().text_range().contains_range(cursor.syntax().text_range()) {
-        return None;
-    }
-    let scope = sema.scope(attr.syntax());
-    let resolved_attr = sema.resolve_path(&path)?;
-    let derive = FamousDefs(sema, scope.krate()).core_macros_builtin_derive()?;
-    if PathResolution::Macro(derive) != resolved_attr {
-        return None;
-    }
-    get_path_at_cursor_in_tt(cursor)
-}
-
-/// Parses the path the identifier is part of inside a token tree.
-pub fn get_path_at_cursor_in_tt(cursor: &ast::Ident) -> Option<ast::Path> {
-    let cursor = cursor.syntax();
-    let first = cursor
-        .siblings_with_tokens(Direction::Prev)
-        .filter_map(SyntaxElement::into_token)
-        .take_while(|tok| tok.kind() != T!['('] && tok.kind() != T![,])
-        .last()?;
-    let path_tokens = first
-        .siblings_with_tokens(Direction::Next)
-        .filter_map(SyntaxElement::into_token)
-        .take_while(|tok| tok != cursor);
-
-    syntax::hacks::parse_expr_from_str(&path_tokens.chain(iter::once(cursor.clone())).join(""))
-        .and_then(|expr| match expr {
-            ast::Expr::PathExpr(it) => it.path(),
-            _ => None,
-        })
-}
-
 /// Picks the token with the highest rank returned by the passed in function.
 pub fn pick_best_token(
     tokens: TokenAtOffset<SyntaxToken>,
 /// Picks the token with the highest rank returned by the passed in function.
 pub fn pick_best_token(
     tokens: TokenAtOffset<SyntaxToken>,
index c037c3e0f87638cf47c25016e703dc58fecb473e..319a21735297a82a2e3e703248e49f3536744b54 100644 (file)
@@ -8,11 +8,10 @@
 use syntax::{
     ast::{self, HasName},
     utils::path_to_string_stripping_turbo_fish,
 use syntax::{
     ast::{self, HasName},
     utils::path_to_string_stripping_turbo_fish,
-    AstNode, AstToken, SyntaxNode,
+    AstNode, SyntaxNode,
 };
 
 use crate::{
 };
 
 use crate::{
-    helpers::get_path_in_derive_attr,
     items_locator::{self, AssocItemSearch, DEFAULT_QUERY_SEARCH_LIMIT},
     RootDatabase,
 };
     items_locator::{self, AssocItemSearch, DEFAULT_QUERY_SEARCH_LIMIT},
     RootDatabase,
 };
@@ -139,23 +138,6 @@ pub fn for_ident_pat(sema: &Semantics<RootDatabase>, pat: &ast::IdentPat) -> Opt
         })
     }
 
         })
     }
 
-    pub fn for_derive_ident(sema: &Semantics<RootDatabase>, ident: &ast::Ident) -> Option<Self> {
-        let attr = ident.syntax().ancestors().find_map(ast::Attr::cast)?;
-        let path = get_path_in_derive_attr(sema, &attr, ident)?;
-
-        if let Some(_) = path.qualifier() {
-            return None;
-        }
-
-        let name = NameToImport::exact_case_sensitive(path.segment()?.name_ref()?.to_string());
-        let candidate_node = attr.syntax().clone();
-        Some(Self {
-            import_candidate: ImportCandidate::Path(PathImportCandidate { qualifier: None, name }),
-            module_with_candidate: sema.scope(&candidate_node).module()?,
-            candidate_node,
-        })
-    }
-
     pub fn for_fuzzy_path(
         module_with_candidate: Module,
         qualifier: Option<ast::Path>,
     pub fn for_fuzzy_path(
         module_with_candidate: Module,
         qualifier: Option<ast::Path>,
index 5ff6519c9ccf93c1c218458da9b960ae1b723282..1b916e91bfdea77b87324e3c307114b1f1ef5c74 100644 (file)
@@ -705,6 +705,15 @@ pub fn end(&self) -> Option<ast::Pat> {
 }
 
 impl ast::TokenTree {
 }
 
 impl ast::TokenTree {
+    pub fn token_trees_and_tokens(
+        &self,
+    ) -> impl Iterator<Item = NodeOrToken<ast::TokenTree, SyntaxToken>> {
+        self.syntax().children_with_tokens().filter_map(|not| match not {
+            NodeOrToken::Node(node) => ast::TokenTree::cast(node).map(NodeOrToken::Node),
+            NodeOrToken::Token(t) => Some(NodeOrToken::Token(t)),
+        })
+    }
+
     pub fn left_delimiter_token(&self) -> Option<SyntaxToken> {
         self.syntax()
             .first_child_or_token()?
     pub fn left_delimiter_token(&self) -> Option<SyntaxToken> {
         self.syntax()
             .first_child_or_token()?