// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use std::cmp::{Ordering, min};
use std::mem::swap;
use std::ops::Deref;
use std::iter::ExactSizeIterator;
use std::fmt::Write;

use {Indent, Shape, Spanned};
use codemap::SpanUtils;
use rewrite::{Rewrite, RewriteContext};
use lists::{write_list, itemize_list, ListFormatting, SeparatorTactic, ListTactic,
            DefinitiveListTactic, definitive_tactic, ListItem, format_item_list, struct_lit_shape,
            struct_lit_tactic, shape_for_tactic, struct_lit_formatting};
use string::{StringFormat, rewrite_string};
use utils::{extra_offset, last_line_width, wrap_str, binary_search, first_line_width,
            semicolon_for_stmt, trimmed_last_line_width, left_most_sub_expr, stmt_expr,
            colon_spaces, contains_skip, mk_sp};
use visitor::FmtVisitor;
use config::{Config, IndentStyle, MultilineStyle, ControlBraceStyle, Style};
use comment::{FindUncommented, rewrite_comment, contains_comment, recover_comment_removed};
use types::{rewrite_path, PathContext};
use items::{span_lo_for_arg, span_hi_for_arg};
use chains::rewrite_chain;
use macros::{rewrite_macro, MacroPosition};

use syntax::{ast, ptr};
use syntax::codemap::{CodeMap, Span, BytePos};
use syntax::parse::classify;

impl Rewrite for ast::Expr {
    fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option<String> {
        format_expr(self, ExprType::SubExpression, context, shape)
    }
}

#[derive(PartialEq)]
enum ExprType {
    Statement,
    SubExpression,
}

fn format_expr(expr: &ast::Expr,
               expr_type: ExprType,
               context: &RewriteContext,
               shape: Shape)
               -> Option<String> {
    if contains_skip(&*expr.attrs) {
        return Some(context.snippet(expr.span));
    }
    let attr_rw = (&*expr.attrs).rewrite(context, shape);
    let expr_rw = match expr.node {
        ast::ExprKind::Array(ref expr_vec) => {
            rewrite_array(expr_vec.iter().map(|e| &**e),
                          mk_sp(context.codemap.span_after(expr.span, "["), expr.span.hi),
                          context,
                          shape)
        }
        ast::ExprKind::Lit(ref l) => {
            match l.node {
                ast::LitKind::Str(_, ast::StrStyle::Cooked) => {
                    rewrite_string_lit(context, l.span, shape)
                }
                _ => {
                    wrap_str(context.snippet(expr.span),
                             context.config.max_width(),
                             shape)
                }
            }
        }
        ast::ExprKind::Call(ref callee, ref args) => {
            let inner_span = mk_sp(callee.span.hi, expr.span.hi);
            rewrite_call_with_binary_search(context, &**callee, args, inner_span, shape)
        }
        ast::ExprKind::Paren(ref subexpr) => rewrite_paren(context, subexpr, shape),
        ast::ExprKind::Binary(ref op, ref lhs, ref rhs) => {
            // FIXME: format comments between operands and operator
            rewrite_pair(&**lhs,
                         &**rhs,
                         "",
                         &format!(" {} ", context.snippet(op.span)),
                         "",
                         context,
                         shape)
        }
        ast::ExprKind::Unary(ref op, ref subexpr) => rewrite_unary_op(context, op, subexpr, shape),
        ast::ExprKind::Struct(ref path, ref fields, ref base) => {
            rewrite_struct_lit(context,
                               path,
                               fields,
                               base.as_ref().map(|e| &**e),
                               expr.span,
                               shape)
        }
        ast::ExprKind::Tup(ref items) => rewrite_tuple(context, items, expr.span, shape),
        ast::ExprKind::While(ref cond, ref block, label) => {
            ControlFlow::new_while(None, cond, block, label, expr.span).rewrite(context, shape)
        }
        ast::ExprKind::WhileLet(ref pat, ref cond, ref block, label) => {
            ControlFlow::new_while(Some(pat), cond, block, label, expr.span).rewrite(context, shape)
        }
        ast::ExprKind::ForLoop(ref pat, ref cond, ref block, label) => {
            ControlFlow::new_for(pat, cond, block, label, expr.span).rewrite(context, shape)
        }
        ast::ExprKind::Loop(ref block, label) => {
            ControlFlow::new_loop(block, label, expr.span).rewrite(context, shape)
        }
        ast::ExprKind::Block(ref block) => block.rewrite(context, shape),
        ast::ExprKind::If(ref cond, ref if_block, ref else_block) => {
            ControlFlow::new_if(cond,
                                None,
                                if_block,
                                else_block.as_ref().map(|e| &**e),
                                expr_type == ExprType::SubExpression,
                                false,
                                expr.span)
                .rewrite(context, shape)
        }
        ast::ExprKind::IfLet(ref pat, ref cond, ref if_block, ref else_block) => {
            ControlFlow::new_if(cond,
                                Some(pat),
                                if_block,
                                else_block.as_ref().map(|e| &**e),
                                expr_type == ExprType::SubExpression,
                                false,
                                expr.span)
                .rewrite(context, shape)
        }
        ast::ExprKind::Match(ref cond, ref arms) => {
            rewrite_match(context, cond, arms, shape, expr.span)
        }
        ast::ExprKind::Path(ref qself, ref path) => {
            rewrite_path(context, PathContext::Expr, qself.as_ref(), path, shape)
        }
        ast::ExprKind::Assign(ref lhs, ref rhs) => {
            rewrite_assignment(context, lhs, rhs, None, shape)
        }
        ast::ExprKind::AssignOp(ref op, ref lhs, ref rhs) => {
            rewrite_assignment(context, lhs, rhs, Some(op), shape)
        }
        ast::ExprKind::Continue(ref opt_ident) => {
            let id_str = match *opt_ident {
                Some(ident) => format!(" {}", ident.node),
                None => String::new(),
            };
            wrap_str(format!("continue{}", id_str),
                     context.config.max_width(),
                     shape)
        }
        ast::ExprKind::Break(ref opt_ident, ref opt_expr) => {
            let id_str = match *opt_ident {
                Some(ident) => format!(" {}", ident.node),
                None => String::new(),
            };

            if let Some(ref expr) = *opt_expr {
                rewrite_unary_prefix(context, &format!("break{} ", id_str), &**expr, shape)
            } else {
                wrap_str(format!("break{}", id_str),
                         context.config.max_width(),
                         shape)
            }
        }
        ast::ExprKind::Closure(capture, ref fn_decl, ref body, _) => {
            rewrite_closure(capture, fn_decl, body, expr.span, context, shape)
        }
        ast::ExprKind::Try(..) |
        ast::ExprKind::Field(..) |
        ast::ExprKind::TupField(..) |
        ast::ExprKind::MethodCall(..) => rewrite_chain(expr, context, shape),
        ast::ExprKind::Mac(ref mac) => {
            // Failure to rewrite a marco should not imply failure to
            // rewrite the expression.
            rewrite_macro(mac, None, context, shape, MacroPosition::Expression).or_else(|| {
                wrap_str(context.snippet(expr.span),
                         context.config.max_width(),
                         shape)
            })
        }
        ast::ExprKind::Ret(None) => {
            wrap_str("return".to_owned(), context.config.max_width(), shape)
        }
        ast::ExprKind::Ret(Some(ref expr)) => {
            rewrite_unary_prefix(context, "return ", &**expr, shape)
        }
        ast::ExprKind::Box(ref expr) => rewrite_unary_prefix(context, "box ", &**expr, shape),
        ast::ExprKind::AddrOf(mutability, ref expr) => {
            rewrite_expr_addrof(context, mutability, expr, shape)
        }
        ast::ExprKind::Cast(ref expr, ref ty) => {
            rewrite_pair(&**expr, &**ty, "", " as ", "", context, shape)
        }
        ast::ExprKind::Type(ref expr, ref ty) => {
            rewrite_pair(&**expr, &**ty, "", ": ", "", context, shape)
        }
        ast::ExprKind::Index(ref expr, ref index) => {
            rewrite_index(&**expr, &**index, context, shape)
        }
        ast::ExprKind::Repeat(ref expr, ref repeats) => {
            let (lbr, rbr) = if context.config.spaces_within_square_brackets() {
                ("[ ", " ]")
            } else {
                ("[", "]")
            };
            rewrite_pair(&**expr, &**repeats, lbr, "; ", rbr, context, shape)
        }
        ast::ExprKind::Range(ref lhs, ref rhs, limits) => {
            let delim = match limits {
                ast::RangeLimits::HalfOpen => "..",
                ast::RangeLimits::Closed => "...",
            };

            match (lhs.as_ref().map(|x| &**x), rhs.as_ref().map(|x| &**x)) {
                (Some(ref lhs), Some(ref rhs)) => {
                    let sp_delim = if context.config.spaces_around_ranges() {
                        format!(" {} ", delim)
                    } else {
                        delim.into()
                    };
                    rewrite_pair(&**lhs, &**rhs, "", &sp_delim, "", context, shape)
                }
                (None, Some(ref rhs)) => {
                    let sp_delim = if context.config.spaces_around_ranges() {
                        format!("{} ", delim)
                    } else {
                        delim.into()
                    };
                    rewrite_unary_prefix(context, &sp_delim, &**rhs, shape)
                }
                (Some(ref lhs), None) => {
                    let sp_delim = if context.config.spaces_around_ranges() {
                        format!(" {}", delim)
                    } else {
                        delim.into()
                    };
                    rewrite_unary_suffix(context, &sp_delim, &**lhs, shape)
                }
                (None, None) => wrap_str(delim.into(), context.config.max_width(), shape),
            }
        }
        // We do not format these expressions yet, but they should still
        // satisfy our width restrictions.
        ast::ExprKind::InPlace(..) |
        ast::ExprKind::InlineAsm(..) => {
            wrap_str(context.snippet(expr.span),
                     context.config.max_width(),
                     shape)
        }
        ast::ExprKind::Catch(ref block) => {
            if let rewrite @ Some(_) = try_one_line_block(context, shape, "do catch ", block) {
                return rewrite;
            }
            // 9 = `do catch `
            let budget = shape.width.checked_sub(9).unwrap_or(0);
            Some(format!("{}{}",
                         "do catch ",
                         try_opt!(block.rewrite(&context, Shape::legacy(budget, shape.indent)))))
        }
    };
    match (attr_rw, expr_rw) {
        (Some(attr_str), Some(expr_str)) => {
            let space = if attr_str.is_empty() { "" } else { " " };
            recover_comment_removed(format!("{}{}{}", attr_str, space, expr_str),
                                    expr.span,
                                    context,
                                    shape)
        }
        _ => None,
    }
}

