aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_ssr/src/search.rs
diff options
context:
space:
mode:
authorDavid Lattimore <[email protected]>2020-07-24 11:53:48 +0100
committerDavid Lattimore <[email protected]>2020-07-24 12:34:00 +0100
commit3dac31fe80b9d7279e87b94615b0d55805e83412 (patch)
treed172c092d9ca93c182b2d88c30c3086a9ea797b0 /crates/ra_ssr/src/search.rs
parent8d09ab86edfc01405fd0045bef82e0642efd5f01 (diff)
SSR: Allow function calls to match method calls
This differs from how this used to work before I removed it in that: a) It's only one direction. Function calls in the pattern can match method calls in the code, but not the other way around. b) We now check that the function call in the pattern resolves to the same function as the method call in the code. The lack of (b) was the reason I felt the need to remove the feature before.
Diffstat (limited to 'crates/ra_ssr/src/search.rs')
-rw-r--r--crates/ra_ssr/src/search.rs65
1 files changed, 44 insertions, 21 deletions
diff --git a/crates/ra_ssr/src/search.rs b/crates/ra_ssr/src/search.rs
index 141e7d026..bcf0f0468 100644
--- a/crates/ra_ssr/src/search.rs
+++ b/crates/ra_ssr/src/search.rs
@@ -46,35 +46,58 @@ impl<'db> MatchFinder<'db> {
46 usage_cache: &mut UsageCache, 46 usage_cache: &mut UsageCache,
47 matches_out: &mut Vec<Match>, 47 matches_out: &mut Vec<Match>,
48 ) { 48 ) {
49 if let Some(first_path) = pick_path_for_usages(pattern) { 49 if let Some(resolved_path) = pick_path_for_usages(pattern) {
50 let definition: Definition = first_path.resolution.clone().into(); 50 let definition: Definition = resolved_path.resolution.clone().into();
51 for reference in self.find_usages(usage_cache, definition) { 51 for reference in self.find_usages(usage_cache, definition) {
52 let file = self.sema.parse(reference.file_range.file_id); 52 if let Some(node_to_match) = self.find_node_to_match(resolved_path, reference) {
53 if let Some(path) = self.sema.find_node_at_offset_with_descend::<ast::Path>( 53 if !is_search_permitted_ancestors(&node_to_match) {
54 file.syntax(), 54 mark::hit!(use_declaration_with_braces);
55 reference.file_range.range.start(), 55 continue;
56 ) { 56 }
57 if let Some(node_to_match) = self 57 if let Ok(m) =
58 .sema 58 matching::get_match(false, rule, &node_to_match, &None, &self.sema)
59 .ancestors_with_macros(path.syntax().clone())
60 .skip(first_path.depth as usize)
61 .next()
62 { 59 {
63 if !is_search_permitted_ancestors(&node_to_match) { 60 matches_out.push(m);
64 mark::hit!(use_declaration_with_braces);
65 continue;
66 }
67 if let Ok(m) =
68 matching::get_match(false, rule, &node_to_match, &None, &self.sema)
69 {
70 matches_out.push(m);
71 }
72 } 61 }
73 } 62 }
74 } 63 }
75 } 64 }
76 } 65 }
77 66
67 fn find_node_to_match(
68 &self,
69 resolved_path: &ResolvedPath,
70 reference: &Reference,
71 ) -> Option<SyntaxNode> {
72 let file = self.sema.parse(reference.file_range.file_id);
73 let depth = resolved_path.depth as usize;
74 let offset = reference.file_range.range.start();
75 if let Some(path) =
76 self.sema.find_node_at_offset_with_descend::<ast::Path>(file.syntax(), offset)
77 {
78 self.sema.ancestors_with_macros(path.syntax().clone()).skip(depth).next()
79 } else if let Some(path) =
80 self.sema.find_node_at_offset_with_descend::<ast::MethodCallExpr>(file.syntax(), offset)
81 {
82 // If the pattern contained a path and we found a reference to that path that wasn't
83 // itself a path, but was a method call, then we need to adjust how far up to try
84 // matching by how deep the path was within a CallExpr. The structure would have been
85 // CallExpr, PathExpr, Path - i.e. a depth offset of 2. We don't need to check if the
86 // path was part of a CallExpr because if it wasn't then all that will happen is we'll
87 // fail to match, which is the desired behavior.
88 const PATH_DEPTH_IN_CALL_EXPR: usize = 2;
89 if depth < PATH_DEPTH_IN_CALL_EXPR {
90 return None;
91 }
92 self.sema
93 .ancestors_with_macros(path.syntax().clone())
94 .skip(depth - PATH_DEPTH_IN_CALL_EXPR)
95 .next()
96 } else {
97 None
98 }
99 }
100
78 fn find_usages<'a>( 101 fn find_usages<'a>(
79 &self, 102 &self,
80 usage_cache: &'a mut UsageCache, 103 usage_cache: &'a mut UsageCache,