Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/ide_completion/src/completions/attribute/derive.rs')
| -rw-r--r-- | crates/ide_completion/src/completions/attribute/derive.rs | 80 |
1 files changed, 47 insertions, 33 deletions
diff --git a/crates/ide_completion/src/completions/attribute/derive.rs b/crates/ide_completion/src/completions/attribute/derive.rs index 36758baafc..2824b2a2c2 100644 --- a/crates/ide_completion/src/completions/attribute/derive.rs +++ b/crates/ide_completion/src/completions/attribute/derive.rs @@ -1,8 +1,9 @@ //! Completion for derives -use hir::HasAttrs; +use hir::{HasAttrs, MacroDef, MacroKind}; +use ide_db::helpers::FamousDefs; use itertools::Itertools; -use rustc_hash::FxHashMap; -use syntax::{ast, SmolStr}; +use rustc_hash::FxHashSet; +use syntax::ast; use crate::{ context::CompletionContext, @@ -15,36 +16,51 @@ pub(super) fn complete_derive( ctx: &CompletionContext, derive_input: ast::TokenTree, ) { - if let Some(existing_derives) = super::parse_comma_sep_paths(derive_input) { - for (derive, docs) in get_derive_names_in_scope(ctx) { + if let Some(existing_derives) = super::parse_comma_sep_paths(derive_input.clone()) { + let core = FamousDefs(&ctx.sema, ctx.krate).core(); + let existing_derives: FxHashSet<_> = existing_derives + .into_iter() + .filter_map(|path| ctx.scope.speculative_resolve_as_mac(&path)) + .filter(|mac| mac.kind() == MacroKind::Derive) + .collect(); + + for (name, mac) in get_derives_in_scope(ctx) { + if existing_derives.contains(&mac) { + continue; + } + + let name = name.to_smol_str(); let label; - let (label, lookup) = if let Some(derive_completion) = DEFAULT_DERIVE_COMPLETIONS - .iter() - .find(|derive_completion| derive_completion.label == derive) - { - let mut components = vec![derive_completion.label]; - components.extend(derive_completion.dependencies.iter().filter(|&&dependency| { - !existing_derives + let (label, lookup) = match core.zip(mac.module(ctx.db).map(|it| it.krate())) { + // show derive dependencies for `core`/`std` derives + Some((core, mac_krate)) if core == mac_krate => { + if let Some(derive_completion) = DEFAULT_DERIVE_DEPENDENCIES .iter() - .filter_map(|it| it.as_single_name_ref()) - .any(|it| it.text() == dependency) - })); - let lookup = components.join(", "); - label = components.iter().rev().join(", "); - (&*label, Some(lookup)) - } else if existing_derives - .iter() - .filter_map(|it| it.as_single_name_ref()) - .any(|it| it.text().as_str() == derive) - { - continue; - } else { - (&*derive, None) + .find(|derive_completion| derive_completion.label == name) + { + let mut components = vec![derive_completion.label]; + components.extend(derive_completion.dependencies.iter().filter( + |&&dependency| { + !existing_derives + .iter() + .filter_map(|it| it.name(ctx.db)) + .any(|it| it.to_smol_str() == dependency) + }, + )); + let lookup = components.join(", "); + label = components.iter().rev().join(", "); + (label.as_str(), Some(lookup)) + } else { + (&*name, None) + } + } + _ => (&*name, None), }; + let mut item = CompletionItem::new(CompletionKind::Attribute, ctx.source_range(), label); item.kind(CompletionItemKind::Attribute); - if let Some(docs) = docs { + if let Some(docs) = mac.docs(ctx.db) { item.documentation(docs); } if let Some(lookup) = lookup { @@ -55,14 +71,12 @@ pub(super) fn complete_derive( } } -fn get_derive_names_in_scope( - ctx: &CompletionContext, -) -> FxHashMap<SmolStr, Option<hir::Documentation>> { - let mut result = FxHashMap::default(); +fn get_derives_in_scope(ctx: &CompletionContext) -> Vec<(hir::Name, MacroDef)> { + let mut result = Vec::default(); ctx.process_all_names(&mut |name, scope_def| { if let hir::ScopeDef::MacroDef(mac) = scope_def { if mac.kind() == hir::MacroKind::Derive { - result.insert(name.to_smol_str(), mac.docs(ctx.db)); + result.push((name, mac)); } } }); @@ -76,7 +90,7 @@ struct DeriveDependencies { /// Standard Rust derives that have dependencies /// (the dependencies are needed so that the main derive don't break the compilation when added) -const DEFAULT_DERIVE_COMPLETIONS: &[DeriveDependencies] = &[ +const DEFAULT_DERIVE_DEPENDENCIES: &[DeriveDependencies] = &[ DeriveDependencies { label: "Copy", dependencies: &["Clone"] }, DeriveDependencies { label: "Eq", dependencies: &["PartialEq"] }, DeriveDependencies { label: "Ord", dependencies: &["PartialOrd", "Eq", "PartialEq"] }, |