diff options
-rw-r--r-- | crates/ra_hir_expand/src/builtin_macro.rs | 52 | ||||
-rw-r--r-- | crates/ra_hir_expand/src/eager.rs | 28 | ||||
-rw-r--r-- | crates/ra_hir_expand/src/name.rs | 1 | ||||
-rw-r--r-- | crates/ra_hir_ty/src/tests/macros.rs | 45 |
4 files changed, 107 insertions, 19 deletions
diff --git a/crates/ra_hir_expand/src/builtin_macro.rs b/crates/ra_hir_expand/src/builtin_macro.rs index b2c8a911f..9fc33e4b1 100644 --- a/crates/ra_hir_expand/src/builtin_macro.rs +++ b/crates/ra_hir_expand/src/builtin_macro.rs | |||
@@ -5,8 +5,9 @@ use crate::{ | |||
5 | name, AstId, CrateId, MacroDefId, MacroDefKind, TextUnit, | 5 | name, AstId, CrateId, MacroDefId, MacroDefKind, TextUnit, |
6 | }; | 6 | }; |
7 | 7 | ||
8 | use crate::{quote, LazyMacroId}; | 8 | use crate::{quote, EagerMacroId, LazyMacroId, MacroCallId}; |
9 | use either::Either; | 9 | use either::Either; |
10 | use ra_db::{FileId, RelativePath}; | ||
10 | use ra_parser::FragmentKind; | 11 | use ra_parser::FragmentKind; |
11 | 12 | ||
12 | macro_rules! register_builtin { | 13 | macro_rules! register_builtin { |
@@ -38,12 +39,14 @@ macro_rules! register_builtin { | |||
38 | impl EagerExpander { | 39 | impl EagerExpander { |
39 | pub fn expand( | 40 | pub fn expand( |
40 | &self, | 41 | &self, |
42 | db: &dyn AstDatabase, | ||
43 | arg_id: EagerMacroId, | ||
41 | tt: &tt::Subtree, | 44 | tt: &tt::Subtree, |
42 | ) -> Result<(tt::Subtree, FragmentKind), mbe::ExpandError> { | 45 | ) -> Result<(tt::Subtree, FragmentKind), mbe::ExpandError> { |
43 | let expander = match *self { | 46 | let expander = match *self { |
44 | $( EagerExpander::$e_kind => $e_expand, )* | 47 | $( EagerExpander::$e_kind => $e_expand, )* |
45 | }; | 48 | }; |
46 | expander(tt) | 49 | expander(db,arg_id,tt) |
47 | } | 50 | } |
48 | } | 51 | } |
49 | 52 | ||
@@ -80,7 +83,6 @@ pub fn find_builtin_macro( | |||
80 | 83 | ||
81 | register_builtin! { | 84 | register_builtin! { |
82 | LAZY: | 85 | LAZY: |
83 | |||
84 | (column, Column) => column_expand, | 86 | (column, Column) => column_expand, |
85 | (compile_error, CompileError) => compile_error_expand, | 87 | (compile_error, CompileError) => compile_error_expand, |
86 | (file, File) => file_expand, | 88 | (file, File) => file_expand, |
@@ -94,8 +96,8 @@ register_builtin! { | |||
94 | (format_args_nl, FormatArgsNl) => format_args_expand, | 96 | (format_args_nl, FormatArgsNl) => format_args_expand, |
95 | 97 | ||
96 | EAGER: | 98 | EAGER: |
97 | // eagers | 99 | (concat, Concat) => concat_expand, |
98 | (concat, Concat) => concat_expand | 100 | (include, Include) => include_expand |
99 | } | 101 | } |
100 | 102 | ||
101 | fn line_expand( | 103 | fn line_expand( |
@@ -251,7 +253,11 @@ fn unquote_str(lit: &tt::Literal) -> Option<String> { | |||
251 | token.value() | 253 | token.value() |
252 | } | 254 | } |
253 | 255 | ||
254 | fn concat_expand(tt: &tt::Subtree) -> Result<(tt::Subtree, FragmentKind), mbe::ExpandError> { | 256 | fn concat_expand( |
257 | _db: &dyn AstDatabase, | ||
258 | _arg_id: EagerMacroId, | ||
259 | tt: &tt::Subtree, | ||
260 | ) -> Result<(tt::Subtree, FragmentKind), mbe::ExpandError> { | ||
255 | let mut text = String::new(); | 261 | let mut text = String::new(); |
256 | for (i, t) in tt.token_trees.iter().enumerate() { | 262 | for (i, t) in tt.token_trees.iter().enumerate() { |
257 | match t { | 263 | match t { |
@@ -266,6 +272,40 @@ fn concat_expand(tt: &tt::Subtree) -> Result<(tt::Subtree, FragmentKind), mbe::E | |||
266 | Ok((quote!(#text), FragmentKind::Expr)) | 272 | Ok((quote!(#text), FragmentKind::Expr)) |
267 | } | 273 | } |
268 | 274 | ||
275 | fn relative_file(db: &dyn AstDatabase, call_id: MacroCallId, path: &str) -> Option<FileId> { | ||
276 | let call_site = call_id.as_file().original_file(db); | ||
277 | let path = RelativePath::new(&path); | ||
278 | |||
279 | db.resolve_relative_path(call_site, &path) | ||
280 | } | ||
281 | |||
282 | fn include_expand( | ||
283 | db: &dyn AstDatabase, | ||
284 | arg_id: EagerMacroId, | ||
285 | tt: &tt::Subtree, | ||
286 | ) -> Result<(tt::Subtree, FragmentKind), mbe::ExpandError> { | ||
287 | let path = tt | ||
288 | .token_trees | ||
289 | .get(0) | ||
290 | .and_then(|tt| match tt { | ||
291 | tt::TokenTree::Leaf(tt::Leaf::Literal(it)) => unquote_str(&it), | ||
292 | _ => None, | ||
293 | }) | ||
294 | .ok_or_else(|| mbe::ExpandError::ConversionError)?; | ||
295 | |||
296 | let file_id = | ||
297 | relative_file(db, arg_id.into(), &path).ok_or_else(|| mbe::ExpandError::ConversionError)?; | ||
298 | |||
299 | // FIXME: | ||
300 | // Handle include as expression | ||
301 | let node = | ||
302 | db.parse_or_expand(file_id.into()).ok_or_else(|| mbe::ExpandError::ConversionError)?; | ||
303 | let res = | ||
304 | mbe::syntax_node_to_token_tree(&node).ok_or_else(|| mbe::ExpandError::ConversionError)?.0; | ||
305 | |||
306 | Ok((res, FragmentKind::Items)) | ||
307 | } | ||
308 | |||
269 | #[cfg(test)] | 309 | #[cfg(test)] |
270 | mod tests { | 310 | mod tests { |
271 | use super::*; | 311 | use super::*; |
diff --git a/crates/ra_hir_expand/src/eager.rs b/crates/ra_hir_expand/src/eager.rs index f95f37ede..2e6dd3dd8 100644 --- a/crates/ra_hir_expand/src/eager.rs +++ b/crates/ra_hir_expand/src/eager.rs | |||
@@ -42,24 +42,26 @@ pub fn expand_eager_macro( | |||
42 | // When `lazy_expand` is called, its *parent* file must be already exists. | 42 | // When `lazy_expand` is called, its *parent* file must be already exists. |
43 | // Here we store an eager macro id for the argument expanded subtree here | 43 | // Here we store an eager macro id for the argument expanded subtree here |
44 | // for that purpose. | 44 | // for that purpose. |
45 | let arg_id: MacroCallId = db | 45 | let arg_id = db.intern_eager_expansion({ |
46 | .intern_eager_expansion({ | 46 | EagerCallLoc { |
47 | EagerCallLoc { | 47 | def, |
48 | def, | 48 | fragment: FragmentKind::Expr, |
49 | fragment: FragmentKind::Expr, | 49 | subtree: Arc::new(parsed_args.clone()), |
50 | subtree: Arc::new(parsed_args.clone()), | 50 | file_id: macro_call.file_id, |
51 | file_id: macro_call.file_id, | 51 | } |
52 | } | 52 | }); |
53 | }) | 53 | let arg_file_id: MacroCallId = arg_id.into(); |
54 | .into(); | ||
55 | 54 | ||
56 | let parsed_args = mbe::token_tree_to_syntax_node(&parsed_args, FragmentKind::Expr).ok()?.0; | 55 | let parsed_args = mbe::token_tree_to_syntax_node(&parsed_args, FragmentKind::Expr).ok()?.0; |
57 | let result = | 56 | let result = eager_macro_recur( |
58 | eager_macro_recur(db, InFile::new(arg_id.as_file(), parsed_args.syntax_node()), resolver)?; | 57 | db, |
58 | InFile::new(arg_file_id.as_file(), parsed_args.syntax_node()), | ||
59 | resolver, | ||
60 | )?; | ||
59 | let subtree = to_subtree(&result)?; | 61 | let subtree = to_subtree(&result)?; |
60 | 62 | ||
61 | if let MacroDefKind::BuiltInEager(eager) = def.kind { | 63 | if let MacroDefKind::BuiltInEager(eager) = def.kind { |
62 | let (subtree, fragment) = eager.expand(&subtree).ok()?; | 64 | let (subtree, fragment) = eager.expand(db, arg_id, &subtree).ok()?; |
63 | let eager = | 65 | let eager = |
64 | EagerCallLoc { def, fragment, subtree: Arc::new(subtree), file_id: macro_call.file_id }; | 66 | EagerCallLoc { def, fragment, subtree: Arc::new(subtree), file_id: macro_call.file_id }; |
65 | 67 | ||
diff --git a/crates/ra_hir_expand/src/name.rs b/crates/ra_hir_expand/src/name.rs index 036cf7d1e..6d201256f 100644 --- a/crates/ra_hir_expand/src/name.rs +++ b/crates/ra_hir_expand/src/name.rs | |||
@@ -174,6 +174,7 @@ pub mod known { | |||
174 | line, | 174 | line, |
175 | stringify, | 175 | stringify, |
176 | concat, | 176 | concat, |
177 | include, | ||
177 | format_args, | 178 | format_args, |
178 | format_args_nl, | 179 | format_args_nl, |
179 | env, | 180 | env, |
diff --git a/crates/ra_hir_ty/src/tests/macros.rs b/crates/ra_hir_ty/src/tests/macros.rs index 5d0efa0f4..42814941f 100644 --- a/crates/ra_hir_ty/src/tests/macros.rs +++ b/crates/ra_hir_ty/src/tests/macros.rs | |||
@@ -439,6 +439,51 @@ fn main() { | |||
439 | } | 439 | } |
440 | 440 | ||
441 | #[test] | 441 | #[test] |
442 | fn infer_builtin_macros_include() { | ||
443 | let (db, pos) = TestDB::with_position( | ||
444 | r#" | ||
445 | //- /main.rs | ||
446 | #[rustc_builtin_macro] | ||
447 | macro_rules! include {() => {}} | ||
448 | |||
449 | include!("foo.rs"); | ||
450 | |||
451 | fn main() { | ||
452 | bar()<|>; | ||
453 | } | ||
454 | |||
455 | //- /foo.rs | ||
456 | fn bar() -> u32 {0} | ||
457 | "#, | ||
458 | ); | ||
459 | assert_eq!("u32", type_at_pos(&db, pos)); | ||
460 | } | ||
461 | |||
462 | #[test] | ||
463 | fn infer_builtin_macros_include_concat() { | ||
464 | let (db, pos) = TestDB::with_position( | ||
465 | r#" | ||
466 | //- /main.rs | ||
467 | #[rustc_builtin_macro] | ||
468 | macro_rules! include {() => {}} | ||
469 | |||
470 | #[rustc_builtin_macro] | ||
471 | macro_rules! concat {() => {}} | ||
472 | |||
473 | include!(concat!("f", "oo.rs")); | ||
474 | |||
475 | fn main() { | ||
476 | bar()<|>; | ||
477 | } | ||
478 | |||
479 | //- /foo.rs | ||
480 | fn bar() -> u32 {0} | ||
481 | "#, | ||
482 | ); | ||
483 | assert_eq!("u32", type_at_pos(&db, pos)); | ||
484 | } | ||
485 | |||
486 | #[test] | ||
442 | fn infer_builtin_macros_concat_with_lazy() { | 487 | fn infer_builtin_macros_concat_with_lazy() { |
443 | assert_snapshot!( | 488 | assert_snapshot!( |
444 | infer(r#" | 489 | infer(r#" |