fn try_one_line_block(context: &RewriteContext,
                      shape: Shape,
                      prefix: &str,
                      block: &ast::Block)
                      -> Option<String> {
    if is_simple_block(block, context.codemap) {
        let expr_shape = Shape::legacy(shape.width - prefix.len(), shape.indent);
        let expr_str = try_opt!(block.stmts[0].rewrite(context, expr_shape));
        let result = format!("{}{{ {} }}", prefix, expr_str);
        if result.len() <= shape.width && !result.contains('\n') {
            return Some(result);
        }
    }
    None
}

pub fn rewrite_pair<LHS, RHS>(lhs: &LHS,
                              rhs: &RHS,
                              prefix: &str,
                              infix: &str,
                              suffix: &str,
                              context: &RewriteContext,
                              shape: Shape)
                              -> Option<String>
    where LHS: Rewrite,
          RHS: Rewrite
{
    // Get "full width" rhs and see if it fits on the current line. This
    // usually works fairly well since it tends to place operands of
    // operations with high precendence close together.
    // Note that this is non-conservative, but its just to see if it's even
    // worth trying to put everything on one line.
    let rhs_shape = try_opt!(shape.sub_width(suffix.len()));
    let rhs_result = rhs.rewrite(context, rhs_shape);

    if let Some(rhs_result) = rhs_result {
        // This is needed in case of line break not caused by a
        // shortage of space, but by end-of-line comments, for example.
        if !rhs_result.contains('\n') {
            let lhs_shape = try_opt!(shape.sub_width(prefix.len() + infix.len()));
            let lhs_result = lhs.rewrite(context, lhs_shape);
            if let Some(lhs_result) = lhs_result {
                let mut result = format!("{}{}{}", prefix, lhs_result, infix);

                let remaining_width = shape
                    .width
                    .checked_sub(last_line_width(&result) + suffix.len())
                    .unwrap_or(0);

                if rhs_result.len() <= remaining_width {
                    result.push_str(&rhs_result);
                    result.push_str(suffix);
                    return Some(result);
                }

                // Try rewriting the rhs into the remaining space.
                let rhs_shape = shape.shrink_left(last_line_width(&result) + suffix.len());
                if let Some(rhs_shape) = rhs_shape {
                    if let Some(rhs_result) = rhs.rewrite(context, rhs_shape) {
                        // FIXME this should always hold.
                        if rhs_result.len() <= remaining_width {
                            result.push_str(&rhs_result);
                            result.push_str(suffix);
                            return Some(result);
                        }
                    }
                }
            }
        }
    }

    // We have to use multiple lines.

    // Re-evaluate the rhs because we have more space now:
    let infix = infix.trim_right();
    let lhs_budget = try_opt!(context
                                  .config
                                  .max_width()
                                  .checked_sub(shape.used_width() + prefix.len() + infix.len()));
    let rhs_shape = match context.config.control_style() {
        Style::Default => {
            try_opt!(shape.sub_width(suffix.len() + prefix.len())).visual_indent(prefix.len())
        }
        Style::Rfc => try_opt!(shape.block_left(context.config.tab_spaces())),
    };

    let rhs_result = try_opt!(rhs.rewrite(context, rhs_shape));
    let lhs_result = try_opt!(lhs.rewrite(context,
                                          Shape {
                                              width: lhs_budget,
                                              ..shape
                                          }));
    Some(format!("{}{}{}\n{}{}{}",
                 prefix,
                 lhs_result,
                 infix,
                 rhs_shape.indent.to_string(context.config),
                 rhs_result,
                 suffix))
}

pub fn rewrite_array<'a, I>(expr_iter: I,
                            span: Span,
                            context: &RewriteContext,
                            shape: Shape)
                            -> Option<String>
    where I: Iterator<Item = &'a ast::Expr>
{
    let bracket_size = if context.config.spaces_within_square_brackets() {
        2 // "[ "
    } else {
        1 // "["
    };

    let nested_shape = match context.config.array_layout() {
        IndentStyle::Block => shape.block().block_indent(context.config.tab_spaces()),
        IndentStyle::Visual => {
            try_opt!(shape
                         .visual_indent(bracket_size)
                         .sub_width(bracket_size * 2))
        }
    };

    let items = itemize_list(context.codemap,
                             expr_iter,
                             "]",
                             |item| item.span.lo,
                             |item| item.span.hi,
                             |item| item.rewrite(context, nested_shape),
                             span.lo,
                             span.hi)
        .collect::<Vec<_>>();

    if items.is_empty() {
        if context.config.spaces_within_square_brackets() {
            return Some("[ ]".to_string());
        } else {
            return Some("[]".to_string());
        }
    }

    let has_long_item = try_opt!(items
                                     .iter()
                                     .map(|li| li.item.as_ref().map(|s| s.len() > 10))
                                     .fold(Some(false),
                                           |acc, x| acc.and_then(|y| x.map(|x| x || y))));

    let tactic = match context.config.array_layout() {
        IndentStyle::Block => {
            // FIXME wrong shape in one-line case
            match shape.width.checked_sub(2 * bracket_size) {
                Some(width) => {
                    let tactic =
                        ListTactic::LimitedHorizontalVertical(context.config.array_width());
                    definitive_tactic(&items, tactic, width)
                }
                None => DefinitiveListTactic::Vertical,
            }
        }
        IndentStyle::Visual => {
            if has_long_item || items.iter().any(ListItem::is_multiline) {
                definitive_tactic(&items,
                                  ListTactic::LimitedHorizontalVertical(context
                                                                            .config
                                                                            .array_width()),
                                  nested_shape.width)
            } else {
                DefinitiveListTactic::Mixed
            }
        }
    };

    let fmt = ListFormatting {
        tactic: tactic,
        separator: ",",
        trailing_separator: SeparatorTactic::Never,
        shape: nested_shape,
        ends_with_newline: false,
        config: context.config,
    };
    let list_str = try_opt!(write_list(&items, &fmt));

    let result = if context.config.array_layout() == IndentStyle::Visual ||
                    tactic != DefinitiveListTactic::Vertical {
        if context.config.spaces_within_square_brackets() && list_str.len() > 0 {
            format!("[ {} ]", list_str)
        } else {
            format!("[{}]", list_str)
        }
    } else {
        format!("[\n{}{},\n{}]",
                nested_shape.indent.to_string(context.config),
                list_str,
                shape.block().indent.to_string(context.config))
    };

    Some(result)
}

