From 69e666fdbaaec1a4e9b9b0e9643a8dbfbb51cb89 Mon Sep 17 00:00:00 2001 From: Anatol Ulrich Date: Thu, 4 Nov 2021 22:01:59 +0100 Subject: [PATCH] maybe? --- crates/ide_ssr/src/search.rs | 57 +++++++++++++++++++++--------------- 1 file changed, 33 insertions(+), 24 deletions(-) diff --git a/crates/ide_ssr/src/search.rs b/crates/ide_ssr/src/search.rs index 42ce85eebe..ffecffc46d 100644 --- a/crates/ide_ssr/src/search.rs +++ b/crates/ide_ssr/src/search.rs @@ -58,7 +58,7 @@ impl<'db> MatchFinder<'db> { if let Some(resolved_path) = pick_path_for_usages(pattern) { let definition: Definition = resolved_path.resolution.clone().into(); for file_range in self.find_usages(usage_cache, definition).file_ranges() { - if let Some(node_to_match) = self.find_node_to_match(resolved_path, file_range) { + for node_to_match in self.find_nodes_to_match(resolved_path, file_range) { if !is_search_permitted_ancestors(&node_to_match) { cov_mark::hit!(use_declaration_with_braces); continue; @@ -69,36 +69,45 @@ impl<'db> MatchFinder<'db> { } } - fn find_node_to_match( + fn find_nodes_to_match( &self, resolved_path: &ResolvedPath, file_range: FileRange, - ) -> Option { + ) -> Vec { let file = self.sema.parse(file_range.file_id); let depth = resolved_path.depth as usize; let offset = file_range.range.start(); - if let Some(path) = - self.sema.find_node_at_offset_with_descend::(file.syntax(), offset) - { - self.sema.ancestors_with_macros(path.syntax().clone()).nth(depth) - } else if let Some(path) = - self.sema.find_node_at_offset_with_descend::(file.syntax(), offset) - { - // If the pattern contained a path and we found a reference to that path that wasn't - // itself a path, but was a method call, then we need to adjust how far up to try - // matching by how deep the path was within a CallExpr. The structure would have been - // CallExpr, PathExpr, Path - i.e. a depth offset of 2. We don't need to check if the - // path was part of a CallExpr because if it wasn't then all that will happen is we'll - // fail to match, which is the desired behavior. - const PATH_DEPTH_IN_CALL_EXPR: usize = 2; - if depth < PATH_DEPTH_IN_CALL_EXPR { - return None; - } - self.sema - .ancestors_with_macros(path.syntax().clone()) - .nth(depth - PATH_DEPTH_IN_CALL_EXPR) + + let mut paths = self + .sema + .find_nodes_at_offset_with_descend::(file.syntax(), offset) + .peekable(); + + if paths.peek().is_some() { + paths + .filter_map(|path| { + self.sema.ancestors_with_macros(path.syntax().clone()).nth(depth) + }) + .collect::>() } else { - None + self.sema + .find_nodes_at_offset_with_descend::(file.syntax(), offset) + .filter_map(|path| { + // If the pattern contained a path and we found a reference to that path that wasn't + // itself a path, but was a method call, then we need to adjust how far up to try + // matching by how deep the path was within a CallExpr. The structure would have been + // CallExpr, PathExpr, Path - i.e. a depth offset of 2. We don't need to check if the + // path was part of a CallExpr because if it wasn't then all that will happen is we'll + // fail to match, which is the desired behavior. + const PATH_DEPTH_IN_CALL_EXPR: usize = 2; + if depth < PATH_DEPTH_IN_CALL_EXPR { + return None; + } + self.sema + .ancestors_with_macros(path.syntax().clone()) + .nth(depth - PATH_DEPTH_IN_CALL_EXPR) + }) + .collect::>() } }