1 //! Completion for derives
3 use itertools::Itertools;
4 use rustc_hash::FxHashMap;
5 use syntax::{ast, SmolStr};
8 context::CompletionContext,
9 item::{CompletionItem, CompletionItemKind, CompletionKind},
13 pub(super) fn complete_derive(
14 acc: &mut Completions,
15 ctx: &CompletionContext,
16 derive_input: ast::TokenTree,
18 if let Some(existing_derives) = super::parse_comma_sep_paths(derive_input) {
19 for (derive, docs) in get_derive_names_in_scope(ctx) {
21 let (label, lookup) = if let Some(derive_completion) = DEFAULT_DERIVE_COMPLETIONS
23 .find(|derive_completion| derive_completion.label == derive)
25 let mut components = vec![derive_completion.label];
26 components.extend(derive_completion.dependencies.iter().filter(|&&dependency| {
29 .filter_map(|it| it.as_single_name_ref())
30 .any(|it| it.text() == dependency)
32 let lookup = components.join(", ");
33 label = components.iter().rev().join(", ");
34 (&*label, Some(lookup))
35 } else if existing_derives
37 .filter_map(|it| it.as_single_name_ref())
38 .any(|it| it.text().as_str() == derive)
45 CompletionItem::new(CompletionKind::Attribute, ctx.source_range(), label);
46 item.kind(CompletionItemKind::Attribute);
47 if let Some(docs) = docs {
48 item.documentation(docs);
50 if let Some(lookup) = lookup {
51 item.lookup_by(lookup);
58 fn get_derive_names_in_scope(
59 ctx: &CompletionContext,
60 ) -> FxHashMap<SmolStr, Option<hir::Documentation>> {
61 let mut result = FxHashMap::default();
62 ctx.process_all_names(&mut |name, scope_def| {
63 if let hir::ScopeDef::MacroDef(mac) = scope_def {
64 if mac.kind() == hir::MacroKind::Derive {
65 result.insert(name.to_smol_str(), mac.docs(ctx.db));
72 struct DeriveDependencies {
74 dependencies: &'static [&'static str],
77 /// Standard Rust derives that have dependencies
78 /// (the dependencies are needed so that the main derive don't break the compilation when added)
79 const DEFAULT_DERIVE_COMPLETIONS: &[DeriveDependencies] = &[
80 DeriveDependencies { label: "Copy", dependencies: &["Clone"] },
81 DeriveDependencies { label: "Eq", dependencies: &["PartialEq"] },
82 DeriveDependencies { label: "Ord", dependencies: &["PartialOrd", "Eq", "PartialEq"] },
83 DeriveDependencies { label: "PartialOrd", dependencies: &["PartialEq"] },