// This functions is pretty messy because of the rules around closures and blocks:
// FIXME - the below is probably no longer true in full.
//   * if there is a return type, then there must be braces,
//   * given a closure with braces, whether that is parsed to give an inner block
//     or not depends on if there is a return type and if there are statements
//     in that block,
//   * if the first expression in the body ends with a block (i.e., is a
//     statement without needing a semi-colon), then adding or removing braces
//     can change whether it is treated as an expression or statement.
fn rewrite_closure(capture: ast::CaptureBy,
                   fn_decl: &ast::FnDecl,
                   body: &ast::Expr,
                   span: Span,
                   context: &RewriteContext,
                   shape: Shape)
                   -> Option<String> {
    let mover = if capture == ast::CaptureBy::Value {
        "move "
    } else {
        ""
    };
    // 4 = "|| {".len(), which is overconservative when the closure consists of
    // a single expression.
    let nested_shape = try_opt!(try_opt!(shape.shrink_left(mover.len())).sub_width(4));

    // 1 = |
    let argument_offset = nested_shape.indent + 1;
    let arg_shape = try_opt!(nested_shape.shrink_left(1)).visual_indent(0);
    let ret_str = try_opt!(fn_decl.output.rewrite(context, arg_shape));

    let arg_items = itemize_list(context.codemap,
                                 fn_decl.inputs.iter(),
                                 "|",
                                 |arg| span_lo_for_arg(arg),
                                 |arg| span_hi_for_arg(arg),
                                 |arg| arg.rewrite(context, arg_shape),
                                 context.codemap.span_after(span, "|"),
                                 body.span.lo);
    let item_vec = arg_items.collect::<Vec<_>>();
    // 1 = space between arguments and return type.
    let horizontal_budget = nested_shape
        .width
        .checked_sub(ret_str.len() + 1)
        .unwrap_or(0);
    let tactic = definitive_tactic(&item_vec, ListTactic::HorizontalVertical, horizontal_budget);
    let arg_shape = match tactic {
        DefinitiveListTactic::Horizontal => try_opt!(arg_shape.sub_width(ret_str.len() + 1)),
        _ => arg_shape,
    };

    let fmt = ListFormatting {
        tactic: tactic,
        separator: ",",
        trailing_separator: SeparatorTactic::Never,
        shape: arg_shape,
        ends_with_newline: false,
        config: context.config,
    };
    let list_str = try_opt!(write_list(&item_vec, &fmt));
    let mut prefix = format!("{}|{}|", mover, list_str);

    if !ret_str.is_empty() {
        if prefix.contains('\n') {
            prefix.push('\n');
            prefix.push_str(&argument_offset.to_string(context.config));
        } else {
            prefix.push(' ');
        }
        prefix.push_str(&ret_str);
    }

    // 1 = space between `|...|` and body.
    let extra_offset = extra_offset(&prefix, shape) + 1;
    let body_shape = try_opt!(shape.sub_width(extra_offset)).add_offset(extra_offset);

    if let ast::ExprKind::Block(ref block) = body.node {
        // The body of the closure is an empty block.
        if block.stmts.is_empty() && !block_contains_comment(block, context.codemap) {
            return Some(format!("{} {{}}", prefix));
        }

        // Figure out if the block is necessary.
        let needs_block = block.rules != ast::BlockCheckMode::Default ||
                          block.stmts.len() > 1 || context.inside_macro ||
                          block_contains_comment(block, context.codemap) ||
                          prefix.contains('\n');

        if ret_str.is_empty() && !needs_block {
            // lock.stmts.len() == 1
            if let Some(ref expr) = stmt_expr(&block.stmts[0]) {
                if let Some(rw) = rewrite_closure_expr(expr, &prefix, context, body_shape) {
                    return Some(rw);
                }
            }
        }

        if !needs_block {
            // We need braces, but we might still prefer a one-liner.
            let stmt = &block.stmts[0];
            // 4 = braces and spaces.
            if let Some(body_shape) = body_shape.sub_width(4) {
                // Checks if rewrite succeeded and fits on a single line.
                if let Some(rewrite) = and_one_line(stmt.rewrite(context, body_shape)) {
                    return Some(format!("{} {{ {} }}", prefix, rewrite));
                }
            }
        }

        // Either we require a block, or tried without and failed.
        return rewrite_closure_block(&block, prefix, context, body_shape);
    }

    if let Some(rw) = rewrite_closure_expr(body, &prefix, context, body_shape) {
        return Some(rw);
    }

    // The closure originally had a non-block expression, but we can't fit on
    // one line, so we'll insert a block.
    let block = ast::Block {
        stmts: vec![ast::Stmt {
                        id: ast::NodeId::new(0),
                        node: ast::StmtKind::Expr(ptr::P(body.clone())),
                        span: body.span,
                    }],
        id: ast::NodeId::new(0),
        rules: ast::BlockCheckMode::Default,
        span: body.span,
    };
    return rewrite_closure_block(&block, prefix, context, body_shape);

    fn rewrite_closure_expr(expr: &ast::Expr,
                            prefix: &str,
                            context: &RewriteContext,
                            shape: Shape)
                            -> Option<String> {
        let mut rewrite = expr.rewrite(context, shape);
        if classify::expr_requires_semi_to_be_stmt(left_most_sub_expr(expr)) {
            rewrite = and_one_line(rewrite);
        }
        rewrite.map(|rw| format!("{} {}", prefix, rw))
    }

    fn rewrite_closure_block(block: &ast::Block,
                             prefix: String,
                             context: &RewriteContext,
                             shape: Shape)
                             -> Option<String> {
        // Start with visual indent, then fall back to block indent if the
        // closure is large.
        let block_threshold = context.config.closure_block_indent_threshold();
        if block_threshold >= 0 {
            if let Some(block_str) = block.rewrite(&context, shape) {
                if block_str.matches('\n').count() <= block_threshold as usize &&
                   !need_block_indent(&block_str, shape) {
                    if let Some(block_str) = block_str.rewrite(context, shape) {
                        return Some(format!("{} {}", prefix, block_str));
                    }
                }
            }
        }

        // The body of the closure is big enough to be block indented, that
        // means we must re-format.
        let block_shape = shape.block().with_max_width(context.config);
        let block_str = try_opt!(block.rewrite(&context, block_shape));
        Some(format!("{} {}", prefix, block_str))
    }
}

fn and_one_line(x: Option<String>) -> Option<String> {
    x.and_then(|x| if x.contains('\n') { None } else { Some(x) })
}

fn nop_block_collapse(block_str: Option<String>, budget: usize) -> Option<String> {
    debug!("nop_block_collapse {:?} {}", block_str, budget);
    block_str.map(|block_str| if block_str.starts_with('{') && budget >= 2 &&
                                 (block_str[1..].find(|c: char| !c.is_whitespace()).unwrap() ==
                                  block_str.len() - 2) {
                      "{}".to_owned()
                  } else {
                      block_str.to_owned()
                  })
}

impl Rewrite for ast::Block {
    fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option<String> {
        // shape.width is used only for the single line case: either the empty block `{}`,
        // or an unsafe expression `unsafe { e }`.

        if self.stmts.is_empty() && !block_contains_comment(self, context.codemap) &&
           shape.width >= 2 {
            return Some("{}".to_owned());
        }

        // If a block contains only a single-line comment, then leave it on one line.
        let user_str = context.snippet(self.span);
        let user_str = user_str.trim();
        if user_str.starts_with('{') && user_str.ends_with('}') {
            let comment_str = user_str[1..user_str.len() - 1].trim();
            if self.stmts.is_empty() && !comment_str.contains('\n') &&
               !comment_str.starts_with("//") &&
               comment_str.len() + 4 <= shape.width {
                return Some(format!("{{ {} }}", comment_str));
            }
        }

        let mut visitor = FmtVisitor::from_codemap(context.parse_session, context.config);
        visitor.block_indent = shape.indent;

        let prefix = match self.rules {
            ast::BlockCheckMode::Unsafe(..) => {
                let snippet = context.snippet(self.span);
                let open_pos = try_opt!(snippet.find_uncommented("{"));
                visitor.last_pos = self.span.lo + BytePos(open_pos as u32);

                // Extract comment between unsafe and block start.
                let trimmed = &snippet[6..open_pos].trim();

                let prefix = if !trimmed.is_empty() {
                    // 9 = "unsafe  {".len(), 7 = "unsafe ".len()
                    let budget = try_opt!(shape.width.checked_sub(9));
                    format!("unsafe {} ",
                            try_opt!(rewrite_comment(trimmed,
                                                     true,
                                                     Shape::legacy(budget, shape.indent + 7),
                                                     context.config)))
                } else {
                    "unsafe ".to_owned()
                };
                if let result @ Some(_) = try_one_line_block(context, shape, &prefix, self) {
                    return result;
                }
                prefix
            }
            ast::BlockCheckMode::Default => {
                visitor.last_pos = self.span.lo;
                String::new()
            }
        };

        visitor.visit_block(self);
        if visitor.failed && shape.indent.alignment != 0 {
            self.rewrite(context,
                         Shape::indented(shape.indent.block_only(), context.config))
        } else {
            Some(format!("{}{}", prefix, visitor.buffer))
        }
    }
}

impl Rewrite for ast::Stmt {
    fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option<String> {
        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(self) { ";" } else { "" };

                format_expr(ex,
                            match self.node {
                                ast::StmtKind::Expr(_) => ExprType::SubExpression,
                                ast::StmtKind::Semi(_) => ExprType::Statement,
                                _ => unreachable!(),
                            },
                            context,
                            try_opt!(shape.sub_width(suffix.len())))
                    .map(|s| s + suffix)
            }
            ast::StmtKind::Mac(..) |
            ast::StmtKind::Item(..) => None,
        };
        result.and_then(|res| recover_comment_removed(res, self.span, context, shape))
    }
}

// Abstraction over control flow expressions
#[derive(Debug)]
struct ControlFlow<'a> {
    cond: Option<&'a ast::Expr>,
    block: &'a ast::Block,
    else_block: Option<&'a ast::Expr>,
    label: Option<ast::SpannedIdent>,
    pat: Option<&'a ast::Pat>,
    keyword: &'a str,
    matcher: &'a str,
    connector: &'a str,
    allow_single_line: bool,
    // True if this is an `if` expression in an `else if` :-( hacky
    nested_if: bool,
    span: Span,
}

impl<'a> ControlFlow<'a> {
    fn new_if(cond: &'a ast::Expr,
              pat: Option<&'a ast::Pat>,
              block: &'a ast::Block,
              else_block: Option<&'a ast::Expr>,
              allow_single_line: bool,
              nested_if: bool,
              span: Span)
              -> ControlFlow<'a> {
        ControlFlow {
            cond: Some(cond),
            block: block,
            else_block: else_block,
            label: None,
            pat: pat,
            keyword: "if",
            matcher: match pat {
                Some(..) => "let",
                None => "",
            },
            connector: " =",
            allow_single_line: allow_single_line,
            nested_if: nested_if,
            span: span,
        }
    }

    fn new_loop(block: &'a ast::Block,
                label: Option<ast::SpannedIdent>,
                span: Span)
                -> ControlFlow<'a> {
        ControlFlow {
            cond: None,
            block: block,
            else_block: None,
            label: label,
            pat: None,
            keyword: "loop",
            matcher: "",
            connector: "",
            allow_single_line: false,
            nested_if: false,
            span: span,
        }
    }

    fn new_while(pat: Option<&'a ast::Pat>,
                 cond: &'a ast::Expr,
                 block: &'a ast::Block,
                 label: Option<ast::SpannedIdent>,
                 span: Span)
                 -> ControlFlow<'a> {
        ControlFlow {
            cond: Some(cond),
            block: block,
            else_block: None,
            label: label,
            pat: pat,
            keyword: "while",
            matcher: match pat {
                Some(..) => "let",
                None => "",
            },
            connector: " =",
            allow_single_line: false,
            nested_if: false,
            span: span,
        }
    }

    fn new_for(pat: &'a ast::Pat,
               cond: &'a ast::Expr,
               block: &'a ast::Block,
               label: Option<ast::SpannedIdent>,
               span: Span)
               -> ControlFlow<'a> {
        ControlFlow {
            cond: Some(cond),
            block: block,
            else_block: None,
            label: label,
            pat: Some(pat),
            keyword: "for",
            matcher: "",
            connector: " in",
            allow_single_line: false,
            nested_if: false,
            span: span,
        }
    }

    fn rewrite_single_line(&self,
                           pat_expr_str: &str,
                           context: &RewriteContext,
                           width: usize)
                           -> Option<String> {
        assert!(self.allow_single_line);
        let else_block = try_opt!(self.else_block);
        let fixed_cost = self.keyword.len() + "  {  } else {  }".len();

        if let ast::ExprKind::Block(ref else_node) = else_block.node {
            if !is_simple_block(self.block, context.codemap) ||
               !is_simple_block(else_node, context.codemap) ||
               pat_expr_str.contains('\n') {
                return None;
            }

            let new_width = try_opt!(width.checked_sub(pat_expr_str.len() + fixed_cost));
            let expr = &self.block.stmts[0];
            let if_str = try_opt!(expr.rewrite(context, Shape::legacy(new_width, Indent::empty())));

            let new_width = try_opt!(new_width.checked_sub(if_str.len()));
            let else_expr = &else_node.stmts[0];
            let else_str =
                try_opt!(else_expr.rewrite(context, Shape::legacy(new_width, Indent::empty())));

            if if_str.contains('\n') || else_str.contains('\n') {
                return None;
            }

            let result = format!("{} {} {{ {} }} else {{ {} }}",
                                 self.keyword,
                                 pat_expr_str,
                                 if_str,
                                 else_str);

            if result.len() <= width {
                return Some(result);
            }
        }

        None
    }
}

