Reformat source code using new defaults

This commit is contained in:
Nick Cameron
2017-06-12 15:58:58 +12:00
parent 32e882789b
commit 1f512948a0
27 changed files with 3224 additions and 2447 deletions
Generated
+1 -1
View File
@@ -1,6 +1,6 @@
[root]
name = "rustfmt"
version = "0.8.5"
version = "0.9.0"
dependencies = [
"diff 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
"env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
+1 -1
View File
@@ -1,7 +1,7 @@
[package]
name = "rustfmt"
version = "0.9"
version = "0.9.0"
authors = ["Nicholas Cameron <ncameron@mozilla.com>", "The Rustfmt developers"]
description = "Tool to find and fix Rust formatting issues"
repository = "https://github.com/rust-lang-nursery/rustfmt"
+46 -30
View File
@@ -42,10 +42,12 @@ fn execute() -> i32 {
opts.optflag("h", "help", "show this message");
opts.optflag("q", "quiet", "no output printed to stdout");
opts.optflag("v", "verbose", "use verbose output");
opts.optmulti("p",
"package",
"specify package to format (only usable in workspaces)",
"<package>");
opts.optmulti(
"p",
"package",
"specify package to format (only usable in workspaces)",
"<package>",
);
opts.optflag("", "all", "format all packages (only usable in workspaces)");
let matches = match opts.parse(env::args().skip(1).take_while(|a| a != "--")) {
@@ -90,9 +92,11 @@ fn execute() -> i32 {
fn print_usage(opts: &Options, reason: &str) {
let msg = format!("{}\nusage: cargo fmt [options]", reason);
println!("{}\nThis utility formats all bin and lib files of the current crate using rustfmt. \
println!(
"{}\nThis utility formats all bin and lib files of the current crate using rustfmt. \
Arguments after `--` are passed to rustfmt.",
opts.usage(&msg));
opts.usage(&msg)
);
}
#[derive(Debug, Clone, Copy, PartialEq)]
@@ -102,9 +106,10 @@ pub enum Verbosity {
Quiet,
}
fn format_crate(verbosity: Verbosity,
workspace_hitlist: WorkspaceHitlist)
-> Result<ExitStatus, std::io::Error> {
fn format_crate(
verbosity: Verbosity,
workspace_hitlist: WorkspaceHitlist,
) -> Result<ExitStatus, std::io::Error> {
let targets = get_targets(workspace_hitlist)?;
// Currently only bin and lib files get formatted
@@ -112,8 +117,8 @@ fn format_crate(verbosity: Verbosity,
.into_iter()
.filter(|t| t.kind.should_format())
.inspect(|t| if verbosity == Verbosity::Verbose {
println!("[{:?}] {:?}", t.kind, t.path)
})
println!("[{:?}] {:?}", t.kind, t.path)
})
.map(|t| t.path)
.collect();
@@ -194,8 +199,10 @@ fn get_targets(workspace_hitlist: WorkspaceHitlist) -> Result<Vec<Target>, std::
return Ok(targets);
}
return Err(std::io::Error::new(std::io::ErrorKind::NotFound,
str::from_utf8(&output.stderr).unwrap()));
return Err(std::io::Error::new(
std::io::ErrorKind::NotFound,
str::from_utf8(&output.stderr).unwrap(),
));
}
// This happens when cargo-fmt is not used inside a crate or
// is used inside a workspace.
@@ -221,18 +228,22 @@ fn get_targets(workspace_hitlist: WorkspaceHitlist) -> Result<Vec<Target>, std::
.unwrap()
.into_iter()
.filter(|member| if workspace_hitlist == WorkspaceHitlist::All {
true
} else {
let member_obj = member.as_object().unwrap();
let member_name = member_obj.get("name").unwrap().as_str().unwrap();
hitlist.take(&member_name.to_string()).is_some()
})
true
} else {
let member_obj = member.as_object().unwrap();
let member_name = member_obj.get("name").unwrap().as_str().unwrap();
hitlist.take(&member_name.to_string()).is_some()
})
.collect();
if hitlist.len() != 0 {
// Mimick cargo of only outputting one <package> spec.
return Err(std::io::Error::new(std::io::ErrorKind::InvalidInput,
format!("package `{}` is not a member of the workspace",
hitlist.iter().next().unwrap())));
return Err(std::io::Error::new(
std::io::ErrorKind::InvalidInput,
format!(
"package `{}` is not a member of the workspace",
hitlist.iter().next().unwrap()
),
));
}
for member in members {
let member_obj = member.as_object().unwrap();
@@ -243,8 +254,10 @@ fn get_targets(workspace_hitlist: WorkspaceHitlist) -> Result<Vec<Target>, std::
}
return Ok(targets);
}
Err(std::io::Error::new(std::io::ErrorKind::NotFound,
str::from_utf8(&output.stderr).unwrap()))
Err(std::io::Error::new(
std::io::ErrorKind::NotFound,
str::from_utf8(&output.stderr).unwrap(),
))
}
@@ -268,10 +281,11 @@ fn target_from_json(jtarget: &Value) -> Target {
}
}
fn format_files(files: &[PathBuf],
fmt_args: &[String],
verbosity: Verbosity)
-> Result<ExitStatus, std::io::Error> {
fn format_files(
files: &[PathBuf],
fmt_args: &[String],
verbosity: Verbosity,
) -> Result<ExitStatus, std::io::Error> {
let stdout = if verbosity == Verbosity::Quiet {
std::process::Stdio::null()
} else {
@@ -294,8 +308,10 @@ fn format_files(files: &[PathBuf],
.spawn()
.map_err(|e| match e.kind() {
std::io::ErrorKind::NotFound => {
std::io::Error::new(std::io::ErrorKind::Other,
"Could not run rustfmt, please make sure it is in your PATH.")
std::io::Error::new(
std::io::ErrorKind::Other,
"Could not run rustfmt, please make sure it is in your PATH.",
)
}
_ => e,
})?;
+75 -52
View File
@@ -74,7 +74,9 @@ fn from_matches(matches: &Matches) -> FmtResult<CliOptions> {
if let Ok(write_mode) = WriteMode::from_str(write_mode) {
options.write_mode = Some(write_mode);
} else {
return Err(FmtError::from(format!("Invalid write-mode: {}", write_mode)));
return Err(FmtError::from(
format!("Invalid write-mode: {}", write_mode),
));
}
}
@@ -96,9 +98,10 @@ fn apply_to(self, config: &mut Config) {
}
/// read the given config file path recursively if present else read the project file path
fn match_cli_path_or_file(config_path: Option<PathBuf>,
input_file: &Path)
-> FmtResult<(Config, Option<PathBuf>)> {
fn match_cli_path_or_file(
config_path: Option<PathBuf>,
input_file: &Path,
) -> FmtResult<(Config, Option<PathBuf>)> {
if let Some(config_file) = config_path {
let toml = Config::from_toml_path(config_file.as_ref())?;
@@ -112,32 +115,44 @@ fn make_opts() -> Options {
opts.optflag("h", "help", "show this message");
opts.optflag("V", "version", "show version information");
opts.optflag("v", "verbose", "print verbose output");
opts.optopt("",
"write-mode",
"mode to write in (not usable when piping from stdin)",
"[replace|overwrite|display|diff|coverage|checkstyle]");
opts.optopt(
"",
"write-mode",
"mode to write in (not usable when piping from stdin)",
"[replace|overwrite|display|diff|coverage|checkstyle]",
);
opts.optflag("", "skip-children", "don't reformat child modules");
opts.optflag("",
"config-help",
"show details of rustfmt configuration options");
opts.optopt("",
"dump-default-config",
"Dumps the default configuration to a file and exits.",
"PATH");
opts.optopt("",
"dump-minimal-config",
"Dumps configuration options that were checked during formatting to a file.",
"PATH");
opts.optopt("",
"config-path",
"Recursively searches the given path for the rustfmt.toml config file. If not \
opts.optflag(
"",
"config-help",
"show details of rustfmt configuration options",
);
opts.optopt(
"",
"dump-default-config",
"Dumps the default configuration to a file and exits.",
"PATH",
);
opts.optopt(
"",
"dump-minimal-config",
"Dumps configuration options that were checked during formatting to a file.",
"PATH",
);
opts.optopt(
"",
"config-path",
"Recursively searches the given path for the rustfmt.toml config file. If not \
found reverts to the input file path",
"[Path for the configuration file]");
opts.optopt("",
"file-lines",
"Format specified line ranges. See README for more detail on the JSON format.",
"JSON");
"[Path for the configuration file]",
);
opts.optopt(
"",
"file-lines",
"Format specified line ranges. See README for more detail on the JSON format.",
"JSON",
);
opts
}
@@ -167,8 +182,8 @@ fn execute(opts: &Options) -> FmtResult<Summary> {
}
Operation::Stdin { input, config_path } => {
// try to read config from local directory
let (mut config, _) = match_cli_path_or_file(config_path,
&env::current_dir().unwrap())?;
let (mut config, _) =
match_cli_path_or_file(config_path, &env::current_dir().unwrap())?;
// write_mode is always Plain for Stdin.
config.set().write_mode(WriteMode::Plain);
@@ -225,9 +240,11 @@ fn execute(opts: &Options) -> FmtResult<Summary> {
Config::from_resolved_toml_path(file.parent().unwrap())?;
if options.verbose {
if let Some(path) = path_tmp.as_ref() {
println!("Using rustfmt config file {} for {}",
path.display(),
file.display());
println!(
"Using rustfmt config file {} for {}",
path.display(),
file.display()
);
}
}
config = config_tmp;
@@ -288,16 +305,20 @@ fn main() {
}
fn print_usage(opts: &Options, reason: &str) {
let reason = format!("{}\n\nusage: {} [options] <file>...",
reason,
env::args_os().next().unwrap().to_string_lossy());
let reason = format!(
"{}\n\nusage: {} [options] <file>...",
reason,
env::args_os().next().unwrap().to_string_lossy()
);
println!("{}", opts.usage(&reason));
}
fn print_version() {
println!("{}-nightly{}",
env!("CARGO_PKG_VERSION"),
include_str!(concat!(env!("OUT_DIR"), "/commit-info.txt")))
println!(
"{}-nightly{}",
env!("CARGO_PKG_VERSION"),
include_str!(concat!(env!("OUT_DIR"), "/commit-info.txt"))
)
}
fn determine_operation(matches: &Matches) -> FmtResult<Operation> {
@@ -318,8 +339,10 @@ fn determine_operation(matches: &Matches) -> FmtResult<Operation> {
}
let config_path_not_found = |path: &str| -> FmtResult<Operation> {
Err(FmtError::from(format!("Error: unable to find a config file for the given path: `{}`",
path)))
Err(FmtError::from(format!(
"Error: unable to find a config file for the given path: `{}`",
path
)))
};
// Read the config_path and convert to parent dir if a file is provided.
@@ -346,25 +369,25 @@ fn determine_operation(matches: &Matches) -> FmtResult<Operation> {
io::stdin().read_to_string(&mut buffer)?;
return Ok(Operation::Stdin {
input: buffer,
config_path: config_path,
});
input: buffer,
config_path: config_path,
});
}
let files: Vec<_> = matches
.free
.iter()
.map(|s| {
let p = PathBuf::from(s);
// we will do comparison later, so here tries to canonicalize first
// to get the expected behavior.
p.canonicalize().unwrap_or(p)
})
let p = PathBuf::from(s);
// we will do comparison later, so here tries to canonicalize first
// to get the expected behavior.
p.canonicalize().unwrap_or(p)
})
.collect();
Ok(Operation::Format {
files: files,
config_path: config_path,
minimal_config_path: minimal_config_path,
})
files: files,
config_path: config_path,
minimal_config_path: minimal_config_path,
})
}
+160 -120
View File
@@ -101,9 +101,9 @@ pub fn rewrite_chain(expr: &ast::Expr, context: &RewriteContext, shape: Shape) -
let trailing_try_num = subexpr_list
.iter()
.take_while(|e| match e.node {
ast::ExprKind::Try(..) => true,
_ => false,
})
ast::ExprKind::Try(..) => true,
_ => false,
})
.count();
// Parent is the first item in the chain, e.g., `foo` in `foo.bar.baz()`.
@@ -128,7 +128,10 @@ pub fn rewrite_chain(expr: &ast::Expr, context: &RewriteContext, shape: Shape) -
} else {
chain_indent(context, shape.add_offset(parent_rewrite.len()))
};
(nested_shape, context.config.chain_indent() == IndentStyle::Visual || is_small_parent)
(
nested_shape,
context.config.chain_indent() == IndentStyle::Visual || is_small_parent,
)
} else if is_block_expr(context, &parent, &parent_rewrite) {
match context.config.chain_indent() {
// Try to put the first child on the same line with parent's last line
@@ -155,26 +158,33 @@ pub fn rewrite_chain(expr: &ast::Expr, context: &RewriteContext, shape: Shape) -
} else {
other_child_shape
};
debug!("child_shapes {:?} {:?}",
first_child_shape,
other_child_shape);
debug!(
"child_shapes {:?} {:?}",
first_child_shape,
other_child_shape
);
let child_shape_iter =
Some(first_child_shape)
.into_iter()
.chain(::std::iter::repeat(other_child_shape).take(subexpr_list.len() - 1));
let child_shape_iter = Some(first_child_shape).into_iter().chain(
::std::iter::repeat(
other_child_shape,
).take(
subexpr_list.len() - 1,
),
);
let iter = subexpr_list.iter().rev().zip(child_shape_iter);
let mut rewrites = try_opt!(iter.map(|(e, shape)| {
rewrite_chain_subexpr(e, total_span, context, shape)
}).collect::<Option<Vec<_>>>());
let mut rewrites = try_opt!(
iter.map(|(e, shape)| {
rewrite_chain_subexpr(e, total_span, context, shape)
}).collect::<Option<Vec<_>>>()
);
// Total of all items excluding the last.
let last_non_try_index = rewrites.len() - (1 + trailing_try_num);
let almost_total = rewrites[..last_non_try_index]
.iter()
.fold(0, |a, b| a + first_line_width(b)) + parent_rewrite.len();
let almost_total = rewrites[..last_non_try_index].iter().fold(0, |a, b| {
a + first_line_width(b)
}) + parent_rewrite.len();
let one_line_len = rewrites.iter().fold(0, |a, r| a + first_line_width(r)) +
parent_rewrite.len();
parent_rewrite.len();
let one_line_budget = min(shape.width, context.config.chain_one_line_max());
let veto_single_line = if one_line_len > one_line_budget {
@@ -206,12 +216,15 @@ pub fn rewrite_chain(expr: &ast::Expr, context: &RewriteContext, shape: Shape) -
if fits_single_line {
fits_single_line = match expr.node {
ref e @ ast::ExprKind::MethodCall(..) => {
if rewrite_method_call_with_overflow(e,
&mut last[0],
almost_total,
total_span,
context,
shape) {
if rewrite_method_call_with_overflow(
e,
&mut last[0],
almost_total,
total_span,
context,
shape,
)
{
// If the first line of the last method does not fit into a single line
// after the others, allow new lines.
almost_total + first_line_width(&last[0]) < context.config.max_width()
@@ -233,13 +246,15 @@ pub fn rewrite_chain(expr: &ast::Expr, context: &RewriteContext, shape: Shape) -
width: one_line_budget,
..parent_shape
};
fits_single_line = rewrite_last_child_with_overflow(context,
&subexpr_list[trailing_try_num],
overflow_shape,
total_span,
almost_total,
one_line_budget,
&mut last[0]);
fits_single_line = rewrite_last_child_with_overflow(
context,
&subexpr_list[trailing_try_num],
overflow_shape,
total_span,
almost_total,
one_line_budget,
&mut last[0],
);
}
}
@@ -254,68 +269,83 @@ pub fn rewrite_chain(expr: &ast::Expr, context: &RewriteContext, shape: Shape) -
format!("\n{}", nested_shape.indent.to_string(context.config))
};
let first_connector = choose_first_connector(context,
&parent_rewrite,
&rewrites[0],
&connector,
&subexpr_list,
extend);
let first_connector = choose_first_connector(
context,
&parent_rewrite,
&rewrites[0],
&connector,
&subexpr_list,
extend,
);
if is_small_parent && rewrites.len() > 1 {
let second_connector = choose_first_connector(context,
&rewrites[0],
&rewrites[1],
&connector,
&subexpr_list[0..subexpr_list.len() - 1],
false);
wrap_str(format!("{}{}{}{}{}",
parent_rewrite,
first_connector,
rewrites[0],
second_connector,
join_rewrites(&rewrites[1..],
&subexpr_list[0..subexpr_list.len() - 1],
&connector)),
context.config.max_width(),
shape)
let second_connector = choose_first_connector(
context,
&rewrites[0],
&rewrites[1],
&connector,
&subexpr_list[0..subexpr_list.len() - 1],
false,
);
wrap_str(
format!(
"{}{}{}{}{}",
parent_rewrite,
first_connector,
rewrites[0],
second_connector,
join_rewrites(
&rewrites[1..],
&subexpr_list[0..subexpr_list.len() - 1],
&connector,
)
),
context.config.max_width(),
shape,
)
} else {
wrap_str(format!("{}{}{}",
parent_rewrite,
first_connector,
join_rewrites(&rewrites, &subexpr_list, &connector)),
context.config.max_width(),
shape)
wrap_str(
format!(
"{}{}{}",
parent_rewrite,
first_connector,
join_rewrites(&rewrites, &subexpr_list, &connector)
),
context.config.max_width(),
shape,
)
}
}
fn is_extendable_parent(context: &RewriteContext, parent_str: &str) -> bool {
context.config.chain_indent() == IndentStyle::Block &&
parent_str.lines().last().map_or(false, |s| {
s.trim()
.chars()
.all(|c| c == ')' || c == ']' || c == '}' || c == '?')
})
parent_str.lines().last().map_or(false, |s| {
s.trim().chars().all(|c| {
c == ')' || c == ']' || c == '}' || c == '?'
})
})
}
// True if the chain is only `?`s.
fn chain_only_try(exprs: &[ast::Expr]) -> bool {
exprs.iter().all(|e| if let ast::ExprKind::Try(_) = e.node {
true
} else {
false
})
true
} else {
false
})
}
// Try to rewrite and replace the last non-try child. Return `true` if
// replacing succeeds.
fn rewrite_last_child_with_overflow(context: &RewriteContext,
expr: &ast::Expr,
shape: Shape,
span: Span,
almost_total: usize,
one_line_budget: usize,
last_child: &mut String)
-> bool {
fn rewrite_last_child_with_overflow(
context: &RewriteContext,
expr: &ast::Expr,
shape: Shape,
span: Span,
almost_total: usize,
one_line_budget: usize,
last_child: &mut String,
) -> bool {
if let Some(shape) = shape.shrink_left(almost_total) {
if let Some(ref mut rw) = rewrite_chain_subexpr(expr, span, context, shape) {
if almost_total + first_line_width(rw) <= one_line_budget {
@@ -327,15 +357,18 @@ fn rewrite_last_child_with_overflow(context: &RewriteContext,
false
}
pub fn rewrite_try(expr: &ast::Expr,
try_count: usize,
context: &RewriteContext,
shape: Shape)
-> Option<String> {
pub fn rewrite_try(
expr: &ast::Expr,
try_count: usize,
context: &RewriteContext,
shape: Shape,
) -> Option<String> {
let sub_expr = try_opt!(expr.rewrite(context, try_opt!(shape.sub_width(try_count))));
Some(format!("{}{}",
sub_expr,
iter::repeat("?").take(try_count).collect::<String>()))
Some(format!(
"{}{}",
sub_expr,
iter::repeat("?").take(try_count).collect::<String>()
))
}
fn join_rewrites(rewrites: &[String], subexps: &[ast::Expr], connector: &str) -> String {
@@ -398,24 +431,27 @@ fn chain_indent(context: &RewriteContext, shape: Shape) -> Shape {
}
}
fn rewrite_method_call_with_overflow(expr_kind: &ast::ExprKind,
last: &mut String,
almost_total: usize,
total_span: Span,
context: &RewriteContext,
shape: Shape)
-> bool {
fn rewrite_method_call_with_overflow(
expr_kind: &ast::ExprKind,
last: &mut String,
almost_total: usize,
total_span: Span,
context: &RewriteContext,
shape: Shape,
) -> bool {
if let &ast::ExprKind::MethodCall(ref method_name, ref types, ref expressions) = expr_kind {
let shape = match shape.shrink_left(almost_total) {
Some(b) => b,
None => return false,
};
let mut last_rewrite = rewrite_method_call(method_name.node,
types,
expressions,
total_span,
context,
shape);
let mut last_rewrite = rewrite_method_call(
method_name.node,
types,
expressions,
total_span,
context,
shape,
);
if let Some(ref mut s) = last_rewrite {
::std::mem::swap(s, last);
@@ -457,11 +493,12 @@ fn convert_try(expr: &ast::Expr, context: &RewriteContext) -> ast::Expr {
// Rewrite the last element in the chain `expr`. E.g., given `a.b.c` we rewrite
// `.c`.
fn rewrite_chain_subexpr(expr: &ast::Expr,
span: Span,
context: &RewriteContext,
shape: Shape)
-> Option<String> {
fn rewrite_chain_subexpr(
expr: &ast::Expr,
span: Span,
context: &RewriteContext,
shape: Shape,
) -> Option<String> {
let rewrite_element = |expr_str: String| if expr_str.len() <= shape.width {
Some(expr_str)
} else {
@@ -500,20 +537,23 @@ fn is_try(expr: &ast::Expr) -> bool {
}
}
fn choose_first_connector<'a>(context: &RewriteContext,
parent_str: &str,
first_child_str: &str,
connector: &'a str,
subexpr_list: &[ast::Expr],
extend: bool)
-> &'a str {
fn choose_first_connector<'a>(
context: &RewriteContext,
parent_str: &str,
first_child_str: &str,
connector: &'a str,
subexpr_list: &[ast::Expr],
extend: bool,
) -> &'a str {
if subexpr_list.is_empty() {
""
} else if extend || subexpr_list.last().map_or(false, is_try) ||
is_extendable_parent(context, parent_str) {
is_extendable_parent(context, parent_str)
{
// 1 = ";", being conservative here.
if last_line_width(parent_str) + first_line_width(first_child_str) + 1 <=
context.config.max_width() {
context.config.max_width()
{
""
} else {
connector
@@ -523,18 +563,18 @@ fn choose_first_connector<'a>(context: &RewriteContext,
}
}
fn rewrite_method_call(method_name: ast::Ident,
types: &[ptr::P<ast::Ty>],
args: &[ptr::P<ast::Expr>],
span: Span,
context: &RewriteContext,
shape: Shape)
-> Option<String> {
fn rewrite_method_call(
method_name: ast::Ident,
types: &[ptr::P<ast::Ty>],
args: &[ptr::P<ast::Expr>],
span: Span,
context: &RewriteContext,
shape: Shape,
) -> Option<String> {
let (lo, type_str) = if types.is_empty() {
(args[0].span.hi, String::new())
} else {
let type_list: Vec<_> =
try_opt!(types.iter().map(|ty| ty.rewrite(context, shape)).collect());
let type_list: Vec<_> = try_opt!(types.iter().map(|ty| ty.rewrite(context, shape)).collect());
let type_str = if context.config.spaces_within_angle_brackets() && type_list.len() > 0 {
format!("::< {} >", type_list.join(", "))
+17 -11
View File
@@ -13,7 +13,8 @@
pub fn output_header<T>(out: &mut T, mode: WriteMode) -> Result<(), io::Error>
where T: Write
where
T: Write,
{
if mode == WriteMode::Checkstyle {
let mut xml_heading = String::new();
@@ -26,7 +27,8 @@ pub fn output_header<T>(out: &mut T, mode: WriteMode) -> Result<(), io::Error>
}
pub fn output_footer<T>(out: &mut T, mode: WriteMode) -> Result<(), io::Error>
where T: Write
where
T: Write,
{
if mode == WriteMode::Checkstyle {
let mut xml_tail = String::new();
@@ -36,11 +38,13 @@ pub fn output_footer<T>(out: &mut T, mode: WriteMode) -> Result<(), io::Error>
Ok(())
}
pub fn output_checkstyle_file<T>(mut writer: T,
filename: &str,
diff: Vec<Mismatch>)
-> Result<(), io::Error>
where T: Write
pub fn output_checkstyle_file<T>(
mut writer: T,
filename: &str,
diff: Vec<Mismatch>,
) -> Result<(), io::Error>
where
T: Write,
{
write!(writer, "<file name=\"{}\">", filename)?;
for mismatch in diff {
@@ -48,11 +52,13 @@ pub fn output_checkstyle_file<T>(mut writer: T,
// Do nothing with `DiffLine::Context` and `DiffLine::Resulting`.
if let DiffLine::Expected(ref str) = line {
let message = xml_escape_str(str);
write!(writer,
"<error line=\"{}\" severity=\"warning\" message=\"Should be `{}`\" \
write!(
writer,
"<error line=\"{}\" severity=\"warning\" message=\"Should be `{}`\" \
/>",
mismatch.line_number,
message)?;
mismatch.line_number,
message
)?;
}
}
}
+6 -4
View File
@@ -77,10 +77,12 @@ fn lookup_line_range(&self, span: Span) -> LineRange {
let lo = self.lookup_char_pos(span.lo);
let hi = self.lookup_char_pos(span.hi);
assert!(lo.file.name == hi.file.name,
"span crossed file boundary: lo: {:?}, hi: {:?}",
lo,
hi);
assert!(
lo.file.name == hi.file.name,
"span crossed file boundary: lo: {:?}, hi: {:?}",
lo,
hi
);
LineRange {
file: lo.file.clone(),
+130 -89
View File
@@ -45,9 +45,9 @@ pub enum CommentStyle<'a> {
fn custom_opener(s: &str) -> &str {
s.lines().next().map_or("", |first_line| {
first_line
.find(' ')
.map_or(first_line, |space_index| &first_line[0..space_index + 1])
first_line.find(' ').map_or(first_line, |space_index| {
&first_line[0..space_index + 1]
})
})
}
@@ -98,14 +98,14 @@ pub fn line_with_same_comment_style(&self, line: &str, normalize_comments: bool)
CommentStyle::TripleSlash |
CommentStyle::Doc => {
line.trim_left().starts_with(self.line_start().trim_left()) ||
comment_style(line, normalize_comments) == *self
comment_style(line, normalize_comments) == *self
}
CommentStyle::DoubleBullet |
CommentStyle::SingleBullet |
CommentStyle::Exclamation => {
line.trim_left().starts_with(self.closer().trim_left()) ||
line.trim_left().starts_with(self.line_start().trim_left()) ||
comment_style(line, normalize_comments) == *self
line.trim_left().starts_with(self.line_start().trim_left()) ||
comment_style(line, normalize_comments) == *self
}
CommentStyle::Custom(opener) => line.trim_left().starts_with(opener.trim_right()),
}
@@ -130,7 +130,8 @@ fn comment_style(orig: &str, normalize_comments: bool) -> CommentStyle {
CommentStyle::DoubleSlash
}
} else if (orig.starts_with("///") && orig.chars().nth(3).map_or(true, |c| c != '/')) ||
(orig.starts_with("/**") && !orig.starts_with("/**/")) {
(orig.starts_with("/**") && !orig.starts_with("/**/"))
{
CommentStyle::TripleSlash
} else if orig.starts_with("//!") || orig.starts_with("/*!") {
CommentStyle::Doc
@@ -141,17 +142,20 @@ fn comment_style(orig: &str, normalize_comments: bool) -> CommentStyle {
}
}
pub fn rewrite_comment(orig: &str,
block_style: bool,
shape: Shape,
config: &Config)
-> Option<String> {
pub fn rewrite_comment(
orig: &str,
block_style: bool,
shape: Shape,
config: &Config,
) -> Option<String> {
// If there are lines without a starting sigil, we won't format them correctly
// so in that case we won't even re-align (if !config.normalize_comments()) and
// we should stop now.
let num_bare_lines = orig.lines()
.map(|line| line.trim())
.filter(|l| !(l.starts_with('*') || l.starts_with("//") || l.starts_with("/*")))
.filter(|l| {
!(l.starts_with('*') || l.starts_with("//") || l.starts_with("/*"))
})
.count();
if num_bare_lines > 0 && !config.normalize_comments() {
return Some(orig.to_owned());
@@ -163,11 +167,12 @@ pub fn rewrite_comment(orig: &str,
identify_comment(orig, block_style, shape, config)
}
fn identify_comment(orig: &str,
block_style: bool,
shape: Shape,
config: &Config)
-> Option<String> {
fn identify_comment(
orig: &str,
block_style: bool,
shape: Shape,
config: &Config,
) -> Option<String> {
let style = comment_style(orig, false);
let first_group = orig.lines()
.take_while(|l| style.line_with_same_comment_style(l, false))
@@ -178,28 +183,34 @@ fn identify_comment(orig: &str,
.collect::<Vec<_>>()
.join("\n");
let first_group_str =
try_opt!(rewrite_comment_inner(&first_group, block_style, style, shape, config));
let first_group_str = try_opt!(rewrite_comment_inner(
&first_group,
block_style,
style,
shape,
config,
));
if rest.is_empty() {
Some(first_group_str)
} else {
identify_comment(&rest, block_style, shape, config).map(|rest_str| {
format!("{}\n{}{}",
first_group_str,
shape
.indent
.to_string(config),
rest_str)
})
format!(
"{}\n{}{}",
first_group_str,
shape.indent.to_string(config),
rest_str
)
})
}
}
fn rewrite_comment_inner(orig: &str,
block_style: bool,
style: CommentStyle,
shape: Shape,
config: &Config)
-> Option<String> {
fn rewrite_comment_inner(
orig: &str,
block_style: bool,
style: CommentStyle,
shape: Shape,
config: &Config,
) -> Option<String> {
let (opener, closer, line_start) = if block_style {
CommentStyle::SingleBullet.to_str_tuplet()
} else {
@@ -235,10 +246,10 @@ fn rewrite_comment_inner(orig: &str,
})
.map(|s| left_trim_comment_line(s, &style))
.map(|line| if orig.starts_with("/*") && line_breaks == 0 {
line.trim_left()
} else {
line
});
line.trim_left()
} else {
line
});
let mut result = opener.to_owned();
for line in lines {
@@ -299,7 +310,8 @@ fn light_rewrite_comment(orig: &str, offset: Indent, config: &Config) -> Option<
/// Does not trim all whitespace.
fn left_trim_comment_line<'a>(line: &'a str, style: &CommentStyle) -> &'a str {
if line.starts_with("//! ") || line.starts_with("/// ") || line.starts_with("/*! ") ||
line.starts_with("/** ") {
line.starts_with("/** ")
{
&line[4..]
} else if let &CommentStyle::Custom(opener) = style {
if line.starts_with(opener) {
@@ -307,13 +319,15 @@ fn left_trim_comment_line<'a>(line: &'a str, style: &CommentStyle) -> &'a str {
} else {
&line[opener.trim_right().len()..]
}
} else if line.starts_with("/* ") || line.starts_with("// ") || line.starts_with("//!") ||
line.starts_with("///") ||
line.starts_with("** ") || line.starts_with("/*!") ||
(line.starts_with("/**") && !line.starts_with("/**/")) {
} else if line.starts_with("/* ") || line.starts_with("// ") ||
line.starts_with("//!") || line.starts_with("///") ||
line.starts_with("** ") || line.starts_with("/*!") ||
(line.starts_with("/**") && !line.starts_with("/**/"))
{
&line[3..]
} else if line.starts_with("/*") || line.starts_with("* ") || line.starts_with("//") ||
line.starts_with("**") {
line.starts_with("**")
{
&line[2..]
} else if line.starts_with('*') {
&line[1..]
@@ -379,8 +393,9 @@ pub fn contains_comment(text: &str) -> bool {
}
struct CharClasses<T>
where T: Iterator,
T::Item: RichChar
where
T: Iterator,
T::Item: RichChar,
{
base: iter::Peekable<T>,
status: CharClassesStatus,
@@ -462,8 +477,9 @@ fn to_codecharkind(&self) -> CodeCharKind {
}
impl<T> CharClasses<T>
where T: Iterator,
T::Item: RichChar
where
T: Iterator,
T::Item: RichChar,
{
fn new(base: T) -> CharClasses<T> {
CharClasses {
@@ -474,8 +490,9 @@ fn new(base: T) -> CharClasses<T> {
}
impl<T> Iterator for CharClasses<T>
where T: Iterator,
T::Item: RichChar
where
T: Iterator,
T::Item: RichChar,
{
type Item = (FullCodeCharKind, T::Item);
@@ -603,13 +620,15 @@ fn next(&mut self) -> Option<Self::Item> {
Some(&(_, (end_idx, _))) => &self.slice[start_idx..end_idx],
None => &self.slice[start_idx..],
};
Some((if kind.is_comment() {
CodeCharKind::Comment
} else {
CodeCharKind::Normal
},
start_idx,
slice))
Some((
if kind.is_comment() {
CodeCharKind::Comment
} else {
CodeCharKind::Normal
},
start_idx,
slice,
))
}
}
@@ -650,8 +669,8 @@ fn next(&mut self) -> Option<Self::Item> {
for (kind, (i, c)) in &mut iter {
let is_comment_connector = self.last_slice_kind == CodeCharKind::Normal &&
&subslice[..2] == "//" &&
[' ', '\t'].contains(&c);
&subslice[..2] == "//" &&
[' ', '\t'].contains(&c);
if is_comment_connector && first_whitespace.is_none() {
first_whitespace = Some(i);
@@ -683,7 +702,11 @@ fn next(&mut self) -> Option<Self::Item> {
CodeCharKind::Comment => CodeCharKind::Normal,
CodeCharKind::Normal => CodeCharKind::Comment,
};
let res = (kind, self.last_slice_end, &self.slice[self.last_slice_end..sub_slice_end]);
let res = (
kind,
self.last_slice_end,
&self.slice[self.last_slice_end..sub_slice_end],
);
self.last_slice_end = sub_slice_end;
self.last_slice_kind = kind;
@@ -693,11 +716,12 @@ fn next(&mut self) -> Option<Self::Item> {
/// Checks is `new` didn't miss any comment from `span`, if it removed any, return previous text
/// (if it fits in the width/offset, else return None), else return `new`
pub fn recover_comment_removed(new: String,
span: Span,
context: &RewriteContext,
shape: Shape)
-> Option<String> {
pub fn recover_comment_removed(
new: String,
span: Span,
context: &RewriteContext,
shape: Shape,
) -> Option<String> {
let snippet = context.snippet(span);
if changed_comment_content(&snippet, &new) {
// We missed some comments
@@ -723,12 +747,14 @@ fn changed_comment_content(orig: &str, new: &str) -> bool {
.flat_map(|(_, _, s)| CommentReducer::new(s))
};
let res = code_comment_content(orig).ne(code_comment_content(new));
debug!("comment::changed_comment_content: {}\norig: '{}'\nnew: '{}'\nraw_old: {}\nraw_new: {}",
res,
orig,
new,
code_comment_content(orig).collect::<String>(),
code_comment_content(new).collect::<String>());
debug!(
"comment::changed_comment_content: {}\norig: '{}'\nnew: '{}'\nraw_old: {}\nraw_new: {}",
res,
orig,
new,
code_comment_content(orig).collect::<String>(),
code_comment_content(new).collect::<String>()
);
res
}
@@ -787,11 +813,14 @@ fn remove_comment_header(comment: &str) -> &str {
} else if comment.starts_with("//") {
&comment[2..]
} else if (comment.starts_with("/**") && !comment.starts_with("/**/")) ||
comment.starts_with("/*!") {
comment.starts_with("/*!")
{
&comment[3..comment.len() - 2]
} else {
assert!(comment.starts_with("/*"),
format!("string '{}' is not a comment", comment));
assert!(
comment.starts_with("/*"),
format!("string '{}' is not a comment", comment)
);
&comment[2..comment.len() - 2]
}
}
@@ -819,8 +848,10 @@ fn comment_code_slices() {
let mut iter = CommentCodeSlices::new(input);
assert_eq!((CodeCharKind::Normal, 0, "code(); "), iter.next().unwrap());
assert_eq!((CodeCharKind::Comment, 8, "/* test */"),
iter.next().unwrap());
assert_eq!(
(CodeCharKind::Comment, 8, "/* test */"),
iter.next().unwrap()
);
assert_eq!((CodeCharKind::Normal, 18, " 1 + 1"), iter.next().unwrap());
assert_eq!(None, iter.next());
}
@@ -831,10 +862,14 @@ fn comment_code_slices_two() {
let mut iter = CommentCodeSlices::new(input);
assert_eq!((CodeCharKind::Normal, 0, ""), iter.next().unwrap());
assert_eq!((CodeCharKind::Comment, 0, "// comment\n"),
iter.next().unwrap());
assert_eq!((CodeCharKind::Normal, 11, " test();"),
iter.next().unwrap());
assert_eq!(
(CodeCharKind::Comment, 0, "// comment\n"),
iter.next().unwrap()
);
assert_eq!(
(CodeCharKind::Normal, 11, " test();"),
iter.next().unwrap()
);
assert_eq!(None, iter.next());
}
@@ -844,8 +879,10 @@ fn comment_code_slices_three() {
let mut iter = CommentCodeSlices::new(input);
assert_eq!((CodeCharKind::Normal, 0, "1 "), iter.next().unwrap());
assert_eq!((CodeCharKind::Comment, 2, "// comment\n // comment2\n"),
iter.next().unwrap());
assert_eq!(
(CodeCharKind::Comment, 2, "// comment\n // comment2\n"),
iter.next().unwrap()
);
assert_eq!((CodeCharKind::Normal, 29, "\n"), iter.next().unwrap());
assert_eq!(None, iter.next());
}
@@ -896,17 +933,19 @@ fn format_comments() {
fn uncommented(text: &str) -> String {
CharClasses::new(text.chars())
.filter_map(|(s, c)| match s {
FullCodeCharKind::Normal => Some(c),
_ => None,
})
FullCodeCharKind::Normal => Some(c),
_ => None,
})
.collect()
}
#[test]
fn test_uncommented() {
assert_eq!(&uncommented("abc/*...*/"), "abc");
assert_eq!(&uncommented("// .... /* \n../* /* *** / */ */a/* // */c\n"),
"..ac\n");
assert_eq!(
&uncommented("// .... /* \n../* /* *** / */ */a/* // */c\n"),
"..ac\n"
);
assert_eq!(&uncommented("abc \" /* */\" qsdf"), "abc \" /* */\" qsdf");
}
@@ -927,9 +966,11 @@ fn check(haystack: &str, needle: &str, expected: Option<usize>) {
check("/*/ */test", "test", Some(6));
check("//test\ntest", "test", Some(7));
check("/* comment only */", "whatever", None);
check("/* comment */ some text /* more commentary */ result",
"result",
Some(46));
check(
"/* comment */ some text /* more commentary */ result",
"result",
Some(46),
);
check("sup // sup", "p", Some(2));
check("sup", "x", None);
check(r#"π? /**/ π is nice!"#, r#"π is nice"#, Some(9));
+4 -2
View File
@@ -605,7 +605,9 @@ fn test_config_used_to_toml() {
let used_options = config.used_options();
let toml = used_options.to_toml().unwrap();
assert_eq!(toml,
format!("verbose = {}\nskip_children = {}\n", verbose, skip_children));
assert_eq!(
toml,
format!("verbose = {}\nskip_children = {}\n", verbose, skip_children)
);
}
}
+766 -574
View File
@@ -47,21 +47,24 @@ enum ExprType {
SubExpression,
}
fn format_expr(expr: &ast::Expr,
expr_type: ExprType,
context: &RewriteContext,
shape: Shape)
-> Option<String> {
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)
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 {
@@ -69,9 +72,11 @@ fn format_expr(expr: &ast::Expr,
rewrite_string_lit(context, l.span, shape)
}
_ => {
wrap_str(context.snippet(expr.span),
context.config.max_width(),
shape)
wrap_str(
context.snippet(expr.span),
context.config.max_width(),
shape,
)
}
}
}
@@ -82,22 +87,26 @@ fn format_expr(expr: &ast::Expr,
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)
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)
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) => {
@@ -114,24 +123,26 @@ fn format_expr(expr: &ast::Expr,
}
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)
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)
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)
@@ -150,9 +161,11 @@ fn format_expr(expr: &ast::Expr,
Some(ident) => format!(" {}", ident.node),
None => String::new(),
};
wrap_str(format!("continue{}", id_str),
context.config.max_width(),
shape)
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 {
@@ -163,9 +176,11 @@ fn format_expr(expr: &ast::Expr,
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)
wrap_str(
format!("break{}", id_str),
context.config.max_width(),
shape,
)
}
}
ast::ExprKind::Closure(capture, ref fn_decl, ref body, _) => {
@@ -179,9 +194,11 @@ fn format_expr(expr: &ast::Expr,
// 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)
wrap_str(
context.snippet(expr.span),
context.config.max_width(),
shape,
)
})
}
ast::ExprKind::Ret(None) => {
@@ -249,9 +266,11 @@ fn format_expr(expr: &ast::Expr,
// satisfy our width restrictions.
ast::ExprKind::InPlace(..) |
ast::ExprKind::InlineAsm(..) => {
wrap_str(context.snippet(expr.span),
context.config.max_width(),
shape)
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) {
@@ -259,28 +278,33 @@ fn format_expr(expr: &ast::Expr,
}
// 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)))))
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)
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> {
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));
@@ -292,16 +316,18 @@ fn try_one_line_block(context: &RewriteContext,
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
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
@@ -374,21 +400,25 @@ pub fn rewrite_pair<LHS, RHS>(lhs: &LHS,
Style::Rfc => try_opt!(shape.sub_width(prefix.len() + infix.len())),
};
let lhs_result = try_opt!(lhs.rewrite(context, lhs_shape));
Some(format!("{}{}{}\n{}{}{}",
prefix,
lhs_result,
infix,
rhs_shape.indent.to_string(context.config),
rhs_result,
suffix))
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>
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 // "[ "
@@ -399,21 +429,22 @@ pub fn rewrite_array<'a, I>(expr_iter: I,
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))
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<_>>();
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() {
@@ -423,11 +454,12 @@ pub fn rewrite_array<'a, I>(expr_iter: I,
}
}
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 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 => {
@@ -443,11 +475,11 @@ pub fn rewrite_array<'a, I>(expr_iter: I,
}
IndentStyle::Visual => {
if has_long_item || items.iter().any(ListItem::is_multiline) {
definitive_tactic(&items,
ListTactic::LimitedHorizontalVertical(context
.config
.array_width()),
nested_shape.width)
definitive_tactic(
&items,
ListTactic::LimitedHorizontalVertical(context.config.array_width()),
nested_shape.width,
)
} else {
DefinitiveListTactic::Mixed
}
@@ -465,17 +497,20 @@ pub fn rewrite_array<'a, I>(expr_iter: I,
let list_str = try_opt!(write_list(&items, &fmt));
let result = if context.config.array_layout() == IndentStyle::Visual ||
tactic != DefinitiveListTactic::Vertical {
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))
format!(
"[\n{}{},\n{}]",
nested_shape.indent.to_string(context.config),
list_str,
shape.block().indent.to_string(context.config)
)
};
Some(result)
@@ -490,13 +525,14 @@ pub fn rewrite_array<'a, I>(expr_iter: I,
// * 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> {
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 {
@@ -511,14 +547,16 @@ fn rewrite_closure(capture: ast::CaptureBy,
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 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
@@ -564,9 +602,9 @@ fn rewrite_closure(capture: ast::CaptureBy,
// 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');
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
@@ -600,22 +638,25 @@ fn rewrite_closure(capture: ast::CaptureBy,
// 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,
}],
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> {
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);
@@ -623,18 +664,20 @@ fn rewrite_closure_expr(expr: &ast::Expr,
rewrite.map(|rw| format!("{} {}", prefix, rw))
}
fn rewrite_closure_block(block: &ast::Block,
prefix: String,
context: &RewriteContext,
shape: Shape)
-> Option<String> {
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) {
!need_block_indent(&block_str, shape)
{
if let Some(block_str) = block_str.rewrite(context, shape) {
return Some(format!("{} {}", prefix, block_str));
}
@@ -656,13 +699,14 @@ fn and_one_line(x: Option<String>) -> Option<String> {
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()
})
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 {
@@ -671,7 +715,8 @@ fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option<String> {
// or an unsafe expression `unsafe { e }`.
if self.stmts.is_empty() && !block_contains_comment(self, context.codemap) &&
shape.width >= 2 {
shape.width >= 2
{
return Some("{}".to_owned());
}
@@ -681,8 +726,9 @@ fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option<String> {
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 {
!comment_str.starts_with("//") &&
comment_str.len() + 4 <= shape.width
{
return Some(format!("{{ {} }}", comment_str));
}
}
@@ -703,11 +749,15 @@ fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option<String> {
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)))
format!(
"unsafe {} ",
try_opt!(rewrite_comment(
trimmed,
true,
Shape::legacy(budget, shape.indent + 7),
context.config,
))
)
} else {
"unsafe ".to_owned()
};
@@ -724,8 +774,10 @@ fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option<String> {
visitor.visit_block(self);
if visitor.failed && shape.indent.alignment != 0 {
self.rewrite(context,
Shape::indented(shape.indent.block_only(), context.config))
self.rewrite(
context,
Shape::indented(shape.indent.block_only(), context.config),
)
} else {
Some(format!("{}{}", prefix, visitor.buffer))
}
@@ -740,20 +792,23 @@ fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option<String> {
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)
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))
result.and_then(|res| {
recover_comment_removed(res, self.span, context, shape)
})
}
}
@@ -775,14 +830,15 @@ struct ControlFlow<'a> {
}
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> {
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,
@@ -801,10 +857,11 @@ fn new_if(cond: &'a ast::Expr,
}
}
fn new_loop(block: &'a ast::Block,
label: Option<ast::SpannedIdent>,
span: Span)
-> ControlFlow<'a> {
fn new_loop(
block: &'a ast::Block,
label: Option<ast::SpannedIdent>,
span: Span,
) -> ControlFlow<'a> {
ControlFlow {
cond: None,
block: block,
@@ -820,12 +877,13 @@ fn new_loop(block: &'a ast::Block,
}
}
fn new_while(pat: Option<&'a ast::Pat>,
cond: &'a ast::Expr,
block: &'a ast::Block,
label: Option<ast::SpannedIdent>,
span: Span)
-> ControlFlow<'a> {
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,
@@ -844,12 +902,13 @@ fn new_while(pat: Option<&'a ast::Pat>,
}
}
fn new_for(pat: &'a ast::Pat,
cond: &'a ast::Expr,
block: &'a ast::Block,
label: Option<ast::SpannedIdent>,
span: Span)
-> ControlFlow<'a> {
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,
@@ -865,40 +924,49 @@ fn new_for(pat: &'a ast::Pat,
}
}
fn rewrite_single_line(&self,
pat_expr_str: &str,
context: &RewriteContext,
width: usize)
-> Option<String> {
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') {
!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 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())));
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);
let result = format!(
"{} {} {{ {} }} else {{ {} }}",
self.keyword,
pat_expr_str,
if_str,
else_str
);
if result.len() <= width {
return Some(result);
@@ -935,26 +1003,29 @@ fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option<String> {
cond_shape = try_opt!(cond_shape.sub_width(2));
}
try_opt!(rewrite_pat_expr(context,
self.pat,
cond,
self.matcher,
self.connector,
self.keyword,
cond_shape))
try_opt!(rewrite_pat_expr(
context,
self.pat,
cond,
self.matcher,
self.connector,
self.keyword,
cond_shape,
))
}
None => String::new(),
};
let force_newline_brace = context.config.control_style() == Style::Rfc &&
pat_expr_string.contains('\n');
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() {
trial.as_ref().unwrap().len() <= context.config.single_line_if_else_max_width()
{
return trial;
}
}
@@ -1009,17 +1080,19 @@ fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option<String> {
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);
&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 {
force_newline_brace
{
alt_block_sep.as_str()
} else {
" "
};
let mut result = format!("{}{}{}{}{}{}",
let mut result =
format!("{}{}{}{}{}{}",
label_string,
self.keyword,
between_kwd_cond_comment
@@ -1044,24 +1117,26 @@ fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option<String> {
// 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)
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)
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;
@@ -1076,18 +1151,23 @@ fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option<String> {
};
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"));
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 = 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() {
@@ -1099,13 +1179,17 @@ fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option<String> {
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());
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));
}
@@ -1123,10 +1207,17 @@ fn rewrite_label(label: Option<ast::SpannedIdent>) -> String {
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)))
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
}
@@ -1142,7 +1233,7 @@ fn block_contains_comment(block: &ast::Block, codemap: &CodeMap) -> bool {
// 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))
!block_contains_comment(block, codemap))
}
/// Checks whether a block contains at most one statement or expression, and no comments.
@@ -1173,11 +1264,12 @@ fn is_unsafe_block(block: &ast::Block) -> bool {
// 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> {
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..],
@@ -1190,9 +1282,10 @@ fn rewrite_match_arm_comment(context: &RewriteContext,
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());
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
@@ -1209,12 +1302,13 @@ fn rewrite_match_arm_comment(context: &RewriteContext,
Some(result)
}
fn rewrite_match(context: &RewriteContext,
cond: &ast::Expr,
arms: &[ast::Arm],
shape: Shape,
span: Span)
-> Option<String> {
fn rewrite_match(
context: &RewriteContext,
cond: &ast::Expr,
arms: &[ast::Arm],
shape: Shape,
span: Span,
) -> Option<String> {
if arms.is_empty() {
return None;
}
@@ -1240,9 +1334,10 @@ fn rewrite_match(context: &RewriteContext,
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])), "{");
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.
@@ -1251,8 +1346,12 @@ fn rewrite_match(context: &RewriteContext,
} 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));
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);
@@ -1270,8 +1369,12 @@ fn rewrite_match(context: &RewriteContext,
// 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));
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));
@@ -1336,9 +1439,11 @@ fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option<String> {
// 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 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();
@@ -1362,17 +1467,19 @@ fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option<String> {
shape
};
let guard_str = try_opt!(rewrite_guard(context,
guard,
guard_shape,
trimmed_last_line_width(&pats_str)));
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() => {
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 {
@@ -1389,7 +1496,7 @@ fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option<String> {
let comma = arm_comma(&context.config, body);
let alt_block_sep = String::from("\n") +
&shape.indent.block_only().to_string(context.config);
&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.
@@ -1409,21 +1516,23 @@ fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option<String> {
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 => {
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));
return Some(format!(
"{}{} =>{}{}{}",
attr_str.trim_left(),
pats_str,
block_sep,
body_str,
comma
));
}
_ => {}
}
@@ -1433,12 +1542,13 @@ fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option<String> {
// 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 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() {
("{", "},")
@@ -1457,22 +1567,26 @@ fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option<String> {
};
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))
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))
Some(format!(
"{}{} =>{}{}{}{}",
attr_str.trim_left(),
pats_str,
block_sep,
indent_str,
next_line_body,
body_suffix
))
}
}
}
@@ -1481,17 +1595,18 @@ fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option<String> {
// 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 == ':'))
(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> {
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 = ` => {`
@@ -1526,16 +1641,17 @@ fn rewrite_guard(context: &RewriteContext,
}
}
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,
keyword: &str,
shape: Shape)
-> Option<String> {
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,
keyword: &str,
shape: Shape,
) -> Option<String> {
debug!("rewrite_pat_expr {:?} {:?} {:?}", shape, pat, expr);
let mut pat_string = String::new();
let mut result = match pat {
@@ -1545,8 +1661,9 @@ fn rewrite_pat_expr(context: &RewriteContext,
} else {
format!("{} ", matcher)
};
let pat_shape = try_opt!(try_opt!(shape.shrink_left(matcher.len()))
.sub_width(connector.len()));
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)
}
@@ -1596,7 +1713,8 @@ fn rewrite_string_lit(context: &RewriteContext, span: Span, shape: Shape) -> Opt
}
if !context.config.force_format_strings() &&
!string_requires_rewrite(context, span, &string_lit, shape) {
!string_requires_rewrite(context, span, &string_lit, shape)
{
return Some(string_lit);
}
@@ -1616,11 +1734,12 @@ fn rewrite_string_lit(context: &RewriteContext, span: Span, shape: Shape) -> Opt
rewrite_string(str_lit, &fmt)
}
fn string_requires_rewrite(context: &RewriteContext,
span: Span,
string: &str,
shape: Shape)
-> bool {
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;
}
@@ -1640,13 +1759,15 @@ fn string_requires_rewrite(context: &RewriteContext,
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
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
@@ -1655,9 +1776,9 @@ pub fn rewrite_call_with_binary_search<R>(context: &RewriteContext,
width: callee_max_width,
..shape
};
let callee_str = callee
.rewrite(context, callee_shape)
.ok_or(Ordering::Greater)?;
let callee_str = callee.rewrite(context, callee_shape).ok_or(
Ordering::Greater,
)?;
rewrite_call_inner(context, &callee_str, args, span, shape, false)
};
@@ -1665,22 +1786,24 @@ pub fn rewrite_call_with_binary_search<R>(context: &RewriteContext,
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> {
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> {
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
@@ -1693,11 +1816,12 @@ fn rewrite_call_inner(context: &RewriteContext,
.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 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 args_span = mk_sp(span_lo, span.hi);
@@ -1727,12 +1851,14 @@ fn rewrite_call_inner(context: &RewriteContext,
if !context.use_block_indent() && need_block_indent(&list_str, nested_shape) && !extendable {
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);
return rewrite_call_inner(
&new_context,
callee_str,
args,
span,
shape,
force_trailing_comma,
);
}
let args_shape = shape
@@ -1745,28 +1871,32 @@ fn rewrite_call_inner(context: &RewriteContext,
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())
})
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)> {
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 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
@@ -1789,15 +1919,18 @@ fn rewrite_call_args(context: &RewriteContext,
config: context.config,
};
write_list(&item_vec, &fmt).map(|args_str| (tactic != DefinitiveListTactic::Vertical, args_str))
write_list(&item_vec, &fmt).map(|args_str| {
(tactic != DefinitiveListTactic::Vertical, args_str)
})
}
fn try_overflow_last_arg(context: &RewriteContext,
item_vec: &mut Vec<ListItem>,
args: &[ptr::P<ast::Expr>],
shape: Shape,
one_line_width: usize)
-> DefinitiveListTactic {
fn try_overflow_last_arg(
context: &RewriteContext,
item_vec: &mut Vec<ListItem>,
args: &[ptr::P<ast::Expr>],
shape: Shape,
one_line_width: usize,
) -> DefinitiveListTactic {
let overflow_last = can_be_overflowed(&context, args);
// Replace the last item with its first line to see if it fits with
@@ -1809,19 +1942,22 @@ fn try_overflow_last_arg(context: &RewriteContext,
_ => (),
}
last_arg_shape(&context, &item_vec, shape).map_or((None, None), |arg_shape| {
rewrite_last_arg_with_overflow(&context,
&args[args.len() - 1],
&mut item_vec[args.len() - 1],
arg_shape)
rewrite_last_arg_with_overflow(
&context,
&args[args.len() - 1],
&mut item_vec[args.len() - 1],
arg_shape,
)
})
} else {
(None, None)
};
let tactic =
definitive_tactic(&*item_vec,
ListTactic::LimitedHorizontalVertical(context.config.fn_call_width()),
one_line_width);
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.
@@ -1849,17 +1985,18 @@ fn last_arg_shape(context: &RewriteContext, items: &Vec<ListItem>, shape: Shape)
shape.block().indent
};
Some(Shape {
width: try_opt!(max_width.checked_sub(overhead)),
indent: arg_indent,
offset: 0,
})
width: try_opt!(max_width.checked_sub(overhead)),
indent: arg_indent,
offset: 0,
})
}
fn rewrite_last_arg_with_overflow(context: &RewriteContext,
last_arg: &ptr::P<ast::Expr>,
last_item: &mut ListItem,
shape: Shape)
-> (Option<String>, Option<String>) {
fn rewrite_last_arg_with_overflow(
context: &RewriteContext,
last_arg: &ptr::P<ast::Expr>,
last_item: &mut ListItem,
shape: Shape,
) -> (Option<String>, Option<String>) {
let rewrite = last_arg.rewrite(context, shape);
let orig_last = last_item.item.clone();
@@ -1873,15 +2010,16 @@ fn rewrite_last_arg_with_overflow(context: &RewriteContext,
}
fn can_be_overflowed(context: &RewriteContext, args: &[ptr::P<ast::Expr>]) -> bool {
args.last()
.map_or(false, |x| can_be_overflowed_expr(context, &x, args.len()))
args.last().map_or(false, |x| {
can_be_overflowed_expr(context, &x, args.len())
})
}
fn can_be_overflowed_expr(context: &RewriteContext, expr: &ast::Expr, args_len: usize) -> bool {
match expr.node {
ast::ExprKind::Match(..) => {
(context.use_block_indent() && args_len == 1) ||
(context.config.fn_call_style() == IndentStyle::Visual && args_len > 1)
(context.config.fn_call_style() == IndentStyle::Visual && args_len > 1)
}
ast::ExprKind::If(..) |
ast::ExprKind::IfLet(..) |
@@ -1894,7 +2032,7 @@ fn can_be_overflowed_expr(context: &RewriteContext, expr: &ast::Expr, args_len:
ast::ExprKind::Block(..) |
ast::ExprKind::Closure(..) => {
context.use_block_indent() ||
context.config.fn_call_style() == IndentStyle::Visual && args_len > 1
context.config.fn_call_style() == IndentStyle::Visual && args_len > 1
}
ast::ExprKind::Call(..) |
ast::ExprKind::MethodCall(..) |
@@ -1933,10 +2071,12 @@ fn wrap_args_with_parens(context: &RewriteContext,
format!("({})", args_str)
}
} else {
format!("(\n{}{}\n{})",
nested_shape.indent.to_string(context.config),
args_str,
shape.block().indent.to_string(context.config))
format!(
"(\n{}{}\n{})",
nested_shape.indent.to_string(context.config),
args_str,
shape.block().indent.to_string(context.config)
)
}
}
@@ -1948,18 +2088,21 @@ fn rewrite_paren(context: &RewriteContext, subexpr: &ast::Expr, shape: Shape) ->
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)
})
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> {
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() {
@@ -1979,21 +2122,29 @@ fn rewrite_index(expr: &ast::Expr,
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 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))
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> {
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> {
@@ -2003,7 +2154,13 @@ enum StructLitField<'a> {
// 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));
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));
@@ -2042,14 +2199,16 @@ enum StructLitField<'a> {
}
};
let items = itemize_list(context.codemap,
field_iter,
"}",
span_lo,
span_hi,
rewrite,
context.codemap.span_after(span, "{"),
span.hi);
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);
@@ -2058,14 +2217,16 @@ enum StructLitField<'a> {
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))
(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)
@@ -2078,8 +2239,10 @@ enum StructLitField<'a> {
}
pub fn struct_lit_field_separator(config: &Config) -> &str {
colon_spaces(config.space_before_struct_lit_field_colon(),
config.space_after_struct_lit_field_colon())
colon_spaces(
config.space_before_struct_lit_field_colon(),
config.space_after_struct_lit_field_colon(),
)
}
fn rewrite_field(context: &RewriteContext, field: &ast::Field, shape: Shape) -> Option<String> {
@@ -2102,26 +2265,30 @@ fn rewrite_field(context: &RewriteContext, field: &ast::Field, shape: Shape) ->
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));
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)
})
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> {
fn shape_from_fn_call_style(
context: &RewriteContext,
shape: Shape,
overhead: usize,
offset: usize,
) -> Option<Shape> {
if context.use_block_indent() {
Some(shape.block().block_indent(context.config.tab_spaces()))
} else {
@@ -2129,41 +2296,45 @@ fn shape_from_fn_call_style(context: &RewriteContext,
}
}
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
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)
});
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 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 {
@@ -2173,11 +2344,12 @@ pub fn rewrite_tuple_type<'a, I>(context: &RewriteContext,
}
}
pub fn rewrite_tuple(context: &RewriteContext,
items: &[ptr::P<ast::Expr>],
span: Span,
shape: Shape)
-> Option<String> {
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 {
@@ -2186,20 +2358,22 @@ pub fn rewrite_tuple(context: &RewriteContext,
// 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()
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> {
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))
@@ -2207,24 +2381,26 @@ pub fn rewrite_unary_prefix<R: Rewrite>(context: &RewriteContext,
// 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> {
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
})
r.push_str(suffix);
r
})
}
fn rewrite_unary_op(context: &RewriteContext,
op: &ast::UnOp,
expr: &ast::Expr,
shape: Shape)
-> Option<String> {
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 => "*",
@@ -2234,12 +2410,13 @@ fn rewrite_unary_op(context: &RewriteContext,
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> {
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(),
@@ -2247,27 +2424,30 @@ fn rewrite_assignment(context: &RewriteContext,
// 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);
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> {
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
};
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 {
@@ -2300,10 +2480,21 @@ fn count_line_breaks(src: &str) -> usize {
// 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()) => {
(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);
}
@@ -2323,11 +2514,12 @@ fn count_line_breaks(src: &str) -> usize {
Some(result)
}
fn rewrite_expr_addrof(context: &RewriteContext,
mutability: ast::Mutability,
expr: &ast::Expr,
shape: Shape)
-> Option<String> {
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 ",
+34 -17
View File
@@ -52,7 +52,7 @@ fn intersects(self, other: Range) -> bool {
false
} else {
(self.lo <= other.hi && other.hi <= self.hi) ||
(other.lo <= self.hi && self.hi <= other.hi)
(other.lo <= self.hi && self.hi <= other.hi)
}
}
@@ -68,7 +68,10 @@ fn adjacent_to(self, other: Range) -> bool {
/// intersect; returns `None` otherwise.
fn merge(self, other: Range) -> Option<Range> {
if self.adjacent_to(other) || self.intersects(other) {
Some(Range::new(cmp::min(self.lo, other.lo), cmp::max(self.hi, other.hi)))
Some(Range::new(
cmp::min(self.lo, other.lo),
cmp::max(self.hi, other.hi),
))
} else {
None
}
@@ -127,7 +130,8 @@ pub fn files(&self) -> Files {
/// Returns true if `self` includes all lines in all files. Otherwise runs `f` on all ranges in
/// the designated file (if any) and returns true if `f` ever does.
fn file_range_matches<F>(&self, file_name: &str, f: F) -> bool
where F: FnMut(&Range) -> bool
where
F: FnMut(&Range) -> bool,
{
let map = match self.0 {
// `None` means "all lines in all files".
@@ -209,8 +213,9 @@ struct JsonSpan {
impl JsonSpan {
fn into_tuple(self) -> Result<(String, Range), String> {
let (lo, hi) = self.range;
let canonical = canonicalize_path_string(&self.file)
.ok_or_else(|| format!("Can't canonicalize {}", &self.file))?;
let canonical = canonicalize_path_string(&self.file).ok_or_else(|| {
format!("Can't canonicalize {}", &self.file)
})?;
Ok((canonical, Range::new(lo, hi)))
}
}
@@ -219,10 +224,13 @@ fn into_tuple(self) -> Result<(String, Range), String> {
// for `FileLines`, so it will just panic instead.
impl<'de> ::serde::de::Deserialize<'de> for FileLines {
fn deserialize<D>(_: D) -> Result<Self, D::Error>
where D: ::serde::de::Deserializer<'de>
where
D: ::serde::de::Deserializer<'de>,
{
panic!("FileLines cannot be deserialized from a project rustfmt.toml file: please \
specify it via the `--file-lines` option instead");
panic!(
"FileLines cannot be deserialized from a project rustfmt.toml file: please \
specify it via the `--file-lines` option instead"
);
}
}
@@ -230,7 +238,8 @@ fn deserialize<D>(_: D) -> Result<Self, D::Error>
// `Config` struct should ensure this impl is never reached.
impl ::serde::ser::Serialize for FileLines {
fn serialize<S>(&self, _: S) -> Result<S::Ok, S::Error>
where S: ::serde::ser::Serializer
where
S: ::serde::ser::Serializer,
{
unreachable!("FileLines cannot be serialized. This is a rustfmt bug.");
}
@@ -270,13 +279,21 @@ fn test_range_contains() {
fn test_range_merge() {
assert_eq!(None, Range::new(1, 3).merge(Range::new(5, 5)));
assert_eq!(None, Range::new(4, 7).merge(Range::new(0, 1)));
assert_eq!(Some(Range::new(3, 7)),
Range::new(3, 5).merge(Range::new(4, 7)));
assert_eq!(Some(Range::new(3, 7)),
Range::new(3, 5).merge(Range::new(5, 7)));
assert_eq!(Some(Range::new(3, 7)),
Range::new(3, 5).merge(Range::new(6, 7)));
assert_eq!(Some(Range::new(3, 7)),
Range::new(3, 7).merge(Range::new(4, 5)));
assert_eq!(
Some(Range::new(3, 7)),
Range::new(3, 5).merge(Range::new(4, 7))
);
assert_eq!(
Some(Range::new(3, 7)),
Range::new(3, 5).merge(Range::new(5, 7))
);
assert_eq!(
Some(Range::new(3, 7)),
Range::new(3, 5).merge(Range::new(6, 7))
);
assert_eq!(
Some(Range::new(3, 7)),
Range::new(3, 7).merge(Range::new(4, 5))
);
}
}
+27 -20
View File
@@ -31,7 +31,8 @@ pub fn append_newline(s: &mut StringBuffer) {
}
pub fn write_all_files<T>(file_map: &FileMap, out: &mut T, config: &Config) -> Result<(), io::Error>
where T: Write
where
T: Write,
{
output_header(out, config.write_mode()).ok();
for &(ref filename, ref text) in file_map {
@@ -43,11 +44,13 @@ pub fn write_all_files<T>(file_map: &FileMap, out: &mut T, config: &Config) -> R
}
// Prints all newlines either as `\n` or as `\r\n`.
pub fn write_system_newlines<T>(writer: T,
text: &StringBuffer,
config: &Config)
-> Result<(), io::Error>
where T: Write
pub fn write_system_newlines<T>(
writer: T,
text: &StringBuffer,
config: &Config,
) -> Result<(), io::Error>
where
T: Write,
{
// Buffer output, since we're writing a since char at a time.
let mut writer = BufWriter::new(writer);
@@ -78,18 +81,21 @@ pub fn write_system_newlines<T>(writer: T,
}
}
pub fn write_file<T>(text: &StringBuffer,
filename: &str,
out: &mut T,
config: &Config)
-> Result<bool, io::Error>
where T: Write
pub fn write_file<T>(
text: &StringBuffer,
filename: &str,
out: &mut T,
config: &Config,
) -> Result<bool, io::Error>
where
T: Write,
{
fn source_and_formatted_text(text: &StringBuffer,
filename: &str,
config: &Config)
-> Result<(String, String), io::Error> {
fn source_and_formatted_text(
text: &StringBuffer,
filename: &str,
config: &Config,
) -> Result<(String, String), io::Error> {
let mut f = File::open(filename)?;
let mut ori_text = String::new();
f.read_to_string(&mut ori_text)?;
@@ -99,10 +105,11 @@ fn source_and_formatted_text(text: &StringBuffer,
Ok((ori_text, fmt_text))
}
fn create_diff(filename: &str,
text: &StringBuffer,
config: &Config)
-> Result<Vec<Mismatch>, io::Error> {
fn create_diff(
filename: &str,
text: &StringBuffer,
config: &Config,
) -> Result<Vec<Mismatch>, io::Error> {
let (ori, fmt) = source_and_formatted_text(text, filename, config)?;
Ok(make_diff(&ori, &fmt, 3))
}
+90 -56
View File
@@ -73,9 +73,10 @@ fn compare_path_list_items(a: &ast::PathListItem, b: &ast::PathListItem) -> Orde
}
}
fn compare_path_list_item_lists(a_items: &Vec<ast::PathListItem>,
b_items: &Vec<ast::PathListItem>)
-> Ordering {
fn compare_path_list_item_lists(
a_items: &Vec<ast::PathListItem>,
b_items: &Vec<ast::PathListItem>,
) -> Ordering {
let mut a = a_items.clone();
let mut b = b_items.clone();
a.sort_by(|a, b| compare_path_list_items(a, b));
@@ -123,19 +124,33 @@ fn compare_use_items(a: &ast::Item, b: &ast::Item) -> Option<Ordering> {
// TODO (some day) remove unused imports, expand globs, compress many single
// imports into a list import.
fn rewrite_view_path_prefix(path: &ast::Path,
context: &RewriteContext,
shape: Shape)
-> Option<String> {
fn rewrite_view_path_prefix(
path: &ast::Path,
context: &RewriteContext,
shape: Shape,
) -> Option<String> {
let path_str = if path.segments.last().unwrap().identifier.to_string() == "self" &&
path.segments.len() > 1 {
path.segments.len() > 1
{
let path = &ast::Path {
span: path.span.clone(),
segments: path.segments[..path.segments.len() - 1].to_owned(),
};
try_opt!(rewrite_path(context, PathContext::Import, None, path, shape))
try_opt!(rewrite_path(
context,
PathContext::Import,
None,
path,
shape,
))
} else {
try_opt!(rewrite_path(context, PathContext::Import, None, path, shape))
try_opt!(rewrite_path(
context,
PathContext::Import,
None,
path,
shape,
))
};
Some(path_str)
}
@@ -162,11 +177,13 @@ fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option<String> {
let prefix_shape = try_opt!(shape.sub_width(ident_str.len() + 4));
let path_str = try_opt!(rewrite_view_path_prefix(path, context, prefix_shape));
Some(if path.segments.last().unwrap().identifier == ident {
path_str
} else {
format!("{} as {}", path_str, ident_str)
})
Some(
if path.segments.last().unwrap().identifier == ident {
path_str
} else {
format!("{} as {}", path_str, ident_str)
},
)
}
}
}
@@ -179,13 +196,13 @@ pub fn format_imports(&mut self, use_items: &[ptr::P<ast::Item>]) {
let pos_before_first_use_item = use_items
.first()
.map(|p_i| {
cmp::max(self.last_pos,
p_i.attrs
.iter()
.map(|attr| attr.span.lo)
.min()
.unwrap_or(p_i.span.lo))
})
cmp::max(
self.last_pos,
p_i.attrs.iter().map(|attr| attr.span.lo).min().unwrap_or(
p_i.span.lo,
),
)
})
.unwrap_or(self.last_pos);
// Construct a list of pairs, each containing a `use` item and the start of span before
// that `use` item.
@@ -193,10 +210,10 @@ pub fn format_imports(&mut self, use_items: &[ptr::P<ast::Item>]) {
let mut ordered_use_items = use_items
.iter()
.map(|p_i| {
let new_item = (&*p_i, last_pos_of_prev_use_item);
last_pos_of_prev_use_item = p_i.span.hi;
new_item
})
let new_item = (&*p_i, last_pos_of_prev_use_item);
last_pos_of_prev_use_item = p_i.span.hi;
new_item
})
.collect::<Vec<_>>();
let pos_after_last_use_item = last_pos_of_prev_use_item;
// Order the imports by view-path & other import path properties
@@ -237,8 +254,10 @@ pub fn format_import(&mut self, vis: &ast::Visibility, vp: &ast::ViewPath, span:
let mut offset = self.block_indent;
offset.alignment += vis.len() + "use ".len();
// 1 = ";"
match vp.rewrite(&self.get_context(),
Shape::legacy(self.config.max_width() - offset.width() - 1, offset)) {
match vp.rewrite(
&self.get_context(),
Shape::legacy(self.config.max_width() - offset.width() - 1, offset),
) {
Some(ref s) if s.is_empty() => {
// Format up to last newline
let prev_span = utils::mk_sp(self.last_pos, source!(self, span).lo);
@@ -295,14 +314,21 @@ fn append_alias(path_item_str: String, vpi: &ast::PathListItem) -> String {
// Pretty prints a multi-item import.
// Assumes that path_list.len() > 0.
pub fn rewrite_use_list(shape: Shape,
path: &ast::Path,
path_list: &[ast::PathListItem],
span: Span,
context: &RewriteContext)
-> Option<String> {
pub fn rewrite_use_list(
shape: Shape,
path: &ast::Path,
path_list: &[ast::PathListItem],
span: Span,
context: &RewriteContext,
) -> Option<String> {
// Returns a different option to distinguish `::foo` and `foo`
let path_str = try_opt!(rewrite_path(context, PathContext::Import, None, path, shape));
let path_str = try_opt!(rewrite_path(
context,
PathContext::Import,
None,
path,
shape,
));
match path_list.len() {
0 => unreachable!(),
@@ -321,14 +347,16 @@ pub fn rewrite_use_list(shape: Shape,
let mut items = {
// Dummy value, see explanation below.
let mut items = vec![ListItem::from_str("")];
let iter = itemize_list(context.codemap,
path_list.iter(),
"}",
|vpi| vpi.span.lo,
|vpi| vpi.span.hi,
rewrite_path_item,
context.codemap.span_after(span, "{"),
span.hi);
let iter = itemize_list(
context.codemap,
path_list.iter(),
"}",
|vpi| vpi.span.lo,
|vpi| vpi.span.hi,
rewrite_path_item,
context.codemap.span_after(span, "{"),
span.hi,
);
items.extend(iter);
items
};
@@ -344,34 +372,40 @@ pub fn rewrite_use_list(shape: Shape,
}
let tactic = definitive_tactic(&items[first_index..],
::lists::ListTactic::Mixed,
remaining_width);
let tactic = definitive_tactic(
&items[first_index..],
::lists::ListTactic::Mixed,
remaining_width,
);
let fmt = ListFormatting {
tactic: tactic,
separator: ",",
trailing_separator: SeparatorTactic::Never,
// Add one to the indent to account for "{"
shape: Shape::legacy(remaining_width,
shape.indent + path_str.len() + colons_offset + 1),
shape: Shape::legacy(
remaining_width,
shape.indent + path_str.len() + colons_offset + 1,
),
ends_with_newline: false,
config: context.config,
};
let list_str = try_opt!(write_list(&items[first_index..], &fmt));
Some(if path_str.is_empty() {
format!("{{{}}}", list_str)
} else {
format!("{}::{{{}}}", path_str, list_str)
})
Some(
if path_str.is_empty() {
format!("{{{}}}", list_str)
} else {
format!("{}::{{{}}}", path_str, list_str)
},
)
}
// Returns true when self item was found.
fn move_self_to_front(items: &mut Vec<ListItem>) -> bool {
match items
.iter()
.position(|item| item.item.as_ref().map(|x| &x[..]) == Some("self")) {
match items.iter().position(|item| {
item.item.as_ref().map(|x| &x[..]) == Some("self")
}) {
Some(pos) => {
items[0] = items.remove(pos);
true
+52 -35
View File
@@ -172,11 +172,12 @@ fn inspect_issue(&mut self, c: char, mut todo_idx: usize, mut fixme_idx: usize)
}
}
fn inspect_number(&mut self,
c: char,
issue: Issue,
mut part: NumberPart)
-> IssueClassification {
fn inspect_number(
&mut self,
c: char,
issue: Issue,
mut part: NumberPart,
) -> IssueClassification {
if !issue.missing_number || c == '\n' {
return IssueClassification::Bad(issue);
} else if c == ')' {
@@ -223,8 +224,10 @@ fn inspect_number(&mut self,
fn find_unnumbered_issue() {
fn check_fail(text: &str, failing_pos: usize) {
let mut seeker = BadIssueSeeker::new(ReportTactic::Unnumbered, ReportTactic::Unnumbered);
assert_eq!(Some(failing_pos),
text.chars().position(|c| seeker.inspect(c).is_some()));
assert_eq!(
Some(failing_pos),
text.chars().position(|c| seeker.inspect(c).is_some())
);
}
fn check_pass(text: &str) {
@@ -252,46 +255,60 @@ fn is_bad_issue(text: &str, report_todo: ReportTactic, report_fixme: ReportTacti
text.chars().any(|c| seeker.inspect(c).is_some())
}
assert!(is_bad_issue("TODO(@maintainer, #1222, hello)\n",
ReportTactic::Always,
ReportTactic::Never));
assert!(is_bad_issue(
"TODO(@maintainer, #1222, hello)\n",
ReportTactic::Always,
ReportTactic::Never,
));
assert!(!is_bad_issue("TODO: no number\n",
ReportTactic::Never,
ReportTactic::Always));
assert!(!is_bad_issue(
"TODO: no number\n",
ReportTactic::Never,
ReportTactic::Always,
));
assert!(is_bad_issue("This is a FIXME(#1)\n",
ReportTactic::Never,
ReportTactic::Always));
assert!(is_bad_issue(
"This is a FIXME(#1)\n",
ReportTactic::Never,
ReportTactic::Always,
));
assert!(!is_bad_issue("bad FIXME\n", ReportTactic::Always, ReportTactic::Never));
assert!(!is_bad_issue(
"bad FIXME\n",
ReportTactic::Always,
ReportTactic::Never,
));
}
#[test]
fn issue_type() {
let mut seeker = BadIssueSeeker::new(ReportTactic::Always, ReportTactic::Never);
let expected = Some(Issue {
issue_type: IssueType::Todo,
missing_number: false,
});
issue_type: IssueType::Todo,
missing_number: false,
});
assert_eq!(expected,
"TODO(#100): more awesomeness"
.chars()
.map(|c| seeker.inspect(c))
.find(Option::is_some)
.unwrap());
assert_eq!(
expected,
"TODO(#100): more awesomeness"
.chars()
.map(|c| seeker.inspect(c))
.find(Option::is_some)
.unwrap()
);
let mut seeker = BadIssueSeeker::new(ReportTactic::Never, ReportTactic::Unnumbered);
let expected = Some(Issue {
issue_type: IssueType::Fixme,
missing_number: true,
});
issue_type: IssueType::Fixme,
missing_number: true,
});
assert_eq!(expected,
"Test. FIXME: bad, bad, not good"
.chars()
.map(|c| seeker.inspect(c))
.find(Option::is_some)
.unwrap());
assert_eq!(
expected,
"Test. FIXME: bad, bad, not good"
.chars()
.map(|c| seeker.inspect(c))
.find(Option::is_some)
.unwrap()
);
}
+848 -689
View File
@@ -29,8 +29,10 @@
use syntax::ast::ImplItem;
fn type_annotation_separator(config: &Config) -> &str {
colon_spaces(config.space_before_type_annotation(),
config.space_after_type_annotation_colon())
colon_spaces(
config.space_before_type_annotation(),
config.space_after_type_annotation_colon(),
)
}
@@ -38,10 +40,12 @@ fn type_annotation_separator(config: &Config) -> &str {
// let pat: ty = init;
impl Rewrite for ast::Local {
fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option<String> {
debug!("Local::rewrite {:?} {} {:?}",
self,
shape.width,
shape.indent);
debug!(
"Local::rewrite {:?} {} {:?}",
self,
shape.width,
shape.indent
);
let mut result = "let ".to_owned();
// 4 = "let ".len()
@@ -145,8 +149,9 @@ fn format_item(&mut self, item: Item) {
self.format_missing_no_indent(item.span.hi - BytePos(1));
self.block_indent = self.block_indent.block_unindent(self.config);
self.buffer
.push_str(&self.block_indent.to_string(self.config));
self.buffer.push_str(
&self.block_indent.to_string(self.config),
);
} else {
for item in &item.body {
self.format_body_element(item);
@@ -181,22 +186,24 @@ fn format_foreign_item(&mut self, item: &ast::ForeignItem) {
match item.node {
ast::ForeignItemKind::Fn(ref fn_decl, ref generics) => {
let indent = self.block_indent;
let rewrite = rewrite_fn_base(&self.get_context(),
indent,
item.ident,
fn_decl,
generics,
ast::Unsafety::Normal,
ast::Constness::NotConst,
ast::Defaultness::Final,
// These are not actually rust functions,
// but we format them as such.
abi::Abi::Rust,
&item.vis,
span,
false,
false,
false);
let rewrite = rewrite_fn_base(
&self.get_context(),
indent,
item.ident,
fn_decl,
generics,
ast::Unsafety::Normal,
ast::Constness::NotConst,
ast::Defaultness::Final,
// These are not actually rust functions,
// but we format them as such.
abi::Abi::Rust,
&item.vis,
span,
false,
false,
false,
);
match rewrite {
Some((new_fn, _)) => {
@@ -231,45 +238,49 @@ fn format_foreign_item(&mut self, item: &ast::ForeignItem) {
self.last_pos = item.span.hi;
}
pub fn rewrite_fn(&mut self,
indent: Indent,
ident: ast::Ident,
fd: &ast::FnDecl,
generics: &ast::Generics,
unsafety: ast::Unsafety,
constness: ast::Constness,
defaultness: ast::Defaultness,
abi: abi::Abi,
vis: &ast::Visibility,
span: Span,
block: &ast::Block)
-> Option<String> {
pub fn rewrite_fn(
&mut self,
indent: Indent,
ident: ast::Ident,
fd: &ast::FnDecl,
generics: &ast::Generics,
unsafety: ast::Unsafety,
constness: ast::Constness,
defaultness: ast::Defaultness,
abi: abi::Abi,
vis: &ast::Visibility,
span: Span,
block: &ast::Block,
) -> Option<String> {
let mut newline_brace = newline_for_brace(self.config, &generics.where_clause);
let context = self.get_context();
let block_snippet = self.snippet(mk_sp(block.span.lo, block.span.hi));
let has_body = !block_snippet[1..block_snippet.len() - 1].trim().is_empty() ||
!context.config.fn_empty_single_line();
!context.config.fn_empty_single_line();
let (mut result, force_newline_brace) = try_opt!(rewrite_fn_base(&context,
indent,
ident,
fd,
generics,
unsafety,
constness,
defaultness,
abi,
vis,
span,
newline_brace,
has_body,
true));
let (mut result, force_newline_brace) = try_opt!(rewrite_fn_base(
&context,
indent,
ident,
fd,
generics,
unsafety,
constness,
defaultness,
abi,
vis,
span,
newline_brace,
has_body,
true,
));
if force_newline_brace {
newline_brace = true;
} else if self.config.fn_brace_style() != BraceStyle::AlwaysNextLine &&
!result.contains('\n') {
!result.contains('\n')
{
newline_brace = false;
}
@@ -288,30 +299,33 @@ pub fn rewrite_fn(&mut self,
self.single_line_fn(&result, block).or_else(|| Some(result))
}
pub fn rewrite_required_fn(&mut self,
indent: Indent,
ident: ast::Ident,
sig: &ast::MethodSig,
span: Span)
-> Option<String> {
pub fn rewrite_required_fn(
&mut self,
indent: Indent,
ident: ast::Ident,
sig: &ast::MethodSig,
span: Span,
) -> Option<String> {
// Drop semicolon or it will be interpreted as comment.
let span = mk_sp(span.lo, span.hi - BytePos(1));
let context = self.get_context();
let (mut result, _) = try_opt!(rewrite_fn_base(&context,
indent,
ident,
&sig.decl,
&sig.generics,
sig.unsafety,
sig.constness.node,
ast::Defaultness::Final,
sig.abi,
&ast::Visibility::Inherited,
span,
false,
false,
false));
let (mut result, _) = try_opt!(rewrite_fn_base(
&context,
indent,
ident,
&sig.decl,
&sig.generics,
sig.unsafety,
sig.constness.node,
ast::Defaultness::Final,
sig.abi,
&ast::Visibility::Inherited,
span,
false,
false,
false,
));
// Re-attach semicolon
result.push(';');
@@ -327,7 +341,8 @@ fn single_line_fn(&self, fn_str: &str, block: &ast::Block) -> Option<String> {
let codemap = self.get_context().codemap;
if self.config.fn_empty_single_line() && is_empty_block(block, codemap) &&
self.block_indent.width() + fn_str.len() + 2 <= self.config.max_width() {
self.block_indent.width() + fn_str.len() + 2 <= self.config.max_width()
{
return Some(format!("{}{{}}", fn_str));
}
@@ -338,14 +353,17 @@ fn single_line_fn(&self, fn_str: &str, block: &ast::Block) -> Option<String> {
Some(e) => {
let suffix = if semicolon_for_expr(e) { ";" } else { "" };
e.rewrite(&self.get_context(),
Shape::indented(self.block_indent, self.config))
.map(|s| s + suffix)
e.rewrite(
&self.get_context(),
Shape::indented(self.block_indent, self.config),
).map(|s| s + suffix)
.or_else(|| Some(self.snippet(e.span)))
}
None => {
stmt.rewrite(&self.get_context(),
Shape::indented(self.block_indent, self.config))
stmt.rewrite(
&self.get_context(),
Shape::indented(self.block_indent, self.config),
)
}
}
} else {
@@ -364,26 +382,29 @@ fn single_line_fn(&self, fn_str: &str, block: &ast::Block) -> Option<String> {
None
}
pub fn visit_enum(&mut self,
ident: ast::Ident,
vis: &ast::Visibility,
enum_def: &ast::EnumDef,
generics: &ast::Generics,
span: Span) {
pub fn visit_enum(
&mut self,
ident: ast::Ident,
vis: &ast::Visibility,
enum_def: &ast::EnumDef,
generics: &ast::Generics,
span: Span,
) {
self.buffer.push_str(&format_header("enum ", ident, vis));
let enum_snippet = self.snippet(span);
let brace_pos = enum_snippet.find_uncommented("{").unwrap();
let body_start = span.lo + BytePos(brace_pos as u32 + 1);
let generics_str = format_generics(&self.get_context(),
generics,
"{",
"{",
self.config.item_brace_style(),
enum_def.variants.is_empty(),
self.block_indent,
mk_sp(span.lo, body_start))
.unwrap();
let generics_str = format_generics(
&self.get_context(),
generics,
"{",
"{",
self.config.item_brace_style(),
enum_def.variants.is_empty(),
self.block_indent,
mk_sp(span.lo, body_start),
).unwrap();
self.buffer.push_str(&generics_str);
self.last_pos = body_start;
@@ -403,19 +424,21 @@ pub fn visit_enum(&mut self,
self.block_indent = self.block_indent.block_unindent(self.config);
if variant_list.is_some() || contains_comment(&enum_snippet[brace_pos..]) {
self.buffer
.push_str(&self.block_indent.to_string(self.config));
self.buffer.push_str(
&self.block_indent.to_string(self.config),
);
}
self.buffer.push_str("}");
self.last_pos = span.hi;
}
// Format the body of an enum definition
fn format_variant_list(&self,
enum_def: &ast::EnumDef,
body_lo: BytePos,
body_hi: BytePos)
-> Option<String> {
fn format_variant_list(
&self,
enum_def: &ast::EnumDef,
body_lo: BytePos,
body_hi: BytePos,
) -> Option<String> {
if enum_def.variants.is_empty() {
return None;
}
@@ -424,18 +447,20 @@ fn format_variant_list(&self,
let indentation = self.block_indent.to_string(self.config);
result.push_str(&indentation);
let items = itemize_list(self.codemap,
enum_def.variants.iter(),
"}",
|f| if !f.node.attrs.is_empty() {
f.node.attrs[0].span.lo
} else {
f.span.lo
},
|f| f.span.hi,
|f| self.format_variant(f),
body_lo,
body_hi);
let items = itemize_list(
self.codemap,
enum_def.variants.iter(),
"}",
|f| if !f.node.attrs.is_empty() {
f.node.attrs[0].span.lo
} else {
f.span.lo
},
|f| f.span.hi,
|f| self.format_variant(f),
body_lo,
body_hi,
);
let shape = Shape::indented(self.block_indent, self.config)
.sub_width(2)
@@ -465,25 +490,23 @@ fn format_variant(&self, field: &ast::Variant) -> Option<String> {
let context = self.get_context();
let indent = self.block_indent;
let mut result = try_opt!(field
.node
.attrs
.rewrite(&context, Shape::indented(indent, self.config)));
let mut result = try_opt!(field.node.attrs.rewrite(
&context,
Shape::indented(indent, self.config),
));
if !result.is_empty() {
let shape = Shape {
width: context.config.max_width(),
indent: self.block_indent,
offset: self.block_indent.alignment,
};
let missing_comment =
rewrite_missing_comment_on_field(&context,
shape,
field.node.attrs[field.node.attrs.len() - 1]
.span
.hi,
field.span.lo,
&mut result)
.unwrap_or(String::new());
let missing_comment = rewrite_missing_comment_on_field(
&context,
shape,
field.node.attrs[field.node.attrs.len() - 1].span.hi,
field.span.lo,
&mut result,
).unwrap_or(String::new());
result.push_str(&missing_comment);
}
@@ -491,15 +514,17 @@ fn format_variant(&self, field: &ast::Variant) -> Option<String> {
ast::VariantData::Tuple(..) |
ast::VariantData::Struct(..) => {
// FIXME: Should limit the width, as we have a trailing comma
format_struct(&context,
"",
field.node.name,
&ast::Visibility::Inherited,
&field.node.data,
None,
field.span,
indent,
Some(self.config.struct_variant_width()))
format_struct(
&context,
"",
field.node.name,
&ast::Visibility::Inherited,
&field.node.data,
None,
field.span,
indent,
Some(self.config.struct_variant_width()),
)
}
ast::VariantData::Unit(..) => {
let tag = if let Some(ref expr) = field.node.disr_expr {
@@ -508,9 +533,11 @@ fn format_variant(&self, field: &ast::Variant) -> Option<String> {
field.node.name.to_string()
};
wrap_str(tag,
self.config.max_width(),
Shape::indented(indent, self.config))
wrap_str(
tag,
self.config.max_width(),
Shape::indented(indent, self.config),
)
}
};
@@ -626,18 +653,21 @@ pub fn format_impl(context: &RewriteContext,
}
}
fn is_impl_single_line(context: &RewriteContext,
items: &[ImplItem],
result: &str,
where_clause_str: &str,
item: &ast::Item)
-> Option<bool> {
fn is_impl_single_line(
context: &RewriteContext,
items: &[ImplItem],
result: &str,
where_clause_str: &str,
item: &ast::Item,
) -> Option<bool> {
let snippet = context.snippet(item.span);
let open_pos = try_opt!(snippet.find_uncommented("{")) + 1;
Some(context.config.impl_empty_single_line() && items.is_empty() &&
result.len() + where_clause_str.len() <= context.config.max_width() &&
!contains_comment(&snippet[open_pos..]))
Some(
context.config.impl_empty_single_line() && items.is_empty() &&
result.len() + where_clause_str.len() <= context.config.max_width() &&
!contains_comment(&snippet[open_pos..]),
)
}
fn format_impl_ref_and_type(context: &RewriteContext,
@@ -645,12 +675,13 @@ fn format_impl_ref_and_type(context: &RewriteContext,
offset: Indent)
-> Option<String> {
if let ast::ItemKind::Impl(unsafety,
polarity,
_,
ref generics,
ref trait_ref,
ref self_ty,
_) = item.node {
polarity,
_,
ref generics,
ref trait_ref,
ref self_ty,
_) = item.node
{
let mut result = String::new();
result.push_str(&format_visibility(&item.vis));
@@ -802,37 +833,44 @@ pub fn format_struct(context: &RewriteContext,
match *struct_def {
ast::VariantData::Unit(..) => Some(format_unit_struct(item_name, ident, vis)),
ast::VariantData::Tuple(ref fields, _) => {
format_tuple_struct(context,
item_name,
ident,
vis,
fields,
generics,
span,
offset)
format_tuple_struct(
context,
item_name,
ident,
vis,
fields,
generics,
span,
offset,
)
}
ast::VariantData::Struct(ref fields, _) => {
format_struct_struct(context,
item_name,
ident,
vis,
fields,
generics,
span,
offset,
one_line_width)
format_struct_struct(
context,
item_name,
ident,
vis,
fields,
generics,
span,
offset,
one_line_width,
)
}
}
}
pub fn format_trait(context: &RewriteContext, item: &ast::Item, offset: Indent) -> Option<String> {
if let ast::ItemKind::Trait(unsafety, ref generics, ref type_param_bounds, ref trait_items) =
item.node {
item.node
{
let mut result = String::new();
let header = format!("{}{}trait {}",
format_visibility(&item.vis),
format_unsafety(unsafety),
item.ident);
let header = format!(
"{}{}trait {}",
format_visibility(&item.vis),
format_unsafety(unsafety),
item.ident
);
result.push_str(&header);
@@ -843,14 +881,16 @@ pub fn format_trait(context: &RewriteContext, item: &ast::Item, offset: Indent)
try_opt!(rewrite_generics(context, generics, shape, mk_sp(item.span.lo, body_lo)));
result.push_str(&generics_str);
let trait_bound_str =
try_opt!(rewrite_trait_bounds(context,
type_param_bounds,
Shape::legacy(context.config.max_width(), offset)));
let trait_bound_str = try_opt!(rewrite_trait_bounds(
context,
type_param_bounds,
Shape::legacy(context.config.max_width(), offset),
));
// If the trait, generics, and trait bound cannot fit on the same line,
// put the trait bounds on an indented new line
if offset.width() + last_line_width(&result) + trait_bound_str.len() >
context.config.comment_width() {
context.config.comment_width()
{
result.push('\n');
let trait_indent = offset.block_only().block_indent(context.config);
result.push_str(&trait_indent.to_string(context.config));
@@ -859,38 +899,39 @@ pub fn format_trait(context: &RewriteContext, item: &ast::Item, offset: Indent)
let has_body = !trait_items.is_empty();
let where_density =
if (context.config.where_density() == Density::Compressed &&
(!result.contains('\n') ||
context.config.fn_args_layout() == IndentStyle::Block)) ||
(context.config.fn_args_layout() == IndentStyle::Block && result.is_empty()) ||
(context.config.where_density() == Density::CompressedIfEmpty && !has_body &&
!result.contains('\n')) {
Density::Compressed
} else {
Density::Tall
};
let where_density = if (context.config.where_density() == Density::Compressed &&
(!result.contains('\n') ||
context.config.fn_args_layout() == IndentStyle::Block)) ||
(context.config.fn_args_layout() == IndentStyle::Block && result.is_empty()) ||
(context.config.where_density() == Density::CompressedIfEmpty && !has_body &&
!result.contains('\n'))
{
Density::Compressed
} else {
Density::Tall
};
let where_budget = try_opt!(context
.config
.max_width()
.checked_sub(last_line_width(&result)));
let where_clause_str = try_opt!(rewrite_where_clause(context,
&generics.where_clause,
context.config.item_brace_style(),
Shape::legacy(where_budget,
offset.block_only()),
where_density,
"{",
!has_body,
trait_bound_str.is_empty() &&
last_line_width(&generics_str) == 1,
None));
let where_budget = try_opt!(context.config.max_width().checked_sub(
last_line_width(&result),
));
let where_clause_str = try_opt!(rewrite_where_clause(
context,
&generics.where_clause,
context.config.item_brace_style(),
Shape::legacy(where_budget, offset.block_only()),
where_density,
"{",
!has_body,
trait_bound_str.is_empty() &&
last_line_width(&generics_str) == 1,
None,
));
// If the where clause cannot fit on the same line,
// put the where clause on a new line
if !where_clause_str.contains('\n') &&
last_line_width(&result) + where_clause_str.len() + offset.width() >
context.config.comment_width() {
last_line_width(&result) + where_clause_str.len() + offset.width() >
context.config.comment_width()
{
result.push('\n');
let width = offset.block_indent + context.config.tab_spaces() - 1;
let where_indent = Indent::new(0, width);
@@ -906,7 +947,8 @@ pub fn format_trait(context: &RewriteContext, item: &ast::Item, offset: Indent)
BraceStyle::PreferSameLine => result.push(' '),
BraceStyle::SameLineWhere => {
if !where_clause_str.is_empty() &&
(!trait_items.is_empty() || result.contains('\n')) {
(!trait_items.is_empty() || result.contains('\n'))
{
result.push('\n');
result.push_str(&offset.to_string(context.config));
} else {
@@ -953,16 +995,17 @@ fn format_unit_struct(item_name: &str, ident: ast::Ident, vis: &ast::Visibility)
format!("{};", format_header(item_name, ident, vis))
}
fn format_struct_struct(context: &RewriteContext,
item_name: &str,
ident: ast::Ident,
vis: &ast::Visibility,
fields: &[ast::StructField],
generics: Option<&ast::Generics>,
span: Span,
offset: Indent,
one_line_width: Option<usize>)
-> Option<String> {
fn format_struct_struct(
context: &RewriteContext,
item_name: &str,
ident: ast::Ident,
vis: &ast::Visibility,
fields: &[ast::StructField],
generics: Option<&ast::Generics>,
span: Span,
offset: Indent,
one_line_width: Option<usize>,
) -> Option<String> {
let mut result = String::with_capacity(1024);
let header_str = format_header(item_name, ident, vis);
@@ -972,18 +1015,21 @@ fn format_struct_struct(context: &RewriteContext,
let generics_str = match generics {
Some(g) => {
try_opt!(format_generics(context,
g,
"{",
"{",
context.config.item_brace_style(),
fields.is_empty(),
offset,
mk_sp(span.lo, body_lo)))
try_opt!(format_generics(
context,
g,
"{",
"{",
context.config.item_brace_style(),
fields.is_empty(),
offset,
mk_sp(span.lo, body_lo),
))
}
None => {
if context.config.item_brace_style() == BraceStyle::AlwaysNextLine &&
!fields.is_empty() {
!fields.is_empty()
{
format!("\n{}{{", offset.block_only().to_string(context.config))
} else {
" {".to_owned()
@@ -1010,28 +1056,27 @@ fn format_struct_struct(context: &RewriteContext,
let item_indent = offset.block_indent(context.config);
// 1 = ","
let item_budget = try_opt!(context
.config
.max_width()
.checked_sub(item_indent.width() + 1));
let item_budget = try_opt!(context.config.max_width().checked_sub(
item_indent.width() + 1,
));
let items =
itemize_list(context.codemap,
fields.iter(),
"}",
|field| {
// Include attributes and doc comments, if present
if !field.attrs.is_empty() {
field.attrs[0].span.lo
} else {
field.span.lo
}
},
|field| field.ty.span.hi,
|field| field.rewrite(context, Shape::legacy(item_budget, item_indent)),
context.codemap.span_after(span, "{"),
span.hi)
.collect::<Vec<_>>();
let items = itemize_list(
context.codemap,
fields.iter(),
"}",
|field| {
// Include attributes and doc comments, if present
if !field.attrs.is_empty() {
field.attrs[0].span.lo
} else {
field.span.lo
}
},
|field| field.ty.span.hi,
|field| field.rewrite(context, Shape::legacy(item_budget, item_indent)),
context.codemap.span_after(span, "{"),
span.hi,
).collect::<Vec<_>>();
// 1 = ,
let budget = context.config.max_width() - offset.width() + context.config.tab_spaces() - 1;
@@ -1052,25 +1097,28 @@ fn format_struct_struct(context: &RewriteContext,
if one_line_width.is_some() && !items_str.contains('\n') {
Some(format!("{} {} }}", result, items_str))
} else {
Some(format!("{}\n{}{}\n{}}}",
result,
offset
.block_indent(context.config)
.to_string(context.config),
items_str,
offset.to_string(context.config)))
Some(format!(
"{}\n{}{}\n{}}}",
result,
offset.block_indent(context.config).to_string(
context.config,
),
items_str,
offset.to_string(context.config)
))
}
}
fn format_tuple_struct(context: &RewriteContext,
item_name: &str,
ident: ast::Ident,
vis: &ast::Visibility,
fields: &[ast::StructField],
generics: Option<&ast::Generics>,
span: Span,
offset: Indent)
-> Option<String> {
fn format_tuple_struct(
context: &RewriteContext,
item_name: &str,
ident: ast::Ident,
vis: &ast::Visibility,
fields: &[ast::StructField],
generics: Option<&ast::Generics>,
span: Span,
offset: Indent,
) -> Option<String> {
let mut result = String::with_capacity(1024);
let header_str = format_header(item_name, ident, vis);
@@ -1089,19 +1137,20 @@ fn format_tuple_struct(context: &RewriteContext,
let generics_str = try_opt!(rewrite_generics(context, generics, shape, g_span));
result.push_str(&generics_str);
let where_budget = try_opt!(context
.config
.max_width()
.checked_sub(last_line_width(&result)));
try_opt!(rewrite_where_clause(context,
&generics.where_clause,
context.config.item_brace_style(),
Shape::legacy(where_budget, offset.block_only()),
Density::Compressed,
";",
true,
false,
None))
let where_budget = try_opt!(context.config.max_width().checked_sub(
last_line_width(&result),
));
try_opt!(rewrite_where_clause(
context,
&generics.where_clause,
context.config.item_brace_style(),
Shape::legacy(where_budget, offset.block_only()),
Density::Compressed,
";",
true,
false,
None,
))
}
None => "".to_owned(),
};
@@ -1123,44 +1172,51 @@ fn format_tuple_struct(context: &RewriteContext,
let (tactic, item_indent) = match context.config.fn_args_layout() {
IndentStyle::Visual => {
// 1 = `(`
(ListTactic::HorizontalVertical, offset.block_only() + result.len() + 1)
(
ListTactic::HorizontalVertical,
offset.block_only() + result.len() + 1,
)
}
IndentStyle::Block => {
(ListTactic::HorizontalVertical, offset.block_only().block_indent(&context.config))
(
ListTactic::HorizontalVertical,
offset.block_only().block_indent(&context.config),
)
}
};
// 3 = `();`
let item_budget = try_opt!(context
.config
.max_width()
.checked_sub(item_indent.width() + 3));
let item_budget = try_opt!(context.config.max_width().checked_sub(
item_indent.width() + 3,
));
let items =
itemize_list(context.codemap,
fields.iter(),
")",
|field| {
// Include attributes and doc comments, if present
if !field.attrs.is_empty() {
field.attrs[0].span.lo
} else {
field.span.lo
}
},
|field| field.ty.span.hi,
|field| field.rewrite(context, Shape::legacy(item_budget, item_indent)),
context.codemap.span_after(span, "("),
span.hi);
let body_budget =
try_opt!(context
.config
.max_width()
.checked_sub(offset.block_only().width() + result.len() + 3));
let body = try_opt!(list_helper(items,
// TODO budget is wrong in block case
Shape::legacy(body_budget, item_indent),
context.config,
tactic));
let items = itemize_list(
context.codemap,
fields.iter(),
")",
|field| {
// Include attributes and doc comments, if present
if !field.attrs.is_empty() {
field.attrs[0].span.lo
} else {
field.span.lo
}
},
|field| field.ty.span.hi,
|field| field.rewrite(context, Shape::legacy(item_budget, item_indent)),
context.codemap.span_after(span, "("),
span.hi,
);
let body_budget = try_opt!(context.config.max_width().checked_sub(
offset.block_only().width() +
result.len() + 3,
));
let body = try_opt!(list_helper(
items,
// TODO budget is wrong in block case
Shape::legacy(body_budget, item_indent),
context.config,
tactic,
));
if context.config.fn_args_layout() == IndentStyle::Visual || !body.contains('\n') {
result.push('(');
@@ -1185,28 +1241,30 @@ fn format_tuple_struct(context: &RewriteContext,
}
if !where_clause_str.is_empty() && !where_clause_str.contains('\n') &&
(result.contains('\n') ||
offset.block_indent + result.len() + where_clause_str.len() + 1 >
context.config.max_width()) {
(result.contains('\n') ||
offset.block_indent + result.len() + where_clause_str.len() + 1 >
context.config.max_width())
{
// We need to put the where clause on a new line, but we didn't
// know that earlier, so the where clause will not be indented properly.
result.push('\n');
result.push_str(&(offset.block_only() + (context.config.tab_spaces() - 1))
.to_string(context.config));
.to_string(context.config));
}
result.push_str(&where_clause_str);
Some(result)
}
pub fn rewrite_type_alias(context: &RewriteContext,
indent: Indent,
ident: ast::Ident,
ty: &ast::Ty,
generics: &ast::Generics,
vis: &ast::Visibility,
span: Span)
-> Option<String> {
pub fn rewrite_type_alias(
context: &RewriteContext,
indent: Indent,
ident: ast::Ident,
ty: &ast::Ty,
generics: &ast::Generics,
vis: &ast::Visibility,
span: Span,
) -> Option<String> {
let mut result = String::new();
result.push_str(&format_visibility(vis));
@@ -1219,19 +1277,20 @@ pub fn rewrite_type_alias(context: &RewriteContext,
let generics_str = try_opt!(rewrite_generics(context, generics, shape, g_span));
result.push_str(&generics_str);
let where_budget = try_opt!(context
.config
.max_width()
.checked_sub(last_line_width(&result)));
let where_clause_str = try_opt!(rewrite_where_clause(context,
&generics.where_clause,
context.config.item_brace_style(),
Shape::legacy(where_budget, indent),
context.config.where_density(),
"=",
true,
true,
Some(span.hi)));
let where_budget = try_opt!(context.config.max_width().checked_sub(
last_line_width(&result),
));
let where_clause_str = try_opt!(rewrite_where_clause(
context,
&generics.where_clause,
context.config.item_brace_style(),
Shape::legacy(where_budget, indent),
context.config.where_density(),
"=",
true,
true,
Some(span.hi),
));
result.push_str(&where_clause_str);
result.push_str(" = ");
@@ -1255,10 +1314,9 @@ pub fn rewrite_type_alias(context: &RewriteContext,
let type_indent = indent.block_indent(context.config);
result.push('\n');
result.push_str(&type_indent.to_string(context.config));
let budget = try_opt!(context
.config
.max_width()
.checked_sub(type_indent.width() + ";".len()));
let budget = try_opt!(context.config.max_width().checked_sub(
type_indent.width() + ";".len(),
));
ty.rewrite(context, Shape::legacy(budget, type_indent))
})
);
@@ -1268,24 +1326,27 @@ pub fn rewrite_type_alias(context: &RewriteContext,
}
fn type_annotation_spacing(config: &Config) -> (&str, &str) {
(if config.space_before_type_annotation() {
" "
} else {
""
},
if config.space_after_type_annotation_colon() {
" "
} else {
""
})
(
if config.space_before_type_annotation() {
" "
} else {
""
},
if config.space_after_type_annotation_colon() {
" "
} else {
""
},
)
}
fn rewrite_missing_comment_on_field(context: &RewriteContext,
shape: Shape,
lo: BytePos,
hi: BytePos,
result: &mut String)
-> Option<String> {
fn rewrite_missing_comment_on_field(
context: &RewriteContext,
shape: Shape,
lo: BytePos,
hi: BytePos,
result: &mut String,
) -> Option<String> {
let possibly_comment_snippet = context.snippet(mk_sp(lo, hi));
let newline_index = possibly_comment_snippet.find('\n');
let comment_index = possibly_comment_snippet.find('/');
@@ -1300,8 +1361,9 @@ fn rewrite_missing_comment_on_field(context: &RewriteContext,
if trimmed.is_empty() {
None
} else {
rewrite_comment(trimmed, false, shape, context.config)
.map(|s| format!("{}\n{}", s, shape.indent.to_string(context.config)))
rewrite_comment(trimmed, false, shape, context.config).map(|s| {
format!("{}\n{}", s, shape.indent.to_string(context.config))
})
}
}
@@ -1314,17 +1376,19 @@ fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option<String> {
let name = self.ident;
let vis = format_visibility(&self.vis);
let mut attr_str = try_opt!(self.attrs.rewrite(context,
Shape::indented(shape.indent,
context.config)));
let mut attr_str = try_opt!(self.attrs.rewrite(
context,
Shape::indented(shape.indent, context.config),
));
// Try format missing comments after attributes
let missing_comment = if !self.attrs.is_empty() {
rewrite_missing_comment_on_field(context,
shape,
self.attrs[self.attrs.len() - 1].span.hi,
self.span.lo,
&mut attr_str)
.unwrap_or(String::new())
rewrite_missing_comment_on_field(
context,
shape,
self.attrs[self.attrs.len() - 1].span.hi,
self.span.lo,
&mut attr_str,
).unwrap_or(String::new())
} else {
String::new()
};
@@ -1332,38 +1396,45 @@ fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option<String> {
let type_annotation_spacing = type_annotation_spacing(context.config);
let mut result = match name {
Some(name) => {
format!("{}{}{}{}{}:",
attr_str,
missing_comment,
vis,
name,
type_annotation_spacing.0)
format!(
"{}{}{}{}{}:",
attr_str,
missing_comment,
vis,
name,
type_annotation_spacing.0
)
}
None => format!("{}{}{}", attr_str, missing_comment, vis),
};
let type_offset = shape.indent.block_indent(context.config);
let rewrite_type_in_next_line = || {
self.ty
.rewrite(context, Shape::indented(type_offset, context.config))
self.ty.rewrite(
context,
Shape::indented(type_offset, context.config),
)
};
let last_line_width = last_line_width(&result) + type_annotation_spacing.1.len();
let budget = try_opt!(shape.width.checked_sub(last_line_width));
let ty_rewritten =
self.ty.rewrite(context,
Shape::legacy(budget, shape.indent + last_line_width));
let ty_rewritten = self.ty.rewrite(
context,
Shape::legacy(budget, shape.indent + last_line_width),
);
match ty_rewritten {
Some(ref ty) if ty.contains('\n') => {
let new_ty = rewrite_type_in_next_line();
match new_ty {
Some(ref new_ty) if !new_ty.contains('\n') &&
new_ty.len() + type_offset.width() <=
context.config.max_width() => {
Some(format!("{}\n{}{}",
result,
type_offset.to_string(&context.config),
&new_ty))
new_ty.len() + type_offset.width() <=
context.config.max_width() => {
Some(format!(
"{}\n{}{}",
result,
type_offset.to_string(&context.config),
&new_ty
))
}
_ => {
if name.is_some() {
@@ -1381,59 +1452,69 @@ fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option<String> {
}
None => {
let ty = try_opt!(rewrite_type_in_next_line());
Some(format!("{}\n{}{}",
result,
type_offset.to_string(&context.config),
&ty))
Some(format!(
"{}\n{}{}",
result,
type_offset.to_string(&context.config),
&ty
))
}
}
}
}
pub fn rewrite_static(prefix: &str,
vis: &ast::Visibility,
ident: ast::Ident,
ty: &ast::Ty,
mutability: ast::Mutability,
expr_opt: Option<&ptr::P<ast::Expr>>,
offset: Indent,
span: Span,
context: &RewriteContext)
-> Option<String> {
pub fn rewrite_static(
prefix: &str,
vis: &ast::Visibility,
ident: ast::Ident,
ty: &ast::Ty,
mutability: ast::Mutability,
expr_opt: Option<&ptr::P<ast::Expr>>,
offset: Indent,
span: Span,
context: &RewriteContext,
) -> Option<String> {
let type_annotation_spacing = type_annotation_spacing(context.config);
let prefix = format!("{}{} {}{}{}:{}",
format_visibility(vis),
prefix,
format_mutability(mutability),
ident,
type_annotation_spacing.0,
type_annotation_spacing.1);
let prefix = format!(
"{}{} {}{}{}:{}",
format_visibility(vis),
prefix,
format_mutability(mutability),
ident,
type_annotation_spacing.0,
type_annotation_spacing.1
);
// 2 = " =".len()
let ty_str = try_opt!(ty.rewrite(context,
Shape::legacy(context.config.max_width() -
offset.block_indent -
prefix.len() -
2,
offset.block_only())));
let ty_str = try_opt!(ty.rewrite(
context,
Shape::legacy(
context.config.max_width() - offset.block_indent -
prefix.len() - 2,
offset.block_only(),
),
));
if let Some(expr) = expr_opt {
let lhs = format!("{}{} =", prefix, ty_str);
// 1 = ;
let remaining_width = context.config.max_width() - offset.block_indent - 1;
rewrite_assign_rhs(context,
lhs,
expr,
Shape::legacy(remaining_width, offset.block_only()))
.and_then(|res| {
recover_comment_removed(res,
span,
context,
Shape {
width: context.config.max_width(),
indent: offset,
offset: offset.alignment,
})
})
rewrite_assign_rhs(
context,
lhs,
expr,
Shape::legacy(remaining_width, offset.block_only()),
).and_then(|res| {
recover_comment_removed(
res,
span,
context,
Shape {
width: context.config.max_width(),
indent: offset,
offset: offset.alignment,
},
)
})
.map(|s| if s.ends_with(';') { s } else { s + ";" })
} else {
let lhs = format!("{}{};", prefix, ty_str);
@@ -1441,12 +1522,13 @@ pub fn rewrite_static(prefix: &str,
}
}
pub fn rewrite_associated_type(ident: ast::Ident,
ty_opt: Option<&ptr::P<ast::Ty>>,
ty_param_bounds_opt: Option<&ast::TyParamBounds>,
context: &RewriteContext,
indent: Indent)
-> Option<String> {
pub fn rewrite_associated_type(
ident: ast::Ident,
ty_opt: Option<&ptr::P<ast::Ty>>,
ty_param_bounds_opt: Option<&ast::TyParamBounds>,
context: &RewriteContext,
indent: Indent,
) -> Option<String> {
let prefix = format!("type {}", ident);
let type_bounds_str = if let Some(ty_param_bounds) = ty_param_bounds_opt {
@@ -1466,27 +1548,35 @@ pub fn rewrite_associated_type(ident: ast::Ident,
};
if let Some(ty) = ty_opt {
let ty_str = try_opt!(ty.rewrite(context,
Shape::legacy(context.config.max_width() -
indent.block_indent -
prefix.len() -
2,
indent.block_only())));
let ty_str = try_opt!(ty.rewrite(
context,
Shape::legacy(
context.config.max_width() - indent.block_indent -
prefix.len() - 2,
indent.block_only(),
),
));
Some(format!("{} = {};", prefix, ty_str))
} else {
Some(format!("{}{};", prefix, type_bounds_str))
}
}
pub fn rewrite_associated_impl_type(ident: ast::Ident,
defaultness: ast::Defaultness,
ty_opt: Option<&ptr::P<ast::Ty>>,
ty_param_bounds_opt: Option<&ast::TyParamBounds>,
context: &RewriteContext,
indent: Indent)
-> Option<String> {
let result =
try_opt!(rewrite_associated_type(ident, ty_opt, ty_param_bounds_opt, context, indent));
pub fn rewrite_associated_impl_type(
ident: ast::Ident,
defaultness: ast::Defaultness,
ty_opt: Option<&ptr::P<ast::Ty>>,
ty_param_bounds_opt: Option<&ast::TyParamBounds>,
context: &RewriteContext,
indent: Indent,
) -> Option<String> {
let result = try_opt!(rewrite_associated_type(
ident,
ty_opt,
ty_param_bounds_opt,
context,
indent,
));
match defaultness {
ast::Defaultness::Default => Some(format!("default {}", result)),
@@ -1510,8 +1600,10 @@ fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option<String> {
impl Rewrite for ast::Arg {
fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option<String> {
if is_named_arg(self) {
let mut result = try_opt!(self.pat.rewrite(context,
Shape::legacy(shape.width, shape.indent)));
let mut result = try_opt!(self.pat.rewrite(
context,
Shape::legacy(shape.width, shape.indent),
));
if self.ty.node != ast::TyKind::Infer {
if context.config.space_before_type_annotation() {
@@ -1522,9 +1614,10 @@ fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option<String> {
result.push_str(" ");
}
let max_width = try_opt!(shape.width.checked_sub(result.len()));
let ty_str = try_opt!(self.ty.rewrite(context,
Shape::legacy(max_width,
shape.indent + result.len())));
let ty_str = try_opt!(self.ty.rewrite(
context,
Shape::legacy(max_width, shape.indent + result.len()),
));
result.push_str(&ty_str);
}
@@ -1535,18 +1628,20 @@ fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option<String> {
}
}
fn rewrite_explicit_self(explicit_self: &ast::ExplicitSelf,
args: &[ast::Arg],
context: &RewriteContext)
-> Option<String> {
fn rewrite_explicit_self(
explicit_self: &ast::ExplicitSelf,
args: &[ast::Arg],
context: &RewriteContext,
) -> Option<String> {
match explicit_self.node {
ast::SelfKind::Region(lt, m) => {
let mut_str = format_mutability(m);
match lt {
Some(ref l) => {
let lifetime_str = try_opt!(l.rewrite(context,
Shape::legacy(usize::max_value(),
Indent::empty())));
let lifetime_str = try_opt!(l.rewrite(
context,
Shape::legacy(usize::max_value(), Indent::empty()),
));
Some(format!("&{} {}self", lifetime_str, mut_str))
}
None => Some(format!("&{}self", mut_str)),
@@ -1556,10 +1651,16 @@ fn rewrite_explicit_self(explicit_self: &ast::ExplicitSelf,
assert!(!args.is_empty(), "&[ast::Arg] shouldn't be empty.");
let mutability = explicit_self_mutability(&args[0]);
let type_str = try_opt!(ty.rewrite(context,
Shape::legacy(usize::max_value(), Indent::empty())));
let type_str = try_opt!(ty.rewrite(
context,
Shape::legacy(usize::max_value(), Indent::empty()),
));
Some(format!("{}self: {}", format_mutability(mutability), type_str))
Some(format!(
"{}self: {}",
format_mutability(mutability),
type_str
))
}
ast::SelfKind::Value(_) => {
assert!(!args.is_empty(), "&[ast::Arg] shouldn't be empty.");
@@ -1640,21 +1741,22 @@ fn span_for_where_pred(pred: &ast::WherePredicate) -> Span {
}
// Return type is (result, force_new_line_for_brace)
fn rewrite_fn_base(context: &RewriteContext,
indent: Indent,
ident: ast::Ident,
fd: &ast::FnDecl,
generics: &ast::Generics,
unsafety: ast::Unsafety,
constness: ast::Constness,
defaultness: ast::Defaultness,
abi: abi::Abi,
vis: &ast::Visibility,
span: Span,
newline_brace: bool,
has_body: bool,
has_braces: bool)
-> Option<(String, bool)> {
fn rewrite_fn_base(
context: &RewriteContext,
indent: Indent,
ident: ast::Ident,
fd: &ast::FnDecl,
generics: &ast::Generics,
unsafety: ast::Unsafety,
constness: ast::Constness,
defaultness: ast::Defaultness,
abi: abi::Abi,
vis: &ast::Visibility,
span: Span,
newline_brace: bool,
has_body: bool,
has_braces: bool,
) -> Option<(String, bool)> {
let mut force_new_line_for_brace = false;
let where_clause = &generics.where_clause;
@@ -1674,7 +1776,10 @@ fn rewrite_fn_base(context: &RewriteContext,
result.push_str(::utils::format_unsafety(unsafety));
if abi != abi::Abi::Rust {
result.push_str(&::utils::format_abi(abi, context.config.force_explicit_abi()));
result.push_str(&::utils::format_abi(
abi,
context.config.force_explicit_abi(),
));
}
// fn foo
@@ -1687,37 +1792,43 @@ fn rewrite_fn_base(context: &RewriteContext,
let generics_str = try_opt!(rewrite_generics(context, generics, shape, g_span));
result.push_str(&generics_str);
let snuggle_angle_bracket = generics_str
.lines()
.last()
.map_or(false, |l| l.trim_left().len() == 1);
let snuggle_angle_bracket = generics_str.lines().last().map_or(
false,
|l| l.trim_left().len() == 1,
);
// Note that the width and indent don't really matter, we'll re-layout the
// return type later anyway.
let ret_str = try_opt!(fd.output
.rewrite(&context, Shape::indented(indent, context.config)));
let ret_str = try_opt!(fd.output.rewrite(
&context,
Shape::indented(indent, context.config),
));
let multi_line_ret_str = ret_str.contains('\n');
let ret_str_len = if multi_line_ret_str { 0 } else { ret_str.len() };
// Args.
let (mut one_line_budget, mut multi_line_budget, mut arg_indent) =
try_opt!(compute_budgets_for_args(context,
&result,
indent,
ret_str_len,
newline_brace,
has_braces));
try_opt!(compute_budgets_for_args(
context,
&result,
indent,
ret_str_len,
newline_brace,
has_braces,
));
if context.config.fn_args_layout() == IndentStyle::Block {
arg_indent = indent.block_indent(context.config);
multi_line_budget = context.config.max_width() - arg_indent.width();
}
debug!("rewrite_fn_base: one_line_budget: {}, multi_line_budget: {}, arg_indent: {:?}",
one_line_budget,
multi_line_budget,
arg_indent);
debug!(
"rewrite_fn_base: one_line_budget: {}, multi_line_budget: {}, arg_indent: {:?}",
one_line_budget,
multi_line_budget,
arg_indent
);
// Check if vertical layout was forced.
if one_line_budget == 0 {
@@ -1751,25 +1862,29 @@ fn rewrite_fn_base(context: &RewriteContext,
}
// A conservative estimation, to goal is to be over all parens in generics
let args_start = generics
.ty_params
.last()
.map_or(span.lo, |tp| end_typaram(tp));
let args_span = mk_sp(context.codemap.span_after(mk_sp(args_start, span.hi), "("),
span_for_return(&fd.output).lo);
let arg_str = try_opt!(rewrite_args(context,
&fd.inputs,
fd.get_self().as_ref(),
one_line_budget,
multi_line_budget,
indent,
arg_indent,
args_span,
fd.variadic,
generics_str.contains('\n')));
let args_start = generics.ty_params.last().map_or(
span.lo,
|tp| end_typaram(tp),
);
let args_span = mk_sp(
context.codemap.span_after(mk_sp(args_start, span.hi), "("),
span_for_return(&fd.output).lo,
);
let arg_str = try_opt!(rewrite_args(
context,
&fd.inputs,
fd.get_self().as_ref(),
one_line_budget,
multi_line_budget,
indent,
arg_indent,
args_span,
fd.variadic,
generics_str.contains('\n'),
));
let multi_line_arg_str = arg_str.contains('\n') ||
arg_str.chars().last().map_or(false, |c| c == ',');
arg_str.chars().last().map_or(false, |c| c == ',');
let put_args_in_block = match context.config.fn_args_layout() {
IndentStyle::Block => multi_line_arg_str || generics_str.contains('\n'),
@@ -1792,10 +1907,10 @@ fn rewrite_fn_base(context: &RewriteContext,
}
// If the last line of args contains comment, we cannot put the closing paren
// on the same line.
if arg_str
.lines()
.last()
.map_or(false, |last_line| last_line.contains("//")) {
if arg_str.lines().last().map_or(false, |last_line| {
last_line.contains("//")
})
{
args_last_line_contains_comment = true;
result.push('\n');
result.push_str(&arg_indent.to_string(context.config));
@@ -1824,7 +1939,7 @@ fn rewrite_fn_base(context: &RewriteContext,
let overlong_sig = sig_length > context.config.max_width();
(!args_last_line_contains_comment) &&
(result.contains('\n') || multi_line_ret_str || overlong_sig)
(result.contains('\n') || multi_line_ret_str || overlong_sig)
}
};
let ret_indent = if ret_should_indent {
@@ -1852,8 +1967,10 @@ fn rewrite_fn_base(context: &RewriteContext,
if multi_line_ret_str || ret_should_indent {
// Now that we know the proper indent and width, we need to
// re-layout the return type.
let ret_str = try_opt!(fd.output.rewrite(context,
Shape::indented(ret_indent, context.config)));
let ret_str = try_opt!(fd.output.rewrite(
context,
Shape::indented(ret_indent, context.config),
));
result.push_str(&ret_str);
} else {
result.push_str(&ret_str);
@@ -1865,20 +1982,21 @@ fn rewrite_fn_base(context: &RewriteContext,
let snippet_hi = span.hi;
let snippet = context.snippet(mk_sp(snippet_lo, snippet_hi));
// Try to preserve the layout of the original snippet.
let original_starts_with_newline =
snippet
.find(|c| c != ' ')
.map_or(false, |i| snippet[i..].starts_with('\n'));
let original_ends_with_newline = snippet
.rfind(|c| c != ' ')
.map_or(false, |i| snippet[i..].ends_with('\n'));
let original_starts_with_newline = snippet.find(|c| c != ' ').map_or(false, |i| {
snippet[i..].starts_with('\n')
});
let original_ends_with_newline = snippet.rfind(|c| c != ' ').map_or(false, |i| {
snippet[i..].ends_with('\n')
});
let snippet = snippet.trim();
if !snippet.is_empty() {
result.push(if original_starts_with_newline {
'\n'
} else {
' '
});
result.push(
if original_starts_with_newline {
'\n'
} else {
' '
},
);
result.push_str(snippet);
if original_ends_with_newline {
force_new_line_for_brace = true;
@@ -1898,20 +2016,22 @@ fn rewrite_fn_base(context: &RewriteContext,
} || (put_args_in_block && ret_str.is_empty());
if where_clause.predicates.len() == 1 && should_compress_where {
let budget = try_opt!(context
.config
.max_width()
.checked_sub(last_line_width(&result)));
let budget = try_opt!(context.config.max_width().checked_sub(
last_line_width(&result),
));
if let Some(where_clause_str) =
rewrite_where_clause(context,
where_clause,
context.config.fn_brace_style(),
Shape::legacy(budget, indent),
Density::Compressed,
"{",
!has_braces,
put_args_in_block && ret_str.is_empty(),
Some(span.hi)) {
rewrite_where_clause(
context,
where_clause,
context.config.fn_brace_style(),
Shape::legacy(budget, indent),
Density::Compressed,
"{",
!has_braces,
put_args_in_block && ret_str.is_empty(),
Some(span.hi),
)
{
if !where_clause_str.contains('\n') {
if last_line_width(&result) + where_clause_str.len() > context.config.max_width() {
result.push('\n');
@@ -1925,15 +2045,17 @@ fn rewrite_fn_base(context: &RewriteContext,
}
}
let where_clause_str = try_opt!(rewrite_where_clause(context,
where_clause,
context.config.fn_brace_style(),
Shape::indented(indent, context.config),
Density::Tall,
"{",
!has_braces,
put_args_in_block && ret_str.is_empty(),
Some(span.hi)));
let where_clause_str = try_opt!(rewrite_where_clause(
context,
where_clause,
context.config.fn_brace_style(),
Shape::indented(indent, context.config),
Density::Tall,
"{",
!has_braces,
put_args_in_block && ret_str.is_empty(),
Some(span.hi),
));
result.push_str(&where_clause_str);
@@ -1945,27 +2067,33 @@ fn last_line_contains_single_line_comment(s: &str) -> bool {
s.lines().last().map_or(false, |l| l.contains("//"))
}
fn rewrite_args(context: &RewriteContext,
args: &[ast::Arg],
explicit_self: Option<&ast::ExplicitSelf>,
one_line_budget: usize,
multi_line_budget: usize,
indent: Indent,
arg_indent: Indent,
span: Span,
variadic: bool,
generics_str_contains_newline: bool)
-> Option<String> {
let mut arg_item_strs =
try_opt!(args.iter()
.map(|arg| arg.rewrite(&context, Shape::legacy(multi_line_budget, arg_indent)))
.collect::<Option<Vec<_>>>());
fn rewrite_args(
context: &RewriteContext,
args: &[ast::Arg],
explicit_self: Option<&ast::ExplicitSelf>,
one_line_budget: usize,
multi_line_budget: usize,
indent: Indent,
arg_indent: Indent,
span: Span,
variadic: bool,
generics_str_contains_newline: bool,
) -> Option<String> {
let mut arg_item_strs = try_opt!(
args.iter()
.map(|arg| {
arg.rewrite(&context, Shape::legacy(multi_line_budget, arg_indent))
})
.collect::<Option<Vec<_>>>()
);
// Account for sugary self.
// FIXME: the comment for the self argument is dropped. This is blocked
// on rust issue #27522.
let min_args = explicit_self
.and_then(|explicit_self| rewrite_explicit_self(explicit_self, args, context))
.and_then(|explicit_self| {
rewrite_explicit_self(explicit_self, args, context)
})
.map_or(1, |self_str| {
arg_item_strs[0] = self_str;
2
@@ -2008,33 +2136,34 @@ enum ArgumentKind<'a> {
None
};
let more_items = itemize_list(context.codemap,
args[min_args - 1..]
.iter()
.map(ArgumentKind::Regular)
.chain(variadic_arg),
")",
|arg| match *arg {
ArgumentKind::Regular(arg) => span_lo_for_arg(arg),
ArgumentKind::Variadic(start) => start,
},
|arg| match *arg {
ArgumentKind::Regular(arg) => arg.ty.span.hi,
ArgumentKind::Variadic(start) => start + BytePos(3),
},
|arg| match *arg {
ArgumentKind::Regular(..) => None,
ArgumentKind::Variadic(..) => Some("...".to_owned()),
},
comment_span_start,
span.hi);
let more_items = itemize_list(
context.codemap,
args[min_args - 1..]
.iter()
.map(ArgumentKind::Regular)
.chain(variadic_arg),
")",
|arg| match *arg {
ArgumentKind::Regular(arg) => span_lo_for_arg(arg),
ArgumentKind::Variadic(start) => start,
},
|arg| match *arg {
ArgumentKind::Regular(arg) => arg.ty.span.hi,
ArgumentKind::Variadic(start) => start + BytePos(3),
},
|arg| match *arg {
ArgumentKind::Regular(..) => None,
ArgumentKind::Variadic(..) => Some("...".to_owned()),
},
comment_span_start,
span.hi,
);
arg_items.extend(more_items);
}
let fits_in_one_line = !generics_str_contains_newline &&
(arg_items.len() == 0 ||
arg_items.len() == 1 && arg_item_strs[0].len() <= one_line_budget);
(arg_items.len() == 0 || arg_items.len() == 1 && arg_item_strs[0].len() <= one_line_budget);
for (item, arg) in arg_items.iter_mut().zip(arg_item_strs) {
item.item = Some(arg);
@@ -2048,10 +2177,18 @@ enum ArgumentKind<'a> {
let (indent, trailing_comma, end_with_newline) = match context.config.fn_args_layout() {
IndentStyle::Block if fits_in_one_line => {
(indent.block_indent(context.config), SeparatorTactic::Never, true)
(
indent.block_indent(context.config),
SeparatorTactic::Never,
true,
)
}
IndentStyle::Block => {
(indent.block_indent(context.config), SeparatorTactic::Vertical, true)
(
indent.block_indent(context.config),
SeparatorTactic::Vertical,
true,
)
}
IndentStyle::Visual if last_line_ends_with_comment => {
(arg_indent, SeparatorTactic::Vertical, true)
@@ -2059,9 +2196,11 @@ enum ArgumentKind<'a> {
IndentStyle::Visual => (arg_indent, SeparatorTactic::Never, false),
};
let tactic = definitive_tactic(&arg_items,
context.config.fn_args_density().to_list_tactic(),
one_line_budget);
let tactic = definitive_tactic(
&arg_items,
context.config.fn_args_density().to_list_tactic(),
one_line_budget,
);
let budget = match tactic {
DefinitiveListTactic::Horizontal => one_line_budget,
_ => multi_line_budget,
@@ -2093,18 +2232,21 @@ fn arg_has_pattern(arg: &ast::Arg) -> bool {
}
}
fn compute_budgets_for_args(context: &RewriteContext,
result: &str,
indent: Indent,
ret_str_len: usize,
newline_brace: bool,
has_braces: bool)
-> Option<((usize, usize, Indent))> {
debug!("compute_budgets_for_args {} {:?}, {}, {}",
result.len(),
indent,
ret_str_len,
newline_brace);
fn compute_budgets_for_args(
context: &RewriteContext,
result: &str,
indent: Indent,
ret_str_len: usize,
newline_brace: bool,
has_braces: bool,
) -> Option<((usize, usize, Indent))> {
debug!(
"compute_budgets_for_args {} {:?}, {}, {}",
result.len(),
indent,
ret_str_len,
newline_brace
);
// Try keeping everything on the same line.
if !result.contains('\n') {
// 2 = `()`, 3 = `() `, space is before ret_string.
@@ -2128,11 +2270,14 @@ fn compute_budgets_for_args(context: &RewriteContext,
if one_line_budget > 0 {
// 4 = "() {".len()
let multi_line_overhead = indent.width() + result.len() +
if newline_brace { 2 } else { 4 };
let multi_line_budget =
try_opt!(context.config.max_width().checked_sub(multi_line_overhead));
if newline_brace { 2 } else { 4 };
let multi_line_budget = try_opt!(context.config.max_width().checked_sub(multi_line_overhead));
return Some((one_line_budget, multi_line_budget, indent + result.len() + 1));
return Some((
one_line_budget,
multi_line_budget,
indent + result.len() + 1,
));
}
}
@@ -2182,13 +2327,13 @@ fn rewrite_generics_inner(context: &RewriteContext,
// Extract comments between generics.
let lt_spans = lifetimes.iter().map(|l| {
let hi = if l.bounds.is_empty() {
l.lifetime.span.hi
} else {
l.bounds[l.bounds.len() - 1].span.hi
};
mk_sp(l.lifetime.span.lo, hi)
});
let hi = if l.bounds.is_empty() {
l.lifetime.span.hi
} else {
l.bounds[l.bounds.len() - 1].span.hi
};
mk_sp(l.lifetime.span.lo, hi)
});
let ty_spans = tys.iter().map(span_for_ty_param);
let items = itemize_list(context.codemap,
@@ -2260,10 +2405,11 @@ pub fn wrap_generics_with_angle_brackets(context: &RewriteContext,
}
}
fn rewrite_trait_bounds(context: &RewriteContext,
type_param_bounds: &ast::TyParamBounds,
shape: Shape)
-> Option<String> {
fn rewrite_trait_bounds(
context: &RewriteContext,
type_param_bounds: &ast::TyParamBounds,
shape: Shape,
) -> Option<String> {
let bounds: &[_] = type_param_bounds;
if bounds.is_empty() {
@@ -2276,15 +2422,16 @@ fn rewrite_trait_bounds(context: &RewriteContext,
Some(format!(": {}", join_bounds(context, shape, &bound_str)))
}
fn rewrite_where_clause_rfc_style(context: &RewriteContext,
where_clause: &ast::WhereClause,
shape: Shape,
terminator: &str,
suppress_comma: bool,
// where clause can be kept on the current line.
snuggle: bool,
span_end: Option<BytePos>)
-> Option<String> {
fn rewrite_where_clause_rfc_style(
context: &RewriteContext,
where_clause: &ast::WhereClause,
shape: Shape,
terminator: &str,
suppress_comma: bool,
// where clause can be kept on the current line.
snuggle: bool,
span_end: Option<BytePos>,
) -> Option<String> {
let block_shape = shape.block();
let starting_newline = if snuggle {
@@ -2325,34 +2472,39 @@ fn rewrite_where_clause_rfc_style(context: &RewriteContext,
};
let preds_str = try_opt!(write_list(items, &fmt));
Some(format!("{}where\n{}{}",
starting_newline,
clause_shape.indent.to_string(context.config),
preds_str))
Some(format!(
"{}where\n{}{}",
starting_newline,
clause_shape.indent.to_string(context.config),
preds_str
))
}
fn rewrite_where_clause(context: &RewriteContext,
where_clause: &ast::WhereClause,
brace_style: BraceStyle,
shape: Shape,
density: Density,
terminator: &str,
suppress_comma: bool,
snuggle: bool,
span_end: Option<BytePos>)
-> Option<String> {
fn rewrite_where_clause(
context: &RewriteContext,
where_clause: &ast::WhereClause,
brace_style: BraceStyle,
shape: Shape,
density: Density,
terminator: &str,
suppress_comma: bool,
snuggle: bool,
span_end: Option<BytePos>,
) -> Option<String> {
if where_clause.predicates.is_empty() {
return Some(String::new());
}
if context.config.where_style() == Style::Rfc {
return rewrite_where_clause_rfc_style(context,
where_clause,
shape,
terminator,
suppress_comma,
snuggle,
span_end);
return rewrite_where_clause_rfc_style(
context,
where_clause,
shape,
terminator,
suppress_comma,
snuggle,
span_end,
);
}
let extra_indent = Indent::new(context.config.tab_spaces(), 0);
@@ -2372,14 +2524,16 @@ fn rewrite_where_clause(context: &RewriteContext,
let len = where_clause.predicates.len();
let end_of_preds = span_for_where_pred(&where_clause.predicates[len - 1]).hi;
let span_end = span_end.unwrap_or(end_of_preds);
let items = itemize_list(context.codemap,
where_clause.predicates.iter(),
terminator,
|pred| span_for_where_pred(pred).lo,
|pred| span_for_where_pred(pred).hi,
|pred| pred.rewrite(context, Shape::legacy(budget, offset)),
span_start,
span_end);
let items = itemize_list(
context.codemap,
where_clause.predicates.iter(),
terminator,
|pred| span_for_where_pred(pred).lo,
|pred| span_for_where_pred(pred).hi,
|pred| pred.rewrite(context, Shape::legacy(budget, offset)),
span_start,
span_end,
);
let item_vec = items.collect::<Vec<_>>();
// FIXME: we don't need to collect here if the where_layout isn't
// HorizontalVertical.
@@ -2415,10 +2569,13 @@ fn rewrite_where_clause(context: &RewriteContext,
terminator.len()
};
if density == Density::Tall || preds_str.contains('\n') ||
shape.indent.width() + " where ".len() + preds_str.len() + end_length > shape.width {
Some(format!("\n{}where {}",
(shape.indent + extra_indent).to_string(context.config),
preds_str))
shape.indent.width() + " where ".len() + preds_str.len() + end_length > shape.width
{
Some(format!(
"\n{}where {}",
(shape.indent + extra_indent).to_string(context.config),
preds_str
))
} else {
Some(format!(" where {}", preds_str))
}
@@ -2428,39 +2585,40 @@ fn format_header(item_name: &str, ident: ast::Ident, vis: &ast::Visibility) -> S
format!("{}{}{}", format_visibility(vis), item_name, ident)
}
fn format_generics(context: &RewriteContext,
generics: &ast::Generics,
opener: &str,
terminator: &str,
brace_style: BraceStyle,
force_same_line_brace: bool,
offset: Indent,
span: Span)
-> Option<String> {
fn format_generics(
context: &RewriteContext,
generics: &ast::Generics,
opener: &str,
terminator: &str,
brace_style: BraceStyle,
force_same_line_brace: bool,
offset: Indent,
span: Span,
) -> Option<String> {
let shape = Shape::indented(offset, context.config);
let mut result = try_opt!(rewrite_generics(context, generics, shape, span));
if !generics.where_clause.predicates.is_empty() || result.contains('\n') {
let budget = try_opt!(context
.config
.max_width()
.checked_sub(last_line_width(&result)));
let where_clause_str =
try_opt!(rewrite_where_clause(context,
&generics.where_clause,
brace_style,
Shape::legacy(budget, offset.block_only()),
Density::Tall,
terminator,
false,
trimmed_last_line_width(&result) == 1,
Some(span.hi)));
let budget = try_opt!(context.config.max_width().checked_sub(
last_line_width(&result),
));
let where_clause_str = try_opt!(rewrite_where_clause(
context,
&generics.where_clause,
brace_style,
Shape::legacy(budget, offset.block_only()),
Density::Tall,
terminator,
false,
trimmed_last_line_width(&result) == 1,
Some(span.hi),
));
result.push_str(&where_clause_str);
let same_line_brace = force_same_line_brace ||
(generics.where_clause.predicates.is_empty() &&
trimmed_last_line_width(&result) == 1);
(generics.where_clause.predicates.is_empty() && trimmed_last_line_width(&result) == 1);
if !same_line_brace &&
(brace_style == BraceStyle::SameLineWhere || brace_style == BraceStyle::AlwaysNextLine) {
(brace_style == BraceStyle::SameLineWhere || brace_style == BraceStyle::AlwaysNextLine)
{
result.push('\n');
result.push_str(&offset.block_only().to_string(context.config));
} else {
@@ -2469,7 +2627,8 @@ fn format_generics(context: &RewriteContext,
result.push_str(opener);
} else {
if force_same_line_brace || trimmed_last_line_width(&result) == 1 ||
brace_style != BraceStyle::AlwaysNextLine {
brace_style != BraceStyle::AlwaysNextLine
{
result.push(' ');
} else {
result.push('\n');
+58 -45
View File
@@ -189,8 +189,10 @@ impl Sub for Indent {
type Output = Indent;
fn sub(self, rhs: Indent) -> Indent {
Indent::new(self.block_indent - rhs.block_indent,
self.alignment - rhs.alignment)
Indent::new(
self.block_indent - rhs.block_indent,
self.alignment - rhs.alignment,
)
}
}
@@ -315,17 +317,17 @@ pub fn block(&self) -> Shape {
pub fn sub_width(&self, width: usize) -> Option<Shape> {
Some(Shape {
width: try_opt!(self.width.checked_sub(width)),
..*self
})
width: try_opt!(self.width.checked_sub(width)),
..*self
})
}
pub fn shrink_left(&self, width: usize) -> Option<Shape> {
Some(Shape {
width: try_opt!(self.width.checked_sub(width)),
indent: self.indent + width,
offset: self.offset + width,
})
width: try_opt!(self.width.checked_sub(width)),
indent: self.indent + width,
offset: self.offset + width,
})
}
pub fn offset_left(&self, width: usize) -> Option<Shape> {
@@ -350,10 +352,12 @@ impl fmt::Display for ErrorKind {
fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
match *self {
ErrorKind::LineOverflow(found, maximum) => {
write!(fmt,
"line exceeded maximum length (maximum: {}, found: {})",
maximum,
found)
write!(
fmt,
"line exceeded maximum length (maximum: {}, found: {})",
maximum,
found
)
}
ErrorKind::TrailingWhitespace => write!(fmt, "left behind trailing whitespace"),
ErrorKind::BadIssue(issue) => write!(fmt, "found {}", issue),
@@ -412,13 +416,15 @@ impl fmt::Display for FormatReport {
fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
for (file, errors) in &self.file_error_map {
for error in errors {
write!(fmt,
"{} {}:{}: {} {}\n",
error.msg_prefix(),
file,
error.line,
error.kind,
error.msg_suffix())?;
write!(
fmt,
"{} {}:{}: {} {}\n",
error.msg_prefix(),
file,
error.line,
error.kind,
error.msg_suffix()
)?;
}
}
Ok(())
@@ -426,14 +432,16 @@ fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
}
// Formatting which depends on the AST.
fn format_ast<F>(krate: &ast::Crate,
mut parse_session: &mut ParseSess,
main_file: &Path,
config: &Config,
codemap: &Rc<CodeMap>,
mut after_file: F)
-> Result<(FileMap, bool), io::Error>
where F: FnMut(&str, &mut StringBuffer) -> Result<bool, io::Error>
fn format_ast<F>(
krate: &ast::Crate,
mut parse_session: &mut ParseSess,
main_file: &Path,
config: &Config,
codemap: &Rc<CodeMap>,
mut after_file: F,
) -> Result<(FileMap, bool), io::Error>
where
F: FnMut(&str, &mut StringBuffer) -> Result<bool, io::Error>,
{
let mut result = FileMap::new();
// diff mode: check if any files are differing
@@ -493,9 +501,9 @@ fn format_lines(text: &mut StringBuffer, name: &str, config: &Config, report: &m
// Add warnings for bad todos/ fixmes
if let Some(issue) = issue_seeker.inspect(c) {
errors.push(FormattingError {
line: cur_line,
kind: ErrorKind::BadIssue(issue),
});
line: cur_line,
kind: ErrorKind::BadIssue(issue),
});
}
}
@@ -510,9 +518,9 @@ fn format_lines(text: &mut StringBuffer, name: &str, config: &Config, report: &m
// Check for any line width errors we couldn't correct.
if config.error_on_line_overflow() && line_len > config.max_width() {
errors.push(FormattingError {
line: cur_line,
kind: ErrorKind::LineOverflow(line_len, config.max_width()),
});
line: cur_line,
kind: ErrorKind::LineOverflow(line_len, config.max_width()),
});
}
}
@@ -541,17 +549,18 @@ fn format_lines(text: &mut StringBuffer, name: &str, config: &Config, report: &m
for &(l, _, _) in &trims {
errors.push(FormattingError {
line: l,
kind: ErrorKind::TrailingWhitespace,
});
line: l,
kind: ErrorKind::TrailingWhitespace,
});
}
report.file_error_map.insert(name.to_owned(), errors);
}
fn parse_input(input: Input,
parse_session: &ParseSess)
-> Result<ast::Crate, Option<DiagnosticBuilder>> {
fn parse_input(
input: Input,
parse_session: &ParseSess,
) -> Result<ast::Crate, Option<DiagnosticBuilder>> {
let result = match input {
Input::File(file) => {
let mut parser = parse::new_parser_from_file(parse_session, &file);
@@ -579,10 +588,11 @@ fn parse_input(input: Input,
}
}
pub fn format_input<T: Write>(input: Input,
config: &Config,
mut out: Option<&mut T>)
-> Result<(Summary, FileMap, FormatReport), (io::Error, Summary)> {
pub fn format_input<T: Write>(
input: Input,
config: &Config,
mut out: Option<&mut T>,
) -> Result<(Summary, FileMap, FormatReport), (io::Error, Summary)> {
let mut summary = Summary::new();
if config.disable_all_formatting() {
return Ok((summary, FileMap::new(), FormatReport::new()));
@@ -614,7 +624,10 @@ pub fn format_input<T: Write>(input: Input,
}
// Suppress error output after parsing.
let silent_emitter = Box::new(EmitterWriter::new(Box::new(Vec::new()), Some(codemap.clone())));
let silent_emitter = Box::new(EmitterWriter::new(
Box::new(Vec::new()),
Some(codemap.clone()),
));
parse_session.span_diagnostic = Handler::with_emitter(true, false, silent_emitter);
let mut report = FormatReport::new();
+133 -101
View File
@@ -69,22 +69,27 @@ pub struct ListFormatting<'a> {
}
pub fn format_fn_args<I>(items: I, shape: Shape, config: &Config) -> Option<String>
where I: Iterator<Item = ListItem>
where
I: Iterator<Item = ListItem>,
{
list_helper(items,
shape,
config,
ListTactic::LimitedHorizontalVertical(config.fn_call_width()))
list_helper(
items,
shape,
config,
ListTactic::LimitedHorizontalVertical(config.fn_call_width()),
)
}
pub fn format_item_list<I>(items: I, shape: Shape, config: &Config) -> Option<String>
where I: Iterator<Item = ListItem>
where
I: Iterator<Item = ListItem>,
{
list_helper(items, shape, config, ListTactic::HorizontalVertical)
}
pub fn list_helper<I>(items: I, shape: Shape, config: &Config, tactic: ListTactic) -> Option<String>
where I: Iterator<Item = ListItem>
where
I: Iterator<Item = ListItem>,
{
let item_vec: Vec<_> = items.collect();
let tactic = definitive_tactic(&item_vec, tactic, shape.width);
@@ -120,15 +125,16 @@ pub struct ListItem {
impl ListItem {
pub fn is_multiline(&self) -> bool {
self.item.as_ref().map_or(false, |s| s.contains('\n')) || self.pre_comment.is_some() ||
self.post_comment
.as_ref()
.map_or(false, |s| s.contains('\n'))
self.post_comment.as_ref().map_or(
false,
|s| s.contains('\n'),
)
}
pub fn has_line_pre_comment(&self) -> bool {
self.pre_comment
.as_ref()
.map_or(false, |comment| comment.starts_with("//"))
self.pre_comment.as_ref().map_or(false, |comment| {
comment.starts_with("//")
})
}
pub fn from_str<S: Into<String>>(s: S) -> ListItem {
@@ -150,13 +156,13 @@ pub enum DefinitiveListTactic {
}
pub fn definitive_tactic<I, T>(items: I, tactic: ListTactic, width: usize) -> DefinitiveListTactic
where I: IntoIterator<Item = T> + Clone,
T: AsRef<ListItem>
where
I: IntoIterator<Item = T> + Clone,
T: AsRef<ListItem>,
{
let pre_line_comments = items
.clone()
.into_iter()
.any(|item| item.as_ref().has_line_pre_comment());
let pre_line_comments = items.clone().into_iter().any(|item| {
item.as_ref().has_line_pre_comment()
});
let limit = match tactic {
_ if pre_line_comments => return DefinitiveListTactic::Vertical,
@@ -173,7 +179,8 @@ pub fn definitive_tactic<I, T>(items: I, tactic: ListTactic, width: usize) -> De
let real_total = total_width + total_sep_len;
if real_total <= limit && !pre_line_comments &&
!items.into_iter().any(|item| item.as_ref().is_multiline()) {
!items.into_iter().any(|item| item.as_ref().is_multiline())
{
DefinitiveListTactic::Horizontal
} else {
DefinitiveListTactic::Vertical
@@ -183,8 +190,9 @@ pub fn definitive_tactic<I, T>(items: I, tactic: ListTactic, width: usize) -> De
// Format a list of commented items into a string.
// TODO: add unit tests
pub fn write_list<I, T>(items: I, formatting: &ListFormatting) -> Option<String>
where I: IntoIterator<Item = T>,
T: AsRef<ListItem>
where
I: IntoIterator<Item = T>,
T: AsRef<ListItem>,
{
let tactic = formatting.tactic;
let sep_len = formatting.separator.len();
@@ -250,8 +258,12 @@ pub fn write_list<I, T>(items: I, formatting: &ListFormatting) -> Option<String>
// Block style in non-vertical mode.
let block_mode = tactic != DefinitiveListTactic::Vertical;
// Width restriction is only relevant in vertical mode.
let comment =
try_opt!(rewrite_comment(comment, block_mode, formatting.shape, formatting.config));
let comment = try_opt!(rewrite_comment(
comment,
block_mode,
formatting.shape,
formatting.config,
));
result.push_str(&comment);
if tactic == DefinitiveListTactic::Vertical {
@@ -267,11 +279,12 @@ pub fn write_list<I, T>(items: I, formatting: &ListFormatting) -> Option<String>
// Post-comments
if tactic != DefinitiveListTactic::Vertical && item.post_comment.is_some() {
let comment = item.post_comment.as_ref().unwrap();
let formatted_comment =
try_opt!(rewrite_comment(comment,
true,
Shape::legacy(formatting.shape.width, Indent::empty()),
formatting.config));
let formatted_comment = try_opt!(rewrite_comment(
comment,
true,
Shape::legacy(formatting.shape.width, Indent::empty()),
formatting.config,
));
result.push(' ');
result.push_str(&formatted_comment);
@@ -295,13 +308,15 @@ pub fn write_list<I, T>(items: I, formatting: &ListFormatting) -> Option<String>
debug!("Width = {}, offset = {:?}", width, offset);
// Use block-style only for the last item or multiline comments.
let block_style = !formatting.ends_with_newline && last ||
comment.trim().contains('\n') ||
comment.trim().len() > width;
comment.trim().contains('\n') ||
comment.trim().len() > width;
let formatted_comment = try_opt!(rewrite_comment(comment,
block_style,
Shape::legacy(width, offset),
formatting.config));
let formatted_comment = try_opt!(rewrite_comment(
comment,
block_style,
Shape::legacy(width, offset),
formatting.config,
));
if !formatted_comment.starts_with('\n') {
result.push(' ');
@@ -318,7 +333,8 @@ pub fn write_list<I, T>(items: I, formatting: &ListFormatting) -> Option<String>
}
pub struct ListItems<'a, I, F1, F2, F3>
where I: Iterator
where
I: Iterator,
{
codemap: &'a CodeMap,
inner: Peekable<I>,
@@ -331,10 +347,11 @@ pub struct ListItems<'a, I, F1, F2, F3>
}
impl<'a, T, I, F1, F2, F3> Iterator for ListItems<'a, I, F1, F2, F3>
where I: Iterator<Item = T>,
F1: Fn(&T) -> BytePos,
F2: Fn(&T) -> BytePos,
F3: Fn(&T) -> Option<String>
where
I: Iterator<Item = T>,
F1: Fn(&T) -> BytePos,
F2: Fn(&T) -> BytePos,
F3: Fn(&T) -> Option<String>,
{
type Item = ListItem;
@@ -349,7 +366,7 @@ fn next(&mut self) -> Option<Self::Item> {
.unwrap();
let trimmed_pre_snippet = pre_snippet.trim();
let has_pre_comment = trimmed_pre_snippet.contains("//") ||
trimmed_pre_snippet.contains("/*");
trimmed_pre_snippet.contains("/*");
let pre_comment = if has_pre_comment {
Some(trimmed_pre_snippet.to_owned())
} else {
@@ -383,13 +400,17 @@ fn next(&mut self) -> Option<Self::Item> {
(Some(i), None) if i > separator_index => separator_index + 1,
// Block-style post-comment before the separator.
(Some(i), None) => {
cmp::max(find_comment_end(&post_snippet[i..]).unwrap() + i,
separator_index + 1)
cmp::max(
find_comment_end(&post_snippet[i..]).unwrap() + i,
separator_index + 1,
)
}
// Block-style post-comment. Either before or after the separator.
(Some(i), Some(j)) if i < j => {
cmp::max(find_comment_end(&post_snippet[i..]).unwrap() + i,
separator_index + 1)
cmp::max(
find_comment_end(&post_snippet[i..]).unwrap() + i,
separator_index + 1,
)
}
// Potential *single* line comment.
(_, Some(j)) if j > separator_index => j + 1,
@@ -397,9 +418,10 @@ fn next(&mut self) -> Option<Self::Item> {
}
}
None => {
post_snippet
.find_uncommented(self.terminator)
.unwrap_or(post_snippet.len())
post_snippet.find_uncommented(self.terminator).unwrap_or(
post_snippet
.len(),
)
}
};
@@ -412,9 +434,10 @@ fn next(&mut self) -> Option<Self::Item> {
let first_newline = test_snippet.find('\n').unwrap_or(test_snippet.len());
// From the end of the first line of comments.
let test_snippet = &test_snippet[first_newline..];
let first = test_snippet
.find(|c: char| !c.is_whitespace())
.unwrap_or(test_snippet.len());
let first = test_snippet.find(|c: char| !c.is_whitespace()).unwrap_or(
test_snippet
.len(),
);
// From the end of the first line of comments to the next non-whitespace char.
let test_snippet = &test_snippet[..first];
@@ -453,19 +476,21 @@ fn next(&mut self) -> Option<Self::Item> {
}
// Creates an iterator over a list's items with associated comments.
pub fn itemize_list<'a, T, I, F1, F2, F3>(codemap: &'a CodeMap,
inner: I,
terminator: &'a str,
get_lo: F1,
get_hi: F2,
get_item_string: F3,
prev_span_end: BytePos,
next_span_start: BytePos)
-> ListItems<'a, I, F1, F2, F3>
where I: Iterator<Item = T>,
F1: Fn(&T) -> BytePos,
F2: Fn(&T) -> BytePos,
F3: Fn(&T) -> Option<String>
pub fn itemize_list<'a, T, I, F1, F2, F3>(
codemap: &'a CodeMap,
inner: I,
terminator: &'a str,
get_lo: F1,
get_hi: F2,
get_item_string: F3,
prev_span_end: BytePos,
next_span_start: BytePos,
) -> ListItems<'a, I, F1, F2, F3>
where
I: Iterator<Item = T>,
F1: Fn(&T) -> BytePos,
F2: Fn(&T) -> BytePos,
F3: Fn(&T) -> Option<String>,
{
ListItems {
codemap: codemap,
@@ -479,9 +504,10 @@ pub fn itemize_list<'a, T, I, F1, F2, F3>(codemap: &'a CodeMap,
}
}
fn needs_trailing_separator(separator_tactic: SeparatorTactic,
list_tactic: DefinitiveListTactic)
-> bool {
fn needs_trailing_separator(
separator_tactic: SeparatorTactic,
list_tactic: DefinitiveListTactic,
) -> bool {
match separator_tactic {
SeparatorTactic::Always => true,
SeparatorTactic::Vertical => list_tactic == DefinitiveListTactic::Vertical,
@@ -491,8 +517,9 @@ fn needs_trailing_separator(separator_tactic: SeparatorTactic,
/// Returns the count and total width of the list items.
fn calculate_width<I, T>(items: I) -> (usize, usize)
where I: IntoIterator<Item = T>,
T: AsRef<ListItem>
where
I: IntoIterator<Item = T>,
T: AsRef<ListItem>,
{
items
.into_iter()
@@ -502,8 +529,8 @@ fn calculate_width<I, T>(items: I) -> (usize, usize)
fn total_item_width(item: &ListItem) -> usize {
comment_len(item.pre_comment.as_ref().map(|x| &(*x)[..])) +
comment_len(item.post_comment.as_ref().map(|x| &(*x)[..])) +
item.item.as_ref().map_or(0, |str| str.len())
comment_len(item.post_comment.as_ref().map(|x| &(*x)[..])) +
item.item.as_ref().map_or(0, |str| str.len())
}
fn comment_len(comment: Option<&str>) -> usize {
@@ -522,33 +549,36 @@ fn comment_len(comment: Option<&str>) -> usize {
}
// Compute horizontal and vertical shapes for a struct-lit-like thing.
pub fn struct_lit_shape(shape: Shape,
context: &RewriteContext,
prefix_width: usize,
suffix_width: usize)
-> Option<(Option<Shape>, Shape)> {
let v_shape = match context.config.struct_lit_style() {
IndentStyle::Visual => {
try_opt!(try_opt!(shape.visual_indent(0).shrink_left(prefix_width))
pub fn struct_lit_shape(
shape: Shape,
context: &RewriteContext,
prefix_width: usize,
suffix_width: usize,
) -> Option<(Option<Shape>, Shape)> {
let v_shape =
match context.config.struct_lit_style() {
IndentStyle::Visual => {
try_opt!(try_opt!(shape.visual_indent(0).shrink_left(prefix_width))
.sub_width(suffix_width))
}
IndentStyle::Block => {
let shape = shape.block_indent(context.config.tab_spaces());
Shape {
width: try_opt!(context.config.max_width().checked_sub(shape.indent.width())),
..shape
}
}
};
IndentStyle::Block => {
let shape = shape.block_indent(context.config.tab_spaces());
Shape {
width: try_opt!(context.config.max_width().checked_sub(shape.indent.width())),
..shape
}
}
};
let h_shape = shape.sub_width(prefix_width + suffix_width);
Some((h_shape, v_shape))
}
// Compute the tactic for the internals of a struct-lit-like thing.
pub fn struct_lit_tactic(h_shape: Option<Shape>,
context: &RewriteContext,
items: &[ListItem])
-> DefinitiveListTactic {
pub fn struct_lit_tactic(
h_shape: Option<Shape>,
context: &RewriteContext,
items: &[ListItem],
) -> DefinitiveListTactic {
if let Some(h_shape) = h_shape {
let mut prelim_tactic = match (context.config.struct_lit_style(), items.len()) {
(IndentStyle::Visual, 1) => ListTactic::HorizontalVertical,
@@ -568,10 +598,11 @@ pub fn struct_lit_tactic(h_shape: Option<Shape>,
// Given a tactic and possible shapes for horizontal and vertical layout,
// come up with the actual shape to use.
pub fn shape_for_tactic(tactic: DefinitiveListTactic,
h_shape: Option<Shape>,
v_shape: Shape)
-> Shape {
pub fn shape_for_tactic(
tactic: DefinitiveListTactic,
h_shape: Option<Shape>,
v_shape: Shape,
) -> Shape {
match tactic {
DefinitiveListTactic::Horizontal => h_shape.unwrap(),
_ => v_shape,
@@ -580,13 +611,14 @@ pub fn shape_for_tactic(tactic: DefinitiveListTactic,
// Create a ListFormatting object for formatting the internals of a
// struct-lit-like thing, that is a series of fields.
pub fn struct_lit_formatting<'a>(shape: Shape,
tactic: DefinitiveListTactic,
context: &'a RewriteContext,
force_no_trailing_comma: bool)
-> ListFormatting<'a> {
pub fn struct_lit_formatting<'a>(
shape: Shape,
tactic: DefinitiveListTactic,
context: &'a RewriteContext,
force_no_trailing_comma: bool,
) -> ListFormatting<'a> {
let ends_with_newline = context.config.struct_lit_style() != IndentStyle::Visual &&
tactic == DefinitiveListTactic::Vertical;
tactic == DefinitiveListTactic::Vertical;
ListFormatting {
tactic: tactic,
separator: ",",
+33 -27
View File
@@ -61,12 +61,13 @@ fn opener(&self) -> &'static str {
}
}
pub fn rewrite_macro(mac: &ast::Mac,
extra_ident: Option<ast::Ident>,
context: &RewriteContext,
shape: Shape,
position: MacroPosition)
-> Option<String> {
pub fn rewrite_macro(
mac: &ast::Mac,
extra_ident: Option<ast::Ident>,
context: &RewriteContext,
shape: Shape,
position: MacroPosition,
) -> Option<String> {
let mut context = &mut context.clone();
context.inside_macro = true;
if context.config.use_try_shorthand() {
@@ -191,24 +192,29 @@ pub fn rewrite_macro(mac: &ast::Mac,
} else {
("[", "]")
};
rewrite_pair(&*expr_vec[0],
&*expr_vec[1],
lbr,
"; ",
rbr,
context,
mac_shape)
.map(|s| format!("{}{}", macro_name, s))
rewrite_pair(
&*expr_vec[0],
&*expr_vec[1],
lbr,
"; ",
rbr,
context,
mac_shape,
).map(|s| format!("{}{}", macro_name, s))
} else {
// Format macro invocation as array literal.
let rewrite =
try_opt!(rewrite_array(expr_vec.iter().map(|x| &**x),
mk_sp(context
.codemap
.span_after(mac.span, original_style.opener()),
mac.span.hi - BytePos(1)),
context,
mac_shape));
let rewrite = try_opt!(rewrite_array(
expr_vec.iter().map(|x| &**x),
mk_sp(
context.codemap.span_after(
mac.span,
original_style.opener(),
),
mac.span.hi - BytePos(1),
),
context,
mac_shape,
));
Some(format!("{}{}", macro_name, rewrite))
}
@@ -229,11 +235,11 @@ pub fn convert_try_mac(mac: &ast::Mac, context: &RewriteContext) -> Option<ast::
let mut parser = new_parser_from_tts(context.parse_session, ts.trees().collect());
Some(ast::Expr {
id: ast::NodeId::new(0), // dummy value
node: ast::ExprKind::Try(try_opt!(parser.parse_expr().ok())),
span: mac.span, // incorrect span, but shouldn't matter too much
attrs: ThinVec::new(),
})
id: ast::NodeId::new(0), // dummy value
node: ast::ExprKind::Try(try_opt!(parser.parse_expr().ok())),
span: mac.span, // incorrect span, but shouldn't matter too much
attrs: ThinVec::new(),
})
} else {
None
}
+45 -33
View File
@@ -47,9 +47,11 @@ pub fn format_missing_no_indent(&mut self, end: BytePos) {
})
}
fn format_missing_inner<F: Fn(&mut FmtVisitor, &str, &str)>(&mut self,
end: BytePos,
process_last_snippet: F) {
fn format_missing_inner<F: Fn(&mut FmtVisitor, &str, &str)>(
&mut self,
end: BytePos,
process_last_snippet: F,
) {
let start = self.last_pos;
if start == end {
@@ -60,10 +62,12 @@ fn format_missing_inner<F: Fn(&mut FmtVisitor, &str, &str)>(&mut self,
return;
}
assert!(start < end,
"Request to format inverted span: {:?} to {:?}",
self.codemap.lookup_char_pos(start),
self.codemap.lookup_char_pos(end));
assert!(
start < end,
"Request to format inverted span: {:?} to {:?}",
self.codemap.lookup_char_pos(start),
self.codemap.lookup_char_pos(end)
);
self.last_pos = end;
let span = mk_sp(start, end);
@@ -72,7 +76,8 @@ fn format_missing_inner<F: Fn(&mut FmtVisitor, &str, &str)>(&mut self,
}
fn write_snippet<F>(&mut self, span: Span, process_last_snippet: F)
where F: Fn(&mut FmtVisitor, &str, &str)
where
F: Fn(&mut FmtVisitor, &str, &str),
{
// Get a snippet from the file start to the span's hi without allocating.
// We need it to determine what precedes the current comment. If the comment
@@ -92,13 +97,15 @@ fn write_snippet<F>(&mut self, span: Span, process_last_snippet: F)
self.write_snippet_inner(big_snippet, big_diff, &snippet, span, process_last_snippet);
}
fn write_snippet_inner<F>(&mut self,
big_snippet: &str,
big_diff: usize,
old_snippet: &str,
span: Span,
process_last_snippet: F)
where F: Fn(&mut FmtVisitor, &str, &str)
fn write_snippet_inner<F>(
&mut self,
big_snippet: &str,
big_diff: usize,
old_snippet: &str,
span: Span,
process_last_snippet: F,
) where
F: Fn(&mut FmtVisitor, &str, &str),
{
// Trim whitespace from the right hand side of each line.
// Annoyingly, the library functions for splitting by lines etc. are not
@@ -139,9 +146,12 @@ fn replace_chars(string: &str) -> String {
let subslice_num_lines = subslice.chars().filter(|c| *c == '\n').count();
if rewrite_next_comment &&
!self.config
.file_lines()
.intersects_range(file_name, cur_line, cur_line + subslice_num_lines) {
!self.config.file_lines().intersects_range(
file_name,
cur_line,
cur_line + subslice_num_lines,
)
{
rewrite_next_comment = false;
}
@@ -150,32 +160,34 @@ fn replace_chars(string: &str) -> String {
if let Some('{') = last_char {
self.buffer.push_str("\n");
}
self.buffer
.push_str(&self.block_indent.to_string(self.config));
self.buffer.push_str(
&self.block_indent.to_string(self.config),
);
} else {
self.buffer.push_str(" ");
}
let comment_width = ::std::cmp::min(self.config.comment_width(),
self.config.max_width() -
self.block_indent.width());
let comment_width = ::std::cmp::min(
self.config.comment_width(),
self.config.max_width() - self.block_indent.width(),
);
self.buffer.push_str(&rewrite_comment(subslice,
false,
Shape::legacy(comment_width,
self.block_indent),
self.config)
.unwrap());
self.buffer.push_str(&rewrite_comment(
subslice,
false,
Shape::legacy(comment_width, self.block_indent),
self.config,
).unwrap());
last_wspace = None;
line_start = offset + subslice.len();
if let Some('/') = subslice.chars().skip(1).next() {
// check that there are no contained block comments
if !subslice
.split('\n')
.map(|s| s.trim_left())
.any(|s| s.len() >= 2 && &s[0..2] == "/*") {
if !subslice.split('\n').map(|s| s.trim_left()).any(|s| {
s.len() >= 2 && &s[0..2] == "/*"
})
{
// Add a newline after line comments
self.buffer.push_str("\n");
}
+23 -17
View File
@@ -20,30 +20,35 @@
/// List all the files containing modules of a crate.
/// If a file is used twice in a crate, it appears only once.
pub fn list_files<'a>(krate: &'a ast::Crate,
codemap: &codemap::CodeMap)
-> BTreeMap<PathBuf, &'a ast::Mod> {
pub fn list_files<'a>(
krate: &'a ast::Crate,
codemap: &codemap::CodeMap,
) -> BTreeMap<PathBuf, &'a ast::Mod> {
let mut result = BTreeMap::new(); // Enforce file order determinism
let root_filename: PathBuf = codemap.span_to_filename(krate.span).into();
list_submodules(&krate.module,
root_filename.parent().unwrap(),
codemap,
&mut result);
list_submodules(
&krate.module,
root_filename.parent().unwrap(),
codemap,
&mut result,
);
result.insert(root_filename, &krate.module);
result
}
/// Recursively list all external modules included in a module.
fn list_submodules<'a>(module: &'a ast::Mod,
search_dir: &Path,
codemap: &codemap::CodeMap,
result: &mut BTreeMap<PathBuf, &'a ast::Mod>) {
fn list_submodules<'a>(
module: &'a ast::Mod,
search_dir: &Path,
codemap: &codemap::CodeMap,
result: &mut BTreeMap<PathBuf, &'a ast::Mod>,
) {
debug!("list_submodules: search_dir: {:?}", search_dir);
for item in &module.items {
if let ast::ItemKind::Mod(ref sub_mod) = item.node {
if !utils::contains_skip(&item.attrs) {
let is_internal = codemap.span_to_filename(item.span) ==
codemap.span_to_filename(sub_mod.inner);
codemap.span_to_filename(sub_mod.inner);
let dir_path = if is_internal {
search_dir.join(&item.ident.to_string())
} else {
@@ -59,11 +64,12 @@ fn list_submodules<'a>(module: &'a ast::Mod,
}
/// Find the file corresponding to an external mod
fn module_file(id: ast::Ident,
attrs: &[ast::Attribute],
dir_path: &Path,
codemap: &codemap::CodeMap)
-> PathBuf {
fn module_file(
id: ast::Ident,
attrs: &[ast::Attribute],
dir_path: &Path,
codemap: &codemap::CodeMap,
) -> PathBuf {
if let Some(path) = parser::Parser::submod_path_from_attr(attrs, dir_path) {
return path;
}
+111 -81
View File
@@ -39,12 +39,13 @@ fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option<String> {
let sub_pat = match *sub_pat {
Some(ref p) => {
// 3 - ` @ `.
let width =
try_opt!(shape.width.checked_sub(prefix.len() + mut_infix.len() +
id_str.len() +
3));
format!(" @ {}",
try_opt!(p.rewrite(context, Shape::legacy(width, shape.indent))))
let width = try_opt!(shape.width.checked_sub(
prefix.len() + mut_infix.len() + id_str.len() + 3,
));
format!(
" @ {}",
try_opt!(p.rewrite(context, Shape::legacy(width, shape.indent)))
)
}
None => "".to_owned(),
};
@@ -80,23 +81,23 @@ fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option<String> {
rewrite_path(context, PathContext::Expr, q_self.as_ref(), path, shape)
}
PatKind::TupleStruct(ref path, ref pat_vec, dotdot_pos) => {
let path_str =
try_opt!(rewrite_path(context, PathContext::Expr, None, path, shape));
rewrite_tuple_pat(pat_vec,
dotdot_pos,
Some(path_str),
self.span,
context,
shape)
let path_str = try_opt!(rewrite_path(context, PathContext::Expr, None, path, shape));
rewrite_tuple_pat(
pat_vec,
dotdot_pos,
Some(path_str),
self.span,
context,
shape,
)
}
PatKind::Lit(ref expr) => expr.rewrite(context, shape),
PatKind::Slice(ref prefix, ref slice_pat, ref suffix) => {
// Rewrite all the sub-patterns.
let prefix = prefix.iter().map(|p| p.rewrite(context, shape));
let slice_pat =
slice_pat
.as_ref()
.map(|p| Some(format!("{}..", try_opt!(p.rewrite(context, shape)))));
let slice_pat = slice_pat.as_ref().map(|p| {
Some(format!("{}..", try_opt!(p.rewrite(context, shape))))
});
let suffix = suffix.iter().map(|p| p.rewrite(context, shape));
// Munge them together.
@@ -119,24 +120,33 @@ fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option<String> {
}
// FIXME(#819) format pattern macros.
PatKind::Mac(..) => {
wrap_str(context.snippet(self.span),
context.config.max_width(),
shape)
wrap_str(
context.snippet(self.span),
context.config.max_width(),
shape,
)
}
}
}
}
fn rewrite_struct_pat(path: &ast::Path,
fields: &[codemap::Spanned<ast::FieldPat>],
elipses: bool,
span: Span,
context: &RewriteContext,
shape: Shape)
-> Option<String> {
fn rewrite_struct_pat(
path: &ast::Path,
fields: &[codemap::Spanned<ast::FieldPat>],
elipses: bool,
span: Span,
context: &RewriteContext,
shape: Shape,
) -> Option<String> {
// 2 = ` {`
let path_shape = try_opt!(shape.sub_width(2));
let path_str = try_opt!(rewrite_path(context, PathContext::Expr, None, path, path_shape));
let path_str = try_opt!(rewrite_path(
context,
PathContext::Expr,
None,
path,
path_shape,
));
if fields.len() == 0 && !elipses {
return Some(format!("{} {{}}", path_str));
@@ -145,17 +155,23 @@ fn rewrite_struct_pat(path: &ast::Path,
let (elipses_str, terminator) = if elipses { (", ..", "..") } else { ("", "}") };
// 3 = ` { `, 2 = ` }`.
let (h_shape, v_shape) =
try_opt!(struct_lit_shape(shape, context, path_str.len() + 3, elipses_str.len() + 2));
let (h_shape, v_shape) = try_opt!(struct_lit_shape(
shape,
context,
path_str.len() + 3,
elipses_str.len() + 2,
));
let items = itemize_list(context.codemap,
fields.iter(),
terminator,
|f| f.span.lo,
|f| f.span.hi,
|f| f.node.rewrite(context, v_shape),
context.codemap.span_after(span, "{"),
span.hi);
let items = itemize_list(
context.codemap,
fields.iter(),
terminator,
|f| f.span.lo,
|f| f.span.hi,
|f| f.node.rewrite(context, v_shape),
context.codemap.span_after(span, "{"),
span.hi,
);
let item_vec = items.collect::<Vec<_>>();
let tactic = struct_lit_tactic(h_shape, context, &item_vec);
@@ -189,14 +205,16 @@ fn rewrite_struct_pat(path: &ast::Path,
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))
(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)
@@ -211,9 +229,11 @@ fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option<String> {
if self.is_shorthand {
pat
} else {
wrap_str(format!("{}: {}", self.ident.to_string(), try_opt!(pat)),
context.config.max_width(),
shape)
wrap_str(
format!("{}: {}", self.ident.to_string(), try_opt!(pat)),
context.config.max_width(),
shape,
)
}
}
}
@@ -241,13 +261,14 @@ fn span(&self) -> Span {
}
}
fn rewrite_tuple_pat(pats: &[ptr::P<ast::Pat>],
dotdot_pos: Option<usize>,
path_str: Option<String>,
span: Span,
context: &RewriteContext,
shape: Shape)
-> Option<String> {
fn rewrite_tuple_pat(
pats: &[ptr::P<ast::Pat>],
dotdot_pos: Option<usize>,
path_str: Option<String>,
span: Span,
context: &RewriteContext,
shape: Shape,
) -> Option<String> {
let mut pat_vec: Vec<_> = pats.into_iter().map(|x| TuplePatField::Pat(x)).collect();
if let Some(pos) = dotdot_pos {
@@ -285,15 +306,16 @@ fn rewrite_tuple_pat(pats: &[ptr::P<ast::Pat>],
let nested_shape = try_opt!(shape.sub_width(path_len + if add_comma { 3 } else { 2 }));
// 1 = "(".len()
let nested_shape = nested_shape.visual_indent(path_len + 1);
let mut items: Vec<_> = itemize_list(context.codemap,
pat_vec.iter(),
if add_comma { ",)" } else { ")" },
|item| item.span().lo,
|item| item.span().hi,
|item| item.rewrite(context, nested_shape),
context.codemap.span_after(span, "("),
span.hi - BytePos(1))
.collect();
let mut items: Vec<_> = itemize_list(
context.codemap,
pat_vec.iter(),
if add_comma { ",)" } else { ")" },
|item| item.span().lo,
|item| item.span().hi,
|item| item.rewrite(context, nested_shape),
context.codemap.span_after(span, "("),
span.hi - BytePos(1),
).collect();
// Condense wildcard string suffix into a single ..
let wildcard_suffix_len = count_wildcard_suffix_len(&items);
@@ -305,24 +327,32 @@ fn rewrite_tuple_pat(pats: &[ptr::P<ast::Pat>],
let da_iter = items.into_iter().take(new_item_count);
try_opt!(format_item_list(da_iter, nested_shape, context.config))
} else {
try_opt!(format_item_list(items.into_iter(), nested_shape, context.config))
try_opt!(format_item_list(
items.into_iter(),
nested_shape,
context.config,
))
};
match path_str {
Some(path_str) => {
Some(if context.config.spaces_within_parens() {
format!("{}( {} )", path_str, list)
} else {
format!("{}({})", path_str, list)
})
Some(
if context.config.spaces_within_parens() {
format!("{}( {} )", path_str, list)
} else {
format!("{}({})", path_str, list)
},
)
}
None => {
let comma = if add_comma { "," } else { "" };
Some(if context.config.spaces_within_parens() {
format!("( {}{} )", list, comma)
} else {
format!("({}{})", list, comma)
})
Some(
if context.config.spaces_within_parens() {
format!("( {}{} )", list, comma)
} else {
format!("({}{})", list, comma)
},
)
}
}
}
@@ -331,10 +361,10 @@ fn count_wildcard_suffix_len(items: &[ListItem]) -> usize {
let mut suffix_len = 0;
for item in items.iter().rev().take_while(|i| match i.item {
Some(ref internal_string) if internal_string ==
"_" => true,
_ => false,
}) {
Some(ref internal_string) if internal_string == "_" => true,
_ => false,
})
{
suffix_len += 1;
if item.pre_comment.is_some() || item.post_comment.is_some() {
+10 -6
View File
@@ -86,7 +86,8 @@ pub fn make_diff(expected: &str, actual: &str, context_size: usize) -> Vec<Misma
}
pub fn print_diff<F>(diff: Vec<Mismatch>, get_section_title: F)
where F: Fn(u32) -> String
where
F: Fn(u32) -> String,
{
match term::stdout() {
Some(ref t) if isatty() && t.supports_color() => {
@@ -115,10 +116,12 @@ fn isatty() -> bool {
}
}
fn print_diff_fancy<F>(diff: Vec<Mismatch>,
get_section_title: F,
mut t: Box<term::Terminal<Output = io::Stdout>>)
where F: Fn(u32) -> String
fn print_diff_fancy<F>(
diff: Vec<Mismatch>,
get_section_title: F,
mut t: Box<term::Terminal<Output = io::Stdout>>,
) where
F: Fn(u32) -> String,
{
for mismatch in diff {
let title = get_section_title(mismatch.line_number);
@@ -145,7 +148,8 @@ fn print_diff_fancy<F>(diff: Vec<Mismatch>,
}
pub fn print_diff_basic<F>(diff: Vec<Mismatch>, get_section_title: F)
where F: Fn(u32) -> String
where
F: Fn(u32) -> String,
{
for mismatch in diff {
let title = get_section_title(mismatch.line_number);
+8 -5
View File
@@ -42,10 +42,12 @@ pub fn rewrite_string<'a>(orig: &str, fmt: &StringFormat<'a>) -> Option<String>
// `cur_start` is the position in `orig` of the start of the current line.
let mut cur_start = 0;
let mut result = String::with_capacity(stripped_str
.len()
.checked_next_power_of_two()
.unwrap_or(usize::max_value()));
let mut result = String::with_capacity(
stripped_str
.len()
.checked_next_power_of_two()
.unwrap_or(usize::max_value()),
);
result.push_str(fmt.opener);
let ender_length = fmt.line_end.len();
@@ -81,7 +83,8 @@ pub fn rewrite_string<'a>(orig: &str, fmt: &StringFormat<'a>) -> Option<String>
if cur_end < cur_start + MIN_STRING {
cur_end = cur_start + max_chars;
while !(punctuation.contains(graphemes[cur_end - 1]) ||
graphemes[cur_end - 1].trim().is_empty()) {
graphemes[cur_end - 1].trim().is_empty())
{
if cur_end >= graphemes.len() {
let line = &graphemes[cur_start..].join("");
result.push_str(line);
+1 -1
View File
@@ -54,7 +54,7 @@ pub fn add_diff(&mut self) {
pub fn has_no_errors(&self) -> bool {
!(self.has_operational_errors || self.has_parsing_errors || self.has_formatting_errors ||
self.has_diff)
self.has_diff)
}
pub fn add(&mut self, other: Summary) {
+265 -200
View File
@@ -34,20 +34,21 @@ pub enum PathContext {
}
// Does not wrap on simple segments.
pub fn rewrite_path(context: &RewriteContext,
path_context: PathContext,
qself: Option<&ast::QSelf>,
path: &ast::Path,
shape: Shape)
-> Option<String> {
pub fn rewrite_path(
context: &RewriteContext,
path_context: PathContext,
qself: Option<&ast::QSelf>,
path: &ast::Path,
shape: Shape,
) -> Option<String> {
let skip_count = qself.map_or(0, |x| x.position);
let mut result = if path.is_global() && qself.is_none() &&
path_context != PathContext::Import {
"::".to_owned()
} else {
String::new()
};
let mut result =
if path.is_global() && qself.is_none() && path_context != PathContext::Import {
"::".to_owned()
} else {
String::new()
};
let mut span_lo = path.span.lo;
@@ -70,13 +71,15 @@ pub fn rewrite_path(context: &RewriteContext,
// 3 = ">::".len()
let shape = try_opt!(try_opt!(shape.shrink_left(extra_offset)).sub_width(3));
result = try_opt!(rewrite_path_segments(PathContext::Type,
result,
path.segments.iter().take(skip_count),
span_lo,
path.span.hi,
context,
shape));
result = try_opt!(rewrite_path_segments(
PathContext::Type,
result,
path.segments.iter().take(skip_count),
span_lo,
path.span.hi,
context,
shape,
));
}
if context.config.spaces_within_angle_brackets() {
@@ -87,24 +90,28 @@ pub fn rewrite_path(context: &RewriteContext,
span_lo = qself.ty.span.hi + BytePos(1);
}
rewrite_path_segments(path_context,
result,
path.segments.iter().skip(skip_count),
span_lo,
path.span.hi,
context,
shape)
rewrite_path_segments(
path_context,
result,
path.segments.iter().skip(skip_count),
span_lo,
path.span.hi,
context,
shape,
)
}
fn rewrite_path_segments<'a, I>(path_context: PathContext,
mut buffer: String,
iter: I,
mut span_lo: BytePos,
span_hi: BytePos,
context: &RewriteContext,
shape: Shape)
-> Option<String>
where I: Iterator<Item = &'a ast::PathSegment>
fn rewrite_path_segments<'a, I>(
path_context: PathContext,
mut buffer: String,
iter: I,
mut span_lo: BytePos,
span_hi: BytePos,
context: &RewriteContext,
shape: Shape,
) -> Option<String>
where
I: Iterator<Item = &'a ast::PathSegment>,
{
let mut first = true;
let shape = shape.visual_indent(0);
@@ -122,12 +129,14 @@ fn rewrite_path_segments<'a, I>(path_context: PathContext,
let extra_offset = extra_offset(&buffer, shape);
let new_shape = try_opt!(shape.shrink_left(extra_offset));
let segment_string = try_opt!(rewrite_segment(path_context,
segment,
&mut span_lo,
span_hi,
context,
new_shape));
let segment_string = try_opt!(rewrite_segment(
path_context,
segment,
&mut span_lo,
span_hi,
context,
new_shape,
));
buffer.push_str(&segment_string);
}
@@ -163,10 +172,10 @@ fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option<String> {
TypeDensity::Compressed => format!("{}=", binding.ident),
};
let budget = try_opt!(shape.width.checked_sub(result.len()));
let rewrite = try_opt!(binding.ty.rewrite(context,
Shape::legacy(budget,
shape.indent +
result.len())));
let rewrite = try_opt!(binding.ty.rewrite(
context,
Shape::legacy(budget, shape.indent + result.len()),
));
result.push_str(&rewrite);
Some(result)
}
@@ -184,21 +193,22 @@ fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option<String> {
//
// When the segment contains a positive number of parameters, we update span_lo
// so that invariants described above will hold for the next segment.
fn rewrite_segment(path_context: PathContext,
segment: &ast::PathSegment,
span_lo: &mut BytePos,
span_hi: BytePos,
context: &RewriteContext,
shape: Shape)
-> Option<String> {
fn rewrite_segment(
path_context: PathContext,
segment: &ast::PathSegment,
span_lo: &mut BytePos,
span_hi: BytePos,
context: &RewriteContext,
shape: Shape,
) -> Option<String> {
let ident_len = segment.identifier.to_string().len();
let shape = try_opt!(shape.shrink_left(ident_len));
let params = if let Some(ref params) = segment.parameters {
match **params {
ast::PathParameters::AngleBracketed(ref data) if !data.lifetimes.is_empty() ||
!data.types.is_empty() ||
!data.bindings.is_empty() => {
!data.types.is_empty() ||
!data.bindings.is_empty() => {
let param_list = data.lifetimes
.iter()
.map(SegmentParam::LifeTime)
@@ -239,12 +249,14 @@ fn rewrite_segment(path_context: PathContext,
Some(ref ty) => FunctionRetTy::Ty(ty.clone()),
None => FunctionRetTy::Default(codemap::DUMMY_SP),
};
try_opt!(format_function_type(data.inputs.iter().map(|x| &**x),
&output,
false,
data.span,
context,
shape))
try_opt!(format_function_type(
data.inputs.iter().map(|x| &**x),
&output,
false,
data.span,
context,
shape,
))
}
_ => String::new(),
}
@@ -255,22 +267,25 @@ fn rewrite_segment(path_context: PathContext,
Some(format!("{}{}", segment.identifier, params))
}
fn format_function_type<'a, I>(inputs: I,
output: &FunctionRetTy,
variadic: bool,
span: Span,
context: &RewriteContext,
shape: Shape)
-> Option<String>
where I: ExactSizeIterator,
<I as Iterator>::Item: Deref,
<I::Item as Deref>::Target: Rewrite + Spanned + 'a
fn format_function_type<'a, I>(
inputs: I,
output: &FunctionRetTy,
variadic: bool,
span: Span,
context: &RewriteContext,
shape: Shape,
) -> Option<String>
where
I: ExactSizeIterator,
<I as Iterator>::Item: Deref,
<I::Item as Deref>::Target: Rewrite + Spanned + 'a,
{
// Code for handling variadics is somewhat duplicated for items, but they
// are different enough to need some serious refactoring to share code.
enum ArgumentKind<T>
where T: Deref,
<T as Deref>::Target: Rewrite + Spanned
where
T: Deref,
<T as Deref>::Target: Rewrite + Spanned,
{
Regular(Box<T>),
Variadic(BytePos),
@@ -288,31 +303,35 @@ enum ArgumentKind<T>
// 1 for (
let offset = shape.indent + 1;
let list_lo = context.codemap.span_after(span, "(");
let items = itemize_list(context.codemap,
// FIXME Would be nice to avoid this allocation,
// but I couldn't get the types to work out.
inputs
.map(|i| ArgumentKind::Regular(Box::new(i)))
.chain(variadic_arg),
")",
|arg| match *arg {
ArgumentKind::Regular(ref ty) => ty.span().lo,
ArgumentKind::Variadic(start) => start,
},
|arg| match *arg {
ArgumentKind::Regular(ref ty) => ty.span().hi,
ArgumentKind::Variadic(start) => start + BytePos(3),
},
|arg| match *arg {
ArgumentKind::Regular(ref ty) => {
ty.rewrite(context, Shape::legacy(budget, offset))
}
ArgumentKind::Variadic(_) => Some("...".to_owned()),
},
list_lo,
span.hi);
let items = itemize_list(
context.codemap,
// FIXME Would be nice to avoid this allocation,
// but I couldn't get the types to work out.
inputs
.map(|i| ArgumentKind::Regular(Box::new(i)))
.chain(variadic_arg),
")",
|arg| match *arg {
ArgumentKind::Regular(ref ty) => ty.span().lo,
ArgumentKind::Variadic(start) => start,
},
|arg| match *arg {
ArgumentKind::Regular(ref ty) => ty.span().hi,
ArgumentKind::Variadic(start) => start + BytePos(3),
},
|arg| match *arg {
ArgumentKind::Regular(ref ty) => ty.rewrite(context, Shape::legacy(budget, offset)),
ArgumentKind::Variadic(_) => Some("...".to_owned()),
},
list_lo,
span.hi,
);
let list_str = try_opt!(format_fn_args(items, Shape::legacy(budget, offset), context.config));
let list_str = try_opt!(format_fn_args(
items,
Shape::legacy(budget, offset),
context.config,
));
let output = match *output {
FunctionRetTy::Ty(ref ty) => {
@@ -329,16 +348,20 @@ enum ArgumentKind<T>
String::new()
};
Some(if context.config.spaces_within_parens() {
format!("( {} ){}{}", list_str, infix, output)
} else {
format!("({}){}{}", list_str, infix, output)
})
Some(
if context.config.spaces_within_parens() {
format!("( {} ){}{}", list_str, infix, output)
} else {
format!("({}){}{}", list_str, infix, output)
},
)
}
fn type_bound_colon(context: &RewriteContext) -> &'static str {
colon_spaces(context.config.space_before_bound(),
context.config.space_after_bound_colon())
colon_spaces(
context.config.space_before_bound(),
context.config.space_after_bound_colon(),
)
}
impl Rewrite for ast::WherePredicate {
@@ -356,11 +379,12 @@ fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option<String> {
let colon = type_bound_colon(context);
if !bound_lifetimes.is_empty() {
let lifetime_str: String = try_opt!(bound_lifetimes
.iter()
.map(|lt| lt.rewrite(context, shape))
.collect::<Option<Vec<_>>>())
.join(", ");
let lifetime_str: String = try_opt!(
bound_lifetimes
.iter()
.map(|lt| lt.rewrite(context, shape))
.collect::<Option<Vec<_>>>()
).join(", ");
// 6 = "for<> ".len()
let used_width = lifetime_str.len() + type_str.len() + colon.len() + 6;
@@ -373,11 +397,13 @@ fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option<String> {
let bounds_str = join_bounds(context, ty_shape, &bounds);
if context.config.spaces_within_angle_brackets() && lifetime_str.len() > 0 {
format!("for< {} > {}{}{}",
lifetime_str,
type_str,
colon,
bounds_str)
format!(
"for< {} > {}{}{}",
lifetime_str,
type_str,
colon,
bounds_str
)
} else {
format!("for<{}> {}{}{}", lifetime_str, type_str, colon, bounds_str)
}
@@ -402,7 +428,12 @@ fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option<String> {
ref bounds,
..
}) => {
try_opt!(rewrite_bounded_lifetime(lifetime, bounds.iter(), context, shape))
try_opt!(rewrite_bounded_lifetime(
lifetime,
bounds.iter(),
context,
shape,
))
}
ast::WherePredicate::EqPredicate(ast::WhereEqPredicate {
ref lhs_ty,
@@ -413,9 +444,10 @@ fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option<String> {
// 3 = " = ".len()
let used_width = 3 + lhs_ty_str.len();
let budget = try_opt!(shape.width.checked_sub(used_width));
let rhs_ty_str = try_opt!(rhs_ty.rewrite(context,
Shape::legacy(budget,
shape.indent + used_width)));
let rhs_ty_str = try_opt!(rhs_ty.rewrite(
context,
Shape::legacy(budget, shape.indent + used_width),
));
format!("{} = {}", lhs_ty_str, rhs_ty_str)
}
};
@@ -430,22 +462,26 @@ fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option<String> {
}
}
fn rewrite_bounded_lifetime<'b, I>(lt: &ast::Lifetime,
bounds: I,
context: &RewriteContext,
shape: Shape)
-> Option<String>
where I: ExactSizeIterator<Item = &'b ast::Lifetime>
fn rewrite_bounded_lifetime<'b, I>(
lt: &ast::Lifetime,
bounds: I,
context: &RewriteContext,
shape: Shape,
) -> Option<String>
where
I: ExactSizeIterator<Item = &'b ast::Lifetime>,
{
let result = try_opt!(lt.rewrite(context, shape));
if bounds.len() == 0 {
Some(result)
} else {
let appendix: Vec<_> = try_opt!(bounds
.into_iter()
.map(|b| b.rewrite(context, shape))
.collect());
let appendix: Vec<_> = try_opt!(
bounds
.into_iter()
.map(|b| b.rewrite(context, shape))
.collect()
);
let colon = type_bound_colon(context);
let overhead = last_line_width(&result) + colon.len();
let result = format!("{}{}{}",
@@ -464,9 +500,13 @@ fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option<String> {
}
ast::TyParamBound::TraitTyParamBound(ref tref, ast::TraitBoundModifier::Maybe) => {
let budget = try_opt!(shape.width.checked_sub(1));
Some(format!("?{}",
try_opt!(tref.rewrite(context,
Shape::legacy(budget, shape.indent + 1)))))
Some(format!(
"?{}",
try_opt!(tref.rewrite(
context,
Shape::legacy(budget, shape.indent + 1),
))
))
}
ast::TyParamBound::RegionTyParamBound(ref l) => l.rewrite(context, shape),
}
@@ -475,9 +515,11 @@ fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option<String> {
impl Rewrite for ast::Lifetime {
fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option<String> {
wrap_str(pprust::lifetime_to_string(self),
context.config.max_width(),
shape)
wrap_str(
pprust::lifetime_to_string(self),
context.config.max_width(),
shape,
)
}
}
@@ -514,8 +556,10 @@ fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option<String> {
};
result.push_str(eq_str);
let budget = try_opt!(shape.width.checked_sub(result.len()));
let rewrite = try_opt!(def.rewrite(context,
Shape::legacy(budget, shape.indent + result.len())));
let rewrite = try_opt!(def.rewrite(
context,
Shape::legacy(budget, shape.indent + result.len()),
));
result.push_str(&rewrite);
}
@@ -526,25 +570,31 @@ fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option<String> {
impl Rewrite for ast::PolyTraitRef {
fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option<String> {
if !self.bound_lifetimes.is_empty() {
let lifetime_str: String = try_opt!(self.bound_lifetimes
.iter()
.map(|lt| lt.rewrite(context, shape))
.collect::<Option<Vec<_>>>())
.join(", ");
let lifetime_str: String = try_opt!(
self.bound_lifetimes
.iter()
.map(|lt| lt.rewrite(context, shape))
.collect::<Option<Vec<_>>>()
).join(", ");
// 6 is "for<> ".len()
let extra_offset = lifetime_str.len() + 6;
let max_path_width = try_opt!(shape.width.checked_sub(extra_offset));
let path_str = try_opt!(self.trait_ref.rewrite(context,
Shape::legacy(max_path_width,
shape.indent +
extra_offset)));
let path_str = try_opt!(self.trait_ref.rewrite(
context,
Shape::legacy(
max_path_width,
shape.indent + extra_offset,
),
));
Some(if context.config.spaces_within_angle_brackets() && lifetime_str.len() > 0 {
format!("for< {} > {}", lifetime_str, path_str)
} else {
format!("for<{}> {}", lifetime_str, path_str)
})
Some(
if context.config.spaces_within_angle_brackets() && lifetime_str.len() > 0 {
format!("for< {} > {}", lifetime_str, path_str)
} else {
format!("for<{}> {}", lifetime_str, path_str)
},
)
} else {
self.trait_ref.rewrite(context, shape)
}
@@ -573,33 +623,39 @@ fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option<String> {
let mut_str = format_mutability(mt.mutbl);
let mut_len = mut_str.len();
Some(match *lifetime {
Some(ref lifetime) => {
let lt_budget = try_opt!(shape.width.checked_sub(2 + mut_len));
let lt_str = try_opt!(lifetime.rewrite(context,
Shape::legacy(lt_budget,
shape.indent + 2 +
mut_len)));
let lt_len = lt_str.len();
let budget = try_opt!(shape.width.checked_sub(2 + mut_len + lt_len));
format!("&{} {}{}",
lt_str,
mut_str,
try_opt!(mt.ty.rewrite(context,
Shape::legacy(budget,
shape.indent + 2 +
mut_len +
lt_len))))
}
None => {
let budget = try_opt!(shape.width.checked_sub(1 + mut_len));
format!("&{}{}",
mut_str,
try_opt!(mt.ty.rewrite(context,
Shape::legacy(budget,
shape.indent + 1 +
mut_len))))
}
})
Some(ref lifetime) => {
let lt_budget = try_opt!(shape.width.checked_sub(2 + mut_len));
let lt_str = try_opt!(lifetime.rewrite(
context,
Shape::legacy(lt_budget, shape.indent + 2 + mut_len),
));
let lt_len = lt_str.len();
let budget = try_opt!(shape.width.checked_sub(2 + mut_len + lt_len));
format!(
"&{} {}{}",
lt_str,
mut_str,
try_opt!(mt.ty.rewrite(
context,
Shape::legacy(
budget,
shape.indent + 2 + mut_len + lt_len,
),
))
)
}
None => {
let budget = try_opt!(shape.width.checked_sub(1 + mut_len));
format!(
"&{}{}",
mut_str,
try_opt!(mt.ty.rewrite(
context,
Shape::legacy(budget, shape.indent + 1 + mut_len),
))
)
}
})
}
// FIXME: we drop any comments here, even though it's a silly place to put
// comments.
@@ -607,10 +663,10 @@ fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option<String> {
let budget = try_opt!(shape.width.checked_sub(2));
ty.rewrite(context, Shape::legacy(budget, shape.indent + 1))
.map(|ty_str| if context.config.spaces_within_parens() {
format!("( {} )", ty_str)
} else {
format!("({})", ty_str)
})
format!("( {} )", ty_str)
} else {
format!("({})", ty_str)
})
}
ast::TyKind::Slice(ref ty) => {
let budget = if context.config.spaces_within_square_brackets() {
@@ -620,10 +676,10 @@ fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option<String> {
};
ty.rewrite(context, Shape::legacy(budget, shape.indent + 1))
.map(|ty_str| if context.config.spaces_within_square_brackets() {
format!("[ {} ]", ty_str)
} else {
format!("[{}]", ty_str)
})
format!("[ {} ]", ty_str)
} else {
format!("[{}]", ty_str)
})
}
ast::TyKind::Tup(ref items) => {
rewrite_tuple_type(context, items.iter().map(|x| &**x), self.span, shape)
@@ -649,8 +705,9 @@ fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option<String> {
ast::TyKind::Mac(..) => None,
ast::TyKind::ImplicitSelf => Some(String::from("")),
ast::TyKind::ImplTrait(ref it) => {
it.rewrite(context, shape)
.map(|it_str| format!("impl {}", it_str))
it.rewrite(context, shape).map(|it_str| {
format!("impl {}", it_str)
})
}
ast::TyKind::Err |
ast::TyKind::Typeof(..) => unreachable!(),
@@ -658,11 +715,12 @@ fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option<String> {
}
}
fn rewrite_bare_fn(bare_fn: &ast::BareFnTy,
span: Span,
context: &RewriteContext,
shape: Shape)
-> Option<String> {
fn rewrite_bare_fn(
bare_fn: &ast::BareFnTy,
span: Span,
context: &RewriteContext,
shape: Shape,
) -> Option<String> {
let mut result = String::with_capacity(128);
if !bare_fn.lifetimes.is_empty() {
@@ -675,8 +733,10 @@ fn rewrite_bare_fn(bare_fn: &ast::BareFnTy,
.lifetimes
.iter()
.map(|l| {
l.rewrite(context,
Shape::legacy(try_opt!(shape.width.checked_sub(6)), shape.indent + 4))
l.rewrite(
context,
Shape::legacy(try_opt!(shape.width.checked_sub(6)), shape.indent + 4),
)
})
.collect::<Option<Vec<_>>>()
).join(", "));
@@ -686,7 +746,10 @@ fn rewrite_bare_fn(bare_fn: &ast::BareFnTy,
result.push_str(::utils::format_unsafety(bare_fn.unsafety));
if bare_fn.abi != abi::Abi::Rust {
result.push_str(&::utils::format_abi(bare_fn.abi, context.config.force_explicit_abi()));
result.push_str(&::utils::format_abi(
bare_fn.abi,
context.config.force_explicit_abi(),
));
}
result.push_str("fn");
@@ -694,12 +757,14 @@ fn rewrite_bare_fn(bare_fn: &ast::BareFnTy,
let budget = try_opt!(shape.width.checked_sub(result.len()));
let indent = shape.indent + result.len();
let rewrite = try_opt!(format_function_type(bare_fn.decl.inputs.iter(),
&bare_fn.decl.output,
bare_fn.decl.variadic,
span,
context,
Shape::legacy(budget, indent)));
let rewrite = try_opt!(format_function_type(
bare_fn.decl.inputs.iter(),
&bare_fn.decl.output,
bare_fn.decl.variadic,
span,
context,
Shape::legacy(budget, indent),
));
result.push_str(&rewrite);
+10 -8
View File
@@ -44,9 +44,9 @@ pub fn format_visibility(vis: &Visibility) -> Cow<'static, str> {
let Path { ref segments, .. } = **path;
let mut segments_iter = segments.iter().map(|seg| seg.identifier.name.to_string());
if path.is_global() {
segments_iter
.next()
.expect("Non-global path in pub(restricted)?");
segments_iter.next().expect(
"Non-global path in pub(restricted)?",
);
}
let is_keyword = |s: &str| s == "self" || s == "super";
let path = segments_iter.collect::<Vec<_>>().join("::");
@@ -128,9 +128,9 @@ fn is_skip_nested(meta_item: &NestedMetaItem) -> bool {
#[inline]
pub fn contains_skip(attrs: &[Attribute]) -> bool {
attrs
.iter()
.any(|a| a.meta().map_or(false, |a| is_skip(&a)))
attrs.iter().any(
|a| a.meta().map_or(false, |a| is_skip(&a)),
)
}
// Find the end of a TyParam
@@ -333,7 +333,8 @@ pub fn wrap_str<S: AsRef<str>>(s: S, max_width: usize, shape: Shape) -> Option<S
// A special check for the last line, since the caller may
// place trailing characters on this line.
if snippet.lines().rev().next().unwrap().len() >
shape.indent.width() + shape.width {
shape.indent.width() + shape.width
{
return None;
}
}
@@ -355,7 +356,8 @@ fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option<String> {
// whether the `guess' was too high (Ordering::Less), or too low.
// This function is guaranteed to try to the hi value first.
pub fn binary_search<C, T>(mut lo: usize, mut hi: usize, callback: C) -> Option<T>
where C: Fn(usize) -> Result<T, Ordering>
where
C: Fn(usize) -> Result<T, Ordering>,
{
let mut middle = hi;
+270 -222
View File
@@ -36,16 +36,16 @@ fn is_use_item(item: &ast::Item) -> bool {
}
fn item_bound(item: &ast::Item) -> Span {
item.attrs
.iter()
.map(|attr| attr.span)
.fold(item.span, |bound, span| {
item.attrs.iter().map(|attr| attr.span).fold(
item.span,
|bound, span| {
Span {
lo: cmp::min(bound.lo, span.lo),
hi: cmp::max(bound.hi, span.hi),
ctxt: span.ctxt,
}
})
},
)
}
pub struct FmtVisitor<'a> {
@@ -62,14 +62,19 @@ pub struct FmtVisitor<'a> {
impl<'a> FmtVisitor<'a> {
fn visit_stmt(&mut self, stmt: &ast::Stmt) {
debug!("visit_stmt: {:?} {:?}",
self.codemap.lookup_char_pos(stmt.span.lo),
self.codemap.lookup_char_pos(stmt.span.hi));
debug!(
"visit_stmt: {:?} {:?}",
self.codemap.lookup_char_pos(stmt.span.lo),
self.codemap.lookup_char_pos(stmt.span.hi)
);
// FIXME(#434): Move this check to somewhere more central, eg Rewrite.
if !self.config
.file_lines()
.intersects(&self.codemap.lookup_line_range(stmt.span)) {
if !self.config.file_lines().intersects(
&self.codemap.lookup_line_range(
stmt.span,
),
)
{
return;
}
@@ -80,9 +85,10 @@ fn visit_stmt(&mut self, stmt: &ast::Stmt) {
ast::StmtKind::Local(..) |
ast::StmtKind::Expr(..) |
ast::StmtKind::Semi(..) => {
let rewrite =
stmt.rewrite(&self.get_context(),
Shape::indented(self.block_indent, self.config));
let rewrite = stmt.rewrite(
&self.get_context(),
Shape::indented(self.block_indent, self.config),
);
self.push_rewrite(stmt.span, rewrite);
}
ast::StmtKind::Mac(ref mac) => {
@@ -94,9 +100,11 @@ fn visit_stmt(&mut self, stmt: &ast::Stmt) {
}
pub fn visit_block(&mut self, b: &ast::Block) {
debug!("visit_block: {:?} {:?}",
self.codemap.lookup_char_pos(b.span.lo),
self.codemap.lookup_char_pos(b.span.hi));
debug!(
"visit_block: {:?} {:?}",
self.codemap.lookup_char_pos(b.span.lo),
self.codemap.lookup_char_pos(b.span.hi)
);
// Check if this block has braces.
let snippet = self.snippet(b.span);
@@ -157,42 +165,48 @@ fn close_block(&mut self, unindent_comment: bool) {
// Note that this only gets called for function definitions. Required methods
// on traits do not get handled here.
fn visit_fn(&mut self,
fk: visit::FnKind,
fd: &ast::FnDecl,
s: Span,
_: ast::NodeId,
defaultness: ast::Defaultness) {
fn visit_fn(
&mut self,
fk: visit::FnKind,
fd: &ast::FnDecl,
s: Span,
_: ast::NodeId,
defaultness: ast::Defaultness,
) {
let indent = self.block_indent;
let block;
let rewrite = match fk {
visit::FnKind::ItemFn(ident, generics, unsafety, constness, abi, vis, b) => {
block = b;
self.rewrite_fn(indent,
ident,
fd,
generics,
unsafety,
constness.node,
defaultness,
abi,
vis,
mk_sp(s.lo, b.span.lo),
&b)
self.rewrite_fn(
indent,
ident,
fd,
generics,
unsafety,
constness.node,
defaultness,
abi,
vis,
mk_sp(s.lo, b.span.lo),
&b,
)
}
visit::FnKind::Method(ident, sig, vis, b) => {
block = b;
self.rewrite_fn(indent,
ident,
fd,
&sig.generics,
sig.unsafety,
sig.constness.node,
defaultness,
sig.abi,
vis.unwrap_or(&ast::Visibility::Inherited),
mk_sp(s.lo, b.span.lo),
&b)
self.rewrite_fn(
indent,
ident,
fd,
&sig.generics,
sig.unsafety,
sig.constness.node,
defaultness,
sig.abi,
vis.unwrap_or(&ast::Visibility::Inherited),
mk_sp(s.lo, b.span.lo),
&b,
)
}
visit::FnKind::Closure(_) => unreachable!(),
};
@@ -267,23 +281,28 @@ pub fn visit_item(&mut self, item: &ast::Item) {
ast::ItemKind::Impl(..) => {
self.format_missing_with_indent(source!(self, item.span).lo);
let snippet = self.get_context().snippet(item.span);
let where_span_end =
snippet
.find_uncommented("{")
.map(|x| (BytePos(x as u32)) + source!(self, item.span).lo);
if let Some(impl_str) = format_impl(&self.get_context(),
item,
self.block_indent,
where_span_end) {
let where_span_end = snippet.find_uncommented("{").map(|x| {
(BytePos(x as u32)) + source!(self, item.span).lo
});
if let Some(impl_str) = format_impl(
&self.get_context(),
item,
self.block_indent,
where_span_end,
)
{
self.buffer.push_str(&impl_str);
self.last_pos = source!(self, item.span).hi;
}
}
ast::ItemKind::Trait(..) => {
self.format_missing_with_indent(item.span.lo);
if let Some(trait_str) = format_trait(&self.get_context(),
item,
self.block_indent) {
if let Some(trait_str) = format_trait(
&self.get_context(),
item,
self.block_indent,
)
{
self.buffer.push_str(&trait_str);
self.last_pos = source!(self, item.span).hi;
}
@@ -298,19 +317,20 @@ pub fn visit_item(&mut self, item: &ast::Item) {
let rewrite = {
let indent = self.block_indent;
let context = self.get_context();
::items::format_struct(&context,
"struct ",
item.ident,
&item.vis,
def,
Some(generics),
item.span,
indent,
None)
.map(|s| match *def {
ast::VariantData::Tuple(..) => s + ";",
_ => s,
})
::items::format_struct(
&context,
"struct ",
item.ident,
&item.vis,
def,
Some(generics),
item.span,
indent,
None,
).map(|s| match *def {
ast::VariantData::Tuple(..) => s + ";",
_ => s,
})
};
self.push_rewrite(item.span, rewrite);
}
@@ -331,53 +351,63 @@ pub fn visit_item(&mut self, item: &ast::Item) {
self.format_foreign_mod(foreign_mod, item.span);
}
ast::ItemKind::Static(ref ty, mutability, ref expr) => {
let rewrite = rewrite_static("static",
&item.vis,
item.ident,
ty,
mutability,
Some(expr),
self.block_indent,
item.span,
&self.get_context());
let rewrite = rewrite_static(
"static",
&item.vis,
item.ident,
ty,
mutability,
Some(expr),
self.block_indent,
item.span,
&self.get_context(),
);
self.push_rewrite(item.span, rewrite);
}
ast::ItemKind::Const(ref ty, ref expr) => {
let rewrite = rewrite_static("const",
&item.vis,
item.ident,
ty,
ast::Mutability::Immutable,
Some(expr),
self.block_indent,
item.span,
&self.get_context());
let rewrite = rewrite_static(
"const",
&item.vis,
item.ident,
ty,
ast::Mutability::Immutable,
Some(expr),
self.block_indent,
item.span,
&self.get_context(),
);
self.push_rewrite(item.span, rewrite);
}
ast::ItemKind::DefaultImpl(..) => {
// FIXME(#78): format impl definitions.
}
ast::ItemKind::Fn(ref decl, unsafety, constness, abi, ref generics, ref body) => {
self.visit_fn(visit::FnKind::ItemFn(item.ident,
generics,
unsafety,
constness,
abi,
&item.vis,
body),
decl,
item.span,
item.id,
ast::Defaultness::Final)
self.visit_fn(
visit::FnKind::ItemFn(
item.ident,
generics,
unsafety,
constness,
abi,
&item.vis,
body,
),
decl,
item.span,
item.id,
ast::Defaultness::Final,
)
}
ast::ItemKind::Ty(ref ty, ref generics) => {
let rewrite = rewrite_type_alias(&self.get_context(),
self.block_indent,
item.ident,
ty,
generics,
&item.vis,
item.span);
let rewrite = rewrite_type_alias(
&self.get_context(),
self.block_indent,
item.ident,
ty,
generics,
&item.vis,
item.span,
);
self.push_rewrite(item.span, rewrite);
}
ast::ItemKind::Union(..) => {
@@ -403,15 +433,17 @@ pub fn visit_trait_item(&mut self, ti: &ast::TraitItem) {
match ti.node {
ast::TraitItemKind::Const(ref ty, ref expr_opt) => {
let rewrite = rewrite_static("const",
&ast::Visibility::Inherited,
ti.ident,
ty,
ast::Mutability::Immutable,
expr_opt.as_ref(),
self.block_indent,
ti.span,
&self.get_context());
let rewrite = rewrite_static(
"const",
&ast::Visibility::Inherited,
ti.ident,
ty,
ast::Mutability::Immutable,
expr_opt.as_ref(),
self.block_indent,
ti.span,
&self.get_context(),
);
self.push_rewrite(ti.span, rewrite);
}
ast::TraitItemKind::Method(ref sig, None) => {
@@ -420,18 +452,22 @@ pub fn visit_trait_item(&mut self, ti: &ast::TraitItem) {
self.push_rewrite(ti.span, rewrite);
}
ast::TraitItemKind::Method(ref sig, Some(ref body)) => {
self.visit_fn(visit::FnKind::Method(ti.ident, sig, None, body),
&sig.decl,
ti.span,
ti.id,
ast::Defaultness::Final);
self.visit_fn(
visit::FnKind::Method(ti.ident, sig, None, body),
&sig.decl,
ti.span,
ti.id,
ast::Defaultness::Final,
);
}
ast::TraitItemKind::Type(ref type_param_bounds, ref type_default) => {
let rewrite = rewrite_associated_type(ti.ident,
type_default.as_ref(),
Some(type_param_bounds),
&self.get_context(),
self.block_indent);
let rewrite = rewrite_associated_type(
ti.ident,
type_default.as_ref(),
Some(type_param_bounds),
&self.get_context(),
self.block_indent,
);
self.push_rewrite(ti.span, rewrite);
}
ast::TraitItemKind::Macro(ref mac) => {
@@ -448,31 +484,37 @@ pub fn visit_impl_item(&mut self, ii: &ast::ImplItem) {
match ii.node {
ast::ImplItemKind::Method(ref sig, ref body) => {
self.visit_fn(visit::FnKind::Method(ii.ident, sig, Some(&ii.vis), body),
&sig.decl,
ii.span,
ii.id,
ii.defaultness);
self.visit_fn(
visit::FnKind::Method(ii.ident, sig, Some(&ii.vis), body),
&sig.decl,
ii.span,
ii.id,
ii.defaultness,
);
}
ast::ImplItemKind::Const(ref ty, ref expr) => {
let rewrite = rewrite_static("const",
&ii.vis,
ii.ident,
ty,
ast::Mutability::Immutable,
Some(expr),
self.block_indent,
ii.span,
&self.get_context());
let rewrite = rewrite_static(
"const",
&ii.vis,
ii.ident,
ty,
ast::Mutability::Immutable,
Some(expr),
self.block_indent,
ii.span,
&self.get_context(),
);
self.push_rewrite(ii.span, rewrite);
}
ast::ImplItemKind::Type(ref ty) => {
let rewrite = rewrite_associated_impl_type(ii.ident,
ii.defaultness,
Some(ty),
None,
&self.get_context(),
self.block_indent);
let rewrite = rewrite_associated_impl_type(
ii.ident,
ii.defaultness,
Some(ty),
None,
&self.get_context(),
self.block_indent,
);
self.push_rewrite(ii.span, rewrite);
}
ast::ImplItemKind::Macro(ref mac) => {
@@ -493,9 +535,10 @@ fn visit_mac(&mut self, mac: &ast::Mac, ident: Option<ast::Ident>, pos: MacroPos
fn push_rewrite(&mut self, span: Span, rewrite: Option<String>) {
self.format_missing_with_indent(source!(self, span).lo);
self.failed = match rewrite {
Some(ref s) if s.rewrite(&self.get_context(),
Shape::indented(self.block_indent, self.config))
.is_none() => true,
Some(ref s) if s.rewrite(
&self.get_context(),
Shape::indented(self.block_indent, self.config),
).is_none() => true,
None => true,
_ => self.failed,
};
@@ -521,9 +564,11 @@ pub fn snippet(&self, span: Span) -> String {
match self.codemap.span_to_snippet(span) {
Ok(s) => s,
Err(_) => {
println!("Couldn't make snippet for span {:?}->{:?}",
self.codemap.lookup_char_pos(span.lo),
self.codemap.lookup_char_pos(span.hi));
println!(
"Couldn't make snippet for span {:?}->{:?}",
self.codemap.lookup_char_pos(span.lo),
self.codemap.lookup_char_pos(span.hi)
);
"".to_owned()
}
}
@@ -548,8 +593,10 @@ pub fn visit_attrs(&mut self, attrs: &[ast::Attribute]) -> bool {
self.format_missing_with_indent(source!(self, first.span).lo);
let rewrite = outers
.rewrite(&self.get_context(),
Shape::indented(self.block_indent, self.config))
.rewrite(
&self.get_context(),
Shape::indented(self.block_indent, self.config),
)
.unwrap();
self.buffer.push_str(&rewrite);
let last = outers.last().unwrap();
@@ -570,13 +617,13 @@ fn walk_mod_items(&mut self, m: &ast::Mod) {
.iter()
.take_while(|ppi| {
is_use_item(&***ppi) &&
(!reorder_imports_in_group ||
{
let current = self.codemap.lookup_line_range(item_bound(&ppi));
let in_same_group = current.lo < last.hi + 2;
last = current;
in_same_group
})
(!reorder_imports_in_group ||
{
let current = self.codemap.lookup_line_range(item_bound(&ppi));
let in_same_group = current.lo < last.hi + 2;
last = current;
in_same_group
})
})
.count();
let (use_items, rest) = items_left.split_at(use_item_length);
@@ -597,7 +644,7 @@ fn format_mod(&mut self, m: &ast::Mod, vis: &ast::Visibility, s: Span, ident: as
let local_file_name = self.codemap.span_to_filename(s);
let inner_span = source!(self, m.inner);
let is_internal = !(inner_span.lo.0 == 0 && inner_span.hi.0 == 0) &&
local_file_name == self.codemap.span_to_filename(inner_span);
local_file_name == self.codemap.span_to_filename(inner_span);
self.buffer.push_str(&*utils::format_visibility(vis));
self.buffer.push_str("mod ");
@@ -658,66 +705,65 @@ fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option<String> {
impl Rewrite for ast::MetaItem {
fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option<String> {
Some(match self.node {
ast::MetaItemKind::Word => String::from(&*self.name.as_str()),
ast::MetaItemKind::List(ref list) => {
let name = self.name.as_str();
// 3 = `#[` and `(`, 2 = `]` and `)`
let item_shape = try_opt!(shape
.shrink_left(name.len() + 3)
.and_then(|s| s.sub_width(2)));
let items = itemize_list(context.codemap,
list.iter(),
")",
|nested_meta_item| nested_meta_item.span.lo,
|nested_meta_item| nested_meta_item.span.hi,
|nested_meta_item| {
nested_meta_item.rewrite(context, item_shape)
},
self.span.lo,
self.span.hi);
let item_vec = items.collect::<Vec<_>>();
let fmt = ListFormatting {
tactic: DefinitiveListTactic::Mixed,
separator: ",",
trailing_separator: SeparatorTactic::Never,
shape: item_shape,
ends_with_newline: false,
config: context.config,
};
format!("{}({})", name, try_opt!(write_list(&item_vec, &fmt)))
}
ast::MetaItemKind::NameValue(ref literal) => {
let name = self.name.as_str();
let value = context.snippet(literal.span);
if &*name == "doc" && value.starts_with("///") {
let doc_shape = Shape {
width: cmp::min(shape.width, context.config.comment_width())
.checked_sub(shape.indent.width())
.unwrap_or(0),
..shape
};
format!("{}",
try_opt!(rewrite_comment(&value,
false,
doc_shape,
context.config)))
} else {
format!("{} = {}", name, value)
}
}
})
ast::MetaItemKind::Word => String::from(&*self.name.as_str()),
ast::MetaItemKind::List(ref list) => {
let name = self.name.as_str();
// 3 = `#[` and `(`, 2 = `]` and `)`
let item_shape = try_opt!(shape.shrink_left(name.len() + 3).and_then(
|s| s.sub_width(2),
));
let items = itemize_list(
context.codemap,
list.iter(),
")",
|nested_meta_item| nested_meta_item.span.lo,
|nested_meta_item| nested_meta_item.span.hi,
|nested_meta_item| nested_meta_item.rewrite(context, item_shape),
self.span.lo,
self.span.hi,
);
let item_vec = items.collect::<Vec<_>>();
let fmt = ListFormatting {
tactic: DefinitiveListTactic::Mixed,
separator: ",",
trailing_separator: SeparatorTactic::Never,
shape: item_shape,
ends_with_newline: false,
config: context.config,
};
format!("{}({})", name, try_opt!(write_list(&item_vec, &fmt)))
}
ast::MetaItemKind::NameValue(ref literal) => {
let name = self.name.as_str();
let value = context.snippet(literal.span);
if &*name == "doc" && value.starts_with("///") {
let doc_shape = Shape {
width: cmp::min(shape.width, context.config.comment_width())
.checked_sub(shape.indent.width())
.unwrap_or(0),
..shape
};
format!(
"{}",
try_opt!(rewrite_comment(&value, false, doc_shape, context.config))
)
} else {
format!("{} = {}", name, value)
}
}
})
}
}
impl Rewrite for ast::Attribute {
fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option<String> {
try_opt!(self.meta())
.rewrite(context, shape)
.map(|rw| if rw.starts_with("///") {
rw
} else {
format!("#[{}]", rw)
})
try_opt!(self.meta()).rewrite(context, shape).map(|rw| {
if rw.starts_with("///") {
rw
} else {
format!("#[{}]", rw)
}
})
}
}
@@ -741,13 +787,15 @@ fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option<String> {
let multi_line = a_str.starts_with("//") && comment.matches('\n').count() > 1;
let comment = comment.trim();
if !comment.is_empty() {
let comment =
try_opt!(rewrite_comment(comment,
false,
Shape::legacy(context.config.comment_width() -
shape.indent.width(),
shape.indent),
context.config));
let comment = try_opt!(rewrite_comment(
comment,
false,
Shape::legacy(
context.config.comment_width() - shape.indent.width(),
shape.indent,
),
context.config,
));
result.push_str(&indent);
result.push_str(&comment);
result.push('\n');