aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_analysis/src/macros.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_analysis/src/macros.rs')
-rw-r--r--crates/ra_analysis/src/macros.rs64
1 files changed, 64 insertions, 0 deletions
diff --git a/crates/ra_analysis/src/macros.rs b/crates/ra_analysis/src/macros.rs
new file mode 100644
index 000000000..c0dd49dc8
--- /dev/null
+++ b/crates/ra_analysis/src/macros.rs
@@ -0,0 +1,64 @@
1/// Begining of macro expansion.
2///
3/// This code should be moved out of ra_analysis into hir (?) ideally.
4use ra_syntax::{ast, AstNode, SourceFileNode, TextRange};
5
6use crate::{db::RootDatabase, FileId};
7
8pub(crate) fn expand(
9 _db: &RootDatabase,
10 _file_id: FileId,
11 macro_call: ast::MacroCall,
12) -> Option<MacroExpansion> {
13 let path = macro_call.path()?;
14 if path.qualifier().is_some() {
15 return None;
16 }
17 let name_ref = path.segment()?.name_ref()?;
18 if name_ref.text() != "ctry" {
19 return None;
20 }
21
22 let arg = macro_call.token_tree()?;
23 let text = format!(
24 r"
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 };
41 Some(res)
42}
43
44pub(crate) struct MacroExpansion {
45 pub(crate) source_file: SourceFileNode,
46 pub(crate) ranges_map: Vec<(TextRange, TextRange)>,
47}
48
49impl 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}