// List-like invocations with parentheses will be formatted as function calls,
// and those with brackets will be formatted as array literals.
-use std::thread;
-
use syntax::ast;
-use syntax::parse::token::{Eof, Comma, Token};
-use syntax::parse::{ParseSess, tts_to_parser};
+use syntax::parse::token::Token;
+use syntax::parse::tts_to_parser;
+use syntax::codemap::{mk_sp, BytePos};
use Indent;
use rewrite::RewriteContext;
use expr::{rewrite_call, rewrite_array};
use comment::FindUncommented;
-use utils::wrap_str;
+use utils::{wrap_str, span_after};
-// We need to pass `TokenTree`s to our expression parsing thread, but they are
-// not `Send`. We wrap them in a `Send` container to force our will.
-// FIXME: this is a pretty terrible hack. Any other solution would be preferred.
-struct ForceSend<T>(pub T);
-unsafe impl<T> Send for ForceSend<T> {}
+static FORCED_BRACKET_MACROS: &'static [&'static str] = &["vec!"];
// FIXME: use the enum from libsyntax?
+#[derive(Clone, Copy)]
enum MacroStyle {
Parens,
Brackets,
Braces,
}
+impl MacroStyle {
+ fn opener(&self) -> &'static str {
+ match *self {
+ MacroStyle::Parens => "(",
+ MacroStyle::Brackets => "[",
+ MacroStyle::Braces => "{",
+ }
+ }
+}
+
pub fn rewrite_macro(mac: &ast::Mac,
context: &RewriteContext,
width: usize,
offset: Indent)
-> Option<String> {
- let style = macro_style(mac, context);
+ let original_style = macro_style(mac, context);
let macro_name = format!("{}!", mac.node.path);
+ let style = if FORCED_BRACKET_MACROS.contains(&¯o_name[..]) {
+ MacroStyle::Brackets
+ } else {
+ original_style
+ };
if let MacroStyle::Braces = style {
return None;
};
}
- let wrapped_tt_vec = ForceSend(mac.node.tts.clone());
- // Wrap expression parsing logic in a thread since the libsyntax parser
- // panicks on failure, which we do not want to propagate.
- let expr_vec_result = thread::catch_panic(move || {
- let parse_session = ParseSess::new();
- let mut parser = tts_to_parser(&parse_session, wrapped_tt_vec.0, vec![]);
- let mut expr_vec = vec![];
-
- loop {
- expr_vec.push(parser.parse_expr());
+ let mut parser = tts_to_parser(context.parse_session, mac.node.tts.clone(), Vec::new());
+ let mut expr_vec = Vec::new();
- match parser.token {
- Token::Eof => break,
- Token::Comma => (),
- _ => panic!("Macro not list-like, skiping..."),
- }
+ loop {
+ expr_vec.push(match parser.parse_expr() {
+ Ok(expr) => expr,
+ Err(..) => return None,
+ });
- let _ = parser.bump();
+ match parser.token {
+ Token::Eof => break,
+ Token::Comma => (),
+ _ => return None,
}
- expr_vec
- });
- let expr_vec = try_opt!(expr_vec_result.ok());
+ let _ = parser.bump();
+
+ if parser.token == Token::Eof {
+ return None;
+ }
+ }
match style {
MacroStyle::Parens => {
// Format macro invocation as array literal.
let extra_offset = macro_name.len();
let rewrite = try_opt!(rewrite_array(expr_vec.iter().map(|x| &**x),
- mac.span,
+ mk_sp(span_after(mac.span,
+ original_style.opener(),
+ context.codemap),
+ mac.span.hi - BytePos(1)),
context,
try_opt!(width.checked_sub(extra_offset)),
offset + extra_offset));
+
Some(format!("{}{}", macro_name, rewrite))
}
MacroStyle::Braces => {
// Skip macro invocations with braces, for now.
- wrap_str(context.snippet(mac.span), context.config.max_width, width, offset)
+ wrap_str(context.snippet(mac.span),
+ context.config.max_width,
+ width,
+ offset)
}
}
}