use std::borrow::Cow;
use std::cmp::min;
+use std::iter;
use itertools::Itertools;
use syntax::parse::token::DelimToken;
use crate::utils::{
colon_spaces, contains_skip, count_newlines, first_line_ends_with, inner_attributes,
last_line_extendable, last_line_width, mk_sp, outer_attributes, ptr_vec_to_ref_vec,
- semicolon_for_expr, semicolon_for_stmt, wrap_str,
+ semicolon_for_expr, unicode_str_width, wrap_str,
};
use crate::vertical::rewrite_with_alignment;
use crate::visitor::FmtVisitor;
path,
fields,
base.as_ref().map(|e| &**e),
+ &expr.attrs,
expr.span,
shape,
),
Some("yield".to_string())
}
}
- ast::ExprKind::Closure(capture, asyncness, movability, ref fn_decl, ref body, _) => {
+ ast::ExprKind::Closure(capture, ref is_async, movability, ref fn_decl, ref body, _) => {
closures::rewrite_closure(
- capture, asyncness, movability, fn_decl, body, expr.span, context, shape,
+ capture, is_async, movability, fn_decl, body, expr.span, context, shape,
)
}
ast::ExprKind::Try(..) | ast::ExprKind::Field(..) | ast::ExprKind::MethodCall(..) => {
))
}
}
- ast::ExprKind::ObsoleteInPlace(ref lhs, ref rhs) => lhs
- .rewrite(context, shape)
- .map(|s| s + " <-")
- .and_then(|lhs| rewrite_assign_rhs(context, lhs, &**rhs, shape)),
ast::ExprKind::Async(capture_by, _node_id, ref block) => {
let mover = if capture_by == ast::CaptureBy::Value {
"move "
))
}
}
+ ast::ExprKind::Await(ast::AwaitOrigin::FieldLike, _) => rewrite_chain(expr, context, shape),
+ ast::ExprKind::Await(ast::AwaitOrigin::MacroLike, ref nested) => {
+ overflow::rewrite_with_parens(
+ context,
+ "await!",
+ iter::once(nested),
+ shape,
+ expr.span,
+ context.config.max_width(),
+ None,
+ )
+ }
ast::ExprKind::Err => None,
};
result
}
-impl Rewrite for ast::Stmt {
- fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option<String> {
- skip_out_of_file_lines_range!(context, self.span());
-
- let result = match self.node {
- ast::StmtKind::Local(ref local) => local.rewrite(context, shape),
- ast::StmtKind::Expr(ref ex) | ast::StmtKind::Semi(ref ex) => {
- let suffix = if semicolon_for_stmt(context, self) {
- ";"
- } else {
- ""
- };
-
- let shape = shape.sub_width(suffix.len())?;
- format_expr(ex, ExprType::Statement, context, shape).map(|s| s + suffix)
- }
- ast::StmtKind::Mac(..) | ast::StmtKind::Item(..) => None,
- };
- result.and_then(|res| recover_comment_removed(res, self.span(), context))
- }
-}
-
// Rewrite condition if the given expression has one.
pub(crate) fn rewrite_cond(
context: &RewriteContext<'_>,
}
}
-pub(crate) fn stmt_is_if(stmt: &ast::Stmt) -> bool {
- match stmt.node {
- ast::StmtKind::Expr(ref e) => match e.node {
- ast::ExprKind::If(..) => true,
- _ => false,
- },
- _ => false,
- }
-}
-
pub(crate) fn is_unsafe_block(block: &ast::Block) -> bool {
if let ast::BlockCheckMode::Unsafe(..) = block.rules {
true
path: &ast::Path,
fields: &'a [ast::Field],
base: Option<&'a ast::Expr>,
+ attrs: &[ast::Attribute],
span: Span,
shape: Shape,
) -> Option<String> {
write_list(&item_vec, &fmt)?
};
- let fields_str = wrap_struct_field(context, &fields_str, shape, v_shape, one_line_width);
+ let fields_str =
+ wrap_struct_field(context, &attrs, &fields_str, shape, v_shape, one_line_width)?;
Some(format!("{} {{{}}}", path_str, fields_str))
// FIXME if context.config.indent_style() == Visual, but we run out
pub(crate) fn wrap_struct_field(
context: &RewriteContext<'_>,
+ attrs: &[ast::Attribute],
fields_str: &str,
shape: Shape,
nested_shape: Shape,
one_line_width: usize,
-) -> String {
- if context.config.indent_style() == IndentStyle::Block
+) -> Option<String> {
+ let should_vertical = context.config.indent_style() == IndentStyle::Block
&& (fields_str.contains('\n')
|| !context.config.struct_lit_single_line()
- || fields_str.len() > one_line_width)
- {
- format!(
- "{}{}{}",
+ || fields_str.len() > one_line_width);
+
+ let inner_attrs = &inner_attributes(attrs);
+ if inner_attrs.is_empty() {
+ if should_vertical {
+ Some(format!(
+ "{}{}{}",
+ nested_shape.indent.to_string_with_newline(context.config),
+ fields_str,
+ shape.indent.to_string_with_newline(context.config)
+ ))
+ } else {
+ // One liner or visual indent.
+ Some(format!(" {} ", fields_str))
+ }
+ } else {
+ Some(format!(
+ "{}{}{}{}{}",
+ nested_shape.indent.to_string_with_newline(context.config),
+ inner_attrs.rewrite(context, shape)?,
nested_shape.indent.to_string_with_newline(context.config),
fields_str,
shape.indent.to_string_with_newline(context.config)
- )
- } else {
- // One liner or visual indent.
- format!(" {} ", fields_str)
+ ))
}
}
rhs_tactics: RhsTactics,
) -> Option<String> {
match orig_rhs {
- Some(ref new_str) if !new_str.contains('\n') && new_str.len() <= shape.width => {
+ Some(ref new_str)
+ if !new_str.contains('\n') && unicode_str_width(new_str) <= shape.width =>
+ {
Some(format!(" {}", new_str))
}
_ => {
}
}
+/// Returns true if formatting next_line_rhs is better on a new line when compared to the
+/// original's line formatting.
+///
+/// It is considered better if:
+/// 1. the tactic is ForceNextLineWithoutIndent
+/// 2. next_line_rhs doesn't have newlines
+/// 3. the original line has more newlines than next_line_rhs
+/// 4. the original formatting of the first line ends with `(`, `{`, or `[` and next_line_rhs
+/// doesn't
pub(crate) fn prefer_next_line(
orig_rhs: &str,
next_line_rhs: &str,