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

Method find_class_references

src/references/mod.rs:608–744  ·  view source on GitHub ↗

Find all references to a class/interface/trait/enum across all files. Matches `ClassReference` spans whose resolved FQN equals `target_fqn`, and optionally `ClassDeclaration` spans at the declaration site.

(&self, target_fqn: &str, include_declaration: bool)

Source from the content-addressed store, hash-verified

606 /// Matches `ClassReference` spans whose resolved FQN equals `target_fqn`,
607 /// and optionally `ClassDeclaration` spans at the declaration site.
608 fn find_class_references(&self, target_fqn: &str, include_declaration: bool) -> Vec<Location> {
609 let mut locations = Vec::new();
610
611 // Normalise: strip leading backslash if present.
612 let target = strip_fqn_prefix(target_fqn);
613 let target_short = crate::util::short_name(target);
614
615 // Snapshot user-file symbol maps (excludes vendor and stubs).
616 let snapshot = self.user_file_symbol_maps();
617
618 for (file_uri, symbol_map) in &snapshot {
619 // Prefer mago-names resolved_names for FQN resolution (byte-offset
620 // based, applies PHP's full name resolution rules). Falls back to
621 // the legacy use_map lazily for identifiers not tracked by
622 // mago-names (e.g. docblock-sourced references).
623 let resolved_names = self.resolved_names.read().get(file_uri).cloned();
624 let file_namespace = self.first_file_namespace(file_uri);
625 let file_use_map = std::cell::OnceCell::new();
626
627 // First pass: resolved-name check to avoid unnecessary content work.
628 // Aliased imports (`use Foo as Bar; new Bar`) must still reach the
629 // full matching loop, because the textual span name is the alias.
630 let has_potential_match = symbol_map.spans.iter().any(|span| match &span.kind {
631 SymbolKind::ClassReference { name, .. } => {
632 if crate::util::short_name(name) == target_short {
633 true
634 } else {
635 let resolved = if let Some(fqn) =
636 resolved_names.as_ref().and_then(|rn| rn.get(span.start))
637 {
638 fqn.to_string()
639 } else {
640 let use_map = file_use_map.get_or_init(|| {
641 self.file_imports
642 .read()
643 .get(file_uri)
644 .cloned()
645 .unwrap_or_default()
646 });
647 Self::resolve_to_fqn(name, use_map, &file_namespace)
648 };
649 class_names_match(strip_fqn_prefix(&resolved), target, target_short)
650 }
651 }
652 SymbolKind::ClassDeclaration { name } => {
653 include_declaration && name == target_short
654 }
655 SymbolKind::SelfStaticParent(ssp_kind) => *ssp_kind != SelfStaticParentKind::This,
656 _ => false,
657 });
658
659 if !has_potential_match {
660 continue;
661 }
662
663 let parsed_uri = match Url::parse(file_uri) {
664 Ok(u) => u,
665 Err(_) => continue,

Callers 1

Calls 15

strip_fqn_prefixFunction · 0.85
class_names_matchFunction · 0.85
build_fqnFunction · 0.85
offset_to_positionFunction · 0.85
user_file_symbol_mapsMethod · 0.80
first_file_namespaceMethod · 0.80
iterMethod · 0.80
cloneMethod · 0.80
get_file_content_arcMethod · 0.80
pushMethod · 0.80
as_strMethod · 0.80

Tested by

no test coverage detected