From 4f0c28e1dcc07052c1f8ddce686628c1c8f959c8 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Mon, 5 May 2025 13:56:24 +0200 Subject: [PATCH] fix: Fix proc-macro API creating malformed negative literals --- .../src/server_impl/rust_analyzer_span.rs | 40 ++++++++++++++----- .../src/server_impl/token_id.rs | 40 ++++++++++++++----- .../src/server_impl/token_stream.rs | 5 +++ .../crates/proc-macro-srv/src/tests/mod.rs | 25 +++++++----- 4 files changed, 83 insertions(+), 27 deletions(-) diff --git a/src/tools/rust-analyzer/crates/proc-macro-srv/src/server_impl/rust_analyzer_span.rs b/src/tools/rust-analyzer/crates/proc-macro-srv/src/server_impl/rust_analyzer_span.rs index 47555a5db2f7..64b40e7b9437 100644 --- a/src/tools/rust-analyzer/crates/proc-macro-srv/src/server_impl/rust_analyzer_span.rs +++ b/src/tools/rust-analyzer/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 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 leaf: tt::Leaf = tt::Leaf::from(literal); - let tree = tt::TokenTree::from(leaf); - TokenStream { token_trees: vec![tree] } + 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/src/tools/rust-analyzer/crates/proc-macro-srv/src/server_impl/token_id.rs b/src/tools/rust-analyzer/crates/proc-macro-srv/src/server_impl/token_id.rs index c002be4be6ff..24a67bf45c8d 100644 --- a/src/tools/rust-analyzer/crates/proc-macro-srv/src/server_impl/token_id.rs +++ b/src/tools/rust-analyzer/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 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 leaf = tt::Leaf::from(literal); - let tree = TokenTree::from(leaf); - TokenStream { token_trees: vec![tree] } + 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/src/tools/rust-analyzer/crates/proc-macro-srv/src/server_impl/token_stream.rs b/src/tools/rust-analyzer/crates/proc-macro-srv/src/server_impl/token_stream.rs index 4946a4f2a621..072557913c2b 100644 --- a/src/tools/rust-analyzer/crates/proc-macro-srv/src/server_impl/token_stream.rs +++ b/src/tools/rust-analyzer/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/src/tools/rust-analyzer/crates/proc-macro-srv/src/tests/mod.rs b/src/tools/rust-analyzer/crates/proc-macro-srv/src/tests/mod.rs index 7a0ac01c50da..36cd675b9a6f 100644 --- a/src/tools/rust-analyzer/crates/proc-macro-srv/src/tests/mod.rs +++ b/src/tools/rust-analyzer/crates/proc-macro-srv/src/tests/mod.rs @@ -248,13 +248,17 @@ fn test_fn_like_mk_literals() { LITERAL Str string 1 LITERAL CStr cstring 1 LITERAL Float 3.14f64 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 Float -3.14 1 LITERAL Integer 123i64 1 - LITERAL Integer -123i64 1 + PUNCH - [alone] 1 + LITERAL Integer 123i64 1 LITERAL Integer 123 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 @@ -266,13 +270,17 @@ fn test_fn_like_mk_literals() { 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 - 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 Float -3.14 42:2@0..100#ROOT2024 LITERAL Integer 123i64 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 - LITERAL Integer -123 42:2@0..100#ROOT2024"#]], + PUNCH - [alone] 42:2@0..100#ROOT2024 + LITERAL Integer 123 42:2@0..100#ROOT2024"#]], ); } @@ -400,7 +408,6 @@ fn test_fn_like_macro_clone_literals() { ); } - #[test] fn test_fn_like_macro_negative_literals() { assert_expand(