impl<'a> Rewrite for ControlFlow<'a> {
    fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option<String> {
        debug!("ControlFlow::rewrite {:?} {:?}", self, shape);
        let constr_shape = if self.nested_if {
            // We are part of an if-elseif-else chain. Our constraints are tightened.
            // 7 = "} else " .len()
            try_opt!(shape.shrink_left(7))
        } else {
            shape
        };

        let label_string = rewrite_label(self.label);
        // 1 = space after keyword.
        let add_offset = self.keyword.len() + label_string.len() + 1;

        let pat_expr_string = match self.cond {
            Some(cond) => {
                let mut cond_shape = match context.config.control_style() {
                    Style::Default => try_opt!(constr_shape.shrink_left(add_offset)),
                    Style::Rfc => constr_shape,
                };
                if context.config.control_brace_style() != ControlBraceStyle::AlwaysNextLine {
                    // 2 = " {".len()
                    cond_shape = try_opt!(cond_shape.sub_width(2));
                }

                try_opt!(rewrite_pat_expr(context,
                                          self.pat,
                                          cond,
                                          self.matcher,
                                          self.connector,
                                          cond_shape))
            }
            None => String::new(),
        };

        let force_newline_brace = context.config.control_style() == Style::Rfc &&
                                  pat_expr_string.contains('\n');

        // Try to format if-else on single line.
        if self.allow_single_line && context.config.single_line_if_else_max_width() > 0 {
            let trial = self.rewrite_single_line(&pat_expr_string, context, shape.width);

            if trial.is_some() &&
               trial.as_ref().unwrap().len() <= context.config.single_line_if_else_max_width() {
                return trial;
            }
        }

        let used_width = if pat_expr_string.contains('\n') {
            last_line_width(&pat_expr_string)
        } else {
            // 2 = spaces after keyword and condition.
            label_string.len() + self.keyword.len() + pat_expr_string.len() + 2
        };

        let block_width = shape.width.checked_sub(used_width).unwrap_or(0);
        // This is used only for the empty block case: `{}`. So, we use 1 if we know
        // we should avoid the single line case.
        let block_width = if self.else_block.is_some() || self.nested_if {
            min(1, block_width)
        } else {
            block_width
        };

        let block_shape = Shape {
            width: block_width,
            ..shape
        };
        let block_str = try_opt!(self.block.rewrite(context, block_shape));

        let cond_span = if let Some(cond) = self.cond {
            cond.span
        } else {
            mk_sp(self.block.span.lo, self.block.span.lo)
        };

        // for event in event
        let between_kwd_cond = mk_sp(
            context.codemap.span_after(self.span, self.keyword.trim()),
            self.pat
                .map_or(cond_span.lo, |p| if self.matcher.is_empty() {
                    p.span.lo
                } else {
                    context.codemap.span_before(self.span, self.matcher.trim())
                }),
        );

        let between_kwd_cond_comment = extract_comment(between_kwd_cond, context, shape);

        let after_cond_comment =
            extract_comment(mk_sp(cond_span.hi, self.block.span.lo), context, shape);

        let alt_block_sep = String::from("\n") +
                            &shape.indent.block_only().to_string(context.config);
        let block_sep = if self.cond.is_none() && between_kwd_cond_comment.is_some() {
            ""
        } else if context.config.control_brace_style() == ControlBraceStyle::AlwaysNextLine ||
                  force_newline_brace {
            alt_block_sep.as_str()
        } else {
            " "
        };

        let mut result = format!("{}{}{}{}{}{}",
                                 label_string,
                                 self.keyword,
                                 between_kwd_cond_comment
                                     .as_ref()
                                     .map_or(if pat_expr_string.is_empty() ||
                                                pat_expr_string.starts_with('\n') {
                                                 ""
                                             } else {
                                                 " "
                                             },
                                             |s| &**s),
                                 pat_expr_string,
                                 after_cond_comment.as_ref().map_or(block_sep, |s| &**s),
                                 block_str);

        if let Some(else_block) = self.else_block {
            let shape = Shape::indented(shape.indent, context.config);
            let mut last_in_chain = false;
            let rewrite = match else_block.node {
                // If the else expression is another if-else expression, prevent it
                // from being formatted on a single line.
                // Note how we're passing the original shape, as the
                // cost of "else" should not cascade.
                ast::ExprKind::IfLet(ref pat, ref cond, ref if_block, ref next_else_block) => {
                    ControlFlow::new_if(cond,
                                        Some(pat),
                                        if_block,
                                        next_else_block.as_ref().map(|e| &**e),
                                        false,
                                        true,
                                        mk_sp(else_block.span.lo, self.span.hi))
                        .rewrite(context, shape)
                }
                ast::ExprKind::If(ref cond, ref if_block, ref next_else_block) => {
                    ControlFlow::new_if(cond,
                                        None,
                                        if_block,
                                        next_else_block.as_ref().map(|e| &**e),
                                        false,
                                        true,
                                        mk_sp(else_block.span.lo, self.span.hi))
                        .rewrite(context, shape)
                }
                _ => {
                    last_in_chain = true;
                    // When rewriting a block, the width is only used for single line
                    // blocks, passing 1 lets us avoid that.
                    let else_shape = Shape {
                        width: min(1, shape.width),
                        ..shape
                    };
                    else_block.rewrite(context, else_shape)
                }
            };

            let between_kwd_else_block =
                mk_sp(self.block.span.hi,
                      context
                          .codemap
                          .span_before(mk_sp(self.block.span.hi, else_block.span.lo), "else"));
            let between_kwd_else_block_comment =
                extract_comment(between_kwd_else_block, context, shape);

            let after_else = mk_sp(context
                                       .codemap
                                       .span_after(mk_sp(self.block.span.hi, else_block.span.lo),
                                                   "else"),
                                   else_block.span.lo);
            let after_else_comment = extract_comment(after_else, context, shape);

            let between_sep = match context.config.control_brace_style() {
                ControlBraceStyle::AlwaysNextLine |
                ControlBraceStyle::ClosingNextLine => &*alt_block_sep,
                ControlBraceStyle::AlwaysSameLine => " ",
            };
            let after_sep = match context.config.control_brace_style() {
                ControlBraceStyle::AlwaysNextLine if last_in_chain => &*alt_block_sep,
                _ => " ",
            };
            try_opt!(write!(&mut result,
                            "{}else{}",
                            between_kwd_else_block_comment
                                .as_ref()
                                .map_or(between_sep, |s| &**s),
                            after_else_comment.as_ref().map_or(after_sep, |s| &**s))
                         .ok());
            result.push_str(&try_opt!(rewrite));
        }

        Some(result)
    }
}

fn rewrite_label(label: Option<ast::SpannedIdent>) -> String {
    match label {
        Some(ident) => format!("{}: ", ident.node),
        None => "".to_owned(),
    }
}

fn extract_comment(span: Span, context: &RewriteContext, shape: Shape) -> Option<String> {
    let comment_str = context.snippet(span);
    if contains_comment(&comment_str) {
        let comment = try_opt!(rewrite_comment(comment_str.trim(), false, shape, context.config));
        Some(format!("\n{indent}{}\n{indent}",
                     comment,
                     indent = shape.indent.to_string(context.config)))
    } else {
        None
    }
}

fn block_contains_comment(block: &ast::Block, codemap: &CodeMap) -> bool {
    let snippet = codemap.span_to_snippet(block.span).unwrap();
    contains_comment(&snippet)
}

// Checks that a block contains no statements, an expression and no comments.
// FIXME: incorrectly returns false when comment is contained completely within
// the expression.
pub fn is_simple_block(block: &ast::Block, codemap: &CodeMap) -> bool {
    (block.stmts.len() == 1 && stmt_is_expr(&block.stmts[0]) &&
     !block_contains_comment(block, codemap))
}

/// Checks whether a block contains at most one statement or expression, and no comments.
pub fn is_simple_block_stmt(block: &ast::Block, codemap: &CodeMap) -> bool {
    block.stmts.len() <= 1 && !block_contains_comment(block, codemap)
}

/// Checks whether a block contains no statements, expressions, or comments.
pub fn is_empty_block(block: &ast::Block, codemap: &CodeMap) -> bool {
    block.stmts.is_empty() && !block_contains_comment(block, codemap)
}

