11//! Completion for derives
2+ use hir:: HasAttrs ;
23use itertools:: Itertools ;
3- use rustc_hash:: FxHashSet ;
4+ use rustc_hash:: FxHashMap ;
45use syntax:: ast;
56
67use crate :: {
@@ -15,66 +16,64 @@ pub(super) fn complete_derive(
1516 derive_input : ast:: TokenTree ,
1617) {
1718 if let Some ( existing_derives) = super :: parse_comma_sep_input ( derive_input) {
18- for derive_completion in DEFAULT_DERIVE_COMPLETIONS
19- . iter ( )
20- . filter ( |completion| !existing_derives. contains ( completion. label ) )
21- {
22- let mut components = vec ! [ derive_completion. label] ;
23- components. extend (
24- derive_completion
25- . dependencies
26- . iter ( )
27- . filter ( |& & dependency| !existing_derives. contains ( dependency) ) ,
28- ) ;
29- let lookup = components. join ( ", " ) ;
30- let label = components. iter ( ) . rev ( ) . join ( ", " ) ;
19+ for ( derive, docs) in get_derive_names_in_scope ( ctx) {
20+ let ( label, lookup) = if let Some ( derive_completion) = DEFAULT_DERIVE_COMPLETIONS
21+ . iter ( )
22+ . find ( |derive_completion| derive_completion. label == derive)
23+ {
24+ let mut components = vec ! [ derive_completion. label] ;
25+ components. extend (
26+ derive_completion
27+ . dependencies
28+ . iter ( )
29+ . filter ( |& & dependency| !existing_derives. contains ( dependency) ) ,
30+ ) ;
31+ let lookup = components. join ( ", " ) ;
32+ let label = components. iter ( ) . rev ( ) . join ( ", " ) ;
33+ ( label, Some ( lookup) )
34+ } else {
35+ ( derive, None )
36+ } ;
3137 let mut item =
3238 CompletionItem :: new ( CompletionKind :: Attribute , ctx. source_range ( ) , label) ;
33- item. lookup_by ( lookup) . kind ( CompletionItemKind :: Attribute ) ;
34- item. add_to ( acc) ;
35- }
36-
37- for custom_derive_name in get_derive_names_in_scope ( ctx) . difference ( & existing_derives) {
38- let mut item = CompletionItem :: new (
39- CompletionKind :: Attribute ,
40- ctx. source_range ( ) ,
41- custom_derive_name,
42- ) ;
4339 item. kind ( CompletionItemKind :: Attribute ) ;
40+ if let Some ( docs) = docs {
41+ item. documentation ( docs) ;
42+ }
43+ if let Some ( lookup) = lookup {
44+ item. lookup_by ( lookup) ;
45+ }
4446 item. add_to ( acc) ;
4547 }
4648 }
4749}
4850
49- fn get_derive_names_in_scope ( ctx : & CompletionContext ) -> FxHashSet < String > {
50- let mut result = FxHashSet :: default ( ) ;
51+ fn get_derive_names_in_scope (
52+ ctx : & CompletionContext ,
53+ ) -> FxHashMap < String , Option < hir:: Documentation > > {
54+ let mut result = FxHashMap :: default ( ) ;
5155 ctx. scope . process_all_names ( & mut |name, scope_def| {
5256 if let hir:: ScopeDef :: MacroDef ( mac) = scope_def {
5357 if mac. kind ( ) == hir:: MacroKind :: Derive {
54- result. insert ( name. to_string ( ) ) ;
58+ result. insert ( name. to_string ( ) , mac . docs ( ctx . db ) ) ;
5559 }
5660 }
5761 } ) ;
5862 result
5963}
6064
61- struct DeriveCompletion {
65+ struct DeriveDependencies {
6266 label : & ' static str ,
6367 dependencies : & ' static [ & ' static str ] ,
6468}
6569
66- /// Standard Rust derives and the information about their dependencies
70+ /// Standard Rust derives that have dependencies
6771/// (the dependencies are needed so that the main derive don't break the compilation when added)
68- const DEFAULT_DERIVE_COMPLETIONS : & [ DeriveCompletion ] = & [
69- DeriveCompletion { label : "Clone" , dependencies : & [ ] } ,
70- DeriveCompletion { label : "Copy" , dependencies : & [ "Clone" ] } ,
71- DeriveCompletion { label : "Debug" , dependencies : & [ ] } ,
72- DeriveCompletion { label : "Default" , dependencies : & [ ] } ,
73- DeriveCompletion { label : "Hash" , dependencies : & [ ] } ,
74- DeriveCompletion { label : "PartialEq" , dependencies : & [ ] } ,
75- DeriveCompletion { label : "Eq" , dependencies : & [ "PartialEq" ] } ,
76- DeriveCompletion { label : "PartialOrd" , dependencies : & [ "PartialEq" ] } ,
77- DeriveCompletion { label : "Ord" , dependencies : & [ "PartialOrd" , "Eq" , "PartialEq" ] } ,
72+ const DEFAULT_DERIVE_COMPLETIONS : & [ DeriveDependencies ] = & [
73+ DeriveDependencies { label : "Copy" , dependencies : & [ "Clone" ] } ,
74+ DeriveDependencies { label : "Eq" , dependencies : & [ "PartialEq" ] } ,
75+ DeriveDependencies { label : "Ord" , dependencies : & [ "PartialOrd" , "Eq" , "PartialEq" ] } ,
76+ DeriveDependencies { label : "PartialOrd" , dependencies : & [ "PartialEq" ] } ,
7877] ;
7978
8079#[ cfg( test) ]
@@ -94,6 +93,7 @@ mod tests {
9493 }
9594
9695 #[ test]
96+ #[ ignore] // FIXME: Fixtures cant test proc-macros/derives yet as we cant specify them in fixtures
9797 fn empty_derive ( ) {
9898 check (
9999 r#"#[derive($0)] struct Test;"# ,
@@ -112,6 +112,7 @@ mod tests {
112112 }
113113
114114 #[ test]
115+ #[ ignore] // FIXME: Fixtures cant test proc-macros/derives yet as we cant specify them in fixtures
115116 fn derive_with_input ( ) {
116117 check (
117118 r#"#[derive(serde::Serialize, PartialEq, $0)] struct Test;"# ,
@@ -129,6 +130,7 @@ mod tests {
129130 }
130131
131132 #[ test]
133+ #[ ignore] // FIXME: Fixtures cant test proc-macros/derives yet as we cant specify them in fixtures
132134 fn derive_with_input2 ( ) {
133135 check (
134136 r#"#[derive($0 serde::Serialize, PartialEq)] struct Test;"# ,
0 commit comments