diff options
Diffstat (limited to 'crates/hir_expand')
-rw-r--r-- | crates/hir_expand/Cargo.toml | 6 | ||||
-rw-r--r-- | crates/hir_expand/src/builtin_derive.rs | 66 | ||||
-rw-r--r-- | crates/hir_expand/src/builtin_macro.rs | 140 | ||||
-rw-r--r-- | crates/hir_expand/src/db.rs | 2 | ||||
-rw-r--r-- | crates/hir_expand/src/name.rs | 1 | ||||
-rw-r--r-- | crates/hir_expand/src/quote.rs | 5 |
6 files changed, 108 insertions, 112 deletions
diff --git a/crates/hir_expand/Cargo.toml b/crates/hir_expand/Cargo.toml index 5271110d2..f649ab925 100644 --- a/crates/hir_expand/Cargo.toml +++ b/crates/hir_expand/Cargo.toml | |||
@@ -16,9 +16,13 @@ rustc-hash = "1.0.0" | |||
16 | la-arena = { version = "0.2.0", path = "../../lib/arena" } | 16 | la-arena = { version = "0.2.0", path = "../../lib/arena" } |
17 | 17 | ||
18 | base_db = { path = "../base_db", version = "0.0.0" } | 18 | base_db = { path = "../base_db", version = "0.0.0" } |
19 | cfg = { path = "../cfg", version = "0.0.0" } | ||
19 | syntax = { path = "../syntax", version = "0.0.0" } | 20 | syntax = { path = "../syntax", version = "0.0.0" } |
20 | parser = { path = "../parser", version = "0.0.0" } | 21 | parser = { path = "../parser", version = "0.0.0" } |
21 | profile = { path = "../profile", version = "0.0.0" } | 22 | profile = { path = "../profile", version = "0.0.0" } |
22 | tt = { path = "../tt", version = "0.0.0" } | 23 | tt = { path = "../tt", version = "0.0.0" } |
23 | mbe = { path = "../mbe", version = "0.0.0" } | 24 | mbe = { path = "../mbe", version = "0.0.0" } |
24 | test_utils = { path = "../test_utils", version = "0.0.0" } | 25 | |
26 | [dev-dependencies] | ||
27 | test_utils = { path = "../test_utils" } | ||
28 | expect-test = "1.1" | ||
diff --git a/crates/hir_expand/src/builtin_derive.rs b/crates/hir_expand/src/builtin_derive.rs index b7f1aae8f..dfdb9cf59 100644 --- a/crates/hir_expand/src/builtin_derive.rs +++ b/crates/hir_expand/src/builtin_derive.rs | |||
@@ -267,13 +267,14 @@ fn partial_ord_expand( | |||
267 | #[cfg(test)] | 267 | #[cfg(test)] |
268 | mod tests { | 268 | mod tests { |
269 | use base_db::{fixture::WithFixture, CrateId, SourceDatabase}; | 269 | use base_db::{fixture::WithFixture, CrateId, SourceDatabase}; |
270 | use expect_test::{expect, Expect}; | ||
270 | use name::{known, Name}; | 271 | use name::{known, Name}; |
271 | 272 | ||
272 | use crate::{test_db::TestDB, AstId, MacroCallId, MacroCallKind, MacroCallLoc}; | 273 | use crate::{test_db::TestDB, AstId, MacroCallId, MacroCallKind, MacroCallLoc}; |
273 | 274 | ||
274 | use super::*; | 275 | use super::*; |
275 | 276 | ||
276 | fn expand_builtin_derive(s: &str, name: Name) -> String { | 277 | fn expand_builtin_derive(ra_fixture: &str, name: Name) -> String { |
277 | let expander = BuiltinDeriveExpander::find_by_name(&name).unwrap(); | 278 | let expander = BuiltinDeriveExpander::find_by_name(&name).unwrap(); |
278 | let fixture = format!( | 279 | let fixture = format!( |
279 | r#"//- /main.rs crate:main deps:core | 280 | r#"//- /main.rs crate:main deps:core |
@@ -282,7 +283,7 @@ $0 | |||
282 | //- /lib.rs crate:core | 283 | //- /lib.rs crate:core |
283 | // empty | 284 | // empty |
284 | "#, | 285 | "#, |
285 | s | 286 | ra_fixture |
286 | ); | 287 | ); |
287 | 288 | ||
288 | let (db, file_pos) = TestDB::with_position(&fixture); | 289 | let (db, file_pos) = TestDB::with_position(&fixture); |
@@ -314,66 +315,57 @@ $0 | |||
314 | parsed.text().to_string() | 315 | parsed.text().to_string() |
315 | } | 316 | } |
316 | 317 | ||
318 | fn check_derive(ra_fixture: &str, name: Name, expected: Expect) { | ||
319 | let expanded = expand_builtin_derive(ra_fixture, name); | ||
320 | expected.assert_eq(&expanded); | ||
321 | } | ||
322 | |||
317 | #[test] | 323 | #[test] |
318 | fn test_copy_expand_simple() { | 324 | fn test_copy_expand_simple() { |
319 | let expanded = expand_builtin_derive( | 325 | check_derive( |
320 | r#" | 326 | r#" |
321 | #[derive(Copy)] | 327 | #[derive(Copy)] |
322 | struct Foo; | 328 | struct Foo; |
323 | "#, | 329 | "#, |
324 | known::Copy, | 330 | known::Copy, |
331 | expect![["impl< >core::marker::CopyforFoo< >{}"]], | ||
325 | ); | 332 | ); |
326 | |||
327 | assert_eq!(expanded, "impl< >core::marker::CopyforFoo< >{}"); | ||
328 | } | 333 | } |
329 | 334 | ||
330 | #[test] | 335 | #[test] |
331 | fn test_copy_expand_with_type_params() { | 336 | fn test_copy_expand_with_type_params() { |
332 | let expanded = expand_builtin_derive( | 337 | check_derive( |
333 | r#" | 338 | r#" |
334 | #[derive(Copy)] | 339 | #[derive(Copy)] |
335 | struct Foo<A, B>; | 340 | struct Foo<A, B>; |
336 | "#, | 341 | "#, |
337 | known::Copy, | 342 | known::Copy, |
338 | ); | 343 | expect![["impl<T0:core::marker::Copy,T1:core::marker::Copy>core::marker::CopyforFoo<T0,T1>{}"]], |
339 | |||
340 | assert_eq!( | ||
341 | expanded, | ||
342 | "impl<T0:core::marker::Copy,T1:core::marker::Copy>core::marker::CopyforFoo<T0,T1>{}" | ||
343 | ); | 344 | ); |
344 | } | 345 | } |
345 | 346 | ||
346 | #[test] | 347 | #[test] |
347 | fn test_copy_expand_with_lifetimes() { | 348 | fn test_copy_expand_with_lifetimes() { |
348 | let expanded = expand_builtin_derive( | 349 | check_derive( |
349 | r#" | 350 | r#" |
350 | #[derive(Copy)] | 351 | #[derive(Copy)] |
351 | struct Foo<A, B, 'a, 'b>; | 352 | struct Foo<A, B, 'a, 'b>; |
352 | "#, | 353 | "#, |
353 | known::Copy, | 354 | known::Copy, |
354 | ); | 355 | // We currently just ignore lifetimes |
355 | 356 | expect![["impl<T0:core::marker::Copy,T1:core::marker::Copy>core::marker::CopyforFoo<T0,T1>{}"]], | |
356 | // We currently just ignore lifetimes | ||
357 | |||
358 | assert_eq!( | ||
359 | expanded, | ||
360 | "impl<T0:core::marker::Copy,T1:core::marker::Copy>core::marker::CopyforFoo<T0,T1>{}" | ||
361 | ); | 357 | ); |
362 | } | 358 | } |
363 | 359 | ||
364 | #[test] | 360 | #[test] |
365 | fn test_clone_expand() { | 361 | fn test_clone_expand() { |
366 | let expanded = expand_builtin_derive( | 362 | check_derive( |
367 | r#" | 363 | r#" |
368 | #[derive(Clone)] | 364 | #[derive(Clone)] |
369 | struct Foo<A, B>; | 365 | struct Foo<A, B>; |
370 | "#, | 366 | "#, |
371 | known::Clone, | 367 | known::Clone, |
372 | ); | 368 | expect![["impl<T0:core::clone::Clone,T1:core::clone::Clone>core::clone::CloneforFoo<T0,T1>{}"]], |
373 | |||
374 | assert_eq!( | ||
375 | expanded, | ||
376 | "impl<T0:core::clone::Clone,T1:core::clone::Clone>core::clone::CloneforFoo<T0,T1>{}" | ||
377 | ); | 369 | ); |
378 | } | 370 | } |
379 | } | 371 | } |
diff --git a/crates/hir_expand/src/builtin_macro.rs b/crates/hir_expand/src/builtin_macro.rs index 57bc6fbd7..2a79c892b 100644 --- a/crates/hir_expand/src/builtin_macro.rs +++ b/crates/hir_expand/src/builtin_macro.rs | |||
@@ -5,8 +5,9 @@ use crate::{ | |||
5 | }; | 5 | }; |
6 | 6 | ||
7 | use base_db::{AnchoredPath, FileId}; | 7 | use base_db::{AnchoredPath, FileId}; |
8 | use cfg::CfgExpr; | ||
8 | use either::Either; | 9 | use either::Either; |
9 | use mbe::{parse_to_token_tree, ExpandResult}; | 10 | use mbe::{parse_exprs_with_sep, parse_to_token_tree, ExpandResult}; |
10 | use parser::FragmentKind; | 11 | use parser::FragmentKind; |
11 | use syntax::ast::{self, AstToken}; | 12 | use syntax::ast::{self, AstToken}; |
12 | 13 | ||
@@ -97,6 +98,7 @@ register_builtin! { | |||
97 | (format_args_nl, FormatArgsNl) => format_args_expand, | 98 | (format_args_nl, FormatArgsNl) => format_args_expand, |
98 | (llvm_asm, LlvmAsm) => asm_expand, | 99 | (llvm_asm, LlvmAsm) => asm_expand, |
99 | (asm, Asm) => asm_expand, | 100 | (asm, Asm) => asm_expand, |
101 | (cfg, Cfg) => cfg_expand, | ||
100 | 102 | ||
101 | EAGER: | 103 | EAGER: |
102 | (compile_error, CompileError) => compile_error_expand, | 104 | (compile_error, CompileError) => compile_error_expand, |
@@ -182,25 +184,10 @@ fn assert_expand( | |||
182 | // ```, | 184 | // ```, |
183 | // which is wrong but useful. | 185 | // which is wrong but useful. |
184 | 186 | ||
185 | let mut args = Vec::new(); | 187 | let args = parse_exprs_with_sep(tt, ','); |
186 | let mut current = Vec::new(); | ||
187 | for tt in tt.token_trees.iter().cloned() { | ||
188 | match tt { | ||
189 | tt::TokenTree::Leaf(tt::Leaf::Punct(p)) if p.char == ',' => { | ||
190 | args.push(current); | ||
191 | current = Vec::new(); | ||
192 | } | ||
193 | _ => { | ||
194 | current.push(tt); | ||
195 | } | ||
196 | } | ||
197 | } | ||
198 | if !current.is_empty() { | ||
199 | args.push(current); | ||
200 | } | ||
201 | 188 | ||
202 | let arg_tts = args.into_iter().flat_map(|arg| { | 189 | let arg_tts = args.into_iter().flat_map(|arg| { |
203 | quote! { &(##arg), } | 190 | quote! { &(#arg), } |
204 | }.token_trees).collect::<Vec<_>>(); | 191 | }.token_trees).collect::<Vec<_>>(); |
205 | 192 | ||
206 | let expanded = quote! { | 193 | let expanded = quote! { |
@@ -238,35 +225,21 @@ fn format_args_expand( | |||
238 | // ]) | 225 | // ]) |
239 | // ```, | 226 | // ```, |
240 | // which is still not really correct, but close enough for now | 227 | // which is still not really correct, but close enough for now |
241 | let mut args = Vec::new(); | 228 | let mut args = parse_exprs_with_sep(tt, ','); |
242 | let mut current = Vec::new(); | 229 | |
243 | for tt in tt.token_trees.iter().cloned() { | ||
244 | match tt { | ||
245 | tt::TokenTree::Leaf(tt::Leaf::Punct(p)) if p.char == ',' => { | ||
246 | args.push(current); | ||
247 | current = Vec::new(); | ||
248 | } | ||
249 | _ => { | ||
250 | current.push(tt); | ||
251 | } | ||
252 | } | ||
253 | } | ||
254 | if !current.is_empty() { | ||
255 | args.push(current); | ||
256 | } | ||
257 | if args.is_empty() { | 230 | if args.is_empty() { |
258 | return ExpandResult::only_err(mbe::ExpandError::NoMatchingRule); | 231 | return ExpandResult::only_err(mbe::ExpandError::NoMatchingRule); |
259 | } | 232 | } |
260 | for arg in &mut args { | 233 | for arg in &mut args { |
261 | // Remove `key =`. | 234 | // Remove `key =`. |
262 | if matches!(arg.get(1), Some(tt::TokenTree::Leaf(tt::Leaf::Punct(p))) if p.char == '=' && p.spacing != tt::Spacing::Joint) | 235 | if matches!(arg.token_trees.get(1), Some(tt::TokenTree::Leaf(tt::Leaf::Punct(p))) if p.char == '=' && p.spacing != tt::Spacing::Joint) |
263 | { | 236 | { |
264 | arg.drain(..2); | 237 | arg.token_trees.drain(..2); |
265 | } | 238 | } |
266 | } | 239 | } |
267 | let _format_string = args.remove(0); | 240 | let _format_string = args.remove(0); |
268 | let arg_tts = args.into_iter().flat_map(|arg| { | 241 | let arg_tts = args.into_iter().flat_map(|arg| { |
269 | quote! { std::fmt::ArgumentV1::new(&(##arg), std::fmt::Display::fmt), } | 242 | quote! { std::fmt::ArgumentV1::new(&(#arg), std::fmt::Display::fmt), } |
270 | }.token_trees).collect::<Vec<_>>(); | 243 | }.token_trees).collect::<Vec<_>>(); |
271 | let expanded = quote! { | 244 | let expanded = quote! { |
272 | std::fmt::Arguments::new_v1(&[], &[##arg_tts]) | 245 | std::fmt::Arguments::new_v1(&[], &[##arg_tts]) |
@@ -287,6 +260,18 @@ fn asm_expand( | |||
287 | ExpandResult::ok(expanded) | 260 | ExpandResult::ok(expanded) |
288 | } | 261 | } |
289 | 262 | ||
263 | fn cfg_expand( | ||
264 | db: &dyn AstDatabase, | ||
265 | id: LazyMacroId, | ||
266 | tt: &tt::Subtree, | ||
267 | ) -> ExpandResult<tt::Subtree> { | ||
268 | let loc = db.lookup_intern_macro(id); | ||
269 | let expr = CfgExpr::parse(tt); | ||
270 | let enabled = db.crate_graph()[loc.krate].cfg_options.check(&expr) != Some(false); | ||
271 | let expanded = if enabled { quote!(true) } else { quote!(false) }; | ||
272 | ExpandResult::ok(expanded) | ||
273 | } | ||
274 | |||
290 | fn unquote_str(lit: &tt::Literal) -> Option<String> { | 275 | fn unquote_str(lit: &tt::Literal) -> Option<String> { |
291 | let lit = ast::make::tokens::literal(&lit.to_string()); | 276 | let lit = ast::make::tokens::literal(&lit.to_string()); |
292 | let token = ast::String::cast(lit)?; | 277 | let token = ast::String::cast(lit)?; |
@@ -506,6 +491,7 @@ mod tests { | |||
506 | MacroCallLoc, | 491 | MacroCallLoc, |
507 | }; | 492 | }; |
508 | use base_db::{fixture::WithFixture, SourceDatabase}; | 493 | use base_db::{fixture::WithFixture, SourceDatabase}; |
494 | use expect_test::{expect, Expect}; | ||
509 | use std::sync::Arc; | 495 | use std::sync::Arc; |
510 | use syntax::ast::NameOwner; | 496 | use syntax::ast::NameOwner; |
511 | 497 | ||
@@ -589,87 +575,86 @@ mod tests { | |||
589 | db.parse_or_expand(file_id).unwrap().to_string() | 575 | db.parse_or_expand(file_id).unwrap().to_string() |
590 | } | 576 | } |
591 | 577 | ||
578 | fn check_expansion(ra_fixture: &str, expect: Expect) { | ||
579 | let expansion = expand_builtin_macro(ra_fixture); | ||
580 | expect.assert_eq(&expansion); | ||
581 | } | ||
582 | |||
592 | #[test] | 583 | #[test] |
593 | fn test_column_expand() { | 584 | fn test_column_expand() { |
594 | let expanded = expand_builtin_macro( | 585 | check_expansion( |
595 | r#" | 586 | r#" |
596 | #[rustc_builtin_macro] | 587 | #[rustc_builtin_macro] |
597 | macro_rules! column {() => {}} | 588 | macro_rules! column {() => {}} |
598 | column!() | 589 | column!() |
599 | "#, | 590 | "#, |
591 | expect![["0"]], | ||
600 | ); | 592 | ); |
601 | |||
602 | assert_eq!(expanded, "0"); | ||
603 | } | 593 | } |
604 | 594 | ||
605 | #[test] | 595 | #[test] |
606 | fn test_line_expand() { | 596 | fn test_line_expand() { |
607 | let expanded = expand_builtin_macro( | 597 | check_expansion( |
608 | r#" | 598 | r#" |
609 | #[rustc_builtin_macro] | 599 | #[rustc_builtin_macro] |
610 | macro_rules! line {() => {}} | 600 | macro_rules! line {() => {}} |
611 | line!() | 601 | line!() |
612 | "#, | 602 | "#, |
603 | expect![["0"]], | ||
613 | ); | 604 | ); |
614 | |||
615 | assert_eq!(expanded, "0"); | ||
616 | } | 605 | } |
617 | 606 | ||
618 | #[test] | 607 | #[test] |
619 | fn test_stringify_expand() { | 608 | fn test_stringify_expand() { |
620 | let expanded = expand_builtin_macro( | 609 | check_expansion( |
621 | r#" | 610 | r#" |
622 | #[rustc_builtin_macro] | 611 | #[rustc_builtin_macro] |
623 | macro_rules! stringify {() => {}} | 612 | macro_rules! stringify {() => {}} |
624 | stringify!(a b c) | 613 | stringify!(a b c) |
625 | "#, | 614 | "#, |
615 | expect![["\"a b c\""]], | ||
626 | ); | 616 | ); |
627 | |||
628 | assert_eq!(expanded, "\"a b c\""); | ||
629 | } | 617 | } |
630 | 618 | ||
631 | #[test] | 619 | #[test] |
632 | fn test_env_expand() { | 620 | fn test_env_expand() { |
633 | let expanded = expand_builtin_macro( | 621 | check_expansion( |
634 | r#" | 622 | r#" |
635 | #[rustc_builtin_macro] | 623 | #[rustc_builtin_macro] |
636 | macro_rules! env {() => {}} | 624 | macro_rules! env {() => {}} |
637 | env!("TEST_ENV_VAR") | 625 | env!("TEST_ENV_VAR") |
638 | "#, | 626 | "#, |
627 | expect![["\"__RA_UNIMPLEMENTED__\""]], | ||
639 | ); | 628 | ); |
640 | |||
641 | assert_eq!(expanded, "\"__RA_UNIMPLEMENTED__\""); | ||
642 | } | 629 | } |
643 | 630 | ||
644 | #[test] | 631 | #[test] |
645 | fn test_option_env_expand() { | 632 | fn test_option_env_expand() { |
646 | let expanded = expand_builtin_macro( | 633 | check_expansion( |
647 | r#" | 634 | r#" |
648 | #[rustc_builtin_macro] | 635 | #[rustc_builtin_macro] |
649 | macro_rules! option_env {() => {}} | 636 | macro_rules! option_env {() => {}} |
650 | option_env!("TEST_ENV_VAR") | 637 | option_env!("TEST_ENV_VAR") |
651 | "#, | 638 | "#, |
639 | expect![["std::option::Option::None:: < &str>"]], | ||
652 | ); | 640 | ); |
653 | |||
654 | assert_eq!(expanded, "std::option::Option::None:: < &str>"); | ||
655 | } | 641 | } |
656 | 642 | ||
657 | #[test] | 643 | #[test] |
658 | fn test_file_expand() { | 644 | fn test_file_expand() { |
659 | let expanded = expand_builtin_macro( | 645 | check_expansion( |
660 | r#" | 646 | r#" |
661 | #[rustc_builtin_macro] | 647 | #[rustc_builtin_macro] |
662 | macro_rules! file {() => {}} | 648 | macro_rules! file {() => {}} |
663 | file!() | 649 | file!() |
664 | "#, | 650 | "#, |
651 | expect![[r#""""#]], | ||
665 | ); | 652 | ); |
666 | |||
667 | assert_eq!(expanded, "\"\""); | ||
668 | } | 653 | } |
669 | 654 | ||
670 | #[test] | 655 | #[test] |
671 | fn test_assert_expand() { | 656 | fn test_assert_expand() { |
672 | let expanded = expand_builtin_macro( | 657 | check_expansion( |
673 | r#" | 658 | r#" |
674 | #[rustc_builtin_macro] | 659 | #[rustc_builtin_macro] |
675 | macro_rules! assert { | 660 | macro_rules! assert { |
@@ -678,14 +663,13 @@ mod tests { | |||
678 | } | 663 | } |
679 | assert!(true, "{} {:?}", arg1(a, b, c), arg2); | 664 | assert!(true, "{} {:?}", arg1(a, b, c), arg2); |
680 | "#, | 665 | "#, |
666 | expect![["{{(&(true), &(\"{} {:?}\"), &(arg1(a,b,c)), &(arg2),);}}"]], | ||
681 | ); | 667 | ); |
682 | |||
683 | assert_eq!(expanded, "{{(&(true), &(\"{} {:?}\"), &(arg1(a,b,c)), &(arg2),);}}"); | ||
684 | } | 668 | } |
685 | 669 | ||
686 | #[test] | 670 | #[test] |
687 | fn test_compile_error_expand() { | 671 | fn test_compile_error_expand() { |
688 | let expanded = expand_builtin_macro( | 672 | check_expansion( |
689 | r#" | 673 | r#" |
690 | #[rustc_builtin_macro] | 674 | #[rustc_builtin_macro] |
691 | macro_rules! compile_error { | 675 | macro_rules! compile_error { |
@@ -694,15 +678,14 @@ mod tests { | |||
694 | } | 678 | } |
695 | compile_error!("error!"); | 679 | compile_error!("error!"); |
696 | "#, | 680 | "#, |
681 | // This expands to nothing (since it's in item position), but emits an error. | ||
682 | expect![[""]], | ||
697 | ); | 683 | ); |
698 | |||
699 | // This expands to nothing (since it's in item position), but emits an error. | ||
700 | assert_eq!(expanded, ""); | ||
701 | } | 684 | } |
702 | 685 | ||
703 | #[test] | 686 | #[test] |
704 | fn test_format_args_expand() { | 687 | fn test_format_args_expand() { |
705 | let expanded = expand_builtin_macro( | 688 | check_expansion( |
706 | r#" | 689 | r#" |
707 | #[rustc_builtin_macro] | 690 | #[rustc_builtin_macro] |
708 | macro_rules! format_args { | 691 | macro_rules! format_args { |
@@ -711,17 +694,32 @@ mod tests { | |||
711 | } | 694 | } |
712 | format_args!("{} {:?}", arg1(a, b, c), arg2); | 695 | format_args!("{} {:?}", arg1(a, b, c), arg2); |
713 | "#, | 696 | "#, |
697 | expect![[ | ||
698 | 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),])"# | ||
699 | ]], | ||
714 | ); | 700 | ); |
701 | } | ||
715 | 702 | ||
716 | assert_eq!( | 703 | #[test] |
717 | expanded, | 704 | fn test_format_args_expand_with_comma_exprs() { |
718 | 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),])"# | 705 | check_expansion( |
706 | r#" | ||
707 | #[rustc_builtin_macro] | ||
708 | macro_rules! format_args { | ||
709 | ($fmt:expr) => ({ /* compiler built-in */ }); | ||
710 | ($fmt:expr, $($args:tt)*) => ({ /* compiler built-in */ }) | ||
711 | } | ||
712 | format_args!("{} {:?}", a::<A,B>(), b); | ||
713 | "#, | ||
714 | expect![[ | ||
715 | r#"std::fmt::Arguments::new_v1(&[], &[std::fmt::ArgumentV1::new(&(a::<A,B>()),std::fmt::Display::fmt),std::fmt::ArgumentV1::new(&(b),std::fmt::Display::fmt),])"# | ||
716 | ]], | ||
719 | ); | 717 | ); |
720 | } | 718 | } |
721 | 719 | ||
722 | #[test] | 720 | #[test] |
723 | fn test_include_bytes_expand() { | 721 | fn test_include_bytes_expand() { |
724 | let expanded = expand_builtin_macro( | 722 | check_expansion( |
725 | r#" | 723 | r#" |
726 | #[rustc_builtin_macro] | 724 | #[rustc_builtin_macro] |
727 | macro_rules! include_bytes { | 725 | macro_rules! include_bytes { |
@@ -730,21 +728,19 @@ mod tests { | |||
730 | } | 728 | } |
731 | include_bytes("foo"); | 729 | include_bytes("foo"); |
732 | "#, | 730 | "#, |
731 | expect![[r#"b"""#]], | ||
733 | ); | 732 | ); |
734 | |||
735 | assert_eq!(expanded, r#"b"""#); | ||
736 | } | 733 | } |
737 | 734 | ||
738 | #[test] | 735 | #[test] |
739 | fn test_concat_expand() { | 736 | fn test_concat_expand() { |
740 | let expanded = expand_builtin_macro( | 737 | check_expansion( |
741 | r##" | 738 | r##" |
742 | #[rustc_builtin_macro] | 739 | #[rustc_builtin_macro] |
743 | macro_rules! concat {} | 740 | macro_rules! concat {} |
744 | concat!("foo", "r", 0, r#"bar"#, false); | 741 | concat!("foo", "r", 0, r#"bar"#, false); |
745 | "##, | 742 | "##, |
743 | expect![[r#""foor0barfalse""#]], | ||
746 | ); | 744 | ); |
747 | |||
748 | assert_eq!(expanded, r#""foor0barfalse""#); | ||
749 | } | 745 | } |
750 | } | 746 | } |
diff --git a/crates/hir_expand/src/db.rs b/crates/hir_expand/src/db.rs index cb6e23320..9086e6c17 100644 --- a/crates/hir_expand/src/db.rs +++ b/crates/hir_expand/src/db.rs | |||
@@ -340,6 +340,8 @@ fn parse_macro_with_arg( | |||
340 | None => return ExpandResult { value: None, err: result.err }, | 340 | None => return ExpandResult { value: None, err: result.err }, |
341 | }; | 341 | }; |
342 | 342 | ||
343 | log::debug!("expanded = {}", tt.as_debug_string()); | ||
344 | |||
343 | let fragment_kind = to_fragment_kind(db, macro_call_id); | 345 | let fragment_kind = to_fragment_kind(db, macro_call_id); |
344 | 346 | ||
345 | let (parse, rev_token_map) = match mbe::token_tree_to_syntax_node(&tt, fragment_kind) { | 347 | let (parse, rev_token_map) = match mbe::token_tree_to_syntax_node(&tt, fragment_kind) { |
diff --git a/crates/hir_expand/src/name.rs b/crates/hir_expand/src/name.rs index c94fb580a..e833e032c 100644 --- a/crates/hir_expand/src/name.rs +++ b/crates/hir_expand/src/name.rs | |||
@@ -154,6 +154,7 @@ pub mod known { | |||
154 | macro_rules, | 154 | macro_rules, |
155 | derive, | 155 | derive, |
156 | doc, | 156 | doc, |
157 | cfg, | ||
157 | cfg_attr, | 158 | cfg_attr, |
158 | // Components of known path (value or mod name) | 159 | // Components of known path (value or mod name) |
159 | std, | 160 | std, |
diff --git a/crates/hir_expand/src/quote.rs b/crates/hir_expand/src/quote.rs index 219bc2097..08bc5aa49 100644 --- a/crates/hir_expand/src/quote.rs +++ b/crates/hir_expand/src/quote.rs | |||
@@ -188,8 +188,9 @@ macro_rules! impl_to_to_tokentrees { | |||
188 | 188 | ||
189 | impl_to_to_tokentrees! { | 189 | impl_to_to_tokentrees! { |
190 | u32 => self { tt::Literal{text: self.to_string().into(), id: tt::TokenId::unspecified()} }; | 190 | u32 => self { tt::Literal{text: self.to_string().into(), id: tt::TokenId::unspecified()} }; |
191 | usize => self { tt::Literal{text: self.to_string().into(), id: tt::TokenId::unspecified()}}; | 191 | usize => self { tt::Literal{text: self.to_string().into(), id: tt::TokenId::unspecified()} }; |
192 | i32 => self { tt::Literal{text: self.to_string().into(), id: tt::TokenId::unspecified()}}; | 192 | i32 => self { tt::Literal{text: self.to_string().into(), id: tt::TokenId::unspecified()} }; |
193 | bool => self { tt::Ident{text: self.to_string().into(), id: tt::TokenId::unspecified()} }; | ||
193 | tt::Leaf => self { self }; | 194 | tt::Leaf => self { self }; |
194 | tt::Literal => self { self }; | 195 | tt::Literal => self { self }; |
195 | tt::Ident => self { self }; | 196 | tt::Ident => self { self }; |