aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_hir')
-rw-r--r--crates/ra_hir/src/lib.rs1
-rw-r--r--crates/ra_hir/src/macros.rs53
2 files changed, 48 insertions, 6 deletions
diff --git a/crates/ra_hir/src/lib.rs b/crates/ra_hir/src/lib.rs
index e89410a76..ce750299f 100644
--- a/crates/ra_hir/src/lib.rs
+++ b/crates/ra_hir/src/lib.rs
@@ -46,6 +46,7 @@ pub use self::{
46 path::{Path, PathKind}, 46 path::{Path, PathKind},
47 name::Name, 47 name::Name,
48 krate::Crate, 48 krate::Crate,
49 macros::{MacroDef, MacroInput, MacroExpansion, MacroDatabase, ExpandMacroQuery},
49 module::{Module, ModuleId, Problem, nameres::{ItemMap, PerNs, Namespace}, ModuleScope, Resolution}, 50 module::{Module, ModuleId, Problem, nameres::{ItemMap, PerNs, Namespace}, ModuleScope, Resolution},
50 function::{Function, FnScopes}, 51 function::{Function, FnScopes},
51 adt::{Struct, Enum}, 52 adt::{Struct, Enum},
diff --git a/crates/ra_hir/src/macros.rs b/crates/ra_hir/src/macros.rs
index 050b97081..ef6502524 100644
--- a/crates/ra_hir/src/macros.rs
+++ b/crates/ra_hir/src/macros.rs
@@ -1,7 +1,10 @@
1use std::sync::Arc; 1use std::sync::Arc;
2 2
3use ra_db::SyntaxDatabase; 3use ra_db::{SyntaxDatabase, LocalSyntaxPtr};
4use ra_syntax::{TextRange, TextUnit, SourceFileNode, AstNode, ast}; 4use ra_syntax::{
5 TextRange, TextUnit, SourceFileNode, AstNode, SyntaxNode,
6 ast,
7};
5 8
6// Hard-coded defs for now :-( 9// Hard-coded defs for now :-(
7#[derive(Debug, Clone, PartialEq, Eq, Hash)] 10#[derive(Debug, Clone, PartialEq, Eq, Hash)]
@@ -12,18 +15,19 @@ pub enum MacroDef {
12#[derive(Debug, Clone, PartialEq, Eq, Hash)] 15#[derive(Debug, Clone, PartialEq, Eq, Hash)]
13pub struct MacroInput { 16pub struct MacroInput {
14 // Should be token trees 17 // Should be token trees
15 text: String, 18 pub text: String,
16} 19}
17 20
18#[derive(Debug, Clone, PartialEq, Eq)] 21#[derive(Debug, Clone, PartialEq, Eq)]
19pub struct MacroExpansion { 22pub struct MacroExpansion {
20 text: String, 23 text: String,
21 ranges_map: Vec<(TextRange, TextRange)>, 24 ranges_map: Vec<(TextRange, TextRange)>,
25 ptr: LocalSyntaxPtr,
22} 26}
23 27
24salsa::query_group! { 28salsa::query_group! {
25 29
26pub trait MacrosDatabase: SyntaxDatabase { 30pub trait MacroDatabase: SyntaxDatabase {
27 fn expand_macro(def: MacroDef, input: MacroInput) -> Option<Arc<MacroExpansion>> { 31 fn expand_macro(def: MacroDef, input: MacroInput) -> Option<Arc<MacroExpansion>> {
28 type ExpandMacroQuery; 32 type ExpandMacroQuery;
29 } 33 }
@@ -32,7 +36,7 @@ pub trait MacrosDatabase: SyntaxDatabase {
32} 36}
33 37
34fn expand_macro( 38fn expand_macro(
35 _db: &impl MacrosDatabase, 39 _db: &impl MacroDatabase,
36 def: MacroDef, 40 def: MacroDef,
37 input: MacroInput, 41 input: MacroInput,
38) -> Option<Arc<MacroExpansion>> { 42) -> Option<Arc<MacroExpansion>> {
@@ -50,8 +54,45 @@ fn expand_macro(
50 let file = SourceFileNode::parse(&text); 54 let file = SourceFileNode::parse(&text);
51 let match_expr = file.syntax().descendants().find_map(ast::MatchExpr::cast)?; 55 let match_expr = file.syntax().descendants().find_map(ast::MatchExpr::cast)?;
52 let match_arg = match_expr.expr()?; 56 let match_arg = match_expr.expr()?;
57 let ptr = LocalSyntaxPtr::new(match_arg.syntax());
53 let src_range = TextRange::offset_len(0.into(), TextUnit::of_str(&input.text)); 58 let src_range = TextRange::offset_len(0.into(), TextUnit::of_str(&input.text));
54 let ranges_map = vec![(src_range, match_arg.syntax().range())]; 59 let ranges_map = vec![(src_range, match_arg.syntax().range())];
55 let res = MacroExpansion { text, ranges_map }; 60 let res = MacroExpansion {
61 text,
62 ranges_map,
63 ptr,
64 };
56 Some(Arc::new(res)) 65 Some(Arc::new(res))
57} 66}
67
68impl MacroExpansion {
69 pub fn file(&self) -> SourceFileNode {
70 SourceFileNode::parse(&self.text)
71 }
72
73 pub fn syntax(&self) -> SyntaxNode {
74 self.ptr.resolve(&self.file())
75 }
76 pub fn map_range_back(&self, tgt_range: TextRange) -> Option<TextRange> {
77 for (s_range, t_range) in self.ranges_map.iter() {
78 if tgt_range.is_subrange(&t_range) {
79 let tgt_at_zero_range = tgt_range - tgt_range.start();
80 let tgt_range_offset = tgt_range.start() - t_range.start();
81 let src_range = tgt_at_zero_range + tgt_range_offset + s_range.start();
82 return Some(src_range);
83 }
84 }
85 None
86 }
87 pub fn map_range_forward(&self, src_range: TextRange) -> Option<TextRange> {
88 for (s_range, t_range) in self.ranges_map.iter() {
89 if src_range.is_subrange(&s_range) {
90 let src_at_zero_range = src_range - src_range.start();
91 let src_range_offset = src_range.start() - s_range.start();
92 let src_range = src_at_zero_range + src_range_offset + t_range.start();
93 return Some(src_range);
94 }
95 }
96 None
97 }
98}