diff options
author | Kirill Bulatov <[email protected]> | 2020-05-02 20:24:27 +0100 |
---|---|---|
committer | Kirill Bulatov <[email protected]> | 2020-05-02 20:24:27 +0100 |
commit | fee74851b02fb69c32291f3051438901faaf667f (patch) | |
tree | 0f086146c872215e7b02e091bd4a187bae83f924 | |
parent | 767bff89ededdff875b042bb37397b972e3a82f1 (diff) |
Propose custom derives in completion
-rw-r--r-- | crates/ra_hir/src/code_model.rs | 15 | ||||
-rw-r--r-- | 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::{ | |||
19 | use hir_expand::{ | 19 | use hir_expand::{ |
20 | diagnostics::DiagnosticSink, | 20 | diagnostics::DiagnosticSink, |
21 | name::{name, AsName}, | 21 | name::{name, AsName}, |
22 | MacroDefId, | 22 | MacroDefId, MacroDefKind, |
23 | }; | 23 | }; |
24 | use hir_ty::{ | 24 | use 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 | ||
132 | fn complete_derive(acc: &mut Completions, ctx: &CompletionContext, derive_input: ast::TokenTree) { | 132 | fn 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 | ||
186 | fn 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 | |||
177 | struct DeriveCompletion { | 199 | struct DeriveCompletion { |
178 | label: &'static str, | 200 | label: &'static str, |
179 | dependencies: &'static [&'static str], | 201 | dependencies: &'static [&'static str], |
180 | } | 202 | } |
181 | 203 | ||
182 | const 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) | ||
206 | const 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: &[] }, |