aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--crates/ra_analysis/src/db.rs3
-rw-r--r--crates/ra_analysis/src/extend_selection.rs8
-rw-r--r--crates/ra_analysis/src/macros.rs67
-rw-r--r--crates/ra_analysis/src/syntax_highlighting.rs6
-rw-r--r--crates/ra_hir/src/lib.rs1
-rw-r--r--crates/ra_hir/src/macros.rs53
6 files changed, 70 insertions, 68 deletions
diff --git a/crates/ra_analysis/src/db.rs b/crates/ra_analysis/src/db.rs
index b072a5eba..712f72484 100644
--- a/crates/ra_analysis/src/db.rs
+++ b/crates/ra_analysis/src/db.rs
@@ -98,5 +98,8 @@ salsa::database_storage! {
98 fn struct_data() for hir::db::StructDataQuery; 98 fn struct_data() for hir::db::StructDataQuery;
99 fn enum_data() for hir::db::EnumDataQuery; 99 fn enum_data() for hir::db::EnumDataQuery;
100 } 100 }
101 impl hir::MacroDatabase {
102 fn expand_macro() for hir::ExpandMacroQuery;
103 }
101 } 104 }
102} 105}
diff --git a/crates/ra_analysis/src/extend_selection.rs b/crates/ra_analysis/src/extend_selection.rs
index 805e9059e..62133ef29 100644
--- a/crates/ra_analysis/src/extend_selection.rs
+++ b/crates/ra_analysis/src/extend_selection.rs
@@ -23,10 +23,10 @@ fn extend_selection_in_macro(
23 frange: FileRange, 23 frange: FileRange,
24) -> Option<TextRange> { 24) -> Option<TextRange> {
25 let macro_call = find_macro_call(source_file.syntax(), frange.range)?; 25 let macro_call = find_macro_call(source_file.syntax(), frange.range)?;
26 let exp = crate::macros::expand(db, frange.file_id, macro_call)?; 26 let (off, exp) = crate::macros::expand(db, frange.file_id, macro_call)?;
27 let dst_range = exp.map_range_forward(frange.range)?; 27 let dst_range = exp.map_range_forward(frange.range - off)?;
28 let dst_range = ra_editor::extend_selection(exp.source_file().syntax(), dst_range)?; 28 let dst_range = ra_editor::extend_selection(exp.syntax().borrowed(), dst_range)?;
29 let src_range = exp.map_range_back(dst_range)?; 29 let src_range = exp.map_range_back(dst_range)? + off;
30 Some(src_range) 30 Some(src_range)
31} 31}
32 32
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.
4use ra_syntax::{ast, AstNode, SourceFileNode, TextRange}; 4use std::sync::Arc;
5
6use ra_syntax::{ast, AstNode, TextUnit};
7use hir::MacroDatabase;
5 8
6use crate::{db::RootDatabase, FileId}; 9use crate::{db::RootDatabase, FileId};
7 10
8pub(crate) fn expand( 11pub(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
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 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}
diff --git a/crates/ra_analysis/src/syntax_highlighting.rs b/crates/ra_analysis/src/syntax_highlighting.rs
index 7e9139a74..35a4630e9 100644
--- a/crates/ra_analysis/src/syntax_highlighting.rs
+++ b/crates/ra_analysis/src/syntax_highlighting.rs
@@ -15,13 +15,13 @@ pub(crate) fn highlight(db: &RootDatabase, file_id: FileId) -> Cancelable<Vec<Hi
15 .descendants() 15 .descendants()
16 .filter_map(ast::MacroCall::cast) 16 .filter_map(ast::MacroCall::cast)
17 { 17 {
18 if let Some(exp) = crate::macros::expand(db, file_id, macro_call) { 18 if let Some((off, exp)) = crate::macros::expand(db, file_id, macro_call) {
19 let mapped_ranges = ra_editor::highlight(exp.source_file().syntax()) 19 let mapped_ranges = ra_editor::highlight(exp.syntax().borrowed())
20 .into_iter() 20 .into_iter()
21 .filter_map(|r| { 21 .filter_map(|r| {
22 let mapped_range = exp.map_range_back(r.range)?; 22 let mapped_range = exp.map_range_back(r.range)?;
23 let res = HighlightedRange { 23 let res = HighlightedRange {
24 range: mapped_range, 24 range: mapped_range + off,
25 tag: r.tag, 25 tag: r.tag,
26 }; 26 };
27 Some(res) 27 Some(res)
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}