diff options
author | Aleksey Kladov <[email protected]> | 2019-01-01 15:11:04 +0000 |
---|---|---|
committer | Aleksey Kladov <[email protected]> | 2019-01-01 19:15:35 +0000 |
commit | b2fec18098b6a99613012d185801fed72e424997 (patch) | |
tree | 5ee6cde2ebd31d18f8fda189ca3709a01fa65dee /crates/ra_hir | |
parent | 57030f587bb0bbe4dea9a97016b4e0f49a7ef5f3 (diff) |
move more macros to hir
Diffstat (limited to 'crates/ra_hir')
-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 |
3 files changed, 113 insertions, 42 deletions
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 | } | ||