pub fn stmt_is_expr(stmt: &ast::Stmt) -> bool {
    match stmt.node {
        ast::StmtKind::Expr(..) => true,
        _ => false,
    }
}

fn is_unsafe_block(block: &ast::Block) -> bool {
    if let ast::BlockCheckMode::Unsafe(..) = block.rules {
        true
    } else {
        false
    }
}

// inter-match-arm-comment-rules:
//  - all comments following a match arm before the start of the next arm
//    are about the second arm
fn rewrite_match_arm_comment(context: &RewriteContext,
                             missed_str: &str,
                             shape: Shape,
                             arm_indent_str: &str)
                             -> Option<String> {
    // The leading "," is not part of the arm-comment
    let missed_str = match missed_str.find_uncommented(",") {
        Some(n) => &missed_str[n + 1..],
        None => &missed_str[..],
    };

    let mut result = String::new();
    // any text not preceeded by a newline is pushed unmodified to the block
    let first_brk = missed_str.find(|c: char| c == '\n').unwrap_or(0);
    result.push_str(&missed_str[..first_brk]);
    let missed_str = &missed_str[first_brk..]; // If missed_str had one newline, it starts with it

    let first = missed_str
        .find(|c: char| !c.is_whitespace())
        .unwrap_or(missed_str.len());
    if missed_str[..first].chars().filter(|c| c == &'\n').count() >= 2 {
        // Excessive vertical whitespace before comment should be preserved
        // FIXME handle vertical whitespace better
        result.push('\n');
    }
    let missed_str = missed_str[first..].trim();
    if !missed_str.is_empty() {
        let comment = try_opt!(rewrite_comment(&missed_str, false, shape, context.config));
        result.push('\n');
        result.push_str(arm_indent_str);
        result.push_str(&comment);
    }

    Some(result)
}

fn rewrite_match(context: &RewriteContext,
                 cond: &ast::Expr,
                 arms: &[ast::Arm],
                 shape: Shape,
                 span: Span)
                 -> Option<String> {
    if arms.is_empty() {
        return None;
    }

    // `match `cond` {`
    let cond_shape = try_opt!(shape.shrink_left(6));
    let cond_shape = try_opt!(cond_shape.sub_width(2));
    let cond_str = try_opt!(cond.rewrite(context, cond_shape));
    let alt_block_sep = String::from("\n") + &shape.indent.block_only().to_string(context.config);
    let block_sep = match context.config.control_brace_style() {
        ControlBraceStyle::AlwaysSameLine => " ",
        _ => alt_block_sep.as_str(),
    };
    let mut result = format!("match {}{}{{", cond_str, block_sep);

    let arm_shape = if context.config.indent_match_arms() {
        shape.block_indent(context.config.tab_spaces())
    } else {
        shape.block_indent(0)
    };

    let arm_indent_str = arm_shape.indent.to_string(context.config);

    let open_brace_pos = context
        .codemap
        .span_after(mk_sp(cond.span.hi, arm_start_pos(&arms[0])), "{");

    for (i, arm) in arms.iter().enumerate() {
        // Make sure we get the stuff between arms.
        let missed_str = if i == 0 {
            context.snippet(mk_sp(open_brace_pos, arm_start_pos(arm)))
        } else {
            context.snippet(mk_sp(arm_end_pos(&arms[i - 1]), arm_start_pos(arm)))
        };
        let comment =
            try_opt!(rewrite_match_arm_comment(context, &missed_str, arm_shape, &arm_indent_str));
        result.push_str(&comment);
        result.push('\n');
        result.push_str(&arm_indent_str);

        let arm_str = arm.rewrite(&context, arm_shape.with_max_width(context.config));
        if let Some(ref arm_str) = arm_str {
            result.push_str(arm_str);
        } else {
            // We couldn't format the arm, just reproduce the source.
            let snippet = context.snippet(mk_sp(arm_start_pos(arm), arm_end_pos(arm)));
            result.push_str(&snippet);
            result.push_str(arm_comma(context.config, &arm.body));
        }
    }
    // BytePos(1) = closing match brace.
    let last_span = mk_sp(arm_end_pos(&arms[arms.len() - 1]), span.hi - BytePos(1));
    let last_comment = context.snippet(last_span);
    let comment =
        try_opt!(rewrite_match_arm_comment(context, &last_comment, arm_shape, &arm_indent_str));
    result.push_str(&comment);
    result.push('\n');
    result.push_str(&shape.indent.to_string(context.config));
    result.push('}');
    Some(result)
}

fn arm_start_pos(arm: &ast::Arm) -> BytePos {
    let &ast::Arm {
        ref attrs,
        ref pats,
        ..
    } = arm;
    if !attrs.is_empty() {
        return attrs[0].span.lo;
    }

    pats[0].span.lo
}

fn arm_end_pos(arm: &ast::Arm) -> BytePos {
    arm.body.span.hi
}

fn arm_comma(config: &Config, body: &ast::Expr) -> &'static str {
    if config.match_block_trailing_comma() {
        ","
    } else if let ast::ExprKind::Block(ref block) = body.node {
        if let ast::BlockCheckMode::Default = block.rules {
            ""
        } else {
            ","
        }
    } else {
        ","
    }
}

// Match arms.
impl Rewrite for ast::Arm {
    fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option<String> {
        debug!("Arm::rewrite {:?} {:?}", self, shape);
        let &ast::Arm {
            ref attrs,
            ref pats,
            ref guard,
            ref body,
        } = self;

        // FIXME this is all a bit grotty, would be nice to abstract out the
        // treatment of attributes.
        let attr_str = if !attrs.is_empty() {
            // We only use this visitor for the attributes, should we use it for
            // more?
            let mut attr_visitor = FmtVisitor::from_codemap(context.parse_session, context.config);
            attr_visitor.block_indent = shape.indent.block_only();
            attr_visitor.last_pos = attrs[0].span.lo;
            if attr_visitor.visit_attrs(attrs) {
                // Attributes included a skip instruction.
                return None;
            }
            attr_visitor.format_missing(pats[0].span.lo);
            attr_visitor.buffer.to_string()
        } else {
            String::new()
        };

        // Patterns
        // 5 = ` => {`
        let pat_shape = try_opt!(shape.sub_width(5));

        let pat_strs = try_opt!(pats.iter()
                                    .map(|p| p.rewrite(context, pat_shape))
                                    .collect::<Option<Vec<_>>>());

        let all_simple = pat_strs.iter().all(|p| pat_is_simple(p));
        let items: Vec<_> = pat_strs.into_iter().map(ListItem::from_str).collect();
        let fmt = ListFormatting {
            tactic: if all_simple {
                DefinitiveListTactic::Mixed
            } else {
                DefinitiveListTactic::Vertical
            },
            separator: " |",
            trailing_separator: SeparatorTactic::Never,
            shape: pat_shape,
            ends_with_newline: false,
            config: context.config,
        };
        let pats_str = try_opt!(write_list(items, &fmt));

        let guard_shape = if pats_str.contains('\n') {
            shape.with_max_width(context.config)
        } else {
            shape
        };

        let guard_str = try_opt!(rewrite_guard(context,
                                               guard,
                                               guard_shape,
                                               trimmed_last_line_width(&pats_str)));

        let pats_str = format!("{}{}", pats_str, guard_str);

        let (mut extend, body) = match body.node {
            ast::ExprKind::Block(ref block) if !is_unsafe_block(block) &&
                                               is_simple_block(block, context.codemap) &&
                                               context.config.wrap_match_arms() => {
                if let ast::StmtKind::Expr(ref expr) = block.stmts[0].node {
                    (false, &**expr)
                } else {
                    (false, &**body)
                }
            }
            ast::ExprKind::Call(_, ref args) => (args.len() == 1, &**body),
            ast::ExprKind::Closure(..) |
            ast::ExprKind::Struct(..) |
            ast::ExprKind::Tup(..) => (true, &**body),
            _ => (false, &**body),
        };
        extend &= context.config.fn_call_style() == IndentStyle::Block;

        let comma = arm_comma(&context.config, body);
        let alt_block_sep = String::from("\n") +
                            &shape.indent.block_only().to_string(context.config);

        let pat_width = extra_offset(&pats_str, shape);
        // Let's try and get the arm body on the same line as the condition.
        // 4 = ` => `.len()
        if shape.width > pat_width + comma.len() + 4 {
            let arm_shape = shape
                .offset_left(pat_width + 4)
                .unwrap()
                .sub_width(comma.len())
                .unwrap();
            let rewrite = nop_block_collapse(body.rewrite(context, arm_shape), arm_shape.width);
            let is_block = if let ast::ExprKind::Block(..) = body.node {
                true
            } else {
                false
            };

            match rewrite {
                Some(ref body_str) if (!body_str.contains('\n') &&
                                       body_str.len() <= arm_shape.width) ||
                                      !context.config.wrap_match_arms() ||
                                      (extend && first_line_width(body_str) <= arm_shape.width) ||
                                      is_block => {
                    let block_sep = match context.config.control_brace_style() {
                        ControlBraceStyle::AlwaysNextLine if is_block => alt_block_sep.as_str(),
                        _ => " ",
                    };

                    return Some(format!("{}{} =>{}{}{}",
                                        attr_str.trim_left(),
                                        pats_str,
                                        block_sep,
                                        body_str,
                                        comma));
                }
                _ => {}
            }
        }

        // FIXME: we're doing a second rewrite of the expr; This may not be
        // necessary.
        let body_shape = try_opt!(shape.sub_width(context.config.tab_spaces()))
            .block_indent(context.config.tab_spaces());
        let next_line_body = try_opt!(nop_block_collapse(body.rewrite(context, body_shape),
                                                         body_shape.width));
        let indent_str = shape
            .indent
            .block_indent(context.config)
            .to_string(context.config);
        let (body_prefix, body_suffix) = if context.config.wrap_match_arms() {
            if context.config.match_block_trailing_comma() {
                ("{", "},")
            } else {
                ("{", "}")
            }
        } else {
            ("", ",")
        };


        let block_sep = match context.config.control_brace_style() {
            ControlBraceStyle::AlwaysNextLine => alt_block_sep + body_prefix + "\n",
            _ if body_prefix.is_empty() => "\n".to_owned(),
            _ => " ".to_owned() + body_prefix + "\n",
        };

        if context.config.wrap_match_arms() {
            Some(format!("{}{} =>{}{}{}\n{}{}",
                         attr_str.trim_left(),
                         pats_str,
                         block_sep,
                         indent_str,
                         next_line_body,
                         shape.indent.to_string(context.config),
                         body_suffix))
        } else {
            Some(format!("{}{} =>{}{}{}{}",
                         attr_str.trim_left(),
                         pats_str,
                         block_sep,
                         indent_str,
                         next_line_body,
                         body_suffix))
        }
    }
}

