mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-10-29 02:52:11 +00:00
Merge pull request #19072 from cessen/concat_uniquely
Fix #19071: ensure `completion_item_hash` serializes items uniquely
This commit is contained in:
commit
3c2aca1e5e
1 changed files with 51 additions and 25 deletions
|
|
@ -79,32 +79,34 @@ fn completion_item_hash(item: &CompletionItem, is_ref_completion: bool) -> [u8;
|
|||
u8::from(relevance.requires_import),
|
||||
u8::from(relevance.is_private_editable),
|
||||
]);
|
||||
if let Some(type_match) = &relevance.type_match {
|
||||
let label = match type_match {
|
||||
CompletionRelevanceTypeMatch::CouldUnify => "could_unify",
|
||||
CompletionRelevanceTypeMatch::Exact => "exact",
|
||||
};
|
||||
hasher.update(label);
|
||||
|
||||
match relevance.type_match {
|
||||
None => hasher.update([0u8]),
|
||||
Some(CompletionRelevanceTypeMatch::CouldUnify) => hasher.update([1u8]),
|
||||
Some(CompletionRelevanceTypeMatch::Exact) => hasher.update([2u8]),
|
||||
}
|
||||
|
||||
hasher.update([u8::from(relevance.trait_.is_some())]);
|
||||
if let Some(trait_) = &relevance.trait_ {
|
||||
hasher.update([u8::from(trait_.is_op_method), u8::from(trait_.notable_trait)]);
|
||||
}
|
||||
if let Some(postfix_match) = &relevance.postfix_match {
|
||||
let label = match postfix_match {
|
||||
CompletionRelevancePostfixMatch::NonExact => "non_exact",
|
||||
CompletionRelevancePostfixMatch::Exact => "exact",
|
||||
};
|
||||
hasher.update(label);
|
||||
|
||||
match relevance.postfix_match {
|
||||
None => hasher.update([0u8]),
|
||||
Some(CompletionRelevancePostfixMatch::NonExact) => hasher.update([1u8]),
|
||||
Some(CompletionRelevancePostfixMatch::Exact) => hasher.update([2u8]),
|
||||
}
|
||||
|
||||
hasher.update([u8::from(relevance.function.is_some())]);
|
||||
if let Some(function) = &relevance.function {
|
||||
hasher.update([u8::from(function.has_params), u8::from(function.has_self_param)]);
|
||||
let label = match function.return_type {
|
||||
CompletionRelevanceReturnType::Other => "other",
|
||||
CompletionRelevanceReturnType::DirectConstructor => "direct_constructor",
|
||||
CompletionRelevanceReturnType::Constructor => "constructor",
|
||||
CompletionRelevanceReturnType::Builder => "builder",
|
||||
let discriminant: u8 = match function.return_type {
|
||||
CompletionRelevanceReturnType::Other => 0,
|
||||
CompletionRelevanceReturnType::DirectConstructor => 1,
|
||||
CompletionRelevanceReturnType::Constructor => 2,
|
||||
CompletionRelevanceReturnType::Builder => 3,
|
||||
};
|
||||
hasher.update(label);
|
||||
hasher.update([discriminant]);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -115,35 +117,59 @@ fn completion_item_hash(item: &CompletionItem, is_ref_completion: bool) -> [u8;
|
|||
u8::from(item.deprecated),
|
||||
u8::from(item.trigger_call_info),
|
||||
]);
|
||||
|
||||
hasher.update(item.label.primary.len().to_ne_bytes());
|
||||
hasher.update(&item.label.primary);
|
||||
|
||||
hasher.update([u8::from(item.label.detail_left.is_some())]);
|
||||
if let Some(label_detail) = &item.label.detail_left {
|
||||
hasher.update(label_detail.len().to_ne_bytes());
|
||||
hasher.update(label_detail);
|
||||
}
|
||||
|
||||
hasher.update([u8::from(item.label.detail_right.is_some())]);
|
||||
if let Some(label_detail) = &item.label.detail_right {
|
||||
hasher.update(label_detail.len().to_ne_bytes());
|
||||
hasher.update(label_detail);
|
||||
}
|
||||
|
||||
// NB: do not hash edits or source range, as those may change between the time the client sends the resolve request
|
||||
// and the time it receives it: some editors do allow changing the buffer between that, leading to ranges being different.
|
||||
//
|
||||
// Documentation hashing is skipped too, as it's a large blob to process,
|
||||
// while not really making completion properties more unique as they are already.
|
||||
hasher.update(item.kind.tag());
|
||||
|
||||
let kind_tag = item.kind.tag();
|
||||
hasher.update(kind_tag.len().to_ne_bytes());
|
||||
hasher.update(kind_tag);
|
||||
|
||||
hasher.update(item.lookup.len().to_ne_bytes());
|
||||
hasher.update(&item.lookup);
|
||||
|
||||
hasher.update([u8::from(item.detail.is_some())]);
|
||||
if let Some(detail) = &item.detail {
|
||||
hasher.update(detail.len().to_ne_bytes());
|
||||
hasher.update(detail);
|
||||
}
|
||||
|
||||
hash_completion_relevance(&mut hasher, &item.relevance);
|
||||
|
||||
hasher.update([u8::from(item.ref_match.is_some())]);
|
||||
if let Some((ref_mode, text_size)) = &item.ref_match {
|
||||
let prefix = match ref_mode {
|
||||
CompletionItemRefMode::Reference(Mutability::Shared) => "&",
|
||||
CompletionItemRefMode::Reference(Mutability::Mut) => "&mut ",
|
||||
CompletionItemRefMode::Dereference => "*",
|
||||
let discriminant = match ref_mode {
|
||||
CompletionItemRefMode::Reference(Mutability::Shared) => 0u8,
|
||||
CompletionItemRefMode::Reference(Mutability::Mut) => 1u8,
|
||||
CompletionItemRefMode::Dereference => 2u8,
|
||||
};
|
||||
hasher.update(prefix);
|
||||
hasher.update(u32::from(*text_size).to_le_bytes());
|
||||
hasher.update([discriminant]);
|
||||
hasher.update(u32::from(*text_size).to_ne_bytes());
|
||||
}
|
||||
|
||||
hasher.update(item.import_to_add.len().to_ne_bytes());
|
||||
for import_path in &item.import_to_add {
|
||||
hasher.update(import_path.len().to_ne_bytes());
|
||||
hasher.update(import_path);
|
||||
}
|
||||
|
||||
hasher.finalize()
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue