aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--crates/ra_hir_expand/src/builtin_macro.rs52
-rw-r--r--crates/ra_hir_expand/src/eager.rs28
-rw-r--r--crates/ra_hir_expand/src/name.rs1
-rw-r--r--crates/ra_hir_ty/src/tests/macros.rs45
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
8use crate::{quote, LazyMacroId}; 8use crate::{quote, EagerMacroId, LazyMacroId, MacroCallId};
9use either::Either; 9use either::Either;
10use ra_db::{FileId, RelativePath};
10use ra_parser::FragmentKind; 11use ra_parser::FragmentKind;
11 12
12macro_rules! register_builtin { 13macro_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
81register_builtin! { 84register_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
101fn line_expand( 103fn line_expand(
@@ -251,7 +253,11 @@ fn unquote_str(lit: &tt::Literal) -> Option<String> {
251 token.value() 253 token.value()
252} 254}
253 255
254fn concat_expand(tt: &tt::Subtree) -> Result<(tt::Subtree, FragmentKind), mbe::ExpandError> { 256fn 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
275fn 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
282fn 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)]
270mod tests { 310mod 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]
442fn infer_builtin_macros_include() {
443 let (db, pos) = TestDB::with_position(
444 r#"
445//- /main.rs
446#[rustc_builtin_macro]
447macro_rules! include {() => {}}
448
449include!("foo.rs");
450
451fn main() {
452 bar()<|>;
453}
454
455//- /foo.rs
456fn bar() -> u32 {0}
457"#,
458 );
459 assert_eq!("u32", type_at_pos(&db, pos));
460}
461
462#[test]
463fn infer_builtin_macros_include_concat() {
464 let (db, pos) = TestDB::with_position(
465 r#"
466//- /main.rs
467#[rustc_builtin_macro]
468macro_rules! include {() => {}}
469
470#[rustc_builtin_macro]
471macro_rules! concat {() => {}}
472
473include!(concat!("f", "oo.rs"));
474
475fn main() {
476 bar()<|>;
477}
478
479//- /foo.rs
480fn bar() -> u32 {0}
481"#,
482 );
483 assert_eq!("u32", type_at_pos(&db, pos));
484}
485
486#[test]
442fn infer_builtin_macros_concat_with_lazy() { 487fn infer_builtin_macros_concat_with_lazy() {
443 assert_snapshot!( 488 assert_snapshot!(
444 infer(r#" 489 infer(r#"