@@ -47,7 +47,9 @@ use self::lsp::ext as lsp_ext;
47
47
#[ cfg( test) ]
48
48
mod integrated_benchmarks;
49
49
50
+ use ide:: { CompletionItem , CompletionRelevance , TextEdit , TextRange } ;
50
51
use serde:: de:: DeserializeOwned ;
52
+ use tenthash:: TentHasher ;
51
53
52
54
pub use crate :: {
53
55
lsp:: capabilities:: server_capabilities, main_loop:: main_loop, reload:: ws_to_crate_graph,
@@ -61,3 +63,90 @@ pub fn from_json<T: DeserializeOwned>(
61
63
serde_json:: from_value ( json. clone ( ) )
62
64
. map_err ( |e| anyhow:: format_err!( "Failed to deserialize {what}: {e}; {json}" ) )
63
65
}
66
+
67
+ fn completion_item_hash ( item : & CompletionItem , is_ref_completion : bool ) -> [ u8 ; 20 ] {
68
+ fn hash_text_range ( hasher : & mut TentHasher , text_range : & TextRange ) {
69
+ hasher. update ( u32:: from ( text_range. start ( ) ) . to_le_bytes ( ) ) ;
70
+ hasher. update ( u32:: from ( text_range. end ( ) ) . to_le_bytes ( ) ) ;
71
+ }
72
+
73
+ fn hash_text_edit ( hasher : & mut TentHasher , edit : & TextEdit ) {
74
+ for indel in edit. iter ( ) {
75
+ hasher. update ( & indel. insert ) ;
76
+ hash_text_range ( hasher, & indel. delete ) ;
77
+ }
78
+ }
79
+
80
+ fn has_completion_relevance ( hasher : & mut TentHasher , relevance : & CompletionRelevance ) {
81
+ use ide_completion:: {
82
+ CompletionRelevancePostfixMatch , CompletionRelevanceReturnType ,
83
+ CompletionRelevanceTypeMatch ,
84
+ } ;
85
+
86
+ if let Some ( type_match) = & relevance. type_match {
87
+ let label = match type_match {
88
+ CompletionRelevanceTypeMatch :: CouldUnify => "could_unify" ,
89
+ CompletionRelevanceTypeMatch :: Exact => "exact" ,
90
+ } ;
91
+ hasher. update ( label) ;
92
+ }
93
+ hasher. update ( & [ u8:: from ( relevance. exact_name_match ) , u8:: from ( relevance. is_local ) ] ) ;
94
+ if let Some ( trait_) = & relevance. trait_ {
95
+ hasher. update ( & [ u8:: from ( trait_. is_op_method ) , u8:: from ( trait_. notable_trait ) ] ) ;
96
+ }
97
+ hasher. update ( & [
98
+ u8:: from ( relevance. is_name_already_imported ) ,
99
+ u8:: from ( relevance. requires_import ) ,
100
+ u8:: from ( relevance. is_private_editable ) ,
101
+ ] ) ;
102
+ if let Some ( postfix_match) = & relevance. postfix_match {
103
+ let label = match postfix_match {
104
+ CompletionRelevancePostfixMatch :: NonExact => "non_exact" ,
105
+ CompletionRelevancePostfixMatch :: Exact => "exact" ,
106
+ } ;
107
+ hasher. update ( label) ;
108
+ }
109
+ if let Some ( function) = & relevance. function {
110
+ hasher. update ( & [ u8:: from ( function. has_params ) , u8:: from ( function. has_self_param ) ] ) ;
111
+ let label = match function. return_type {
112
+ CompletionRelevanceReturnType :: Other => "other" ,
113
+ CompletionRelevanceReturnType :: DirectConstructor => "direct_constructor" ,
114
+ CompletionRelevanceReturnType :: Constructor => "constructor" ,
115
+ CompletionRelevanceReturnType :: Builder => "builder" ,
116
+ } ;
117
+ hasher. update ( label) ;
118
+ }
119
+ }
120
+
121
+ let mut hasher = TentHasher :: new ( ) ;
122
+ hasher. update ( & [
123
+ u8:: from ( is_ref_completion) ,
124
+ u8:: from ( item. is_snippet ) ,
125
+ u8:: from ( item. deprecated ) ,
126
+ u8:: from ( item. trigger_call_info ) ,
127
+ ] ) ;
128
+ hasher. update ( & item. label ) ;
129
+ if let Some ( label_detail) = & item. label_detail {
130
+ hasher. update ( label_detail) ;
131
+ }
132
+ hash_text_range ( & mut hasher, & item. source_range ) ;
133
+ hash_text_edit ( & mut hasher, & item. text_edit ) ;
134
+ hasher. update ( item. kind . tag ( ) ) ;
135
+ hasher. update ( & item. lookup ) ;
136
+ if let Some ( detail) = & item. detail {
137
+ hasher. update ( detail) ;
138
+ }
139
+ if let Some ( documentation) = & item. documentation {
140
+ hasher. update ( documentation. as_str ( ) ) ;
141
+ }
142
+ has_completion_relevance ( & mut hasher, & item. relevance ) ;
143
+ if let Some ( ( mutability, text_size) ) = & item. ref_match {
144
+ hasher. update ( mutability. as_keyword_for_ref ( ) ) ;
145
+ hasher. update ( u32:: from ( * text_size) . to_le_bytes ( ) ) ;
146
+ }
147
+ for ( import_path, import_name) in & item. import_to_add {
148
+ hasher. update ( import_path) ;
149
+ hasher. update ( import_name) ;
150
+ }
151
+ hasher. finalize ( )
152
+ }
0 commit comments