diff --git a/crates/proc-macro-srv/proc-macro-test/imp/src/lib.rs b/crates/proc-macro-srv/proc-macro-test/imp/src/lib.rs index dfdbb4c95fca..6820e4b33539 100644 --- a/crates/proc-macro-srv/proc-macro-test/imp/src/lib.rs +++ b/crates/proc-macro-srv/proc-macro-test/imp/src/lib.rs @@ -31,12 +31,17 @@ pub fn fn_like_mk_literals(_args: TokenStream) -> TokenStream { TokenTree::from(Literal::byte_string(b"byte_string")), TokenTree::from(Literal::character('c')), TokenTree::from(Literal::string("string")), + TokenTree::from(Literal::c_string(c"cstring")), // as of 2022-07-21, there's no method on `Literal` to build a raw // string or a raw byte string TokenTree::from(Literal::f64_suffixed(3.14)), + TokenTree::from(Literal::f64_suffixed(-3.14)), TokenTree::from(Literal::f64_unsuffixed(3.14)), + TokenTree::from(Literal::f64_unsuffixed(-3.14)), TokenTree::from(Literal::i64_suffixed(123)), + TokenTree::from(Literal::i64_suffixed(-123)), TokenTree::from(Literal::i64_unsuffixed(123)), + TokenTree::from(Literal::i64_unsuffixed(-123)), ]; TokenStream::from_iter(trees) } diff --git a/crates/proc-macro-srv/src/server_impl/rust_analyzer_span.rs b/crates/proc-macro-srv/src/server_impl/rust_analyzer_span.rs index 47555a5db2f7..64b40e7b9437 100644 --- a/crates/proc-macro-srv/src/server_impl/rust_analyzer_span.rs +++ b/crates/proc-macro-srv/src/server_impl/rust_analyzer_span.rs @@ -168,16 +168,38 @@ impl server::TokenStream for RaSpanServer { } bridge::TokenTree::Literal(literal) => { - let literal = tt::Literal { - symbol: literal.symbol, - suffix: literal.suffix, - span: literal.span, - kind: literal_kind_to_internal(literal.kind), - }; - - let leaf: tt::Leaf = tt::Leaf::from(literal); - let tree = tt::TokenTree::from(leaf); - TokenStream { token_trees: vec![tree] } + let token_trees = + if let Some((_minus, symbol)) = literal.symbol.as_str().split_once('-') { + let punct = tt::Punct { + spacing: tt::Spacing::Alone, + span: literal.span, + char: '-' as char, + }; + let leaf: tt::Leaf = tt::Leaf::from(punct); + let minus_tree = tt::TokenTree::from(leaf); + + let literal = tt::Literal { + symbol: Symbol::intern(symbol), + suffix: literal.suffix, + span: literal.span, + kind: literal_kind_to_internal(literal.kind), + }; + let leaf: tt::Leaf = tt::Leaf::from(literal); + let tree = tt::TokenTree::from(leaf); + vec![minus_tree, tree] + } else { + let literal = tt::Literal { + symbol: literal.symbol, + suffix: literal.suffix, + span: literal.span, + kind: literal_kind_to_internal(literal.kind), + }; + + let leaf: tt::Leaf = tt::Leaf::from(literal); + let tree = tt::TokenTree::from(leaf); + vec![tree] + }; + TokenStream { token_trees } } bridge::TokenTree::Punct(p) => { diff --git a/crates/proc-macro-srv/src/server_impl/token_id.rs b/crates/proc-macro-srv/src/server_impl/token_id.rs index c002be4be6ff..24a67bf45c8d 100644 --- a/crates/proc-macro-srv/src/server_impl/token_id.rs +++ b/crates/proc-macro-srv/src/server_impl/token_id.rs @@ -153,16 +153,38 @@ impl server::TokenStream for TokenIdServer { } bridge::TokenTree::Literal(literal) => { - let literal = Literal { - symbol: literal.symbol, - suffix: literal.suffix, - span: literal.span, - kind: literal_kind_to_internal(literal.kind), - }; - - let leaf = tt::Leaf::from(literal); - let tree = TokenTree::from(leaf); - TokenStream { token_trees: vec![tree] } + let token_trees = + if let Some((_minus, symbol)) = literal.symbol.as_str().split_once('-') { + let punct = tt::Punct { + spacing: tt::Spacing::Alone, + span: literal.span, + char: '-' as char, + }; + let leaf: tt::Leaf = tt::Leaf::from(punct); + let minus_tree = tt::TokenTree::from(leaf); + + let literal = Literal { + symbol: Symbol::intern(symbol), + suffix: literal.suffix, + span: literal.span, + kind: literal_kind_to_internal(literal.kind), + }; + let leaf: tt::Leaf = tt::Leaf::from(literal); + let tree = tt::TokenTree::from(leaf); + vec![minus_tree, tree] + } else { + let literal = Literal { + symbol: literal.symbol, + suffix: literal.suffix, + span: literal.span, + kind: literal_kind_to_internal(literal.kind), + }; + + let leaf: tt::Leaf = tt::Leaf::from(literal); + let tree = tt::TokenTree::from(leaf); + vec![tree] + }; + TokenStream { token_trees } } bridge::TokenTree::Punct(p) => { diff --git a/crates/proc-macro-srv/src/server_impl/token_stream.rs b/crates/proc-macro-srv/src/server_impl/token_stream.rs index 4946a4f2a621..072557913c2b 100644 --- a/crates/proc-macro-srv/src/server_impl/token_stream.rs +++ b/crates/proc-macro-srv/src/server_impl/token_stream.rs @@ -68,6 +68,11 @@ impl TokenStream { span: ident.span, })) } + // Note, we do not have to assemble our `-` punct and literal split into a single + // negative bridge literal here. As the proc-macro docs state + // > Literals created from negative numbers might not survive round-trips through + // > TokenStream or strings and may be broken into two tokens (- and positive + // > literal). tt::TokenTree::Leaf(tt::Leaf::Literal(lit)) => { result.push(bridge::TokenTree::Literal(bridge::Literal { span: lit.span, diff --git a/crates/proc-macro-srv/src/tests/mod.rs b/crates/proc-macro-srv/src/tests/mod.rs index 011221459657..36cd675b9a6f 100644 --- a/crates/proc-macro-srv/src/tests/mod.rs +++ b/crates/proc-macro-srv/src/tests/mod.rs @@ -11,8 +11,24 @@ fn test_derive_empty() { assert_expand( "DeriveEmpty", r#"struct S;"#, - expect!["SUBTREE $$ 1 1"], - expect!["SUBTREE $$ 42:2@0..100#ROOT2024 42:2@0..100#ROOT2024"], + expect![[r#" + SUBTREE $$ 1 1 + IDENT struct 1 + IDENT S 1 + PUNCH ; [alone] 1 + + + + SUBTREE $$ 1 1"#]], + expect![[r#" + SUBTREE $$ 42:2@0..100#ROOT2024 42:2@0..100#ROOT2024 + IDENT struct 42:2@0..6#ROOT2024 + IDENT S 42:2@7..8#ROOT2024 + PUNCH ; [alone] 42:2@8..9#ROOT2024 + + + + SUBTREE $$ 42:2@0..100#ROOT2024 42:2@0..100#ROOT2024"#]], ); } @@ -22,6 +38,13 @@ fn test_derive_error() { "DeriveError", r#"struct S;"#, expect![[r#" + SUBTREE $$ 1 1 + IDENT struct 1 + IDENT S 1 + PUNCH ; [alone] 1 + + + SUBTREE $$ 1 1 IDENT compile_error 1 PUNCH ! [alone] 1 @@ -29,6 +52,13 @@ fn test_derive_error() { LITERAL Str #[derive(DeriveError)] struct S ; 1 PUNCH ; [alone] 1"#]], expect![[r#" + SUBTREE $$ 42:2@0..100#ROOT2024 42:2@0..100#ROOT2024 + IDENT struct 42:2@0..6#ROOT2024 + IDENT S 42:2@7..8#ROOT2024 + PUNCH ; [alone] 42:2@8..9#ROOT2024 + + + SUBTREE $$ 42:2@0..100#ROOT2024 42:2@0..100#ROOT2024 IDENT compile_error 42:2@0..100#ROOT2024 PUNCH ! [alone] 42:2@0..100#ROOT2024 @@ -44,6 +74,17 @@ fn test_fn_like_macro_noop() { "fn_like_noop", r#"ident, 0, 1, []"#, expect![[r#" + SUBTREE $$ 1 1 + IDENT ident 1 + PUNCH , [alone] 1 + LITERAL Integer 0 1 + PUNCH , [alone] 1 + LITERAL Integer 1 1 + PUNCH , [alone] 1 + SUBTREE [] 1 1 + + + SUBTREE $$ 1 1 IDENT ident 1 PUNCH , [alone] 1 @@ -53,6 +94,17 @@ fn test_fn_like_macro_noop() { PUNCH , [alone] 1 SUBTREE [] 1 1"#]], expect![[r#" + SUBTREE $$ 42:2@0..100#ROOT2024 42:2@0..100#ROOT2024 + IDENT ident 42:2@0..5#ROOT2024 + PUNCH , [alone] 42:2@5..6#ROOT2024 + LITERAL Integer 0 42:2@7..8#ROOT2024 + PUNCH , [alone] 42:2@8..9#ROOT2024 + LITERAL Integer 1 42:2@10..11#ROOT2024 + PUNCH , [alone] 42:2@11..12#ROOT2024 + SUBTREE [] 42:2@13..14#ROOT2024 42:2@14..15#ROOT2024 + + + SUBTREE $$ 42:2@0..100#ROOT2024 42:2@0..100#ROOT2024 IDENT ident 42:2@0..5#ROOT2024 PUNCH , [alone] 42:2@5..6#ROOT2024 @@ -70,11 +122,25 @@ fn test_fn_like_macro_clone_ident_subtree() { "fn_like_clone_tokens", r#"ident, []"#, expect![[r#" + SUBTREE $$ 1 1 + IDENT ident 1 + PUNCH , [alone] 1 + SUBTREE [] 1 1 + + + SUBTREE $$ 1 1 IDENT ident 1 PUNCH , [alone] 1 SUBTREE [] 1 1"#]], expect![[r#" + SUBTREE $$ 42:2@0..100#ROOT2024 42:2@0..100#ROOT2024 + IDENT ident 42:2@0..5#ROOT2024 + PUNCH , [alone] 42:2@5..6#ROOT2024 + SUBTREE [] 42:2@7..8#ROOT2024 42:2@8..9#ROOT2024 + + + SUBTREE $$ 42:2@0..100#ROOT2024 42:2@0..100#ROOT2024 IDENT ident 42:2@0..5#ROOT2024 PUNCH , [alone] 42:2@5..6#ROOT2024 @@ -88,9 +154,19 @@ fn test_fn_like_macro_clone_raw_ident() { "fn_like_clone_tokens", "r#async", expect![[r#" + SUBTREE $$ 1 1 + IDENT r#async 1 + + + SUBTREE $$ 1 1 IDENT r#async 1"#]], expect![[r#" + SUBTREE $$ 42:2@0..100#ROOT2024 42:2@0..100#ROOT2024 + IDENT r#async 42:2@0..7#ROOT2024 + + + SUBTREE $$ 42:2@0..100#ROOT2024 42:2@0..100#ROOT2024 IDENT r#async 42:2@0..7#ROOT2024"#]], ); @@ -103,9 +179,21 @@ fn test_fn_like_fn_like_span_join() { "fn_like_span_join", "foo bar", expect![[r#" + SUBTREE $$ 1 1 + IDENT foo 1 + IDENT bar 1 + + + SUBTREE $$ 1 1 IDENT r#joined 1"#]], expect![[r#" + SUBTREE $$ 42:2@0..100#ROOT2024 42:2@0..100#ROOT2024 + IDENT foo 42:2@0..3#ROOT2024 + IDENT bar 42:2@8..11#ROOT2024 + + + SUBTREE $$ 42:2@0..100#ROOT2024 42:2@0..100#ROOT2024 IDENT r#joined 42:2@0..11#ROOT2024"#]], ); @@ -118,11 +206,25 @@ fn test_fn_like_fn_like_span_ops() { "fn_like_span_ops", "set_def_site resolved_at_def_site start_span", expect![[r#" + SUBTREE $$ 1 1 + IDENT set_def_site 1 + IDENT resolved_at_def_site 1 + IDENT start_span 1 + + + SUBTREE $$ 1 1 IDENT set_def_site 0 IDENT resolved_at_def_site 1 IDENT start_span 1"#]], expect![[r#" + SUBTREE $$ 42:2@0..100#ROOT2024 42:2@0..100#ROOT2024 + IDENT set_def_site 42:2@0..12#ROOT2024 + IDENT resolved_at_def_site 42:2@13..33#ROOT2024 + IDENT start_span 42:2@34..44#ROOT2024 + + + SUBTREE $$ 42:2@0..100#ROOT2024 42:2@0..100#ROOT2024 IDENT set_def_site 41:1@0..150#ROOT2024 IDENT resolved_at_def_site 42:2@13..33#ROOT2024 @@ -136,22 +238,48 @@ fn test_fn_like_mk_literals() { "fn_like_mk_literals", r#""#, expect![[r#" + SUBTREE $$ 1 1 + + + SUBTREE $$ 1 1 LITERAL ByteStr byte_string 1 LITERAL Char c 1 LITERAL Str string 1 + LITERAL CStr cstring 1 LITERAL Float 3.14f64 1 + PUNCH - [alone] 1 + LITERAL Float 3.14f64 1 + LITERAL Float 3.14 1 + PUNCH - [alone] 1 LITERAL Float 3.14 1 LITERAL Integer 123i64 1 + PUNCH - [alone] 1 + LITERAL Integer 123i64 1 + LITERAL Integer 123 1 + PUNCH - [alone] 1 LITERAL Integer 123 1"#]], expect![[r#" + SUBTREE $$ 42:2@0..100#ROOT2024 42:2@0..100#ROOT2024 + + + SUBTREE $$ 42:2@0..100#ROOT2024 42:2@0..100#ROOT2024 LITERAL ByteStr byte_string 42:2@0..100#ROOT2024 LITERAL Char c 42:2@0..100#ROOT2024 LITERAL Str string 42:2@0..100#ROOT2024 + LITERAL CStr cstring 42:2@0..100#ROOT2024 + LITERAL Float 3.14f64 42:2@0..100#ROOT2024 + PUNCH - [alone] 42:2@0..100#ROOT2024 LITERAL Float 3.14f64 42:2@0..100#ROOT2024 LITERAL Float 3.14 42:2@0..100#ROOT2024 + PUNCH - [alone] 42:2@0..100#ROOT2024 + LITERAL Float 3.14 42:2@0..100#ROOT2024 + LITERAL Integer 123i64 42:2@0..100#ROOT2024 + PUNCH - [alone] 42:2@0..100#ROOT2024 LITERAL Integer 123i64 42:2@0..100#ROOT2024 + LITERAL Integer 123 42:2@0..100#ROOT2024 + PUNCH - [alone] 42:2@0..100#ROOT2024 LITERAL Integer 123 42:2@0..100#ROOT2024"#]], ); } @@ -162,10 +290,18 @@ fn test_fn_like_mk_idents() { "fn_like_mk_idents", r#""#, expect![[r#" + SUBTREE $$ 1 1 + + + SUBTREE $$ 1 1 IDENT standard 1 IDENT r#raw 1"#]], expect![[r#" + SUBTREE $$ 42:2@0..100#ROOT2024 42:2@0..100#ROOT2024 + + + SUBTREE $$ 42:2@0..100#ROOT2024 42:2@0..100#ROOT2024 IDENT standard 42:2@0..100#ROOT2024 IDENT r#raw 42:2@0..100#ROOT2024"#]], @@ -178,6 +314,30 @@ fn test_fn_like_macro_clone_literals() { "fn_like_clone_tokens", r###"1u16, 2_u32, -4i64, 3.14f32, "hello bridge", "suffixed"suffix, r##"raw"##, 'a', b'b', c"null""###, expect![[r#" + SUBTREE $$ 1 1 + LITERAL Integer 1u16 1 + PUNCH , [alone] 1 + LITERAL Integer 2_u32 1 + PUNCH , [alone] 1 + PUNCH - [alone] 1 + LITERAL Integer 4i64 1 + PUNCH , [alone] 1 + LITERAL Float 3.14f32 1 + PUNCH , [alone] 1 + LITERAL Str hello bridge 1 + PUNCH , [alone] 1 + LITERAL Str suffixedsuffix 1 + PUNCH , [alone] 1 + LITERAL StrRaw(2) raw 1 + PUNCH , [alone] 1 + LITERAL Char a 1 + PUNCH , [alone] 1 + LITERAL Byte b 1 + PUNCH , [alone] 1 + LITERAL CStr null 1 + + + SUBTREE $$ 1 1 LITERAL Integer 1u16 1 PUNCH , [alone] 1 @@ -200,6 +360,30 @@ fn test_fn_like_macro_clone_literals() { PUNCH , [alone] 1 LITERAL CStr null 1"#]], expect![[r#" + SUBTREE $$ 42:2@0..100#ROOT2024 42:2@0..100#ROOT2024 + LITERAL Integer 1u16 42:2@0..4#ROOT2024 + PUNCH , [alone] 42:2@4..5#ROOT2024 + LITERAL Integer 2_u32 42:2@6..11#ROOT2024 + PUNCH , [alone] 42:2@11..12#ROOT2024 + PUNCH - [alone] 42:2@13..14#ROOT2024 + LITERAL Integer 4i64 42:2@14..18#ROOT2024 + PUNCH , [alone] 42:2@18..19#ROOT2024 + LITERAL Float 3.14f32 42:2@20..27#ROOT2024 + PUNCH , [alone] 42:2@27..28#ROOT2024 + LITERAL Str hello bridge 42:2@29..43#ROOT2024 + PUNCH , [alone] 42:2@43..44#ROOT2024 + LITERAL Str suffixedsuffix 42:2@45..61#ROOT2024 + PUNCH , [alone] 42:2@61..62#ROOT2024 + LITERAL StrRaw(2) raw 42:2@63..73#ROOT2024 + PUNCH , [alone] 42:2@73..74#ROOT2024 + LITERAL Char a 42:2@75..78#ROOT2024 + PUNCH , [alone] 42:2@78..79#ROOT2024 + LITERAL Byte b 42:2@80..84#ROOT2024 + PUNCH , [alone] 42:2@84..85#ROOT2024 + LITERAL CStr null 42:2@86..93#ROOT2024 + + + SUBTREE $$ 42:2@0..100#ROOT2024 42:2@0..100#ROOT2024 LITERAL Integer 1u16 42:2@0..4#ROOT2024 PUNCH , [alone] 42:2@4..5#ROOT2024 @@ -224,6 +408,70 @@ fn test_fn_like_macro_clone_literals() { ); } +#[test] +fn test_fn_like_macro_negative_literals() { + assert_expand( + "fn_like_clone_tokens", + r###"-1u16, - 2_u32, -3.14f32, - 2.7"###, + expect![[r#" + SUBTREE $$ 1 1 + PUNCH - [alone] 1 + LITERAL Integer 1u16 1 + PUNCH , [alone] 1 + PUNCH - [alone] 1 + LITERAL Integer 2_u32 1 + PUNCH , [alone] 1 + PUNCH - [alone] 1 + LITERAL Float 3.14f32 1 + PUNCH , [alone] 1 + PUNCH - [alone] 1 + LITERAL Float 2.7 1 + + + + SUBTREE $$ 1 1 + PUNCH - [alone] 1 + LITERAL Integer 1u16 1 + PUNCH , [alone] 1 + PUNCH - [alone] 1 + LITERAL Integer 2_u32 1 + PUNCH , [alone] 1 + PUNCH - [alone] 1 + LITERAL Float 3.14f32 1 + PUNCH , [alone] 1 + PUNCH - [alone] 1 + LITERAL Float 2.7 1"#]], + expect![[r#" + SUBTREE $$ 42:2@0..100#ROOT2024 42:2@0..100#ROOT2024 + PUNCH - [alone] 42:2@0..1#ROOT2024 + LITERAL Integer 1u16 42:2@1..5#ROOT2024 + PUNCH , [alone] 42:2@5..6#ROOT2024 + PUNCH - [alone] 42:2@7..8#ROOT2024 + LITERAL Integer 2_u32 42:2@9..14#ROOT2024 + PUNCH , [alone] 42:2@14..15#ROOT2024 + PUNCH - [alone] 42:2@16..17#ROOT2024 + LITERAL Float 3.14f32 42:2@17..24#ROOT2024 + PUNCH , [alone] 42:2@24..25#ROOT2024 + PUNCH - [alone] 42:2@26..27#ROOT2024 + LITERAL Float 2.7 42:2@28..31#ROOT2024 + + + + SUBTREE $$ 42:2@0..100#ROOT2024 42:2@0..100#ROOT2024 + PUNCH - [alone] 42:2@0..1#ROOT2024 + LITERAL Integer 1u16 42:2@1..5#ROOT2024 + PUNCH , [alone] 42:2@5..6#ROOT2024 + PUNCH - [alone] 42:2@7..8#ROOT2024 + LITERAL Integer 2_u32 42:2@9..14#ROOT2024 + PUNCH , [alone] 42:2@14..15#ROOT2024 + PUNCH - [alone] 42:2@16..17#ROOT2024 + LITERAL Float 3.14f32 42:2@17..24#ROOT2024 + PUNCH , [alone] 42:2@24..25#ROOT2024 + PUNCH - [alone] 42:2@26..27#ROOT2024 + LITERAL Float 2.7 42:2@28..31#ROOT2024"#]], + ); +} + #[test] fn test_attr_macro() { // Corresponds to @@ -234,6 +482,15 @@ fn test_attr_macro() { r#"mod m {}"#, r#"some arguments"#, expect![[r#" + SUBTREE $$ 1 1 + IDENT mod 1 + IDENT m 1 + SUBTREE {} 1 1 + + SUBTREE $$ 1 1 + IDENT some 1 + IDENT arguments 1 + SUBTREE $$ 1 1 IDENT compile_error 1 PUNCH ! [alone] 1 @@ -241,6 +498,15 @@ fn test_attr_macro() { LITERAL Str #[attr_error(some arguments)] mod m {} 1 PUNCH ; [alone] 1"#]], expect![[r#" + SUBTREE $$ 42:2@0..100#ROOT2024 42:2@0..100#ROOT2024 + IDENT mod 42:2@0..3#ROOT2024 + IDENT m 42:2@4..5#ROOT2024 + SUBTREE {} 42:2@6..7#ROOT2024 42:2@7..8#ROOT2024 + + SUBTREE $$ 42:2@0..100#ROOT2024 42:2@0..100#ROOT2024 + IDENT some 42:2@0..4#ROOT2024 + IDENT arguments 42:2@5..14#ROOT2024 + SUBTREE $$ 42:2@0..100#ROOT2024 42:2@0..100#ROOT2024 IDENT compile_error 42:2@0..100#ROOT2024 PUNCH ! [alone] 42:2@0..100#ROOT2024 diff --git a/crates/proc-macro-srv/src/tests/utils.rs b/crates/proc-macro-srv/src/tests/utils.rs index a476a70a7409..a0a45b269e4a 100644 --- a/crates/proc-macro-srv/src/tests/utils.rs +++ b/crates/proc-macro-srv/src/tests/utils.rs @@ -32,9 +32,9 @@ pub fn assert_expand( macro_name: &str, #[rust_analyzer::rust_fixture] ra_fixture: &str, expect: Expect, - expect_s: Expect, + expect_spanned: Expect, ) { - assert_expand_impl(macro_name, ra_fixture, None, expect, expect_s); + assert_expand_impl(macro_name, ra_fixture, None, expect, expect_spanned); } pub fn assert_expand_attr( @@ -42,9 +42,9 @@ pub fn assert_expand_attr( #[rust_analyzer::rust_fixture] ra_fixture: &str, attr_args: &str, expect: Expect, - expect_s: Expect, + expect_spanned: Expect, ) { - assert_expand_impl(macro_name, ra_fixture, Some(attr_args), expect, expect_s); + assert_expand_impl(macro_name, ra_fixture, Some(attr_args), expect, expect_spanned); } fn assert_expand_impl( @@ -52,7 +52,7 @@ fn assert_expand_impl( input: &str, attr: Option<&str>, expect: Expect, - expect_s: Expect, + expect_spanned: Expect, ) { let path = proc_macro_test_dylib_path(); let expander = dylib::Expander::new(&path).unwrap(); @@ -60,20 +60,17 @@ fn assert_expand_impl( let def_site = TokenId(0); let call_site = TokenId(1); let mixed_site = TokenId(2); - let input_ts = parse_string(call_site, input); + let input_ts = parse_string(call_site, input).into_subtree(call_site); let attr_ts = attr.map(|attr| parse_string(call_site, attr).into_subtree(call_site)); + let input_ts_string = format!("{input_ts:?}"); + let attr_ts_string = attr_ts.as_ref().map(|it| format!("{it:?}")); - let res = expander - .expand( - macro_name, - input_ts.into_subtree(call_site), - attr_ts, - def_site, - call_site, - mixed_site, - ) - .unwrap(); - expect.assert_eq(&format!("{res:?}")); + let res = + expander.expand(macro_name, input_ts, attr_ts, def_site, call_site, mixed_site).unwrap(); + expect.assert_eq(&format!( + "{input_ts_string}\n\n{}\n\n{res:?}", + attr_ts_string.unwrap_or_default() + )); let def_site = Span { range: TextRange::new(0.into(), 150.into()), @@ -93,15 +90,17 @@ fn assert_expand_impl( }; let mixed_site = call_site; - let fixture = parse_string_spanned(call_site.anchor, call_site.ctx, input); + let fixture = + parse_string_spanned(call_site.anchor, call_site.ctx, input).into_subtree(call_site); let attr = attr.map(|attr| { parse_string_spanned(call_site.anchor, call_site.ctx, attr).into_subtree(call_site) }); + let fixture_string = format!("{fixture:?}"); + let attr_string = attr.as_ref().map(|it| format!("{it:?}")); - let res = expander - .expand(macro_name, fixture.into_subtree(call_site), attr, def_site, call_site, mixed_site) - .unwrap(); - expect_s.assert_eq(&format!("{res:#?}")); + let res = expander.expand(macro_name, fixture, attr, def_site, call_site, mixed_site).unwrap(); + expect_spanned + .assert_eq(&format!("{fixture_string}\n\n{}\n\n{res:#?}", attr_string.unwrap_or_default())); } pub(crate) fn list() -> Vec { diff --git a/crates/tt/src/lib.rs b/crates/tt/src/lib.rs index 1dbc07c0929c..a511bb0039cb 100644 --- a/crates/tt/src/lib.rs +++ b/crates/tt/src/lib.rs @@ -817,6 +817,58 @@ impl fmt::Display for Ident { } } +impl Literal { + pub fn display_no_minus(&self) -> impl fmt::Display { + struct NoMinus<'a, S>(&'a Literal); + impl fmt::Display for NoMinus<'_, S> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let symbol = + self.0.symbol.as_str().strip_prefix('-').unwrap_or(self.0.symbol.as_str()); + match self.0.kind { + LitKind::Byte => write!(f, "b'{}'", symbol), + LitKind::Char => write!(f, "'{}'", symbol), + LitKind::Integer | LitKind::Float | LitKind::Err(_) => write!(f, "{}", symbol), + LitKind::Str => write!(f, "\"{}\"", symbol), + LitKind::ByteStr => write!(f, "b\"{}\"", symbol), + LitKind::CStr => write!(f, "c\"{}\"", symbol), + LitKind::StrRaw(num_of_hashes) => { + let num_of_hashes = num_of_hashes as usize; + write!( + f, + r#"r{0:# { + let num_of_hashes = num_of_hashes as usize; + write!( + f, + r#"br{0:# { + let num_of_hashes = num_of_hashes as usize; + write!( + f, + r#"cr{0:# fmt::Display for Literal { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self.kind {