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

Function build_union_completion_items

src/completion/builder.rs:607–680  ·  view source on GitHub ↗

Build completion items from multiple candidate classes (union types), resolving each through full inheritance and deduplicating across them. This is the high-level entry point that combines per-candidate item building with union-aware merging. For each candidate: 1. Resolves the class fully (own + traits + parents + virtual members). 2. Determines whether the cursor is inside the target class or

(
    candidates: &[Arc<ClassInfo>],
    effective_access: AccessKind,
    current_class: Option<&ClassInfo>,
    class_loader: &dyn Fn(&str) -> Option<Arc<ClassInfo>>,
    cache: &crate::virtual_memb

Source from the content-addressed store, hash-verified

605/// The collected items are then passed to [`merge_union_completion_items`]
606/// for deduplication and sort-tier assignment.
607pub(crate) fn build_union_completion_items(
608 candidates: &[Arc<ClassInfo>],
609 effective_access: AccessKind,
610 current_class: Option<&ClassInfo>,
611 class_loader: &dyn Fn(&str) -> Option<Arc<ClassInfo>>,
612 cache: &crate::virtual_members::ResolvedClassCache,
613 uri: &str,
614) -> Vec<CompletionItem> {
615 let current_class_name = current_class.map(|cc| cc.name.as_str());
616 let num_candidates = candidates.len();
617
618 // Track how many candidate classes contributed each label so we can
619 // distinguish intersection vs branch-only members.
620 let mut all_items: Vec<CompletionItem> = Vec::new();
621 let mut occurrence_count: HashMap<String, usize> = HashMap::new();
622
623 for target_class in candidates {
624 let resolved =
625 crate::virtual_members::resolve_class_fully_cached(target_class, class_loader, cache);
626
627 // Scope methods (and @method virtual methods from the model) are
628 // injected onto the candidate ClassInfo by `resolve_named_type`
629 // after generic substitution. `resolve_class_fully_cached` uses
630 // a cache key without generic args, so a prior cache entry for
631 // the same class without generics will lack those injected
632 // methods. Merge back any instance methods from the candidate
633 // that are missing from the resolved result so that scopes
634 // survive the re-resolution.
635 let merged = if target_class.methods.len() > resolved.methods.len() {
636 let mut patched = (*resolved).clone();
637 for method in target_class.methods.iter() {
638 if !patched
639 .methods
640 .iter()
641 .any(|m| m.name == method.name && m.is_static == method.is_static)
642 {
643 patched.methods.push(method.clone());
644 }
645 }
646 std::sync::Arc::new(patched)
647 } else {
648 resolved
649 };
650
651 let self_or_ancestor = is_ancestor_of(current_class, target_class, class_loader);
652
653 let items = build_completion_items(
654 &merged,
655 effective_access,
656 current_class_name,
657 self_or_ancestor,
658 uri,
659 );
660
661 for item in items {
662 if let Some(existing) = all_items
663 .iter_mut()
664 .find(|existing| existing.label == item.label)

Callers 1

Calls 12

is_ancestor_ofFunction · 0.85
build_completion_itemsFunction · 0.85
merge_data_class_namesFunction · 0.85
as_strMethod · 0.80
cloneMethod · 0.80
iterMethod · 0.80
pushMethod · 0.80
mapMethod · 0.45
findMethod · 0.45
insertMethod · 0.45

Tested by

no test coverage detected