Accept `.var` shorthand inside of parens

This commit is contained in:
David Tolnay 2019-10-11 10:45:33 -07:00
parent e50cf82f33
commit 7fa5b8114d
No known key found for this signature in database
GPG Key ID: F9BA143B95FF6D82
2 changed files with 40 additions and 6 deletions

View File

@ -1,8 +1,11 @@
use proc_macro2::{TokenStream, TokenTree};
use proc_macro2::{Delimiter, Group, TokenStream, TokenTree};
use quote::{format_ident, quote, ToTokens};
use std::iter::once;
use syn::parse::{Nothing, Parse, ParseStream};
use syn::{Attribute, Error, Field, Ident, Index, LitInt, LitStr, Result, Token};
use syn::{
braced, bracketed, parenthesized, token, Attribute, Error, Field, Ident, Index, LitInt, LitStr,
Result, Token,
};
pub struct Display {
pub fmt: LitStr,
@ -12,16 +15,15 @@ pub struct Display {
impl Parse for Display {
fn parse(input: ParseStream) -> Result<Self> {
let fmt: LitStr = input.parse()?;
let args = input.call(parse_token_expr)?;
let args = parse_token_expr(input, false)?;
let mut display = Display { fmt, args };
display.expand_shorthand();
Ok(display)
}
}
fn parse_token_expr(input: ParseStream) -> Result<TokenStream> {
fn parse_token_expr(input: ParseStream, mut last_is_comma: bool) -> Result<TokenStream> {
let mut tokens = TokenStream::new();
let mut last_is_comma = false;
while !input.is_empty() {
if last_is_comma && input.peek(Token![.]) {
if input.peek2(Ident) {
@ -39,7 +41,30 @@ fn parse_token_expr(input: ParseStream) -> Result<TokenStream> {
}
}
last_is_comma = input.peek(Token![,]);
let token: TokenTree = input.parse()?;
let token: TokenTree = if input.peek(token::Paren) {
let content;
let delimiter = parenthesized!(content in input);
let nested = parse_token_expr(&content, true)?;
let mut group = Group::new(Delimiter::Parenthesis, nested);
group.set_span(delimiter.span);
TokenTree::Group(group)
} else if input.peek(token::Brace) {
let content;
let delimiter = braced!(content in input);
let nested = parse_token_expr(&content, true)?;
let mut group = Group::new(Delimiter::Brace, nested);
group.set_span(delimiter.span);
TokenTree::Group(group)
} else if input.peek(token::Bracket) {
let content;
let delimiter = bracketed!(content in input);
let nested = parse_token_expr(&content, true)?;
let mut group = Group::new(Delimiter::Bracket, nested);
group.set_span(delimiter.span);
TokenTree::Group(group)
} else {
input.parse()?
};
tokens.extend(once(token));
}
Ok(tokens)

View File

@ -35,6 +35,14 @@ enum EnumError {
#[error("1 + 1 = {}", 1 + 1)]
struct Arithmetic;
#[derive(Error, Debug)]
#[error("!bool = {}", not(.0))]
struct NestedShorthand(bool);
fn not(bool: &bool) -> bool {
!*bool
}
fn assert<T: Display>(expected: &str, value: T) {
assert_eq!(expected, value.to_string());
}
@ -54,4 +62,5 @@ fn test_display() {
assert("tuple error: 0", EnumError::Tuple(0));
assert("unit error", EnumError::Unit);
assert("1 + 1 = 2", Arithmetic);
assert("!bool = false", NestedShorthand(true));
}