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

Method find_implementors

src/definition/implementation.rs:618–859  ·  view source on GitHub ↗

Find all classes that implement or extend the target. Scans: 1. All classes already in `uri_classes_index` (open files + autoload-discovered) 2. All classes loadable via `fqn_uri_index` 3. Class index files not yet loaded — string pre-filter then parse 4. Embedded PHP stubs — string pre-filter then lazy parse 5. User PSR-4 directories — walk for `.php` files not covered by the class index, string

(
        &self,
        target_short: &str,
        target_fqn: &str,
        class_loader: &dyn Fn(&str) -> Option<Arc<ClassInfo>>,
        include_abstract: bool,
        direct_only: bool,
    )

Source from the content-addressed store, hash-verified

616 /// excluded. This mode is used by the type hierarchy protocol where
617 /// the client walks the tree one level at a time.
618 pub(crate) fn find_implementors(
619 &self,
620 target_short: &str,
621 target_fqn: &str,
622 class_loader: &dyn Fn(&str) -> Option<Arc<ClassInfo>>,
623 include_abstract: bool,
624 direct_only: bool,
625 ) -> Vec<ClassInfo> {
626 let mut result: Vec<ClassInfo> = Vec::new();
627 // Track by FQN to avoid short-name collisions across namespaces.
628 let mut seen_fqns: HashSet<String> = HashSet::new();
629
630 // ── Phase 1: GTI index lookup ───────────────────────────────────
631 // Use the reverse inheritance index for O(1) lookup of classes
632 // that directly extend/implement/use the target. Then
633 // recursively collect transitive children.
634 let gti_candidates: Vec<String> = {
635 let gti = self.gti_index.read();
636 if direct_only {
637 gti.get(target_fqn).cloned().unwrap_or_default()
638 } else {
639 // Transitive: BFS collecting all descendants.
640 let mut all_children: Vec<String> = Vec::new();
641 let mut queue: Vec<String> = vec![target_fqn.to_string()];
642 let mut visited: HashSet<String> = HashSet::new();
643 visited.insert(target_fqn.to_string());
644 while let Some(parent) = queue.pop() {
645 if let Some(children) = gti.get(&parent) {
646 for child in children {
647 if visited.insert(child.clone()) {
648 all_children.push(child.clone());
649 queue.push(child.clone());
650 }
651 }
652 }
653 }
654 all_children
655 }
656 };
657
658 for child_fqn in &gti_candidates {
659 if seen_fqns.contains(child_fqn) {
660 continue;
661 }
662 if let Some(cls) = class_loader(child_fqn) {
663 if !direct_only {
664 if cls.kind == ClassLikeKind::Interface {
665 continue;
666 }
667 if cls.is_abstract && !include_abstract {
668 continue;
669 }
670 }
671 seen_fqns.insert(child_fqn.clone());
672 result.push(Arc::unwrap_or_clone(cls));
673 }
674 }
675

Calls 14

build_fqnFunction · 0.85
path_to_uriFunction · 0.85
cloneMethod · 0.80
pushMethod · 0.80
containsMethod · 0.80
iterMethod · 0.80
valuesMethod · 0.80
parse_and_cache_fileMethod · 0.80
filterMethod · 0.80
collect_php_filesFunction · 0.50
getMethod · 0.45

Tested by

no test coverage detected