Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3051,6 +3051,7 @@ impl<'a> ToExpr for MacroArg {
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,
MacroArg::Item(..) => len == 1,
}
}
}
15 changes: 12 additions & 3 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -596,14 +596,23 @@ pub fn format_snippet(snippet: &str, config: &Config) -> Option<String> {
}
}

const FN_MAIN_PREFIX: &str = "fn main() {\n";

fn enclose_in_main_block(s: &str, config: &Config) -> String {
let indent = Indent::from_width(config, config.tab_spaces());
FN_MAIN_PREFIX.to_owned() + &indent.to_string(config)
+ &s.lines()
.collect::<Vec<_>>()
.join(&indent.to_string_with_newline(config)) + "\n}"
}

/// Format the given code block. Mainly targeted for code block in comment.
/// The code block may be incomplete (i.e. parser may be unable to parse it).
/// To avoid panic in parser, we wrap the code block with a dummy function.
/// The returned code block does *not* end with newline.
pub fn format_code_block(code_snippet: &str, config: &Config) -> Option<String> {
// Wrap the given code block with `fn main()` if it does not have one.
let fn_main_prefix = "fn main() {\n";
let snippet = fn_main_prefix.to_owned() + code_snippet + "\n}";
let snippet = enclose_in_main_block(code_snippet, config);
let mut result = String::with_capacity(snippet.len());
let mut is_first = true;

Expand All @@ -612,7 +621,7 @@ pub fn format_code_block(code_snippet: &str, config: &Config) -> Option<String>
let formatted = format_snippet(&snippet, config)?;
// 2 = "}\n"
let block_len = formatted.len().checked_sub(2).unwrap_or(0);
for line in formatted[fn_main_prefix.len()..block_len].lines() {
for line in formatted[FN_MAIN_PREFIX.len()..block_len].lines() {
if !is_first {
result.push('\n');
} else {
Expand Down
25 changes: 20 additions & 5 deletions src/macros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
use std::collections::HashMap;

use config::lists::*;
use syntax::ast;
use syntax::{ast, ptr};
use syntax::codemap::{BytePos, Span};
use syntax::parse::new_parser_from_tts;
use syntax::parse::parser::Parser;
Expand All @@ -38,6 +38,7 @@ use expr::{rewrite_array, rewrite_call_inner};
use lists::{itemize_list, write_list, ListFormatting};
use rewrite::{Rewrite, RewriteContext};
use shape::{Indent, Shape};
use spanned::Spanned;
use utils::{format_visibility, mk_sp, wrap_str};

const FORCED_BRACKET_MACROS: &[&str] = &["vec!"];
Expand Down Expand Up @@ -70,9 +71,21 @@ impl MacroStyle {

#[derive(Debug)]
pub enum MacroArg {
Expr(ast::Expr),
Ty(ast::Ty),
Pat(ast::Pat),
Expr(ptr::P<ast::Expr>),
Ty(ptr::P<ast::Ty>),
Pat(ptr::P<ast::Pat>),
// `parse_item` returns `Option<ptr::P<ast::Item>>`.
Item(Option<ptr::P<ast::Item>>),
}

impl Rewrite for ast::Item {
fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option<String> {
let mut visitor = ::visitor::FmtVisitor::from_context(context);
visitor.block_indent = shape.indent;
visitor.last_pos = self.span().lo();
visitor.visit_item(self);
Some(visitor.buffer)
}
}

impl Rewrite for MacroArg {
Expand All @@ -81,6 +94,7 @@ impl Rewrite for MacroArg {
MacroArg::Expr(ref expr) => expr.rewrite(context, shape),
MacroArg::Ty(ref ty) => ty.rewrite(context, shape),
MacroArg::Pat(ref pat) => pat.rewrite(context, shape),
MacroArg::Item(ref item) => item.as_ref().and_then(|item| item.rewrite(context, shape)),
}
}
}
Expand All @@ -96,7 +110,7 @@ fn parse_macro_arg(parser: &mut Parser) -> Option<MacroArg> {
} else {
// Parsing succeeded.
*parser = cloned_parser;
return Some(MacroArg::$macro_arg((*x).clone()));
return Some(MacroArg::$macro_arg(x.clone()));
}
}
Err(mut e) => {
Expand All @@ -110,6 +124,7 @@ fn parse_macro_arg(parser: &mut Parser) -> Option<MacroArg> {
parse_macro_arg!(Expr, parse_expr);
parse_macro_arg!(Ty, parse_ty);
parse_macro_arg!(Pat, parse_pat);
parse_macro_arg!(Item, parse_item);

None
}
Expand Down
1 change: 1 addition & 0 deletions src/spanned.rs
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,7 @@ impl Spanned for MacroArg {
MacroArg::Expr(ref expr) => expr.span(),
MacroArg::Ty(ref ty) => ty.span(),
MacroArg::Pat(ref pat) => pat.span(),
MacroArg::Item(ref item) => item.as_ref().unwrap().span(),
}
}
}
17 changes: 17 additions & 0 deletions tests/source/issue-2523.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// rustfmt-normalize_comments: true

// Do not unindent macro calls in comment with unformattable syntax.
//! ```rust
//! let x = 3 ;
//! some_macro!(pub fn fn foo() (
//! println!("Don't unindent me!");
//! ));
//! ```
// Format items that appear as arguments of macro call.
//! ```rust
//! let x = 3 ;
//! some_macro!(pub fn foo() {
//! println!("Don't unindent me!");
//! });
//! ```
17 changes: 17 additions & 0 deletions tests/target/issue-2523.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// rustfmt-normalize_comments: true

// Do not unindent macro calls in comment with unformattable syntax.
//! ```rust
//! let x = 3;
//! some_macro!(pub fn fn foo() (
//! println!("Don't unindent me!");
//! ));
//! ```
// Format items that appear as arguments of macro call.
//! ```rust
//! let x = 3;
//! some_macro!(pub fn foo() {
//! println!("Don't unindent me!");
//! });
//! ```