// A pattern is simple if it is very short or it is short-ish and just a path.
// E.g. `Foo::Bar` is simple, but `Foo(..)` is not.
fn pat_is_simple(pat_str: &str) -> bool {
    pat_str.len() <= 16 ||
    (pat_str.len() <= 24 && pat_str.chars().all(|c| c.is_alphabetic() || c == ':'))
}

// The `if ...` guard on a match arm.
fn rewrite_guard(context: &RewriteContext,
                 guard: &Option<ptr::P<ast::Expr>>,
                 shape: Shape,
                 // The amount of space used up on this line for the pattern in
                 // the arm (excludes offset).
                 pattern_width: usize)
                 -> Option<String> {
    if let Some(ref guard) = *guard {
        // First try to fit the guard string on the same line as the pattern.
        // 4 = ` if `, 5 = ` => {`
        let overhead = pattern_width + 4 + 5;
        if overhead < shape.width {
            let cond_shape = shape
                .shrink_left(pattern_width + 4)
                .unwrap()
                .sub_width(5)
                .unwrap();
            let cond_str = guard.rewrite(context, cond_shape);
            if let Some(cond_str) = cond_str {
                return Some(format!(" if {}", cond_str));
            }
        }

        // Not enough space to put the guard after the pattern, try a newline.
        let overhead = shape.indent.block_indent(context.config).width() + 4 + 5;
        if overhead < shape.width {
            let cond_str = guard.rewrite(context,
                                         Shape::legacy(shape.width - overhead,
                                                       // 3 == `if `
                                                       shape.indent.block_indent(context.config) +
                                                       3));
            if let Some(cond_str) = cond_str {
                return Some(format!("\n{}if {}",
                                    shape
                                        .indent
                                        .block_indent(context.config)
                                        .to_string(context.config),
                                    cond_str));
            }
        }

        None
    } else {
        Some(String::new())
    }
}

fn rewrite_pat_expr(context: &RewriteContext,
                    pat: Option<&ast::Pat>,
                    expr: &ast::Expr,
                    matcher: &str,
                    // Connecting piece between pattern and expression,
                    // *without* trailing space.
                    connector: &str,
                    shape: Shape)
                    -> Option<String> {
    debug!("rewrite_pat_expr {:?} {:?} {:?}", shape, pat, expr);
    let mut pat_string = String::new();
    let mut result = match pat {
        Some(pat) => {
            let matcher = if matcher.is_empty() {
                matcher.to_owned()
            } else {
                format!("{} ", matcher)
            };
            let pat_shape = try_opt!(try_opt!(shape.shrink_left(matcher.len()))
                                         .sub_width(connector.len()));
            pat_string = try_opt!(pat.rewrite(context, pat_shape));
            format!("{}{}{}", matcher, pat_string, connector)
        }
        None => String::new(),
    };

    // Consider only the last line of the pat string.
    let extra_offset = extra_offset(&result, shape);

    // The expression may (partially) fit on the current line.
    if shape.width > extra_offset + 1 {
        let spacer = if pat.is_some() { " " } else { "" };

        let expr_shape = try_opt!(shape.offset_left(extra_offset + spacer.len()));
        let expr_rewrite = expr.rewrite(context, expr_shape);

        if let Some(expr_string) = expr_rewrite {
            if pat.is_none() || pat_is_simple(&pat_string) || !expr_string.contains('\n') {
                result.push_str(spacer);
                result.push_str(&expr_string);
                return Some(result);
            }
        }
    }

    let nested_indent = shape.indent.block_only().block_indent(context.config);

    // The expression won't fit on the current line, jump to next.
    result.push('\n');
    result.push_str(&nested_indent.to_string(context.config));

    let expr_rewrite = expr.rewrite(&context, Shape::indented(nested_indent, context.config));
    result.push_str(&try_opt!(expr_rewrite));

    Some(result)
}

fn rewrite_string_lit(context: &RewriteContext, span: Span, shape: Shape) -> Option<String> {
    let string_lit = context.snippet(span);

    if !context.config.format_strings() && !context.config.force_format_strings() {
        return Some(string_lit);
    }

    if !context.config.force_format_strings() &&
       !string_requires_rewrite(context, span, &string_lit, shape) {
        return Some(string_lit);
    }

    let fmt = StringFormat {
        opener: "\"",
        closer: "\"",
        line_start: " ",
        line_end: "\\",
        shape: shape,
        trim_end: false,
        config: context.config,
    };

    // Remove the quote characters.
    let str_lit = &string_lit[1..string_lit.len() - 1];

    rewrite_string(str_lit, &fmt)
}

fn string_requires_rewrite(context: &RewriteContext,
                           span: Span,
                           string: &str,
                           shape: Shape)
                           -> bool {
    if context.codemap.lookup_char_pos(span.lo).col.0 != shape.indent.width() {
        return true;
    }

    for (i, line) in string.lines().enumerate() {
        if i == 0 {
            if line.len() > shape.width {
                return true;
            }
        } else {
            if line.len() > shape.width + shape.indent.width() {
                return true;
            }
        }
    }

    false
}

pub fn rewrite_call_with_binary_search<R>(context: &RewriteContext,
                                          callee: &R,
                                          args: &[ptr::P<ast::Expr>],
                                          span: Span,
                                          shape: Shape)
                                          -> Option<String>
    where R: Rewrite
{
    let closure = |callee_max_width| {
        // FIXME using byte lens instead of char lens (and probably all over the
        // place too)
        let callee_shape = Shape {
            width: callee_max_width,
            ..shape
        };
        let callee_str = callee
            .rewrite(context, callee_shape)
            .ok_or(Ordering::Greater)?;

        rewrite_call_inner(context, &callee_str, args, span, shape, false)
    };

    binary_search(1, shape.width, closure)
}

pub fn rewrite_call(context: &RewriteContext,
                    callee: &str,
                    args: &[ptr::P<ast::Expr>],
                    span: Span,
                    shape: Shape)
                    -> Option<String> {
    rewrite_call_inner(context, &callee, args, span, shape, false).ok()
}

fn rewrite_call_inner(context: &RewriteContext,
                      callee_str: &str,
                      args: &[ptr::P<ast::Expr>],
                      span: Span,
                      shape: Shape,
                      force_trailing_comma: bool)
                      -> Result<String, Ordering> {
    // 2 = `( `, 1 = `(`
    let paren_overhead = if context.config.spaces_within_parens() {
        2
    } else {
        1
    };
    let used_width = extra_offset(&callee_str, shape);
    let one_line_width = shape
        .width
        .checked_sub(used_width + 2 * paren_overhead)
        .ok_or(Ordering::Greater)?;

    let nested_shape = shape_from_fn_call_style(context,
                                                shape,
                                                used_width + 2 * paren_overhead,
                                                used_width + paren_overhead)
        .ok_or(Ordering::Greater)?;

    let span_lo = context.codemap.span_after(span, "(");
    let new_span = mk_sp(span_lo, span.hi);

    let (extendable, list_str) = rewrite_call_args(context,
                                                   args,
                                                   new_span,
                                                   nested_shape,
                                                   one_line_width,
                                                   force_trailing_comma)
        .ok_or(Ordering::Less)?;

    if !use_block_indent(context) && need_block_indent(&list_str, nested_shape) && !extendable {
        println!("here");
        let mut new_context = context.clone();
        new_context.use_block = true;
        return rewrite_call_inner(&new_context,
                                  callee_str,
                                  args,
                                  span,
                                  shape,
                                  force_trailing_comma);
    }

    Ok(format!("{}{}",
               callee_str,
               wrap_args_with_parens(context, &list_str, extendable, shape, nested_shape)))
}

fn need_block_indent(s: &str, shape: Shape) -> bool {
    s.lines().skip(1).any(|s| {
                              s.find(|c| !char::is_whitespace(c))
                                  .map_or(false, |w| w + 1 < shape.indent.width())
                          })
}

