diff options
author | bors[bot] <26634292+bors[bot]@users.noreply.github.com> | 2020-03-16 09:48:09 +0000 |
---|---|---|
committer | GitHub <[email protected]> | 2020-03-16 09:48:09 +0000 |
commit | a99cac671c3e6105a0192acbb1a91cb83e453018 (patch) | |
tree | a6eb701b7fc1a7e83b686a04e498253ee1b34cb0 /crates/ra_ide | |
parent | 6616f336b28bcab7d693473c6d9263dff15639ae (diff) | |
parent | b150965ed7994c679711bc807de301a12f5c7944 (diff) |
Merge #3540
3540: Swtches to rust SSR query check r=matklad a=mikhail-m1
related to #3186
Co-authored-by: Mikhail Modin <[email protected]>
Diffstat (limited to 'crates/ra_ide')
-rw-r--r-- | crates/ra_ide/src/lib.rs | 3 | ||||
-rw-r--r-- | crates/ra_ide/src/ssr.rs | 36 |
2 files changed, 30 insertions, 9 deletions
diff --git a/crates/ra_ide/src/lib.rs b/crates/ra_ide/src/lib.rs index e9af80b6c..5ab06c6cf 100644 --- a/crates/ra_ide/src/lib.rs +++ b/crates/ra_ide/src/lib.rs | |||
@@ -473,9 +473,10 @@ impl Analysis { | |||
473 | pub fn structural_search_replace( | 473 | pub fn structural_search_replace( |
474 | &self, | 474 | &self, |
475 | query: &str, | 475 | query: &str, |
476 | parse_only: bool, | ||
476 | ) -> Cancelable<Result<SourceChange, SsrError>> { | 477 | ) -> Cancelable<Result<SourceChange, SsrError>> { |
477 | self.with_db(|db| { | 478 | self.with_db(|db| { |
478 | let edits = ssr::parse_search_replace(query, db)?; | 479 | let edits = ssr::parse_search_replace(query, parse_only, db)?; |
479 | Ok(SourceChange::source_file_edits("ssr", edits)) | 480 | Ok(SourceChange::source_file_edits("ssr", edits)) |
480 | }) | 481 | }) |
481 | } | 482 | } |
diff --git a/crates/ra_ide/src/ssr.rs b/crates/ra_ide/src/ssr.rs index c011a2e74..1c9710a5d 100644 --- a/crates/ra_ide/src/ssr.rs +++ b/crates/ra_ide/src/ssr.rs | |||
@@ -1,8 +1,10 @@ | |||
1 | //! structural search replace | 1 | //! structural search replace |
2 | 2 | ||
3 | use crate::source_change::SourceFileEdit; | 3 | use crate::source_change::SourceFileEdit; |
4 | use ra_db::{SourceDatabase, SourceDatabaseExt}; | ||
5 | use ra_ide_db::symbol_index::SymbolsDatabase; | ||
4 | use ra_ide_db::RootDatabase; | 6 | use ra_ide_db::RootDatabase; |
5 | use ra_syntax::ast::make::expr_from_text; | 7 | use ra_syntax::ast::make::try_expr_from_text; |
6 | use ra_syntax::ast::{AstToken, Comment}; | 8 | use ra_syntax::ast::{AstToken, Comment}; |
7 | use ra_syntax::{AstNode, SyntaxElement, SyntaxNode}; | 9 | use ra_syntax::{AstNode, SyntaxElement, SyntaxNode}; |
8 | use ra_text_edit::{TextEdit, TextEditBuilder}; | 10 | use ra_text_edit::{TextEdit, TextEditBuilder}; |
@@ -10,9 +12,6 @@ use rustc_hash::FxHashMap; | |||
10 | use std::collections::HashMap; | 12 | use std::collections::HashMap; |
11 | use std::str::FromStr; | 13 | use std::str::FromStr; |
12 | 14 | ||
13 | pub use ra_db::{SourceDatabase, SourceDatabaseExt}; | ||
14 | use ra_ide_db::symbol_index::SymbolsDatabase; | ||
15 | |||
16 | #[derive(Debug, PartialEq)] | 15 | #[derive(Debug, PartialEq)] |
17 | pub struct SsrError(String); | 16 | pub struct SsrError(String); |
18 | 17 | ||
@@ -26,14 +25,17 @@ impl std::error::Error for SsrError {} | |||
26 | 25 | ||
27 | pub fn parse_search_replace( | 26 | pub fn parse_search_replace( |
28 | query: &str, | 27 | query: &str, |
28 | parse_only: bool, | ||
29 | db: &RootDatabase, | 29 | db: &RootDatabase, |
30 | ) -> Result<Vec<SourceFileEdit>, SsrError> { | 30 | ) -> Result<Vec<SourceFileEdit>, SsrError> { |
31 | let mut edits = vec![]; | 31 | let mut edits = vec![]; |
32 | let query: SsrQuery = query.parse()?; | 32 | let query: SsrQuery = query.parse()?; |
33 | if parse_only { | ||
34 | return Ok(edits); | ||
35 | } | ||
33 | for &root in db.local_roots().iter() { | 36 | for &root in db.local_roots().iter() { |
34 | let sr = db.source_root(root); | 37 | let sr = db.source_root(root); |
35 | for file_id in sr.walk() { | 38 | for file_id in sr.walk() { |
36 | dbg!(db.file_relative_path(file_id)); | ||
37 | let matches = find(&query.pattern, db.parse(file_id).tree().syntax()); | 39 | let matches = find(&query.pattern, db.parse(file_id).tree().syntax()); |
38 | if !matches.matches.is_empty() { | 40 | if !matches.matches.is_empty() { |
39 | edits.push(SourceFileEdit { file_id, edit: replace(&matches, &query.template) }); | 41 | edits.push(SourceFileEdit { file_id, edit: replace(&matches, &query.template) }); |
@@ -106,7 +108,10 @@ impl FromStr for SsrQuery { | |||
106 | template = replace_in_template(template, var, new_var); | 108 | template = replace_in_template(template, var, new_var); |
107 | } | 109 | } |
108 | 110 | ||
109 | let template = expr_from_text(&template).syntax().clone(); | 111 | let template = try_expr_from_text(&template) |
112 | .ok_or(SsrError("Template is not an expression".into()))? | ||
113 | .syntax() | ||
114 | .clone(); | ||
110 | let mut placeholders = FxHashMap::default(); | 115 | let mut placeholders = FxHashMap::default(); |
111 | 116 | ||
112 | traverse(&template, &mut |n| { | 117 | traverse(&template, &mut |n| { |
@@ -118,7 +123,13 @@ impl FromStr for SsrQuery { | |||
118 | } | 123 | } |
119 | }); | 124 | }); |
120 | 125 | ||
121 | let pattern = SsrPattern { pattern: expr_from_text(&pattern).syntax().clone(), vars }; | 126 | let pattern = SsrPattern { |
127 | pattern: try_expr_from_text(&pattern) | ||
128 | .ok_or(SsrError("Pattern is not an expression".into()))? | ||
129 | .syntax() | ||
130 | .clone(), | ||
131 | vars, | ||
132 | }; | ||
122 | let template = SsrTemplate { template, placeholders }; | 133 | let template = SsrTemplate { template, placeholders }; |
123 | Ok(SsrQuery { pattern, template }) | 134 | Ok(SsrQuery { pattern, template }) |
124 | } | 135 | } |
@@ -284,7 +295,6 @@ mod tests { | |||
284 | assert_eq!(result.pattern.vars[0].0, "__search_pattern_a"); | 295 | assert_eq!(result.pattern.vars[0].0, "__search_pattern_a"); |
285 | assert_eq!(result.pattern.vars[1].0, "__search_pattern_b"); | 296 | assert_eq!(result.pattern.vars[1].0, "__search_pattern_b"); |
286 | assert_eq!(&result.template.template.text(), "bar(__search_pattern_b, __search_pattern_a)"); | 297 | assert_eq!(&result.template.template.text(), "bar(__search_pattern_b, __search_pattern_a)"); |
287 | dbg!(result.template.placeholders); | ||
288 | } | 298 | } |
289 | 299 | ||
290 | #[test] | 300 | #[test] |
@@ -335,6 +345,16 @@ mod tests { | |||
335 | } | 345 | } |
336 | 346 | ||
337 | #[test] | 347 | #[test] |
348 | fn parser_invlid_pattern() { | ||
349 | assert_eq!(parse_error_text(" ==>> ()"), "Parse error: Pattern is not an expression"); | ||
350 | } | ||
351 | |||
352 | #[test] | ||
353 | fn parser_invlid_template() { | ||
354 | assert_eq!(parse_error_text("() ==>> )"), "Parse error: Template is not an expression"); | ||
355 | } | ||
356 | |||
357 | #[test] | ||
338 | fn parse_match_replace() { | 358 | fn parse_match_replace() { |
339 | let query: SsrQuery = "foo($x:expr) ==>> bar($x)".parse().unwrap(); | 359 | let query: SsrQuery = "foo($x:expr) ==>> bar($x)".parse().unwrap(); |
340 | let input = "fn main() { foo(1+2); }"; | 360 | let input = "fn main() { foo(1+2); }"; |