diff options
Diffstat (limited to 'crates')
-rw-r--r-- | crates/ra_hir_expand/src/lib.rs | 20 | ||||
-rw-r--r-- | crates/ra_ide/src/lib.rs | 3 | ||||
-rw-r--r-- | crates/ra_ide/src/ssr.rs | 36 | ||||
-rw-r--r-- | crates/ra_syntax/src/ast/make.rs | 16 | ||||
-rw-r--r-- | crates/rust-analyzer/src/main_loop/handlers.rs | 5 | ||||
-rw-r--r-- | crates/rust-analyzer/src/req.rs | 4 |
6 files changed, 55 insertions, 29 deletions
diff --git a/crates/ra_hir_expand/src/lib.rs b/crates/ra_hir_expand/src/lib.rs index 3fce73e8a..7b72eb7a0 100644 --- a/crates/ra_hir_expand/src/lib.rs +++ b/crates/ra_hir_expand/src/lib.rs | |||
@@ -17,7 +17,7 @@ pub mod eager; | |||
17 | use std::hash::Hash; | 17 | use std::hash::Hash; |
18 | use std::sync::Arc; | 18 | use std::sync::Arc; |
19 | 19 | ||
20 | use ra_db::{salsa, CrateId, FileId}; | 20 | use ra_db::{impl_intern_key, salsa, CrateId, FileId}; |
21 | use ra_syntax::{ | 21 | use ra_syntax::{ |
22 | algo, | 22 | algo, |
23 | ast::{self, AstNode}, | 23 | ast::{self, AstNode}, |
@@ -174,25 +174,11 @@ pub enum MacroCallId { | |||
174 | 174 | ||
175 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | 175 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] |
176 | pub struct LazyMacroId(salsa::InternId); | 176 | pub struct LazyMacroId(salsa::InternId); |
177 | impl salsa::InternKey for LazyMacroId { | 177 | impl_intern_key!(LazyMacroId); |
178 | fn from_intern_id(v: salsa::InternId) -> Self { | ||
179 | LazyMacroId(v) | ||
180 | } | ||
181 | fn as_intern_id(&self) -> salsa::InternId { | ||
182 | self.0 | ||
183 | } | ||
184 | } | ||
185 | 178 | ||
186 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | 179 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] |
187 | pub struct EagerMacroId(salsa::InternId); | 180 | pub struct EagerMacroId(salsa::InternId); |
188 | impl salsa::InternKey for EagerMacroId { | 181 | impl_intern_key!(EagerMacroId); |
189 | fn from_intern_id(v: salsa::InternId) -> Self { | ||
190 | EagerMacroId(v) | ||
191 | } | ||
192 | fn as_intern_id(&self) -> salsa::InternId { | ||
193 | self.0 | ||
194 | } | ||
195 | } | ||
196 | 182 | ||
197 | impl From<LazyMacroId> for MacroCallId { | 183 | impl From<LazyMacroId> for MacroCallId { |
198 | fn from(it: LazyMacroId) -> Self { | 184 | fn from(it: LazyMacroId) -> Self { |
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); }"; |
diff --git a/crates/ra_syntax/src/ast/make.rs b/crates/ra_syntax/src/ast/make.rs index ae8829807..9f6f1cc53 100644 --- a/crates/ra_syntax/src/ast/make.rs +++ b/crates/ra_syntax/src/ast/make.rs | |||
@@ -112,10 +112,14 @@ pub fn expr_prefix(op: SyntaxKind, expr: ast::Expr) -> ast::Expr { | |||
112 | let token = token(op); | 112 | let token = token(op); |
113 | expr_from_text(&format!("{}{}", token, expr.syntax())) | 113 | expr_from_text(&format!("{}{}", token, expr.syntax())) |
114 | } | 114 | } |
115 | pub fn expr_from_text(text: &str) -> ast::Expr { | 115 | fn expr_from_text(text: &str) -> ast::Expr { |
116 | ast_from_text(&format!("const C: () = {};", text)) | 116 | ast_from_text(&format!("const C: () = {};", text)) |
117 | } | 117 | } |
118 | 118 | ||
119 | pub fn try_expr_from_text(text: &str) -> Option<ast::Expr> { | ||
120 | try_ast_from_text(&format!("const C: () = {};", text)) | ||
121 | } | ||
122 | |||
119 | pub fn bind_pat(name: ast::Name) -> ast::BindPat { | 123 | pub fn bind_pat(name: ast::Name) -> ast::BindPat { |
120 | return from_text(name.text()); | 124 | return from_text(name.text()); |
121 | 125 | ||
@@ -239,6 +243,16 @@ fn ast_from_text<N: AstNode>(text: &str) -> N { | |||
239 | node | 243 | node |
240 | } | 244 | } |
241 | 245 | ||
246 | fn try_ast_from_text<N: AstNode>(text: &str) -> Option<N> { | ||
247 | let parse = SourceFile::parse(text); | ||
248 | let node = parse.tree().syntax().descendants().find_map(N::cast)?; | ||
249 | let node = node.syntax().clone(); | ||
250 | let node = unroot(node); | ||
251 | let node = N::cast(node).unwrap(); | ||
252 | assert_eq!(node.syntax().text_range().start(), 0.into()); | ||
253 | Some(node) | ||
254 | } | ||
255 | |||
242 | fn unroot(n: SyntaxNode) -> SyntaxNode { | 256 | fn unroot(n: SyntaxNode) -> SyntaxNode { |
243 | SyntaxNode::new_root(n.green().clone()) | 257 | SyntaxNode::new_root(n.green().clone()) |
244 | } | 258 | } |
diff --git a/crates/rust-analyzer/src/main_loop/handlers.rs b/crates/rust-analyzer/src/main_loop/handlers.rs index df3622d61..1cc2f6571 100644 --- a/crates/rust-analyzer/src/main_loop/handlers.rs +++ b/crates/rust-analyzer/src/main_loop/handlers.rs | |||
@@ -932,7 +932,10 @@ pub fn handle_document_highlight( | |||
932 | 932 | ||
933 | pub fn handle_ssr(world: WorldSnapshot, params: req::SsrParams) -> Result<req::SourceChange> { | 933 | pub fn handle_ssr(world: WorldSnapshot, params: req::SsrParams) -> Result<req::SourceChange> { |
934 | let _p = profile("handle_ssr"); | 934 | let _p = profile("handle_ssr"); |
935 | world.analysis().structural_search_replace(¶ms.arg)??.try_conv_with(&world) | 935 | world |
936 | .analysis() | ||
937 | .structural_search_replace(¶ms.query, params.parse_only)?? | ||
938 | .try_conv_with(&world) | ||
936 | } | 939 | } |
937 | 940 | ||
938 | pub fn publish_diagnostics(world: &WorldSnapshot, file_id: FileId) -> Result<DiagnosticTask> { | 941 | pub fn publish_diagnostics(world: &WorldSnapshot, file_id: FileId) -> Result<DiagnosticTask> { |
diff --git a/crates/rust-analyzer/src/req.rs b/crates/rust-analyzer/src/req.rs index 156328df8..9e27d3f1c 100644 --- a/crates/rust-analyzer/src/req.rs +++ b/crates/rust-analyzer/src/req.rs | |||
@@ -218,6 +218,8 @@ impl Request for Ssr { | |||
218 | } | 218 | } |
219 | 219 | ||
220 | #[derive(Debug, Deserialize, Serialize)] | 220 | #[derive(Debug, Deserialize, Serialize)] |
221 | #[serde(rename_all = "camelCase")] | ||
221 | pub struct SsrParams { | 222 | pub struct SsrParams { |
222 | pub arg: String, | 223 | pub query: String, |
224 | pub parse_only: bool, | ||
223 | } | 225 | } |