MCPcopy Create free account
hub / github.com/PHPantom-dev/phpantom_lsp / merge_union_completion_items

Function merge_union_completion_items

src/completion/builder.rs:736–811  ·  view source on GitHub ↗

Partition and sort completion items by union membership. When a variable has a union type (`num_candidates > 1`), members present on **all** candidate types (intersection members) are more likely to be type-safe. This function: 1. Partitions items into intersection and branch-only based on `occurrence_count` vs `num_candidates`. 2. Sorts each partition alphabetically by `filter_text` / `label`.

(
    items: Vec<CompletionItem>,
    occurrence_count: HashMap<String, usize>,
    num_candidates: usize,
)

Source from the content-addressed store, hash-verified

734/// When `num_candidates <= 1`, returns `items` unchanged (the items
735/// already have correct `sort_text` from [`build_completion_items`]).
736pub(crate) fn merge_union_completion_items(
737 items: Vec<CompletionItem>,
738 occurrence_count: HashMap<String, usize>,
739 num_candidates: usize,
740) -> Vec<CompletionItem> {
741 if num_candidates <= 1 {
742 return items;
743 }
744
745 let sort_key = |item: &CompletionItem| -> (u8, String) {
746 (
747 kind_sort_tier(item.kind),
748 item.filter_text
749 .as_deref()
750 .unwrap_or(&item.label)
751 .to_lowercase(),
752 )
753 };
754
755 let mut intersection: Vec<CompletionItem> = Vec::new();
756 let mut branch_only: Vec<CompletionItem> = Vec::new();
757
758 for item in items {
759 let count = occurrence_count.get(&item.label).copied().unwrap_or(1);
760 if count >= num_candidates {
761 intersection.push(item);
762 } else {
763 branch_only.push(item);
764 }
765 }
766
767 intersection.sort_by_key(|item| sort_key(item));
768 branch_only.sort_by_key(|item| sort_key(item));
769
770 // Assign sort_text: "0_NNNNN" for intersection, "1_NNNNN" for
771 // branch-only.
772 let mut result = Vec::with_capacity(intersection.len() + branch_only.len());
773
774 for (i, mut item) in intersection.into_iter().enumerate() {
775 item.sort_text = Some(format!("0_{:05}", i));
776 // Update description to show all contributing class names
777 // (the initial description only has the first candidate).
778 if let Some(class_names) = class_names_from_data(&item) {
779 if let Some(ref mut ld) = item.label_details {
780 ld.description = Some(class_names);
781 } else {
782 item.label_details = Some(CompletionItemLabelDetails {
783 detail: None,
784 description: Some(class_names),
785 });
786 }
787 }
788 result.push(item);
789 }
790
791 for (i, mut item) in branch_only.into_iter().enumerate() {
792 item.sort_text = Some(format!("1_{:05}", i));
793 // Add label_details showing the originating class(es) so the

Calls 5

kind_sort_tierFunction · 0.85
class_names_from_dataFunction · 0.85
pushMethod · 0.80
into_iterMethod · 0.80
getMethod · 0.45