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

2
Cargo.lock generated
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)",

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"

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,
})?;

View file

@ -74,7 +74,9 @@ impl 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 @@ impl CliOptions {
}
/// 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,
})
}

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(", "))

View file

@ -13,7 +13,8 @@ use config::WriteMode;
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
)?;
}
}
}

View file

@ -77,10 +77,12 @@ impl LineRangeUtils for CodeMap {
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(),

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 @@ impl<'a> CommentStyle<'a> {
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 @@ impl FullCodeCharKind {
}
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 @@ impl<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 @@ impl<'a> Iterator for UngroupedCommentCodeSlices<'a> {
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 @@ impl<'a> Iterator for CommentCodeSlices<'a> {
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 @@ impl<'a> Iterator for CommentCodeSlices<'a> {
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 @@ impl<'a> Iterator for CommentCodeSlices<'a> {
/// 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 @@ mod test {
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 @@ mod test {
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 @@ mod test {
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 @@ mod test {
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 @@ mod test {
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));

View file

@ -605,7 +605,9 @@ mod test {
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)
);
}
}

File diff suppressed because it is too large Load diff

View file

@ -52,7 +52,7 @@ impl Range {
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 @@ impl Range {
/// 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 @@ impl FileLines {
/// 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 @@ impl JsonSpan {
// 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 @@ impl<'de> ::serde::de::Deserialize<'de> for FileLines {
// `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 @@ mod test {
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))
);
}
}

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 @@ pub fn write_file<T>(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))
}

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 @@ impl Rewrite for ast::ViewPath {
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 @@ impl<'a> FmtVisitor<'a> {
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 @@ impl<'a> FmtVisitor<'a> {
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 @@ impl<'a> FmtVisitor<'a> {
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

View file

@ -172,11 +172,12 @@ impl BadIssueSeeker {
}
}
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 @@ impl BadIssueSeeker {
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 find_issue() {
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()
);
}

File diff suppressed because it is too large Load diff

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 @@ impl 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 @@ impl fmt::Display for FormatReport {
}
// 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();

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 @@ impl<'a, T, I, F1, F2, F3> Iterator for ListItems<'a, I, F1, F2, F3>
.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 @@ impl<'a, T, I, F1, F2, F3> Iterator for ListItems<'a, I, F1, F2, F3>
(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 @@ impl<'a, T, I, F1, F2, F3> Iterator for ListItems<'a, I, F1, F2, F3>
}
}
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 @@ impl<'a, T, I, F1, F2, F3> Iterator for ListItems<'a, I, F1, F2, F3>
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 @@ impl<'a, T, I, F1, F2, F3> Iterator for ListItems<'a, I, F1, F2, F3>
}
// 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: ",",

View file

@ -61,12 +61,13 @@ impl MacroStyle {
}
}
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
}

View file

@ -47,9 +47,11 @@ impl<'a> FmtVisitor<'a> {
})
}
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 @@ impl<'a> FmtVisitor<'a> {
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 @@ impl<'a> FmtVisitor<'a> {
}
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 @@ impl<'a> FmtVisitor<'a> {
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 @@ impl<'a> FmtVisitor<'a> {
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 @@ impl<'a> FmtVisitor<'a> {
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");
}

View file

@ -20,30 +20,35 @@ use syntax::parse::parser;
/// 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;
}

View file

@ -39,12 +39,13 @@ impl Rewrite for Pat {
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 @@ impl Rewrite for Pat {
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 @@ impl Rewrite for Pat {
}
// 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 @@ impl Rewrite for FieldPat {
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 @@ impl<'a> Spanned for TuplePatField<'a> {
}
}
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() {

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 @@ pub fn print_diff<F>(diff: Vec<Mismatch>, get_section_title: F)
}
}
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);

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);

View file

@ -54,7 +54,7 @@ impl Summary {
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) {

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 @@ impl<'a> Rewrite for SegmentParam<'a> {
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 @@ impl<'a> Rewrite for SegmentParam<'a> {
//
// 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 @@ fn format_function_type<'a, I>(inputs: I,
// 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 @@ fn format_function_type<'a, I>(inputs: I,
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 @@ impl Rewrite for ast::WherePredicate {
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 @@ impl Rewrite for ast::WherePredicate {
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 @@ impl Rewrite for ast::WherePredicate {
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 @@ impl Rewrite for ast::WherePredicate {
// 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 @@ impl Rewrite for ast::LifetimeDef {
}
}
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 @@ impl Rewrite for ast::TyParamBound {
}
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 @@ impl Rewrite for ast::TyParamBound {
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 @@ impl Rewrite for ast::TyParam {
};
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 @@ impl Rewrite for ast::TyParam {
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 @@ impl Rewrite for ast::Ty {
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 @@ impl Rewrite for ast::Ty {
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 @@ impl Rewrite for ast::Ty {
};
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 @@ impl Rewrite for ast::Ty {
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 @@ impl Rewrite for ast::Ty {
}
}
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);

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 @@ impl Rewrite for 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;

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 @@ impl<'a> FmtVisitor<'a> {
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 @@ impl<'a> FmtVisitor<'a> {
}
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 @@ impl<'a> FmtVisitor<'a> {
// 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 @@ impl<'a> FmtVisitor<'a> {
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 @@ impl<'a> FmtVisitor<'a> {
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 @@ impl<'a> FmtVisitor<'a> {
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 @@ impl<'a> FmtVisitor<'a> {
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 @@ impl<'a> FmtVisitor<'a> {
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 @@ impl<'a> FmtVisitor<'a> {
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 @@ impl<'a> FmtVisitor<'a> {
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 @@ impl<'a> FmtVisitor<'a> {
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 @@ impl<'a> FmtVisitor<'a> {
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 @@ impl<'a> FmtVisitor<'a> {
.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 @@ impl<'a> FmtVisitor<'a> {
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 @@ impl Rewrite for ast::NestedMetaItem {
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 @@ impl<'a> Rewrite for [ast::Attribute] {
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');