diff options
Diffstat (limited to 'crates/ra_analysis/src/macros.rs')
-rw-r--r-- | crates/ra_analysis/src/macros.rs | 67 |
1 files changed, 12 insertions, 55 deletions
diff --git a/crates/ra_analysis/src/macros.rs b/crates/ra_analysis/src/macros.rs index b9feb7fad..21ec36cd6 100644 --- a/crates/ra_analysis/src/macros.rs +++ b/crates/ra_analysis/src/macros.rs | |||
@@ -1,15 +1,18 @@ | |||
1 | /// Begining of macro expansion. | 1 | /// Begining of macro expansion. |
2 | /// | 2 | /// |
3 | /// This code should be moved out of ra_analysis into hir (?) ideally. | 3 | /// This code should be moved out of ra_analysis into hir (?) ideally. |
4 | use ra_syntax::{ast, AstNode, SourceFileNode, TextRange}; | 4 | use std::sync::Arc; |
5 | |||
6 | use ra_syntax::{ast, AstNode, TextUnit}; | ||
7 | use hir::MacroDatabase; | ||
5 | 8 | ||
6 | use crate::{db::RootDatabase, FileId}; | 9 | use crate::{db::RootDatabase, FileId}; |
7 | 10 | ||
8 | pub(crate) fn expand( | 11 | pub(crate) fn expand( |
9 | _db: &RootDatabase, | 12 | db: &RootDatabase, |
10 | _file_id: FileId, | 13 | _file_id: FileId, |
11 | macro_call: ast::MacroCall, | 14 | macro_call: ast::MacroCall, |
12 | ) -> Option<MacroExpansion> { | 15 | ) -> Option<(TextUnit, Arc<hir::MacroExpansion>)> { |
13 | let path = macro_call.path()?; | 16 | let path = macro_call.path()?; |
14 | if path.qualifier().is_some() { | 17 | if path.qualifier().is_some() { |
15 | return None; | 18 | return None; |
@@ -18,58 +21,12 @@ pub(crate) fn expand( | |||
18 | if name_ref.text() != "ctry" { | 21 | if name_ref.text() != "ctry" { |
19 | return None; | 22 | return None; |
20 | } | 23 | } |
24 | let arg = macro_call.token_tree()?.syntax(); | ||
21 | 25 | ||
22 | let arg = macro_call.token_tree()?; | 26 | let def = hir::MacroDef::CTry; |
23 | let text = format!( | 27 | let input = hir::MacroInput { |
24 | r" | 28 | text: arg.text().to_string(), |
25 | fn dummy() {{ | ||
26 | match {} {{ | ||
27 | None => return Ok(None), | ||
28 | Some(it) => it, | ||
29 | }} | ||
30 | }}", | ||
31 | arg.syntax().text() | ||
32 | ); | ||
33 | let file = SourceFileNode::parse(&text); | ||
34 | let match_expr = file.syntax().descendants().find_map(ast::MatchExpr::cast)?; | ||
35 | let match_arg = match_expr.expr()?; | ||
36 | let ranges_map = vec![(arg.syntax().range(), match_arg.syntax().range())]; | ||
37 | let res = MacroExpansion { | ||
38 | source_file: file, | ||
39 | ranges_map, | ||
40 | }; | 29 | }; |
41 | Some(res) | 30 | let exp = db.expand_macro(def, input)?; |
42 | } | 31 | Some((arg.range().start(), exp)) |
43 | |||
44 | pub(crate) struct MacroExpansion { | ||
45 | pub(crate) source_file: SourceFileNode, | ||
46 | pub(crate) ranges_map: Vec<(TextRange, TextRange)>, | ||
47 | } | ||
48 | |||
49 | impl MacroExpansion { | ||
50 | pub(crate) fn source_file(&self) -> &SourceFileNode { | ||
51 | &self.source_file | ||
52 | } | ||
53 | pub(crate) fn map_range_back(&self, tgt_range: TextRange) -> Option<TextRange> { | ||
54 | for (s_range, t_range) in self.ranges_map.iter() { | ||
55 | if tgt_range.is_subrange(&t_range) { | ||
56 | let tgt_at_zero_range = tgt_range - tgt_range.start(); | ||
57 | let tgt_range_offset = tgt_range.start() - t_range.start(); | ||
58 | let src_range = tgt_at_zero_range + tgt_range_offset + s_range.start(); | ||
59 | return Some(src_range); | ||
60 | } | ||
61 | } | ||
62 | None | ||
63 | } | ||
64 | pub(crate) fn map_range_forward(&self, src_range: TextRange) -> Option<TextRange> { | ||
65 | for (s_range, t_range) in self.ranges_map.iter() { | ||
66 | if src_range.is_subrange(&s_range) { | ||
67 | let src_at_zero_range = src_range - src_range.start(); | ||
68 | let src_range_offset = src_range.start() - s_range.start(); | ||
69 | let src_range = src_at_zero_range + src_range_offset + t_range.start(); | ||
70 | return Some(src_range); | ||
71 | } | ||
72 | } | ||
73 | None | ||
74 | } | ||
75 | } | 32 | } |