fn rewrite_call_args(context: &RewriteContext,
                     args: &[ptr::P<ast::Expr>],
                     span: Span,
                     shape: Shape,
                     one_line_width: usize,
                     force_trailing_comma: bool)
                     -> Option<(bool, String)> {
    let mut item_context = context.clone();
    item_context.inside_macro = false;
    let items = itemize_list(context.codemap,
                             args.iter(),
                             ")",
                             |item| item.span.lo,
                             |item| item.span.hi,
                             |item| item.rewrite(&item_context, shape),
                             span.lo,
                             span.hi);
    let mut item_vec: Vec<_> = items.collect();

    // Try letting the last argument overflow to the next line with block
    // indentation. If its first line fits on one line with the other arguments,
    // we format the function arguments horizontally.
    let overflow_last = can_be_overflowed(&item_context, args);

    let mut orig_last = None;
    let mut placeholder = None;

    // Replace the last item with its first line to see if it fits with
    // first arguments.
    if overflow_last {
        let arg_shape = if use_block_indent(context) && is_extendable(args) {
            Shape {
                width: context.config.fn_call_width(),
                indent: shape.block().indent.block_unindent(context.config),
                offset: 0,
            }
        } else {
            shape.block()
        };
        let rewrite = args.last().unwrap().rewrite(&item_context, arg_shape);
        swap(&mut item_vec[args.len() - 1].item, &mut orig_last);

        if let Some(rewrite) = rewrite {
            let rewrite_first_line = Some(rewrite[..first_line_width(&rewrite)].to_owned());
            placeholder = Some(rewrite);

            item_vec[args.len() - 1].item = rewrite_first_line;
        }
    }

    let one_line_shape = Shape {
        width: one_line_width,
        ..shape
    };

    let tactic =
        definitive_tactic(&item_vec,
                          ListTactic::LimitedHorizontalVertical(context.config.fn_call_width()),
                          one_line_width);

    // Replace the stub with the full overflowing last argument if the rewrite
    // succeeded and its first line fits with the other arguments.
    match (overflow_last, tactic, placeholder) {
        (true, DefinitiveListTactic::Horizontal, placeholder @ Some(..)) => {
            item_vec[args.len() - 1].item = placeholder;
        }
        (true, _, _) => {
            item_vec[args.len() - 1].item = orig_last;
        }
        (false, _, _) => {}
    }

    let mut fmt = ListFormatting {
        tactic: tactic,
        separator: ",",
        trailing_separator: if force_trailing_comma {
            SeparatorTactic::Always
        } else if context.inside_macro || context.config.fn_call_style() == IndentStyle::Visual ||
                  args.len() <= 1 {
            SeparatorTactic::Never
        } else {
            context.config.trailing_comma()
        },
        shape: one_line_shape,
        ends_with_newline: false,
        config: context.config,
    };

    let one_line_budget = min(one_line_width, context.config.fn_call_width());
    let almost_no_newline =
        item_vec
            .iter()
            .rev()
            .skip(1)
            .all(|item| item.item.as_ref().map_or(false, |s| !s.contains('\n')));
    let extendable = almost_no_newline &&
                     item_vec.iter().fold(0, |acc, item| {
        acc + item.item.as_ref().map_or(0, |s| 2 + first_line_width(s))
    }) <= one_line_budget + 2;

    let result = write_list(&item_vec, &fmt);
    let last_char_is_not_comma = result
        .as_ref()
        .map_or(false, |r| r.chars().last().unwrap_or(' ') != ',');
    match result {
        // If arguments do not fit in a single line and do not contain newline,
        // try to put it on the next line. Try this only when we are in block mode
        // and not rewriting macro.
        Some(ref s) if use_block_indent(context) && !context.inside_macro &&
                       ((!can_be_overflowed(context, args) && last_char_is_not_comma &&
                         s.contains('\n')) ||
                        first_line_width(s) > one_line_budget) => {
            fmt.trailing_separator = SeparatorTactic::Vertical;
            fmt.tactic = DefinitiveListTactic::Vertical;
            write_list(&item_vec, &fmt).map(|rw| (false, rw))
        }
        rewrite @ _ => {
            rewrite.map(|rw| (extendable && (last_char_is_not_comma || force_trailing_comma), rw))
        }
    }
}

fn use_block_indent(context: &RewriteContext) -> bool {
    context.config.fn_call_style() == IndentStyle::Block || context.use_block
}

fn can_be_overflowed(context: &RewriteContext, args: &[ptr::P<ast::Expr>]) -> bool {
    match args.last().map(|x| &x.node) {
        Some(&ast::ExprKind::Match(..)) => {
            (use_block_indent(context) && args.len() == 1) ||
            (context.config.fn_call_style() == IndentStyle::Visual && args.len() > 1)
        }
        Some(&ast::ExprKind::Block(..)) |
        Some(&ast::ExprKind::Closure(..)) => {
            use_block_indent(context) ||
            context.config.fn_call_style() == IndentStyle::Visual && args.len() > 1
        }
        Some(&ast::ExprKind::Call(..)) |
        Some(&ast::ExprKind::Mac(..)) |
        Some(&ast::ExprKind::Struct(..)) => use_block_indent(context) && args.len() == 1,
        Some(&ast::ExprKind::Tup(..)) => use_block_indent(context),
        _ => false,
    }
}

fn is_extendable(args: &[ptr::P<ast::Expr>]) -> bool {
    if args.len() == 1 {
        match args[0].node {
            ast::ExprKind::Block(..) |
            ast::ExprKind::Call(..) |
            ast::ExprKind::Closure(..) |
            ast::ExprKind::Match(..) |
            ast::ExprKind::Mac(..) |
            ast::ExprKind::Struct(..) |
            ast::ExprKind::Tup(..) => true,
            _ => false,
        }
    } else if args.len() > 1 {
        match args[args.len() - 1].node {
            ast::ExprKind::Block(..) |
            ast::ExprKind::Closure(..) |
            ast::ExprKind::Tup(..) => true,
            _ => false,
        }
    } else {
        false
    }
}

fn wrap_args_with_parens(context: &RewriteContext,
                         args_str: &str,
                         is_extendable: bool,
                         shape: Shape,
                         nested_shape: Shape)
                         -> String {
    if !use_block_indent(context) || (context.inside_macro && !args_str.contains('\n')) ||
       is_extendable {
        if context.config.spaces_within_parens() && args_str.len() > 0 {
            format!("( {} )", args_str)
        } else {
            format!("({})", args_str)
        }
    } else {
        format!("(\n{}{}\n{})",
                nested_shape.indent.to_string(context.config),
                args_str,
                shape.block().indent.to_string(context.config))
    }
}

fn rewrite_paren(context: &RewriteContext, subexpr: &ast::Expr, shape: Shape) -> Option<String> {
    debug!("rewrite_paren, shape: {:?}", shape);
    // 1 is for opening paren, 2 is for opening+closing, we want to keep the closing
    // paren on the same line as the subexpr.
    let sub_shape = try_opt!(shape.sub_width(2)).visual_indent(1);
    let subexpr_str = subexpr.rewrite(context, sub_shape);
    debug!("rewrite_paren, subexpr_str: `{:?}`", subexpr_str);

    subexpr_str.map(|s| if context.config.spaces_within_parens() && s.len() > 0 {
                        format!("( {} )", s)
                    } else {
                        format!("({})", s)
                    })
}

fn rewrite_index(expr: &ast::Expr,
                 index: &ast::Expr,
                 context: &RewriteContext,
                 shape: Shape)
                 -> Option<String> {
    let expr_str = try_opt!(expr.rewrite(context, shape));

    let (lbr, rbr) = if context.config.spaces_within_square_brackets() {
        ("[ ", " ]")
    } else {
        ("[", "]")
    };

    let offset = expr_str.len() + lbr.len();
    if let Some(index_shape) = shape.visual_indent(offset).sub_width(offset + rbr.len()) {
        if let Some(index_str) = index.rewrite(context, index_shape) {
            return Some(format!("{}{}{}{}", expr_str, lbr, index_str, rbr));
        }
    }

    let indent = shape.indent.block_indent(&context.config);
    let indent = indent.to_string(&context.config);
    // FIXME this is not right, since we don't take into account that shape.width
    // might be reduced from max_width by something on the right.
    let budget = try_opt!(context
                              .config
                              .max_width()
                              .checked_sub(indent.len() + lbr.len() + rbr.len()));
    let index_str = try_opt!(index.rewrite(context, Shape::legacy(budget, shape.indent)));
    Some(format!("{}\n{}{}{}{}", expr_str, indent, lbr, index_str, rbr))
}

