diff options
-rw-r--r-- | crates/ra_analysis/src/db.rs | 18 | ||||
-rw-r--r-- | crates/ra_analysis/src/extend_selection.rs | 4 | ||||
-rw-r--r-- | crates/ra_analysis/src/lib.rs | 1 | ||||
-rw-r--r-- | crates/ra_analysis/src/macros.rs | 32 | ||||
-rw-r--r-- | crates/ra_analysis/src/syntax_highlighting.rs | 2 | ||||
-rw-r--r-- | crates/ra_hir/src/db.rs | 7 | ||||
-rw-r--r-- | crates/ra_hir/src/lib.rs | 2 | ||||
-rw-r--r-- | crates/ra_hir/src/macros.rs | 146 |
8 files changed, 127 insertions, 85 deletions
diff --git a/crates/ra_analysis/src/db.rs b/crates/ra_analysis/src/db.rs index 712f72484..2a71cc2b6 100644 --- a/crates/ra_analysis/src/db.rs +++ b/crates/ra_analysis/src/db.rs | |||
@@ -1,7 +1,6 @@ | |||
1 | use std::{fmt, sync::Arc}; | 1 | use std::{fmt, sync::Arc}; |
2 | use salsa::{self, Database}; | 2 | use salsa::{self, Database}; |
3 | use ra_db::{LocationIntener, BaseDatabase}; | 3 | use ra_db::{LocationIntener, BaseDatabase}; |
4 | use hir::{self, DefId, DefLoc}; | ||
5 | 4 | ||
6 | use crate::{ | 5 | use crate::{ |
7 | symbol_index, | 6 | symbol_index, |
@@ -15,7 +14,8 @@ pub(crate) struct RootDatabase { | |||
15 | 14 | ||
16 | #[derive(Default)] | 15 | #[derive(Default)] |
17 | struct IdMaps { | 16 | struct IdMaps { |
18 | defs: LocationIntener<DefLoc, DefId>, | 17 | defs: LocationIntener<hir::DefLoc, hir::DefId>, |
18 | macros: LocationIntener<hir::MacroInvocationLoc, hir::MacroInvocationId>, | ||
19 | } | 19 | } |
20 | 20 | ||
21 | impl fmt::Debug for IdMaps { | 21 | impl fmt::Debug for IdMaps { |
@@ -59,12 +59,18 @@ impl salsa::ParallelDatabase for RootDatabase { | |||
59 | 59 | ||
60 | impl BaseDatabase for RootDatabase {} | 60 | impl BaseDatabase for RootDatabase {} |
61 | 61 | ||
62 | impl AsRef<LocationIntener<DefLoc, DefId>> for RootDatabase { | 62 | impl AsRef<LocationIntener<hir::DefLoc, hir::DefId>> for RootDatabase { |
63 | fn as_ref(&self) -> &LocationIntener<DefLoc, DefId> { | 63 | fn as_ref(&self) -> &LocationIntener<hir::DefLoc, hir::DefId> { |
64 | &self.id_maps.defs | 64 | &self.id_maps.defs |
65 | } | 65 | } |
66 | } | 66 | } |
67 | 67 | ||
68 | impl AsRef<LocationIntener<hir::MacroInvocationLoc, hir::MacroInvocationId>> for RootDatabase { | ||
69 | fn as_ref(&self) -> &LocationIntener<hir::MacroInvocationLoc, hir::MacroInvocationId> { | ||
70 | &self.id_maps.macros | ||
71 | } | ||
72 | } | ||
73 | |||
68 | salsa::database_storage! { | 74 | salsa::database_storage! { |
69 | pub(crate) struct RootDatabaseStorage for RootDatabase { | 75 | pub(crate) struct RootDatabaseStorage for RootDatabase { |
70 | impl ra_db::FilesDatabase { | 76 | impl ra_db::FilesDatabase { |
@@ -85,6 +91,7 @@ salsa::database_storage! { | |||
85 | fn library_symbols() for symbol_index::LibrarySymbolsQuery; | 91 | fn library_symbols() for symbol_index::LibrarySymbolsQuery; |
86 | } | 92 | } |
87 | impl hir::db::HirDatabase { | 93 | impl hir::db::HirDatabase { |
94 | fn expand_macro_invocation() for hir::db::ExpandMacroInvocationQuery; | ||
88 | fn module_tree() for hir::db::ModuleTreeQuery; | 95 | fn module_tree() for hir::db::ModuleTreeQuery; |
89 | fn fn_scopes() for hir::db::FnScopesQuery; | 96 | fn fn_scopes() for hir::db::FnScopesQuery; |
90 | fn file_items() for hir::db::SourceFileItemsQuery; | 97 | fn file_items() for hir::db::SourceFileItemsQuery; |
@@ -98,8 +105,5 @@ salsa::database_storage! { | |||
98 | fn struct_data() for hir::db::StructDataQuery; | 105 | fn struct_data() for hir::db::StructDataQuery; |
99 | fn enum_data() for hir::db::EnumDataQuery; | 106 | fn enum_data() for hir::db::EnumDataQuery; |
100 | } | 107 | } |
101 | impl hir::MacroDatabase { | ||
102 | fn expand_macro() for hir::ExpandMacroQuery; | ||
103 | } | ||
104 | } | 108 | } |
105 | } | 109 | } |
diff --git a/crates/ra_analysis/src/extend_selection.rs b/crates/ra_analysis/src/extend_selection.rs index 62133ef29..f1b77f981 100644 --- a/crates/ra_analysis/src/extend_selection.rs +++ b/crates/ra_analysis/src/extend_selection.rs | |||
@@ -18,12 +18,12 @@ pub(crate) fn extend_selection(db: &RootDatabase, frange: FileRange) -> TextRang | |||
18 | } | 18 | } |
19 | 19 | ||
20 | fn extend_selection_in_macro( | 20 | fn extend_selection_in_macro( |
21 | db: &RootDatabase, | 21 | _db: &RootDatabase, |
22 | source_file: &SourceFileNode, | 22 | source_file: &SourceFileNode, |
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 (off, exp) = crate::macros::expand(db, frange.file_id, macro_call)?; | 26 | let (off, exp) = hir::MacroDef::ast_expand(macro_call)?; |
27 | let dst_range = exp.map_range_forward(frange.range - off)?; | 27 | let dst_range = exp.map_range_forward(frange.range - off)?; |
28 | let dst_range = ra_editor::extend_selection(exp.syntax().borrowed(), 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)? + off; | 29 | let src_range = exp.map_range_back(dst_range)? + off; |
diff --git a/crates/ra_analysis/src/lib.rs b/crates/ra_analysis/src/lib.rs index e6cfaecc3..08ecb125a 100644 --- a/crates/ra_analysis/src/lib.rs +++ b/crates/ra_analysis/src/lib.rs | |||
@@ -19,7 +19,6 @@ mod runnables; | |||
19 | 19 | ||
20 | mod extend_selection; | 20 | mod extend_selection; |
21 | mod syntax_highlighting; | 21 | mod syntax_highlighting; |
22 | mod macros; | ||
23 | 22 | ||
24 | use std::{fmt, sync::Arc}; | 23 | use std::{fmt, sync::Arc}; |
25 | 24 | ||
diff --git a/crates/ra_analysis/src/macros.rs b/crates/ra_analysis/src/macros.rs deleted file mode 100644 index 21ec36cd6..000000000 --- a/crates/ra_analysis/src/macros.rs +++ /dev/null | |||
@@ -1,32 +0,0 @@ | |||
1 | /// Begining of macro expansion. | ||
2 | /// | ||
3 | /// This code should be moved out of ra_analysis into hir (?) ideally. | ||
4 | use std::sync::Arc; | ||
5 | |||
6 | use ra_syntax::{ast, AstNode, TextUnit}; | ||
7 | use hir::MacroDatabase; | ||
8 | |||
9 | use crate::{db::RootDatabase, FileId}; | ||
10 | |||
11 | pub(crate) fn expand( | ||
12 | db: &RootDatabase, | ||
13 | _file_id: FileId, | ||
14 | macro_call: ast::MacroCall, | ||
15 | ) -> Option<(TextUnit, Arc<hir::MacroExpansion>)> { | ||
16 | let path = macro_call.path()?; | ||
17 | if path.qualifier().is_some() { | ||
18 | return None; | ||
19 | } | ||
20 | let name_ref = path.segment()?.name_ref()?; | ||
21 | if name_ref.text() != "ctry" { | ||
22 | return None; | ||
23 | } | ||
24 | let arg = macro_call.token_tree()?.syntax(); | ||
25 | |||
26 | let def = hir::MacroDef::CTry; | ||
27 | let input = hir::MacroInput { | ||
28 | text: arg.text().to_string(), | ||
29 | }; | ||
30 | let exp = db.expand_macro(def, input)?; | ||
31 | Some((arg.range().start(), exp)) | ||
32 | } | ||
diff --git a/crates/ra_analysis/src/syntax_highlighting.rs b/crates/ra_analysis/src/syntax_highlighting.rs index 35a4630e9..a644b3fe0 100644 --- a/crates/ra_analysis/src/syntax_highlighting.rs +++ b/crates/ra_analysis/src/syntax_highlighting.rs | |||
@@ -15,7 +15,7 @@ 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((off, exp)) = crate::macros::expand(db, file_id, macro_call) { | 18 | if let Some((off, exp)) = hir::MacroDef::ast_expand(macro_call) { |
19 | let mapped_ranges = ra_editor::highlight(exp.syntax().borrowed()) | 19 | let mapped_ranges = ra_editor::highlight(exp.syntax().borrowed()) |
20 | .into_iter() | 20 | .into_iter() |
21 | .filter_map(|r| { | 21 | .filter_map(|r| { |
diff --git a/crates/ra_hir/src/db.rs b/crates/ra_hir/src/db.rs index 5a8ca3b47..242d0549d 100644 --- a/crates/ra_hir/src/db.rs +++ b/crates/ra_hir/src/db.rs | |||
@@ -8,6 +8,7 @@ use crate::{ | |||
8 | SourceFileItems, SourceItemId, | 8 | SourceFileItems, SourceItemId, |
9 | query_definitions, | 9 | query_definitions, |
10 | FnScopes, | 10 | FnScopes, |
11 | macros::{MacroInvocationLoc, MacroInvocationId, MacroInput, MacroDef, MacroExpansion}, | ||
11 | module::{ModuleId, ModuleTree, ModuleSource, | 12 | module::{ModuleId, ModuleTree, ModuleSource, |
12 | nameres::{ItemMap, InputModuleItems}}, | 13 | nameres::{ItemMap, InputModuleItems}}, |
13 | ty::{InferenceResult, Ty}, | 14 | ty::{InferenceResult, Ty}, |
@@ -18,7 +19,13 @@ salsa::query_group! { | |||
18 | 19 | ||
19 | pub trait HirDatabase: SyntaxDatabase | 20 | pub trait HirDatabase: SyntaxDatabase |
20 | + AsRef<LocationIntener<DefLoc, DefId>> | 21 | + AsRef<LocationIntener<DefLoc, DefId>> |
22 | + AsRef<LocationIntener<MacroInvocationLoc, MacroInvocationId>> | ||
21 | { | 23 | { |
24 | fn expand_macro_invocation(invoc: MacroInvocationId) -> Option<Arc<MacroExpansion>> { | ||
25 | type ExpandMacroInvocationQuery; | ||
26 | use fn crate::macros::expand_macro_invocation; | ||
27 | } | ||
28 | |||
22 | fn fn_scopes(def_id: DefId) -> Arc<FnScopes> { | 29 | fn fn_scopes(def_id: DefId) -> Arc<FnScopes> { |
23 | type FnScopesQuery; | 30 | type FnScopesQuery; |
24 | use fn query_definitions::fn_scopes; | 31 | use fn query_definitions::fn_scopes; |
diff --git a/crates/ra_hir/src/lib.rs b/crates/ra_hir/src/lib.rs index ce750299f..1bafb1c4d 100644 --- a/crates/ra_hir/src/lib.rs +++ b/crates/ra_hir/src/lib.rs | |||
@@ -46,7 +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 | macros::{MacroDef, MacroInput, MacroExpansion, MacroInvocationId, MacroInvocationLoc}, |
50 | module::{Module, ModuleId, Problem, nameres::{ItemMap, PerNs, Namespace}, ModuleScope, Resolution}, | 50 | module::{Module, ModuleId, Problem, nameres::{ItemMap, PerNs, Namespace}, ModuleScope, Resolution}, |
51 | function::{Function, FnScopes}, | 51 | function::{Function, FnScopes}, |
52 | adt::{Struct, Enum}, | 52 | adt::{Struct, Enum}, |
diff --git a/crates/ra_hir/src/macros.rs b/crates/ra_hir/src/macros.rs index ef6502524..f0b99cc1a 100644 --- a/crates/ra_hir/src/macros.rs +++ b/crates/ra_hir/src/macros.rs | |||
@@ -1,17 +1,108 @@ | |||
1 | use std::sync::Arc; | 1 | use std::sync::Arc; |
2 | 2 | ||
3 | use ra_db::{SyntaxDatabase, LocalSyntaxPtr}; | 3 | use ra_db::{LocalSyntaxPtr, LocationIntener}; |
4 | use ra_syntax::{ | 4 | use ra_syntax::{ |
5 | TextRange, TextUnit, SourceFileNode, AstNode, SyntaxNode, | 5 | TextRange, TextUnit, SourceFileNode, AstNode, SyntaxNode, |
6 | ast, | 6 | ast, |
7 | }; | 7 | }; |
8 | 8 | ||
9 | use crate::{SourceRootId, module::ModuleId, SourceItemId, HirDatabase}; | ||
10 | |||
11 | /// Def's are a core concept of hir. A `Def` is an Item (function, module, etc) | ||
12 | /// in a specific module. | ||
13 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | ||
14 | pub struct MacroInvocationId(u32); | ||
15 | ra_db::impl_numeric_id!(MacroInvocationId); | ||
16 | |||
17 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | ||
18 | pub struct MacroInvocationLoc { | ||
19 | source_root_id: SourceRootId, | ||
20 | module_id: ModuleId, | ||
21 | source_item_id: SourceItemId, | ||
22 | } | ||
23 | |||
24 | impl MacroInvocationId { | ||
25 | pub(crate) fn loc( | ||
26 | self, | ||
27 | db: &impl AsRef<LocationIntener<MacroInvocationLoc, MacroInvocationId>>, | ||
28 | ) -> MacroInvocationLoc { | ||
29 | db.as_ref().id2loc(self) | ||
30 | } | ||
31 | } | ||
32 | |||
33 | impl MacroInvocationLoc { | ||
34 | #[allow(unused)] | ||
35 | pub(crate) fn id( | ||
36 | &self, | ||
37 | db: &impl AsRef<LocationIntener<MacroInvocationLoc, MacroInvocationId>>, | ||
38 | ) -> MacroInvocationId { | ||
39 | db.as_ref().loc2id(&self) | ||
40 | } | ||
41 | } | ||
42 | |||
9 | // Hard-coded defs for now :-( | 43 | // Hard-coded defs for now :-( |
10 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | 44 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] |
11 | pub enum MacroDef { | 45 | pub enum MacroDef { |
12 | CTry, | 46 | CTry, |
13 | } | 47 | } |
14 | 48 | ||
49 | impl MacroDef { | ||
50 | pub fn ast_expand(macro_call: ast::MacroCall) -> Option<(TextUnit, MacroExpansion)> { | ||
51 | let (def, input) = MacroDef::from_call(macro_call)?; | ||
52 | let exp = def.expand(input)?; | ||
53 | let off = macro_call.token_tree()?.syntax().range().start(); | ||
54 | Some((off, exp)) | ||
55 | } | ||
56 | |||
57 | fn from_call(macro_call: ast::MacroCall) -> Option<(MacroDef, MacroInput)> { | ||
58 | let def = { | ||
59 | let path = macro_call.path()?; | ||
60 | if path.qualifier().is_some() { | ||
61 | return None; | ||
62 | } | ||
63 | let name_ref = path.segment()?.name_ref()?; | ||
64 | if name_ref.text() != "ctry" { | ||
65 | return None; | ||
66 | } | ||
67 | MacroDef::CTry | ||
68 | }; | ||
69 | |||
70 | let input = { | ||
71 | let arg = macro_call.token_tree()?.syntax(); | ||
72 | MacroInput { | ||
73 | text: arg.text().to_string(), | ||
74 | } | ||
75 | }; | ||
76 | Some((def, input)) | ||
77 | } | ||
78 | |||
79 | fn expand(self, input: MacroInput) -> Option<MacroExpansion> { | ||
80 | let MacroDef::CTry = self; | ||
81 | let text = format!( | ||
82 | r" | ||
83 | fn dummy() {{ | ||
84 | match {} {{ | ||
85 | None => return Ok(None), | ||
86 | Some(it) => it, | ||
87 | }} | ||
88 | }}", | ||
89 | input.text | ||
90 | ); | ||
91 | let file = SourceFileNode::parse(&text); | ||
92 | let match_expr = file.syntax().descendants().find_map(ast::MatchExpr::cast)?; | ||
93 | let match_arg = match_expr.expr()?; | ||
94 | let ptr = LocalSyntaxPtr::new(match_arg.syntax()); | ||
95 | let src_range = TextRange::offset_len(0.into(), TextUnit::of_str(&input.text)); | ||
96 | let ranges_map = vec![(src_range, match_arg.syntax().range())]; | ||
97 | let res = MacroExpansion { | ||
98 | text, | ||
99 | ranges_map, | ||
100 | ptr, | ||
101 | }; | ||
102 | Some(res) | ||
103 | } | ||
104 | } | ||
105 | |||
15 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | 106 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] |
16 | pub struct MacroInput { | 107 | pub struct MacroInput { |
17 | // Should be token trees | 108 | // Should be token trees |
@@ -25,46 +116,6 @@ pub struct MacroExpansion { | |||
25 | ptr: LocalSyntaxPtr, | 116 | ptr: LocalSyntaxPtr, |
26 | } | 117 | } |
27 | 118 | ||
28 | salsa::query_group! { | ||
29 | |||
30 | pub trait MacroDatabase: SyntaxDatabase { | ||
31 | fn expand_macro(def: MacroDef, input: MacroInput) -> Option<Arc<MacroExpansion>> { | ||
32 | type ExpandMacroQuery; | ||
33 | } | ||
34 | } | ||
35 | |||
36 | } | ||
37 | |||
38 | fn expand_macro( | ||
39 | _db: &impl MacroDatabase, | ||
40 | def: MacroDef, | ||
41 | input: MacroInput, | ||
42 | ) -> Option<Arc<MacroExpansion>> { | ||
43 | let MacroDef::CTry = def; | ||
44 | let text = format!( | ||
45 | r" | ||
46 | fn dummy() {{ | ||
47 | match {} {{ | ||
48 | None => return Ok(None), | ||
49 | Some(it) => it, | ||
50 | }} | ||
51 | }}", | ||
52 | input.text | ||
53 | ); | ||
54 | let file = SourceFileNode::parse(&text); | ||
55 | let match_expr = file.syntax().descendants().find_map(ast::MatchExpr::cast)?; | ||
56 | let match_arg = match_expr.expr()?; | ||
57 | let ptr = LocalSyntaxPtr::new(match_arg.syntax()); | ||
58 | let src_range = TextRange::offset_len(0.into(), TextUnit::of_str(&input.text)); | ||
59 | let ranges_map = vec![(src_range, match_arg.syntax().range())]; | ||
60 | let res = MacroExpansion { | ||
61 | text, | ||
62 | ranges_map, | ||
63 | ptr, | ||
64 | }; | ||
65 | Some(Arc::new(res)) | ||
66 | } | ||
67 | |||
68 | impl MacroExpansion { | 119 | impl MacroExpansion { |
69 | pub fn file(&self) -> SourceFileNode { | 120 | pub fn file(&self) -> SourceFileNode { |
70 | SourceFileNode::parse(&self.text) | 121 | SourceFileNode::parse(&self.text) |
@@ -96,3 +147,16 @@ impl MacroExpansion { | |||
96 | None | 147 | None |
97 | } | 148 | } |
98 | } | 149 | } |
150 | |||
151 | pub(crate) fn expand_macro_invocation( | ||
152 | db: &impl HirDatabase, | ||
153 | invoc: MacroInvocationId, | ||
154 | ) -> Option<Arc<MacroExpansion>> { | ||
155 | let loc = invoc.loc(db); | ||
156 | let syntax = db.file_item(loc.source_item_id); | ||
157 | let syntax = syntax.borrowed(); | ||
158 | let macro_call = ast::MacroCall::cast(syntax).unwrap(); | ||
159 | |||
160 | let (def, input) = MacroDef::from_call(macro_call)?; | ||
161 | def.expand(input).map(Arc::new) | ||
162 | } | ||