diff options
Diffstat (limited to 'crates/ra_ssr/src/lib.rs')
-rw-r--r-- | crates/ra_ssr/src/lib.rs | 61 |
1 files changed, 44 insertions, 17 deletions
diff --git a/crates/ra_ssr/src/lib.rs b/crates/ra_ssr/src/lib.rs index a0a5c9762..286619f59 100644 --- a/crates/ra_ssr/src/lib.rs +++ b/crates/ra_ssr/src/lib.rs | |||
@@ -7,6 +7,7 @@ mod matching; | |||
7 | mod nester; | 7 | mod nester; |
8 | mod parsing; | 8 | mod parsing; |
9 | mod replacing; | 9 | mod replacing; |
10 | mod resolving; | ||
10 | mod search; | 11 | mod search; |
11 | #[macro_use] | 12 | #[macro_use] |
12 | mod errors; | 13 | mod errors; |
@@ -21,6 +22,7 @@ use hir::Semantics; | |||
21 | use ra_db::{FileId, FilePosition, FileRange}; | 22 | use ra_db::{FileId, FilePosition, FileRange}; |
22 | use ra_ide_db::source_change::SourceFileEdit; | 23 | use ra_ide_db::source_change::SourceFileEdit; |
23 | use ra_syntax::{ast, AstNode, SyntaxNode, TextRange}; | 24 | use ra_syntax::{ast, AstNode, SyntaxNode, TextRange}; |
25 | use resolving::ResolvedRule; | ||
24 | use rustc_hash::FxHashMap; | 26 | use rustc_hash::FxHashMap; |
25 | 27 | ||
26 | // A structured search replace rule. Create by calling `parse` on a str. | 28 | // A structured search replace rule. Create by calling `parse` on a str. |
@@ -48,7 +50,9 @@ pub struct SsrMatches { | |||
48 | pub struct MatchFinder<'db> { | 50 | pub struct MatchFinder<'db> { |
49 | /// Our source of information about the user's code. | 51 | /// Our source of information about the user's code. |
50 | sema: Semantics<'db, ra_ide_db::RootDatabase>, | 52 | sema: Semantics<'db, ra_ide_db::RootDatabase>, |
51 | rules: Vec<parsing::ParsedRule>, | 53 | rules: Vec<ResolvedRule>, |
54 | scope: hir::SemanticsScope<'db>, | ||
55 | hygiene: hir::Hygiene, | ||
52 | } | 56 | } |
53 | 57 | ||
54 | impl<'db> MatchFinder<'db> { | 58 | impl<'db> MatchFinder<'db> { |
@@ -56,10 +60,24 @@ impl<'db> MatchFinder<'db> { | |||
56 | /// `lookup_context`. | 60 | /// `lookup_context`. |
57 | pub fn in_context( | 61 | pub fn in_context( |
58 | db: &'db ra_ide_db::RootDatabase, | 62 | db: &'db ra_ide_db::RootDatabase, |
59 | _lookup_context: FilePosition, | 63 | lookup_context: FilePosition, |
60 | ) -> MatchFinder<'db> { | 64 | ) -> MatchFinder<'db> { |
61 | // FIXME: Use lookup_context | 65 | let sema = Semantics::new(db); |
62 | MatchFinder { sema: Semantics::new(db), rules: Vec::new() } | 66 | let file = sema.parse(lookup_context.file_id); |
67 | // Find a node at the requested position, falling back to the whole file. | ||
68 | let node = file | ||
69 | .syntax() | ||
70 | .token_at_offset(lookup_context.offset) | ||
71 | .left_biased() | ||
72 | .map(|token| token.parent()) | ||
73 | .unwrap_or_else(|| file.syntax().clone()); | ||
74 | let scope = sema.scope(&node); | ||
75 | MatchFinder { | ||
76 | sema: Semantics::new(db), | ||
77 | rules: Vec::new(), | ||
78 | scope, | ||
79 | hygiene: hir::Hygiene::new(db, lookup_context.file_id.into()), | ||
80 | } | ||
63 | } | 81 | } |
64 | 82 | ||
65 | /// Constructs an instance using the start of the first file in `db` as the lookup context. | 83 | /// Constructs an instance using the start of the first file in `db` as the lookup context. |
@@ -84,8 +102,16 @@ impl<'db> MatchFinder<'db> { | |||
84 | /// Adds a rule to be applied. The order in which rules are added matters. Earlier rules take | 102 | /// Adds a rule to be applied. The order in which rules are added matters. Earlier rules take |
85 | /// precedence. If a node is matched by an earlier rule, then later rules won't be permitted to | 103 | /// precedence. If a node is matched by an earlier rule, then later rules won't be permitted to |
86 | /// match to it. | 104 | /// match to it. |
87 | pub fn add_rule(&mut self, rule: SsrRule) { | 105 | pub fn add_rule(&mut self, rule: SsrRule) -> Result<(), SsrError> { |
88 | self.add_parsed_rules(rule.parsed_rules); | 106 | for parsed_rule in rule.parsed_rules { |
107 | self.rules.push(ResolvedRule::new( | ||
108 | parsed_rule, | ||
109 | &self.scope, | ||
110 | &self.hygiene, | ||
111 | self.rules.len(), | ||
112 | )?); | ||
113 | } | ||
114 | Ok(()) | ||
89 | } | 115 | } |
90 | 116 | ||
91 | /// Finds matches for all added rules and returns edits for all found matches. | 117 | /// Finds matches for all added rules and returns edits for all found matches. |
@@ -110,8 +136,16 @@ impl<'db> MatchFinder<'db> { | |||
110 | 136 | ||
111 | /// Adds a search pattern. For use if you intend to only call `find_matches_in_file`. If you | 137 | /// Adds a search pattern. For use if you intend to only call `find_matches_in_file`. If you |
112 | /// intend to do replacement, use `add_rule` instead. | 138 | /// intend to do replacement, use `add_rule` instead. |
113 | pub fn add_search_pattern(&mut self, pattern: SsrPattern) { | 139 | pub fn add_search_pattern(&mut self, pattern: SsrPattern) -> Result<(), SsrError> { |
114 | self.add_parsed_rules(pattern.parsed_rules); | 140 | for parsed_rule in pattern.parsed_rules { |
141 | self.rules.push(ResolvedRule::new( | ||
142 | parsed_rule, | ||
143 | &self.scope, | ||
144 | &self.hygiene, | ||
145 | self.rules.len(), | ||
146 | )?); | ||
147 | } | ||
148 | Ok(()) | ||
115 | } | 149 | } |
116 | 150 | ||
117 | /// Returns matches for all added rules. | 151 | /// Returns matches for all added rules. |
@@ -149,13 +183,6 @@ impl<'db> MatchFinder<'db> { | |||
149 | res | 183 | res |
150 | } | 184 | } |
151 | 185 | ||
152 | fn add_parsed_rules(&mut self, parsed_rules: Vec<parsing::ParsedRule>) { | ||
153 | for mut parsed_rule in parsed_rules { | ||
154 | parsed_rule.index = self.rules.len(); | ||
155 | self.rules.push(parsed_rule); | ||
156 | } | ||
157 | } | ||
158 | |||
159 | fn output_debug_for_nodes_at_range( | 186 | fn output_debug_for_nodes_at_range( |
160 | &self, | 187 | &self, |
161 | node: &SyntaxNode, | 188 | node: &SyntaxNode, |
@@ -175,7 +202,7 @@ impl<'db> MatchFinder<'db> { | |||
175 | // we get lots of noise. If at some point we add support for restricting rules | 202 | // we get lots of noise. If at some point we add support for restricting rules |
176 | // to a particular kind of thing (e.g. only match type references), then we can | 203 | // to a particular kind of thing (e.g. only match type references), then we can |
177 | // relax this. | 204 | // relax this. |
178 | if rule.pattern.kind() != node.kind() { | 205 | if rule.pattern.node.kind() != node.kind() { |
179 | continue; | 206 | continue; |
180 | } | 207 | } |
181 | out.push(MatchDebugInfo { | 208 | out.push(MatchDebugInfo { |
@@ -185,7 +212,7 @@ impl<'db> MatchFinder<'db> { | |||
185 | "Match failed, but no reason was given".to_owned() | 212 | "Match failed, but no reason was given".to_owned() |
186 | }), | 213 | }), |
187 | }), | 214 | }), |
188 | pattern: rule.pattern.clone(), | 215 | pattern: rule.pattern.node.clone(), |
189 | node: node.clone(), | 216 | node: node.clone(), |
190 | }); | 217 | }); |
191 | } | 218 | } |