diff options
Diffstat (limited to 'crates/ra_hir_expand')
-rw-r--r-- | crates/ra_hir_expand/src/builtin_macro.rs | 73 | ||||
-rw-r--r-- | crates/ra_hir_expand/src/name.rs | 2 |
2 files changed, 71 insertions, 4 deletions
diff --git a/crates/ra_hir_expand/src/builtin_macro.rs b/crates/ra_hir_expand/src/builtin_macro.rs index b50eb347c..626f9efd0 100644 --- a/crates/ra_hir_expand/src/builtin_macro.rs +++ b/crates/ra_hir_expand/src/builtin_macro.rs | |||
@@ -99,6 +99,8 @@ register_builtin! { | |||
99 | EAGER: | 99 | EAGER: |
100 | (concat, Concat) => concat_expand, | 100 | (concat, Concat) => concat_expand, |
101 | (include, Include) => include_expand, | 101 | (include, Include) => include_expand, |
102 | (include_bytes, IncludeBytes) => include_bytes_expand, | ||
103 | (include_str, IncludeStr) => include_str_expand, | ||
102 | (env, Env) => env_expand, | 104 | (env, Env) => env_expand, |
103 | (option_env, OptionEnv) => option_env_expand | 105 | (option_env, OptionEnv) => option_env_expand |
104 | } | 106 | } |
@@ -292,11 +294,16 @@ fn concat_expand( | |||
292 | Ok((quote!(#text), FragmentKind::Expr)) | 294 | Ok((quote!(#text), FragmentKind::Expr)) |
293 | } | 295 | } |
294 | 296 | ||
295 | fn relative_file(db: &dyn AstDatabase, call_id: MacroCallId, path: &str) -> Option<FileId> { | 297 | fn relative_file( |
298 | db: &dyn AstDatabase, | ||
299 | call_id: MacroCallId, | ||
300 | path: &str, | ||
301 | allow_recursion: bool, | ||
302 | ) -> Option<FileId> { | ||
296 | let call_site = call_id.as_file().original_file(db); | 303 | let call_site = call_id.as_file().original_file(db); |
297 | let res = db.resolve_path(call_site, path)?; | 304 | let res = db.resolve_path(call_site, path)?; |
298 | // Prevent include itself | 305 | // Prevent include itself |
299 | if res == call_site { | 306 | if res == call_site && !allow_recursion { |
300 | None | 307 | None |
301 | } else { | 308 | } else { |
302 | Some(res) | 309 | Some(res) |
@@ -319,8 +326,8 @@ fn include_expand( | |||
319 | tt: &tt::Subtree, | 326 | tt: &tt::Subtree, |
320 | ) -> Result<(tt::Subtree, FragmentKind), mbe::ExpandError> { | 327 | ) -> Result<(tt::Subtree, FragmentKind), mbe::ExpandError> { |
321 | let path = parse_string(tt)?; | 328 | let path = parse_string(tt)?; |
322 | let file_id = | 329 | let file_id = relative_file(db, arg_id.into(), &path, false) |
323 | relative_file(db, arg_id.into(), &path).ok_or_else(|| mbe::ExpandError::ConversionError)?; | 330 | .ok_or_else(|| mbe::ExpandError::ConversionError)?; |
324 | 331 | ||
325 | // FIXME: | 332 | // FIXME: |
326 | // Handle include as expression | 333 | // Handle include as expression |
@@ -331,6 +338,48 @@ fn include_expand( | |||
331 | Ok((res, FragmentKind::Items)) | 338 | Ok((res, FragmentKind::Items)) |
332 | } | 339 | } |
333 | 340 | ||
341 | fn include_bytes_expand( | ||
342 | _db: &dyn AstDatabase, | ||
343 | _arg_id: EagerMacroId, | ||
344 | tt: &tt::Subtree, | ||
345 | ) -> Result<(tt::Subtree, FragmentKind), mbe::ExpandError> { | ||
346 | let _path = parse_string(tt)?; | ||
347 | |||
348 | // FIXME: actually read the file here if the user asked for macro expansion | ||
349 | let res = tt::Subtree { | ||
350 | delimiter: None, | ||
351 | token_trees: vec![tt::TokenTree::Leaf(tt::Leaf::Literal(tt::Literal { | ||
352 | text: r#"b"""#.into(), | ||
353 | id: tt::TokenId::unspecified(), | ||
354 | }))], | ||
355 | }; | ||
356 | Ok((res, FragmentKind::Expr)) | ||
357 | } | ||
358 | |||
359 | fn include_str_expand( | ||
360 | db: &dyn AstDatabase, | ||
361 | arg_id: EagerMacroId, | ||
362 | tt: &tt::Subtree, | ||
363 | ) -> Result<(tt::Subtree, FragmentKind), mbe::ExpandError> { | ||
364 | let path = parse_string(tt)?; | ||
365 | |||
366 | // FIXME: we're not able to read excluded files (which is most of them because | ||
367 | // it's unusual to `include_str!` a Rust file), but we can return an empty string. | ||
368 | // Ideally, we'd be able to offer a precise expansion if the user asks for macro | ||
369 | // expansion. | ||
370 | let file_id = match relative_file(db, arg_id.into(), &path, true) { | ||
371 | Some(file_id) => file_id, | ||
372 | None => { | ||
373 | return Ok((quote!(""), FragmentKind::Expr)); | ||
374 | } | ||
375 | }; | ||
376 | |||
377 | let text = db.file_text(file_id); | ||
378 | let text = &*text; | ||
379 | |||
380 | Ok((quote!(#text), FragmentKind::Expr)) | ||
381 | } | ||
382 | |||
334 | fn get_env_inner(db: &dyn AstDatabase, arg_id: EagerMacroId, key: &str) -> Option<String> { | 383 | fn get_env_inner(db: &dyn AstDatabase, arg_id: EagerMacroId, key: &str) -> Option<String> { |
335 | let krate = db.lookup_intern_eager_expansion(arg_id).krate; | 384 | let krate = db.lookup_intern_eager_expansion(arg_id).krate; |
336 | db.crate_graph()[krate].env.get(key) | 385 | db.crate_graph()[krate].env.get(key) |
@@ -581,4 +630,20 @@ mod tests { | |||
581 | r#"std::fmt::Arguments::new_v1(&[], &[std::fmt::ArgumentV1::new(&(arg1(a,b,c)),std::fmt::Display::fmt),std::fmt::ArgumentV1::new(&(arg2),std::fmt::Display::fmt),])"# | 630 | r#"std::fmt::Arguments::new_v1(&[], &[std::fmt::ArgumentV1::new(&(arg1(a,b,c)),std::fmt::Display::fmt),std::fmt::ArgumentV1::new(&(arg2),std::fmt::Display::fmt),])"# |
582 | ); | 631 | ); |
583 | } | 632 | } |
633 | |||
634 | #[test] | ||
635 | fn test_include_bytes_expand() { | ||
636 | let expanded = expand_builtin_macro( | ||
637 | r#" | ||
638 | #[rustc_builtin_macro] | ||
639 | macro_rules! include_bytes { | ||
640 | ($file:expr) => {{ /* compiler built-in */ }}; | ||
641 | ($file:expr,) => {{ /* compiler built-in */ }}; | ||
642 | } | ||
643 | include_bytes("foo"); | ||
644 | "#, | ||
645 | ); | ||
646 | |||
647 | assert_eq!(expanded, r#"b"""#); | ||
648 | } | ||
584 | } | 649 | } |
diff --git a/crates/ra_hir_expand/src/name.rs b/crates/ra_hir_expand/src/name.rs index 660bdfe33..1b0303685 100644 --- a/crates/ra_hir_expand/src/name.rs +++ b/crates/ra_hir_expand/src/name.rs | |||
@@ -191,6 +191,8 @@ pub mod known { | |||
191 | stringify, | 191 | stringify, |
192 | concat, | 192 | concat, |
193 | include, | 193 | include, |
194 | include_bytes, | ||
195 | include_str, | ||
194 | format_args, | 196 | format_args, |
195 | format_args_nl, | 197 | format_args_nl, |
196 | env, | 198 | env, |