fn rewrite_struct_lit<'a>(context: &RewriteContext,
                          path: &ast::Path,
                          fields: &'a [ast::Field],
                          base: Option<&'a ast::Expr>,
                          span: Span,
                          shape: Shape)
                          -> Option<String> {
    debug!("rewrite_struct_lit: shape {:?}", shape);

    enum StructLitField<'a> {
        Regular(&'a ast::Field),
        Base(&'a ast::Expr),
    }

    // 2 = " {".len()
    let path_shape = try_opt!(shape.sub_width(2));
    let path_str = try_opt!(rewrite_path(context, PathContext::Expr, None, path, path_shape));

    if fields.len() == 0 && base.is_none() {
        return Some(format!("{} {{}}", path_str));
    }

    let field_iter = fields
        .into_iter()
        .map(StructLitField::Regular)
        .chain(base.into_iter().map(StructLitField::Base));

    // Foo { a: Foo } - indent is +3, width is -5.
    let (h_shape, v_shape) = try_opt!(struct_lit_shape(shape, context, path_str.len() + 3, 2));

    let span_lo = |item: &StructLitField| match *item {
        StructLitField::Regular(field) => field.span.lo,
        StructLitField::Base(expr) => {
            let last_field_hi = fields.last().map_or(span.lo, |field| field.span.hi);
            let snippet = context.snippet(mk_sp(last_field_hi, expr.span.lo));
            let pos = snippet.find_uncommented("..").unwrap();
            last_field_hi + BytePos(pos as u32)
        }
    };
    let span_hi = |item: &StructLitField| match *item {
        StructLitField::Regular(field) => field.span.hi,
        StructLitField::Base(expr) => expr.span.hi,
    };
    let rewrite = |item: &StructLitField| match *item {
        StructLitField::Regular(field) => {
            // The 1 taken from the v_budget is for the comma.
            rewrite_field(context, field, try_opt!(v_shape.sub_width(1)))
        }
        StructLitField::Base(expr) => {
            // 2 = ..
            expr.rewrite(context, try_opt!(v_shape.shrink_left(2)))
                .map(|s| format!("..{}", s))
        }
    };

    let items = itemize_list(context.codemap,
                             field_iter,
                             "}",
                             span_lo,
                             span_hi,
                             rewrite,
                             context.codemap.span_after(span, "{"),
                             span.hi);
    let item_vec = items.collect::<Vec<_>>();

    let tactic = struct_lit_tactic(h_shape, context, &item_vec);
    let nested_shape = shape_for_tactic(tactic, h_shape, v_shape);
    let fmt = struct_lit_formatting(nested_shape, tactic, context, base.is_some());

    let fields_str = try_opt!(write_list(&item_vec, &fmt));
    let fields_str = if context.config.struct_lit_style() == IndentStyle::Block &&
                        (fields_str.contains('\n') ||
                         context.config.struct_lit_multiline_style() ==
                         MultilineStyle::ForceMulti ||
                         fields_str.len() > h_shape.map(|s| s.width).unwrap_or(0)) {
        format!("\n{}{}\n{}",
                v_shape.indent.to_string(context.config),
                fields_str,
                shape.indent.to_string(context.config))
    } else {
        // One liner or visual indent.
        format!(" {} ", fields_str)
    };

    Some(format!("{} {{{}}}", path_str, fields_str))

    // FIXME if context.config.struct_lit_style() == Visual, but we run out
    // of space, we should fall back to BlockIndent.
}

pub fn type_annotation_separator(config: &Config) -> &str {
    colon_spaces(config.space_before_type_annotation(),
                 config.space_after_type_annotation_colon())
}

fn rewrite_field(context: &RewriteContext, field: &ast::Field, shape: Shape) -> Option<String> {
    let name = &field.ident.node.to_string();
    if field.is_shorthand {
        Some(name.to_string())
    } else {
        let separator = type_annotation_separator(context.config);
        let overhead = name.len() + separator.len();
        let mut expr_shape = try_opt!(shape.sub_width(overhead));
        expr_shape.offset += overhead;
        let expr = field.expr.rewrite(context, expr_shape);

        let mut attrs_str = try_opt!((*field.attrs).rewrite(context, shape));
        if !attrs_str.is_empty() {
            attrs_str.push_str(&format!("\n{}", shape.indent.to_string(context.config)));
        };

        match expr {
            Some(e) => Some(format!("{}{}{}{}", attrs_str, name, separator, e)),
            None => {
                let expr_offset = shape.indent.block_indent(context.config);
                let expr = field
                    .expr
                    .rewrite(context, Shape::indented(expr_offset, context.config));
                expr.map(|s| {
                             format!("{}{}:\n{}{}",
                                     attrs_str,
                                     name,
                                     expr_offset.to_string(&context.config),
                                     s)
                         })
            }
        }
    }
}

fn shape_from_fn_call_style(context: &RewriteContext,
                            shape: Shape,
                            overhead: usize,
                            offset: usize)
                            -> Option<Shape> {
    if use_block_indent(context) {
        Some(shape.block().block_indent(context.config.tab_spaces()))
    } else {
        shape.visual_indent(offset).sub_width(overhead)
    }
}

pub fn rewrite_tuple_type<'a, I>(context: &RewriteContext,
                                 mut items: I,
                                 span: Span,
                                 shape: Shape)
                                 -> Option<String>
    where I: ExactSizeIterator,
          <I as Iterator>::Item: Deref,
          <I::Item as Deref>::Target: Rewrite + Spanned + 'a
{
    // In case of length 1, need a trailing comma
    debug!("rewrite_tuple_type {:?}", shape);
    if items.len() == 1 {
        // 3 = "(" + ",)"
        let nested_shape = try_opt!(shape.sub_width(3)).visual_indent(1);
        return items
            .next()
            .unwrap()
            .rewrite(context, nested_shape)
            .map(|s| if context.config.spaces_within_parens() {
                     format!("( {}, )", s)
                 } else {
                     format!("({},)", s)
                 });
    }

    let list_lo = context.codemap.span_after(span, "(");
    let nested_shape = try_opt!(shape.sub_width(2)).visual_indent(1);
    let items = itemize_list(context.codemap,
                             items,
                             ")",
                             |item| item.span().lo,
                             |item| item.span().hi,
                             |item| item.rewrite(context, nested_shape),
                             list_lo,
                             span.hi - BytePos(1));
    let list_str = try_opt!(format_item_list(items, nested_shape, context.config));

    if context.config.spaces_within_parens() && list_str.len() > 0 {
        Some(format!("( {} )", list_str))
    } else {
        Some(format!("({})", list_str))
    }
}

pub fn rewrite_tuple(context: &RewriteContext,
                     items: &[ptr::P<ast::Expr>],
                     span: Span,
                     shape: Shape)
                     -> Option<String> {
    debug!("rewrite_tuple {:?}", shape);
    // Use old `rewrite_tuple`
    if context.config.fn_call_style() == IndentStyle::Visual {
        return rewrite_tuple_type(context, items.iter().map(|x| &**x), span, shape);
    }

    // We use the same rule as funcation call for rewriting tuple.
    // 1 = ","
    rewrite_call_inner(context,
                       &String::new(),
                       items,
                       span,
                       shape,
                       items.len() == 1)
        .ok()
}

pub fn rewrite_unary_prefix<R: Rewrite>(context: &RewriteContext,
                                        prefix: &str,
                                        rewrite: &R,
                                        shape: Shape)
                                        -> Option<String> {
    rewrite
        .rewrite(context, try_opt!(shape.offset_left(prefix.len())))
        .map(|r| format!("{}{}", prefix, r))
}

// FIXME: this is probably not correct for multi-line Rewrites. we should
// subtract suffix.len() from the last line budget, not the first!
pub fn rewrite_unary_suffix<R: Rewrite>(context: &RewriteContext,
                                        suffix: &str,
                                        rewrite: &R,
                                        shape: Shape)
                                        -> Option<String> {
    rewrite
        .rewrite(context, try_opt!(shape.sub_width(suffix.len())))
        .map(|mut r| {
                 r.push_str(suffix);
                 r
             })
}

fn rewrite_unary_op(context: &RewriteContext,
                    op: &ast::UnOp,
                    expr: &ast::Expr,
                    shape: Shape)
                    -> Option<String> {
    // For some reason, an UnOp is not spanned like BinOp!
    let operator_str = match *op {
        ast::UnOp::Deref => "*",
        ast::UnOp::Not => "!",
        ast::UnOp::Neg => "-",
    };
    rewrite_unary_prefix(context, operator_str, expr, shape)
}

fn rewrite_assignment(context: &RewriteContext,
                      lhs: &ast::Expr,
                      rhs: &ast::Expr,
                      op: Option<&ast::BinOp>,
                      shape: Shape)
                      -> Option<String> {
    let operator_str = match op {
        Some(op) => context.snippet(op.span),
        None => "=".to_owned(),
    };

    // 1 = space between lhs and operator.
    let lhs_shape = try_opt!(shape.sub_width(operator_str.len() + 1));
    let lhs_str = format!("{} {}",
                          try_opt!(lhs.rewrite(context, lhs_shape)),
                          operator_str);

    rewrite_assign_rhs(context, lhs_str, rhs, shape)
}

// The left hand side must contain everything up to, and including, the
// assignment operator.
pub fn rewrite_assign_rhs<S: Into<String>>(context: &RewriteContext,
                                           lhs: S,
                                           ex: &ast::Expr,
                                           shape: Shape)
                                           -> Option<String> {
    let mut result = lhs.into();
    let last_line_width = last_line_width(&result) -
                          if result.contains('\n') {
                              shape.indent.width()
                          } else {
                              0
                          };
    // 1 = space between operator and rhs.
    let orig_shape = try_opt!(shape.block_indent(0).offset_left(last_line_width + 1));
    let rhs = match ex.node {
        ast::ExprKind::Mac(ref mac) => {
            match rewrite_macro(mac, None, context, orig_shape, MacroPosition::Expression) {
                None if !context.snippet(ex.span).contains("\n") => {
                    context.snippet(ex.span).rewrite(context, orig_shape)
                }
                rhs @ _ => rhs,
            }
        }
        _ => ex.rewrite(context, orig_shape),
    };

    fn count_line_breaks(src: &str) -> usize {
        src.chars().filter(|&x| x == '\n').count()
    }

    match rhs {
        Some(ref new_str) if count_line_breaks(new_str) < 2 => {
            result.push(' ');
            result.push_str(new_str);
        }
        _ => {
            // Expression did not fit on the same line as the identifier or is
            // at least three lines big. Try splitting the line and see
            // if that works better.
            let new_shape = try_opt!(shape.block_left(context.config.tab_spaces()));
            let new_rhs = ex.rewrite(context, new_shape);

            // FIXME: DRY!
            match (rhs, new_rhs) {
                (Some(ref orig_rhs), Some(ref replacement_rhs))
                    if count_line_breaks(orig_rhs) > count_line_breaks(replacement_rhs) + 1 ||
                       (orig_rhs.rewrite(context, shape).is_none() &&
                        replacement_rhs.rewrite(context, new_shape).is_some()) => {
                    result.push_str(&format!("\n{}", new_shape.indent.to_string(context.config)));
                    result.push_str(replacement_rhs);
                }
                (None, Some(ref final_rhs)) => {
                    result.push_str(&format!("\n{}", new_shape.indent.to_string(context.config)));
                    result.push_str(final_rhs);
                }
                (None, None) => return None,
                (Some(ref orig_rhs), _) => {
                    result.push(' ');
                    result.push_str(orig_rhs);
                }
            }
        }
    }

    Some(result)
}

fn rewrite_expr_addrof(context: &RewriteContext,
                       mutability: ast::Mutability,
                       expr: &ast::Expr,
                       shape: Shape)
                       -> Option<String> {
    let operator_str = match mutability {
        ast::Mutability::Immutable => "&",
        ast::Mutability::Mutable => "&mut ",
    };
    rewrite_unary_prefix(context, operator_str, expr, shape)
}
