1
1
//! Completion for derives
2
+ use hir:: HasAttrs ;
2
3
use itertools:: Itertools ;
3
- use rustc_hash:: FxHashSet ;
4
+ use rustc_hash:: FxHashMap ;
4
5
use syntax:: ast;
5
6
6
7
use crate :: {
@@ -15,66 +16,64 @@ pub(super) fn complete_derive(
15
16
derive_input : ast:: TokenTree ,
16
17
) {
17
18
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
+ } ;
31
37
let mut item =
32
38
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
- ) ;
43
39
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
+ }
44
46
item. add_to ( acc) ;
45
47
}
46
48
}
47
49
}
48
50
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 ( ) ;
51
55
ctx. scope . process_all_names ( & mut |name, scope_def| {
52
56
if let hir:: ScopeDef :: MacroDef ( mac) = scope_def {
53
57
if mac. kind ( ) == hir:: MacroKind :: Derive {
54
- result. insert ( name. to_string ( ) ) ;
58
+ result. insert ( name. to_string ( ) , mac . docs ( ctx . db ) ) ;
55
59
}
56
60
}
57
61
} ) ;
58
62
result
59
63
}
60
64
61
- struct DeriveCompletion {
65
+ struct DeriveDependencies {
62
66
label : & ' static str ,
63
67
dependencies : & ' static [ & ' static str ] ,
64
68
}
65
69
66
- /// Standard Rust derives and the information about their dependencies
70
+ /// Standard Rust derives that have dependencies
67
71
/// (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" ] } ,
78
77
] ;
79
78
80
79
#[ cfg( test) ]
@@ -94,6 +93,7 @@ mod tests {
94
93
}
95
94
96
95
#[ test]
96
+ #[ ignore] // FIXME: Fixtures cant test proc-macros/derives yet as we cant specify them in fixtures
97
97
fn empty_derive ( ) {
98
98
check (
99
99
r#"#[derive($0)] struct Test;"# ,
@@ -112,6 +112,7 @@ mod tests {
112
112
}
113
113
114
114
#[ test]
115
+ #[ ignore] // FIXME: Fixtures cant test proc-macros/derives yet as we cant specify them in fixtures
115
116
fn derive_with_input ( ) {
116
117
check (
117
118
r#"#[derive(serde::Serialize, PartialEq, $0)] struct Test;"# ,
@@ -129,6 +130,7 @@ mod tests {
129
130
}
130
131
131
132
#[ test]
133
+ #[ ignore] // FIXME: Fixtures cant test proc-macros/derives yet as we cant specify them in fixtures
132
134
fn derive_with_input2 ( ) {
133
135
check (
134
136
r#"#[derive($0 serde::Serialize, PartialEq)] struct Test;"# ,
0 commit comments