From 848d4559e1629c4a6a603844217daaee479b486b Mon Sep 17 00:00:00 2001 From: topecongiro Date: Wed, 30 Aug 2017 12:00:10 +0900 Subject: [PATCH] Enhance macro rewrite --- src/expr.rs | 19 ++++++- src/lib.rs | 45 ++++++++------- src/macros.rs | 123 +++++++++++++++++++++++++++-------------- tests/source/macros.rs | 17 +++++- tests/target/macros.rs | 24 +++++++- 5 files changed, 156 insertions(+), 72 deletions(-) diff --git a/src/expr.rs b/src/expr.rs index ffab5b02f5a..05707d79960 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -26,7 +26,7 @@ use items::{span_hi_for_arg, span_lo_for_arg}; use lists::{definitive_tactic, itemize_list, shape_for_tactic, struct_lit_formatting, struct_lit_shape, struct_lit_tactic, write_list, DefinitiveListTactic, ListFormatting, ListItem, ListTactic, Separator, SeparatorPlace, SeparatorTactic}; -use macros::{rewrite_macro, MacroPosition}; +use macros::{rewrite_macro, MacroArg, MacroPosition}; use patterns::{can_be_overflowed_pat, TuplePatField}; use rewrite::{Rewrite, RewriteContext}; use string::{rewrite_string, StringFormat}; @@ -3015,3 +3015,20 @@ impl<'a> ToExpr for ast::StructField { false } } + +impl<'a> ToExpr for MacroArg { + fn to_expr(&self) -> Option<&ast::Expr> { + match self { + &MacroArg::Expr(ref expr) => Some(expr), + _ => None, + } + } + + fn can_be_overflowed(&self, context: &RewriteContext, len: usize) -> bool { + match self { + &MacroArg::Expr(ref expr) => can_be_overflowed_expr(context, expr, len), + &MacroArg::Ty(ref ty) => can_be_overflowed_type(context, ty, len), + &MacroArg::Pat(..) => false, + } + } +} diff --git a/src/lib.rs b/src/lib.rs index 8152973af43..596fa5b5396 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -34,6 +34,7 @@ use std::rc::Rc; use errors::{DiagnosticBuilder, Handler}; use errors::emitter::{ColorConfig, EmitterWriter}; +use macros::MacroArg; use strings::string_buffer::StringBuffer; use syntax::ast; use syntax::codemap::{CodeMap, FilePathMapping, Span}; @@ -216,6 +217,16 @@ impl Spanned for ast::TyParamBound { } } +impl Spanned for MacroArg { + fn span(&self) -> Span { + match *self { + MacroArg::Expr(ref expr) => expr.span(), + MacroArg::Ty(ref ty) => ty.span(), + MacroArg::Pat(ref pat) => pat.span(), + } + } +} + #[derive(Copy, Clone, Debug)] pub struct Indent { // Width of the block indent, in characters. Must be a multiple of @@ -682,7 +693,6 @@ fn format_ast( parse_session: &mut ParseSess, main_file: &Path, config: &Config, - codemap: &Rc, mut after_file: F, ) -> Result<(FileMap, bool), io::Error> where @@ -703,29 +713,19 @@ where if config.verbose() { println!("Formatting {}", path_str); } - { - let mut visitor = FmtVisitor::from_codemap(parse_session, config); - let filemap = visitor.codemap.lookup_char_pos(module.inner.lo()).file; - // Format inner attributes if available. - if !krate.attrs.is_empty() && path == main_file { - visitor.visit_attrs(&krate.attrs, ast::AttrStyle::Inner); - } else { - visitor.last_pos = filemap.start_pos; - } - visitor.format_separate_mod(module, &*filemap); + let mut visitor = FmtVisitor::from_codemap(parse_session, config); + let filemap = visitor.codemap.lookup_char_pos(module.inner.lo()).file; + // Format inner attributes if available. + if !krate.attrs.is_empty() && path == main_file { + visitor.visit_attrs(&krate.attrs, ast::AttrStyle::Inner); + } else { + visitor.last_pos = filemap.start_pos; + } + visitor.format_separate_mod(module, &*filemap); - has_diff |= after_file(path_str, &mut visitor.buffer)?; + has_diff |= after_file(path_str, &mut visitor.buffer)?; - result.push((path_str.to_owned(), visitor.buffer)); - } - // Reset the error count. - if parse_session.span_diagnostic.has_errors() { - let silent_emitter = Box::new(EmitterWriter::new( - Box::new(Vec::new()), - Some(codemap.clone()), - )); - parse_session.span_diagnostic = Handler::with_emitter(true, false, silent_emitter); - } + result.push((path_str.to_owned(), visitor.buffer)); } Ok((result, has_diff)) @@ -913,7 +913,6 @@ pub fn format_input( &mut parse_session, &main_file, config, - &codemap, |file_name, file| { // For some reason, the codemap does not include terminating // newlines so we must add one on for each file. This is sad. diff --git a/src/macros.rs b/src/macros.rs index d9156e08e85..800dfaef2e4 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -22,6 +22,7 @@ use syntax::ast; use syntax::codemap::BytePos; use syntax::parse::new_parser_from_tts; +use syntax::parse::parser::Parser; use syntax::parse::token::Token; use syntax::symbol; use syntax::tokenstream::TokenStream; @@ -61,6 +62,51 @@ impl MacroStyle { } } +pub enum MacroArg { + Expr(ast::Expr), + Ty(ast::Ty), + Pat(ast::Pat), +} + +impl Rewrite for MacroArg { + fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option { + match self { + &MacroArg::Expr(ref expr) => expr.rewrite(context, shape), + &MacroArg::Ty(ref ty) => ty.rewrite(context, shape), + &MacroArg::Pat(ref pat) => pat.rewrite(context, shape), + } + } +} + +fn parse_macro_arg(parser: &mut Parser) -> Option { + macro_rules! parse_macro_arg { + ($target:tt, $macro_arg:ident, $parser:ident) => { + let mut cloned_parser = (*parser).clone(); + match cloned_parser.$parser() { + Ok($target) => { + if parser.sess.span_diagnostic.has_errors() { + parser.sess.span_diagnostic.reset_err_count(); + } else { + // Parsing succeeded. + *parser = cloned_parser; + return Some(MacroArg::$macro_arg((*$target).clone())); + } + } + Err(mut e) => { + e.cancel(); + parser.sess.span_diagnostic.reset_err_count(); + } + } + } + } + + parse_macro_arg!(expr, Expr, parse_expr); + parse_macro_arg!(ty, Ty, parse_ty); + parse_macro_arg!(pat, Pat, parse_pat); + + return None; +} + pub fn rewrite_macro( mac: &ast::Mac, extra_ident: Option, @@ -93,7 +139,7 @@ pub fn rewrite_macro( original_style }; - let ts: TokenStream = mac.node.tts.clone().into(); + let ts: TokenStream = mac.node.stream(); if ts.is_empty() && !contains_comment(&context.snippet(mac.span)) { return match style { MacroStyle::Parens if position == MacroPosition::Item => { @@ -106,32 +152,16 @@ pub fn rewrite_macro( } let mut parser = new_parser_from_tts(context.parse_session, ts.trees().collect()); - let mut expr_vec = Vec::new(); + let mut arg_vec = Vec::new(); let mut vec_with_semi = false; let mut trailing_comma = false; if MacroStyle::Braces != style { loop { - let expr = match parser.parse_expr() { - Ok(expr) => { - // Recovered errors. - if context.parse_session.span_diagnostic.has_errors() { - return indent_macro_snippet( - context, - &context.snippet(mac.span), - shape.indent, - ); - } - - expr - } - Err(mut e) => { - e.cancel(); - return indent_macro_snippet(context, &context.snippet(mac.span), shape.indent); - } - }; - - expr_vec.push(expr); + match parse_macro_arg(&mut parser) { + Some(arg) => arg_vec.push(arg), + None => return Some(context.snippet(mac.span)), + } match parser.token { Token::Eof => break, @@ -141,25 +171,22 @@ pub fn rewrite_macro( if FORCED_BRACKET_MACROS.contains(&¯o_name[..]) { parser.bump(); if parser.token != Token::Eof { - match parser.parse_expr() { - Ok(expr) => { - if context.parse_session.span_diagnostic.has_errors() { - return None; - } - expr_vec.push(expr); + match parse_macro_arg(&mut parser) { + Some(arg) => { + arg_vec.push(arg); parser.bump(); - if parser.token == Token::Eof && expr_vec.len() == 2 { + if parser.token == Token::Eof && arg_vec.len() == 2 { vec_with_semi = true; break; } } - Err(mut e) => e.cancel(), + None => return Some(context.snippet(mac.span)), } } } - return None; + return Some(context.snippet(mac.span)); } - _ => return None, + _ => return Some(context.snippet(mac.span)), } parser.bump(); @@ -178,7 +205,7 @@ pub fn rewrite_macro( let rw = rewrite_call_inner( context, ¯o_name, - &expr_vec.iter().map(|e| &**e).collect::>()[..], + &arg_vec.iter().map(|e| &*e).collect::>()[..], mac.span, shape, context.config.fn_call_width(), @@ -201,8 +228,8 @@ pub fn rewrite_macro( // 6 = `vec!` + `; ` let total_overhead = lbr.len() + rbr.len() + 6; let nested_shape = mac_shape.block_indent(context.config.tab_spaces()); - let lhs = try_opt!(expr_vec[0].rewrite(context, nested_shape)); - let rhs = try_opt!(expr_vec[1].rewrite(context, nested_shape)); + let lhs = try_opt!(arg_vec[0].rewrite(context, nested_shape)); + let rhs = try_opt!(arg_vec[1].rewrite(context, nested_shape)); if !lhs.contains('\n') && !rhs.contains('\n') && lhs.len() + rhs.len() + total_overhead <= shape.width { @@ -228,14 +255,26 @@ pub fn rewrite_macro( context.inside_macro = false; trailing_comma = false; } + // Convert `MacroArg` into `ast::Expr`, as `rewrite_array` only accepts the latter. + let expr_vec: Vec<_> = arg_vec + .iter() + .filter_map(|e| match *e { + MacroArg::Expr(ref e) => Some(e.clone()), + _ => None, + }) + .collect(); + if expr_vec.len() != arg_vec.len() { + return Some(context.snippet(mac.span)); + } + let sp = mk_sp( + context + .codemap + .span_after(mac.span, original_style.opener()), + mac.span.hi() - BytePos(1), + ); let rewrite = try_opt!(rewrite_array( - expr_vec.iter().map(|x| &**x), - mk_sp( - context - .codemap - .span_after(mac.span, original_style.opener()), - mac.span.hi() - BytePos(1), - ), + expr_vec.iter(), + sp, context, mac_shape, trailing_comma, diff --git a/tests/source/macros.rs b/tests/source/macros.rs index caccd75a700..10f6e2d7ea0 100644 --- a/tests/source/macros.rs +++ b/tests/source/macros.rs @@ -164,9 +164,6 @@ fn issue_1921() { } } -// Put the following tests with macro invocations whose arguments cannot be parsed as expressioins -// at the end of the file for now. - // #1577 fn issue1577() { let json = json!({ @@ -178,3 +175,17 @@ gfx_pipeline!(pipe { vbuf: gfx::VertexBuffer = (), out: gfx::RenderTarget = "Target0", }); + +// #1919 +#[test] +fn __bindgen_test_layout_HandleWithDtor_open0_int_close0_instantiation() { + assert_eq!( + ::std::mem::size_of::>(), + 8usize, + concat!( + "Size of template specialization: ", + stringify ! ( HandleWithDtor < :: std :: os :: raw :: c_int > ) + ) + ); + assert_eq ! ( :: std :: mem :: align_of :: < HandleWithDtor < :: std :: os :: raw :: c_int > > ( ) , 8usize , concat ! ( "Alignment of template specialization: " , stringify ! ( HandleWithDtor < :: std :: os :: raw :: c_int > ) ) ); +} diff --git a/tests/target/macros.rs b/tests/target/macros.rs index 0b651cc5445..d47063d255c 100644 --- a/tests/target/macros.rs +++ b/tests/target/macros.rs @@ -208,9 +208,6 @@ fn issue_1921() { } } -// Put the following tests with macro invocations whose arguments cannot be parsed as expressioins -// at the end of the file for now. - // #1577 fn issue1577() { let json = json!({ @@ -222,3 +219,24 @@ gfx_pipeline!(pipe { vbuf: gfx::VertexBuffer = (), out: gfx::RenderTarget = "Target0", }); + +// #1919 +#[test] +fn __bindgen_test_layout_HandleWithDtor_open0_int_close0_instantiation() { + assert_eq!( + ::std::mem::size_of::>(), + 8usize, + concat!( + "Size of template specialization: ", + stringify!(HandleWithDtor<::std::os::raw::c_int>) + ) + ); + assert_eq!( + ::std::mem::align_of::>(), + 8usize, + concat!( + "Alignment of template specialization: ", + stringify!(HandleWithDtor<::std::os::raw::c_int>) + ) + ); +}