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

Method resolve_class_name

src/resolution.rs:699–775  ·  view source on GitHub ↗

Resolve a class name using use-map, namespace, local classes, and cross-file / PSR-4 / stubs. This is the single canonical implementation of the "class_loader" logic used by the completion handler, definition resolver, and named-argument resolution. It handles: - Fully-qualified names (`\PDO`, `\Couchbase\Cluster`) - Unqualified names resolved via the import table (`use` statements), local clas

(
        &self,
        name: &str,
        local_classes: &[Arc<ClassInfo>],
        file_use_map: &HashMap<String, String>,
        file_namespace: &Option<String>,
    )

Source from the content-addressed store, hash-verified

697 /// local class list, current namespace, or global scope
698 /// - Qualified names with alias expansion and namespace prefixing
699 pub(crate) fn resolve_class_name(
700 &self,
701 name: &str,
702 local_classes: &[Arc<ClassInfo>],
703 file_use_map: &HashMap<String, String>,
704 file_namespace: &Option<String>,
705 ) -> Option<Arc<ClassInfo>> {
706 // ── Fully qualified name (leading `\`) ──────────────
707 if let Some(stripped) = name.strip_prefix('\\') {
708 return self.find_or_load_class(stripped);
709 }
710
711 // ── Unqualified name (no `\` at all) ────────────────
712 if !name.contains('\\') {
713 // Check the import table first (`use` statements).
714 if let Some(fqn) = file_use_map.get(name) {
715 return self.find_or_load_class(fqn);
716 }
717 // Check local classes (same-file shortcut).
718 // In multi-namespace files, prefer the class whose
719 // file_namespace matches the current namespace context.
720 let lookup = short_name(name);
721 let ns_atom = file_namespace.as_ref().map(|ns| crate::atom::atom(ns));
722 let local_match = local_classes
723 .iter()
724 .find(|c| c.name == lookup && c.file_namespace == ns_atom)
725 .or_else(|| local_classes.iter().find(|c| c.name == lookup));
726 if let Some(cls) = local_match {
727 return Some(Arc::clone(cls));
728 }
729 // In a namespace, try the namespace-qualified form first.
730 // Per PHP semantics, class names do NOT fall back to global
731 // scope (unlike functions/constants). However, names that
732 // arrive here may be already-resolved FQNs from ClassInfo
733 // fields (e.g. `parent_class = "Exception"`) that happen to
734 // be single-segment global names. For those, the namespace-
735 // qualified attempt will fail, so we fall back to a direct
736 // lookup. To preserve PHP semantics for user-typed code,
737 // the namespace-qualified form is tried first and wins when
738 // a same-named class exists in the current namespace.
739 if let Some(ns) = file_namespace {
740 let ns_qualified = format!("{}\\{}", ns, name);
741 if let Some(cls) = self.find_or_load_class(&ns_qualified) {
742 return Some(cls);
743 }
744 }
745 // Global scope: either no namespace context, or the
746 // namespace-qualified lookup above did not find a match.
747 return self.find_or_load_class(name);
748 }
749
750 // ── Qualified name (contains `\`, no leading `\`) ───
751 // Check if the first segment is a use-map alias
752 // (e.g. `OA\Endpoint` where `use Swagger\OpenAPI as OA;`
753 // maps `OA` → `Swagger\OpenAPI`). Expand to FQN.
754 let first_segment = name.split('\\').next().unwrap_or(name);
755 if let Some(fqn_prefix) = file_use_map.get(first_segment) {
756 let rest = &name[first_segment.len()..];

Callers 1

class_loader_withMethod · 0.80

Calls 9

atomFunction · 0.85
find_or_load_classMethod · 0.80
containsMethod · 0.80
iterMethod · 0.80
nextMethod · 0.80
short_nameFunction · 0.70
getMethod · 0.45
mapMethod · 0.45
findMethod · 0.45

Tested by

no test coverage detected