aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKirill Bulatov <[email protected]>2020-05-02 20:24:27 +0100
committerKirill Bulatov <[email protected]>2020-05-02 20:24:27 +0100
commitfee74851b02fb69c32291f3051438901faaf667f (patch)
tree0f086146c872215e7b02e091bd4a187bae83f924
parent767bff89ededdff875b042bb37397b972e3a82f1 (diff)
Propose custom derives in completion
-rw-r--r--crates/ra_hir/src/code_model.rs15
-rw-r--r--crates/ra_ide/src/completion/complete_attribute.rs40
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::{
19use hir_expand::{ 19use hir_expand::{
20 diagnostics::DiagnosticSink, 20 diagnostics::DiagnosticSink,
21 name::{name, AsName}, 21 name::{name, AsName},
22 MacroDefId, 22 MacroDefId, MacroDefKind,
23}; 23};
24use hir_ty::{ 24use hir_ty::{
25 autoderef, display::HirFormatter, expr::ExprValidator, method_resolution, ApplicationTy, 25 autoderef, display::HirFormatter, expr::ExprValidator, method_resolution, ApplicationTy,
@@ -762,13 +762,12 @@ impl MacroDef {
762 762
763 /// Indicate it is a proc-macro 763 /// Indicate it is a proc-macro
764 pub fn is_proc_macro(&self) -> bool { 764 pub fn is_proc_macro(&self) -> bool {
765 match self.id.kind { 765 matches!(self.id.kind, MacroDefKind::CustomDerive(_))
766 hir_expand::MacroDefKind::Declarative => false, 766 }
767 hir_expand::MacroDefKind::BuiltIn(_) => false, 767
768 hir_expand::MacroDefKind::BuiltInDerive(_) => false, 768 /// Indicate it is a derive macro
769 hir_expand::MacroDefKind::BuiltInEager(_) => false, 769 pub fn is_derive_macro(&self) -> bool {
770 hir_expand::MacroDefKind::CustomDerive(_) => true, 770 matches!(self.id.kind, MacroDefKind::CustomDerive(_) | MacroDefKind::BuiltInDerive(_))
771 }
772 } 771 }
773} 772}
774 773
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] = &[
130]; 130];
131 131
132fn complete_derive(acc: &mut Completions, ctx: &CompletionContext, derive_input: ast::TokenTree) { 132fn complete_derive(acc: &mut Completions, ctx: &CompletionContext, derive_input: ast::TokenTree) {
133 // TODO kb autodetect derive macros
134 // https://rust-lang.zulipchat.com/#narrow/stream/185405-t-compiler.2Fwg-rls-2.2E0/topic/Find.20all.20possible.20derive.20macro.20values.3F/near/195955580
135
136 if let Ok(existing_derives) = parse_derive_input(derive_input) { 133 if let Ok(existing_derives) = parse_derive_input(derive_input) {
137 for derive_completion in DERIVE_COMPLETIONS 134 for derive_completion in DEFAULT_DERIVE_COMPLETIONS
138 .into_iter() 135 .into_iter()
139 .filter(|completion| !existing_derives.contains(completion.label)) 136 .filter(|completion| !existing_derives.contains(completion.label))
140 { 137 {
@@ -147,9 +144,21 @@ fn complete_derive(acc: &mut Completions, ctx: &CompletionContext, derive_input:
147 label.push_str(", "); 144 label.push_str(", ");
148 label.push_str(dependency); 145 label.push_str(dependency);
149 } 146 }
150 let item = CompletionItem::new(CompletionKind::Attribute, ctx.source_range(), label) 147 acc.add(
151 .kind(CompletionItemKind::Attribute); 148 CompletionItem::new(CompletionKind::Attribute, ctx.source_range(), label)
152 acc.add(item); 149 .kind(CompletionItemKind::Attribute),
150 );
151 }
152
153 for custom_derive_name in get_derive_names_in_scope(ctx).difference(&existing_derives) {
154 acc.add(
155 CompletionItem::new(
156 CompletionKind::Attribute,
157 ctx.source_range(),
158 custom_derive_name,
159 )
160 .kind(CompletionItemKind::Attribute),
161 );
153 } 162 }
154 } 163 }
155} 164}
@@ -174,12 +183,27 @@ fn parse_derive_input(derive_input: ast::TokenTree) -> Result<FxHashSet<String>,
174 } 183 }
175} 184}
176 185
186fn get_derive_names_in_scope(ctx: &CompletionContext) -> FxHashSet<String> {
187 let mut result = FxHashSet::default();
188 ctx.scope().process_all_names(&mut |name, scope_def| {
189 if let hir::ScopeDef::MacroDef(mac) = scope_def {
190 if mac.is_derive_macro() {
191 let name_string = name.to_string();
192 result.insert(name_string);
193 }
194 }
195 });
196 result
197}
198
177struct DeriveCompletion { 199struct DeriveCompletion {
178 label: &'static str, 200 label: &'static str,
179 dependencies: &'static [&'static str], 201 dependencies: &'static [&'static str],
180} 202}
181 203
182const DERIVE_COMPLETIONS: &[DeriveCompletion] = &[ 204/// Standard Rust derives and the information about their dependencies
205/// (the dependencies are needed so that the main derive don't break the compilation when added)
206const DEFAULT_DERIVE_COMPLETIONS: &[DeriveCompletion] = &[
183 DeriveCompletion { label: "Clone", dependencies: &[] }, 207 DeriveCompletion { label: "Clone", dependencies: &[] },
184 DeriveCompletion { label: "Copy", dependencies: &["Clone"] }, 208 DeriveCompletion { label: "Copy", dependencies: &["Clone"] },
185 DeriveCompletion { label: "Debug", dependencies: &[] }, 209 DeriveCompletion { label: "Debug", dependencies: &[] },