From 9a7ea6aacb12dd7b0aadc0cb9140f77d1ea1251f Mon Sep 17 00:00:00 2001 From: topecongiro Date: Fri, 8 Feb 2019 12:28:35 +0900 Subject: [PATCH] Handle a macro argument with a single keyword Closes #3331. --- src/macros.rs | 101 +++++++++++++++++++++++++++++++++++++---- src/overflow.rs | 1 + src/spanned.rs | 1 + tests/source/macros.rs | 8 ++++ tests/target/macros.rs | 8 ++++ 5 files changed, 110 insertions(+), 9 deletions(-) diff --git a/src/macros.rs b/src/macros.rs index a925331f9fe..6b4c353cfd2 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -26,7 +26,7 @@ use syntax::parse::parser::Parser; use syntax::parse::token::{BinOpToken, DelimToken, Token}; use syntax::print::pprust; use syntax::source_map::{BytePos, Span}; -use syntax::symbol; +use syntax::symbol::keywords; use syntax::tokenstream::{Cursor, TokenStream, TokenTree}; use syntax::ThinVec; use syntax::{ast, parse, ptr}; @@ -64,6 +64,7 @@ pub enum MacroArg { Ty(ptr::P), Pat(ptr::P), Item(ptr::P), + Keyword(ast::Ident, Span), } impl MacroArg { @@ -92,6 +93,7 @@ impl Rewrite for MacroArg { MacroArg::Ty(ref ty) => ty.rewrite(context, shape), MacroArg::Pat(ref pat) => pat.rewrite(context, shape), MacroArg::Item(ref item) => item.rewrite(context, shape), + MacroArg::Keyword(ident, _) => Some(ident.to_string()), } } } @@ -156,7 +158,7 @@ fn rewrite_macro_name( format!("{}!", path) }; match extra_ident { - Some(ident) if ident != symbol::keywords::Invalid.ident() => format!("{} {}", name, ident), + Some(ident) if ident != keywords::Invalid.ident() => format!("{} {}", name, ident), _ => name, } } @@ -224,6 +226,23 @@ pub fn rewrite_macro( result } +fn check_keyword<'a, 'b: 'a>(parser: &'a mut Parser<'b>) -> Option { + for &keyword in RUST_KEYWORDS.iter() { + if parser.token.is_keyword(keyword) + && parser.look_ahead(1, |t| { + *t == Token::Eof + || *t == Token::Comma + || *t == Token::CloseDelim(DelimToken::NoDelim) + }) + { + let macro_arg = MacroArg::Keyword(keyword.ident(), parser.span); + parser.bump(); + return Some(macro_arg); + } + } + None +} + pub fn rewrite_macro_inner( mac: &ast::Mac, extra_ident: Option, @@ -276,11 +295,12 @@ pub fn rewrite_macro_inner( if DelimToken::Brace != style { loop { - match parse_macro_arg(&mut parser) { - Some(arg) => arg_vec.push(arg), - None => { - return return_macro_parse_failure_fallback(context, shape.indent, mac.span); - } + if let Some(arg) = parse_macro_arg(&mut parser) { + arg_vec.push(arg); + } else if let Some(arg) = check_keyword(&mut parser) { + arg_vec.push(arg); + } else { + return return_macro_parse_failure_fallback(context, shape.indent, mac.span); } match parser.token { @@ -1373,8 +1393,8 @@ fn format_lazy_static(context: &RewriteContext, shape: Shape, ts: &TokenStream) while parser.token != Token::Eof { // Parse a `lazy_static!` item. let vis = crate::utils::format_visibility(context, &parse_or!(parse_visibility, false)); - parser.eat_keyword(symbol::keywords::Static); - parser.eat_keyword(symbol::keywords::Ref); + parser.eat_keyword(keywords::Static); + parser.eat_keyword(keywords::Ref); let id = parse_or!(parse_ident); parser.eat(&Token::Colon); let ty = parse_or!(parse_ty); @@ -1449,3 +1469,66 @@ fn rewrite_macro_with_items( result.push_str(trailing_semicolon); Some(result) } + +const RUST_KEYWORDS: [keywords::Keyword; 60] = [ + keywords::PathRoot, + keywords::DollarCrate, + keywords::Underscore, + keywords::As, + keywords::Box, + keywords::Break, + keywords::Const, + keywords::Continue, + keywords::Crate, + keywords::Else, + keywords::Enum, + keywords::Extern, + keywords::False, + keywords::Fn, + keywords::For, + keywords::If, + keywords::Impl, + keywords::In, + keywords::Let, + keywords::Loop, + keywords::Match, + keywords::Mod, + keywords::Move, + keywords::Mut, + keywords::Pub, + keywords::Ref, + keywords::Return, + keywords::SelfLower, + keywords::SelfUpper, + keywords::Static, + keywords::Struct, + keywords::Super, + keywords::Trait, + keywords::True, + keywords::Type, + keywords::Unsafe, + keywords::Use, + keywords::Where, + keywords::While, + keywords::Abstract, + keywords::Become, + keywords::Do, + keywords::Final, + keywords::Macro, + keywords::Override, + keywords::Priv, + keywords::Typeof, + keywords::Unsized, + keywords::Virtual, + keywords::Yield, + keywords::Dyn, + keywords::Async, + keywords::Try, + keywords::UnderscoreLifetime, + keywords::StaticLifetime, + keywords::Auto, + keywords::Catch, + keywords::Default, + keywords::Existential, + keywords::Union, +]; diff --git a/src/overflow.rs b/src/overflow.rs index 04456aea106..6a2895d4ff9 100644 --- a/src/overflow.rs +++ b/src/overflow.rs @@ -167,6 +167,7 @@ impl<'a> OverflowableItem<'a> { MacroArg::Ty(ref ty) => can_be_overflowed_type(context, ty, len), MacroArg::Pat(..) => false, MacroArg::Item(..) => len == 1, + MacroArg::Keyword(..) => false, }, OverflowableItem::NestedMetaItem(nested_meta_item) if len == 1 => { match nested_meta_item.node { diff --git a/src/spanned.rs b/src/spanned.rs index ab021ed7ec1..9c45d6ae705 100644 --- a/src/spanned.rs +++ b/src/spanned.rs @@ -198,6 +198,7 @@ impl Spanned for MacroArg { MacroArg::Ty(ref ty) => ty.span(), MacroArg::Pat(ref pat) => pat.span(), MacroArg::Item(ref item) => item.span(), + MacroArg::Keyword(_, span) => span, } } } diff --git a/tests/source/macros.rs b/tests/source/macros.rs index 5386d68898d..d41a72e52f1 100644 --- a/tests/source/macros.rs +++ b/tests/source/macros.rs @@ -463,3 +463,11 @@ fn issue3004() { foo!(|_| { ( ) }); stringify!(( foo+ )); } + +// #3331 +pub fn fold_abi(_visitor: &mut V, _i: Abi) -> Abi { + Abi { + extern_token: Token ! [ extern ](tokens_helper(_visitor, &_i.extern_token.span)), + name: (_i.name).map(|it| _visitor.fold_lit_str(it)), + } +} diff --git a/tests/target/macros.rs b/tests/target/macros.rs index ca5f91b715e..d0fe892d91b 100644 --- a/tests/target/macros.rs +++ b/tests/target/macros.rs @@ -1040,3 +1040,11 @@ fn issue3004() { foo!(|_| { () }); stringify!((foo+)); } + +// #3331 +pub fn fold_abi(_visitor: &mut V, _i: Abi) -> Abi { + Abi { + extern_token: Token![extern](tokens_helper(_visitor, &_i.extern_token.span)), + name: (_i.name).map(|it| _visitor.fold_lit_str(it)), + } +}