mirror of
				https://github.com/rust-lang/rust-analyzer.git
				synced 2025-10-31 12:04:43 +00:00 
			
		
		
		
	Merge pull request #19746 from Veykril/push-swvuyqwwplrt
fix: Fix proc-macro API creating malformed negative literals
This commit is contained in:
		
						commit
						aaefc26412
					
				
					 7 changed files with 413 additions and 42 deletions
				
			
		|  | @ -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) | ||||
| } | ||||
|  |  | |||
|  | @ -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) => { | ||||
|  |  | |||
|  | @ -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) => { | ||||
|  |  | |||
|  | @ -68,6 +68,11 @@ impl<S: Copy> TokenStream<S> { | |||
|                         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, | ||||
|  |  | |||
|  | @ -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 | ||||
|  |  | |||
|  | @ -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<String> { | ||||
|  |  | |||
|  | @ -817,6 +817,58 @@ impl<S> fmt::Display for Ident<S> { | |||
|     } | ||||
| } | ||||
| 
 | ||||
| impl<S> Literal<S> { | ||||
|     pub fn display_no_minus(&self) -> impl fmt::Display { | ||||
|         struct NoMinus<'a, S>(&'a Literal<S>); | ||||
|         impl<S> 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:#<num_of_hashes$}"{text}"{0:#<num_of_hashes$}"#, | ||||
|                             "", | ||||
|                             text = symbol | ||||
|                         ) | ||||
|                     } | ||||
|                     LitKind::ByteStrRaw(num_of_hashes) => { | ||||
|                         let num_of_hashes = num_of_hashes as usize; | ||||
|                         write!( | ||||
|                             f, | ||||
|                             r#"br{0:#<num_of_hashes$}"{text}"{0:#<num_of_hashes$}"#, | ||||
|                             "", | ||||
|                             text = symbol | ||||
|                         ) | ||||
|                     } | ||||
|                     LitKind::CStrRaw(num_of_hashes) => { | ||||
|                         let num_of_hashes = num_of_hashes as usize; | ||||
|                         write!( | ||||
|                             f, | ||||
|                             r#"cr{0:#<num_of_hashes$}"{text}"{0:#<num_of_hashes$}"#, | ||||
|                             "", | ||||
|                             text = symbol | ||||
|                         ) | ||||
|                     } | ||||
|                 }?; | ||||
|                 if let Some(suffix) = &self.0.suffix { | ||||
|                     write!(f, "{suffix}")?; | ||||
|                 } | ||||
|                 Ok(()) | ||||
|             } | ||||
|         } | ||||
|         NoMinus(self) | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl<S> fmt::Display for Literal<S> { | ||||
|     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | ||||
|         match self.kind { | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Lukas Wirth
						Lukas Wirth