diff options
Diffstat (limited to 'crates/ra_hir')
-rw-r--r-- | crates/ra_hir/src/lib.rs | 1 | ||||
-rw-r--r-- | crates/ra_hir/src/macros.rs | 53 |
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 @@ | |||
1 | use std::sync::Arc; | 1 | use std::sync::Arc; |
2 | 2 | ||
3 | use ra_db::SyntaxDatabase; | 3 | use ra_db::{SyntaxDatabase, LocalSyntaxPtr}; |
4 | use ra_syntax::{TextRange, TextUnit, SourceFileNode, AstNode, ast}; | 4 | use 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)] |
13 | pub struct MacroInput { | 16 | pub 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)] |
19 | pub struct MacroExpansion { | 22 | pub 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 | ||
24 | salsa::query_group! { | 28 | salsa::query_group! { |
25 | 29 | ||
26 | pub trait MacrosDatabase: SyntaxDatabase { | 30 | pub 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 | ||
34 | fn expand_macro( | 38 | fn 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 | |||
68 | impl 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 | } | ||