diff options
author | Aleksey Kladov <[email protected]> | 2018-12-31 16:19:50 +0000 |
---|---|---|
committer | Aleksey Kladov <[email protected]> | 2019-01-01 19:15:35 +0000 |
commit | 57030f587bb0bbe4dea9a97016b4e0f49a7ef5f3 (patch) | |
tree | b30fe16afdaffcd5bb74d434101732dc20908d43 | |
parent | d75365619212983d2b7abf7b5b5e73c70dd07fb4 (diff) |
use macros database in analysis
-rw-r--r-- | crates/ra_analysis/src/db.rs | 3 | ||||
-rw-r--r-- | crates/ra_analysis/src/extend_selection.rs | 8 | ||||
-rw-r--r-- | crates/ra_analysis/src/macros.rs | 67 | ||||
-rw-r--r-- | crates/ra_analysis/src/syntax_highlighting.rs | 6 | ||||
-rw-r--r-- | crates/ra_hir/src/lib.rs | 1 | ||||
-rw-r--r-- | crates/ra_hir/src/macros.rs | 53 |
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. |
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 | } |
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 @@ | |||
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 | } | ||