| { | ||
| "git": { | ||
| "sha1": "a3e4ace7092f5f0b750efe22fe8c4b65e8495d94" | ||
| "sha1": "3eb762421182b53411e58ff93765b5604ed89c8b" | ||
| } | ||
| } |
+4
-1
@@ -16,3 +16,3 @@ # THIS FILE IS AUTOMATICALLY GENERATED BY CARGO | ||
| name = "paste" | ||
| version = "1.0.3" | ||
| version = "1.0.4" | ||
| authors = ["David Tolnay <dtolnay@gmail.com>"] | ||
@@ -29,2 +29,5 @@ description = "Macros for all your token pasting needs" | ||
| proc-macro = true | ||
| [dev-dependencies.paste-test-suite] | ||
| version = "0" | ||
| [dev-dependencies.rustversion] | ||
@@ -31,0 +34,0 @@ version = "1.0" |
+42
-20
@@ -14,24 +14,46 @@ use crate::error::Result; | ||
| let mut tokens = attr.clone().into_iter(); | ||
| match tokens.next() { | ||
| Some(TokenTree::Ident(..)) => {} | ||
| _ => return Ok(attr), | ||
| } | ||
| let mut leading_colons = 0; // $(::)? | ||
| let mut leading_path = 0; // $($ident)::+ | ||
| let group = match tokens.next() { | ||
| Some(TokenTree::Punct(ref punct)) if punct.as_char() == '=' => { | ||
| let mut count = 0; | ||
| if tokens.inspect(|_| count += 1).all(|tt| is_stringlike(&tt)) && count > 1 { | ||
| *contains_paste = true; | ||
| return do_paste_name_value_attr(attr, span); | ||
| let mut token; | ||
| let group = loop { | ||
| token = tokens.next(); | ||
| match token { | ||
| // colon after `$(:)?` | ||
| Some(TokenTree::Punct(ref punct)) | ||
| if punct.as_char() == ':' && leading_colons < 2 && leading_path == 0 => | ||
| { | ||
| leading_colons += 1; | ||
| } | ||
| return Ok(attr); | ||
| // ident after `$(::)? $($ident ::)*` | ||
| Some(TokenTree::Ident(_)) if leading_colons != 1 && leading_path % 3 == 0 => { | ||
| leading_path += 1; | ||
| } | ||
| // colon after `$(::)? $($ident ::)* $ident $(:)?` | ||
| Some(TokenTree::Punct(ref punct)) if punct.as_char() == ':' && leading_path % 3 > 0 => { | ||
| leading_path += 1; | ||
| } | ||
| // eq+value after `$(::)? $($ident)::+` | ||
| Some(TokenTree::Punct(ref punct)) | ||
| if punct.as_char() == '=' && leading_path % 3 == 1 => | ||
| { | ||
| let mut count = 0; | ||
| if tokens.inspect(|_| count += 1).all(|tt| is_stringlike(&tt)) && count > 1 { | ||
| *contains_paste = true; | ||
| let leading = leading_colons + leading_path; | ||
| return do_paste_name_value_attr(attr, span, leading); | ||
| } | ||
| return Ok(attr); | ||
| } | ||
| // parens after `$(::)? $($ident)::+` | ||
| Some(TokenTree::Group(ref group)) | ||
| if group.delimiter() == Delimiter::Parenthesis && leading_path % 3 == 1 => | ||
| { | ||
| break group; | ||
| } | ||
| // bail out | ||
| _ => return Ok(attr), | ||
| } | ||
| Some(TokenTree::Group(group)) => group, | ||
| _ => return Ok(attr), | ||
| }; | ||
| if group.delimiter() != Delimiter::Parenthesis { | ||
| return Ok(attr); | ||
| } | ||
| // There can't be anything else after the first group in a valid attribute. | ||
@@ -75,3 +97,3 @@ if tokens.next().is_some() { | ||
| // Just keep the initial ident in `#[ident(...)]`. | ||
| .take(1) | ||
| .take(leading_colons + leading_path) | ||
| .chain(iter::once(TokenTree::Group(group))) | ||
@@ -84,6 +106,6 @@ .collect()) | ||
| fn do_paste_name_value_attr(attr: TokenStream, span: Span) -> Result<TokenStream> { | ||
| fn do_paste_name_value_attr(attr: TokenStream, span: Span, leading: usize) -> Result<TokenStream> { | ||
| let mut expanded = TokenStream::new(); | ||
| let mut tokens = attr.into_iter().peekable(); | ||
| expanded.extend(tokens.by_ref().take(2)); // `doc =` | ||
| expanded.extend(tokens.by_ref().take(leading + 1)); // `doc =` | ||
@@ -90,0 +112,0 @@ let mut segments = segment::parse(&mut tokens)?; |
+6
-9
@@ -211,11 +211,8 @@ //! [![github]](https://github.com/dtolnay/paste) [![crates-io]](https://crates.io/crates/paste) [![docs-rs]](https://docs.rs/paste) | ||
| let mut group_contains_paste = false; | ||
| let nested = match delimiter { | ||
| Delimiter::Bracket if lookbehind == Lookbehind::Pound => { | ||
| expand_attr(content, span, &mut group_contains_paste)? | ||
| } | ||
| Delimiter::Bracket if lookbehind == Lookbehind::PoundBang => { | ||
| expand_attr(content, span, &mut group_contains_paste)? | ||
| } | ||
| _ => expand(content, &mut group_contains_paste)?, | ||
| }; | ||
| let mut nested = expand(content, &mut group_contains_paste)?; | ||
| if delimiter == Delimiter::Bracket | ||
| && (lookbehind == Lookbehind::Pound || lookbehind == Lookbehind::PoundBang) | ||
| { | ||
| nested = expand_attr(nested, span, &mut group_contains_paste)? | ||
| } | ||
| let group = if group_contains_paste { | ||
@@ -222,0 +219,0 @@ let mut group = Group::new(delimiter, nested); |
+23
-0
| use paste::paste; | ||
| use paste_test_suite::paste_test; | ||
| #[test] | ||
| fn test_attr() { | ||
| paste! { | ||
| #[paste_test(k = "val" "ue")] | ||
| struct A; | ||
| #[paste_test_suite::paste_test(k = "val" "ue")] | ||
| struct B; | ||
| #[::paste_test_suite::paste_test(k = "val" "ue")] | ||
| struct C; | ||
| #[paste_test(k = "va" [<l u>] e)] | ||
| struct D; | ||
| } | ||
| let _ = A; | ||
| let _ = B; | ||
| let _ = C; | ||
| let _ = D; | ||
| } | ||
| #[test] | ||
| fn test_paste_cfg() { | ||
@@ -5,0 +28,0 @@ macro_rules! m { |
Sorry, the diff of this file is not supported yet