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

Function build_origin_lines

src/hover/mod.rs:88–166  ·  view source on GitHub ↗

Build the origin indicator lines for a member. Checks whether the member is actually declared on the owner class (not just inherited), then inspects the parent class and implemented interfaces (via `class_loader`) to determine whether the member overrides a parent or implements an interface contract. Also checks `is_virtual` for synthesized members. Returns a (possibly empty) string of Markdown

(
    member_name: &str,
    owner: &ClassInfo,
    is_virtual: bool,
    member_kind: MemberKindForOrigin,
    class_loader: &dyn Fn(&str) -> Option<Arc<ClassInfo>>,
)

Source from the content-addressed store, hash-verified

86/// Returns a (possibly empty) string of Markdown lines to prepend to the
87/// hover content.
88fn build_origin_lines(
89 member_name: &str,
90 owner: &ClassInfo,
91 is_virtual: bool,
92 member_kind: MemberKindForOrigin,
93 class_loader: &dyn Fn(&str) -> Option<Arc<ClassInfo>>,
94) -> String {
95 let mut origins: Vec<MemberOrigin> = Vec::new();
96
97 if is_virtual {
98 origins.push(MemberOrigin::Virtual);
99 }
100
101 // Only check for override / implements when the member is actually
102 // declared on the owner class itself (not merely inherited from a
103 // parent). Without this gate, an inherited method would incorrectly
104 // show "overrides ParentClass".
105 let declared_on_owner = raw_class_has_member(owner, member_name, &member_kind, class_loader);
106
107 if declared_on_owner {
108 // Check parent class for override.
109 if let Some(ref parent_name) = owner.parent_class
110 && let Some(parent) = class_loader(parent_name)
111 {
112 let has_member = match member_kind {
113 MemberKindForOrigin::Method => parent
114 .methods
115 .iter()
116 .any(|m| m.name.eq_ignore_ascii_case(member_name)),
117 MemberKindForOrigin::Property => {
118 parent.properties.iter().any(|p| p.name == member_name)
119 }
120 MemberKindForOrigin::Constant => {
121 parent.constants.iter().any(|c| c.name == member_name)
122 }
123 };
124 if has_member {
125 origins.push(MemberOrigin::Override(short_name(parent_name).to_string()));
126 }
127 }
128
129 // Check interfaces for implements.
130 for iface_name in &owner.interfaces {
131 if let Some(iface) = class_loader(iface_name) {
132 let has_member = match member_kind {
133 MemberKindForOrigin::Method => iface
134 .methods
135 .iter()
136 .any(|m| m.name.eq_ignore_ascii_case(member_name)),
137 MemberKindForOrigin::Property => {
138 iface.properties.iter().any(|p| p.name == member_name)
139 }
140 MemberKindForOrigin::Constant => {
141 iface.constants.iter().any(|c| c.name == member_name)
142 }
143 };
144 if has_member {
145 origins.push(MemberOrigin::Implements(short_name(iface_name).to_string()));

Callers 3

hover_for_methodMethod · 0.85
hover_for_propertyMethod · 0.85
hover_for_constantMethod · 0.85

Calls 6

raw_class_has_memberFunction · 0.85
pushMethod · 0.80
iterMethod · 0.80
short_nameFunction · 0.50
is_emptyMethod · 0.45
mapMethod · 0.45

Tested by

no test coverage detected