Reverse jump: from a method definition in a concrete class to the interface or abstract class that declares the prototype. When the cursor is on a method name at its definition site (e.g. `public function handle()` in a class that implements `Handler`), this finds the interface/abstract method declaration and returns its location.
(
&self,
uri: &str,
content: &str,
current_class: &ClassInfo,
member_name: &str,
class_loader: &dyn Fn(&str) -> Option<Arc<ClassInfo>>,
)
| 207 | /// this finds the interface/abstract method declaration and returns |
| 208 | /// its location. |
| 209 | fn resolve_reverse_implementation( |
| 210 | &self, |
| 211 | uri: &str, |
| 212 | content: &str, |
| 213 | current_class: &ClassInfo, |
| 214 | member_name: &str, |
| 215 | class_loader: &dyn Fn(&str) -> Option<Arc<ClassInfo>>, |
| 216 | ) -> Option<Vec<Location>> { |
| 217 | // For interfaces and abstract classes, the forward direction |
| 218 | // applies: find concrete implementors that define the method. |
| 219 | if current_class.kind == ClassLikeKind::Interface || current_class.is_abstract { |
| 220 | return self.resolve_interface_member_implementations( |
| 221 | uri, |
| 222 | content, |
| 223 | current_class, |
| 224 | member_name, |
| 225 | class_loader, |
| 226 | ); |
| 227 | } |
| 228 | |
| 229 | let mut locations = Vec::new(); |
| 230 | |
| 231 | // Check implemented interfaces for a method with the same name. |
| 232 | let all_ifaces = self.collect_all_interfaces(current_class, class_loader); |
| 233 | for iface_name in &all_ifaces { |
| 234 | if let Some(iface) = class_loader(iface_name) { |
| 235 | let has_member = iface.has_method(member_name) |
| 236 | || iface.properties.iter().any(|p| p.name == member_name); |
| 237 | if has_member { |
| 238 | let member_kind = if iface.has_method(member_name) { |
| 239 | MemberKind::Method |
| 240 | } else { |
| 241 | MemberKind::Property |
| 242 | }; |
| 243 | if let Some((class_uri, class_content)) = |
| 244 | self.find_class_file_content(iface_name, uri, content) |
| 245 | && let Some(member_pos) = Self::find_member_position_in_class( |
| 246 | &class_content, |
| 247 | member_name, |
| 248 | member_kind, |
| 249 | &iface, |
| 250 | ) |
| 251 | && let Ok(parsed_uri) = Url::parse(&class_uri) |
| 252 | { |
| 253 | let loc = point_location(parsed_uri, member_pos); |
| 254 | if !locations.contains(&loc) { |
| 255 | locations.push(loc); |
| 256 | } |
| 257 | } |
| 258 | } |
| 259 | } |
| 260 | } |
| 261 | |
| 262 | // Check parent abstract classes for an abstract method with the |
| 263 | // same name. |
| 264 | let mut current = current_class.parent_class; |
| 265 | let mut depth = 0u32; |
| 266 | while let Some(parent_name) = current { |
no test coverage detected