diff options
Diffstat (limited to 'crates')
-rw-r--r-- | crates/ra_hir_def/src/lib.rs | 23 | ||||
-rw-r--r-- | crates/ra_hir_expand/src/builtin_derive.rs | 24 | ||||
-rw-r--r-- | crates/ra_hir_expand/src/builtin_macro.rs | 126 | ||||
-rw-r--r-- | crates/ra_hir_expand/src/db.rs | 23 | ||||
-rw-r--r-- | crates/ra_hir_expand/src/eager.rs | 93 | ||||
-rw-r--r-- | crates/ra_hir_expand/src/hygiene.rs | 23 | ||||
-rw-r--r-- | crates/ra_hir_expand/src/lib.rs | 59 | ||||
-rw-r--r-- | crates/ra_hir_expand/src/name.rs | 1 | ||||
-rw-r--r-- | crates/ra_parser/src/lib.rs | 2 | ||||
-rw-r--r-- | crates/ra_syntax/src/ast/make.rs | 8 |
10 files changed, 305 insertions, 77 deletions
diff --git a/crates/ra_hir_def/src/lib.rs b/crates/ra_hir_def/src/lib.rs index c9b14d0c8..a3d617e1f 100644 --- a/crates/ra_hir_def/src/lib.rs +++ b/crates/ra_hir_def/src/lib.rs | |||
@@ -47,8 +47,8 @@ mod marks; | |||
47 | use std::hash::Hash; | 47 | use std::hash::Hash; |
48 | 48 | ||
49 | use hir_expand::{ | 49 | use hir_expand::{ |
50 | ast_id_map::FileAstId, db::AstDatabase, hygiene::Hygiene, AstId, HirFileId, InFile, | 50 | ast_id_map::FileAstId, db::AstDatabase, eager::expand_eager_macro, hygiene::Hygiene, AstId, |
51 | MacroCallId, MacroCallKind, MacroDefId, | 51 | HirFileId, InFile, MacroCallId, MacroCallKind, MacroDefId, MacroDefKind, |
52 | }; | 52 | }; |
53 | use ra_arena::{impl_arena_id, RawId}; | 53 | use ra_arena::{impl_arena_id, RawId}; |
54 | use ra_db::{impl_intern_key, salsa, CrateId}; | 54 | use ra_db::{impl_intern_key, salsa, CrateId}; |
@@ -459,8 +459,21 @@ impl AsMacroCall for AstIdWithPath<ast::MacroCall> { | |||
459 | db: &impl AstDatabase, | 459 | db: &impl AstDatabase, |
460 | resolver: impl Fn(path::ModPath) -> Option<MacroDefId>, | 460 | resolver: impl Fn(path::ModPath) -> Option<MacroDefId>, |
461 | ) -> Option<MacroCallId> { | 461 | ) -> Option<MacroCallId> { |
462 | let def = resolver(self.path.clone())?; | 462 | let def: MacroDefId = resolver(self.path.clone())?; |
463 | Some(def.as_call_id(db, MacroCallKind::FnLike(self.ast_id))) | 463 | |
464 | if let MacroDefKind::BuiltInEager(_) = def.kind { | ||
465 | let macro_call = InFile::new(self.ast_id.file_id, self.ast_id.to_node(db)); | ||
466 | let hygiene = Hygiene::new(db, self.ast_id.file_id); | ||
467 | |||
468 | Some( | ||
469 | expand_eager_macro(db, macro_call, def, &|path: ast::Path| { | ||
470 | resolver(path::ModPath::from_src(path, &hygiene)?) | ||
471 | })? | ||
472 | .into(), | ||
473 | ) | ||
474 | } else { | ||
475 | Some(def.as_lazy_macro(db, MacroCallKind::FnLike(self.ast_id)).into()) | ||
476 | } | ||
464 | } | 477 | } |
465 | } | 478 | } |
466 | 479 | ||
@@ -471,6 +484,6 @@ impl AsMacroCall for AstIdWithPath<ast::ModuleItem> { | |||
471 | resolver: impl Fn(path::ModPath) -> Option<MacroDefId>, | 484 | resolver: impl Fn(path::ModPath) -> Option<MacroDefId>, |
472 | ) -> Option<MacroCallId> { | 485 | ) -> Option<MacroCallId> { |
473 | let def = resolver(self.path.clone())?; | 486 | let def = resolver(self.path.clone())?; |
474 | Some(def.as_call_id(db, MacroCallKind::Attr(self.ast_id))) | 487 | Some(def.as_lazy_macro(db, MacroCallKind::Attr(self.ast_id)).into()) |
475 | } | 488 | } |
476 | } | 489 | } |
diff --git a/crates/ra_hir_expand/src/builtin_derive.rs b/crates/ra_hir_expand/src/builtin_derive.rs index 0b70fb9e1..87224481c 100644 --- a/crates/ra_hir_expand/src/builtin_derive.rs +++ b/crates/ra_hir_expand/src/builtin_derive.rs | |||
@@ -9,7 +9,7 @@ use ra_syntax::{ | |||
9 | }; | 9 | }; |
10 | 10 | ||
11 | use crate::db::AstDatabase; | 11 | use crate::db::AstDatabase; |
12 | use crate::{name, quote, MacroCallId, MacroDefId, MacroDefKind}; | 12 | use crate::{name, quote, LazyMacroId, MacroDefId, MacroDefKind}; |
13 | 13 | ||
14 | macro_rules! register_builtin { | 14 | macro_rules! register_builtin { |
15 | ( $($trait:ident => $expand:ident),* ) => { | 15 | ( $($trait:ident => $expand:ident),* ) => { |
@@ -22,7 +22,7 @@ macro_rules! register_builtin { | |||
22 | pub fn expand( | 22 | pub fn expand( |
23 | &self, | 23 | &self, |
24 | db: &dyn AstDatabase, | 24 | db: &dyn AstDatabase, |
25 | id: MacroCallId, | 25 | id: LazyMacroId, |
26 | tt: &tt::Subtree, | 26 | tt: &tt::Subtree, |
27 | ) -> Result<tt::Subtree, mbe::ExpandError> { | 27 | ) -> Result<tt::Subtree, mbe::ExpandError> { |
28 | let expander = match *self { | 28 | let expander = match *self { |
@@ -155,7 +155,7 @@ fn expand_simple_derive( | |||
155 | 155 | ||
156 | fn copy_expand( | 156 | fn copy_expand( |
157 | _db: &dyn AstDatabase, | 157 | _db: &dyn AstDatabase, |
158 | _id: MacroCallId, | 158 | _id: LazyMacroId, |
159 | tt: &tt::Subtree, | 159 | tt: &tt::Subtree, |
160 | ) -> Result<tt::Subtree, mbe::ExpandError> { | 160 | ) -> Result<tt::Subtree, mbe::ExpandError> { |
161 | expand_simple_derive(tt, quote! { std::marker::Copy }) | 161 | expand_simple_derive(tt, quote! { std::marker::Copy }) |
@@ -163,7 +163,7 @@ fn copy_expand( | |||
163 | 163 | ||
164 | fn clone_expand( | 164 | fn clone_expand( |
165 | _db: &dyn AstDatabase, | 165 | _db: &dyn AstDatabase, |
166 | _id: MacroCallId, | 166 | _id: LazyMacroId, |
167 | tt: &tt::Subtree, | 167 | tt: &tt::Subtree, |
168 | ) -> Result<tt::Subtree, mbe::ExpandError> { | 168 | ) -> Result<tt::Subtree, mbe::ExpandError> { |
169 | expand_simple_derive(tt, quote! { std::clone::Clone }) | 169 | expand_simple_derive(tt, quote! { std::clone::Clone }) |
@@ -171,7 +171,7 @@ fn clone_expand( | |||
171 | 171 | ||
172 | fn default_expand( | 172 | fn default_expand( |
173 | _db: &dyn AstDatabase, | 173 | _db: &dyn AstDatabase, |
174 | _id: MacroCallId, | 174 | _id: LazyMacroId, |
175 | tt: &tt::Subtree, | 175 | tt: &tt::Subtree, |
176 | ) -> Result<tt::Subtree, mbe::ExpandError> { | 176 | ) -> Result<tt::Subtree, mbe::ExpandError> { |
177 | expand_simple_derive(tt, quote! { std::default::Default }) | 177 | expand_simple_derive(tt, quote! { std::default::Default }) |
@@ -179,7 +179,7 @@ fn default_expand( | |||
179 | 179 | ||
180 | fn debug_expand( | 180 | fn debug_expand( |
181 | _db: &dyn AstDatabase, | 181 | _db: &dyn AstDatabase, |
182 | _id: MacroCallId, | 182 | _id: LazyMacroId, |
183 | tt: &tt::Subtree, | 183 | tt: &tt::Subtree, |
184 | ) -> Result<tt::Subtree, mbe::ExpandError> { | 184 | ) -> Result<tt::Subtree, mbe::ExpandError> { |
185 | expand_simple_derive(tt, quote! { std::fmt::Debug }) | 185 | expand_simple_derive(tt, quote! { std::fmt::Debug }) |
@@ -187,7 +187,7 @@ fn debug_expand( | |||
187 | 187 | ||
188 | fn hash_expand( | 188 | fn hash_expand( |
189 | _db: &dyn AstDatabase, | 189 | _db: &dyn AstDatabase, |
190 | _id: MacroCallId, | 190 | _id: LazyMacroId, |
191 | tt: &tt::Subtree, | 191 | tt: &tt::Subtree, |
192 | ) -> Result<tt::Subtree, mbe::ExpandError> { | 192 | ) -> Result<tt::Subtree, mbe::ExpandError> { |
193 | expand_simple_derive(tt, quote! { std::hash::Hash }) | 193 | expand_simple_derive(tt, quote! { std::hash::Hash }) |
@@ -195,7 +195,7 @@ fn hash_expand( | |||
195 | 195 | ||
196 | fn eq_expand( | 196 | fn eq_expand( |
197 | _db: &dyn AstDatabase, | 197 | _db: &dyn AstDatabase, |
198 | _id: MacroCallId, | 198 | _id: LazyMacroId, |
199 | tt: &tt::Subtree, | 199 | tt: &tt::Subtree, |
200 | ) -> Result<tt::Subtree, mbe::ExpandError> { | 200 | ) -> Result<tt::Subtree, mbe::ExpandError> { |
201 | expand_simple_derive(tt, quote! { std::cmp::Eq }) | 201 | expand_simple_derive(tt, quote! { std::cmp::Eq }) |
@@ -203,7 +203,7 @@ fn eq_expand( | |||
203 | 203 | ||
204 | fn partial_eq_expand( | 204 | fn partial_eq_expand( |
205 | _db: &dyn AstDatabase, | 205 | _db: &dyn AstDatabase, |
206 | _id: MacroCallId, | 206 | _id: LazyMacroId, |
207 | tt: &tt::Subtree, | 207 | tt: &tt::Subtree, |
208 | ) -> Result<tt::Subtree, mbe::ExpandError> { | 208 | ) -> Result<tt::Subtree, mbe::ExpandError> { |
209 | expand_simple_derive(tt, quote! { std::cmp::PartialEq }) | 209 | expand_simple_derive(tt, quote! { std::cmp::PartialEq }) |
@@ -211,7 +211,7 @@ fn partial_eq_expand( | |||
211 | 211 | ||
212 | fn ord_expand( | 212 | fn ord_expand( |
213 | _db: &dyn AstDatabase, | 213 | _db: &dyn AstDatabase, |
214 | _id: MacroCallId, | 214 | _id: LazyMacroId, |
215 | tt: &tt::Subtree, | 215 | tt: &tt::Subtree, |
216 | ) -> Result<tt::Subtree, mbe::ExpandError> { | 216 | ) -> Result<tt::Subtree, mbe::ExpandError> { |
217 | expand_simple_derive(tt, quote! { std::cmp::Ord }) | 217 | expand_simple_derive(tt, quote! { std::cmp::Ord }) |
@@ -219,7 +219,7 @@ fn ord_expand( | |||
219 | 219 | ||
220 | fn partial_ord_expand( | 220 | fn partial_ord_expand( |
221 | _db: &dyn AstDatabase, | 221 | _db: &dyn AstDatabase, |
222 | _id: MacroCallId, | 222 | _id: LazyMacroId, |
223 | tt: &tt::Subtree, | 223 | tt: &tt::Subtree, |
224 | ) -> Result<tt::Subtree, mbe::ExpandError> { | 224 | ) -> Result<tt::Subtree, mbe::ExpandError> { |
225 | expand_simple_derive(tt, quote! { std::cmp::PartialOrd }) | 225 | expand_simple_derive(tt, quote! { std::cmp::PartialOrd }) |
@@ -228,7 +228,7 @@ fn partial_ord_expand( | |||
228 | #[cfg(test)] | 228 | #[cfg(test)] |
229 | mod tests { | 229 | mod tests { |
230 | use super::*; | 230 | use super::*; |
231 | use crate::{test_db::TestDB, AstId, MacroCallKind, MacroCallLoc}; | 231 | use crate::{test_db::TestDB, AstId, MacroCallId, MacroCallKind, MacroCallLoc}; |
232 | use ra_db::{fixture::WithFixture, SourceDatabase}; | 232 | use ra_db::{fixture::WithFixture, SourceDatabase}; |
233 | 233 | ||
234 | fn expand_builtin_derive(s: &str, expander: BuiltinDeriveExpander) -> String { | 234 | fn expand_builtin_derive(s: &str, expander: BuiltinDeriveExpander) -> String { |
diff --git a/crates/ra_hir_expand/src/builtin_macro.rs b/crates/ra_hir_expand/src/builtin_macro.rs index d91aa4ffa..1f380b571 100644 --- a/crates/ra_hir_expand/src/builtin_macro.rs +++ b/crates/ra_hir_expand/src/builtin_macro.rs | |||
@@ -1,24 +1,31 @@ | |||
1 | //! Builtin macro | 1 | //! Builtin macro |
2 | use crate::db::AstDatabase; | 2 | use crate::db::AstDatabase; |
3 | use crate::{ | 3 | use crate::{ |
4 | ast::{self}, | 4 | ast::{self, AstToken, HasStringValue}, |
5 | name, AstId, CrateId, MacroCallId, MacroDefId, MacroDefKind, TextUnit, | 5 | name, AstId, CrateId, MacroDefId, MacroDefKind, TextUnit, |
6 | }; | 6 | }; |
7 | 7 | ||
8 | use crate::quote; | 8 | use crate::{quote, LazyMacroId}; |
9 | use either::Either; | ||
10 | use ra_parser::FragmentKind; | ||
9 | 11 | ||
10 | macro_rules! register_builtin { | 12 | macro_rules! register_builtin { |
11 | ( $(($name:ident, $kind: ident) => $expand:ident),* ) => { | 13 | ( LAZY: $(($name:ident, $kind: ident) => $expand:ident),* , EAGER: $(($e_name:ident, $e_kind: ident) => $e_expand:ident),* ) => { |
12 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | 14 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] |
13 | pub enum BuiltinFnLikeExpander { | 15 | pub enum BuiltinFnLikeExpander { |
14 | $($kind),* | 16 | $($kind),* |
15 | } | 17 | } |
16 | 18 | ||
19 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | ||
20 | pub enum EagerExpander { | ||
21 | $($e_kind),* | ||
22 | } | ||
23 | |||
17 | impl BuiltinFnLikeExpander { | 24 | impl BuiltinFnLikeExpander { |
18 | pub fn expand( | 25 | pub fn expand( |
19 | &self, | 26 | &self, |
20 | db: &dyn AstDatabase, | 27 | db: &dyn AstDatabase, |
21 | id: MacroCallId, | 28 | id: LazyMacroId, |
22 | tt: &tt::Subtree, | 29 | tt: &tt::Subtree, |
23 | ) -> Result<tt::Subtree, mbe::ExpandError> { | 30 | ) -> Result<tt::Subtree, mbe::ExpandError> { |
24 | let expander = match *self { | 31 | let expander = match *self { |
@@ -26,28 +33,54 @@ macro_rules! register_builtin { | |||
26 | }; | 33 | }; |
27 | expander(db, id, tt) | 34 | expander(db, id, tt) |
28 | } | 35 | } |
36 | } | ||
29 | 37 | ||
30 | fn by_name(ident: &name::Name) -> Option<BuiltinFnLikeExpander> { | 38 | impl EagerExpander { |
31 | match ident { | 39 | pub fn expand( |
32 | $( id if id == &name::name![$name] => Some(BuiltinFnLikeExpander::$kind), )* | 40 | &self, |
33 | _ => return None, | 41 | tt: &tt::Subtree, |
34 | } | 42 | ) -> Result<(tt::Subtree, FragmentKind), mbe::ExpandError> { |
43 | let expander = match *self { | ||
44 | $( EagerExpander::$e_kind => $e_expand, )* | ||
45 | }; | ||
46 | expander(tt) | ||
35 | } | 47 | } |
36 | } | 48 | } |
37 | 49 | ||
38 | pub fn find_builtin_macro( | 50 | fn find_by_name(ident: &name::Name) -> Option<Either<BuiltinFnLikeExpander, EagerExpander>> { |
39 | ident: &name::Name, | 51 | match ident { |
40 | krate: CrateId, | 52 | $( id if id == &name::name![$name] => Some(Either::Left(BuiltinFnLikeExpander::$kind)), )* |
41 | ast_id: AstId<ast::MacroCall>, | 53 | $( id if id == &name::name![$e_name] => Some(Either::Right(EagerExpander::$e_kind)), )* |
42 | ) -> Option<MacroDefId> { | 54 | _ => return None, |
43 | let kind = BuiltinFnLikeExpander::by_name(ident)?; | 55 | } |
44 | |||
45 | Some(MacroDefId { krate: Some(krate), ast_id: Some(ast_id), kind: MacroDefKind::BuiltIn(kind) }) | ||
46 | } | 56 | } |
47 | }; | 57 | }; |
48 | } | 58 | } |
49 | 59 | ||
60 | pub fn find_builtin_macro( | ||
61 | ident: &name::Name, | ||
62 | krate: CrateId, | ||
63 | ast_id: AstId<ast::MacroCall>, | ||
64 | ) -> Option<MacroDefId> { | ||
65 | let kind = find_by_name(ident)?; | ||
66 | |||
67 | match kind { | ||
68 | Either::Left(kind) => Some(MacroDefId { | ||
69 | krate: Some(krate), | ||
70 | ast_id: Some(ast_id), | ||
71 | kind: MacroDefKind::BuiltIn(kind), | ||
72 | }), | ||
73 | Either::Right(kind) => Some(MacroDefId { | ||
74 | krate: Some(krate), | ||
75 | ast_id: Some(ast_id), | ||
76 | kind: MacroDefKind::BuiltInEager(kind), | ||
77 | }), | ||
78 | } | ||
79 | } | ||
80 | |||
50 | register_builtin! { | 81 | register_builtin! { |
82 | LAZY: | ||
83 | |||
51 | (column, Column) => column_expand, | 84 | (column, Column) => column_expand, |
52 | (compile_error, CompileError) => compile_error_expand, | 85 | (compile_error, CompileError) => compile_error_expand, |
53 | (file, File) => file_expand, | 86 | (file, File) => file_expand, |
@@ -58,12 +91,16 @@ register_builtin! { | |||
58 | (option_env, OptionEnv) => option_env_expand, | 91 | (option_env, OptionEnv) => option_env_expand, |
59 | // format_args_nl only differs in that it adds a newline in the end, | 92 | // format_args_nl only differs in that it adds a newline in the end, |
60 | // so we use the same stub expansion for now | 93 | // so we use the same stub expansion for now |
61 | (format_args_nl, FormatArgsNl) => format_args_expand | 94 | (format_args_nl, FormatArgsNl) => format_args_expand, |
95 | |||
96 | EAGER: | ||
97 | // eagers | ||
98 | (concat, Concat) => concat_expand | ||
62 | } | 99 | } |
63 | 100 | ||
64 | fn line_expand( | 101 | fn line_expand( |
65 | _db: &dyn AstDatabase, | 102 | _db: &dyn AstDatabase, |
66 | _id: MacroCallId, | 103 | _id: LazyMacroId, |
67 | _tt: &tt::Subtree, | 104 | _tt: &tt::Subtree, |
68 | ) -> Result<tt::Subtree, mbe::ExpandError> { | 105 | ) -> Result<tt::Subtree, mbe::ExpandError> { |
69 | // dummy implementation for type-checking purposes | 106 | // dummy implementation for type-checking purposes |
@@ -77,13 +114,9 @@ fn line_expand( | |||
77 | 114 | ||
78 | fn stringify_expand( | 115 | fn stringify_expand( |
79 | db: &dyn AstDatabase, | 116 | db: &dyn AstDatabase, |
80 | id: MacroCallId, | 117 | id: LazyMacroId, |
81 | _tt: &tt::Subtree, | 118 | _tt: &tt::Subtree, |
82 | ) -> Result<tt::Subtree, mbe::ExpandError> { | 119 | ) -> Result<tt::Subtree, mbe::ExpandError> { |
83 | let id = match id { | ||
84 | MacroCallId::LazyMacro(id) => id, | ||
85 | }; | ||
86 | |||
87 | let loc = db.lookup_intern_macro(id); | 120 | let loc = db.lookup_intern_macro(id); |
88 | 121 | ||
89 | let macro_content = { | 122 | let macro_content = { |
@@ -103,7 +136,7 @@ fn stringify_expand( | |||
103 | 136 | ||
104 | fn env_expand( | 137 | fn env_expand( |
105 | _db: &dyn AstDatabase, | 138 | _db: &dyn AstDatabase, |
106 | _id: MacroCallId, | 139 | _id: LazyMacroId, |
107 | _tt: &tt::Subtree, | 140 | _tt: &tt::Subtree, |
108 | ) -> Result<tt::Subtree, mbe::ExpandError> { | 141 | ) -> Result<tt::Subtree, mbe::ExpandError> { |
109 | // dummy implementation for type-checking purposes | 142 | // dummy implementation for type-checking purposes |
@@ -114,7 +147,7 @@ fn env_expand( | |||
114 | 147 | ||
115 | fn option_env_expand( | 148 | fn option_env_expand( |
116 | _db: &dyn AstDatabase, | 149 | _db: &dyn AstDatabase, |
117 | _id: MacroCallId, | 150 | _id: LazyMacroId, |
118 | _tt: &tt::Subtree, | 151 | _tt: &tt::Subtree, |
119 | ) -> Result<tt::Subtree, mbe::ExpandError> { | 152 | ) -> Result<tt::Subtree, mbe::ExpandError> { |
120 | // dummy implementation for type-checking purposes | 153 | // dummy implementation for type-checking purposes |
@@ -125,7 +158,7 @@ fn option_env_expand( | |||
125 | 158 | ||
126 | fn column_expand( | 159 | fn column_expand( |
127 | _db: &dyn AstDatabase, | 160 | _db: &dyn AstDatabase, |
128 | _id: MacroCallId, | 161 | _id: LazyMacroId, |
129 | _tt: &tt::Subtree, | 162 | _tt: &tt::Subtree, |
130 | ) -> Result<tt::Subtree, mbe::ExpandError> { | 163 | ) -> Result<tt::Subtree, mbe::ExpandError> { |
131 | // dummy implementation for type-checking purposes | 164 | // dummy implementation for type-checking purposes |
@@ -139,7 +172,7 @@ fn column_expand( | |||
139 | 172 | ||
140 | fn file_expand( | 173 | fn file_expand( |
141 | _db: &dyn AstDatabase, | 174 | _db: &dyn AstDatabase, |
142 | _id: MacroCallId, | 175 | _id: LazyMacroId, |
143 | _tt: &tt::Subtree, | 176 | _tt: &tt::Subtree, |
144 | ) -> Result<tt::Subtree, mbe::ExpandError> { | 177 | ) -> Result<tt::Subtree, mbe::ExpandError> { |
145 | // FIXME: RA purposefully lacks knowledge of absolute file names | 178 | // FIXME: RA purposefully lacks knowledge of absolute file names |
@@ -155,7 +188,7 @@ fn file_expand( | |||
155 | 188 | ||
156 | fn compile_error_expand( | 189 | fn compile_error_expand( |
157 | _db: &dyn AstDatabase, | 190 | _db: &dyn AstDatabase, |
158 | _id: MacroCallId, | 191 | _id: LazyMacroId, |
159 | tt: &tt::Subtree, | 192 | tt: &tt::Subtree, |
160 | ) -> Result<tt::Subtree, mbe::ExpandError> { | 193 | ) -> Result<tt::Subtree, mbe::ExpandError> { |
161 | if tt.count() == 1 { | 194 | if tt.count() == 1 { |
@@ -172,7 +205,7 @@ fn compile_error_expand( | |||
172 | 205 | ||
173 | fn format_args_expand( | 206 | fn format_args_expand( |
174 | _db: &dyn AstDatabase, | 207 | _db: &dyn AstDatabase, |
175 | _id: MacroCallId, | 208 | _id: LazyMacroId, |
176 | tt: &tt::Subtree, | 209 | tt: &tt::Subtree, |
177 | ) -> Result<tt::Subtree, mbe::ExpandError> { | 210 | ) -> Result<tt::Subtree, mbe::ExpandError> { |
178 | // We expand `format_args!("", a1, a2)` to | 211 | // We expand `format_args!("", a1, a2)` to |
@@ -212,23 +245,44 @@ fn format_args_expand( | |||
212 | Ok(expanded) | 245 | Ok(expanded) |
213 | } | 246 | } |
214 | 247 | ||
248 | fn unquote_str(lit: &tt::Literal) -> Option<String> { | ||
249 | let lit = ast::make::tokens::literal(&lit.to_string()); | ||
250 | let token = ast::String::cast(lit)?; | ||
251 | token.value() | ||
252 | } | ||
253 | |||
254 | fn concat_expand(tt: &tt::Subtree) -> Result<(tt::Subtree, FragmentKind), mbe::ExpandError> { | ||
255 | let mut text = String::new(); | ||
256 | for (i, t) in tt.token_trees.iter().enumerate() { | ||
257 | match t { | ||
258 | tt::TokenTree::Leaf(tt::Leaf::Literal(it)) if i % 2 == 0 => { | ||
259 | text += &unquote_str(&it).ok_or_else(|| mbe::ExpandError::ConversionError)?; | ||
260 | } | ||
261 | tt::TokenTree::Leaf(tt::Leaf::Punct(punct)) if i % 2 == 1 && punct.char == ',' => (), | ||
262 | _ => return Err(mbe::ExpandError::UnexpectedToken), | ||
263 | } | ||
264 | } | ||
265 | |||
266 | Ok((quote!(#text), FragmentKind::Expr)) | ||
267 | } | ||
268 | |||
215 | #[cfg(test)] | 269 | #[cfg(test)] |
216 | mod tests { | 270 | mod tests { |
217 | use super::*; | 271 | use super::*; |
218 | use crate::{name::AsName, test_db::TestDB, AstNode, MacroCallKind, MacroCallLoc}; | 272 | use crate::{name::AsName, test_db::TestDB, AstNode, MacroCallId, MacroCallKind, MacroCallLoc}; |
219 | use ra_db::{fixture::WithFixture, SourceDatabase}; | 273 | use ra_db::{fixture::WithFixture, SourceDatabase}; |
220 | use ra_syntax::ast::NameOwner; | 274 | use ra_syntax::ast::NameOwner; |
221 | 275 | ||
222 | fn expand_builtin_macro(s: &str) -> String { | 276 | fn expand_builtin_macro(ra_fixture: &str) -> String { |
223 | let (db, file_id) = TestDB::with_single_file(&s); | 277 | let (db, file_id) = TestDB::with_single_file(&ra_fixture); |
224 | let parsed = db.parse(file_id); | 278 | let parsed = db.parse(file_id); |
225 | let macro_calls: Vec<_> = | 279 | let macro_calls: Vec<_> = |
226 | parsed.syntax_node().descendants().filter_map(ast::MacroCall::cast).collect(); | 280 | parsed.syntax_node().descendants().filter_map(ast::MacroCall::cast).collect(); |
227 | 281 | ||
228 | let ast_id_map = db.ast_id_map(file_id.into()); | 282 | let ast_id_map = db.ast_id_map(file_id.into()); |
229 | 283 | ||
230 | let expander = | 284 | let expander = find_by_name(¯o_calls[0].name().unwrap().as_name()).unwrap(); |
231 | BuiltinFnLikeExpander::by_name(¯o_calls[0].name().unwrap().as_name()).unwrap(); | 285 | let expander = expander.left().unwrap(); |
232 | 286 | ||
233 | // the first one should be a macro_rules | 287 | // the first one should be a macro_rules |
234 | let def = MacroDefId { | 288 | let def = MacroDefId { |
diff --git a/crates/ra_hir_expand/src/db.rs b/crates/ra_hir_expand/src/db.rs index b695c5b8d..ac8256a84 100644 --- a/crates/ra_hir_expand/src/db.rs +++ b/crates/ra_hir_expand/src/db.rs | |||
@@ -9,8 +9,9 @@ use ra_prof::profile; | |||
9 | use ra_syntax::{AstNode, Parse, SyntaxKind::*, SyntaxNode}; | 9 | use ra_syntax::{AstNode, Parse, SyntaxKind::*, SyntaxNode}; |
10 | 10 | ||
11 | use crate::{ | 11 | use crate::{ |
12 | ast_id_map::AstIdMap, BuiltinDeriveExpander, BuiltinFnLikeExpander, HirFileId, HirFileIdRepr, | 12 | ast_id_map::AstIdMap, BuiltinDeriveExpander, BuiltinFnLikeExpander, EagerCallLoc, EagerMacroId, |
13 | LazyMacroId, MacroCallId, MacroCallLoc, MacroDefId, MacroDefKind, MacroFile, | 13 | HirFileId, HirFileIdRepr, LazyMacroId, MacroCallId, MacroCallLoc, MacroDefId, MacroDefKind, |
14 | MacroFile, | ||
14 | }; | 15 | }; |
15 | 16 | ||
16 | #[derive(Debug, Clone, Eq, PartialEq)] | 17 | #[derive(Debug, Clone, Eq, PartialEq)] |
@@ -24,7 +25,7 @@ impl TokenExpander { | |||
24 | pub fn expand( | 25 | pub fn expand( |
25 | &self, | 26 | &self, |
26 | db: &dyn AstDatabase, | 27 | db: &dyn AstDatabase, |
27 | id: MacroCallId, | 28 | id: LazyMacroId, |
28 | tt: &tt::Subtree, | 29 | tt: &tt::Subtree, |
29 | ) -> Result<tt::Subtree, mbe::ExpandError> { | 30 | ) -> Result<tt::Subtree, mbe::ExpandError> { |
30 | match self { | 31 | match self { |
@@ -66,6 +67,9 @@ pub trait AstDatabase: SourceDatabase { | |||
66 | fn parse_macro(&self, macro_file: MacroFile) | 67 | fn parse_macro(&self, macro_file: MacroFile) |
67 | -> Option<(Parse<SyntaxNode>, Arc<mbe::TokenMap>)>; | 68 | -> Option<(Parse<SyntaxNode>, Arc<mbe::TokenMap>)>; |
68 | fn macro_expand(&self, macro_call: MacroCallId) -> Result<Arc<tt::Subtree>, String>; | 69 | fn macro_expand(&self, macro_call: MacroCallId) -> Result<Arc<tt::Subtree>, String>; |
70 | |||
71 | #[salsa::interned] | ||
72 | fn intern_eager_expansion(&self, eager: EagerCallLoc) -> EagerMacroId; | ||
69 | } | 73 | } |
70 | 74 | ||
71 | pub(crate) fn ast_id_map(db: &dyn AstDatabase, file_id: HirFileId) -> Arc<AstIdMap> { | 75 | pub(crate) fn ast_id_map(db: &dyn AstDatabase, file_id: HirFileId) -> Arc<AstIdMap> { |
@@ -101,6 +105,7 @@ pub(crate) fn macro_def( | |||
101 | MacroDefKind::BuiltInDerive(expander) => { | 105 | MacroDefKind::BuiltInDerive(expander) => { |
102 | Some(Arc::new((TokenExpander::BuiltinDerive(expander), mbe::TokenMap::default()))) | 106 | Some(Arc::new((TokenExpander::BuiltinDerive(expander), mbe::TokenMap::default()))) |
103 | } | 107 | } |
108 | MacroDefKind::BuiltInEager(_expander) => None, | ||
104 | } | 109 | } |
105 | } | 110 | } |
106 | 111 | ||
@@ -110,6 +115,10 @@ pub(crate) fn macro_arg( | |||
110 | ) -> Option<Arc<(tt::Subtree, mbe::TokenMap)>> { | 115 | ) -> Option<Arc<(tt::Subtree, mbe::TokenMap)>> { |
111 | let id = match id { | 116 | let id = match id { |
112 | MacroCallId::LazyMacro(id) => id, | 117 | MacroCallId::LazyMacro(id) => id, |
118 | MacroCallId::EagerMacro(_id) => { | ||
119 | // FIXME: support macro_arg for eager macro | ||
120 | return None; | ||
121 | } | ||
113 | }; | 122 | }; |
114 | let loc = db.lookup_intern_macro(id); | 123 | let loc = db.lookup_intern_macro(id); |
115 | let arg = loc.kind.arg(db)?; | 124 | let arg = loc.kind.arg(db)?; |
@@ -123,13 +132,16 @@ pub(crate) fn macro_expand( | |||
123 | ) -> Result<Arc<tt::Subtree>, String> { | 132 | ) -> Result<Arc<tt::Subtree>, String> { |
124 | let lazy_id = match id { | 133 | let lazy_id = match id { |
125 | MacroCallId::LazyMacro(id) => id, | 134 | MacroCallId::LazyMacro(id) => id, |
135 | MacroCallId::EagerMacro(id) => { | ||
136 | return Ok(db.lookup_intern_eager_expansion(id).subtree); | ||
137 | } | ||
126 | }; | 138 | }; |
127 | 139 | ||
128 | let loc = db.lookup_intern_macro(lazy_id); | 140 | let loc = db.lookup_intern_macro(lazy_id); |
129 | let macro_arg = db.macro_arg(id).ok_or("Fail to args in to tt::TokenTree")?; | 141 | let macro_arg = db.macro_arg(id).ok_or("Fail to args in to tt::TokenTree")?; |
130 | 142 | ||
131 | let macro_rules = db.macro_def(loc.def).ok_or("Fail to find macro definition")?; | 143 | let macro_rules = db.macro_def(loc.def).ok_or("Fail to find macro definition")?; |
132 | let tt = macro_rules.0.expand(db, id, ¯o_arg.0).map_err(|err| format!("{:?}", err))?; | 144 | let tt = macro_rules.0.expand(db, lazy_id, ¯o_arg.0).map_err(|err| format!("{:?}", err))?; |
133 | // Set a hard limit for the expanded tt | 145 | // Set a hard limit for the expanded tt |
134 | let count = tt.count(); | 146 | let count = tt.count(); |
135 | if count > 65536 { | 147 | if count > 65536 { |
@@ -177,6 +189,9 @@ pub(crate) fn parse_macro( | |||
177 | fn to_fragment_kind(db: &dyn AstDatabase, id: MacroCallId) -> FragmentKind { | 189 | fn to_fragment_kind(db: &dyn AstDatabase, id: MacroCallId) -> FragmentKind { |
178 | let lazy_id = match id { | 190 | let lazy_id = match id { |
179 | MacroCallId::LazyMacro(id) => id, | 191 | MacroCallId::LazyMacro(id) => id, |
192 | MacroCallId::EagerMacro(id) => { | ||
193 | return db.lookup_intern_eager_expansion(id).fragment; | ||
194 | } | ||
180 | }; | 195 | }; |
181 | let syn = db.lookup_intern_macro(lazy_id).kind.node(db).value; | 196 | let syn = db.lookup_intern_macro(lazy_id).kind.node(db).value; |
182 | 197 | ||
diff --git a/crates/ra_hir_expand/src/eager.rs b/crates/ra_hir_expand/src/eager.rs new file mode 100644 index 000000000..8caf8497e --- /dev/null +++ b/crates/ra_hir_expand/src/eager.rs | |||
@@ -0,0 +1,93 @@ | |||
1 | //! Eager expansion related utils | ||
2 | |||
3 | use crate::{ | ||
4 | ast::{self, AstNode}, | ||
5 | db::AstDatabase, | ||
6 | EagerCallLoc, EagerMacroId, InFile, MacroCallId, MacroCallKind, MacroDefId, MacroDefKind, | ||
7 | }; | ||
8 | |||
9 | use ra_parser::FragmentKind; | ||
10 | use ra_syntax::{algo::replace_descendants, SyntaxElement, SyntaxNode}; | ||
11 | use std::{collections::HashMap, sync::Arc}; | ||
12 | |||
13 | fn to_subtree(node: &SyntaxNode) -> Option<tt::Subtree> { | ||
14 | let mut subtree = mbe::syntax_node_to_token_tree(node)?.0; | ||
15 | subtree.delimiter = None; | ||
16 | Some(subtree) | ||
17 | } | ||
18 | |||
19 | fn lazy_expand( | ||
20 | db: &impl AstDatabase, | ||
21 | def: &MacroDefId, | ||
22 | macro_call: InFile<ast::MacroCall>, | ||
23 | ) -> Option<InFile<SyntaxNode>> { | ||
24 | let ast_id = db.ast_id_map(macro_call.file_id).ast_id(¯o_call.value); | ||
25 | |||
26 | let id: MacroCallId = | ||
27 | def.as_lazy_macro(db, MacroCallKind::FnLike(macro_call.with_value(ast_id))).into(); | ||
28 | |||
29 | db.parse_or_expand(id.as_file()).map(|node| InFile::new(id.as_file(), node)) | ||
30 | } | ||
31 | |||
32 | fn eager_macro_recur( | ||
33 | db: &impl AstDatabase, | ||
34 | curr: InFile<SyntaxNode>, | ||
35 | macro_resolver: &dyn Fn(ast::Path) -> Option<MacroDefId>, | ||
36 | ) -> Option<SyntaxNode> { | ||
37 | let mut original = curr.value.clone(); | ||
38 | |||
39 | let children = curr.value.descendants().filter_map(ast::MacroCall::cast); | ||
40 | let mut replaces: HashMap<SyntaxElement, SyntaxElement> = HashMap::default(); | ||
41 | |||
42 | // Collect replacement | ||
43 | for child in children { | ||
44 | let def: MacroDefId = macro_resolver(child.path()?)?; | ||
45 | let insert = match def.kind { | ||
46 | MacroDefKind::BuiltInEager(_) => { | ||
47 | let id: MacroCallId = | ||
48 | expand_eager_macro(db, curr.with_value(child.clone()), def, macro_resolver)? | ||
49 | .into(); | ||
50 | db.parse_or_expand(id.as_file())? | ||
51 | } | ||
52 | MacroDefKind::Declarative | ||
53 | | MacroDefKind::BuiltIn(_) | ||
54 | | MacroDefKind::BuiltInDerive(_) => { | ||
55 | let expanded = lazy_expand(db, &def, curr.with_value(child.clone()))?; | ||
56 | // replace macro inside | ||
57 | eager_macro_recur(db, expanded, macro_resolver)? | ||
58 | } | ||
59 | }; | ||
60 | |||
61 | replaces.insert(child.syntax().clone().into(), insert.into()); | ||
62 | } | ||
63 | |||
64 | if !replaces.is_empty() { | ||
65 | original = replace_descendants(&original, |n| replaces.get(n).cloned()); | ||
66 | } | ||
67 | |||
68 | Some(original) | ||
69 | } | ||
70 | |||
71 | pub fn expand_eager_macro( | ||
72 | db: &impl AstDatabase, | ||
73 | macro_call: InFile<ast::MacroCall>, | ||
74 | def: MacroDefId, | ||
75 | resolver: &dyn Fn(ast::Path) -> Option<MacroDefId>, | ||
76 | ) -> Option<EagerMacroId> { | ||
77 | let args = macro_call.value.token_tree()?; | ||
78 | let parsed_args = mbe::ast_to_token_tree(&args)?.0; | ||
79 | let parsed_args = mbe::token_tree_to_syntax_node(&parsed_args, FragmentKind::Expr).ok()?.0; | ||
80 | let result = eager_macro_recur(db, macro_call.with_value(parsed_args.syntax_node()), resolver)?; | ||
81 | |||
82 | let subtree = to_subtree(&result)?; | ||
83 | |||
84 | if let MacroDefKind::BuiltInEager(eager) = def.kind { | ||
85 | let (subtree, fragment) = eager.expand(&subtree).ok()?; | ||
86 | let eager = | ||
87 | EagerCallLoc { def, fragment, subtree: Arc::new(subtree), file_id: macro_call.file_id }; | ||
88 | |||
89 | Some(db.intern_eager_expansion(eager)) | ||
90 | } else { | ||
91 | None | ||
92 | } | ||
93 | } | ||
diff --git a/crates/ra_hir_expand/src/hygiene.rs b/crates/ra_hir_expand/src/hygiene.rs index ed0e7aa78..cb554ae4b 100644 --- a/crates/ra_hir_expand/src/hygiene.rs +++ b/crates/ra_hir_expand/src/hygiene.rs | |||
@@ -9,7 +9,7 @@ use ra_syntax::ast; | |||
9 | use crate::{ | 9 | use crate::{ |
10 | db::AstDatabase, | 10 | db::AstDatabase, |
11 | name::{AsName, Name}, | 11 | name::{AsName, Name}, |
12 | HirFileId, HirFileIdRepr, MacroDefKind, | 12 | HirFileId, HirFileIdRepr, MacroCallId, MacroDefKind, |
13 | }; | 13 | }; |
14 | 14 | ||
15 | #[derive(Debug)] | 15 | #[derive(Debug)] |
@@ -22,17 +22,18 @@ impl Hygiene { | |||
22 | pub fn new(db: &impl AstDatabase, file_id: HirFileId) -> Hygiene { | 22 | pub fn new(db: &impl AstDatabase, file_id: HirFileId) -> Hygiene { |
23 | let def_crate = match file_id.0 { | 23 | let def_crate = match file_id.0 { |
24 | HirFileIdRepr::FileId(_) => None, | 24 | HirFileIdRepr::FileId(_) => None, |
25 | HirFileIdRepr::MacroFile(macro_file) => { | 25 | HirFileIdRepr::MacroFile(macro_file) => match macro_file.macro_call_id { |
26 | let lazy_id = match macro_file.macro_call_id { | 26 | MacroCallId::LazyMacro(id) => { |
27 | crate::MacroCallId::LazyMacro(id) => id, | 27 | let loc = db.lookup_intern_macro(id); |
28 | }; | 28 | match loc.def.kind { |
29 | let loc = db.lookup_intern_macro(lazy_id); | 29 | MacroDefKind::Declarative => loc.def.krate, |
30 | match loc.def.kind { | 30 | MacroDefKind::BuiltIn(_) => None, |
31 | MacroDefKind::Declarative => loc.def.krate, | 31 | MacroDefKind::BuiltInDerive(_) => None, |
32 | MacroDefKind::BuiltIn(_) => None, | 32 | MacroDefKind::BuiltInEager(_) => None, |
33 | MacroDefKind::BuiltInDerive(_) => None, | 33 | } |
34 | } | 34 | } |
35 | } | 35 | MacroCallId::EagerMacro(_id) => None, |
36 | }, | ||
36 | }; | 37 | }; |
37 | Hygiene { def_crate } | 38 | Hygiene { def_crate } |
38 | } | 39 | } |
diff --git a/crates/ra_hir_expand/src/lib.rs b/crates/ra_hir_expand/src/lib.rs index 3a1c6d2b0..3fce73e8a 100644 --- a/crates/ra_hir_expand/src/lib.rs +++ b/crates/ra_hir_expand/src/lib.rs | |||
@@ -12,6 +12,7 @@ pub mod diagnostics; | |||
12 | pub mod builtin_derive; | 12 | pub mod builtin_derive; |
13 | pub mod builtin_macro; | 13 | pub mod builtin_macro; |
14 | pub mod quote; | 14 | pub mod quote; |
15 | pub mod eager; | ||
15 | 16 | ||
16 | use std::hash::Hash; | 17 | use std::hash::Hash; |
17 | use std::sync::Arc; | 18 | use std::sync::Arc; |
@@ -25,7 +26,7 @@ use ra_syntax::{ | |||
25 | 26 | ||
26 | use crate::ast_id_map::FileAstId; | 27 | use crate::ast_id_map::FileAstId; |
27 | use crate::builtin_derive::BuiltinDeriveExpander; | 28 | use crate::builtin_derive::BuiltinDeriveExpander; |
28 | use crate::builtin_macro::BuiltinFnLikeExpander; | 29 | use crate::builtin_macro::{BuiltinFnLikeExpander, EagerExpander}; |
29 | 30 | ||
30 | #[cfg(test)] | 31 | #[cfg(test)] |
31 | mod test_db; | 32 | mod test_db; |
@@ -70,11 +71,17 @@ impl HirFileId { | |||
70 | match self.0 { | 71 | match self.0 { |
71 | HirFileIdRepr::FileId(file_id) => file_id, | 72 | HirFileIdRepr::FileId(file_id) => file_id, |
72 | HirFileIdRepr::MacroFile(macro_file) => { | 73 | HirFileIdRepr::MacroFile(macro_file) => { |
73 | let lazy_id = match macro_file.macro_call_id { | 74 | let file_id = match macro_file.macro_call_id { |
74 | MacroCallId::LazyMacro(id) => id, | 75 | MacroCallId::LazyMacro(id) => { |
76 | let loc = db.lookup_intern_macro(id); | ||
77 | loc.kind.file_id() | ||
78 | } | ||
79 | MacroCallId::EagerMacro(id) => { | ||
80 | let loc = db.lookup_intern_eager_expansion(id); | ||
81 | loc.file_id | ||
82 | } | ||
75 | }; | 83 | }; |
76 | let loc = db.lookup_intern_macro(lazy_id); | 84 | file_id.original_file(db) |
77 | loc.kind.file_id().original_file(db) | ||
78 | } | 85 | } |
79 | } | 86 | } |
80 | } | 87 | } |
@@ -86,6 +93,10 @@ impl HirFileId { | |||
86 | HirFileIdRepr::MacroFile(macro_file) => { | 93 | HirFileIdRepr::MacroFile(macro_file) => { |
87 | let lazy_id = match macro_file.macro_call_id { | 94 | let lazy_id = match macro_file.macro_call_id { |
88 | MacroCallId::LazyMacro(id) => id, | 95 | MacroCallId::LazyMacro(id) => id, |
96 | MacroCallId::EagerMacro(_id) => { | ||
97 | // FIXME: handle call node for eager macro | ||
98 | return None; | ||
99 | } | ||
89 | }; | 100 | }; |
90 | let loc = db.lookup_intern_macro(lazy_id); | 101 | let loc = db.lookup_intern_macro(lazy_id); |
91 | Some(loc.kind.node(db)) | 102 | Some(loc.kind.node(db)) |
@@ -100,6 +111,10 @@ impl HirFileId { | |||
100 | HirFileIdRepr::MacroFile(macro_file) => { | 111 | HirFileIdRepr::MacroFile(macro_file) => { |
101 | let lazy_id = match macro_file.macro_call_id { | 112 | let lazy_id = match macro_file.macro_call_id { |
102 | MacroCallId::LazyMacro(id) => id, | 113 | MacroCallId::LazyMacro(id) => id, |
114 | MacroCallId::EagerMacro(_id) => { | ||
115 | // FIXME: handle expansion_info for eager macro | ||
116 | return None; | ||
117 | } | ||
103 | }; | 118 | }; |
104 | let loc: MacroCallLoc = db.lookup_intern_macro(lazy_id); | 119 | let loc: MacroCallLoc = db.lookup_intern_macro(lazy_id); |
105 | 120 | ||
@@ -129,6 +144,9 @@ impl HirFileId { | |||
129 | HirFileIdRepr::MacroFile(macro_file) => { | 144 | HirFileIdRepr::MacroFile(macro_file) => { |
130 | let lazy_id = match macro_file.macro_call_id { | 145 | let lazy_id = match macro_file.macro_call_id { |
131 | MacroCallId::LazyMacro(id) => id, | 146 | MacroCallId::LazyMacro(id) => id, |
147 | MacroCallId::EagerMacro(_id) => { | ||
148 | return None; | ||
149 | } | ||
132 | }; | 150 | }; |
133 | let loc: MacroCallLoc = db.lookup_intern_macro(lazy_id); | 151 | let loc: MacroCallLoc = db.lookup_intern_macro(lazy_id); |
134 | let item = match loc.def.kind { | 152 | let item = match loc.def.kind { |
@@ -151,6 +169,7 @@ pub struct MacroFile { | |||
151 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | 169 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] |
152 | pub enum MacroCallId { | 170 | pub enum MacroCallId { |
153 | LazyMacro(LazyMacroId), | 171 | LazyMacro(LazyMacroId), |
172 | EagerMacro(EagerMacroId), | ||
154 | } | 173 | } |
155 | 174 | ||
156 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | 175 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] |
@@ -164,11 +183,27 @@ impl salsa::InternKey for LazyMacroId { | |||
164 | } | 183 | } |
165 | } | 184 | } |
166 | 185 | ||
186 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | ||
187 | pub struct EagerMacroId(salsa::InternId); | ||
188 | impl salsa::InternKey for EagerMacroId { | ||
189 | fn from_intern_id(v: salsa::InternId) -> Self { | ||
190 | EagerMacroId(v) | ||
191 | } | ||
192 | fn as_intern_id(&self) -> salsa::InternId { | ||
193 | self.0 | ||
194 | } | ||
195 | } | ||
196 | |||
167 | impl From<LazyMacroId> for MacroCallId { | 197 | impl From<LazyMacroId> for MacroCallId { |
168 | fn from(it: LazyMacroId) -> Self { | 198 | fn from(it: LazyMacroId) -> Self { |
169 | MacroCallId::LazyMacro(it) | 199 | MacroCallId::LazyMacro(it) |
170 | } | 200 | } |
171 | } | 201 | } |
202 | impl From<EagerMacroId> for MacroCallId { | ||
203 | fn from(it: EagerMacroId) -> Self { | ||
204 | MacroCallId::EagerMacro(it) | ||
205 | } | ||
206 | } | ||
172 | 207 | ||
173 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | 208 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] |
174 | pub struct MacroDefId { | 209 | pub struct MacroDefId { |
@@ -184,8 +219,8 @@ pub struct MacroDefId { | |||
184 | } | 219 | } |
185 | 220 | ||
186 | impl MacroDefId { | 221 | impl MacroDefId { |
187 | pub fn as_call_id(self, db: &dyn db::AstDatabase, kind: MacroCallKind) -> MacroCallId { | 222 | pub fn as_lazy_macro(self, db: &dyn db::AstDatabase, kind: MacroCallKind) -> LazyMacroId { |
188 | db.intern_macro(MacroCallLoc { def: self, kind }).into() | 223 | db.intern_macro(MacroCallLoc { def: self, kind }) |
189 | } | 224 | } |
190 | } | 225 | } |
191 | 226 | ||
@@ -195,6 +230,7 @@ pub enum MacroDefKind { | |||
195 | BuiltIn(BuiltinFnLikeExpander), | 230 | BuiltIn(BuiltinFnLikeExpander), |
196 | // FIXME: maybe just Builtin and rename BuiltinFnLikeExpander to BuiltinExpander | 231 | // FIXME: maybe just Builtin and rename BuiltinFnLikeExpander to BuiltinExpander |
197 | BuiltInDerive(BuiltinDeriveExpander), | 232 | BuiltInDerive(BuiltinDeriveExpander), |
233 | BuiltInEager(EagerExpander), | ||
198 | } | 234 | } |
199 | 235 | ||
200 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | 236 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] |
@@ -240,6 +276,14 @@ impl MacroCallId { | |||
240 | } | 276 | } |
241 | } | 277 | } |
242 | 278 | ||
279 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
280 | pub struct EagerCallLoc { | ||
281 | pub(crate) def: MacroDefId, | ||
282 | pub(crate) fragment: FragmentKind, | ||
283 | pub(crate) subtree: Arc<tt::Subtree>, | ||
284 | pub(crate) file_id: HirFileId, | ||
285 | } | ||
286 | |||
243 | /// ExpansionInfo mainly describes how to map text range between src and expanded macro | 287 | /// ExpansionInfo mainly describes how to map text range between src and expanded macro |
244 | #[derive(Debug, Clone, PartialEq, Eq)] | 288 | #[derive(Debug, Clone, PartialEq, Eq)] |
245 | pub struct ExpansionInfo { | 289 | pub struct ExpansionInfo { |
@@ -253,6 +297,7 @@ pub struct ExpansionInfo { | |||
253 | } | 297 | } |
254 | 298 | ||
255 | pub use mbe::Origin; | 299 | pub use mbe::Origin; |
300 | use ra_parser::FragmentKind; | ||
256 | 301 | ||
257 | impl ExpansionInfo { | 302 | impl ExpansionInfo { |
258 | pub fn call_node(&self) -> Option<InFile<SyntaxNode>> { | 303 | pub fn call_node(&self) -> Option<InFile<SyntaxNode>> { |
diff --git a/crates/ra_hir_expand/src/name.rs b/crates/ra_hir_expand/src/name.rs index b2e10f445..036cf7d1e 100644 --- a/crates/ra_hir_expand/src/name.rs +++ b/crates/ra_hir_expand/src/name.rs | |||
@@ -173,6 +173,7 @@ pub mod known { | |||
173 | compile_error, | 173 | compile_error, |
174 | line, | 174 | line, |
175 | stringify, | 175 | stringify, |
176 | concat, | ||
176 | format_args, | 177 | format_args, |
177 | format_args_nl, | 178 | format_args_nl, |
178 | env, | 179 | env, |
diff --git a/crates/ra_parser/src/lib.rs b/crates/ra_parser/src/lib.rs index 81055746b..652492c1e 100644 --- a/crates/ra_parser/src/lib.rs +++ b/crates/ra_parser/src/lib.rs | |||
@@ -83,7 +83,7 @@ pub fn parse(token_source: &mut dyn TokenSource, tree_sink: &mut dyn TreeSink) { | |||
83 | parse_from_tokens(token_source, tree_sink, grammar::root); | 83 | parse_from_tokens(token_source, tree_sink, grammar::root); |
84 | } | 84 | } |
85 | 85 | ||
86 | #[derive(Clone, Copy)] | 86 | #[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)] |
87 | pub enum FragmentKind { | 87 | pub enum FragmentKind { |
88 | Path, | 88 | Path, |
89 | Expr, | 89 | Expr, |
diff --git a/crates/ra_syntax/src/ast/make.rs b/crates/ra_syntax/src/ast/make.rs index 3f11b747f..0da24560e 100644 --- a/crates/ra_syntax/src/ast/make.rs +++ b/crates/ra_syntax/src/ast/make.rs | |||
@@ -219,7 +219,7 @@ fn unroot(n: SyntaxNode) -> SyntaxNode { | |||
219 | } | 219 | } |
220 | 220 | ||
221 | pub mod tokens { | 221 | pub mod tokens { |
222 | use crate::{AstNode, Parse, SourceFile, SyntaxKind::*, SyntaxToken, T}; | 222 | use crate::{ast, AstNode, Parse, SourceFile, SyntaxKind::*, SyntaxToken, T}; |
223 | use once_cell::sync::Lazy; | 223 | use once_cell::sync::Lazy; |
224 | 224 | ||
225 | pub(super) static SOURCE_FILE: Lazy<Parse<SourceFile>> = | 225 | pub(super) static SOURCE_FILE: Lazy<Parse<SourceFile>> = |
@@ -251,6 +251,12 @@ pub mod tokens { | |||
251 | sf.syntax().first_child_or_token().unwrap().into_token().unwrap() | 251 | sf.syntax().first_child_or_token().unwrap().into_token().unwrap() |
252 | } | 252 | } |
253 | 253 | ||
254 | pub fn literal(text: &str) -> SyntaxToken { | ||
255 | assert_eq!(text.trim(), text); | ||
256 | let lit: ast::Literal = super::ast_from_text(&format!("fn f() {{ let _ = {}; }}", text)); | ||
257 | lit.syntax().first_child_or_token().unwrap().into_token().unwrap() | ||
258 | } | ||
259 | |||
254 | pub fn single_newline() -> SyntaxToken { | 260 | pub fn single_newline() -> SyntaxToken { |
255 | SOURCE_FILE | 261 | SOURCE_FILE |
256 | .tree() | 262 | .tree() |