From fee74851b02fb69c32291f3051438901faaf667f Mon Sep 17 00:00:00 2001 From: Kirill Bulatov Date: Sat, 2 May 2020 22:24:27 +0300 Subject: Propose custom derives in completion --- crates/ra_hir/src/code_model.rs | 15 ++++---- crates/ra_ide/src/completion/complete_attribute.rs | 40 +++++++++++++++++----- 2 files changed, 39 insertions(+), 16 deletions(-) diff --git a/crates/ra_hir/src/code_model.rs b/crates/ra_hir/src/code_model.rs index af59aa1b6..a004363ee 100644 --- a/crates/ra_hir/src/code_model.rs +++ b/crates/ra_hir/src/code_model.rs @@ -19,7 +19,7 @@ use hir_def::{ use hir_expand::{ diagnostics::DiagnosticSink, name::{name, AsName}, - MacroDefId, + MacroDefId, MacroDefKind, }; use hir_ty::{ autoderef, display::HirFormatter, expr::ExprValidator, method_resolution, ApplicationTy, @@ -762,13 +762,12 @@ impl MacroDef { /// Indicate it is a proc-macro pub fn is_proc_macro(&self) -> bool { - match self.id.kind { - hir_expand::MacroDefKind::Declarative => false, - hir_expand::MacroDefKind::BuiltIn(_) => false, - hir_expand::MacroDefKind::BuiltInDerive(_) => false, - hir_expand::MacroDefKind::BuiltInEager(_) => false, - hir_expand::MacroDefKind::CustomDerive(_) => true, - } + matches!(self.id.kind, MacroDefKind::CustomDerive(_)) + } + + /// Indicate it is a derive macro + pub fn is_derive_macro(&self) -> bool { + matches!(self.id.kind, MacroDefKind::CustomDerive(_) | MacroDefKind::BuiltInDerive(_)) } } diff --git a/crates/ra_ide/src/completion/complete_attribute.rs b/crates/ra_ide/src/completion/complete_attribute.rs index 8934b45fe..346ba9e7a 100644 --- a/crates/ra_ide/src/completion/complete_attribute.rs +++ b/crates/ra_ide/src/completion/complete_attribute.rs @@ -130,11 +130,8 @@ const ATTRIBUTES: &[AttrCompletion] = &[ ]; fn complete_derive(acc: &mut Completions, ctx: &CompletionContext, derive_input: ast::TokenTree) { - // TODO kb autodetect derive macros - // https://rust-lang.zulipchat.com/#narrow/stream/185405-t-compiler.2Fwg-rls-2.2E0/topic/Find.20all.20possible.20derive.20macro.20values.3F/near/195955580 - if let Ok(existing_derives) = parse_derive_input(derive_input) { - for derive_completion in DERIVE_COMPLETIONS + for derive_completion in DEFAULT_DERIVE_COMPLETIONS .into_iter() .filter(|completion| !existing_derives.contains(completion.label)) { @@ -147,9 +144,21 @@ fn complete_derive(acc: &mut Completions, ctx: &CompletionContext, derive_input: label.push_str(", "); label.push_str(dependency); } - let item = CompletionItem::new(CompletionKind::Attribute, ctx.source_range(), label) - .kind(CompletionItemKind::Attribute); - acc.add(item); + acc.add( + CompletionItem::new(CompletionKind::Attribute, ctx.source_range(), label) + .kind(CompletionItemKind::Attribute), + ); + } + + for custom_derive_name in get_derive_names_in_scope(ctx).difference(&existing_derives) { + acc.add( + CompletionItem::new( + CompletionKind::Attribute, + ctx.source_range(), + custom_derive_name, + ) + .kind(CompletionItemKind::Attribute), + ); } } } @@ -174,12 +183,27 @@ fn parse_derive_input(derive_input: ast::TokenTree) -> Result, } } +fn get_derive_names_in_scope(ctx: &CompletionContext) -> FxHashSet { + let mut result = FxHashSet::default(); + ctx.scope().process_all_names(&mut |name, scope_def| { + if let hir::ScopeDef::MacroDef(mac) = scope_def { + if mac.is_derive_macro() { + let name_string = name.to_string(); + result.insert(name_string); + } + } + }); + result +} + struct DeriveCompletion { label: &'static str, dependencies: &'static [&'static str], } -const DERIVE_COMPLETIONS: &[DeriveCompletion] = &[ +/// Standard Rust derives and the information about their dependencies +/// (the dependencies are needed so that the main derive don't break the compilation when added) +const DEFAULT_DERIVE_COMPLETIONS: &[DeriveCompletion] = &[ DeriveCompletion { label: "Clone", dependencies: &[] }, DeriveCompletion { label: "Copy", dependencies: &["Clone"] }, DeriveCompletion { label: "Debug", dependencies: &[] }, -- cgit v1.2.3