Reformat source code using new defaults
This commit is contained in:
parent
32e882789b
commit
1f512948a0
27 changed files with 3224 additions and 2447 deletions
2
Cargo.lock
generated
2
Cargo.lock
generated
|
@ -1,6 +1,6 @@
|
||||||
[root]
|
[root]
|
||||||
name = "rustfmt"
|
name = "rustfmt"
|
||||||
version = "0.8.5"
|
version = "0.9.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"diff 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
"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)",
|
"env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
[package]
|
[package]
|
||||||
|
|
||||||
name = "rustfmt"
|
name = "rustfmt"
|
||||||
version = "0.9"
|
version = "0.9.0"
|
||||||
authors = ["Nicholas Cameron <ncameron@mozilla.com>", "The Rustfmt developers"]
|
authors = ["Nicholas Cameron <ncameron@mozilla.com>", "The Rustfmt developers"]
|
||||||
description = "Tool to find and fix Rust formatting issues"
|
description = "Tool to find and fix Rust formatting issues"
|
||||||
repository = "https://github.com/rust-lang-nursery/rustfmt"
|
repository = "https://github.com/rust-lang-nursery/rustfmt"
|
||||||
|
|
|
@ -42,10 +42,12 @@ fn execute() -> i32 {
|
||||||
opts.optflag("h", "help", "show this message");
|
opts.optflag("h", "help", "show this message");
|
||||||
opts.optflag("q", "quiet", "no output printed to stdout");
|
opts.optflag("q", "quiet", "no output printed to stdout");
|
||||||
opts.optflag("v", "verbose", "use verbose output");
|
opts.optflag("v", "verbose", "use verbose output");
|
||||||
opts.optmulti("p",
|
opts.optmulti(
|
||||||
"package",
|
"p",
|
||||||
"specify package to format (only usable in workspaces)",
|
"package",
|
||||||
"<package>");
|
"specify package to format (only usable in workspaces)",
|
||||||
|
"<package>",
|
||||||
|
);
|
||||||
opts.optflag("", "all", "format all packages (only usable in workspaces)");
|
opts.optflag("", "all", "format all packages (only usable in workspaces)");
|
||||||
|
|
||||||
let matches = match opts.parse(env::args().skip(1).take_while(|a| a != "--")) {
|
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) {
|
fn print_usage(opts: &Options, reason: &str) {
|
||||||
let msg = format!("{}\nusage: cargo fmt [options]", reason);
|
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.",
|
Arguments after `--` are passed to rustfmt.",
|
||||||
opts.usage(&msg));
|
opts.usage(&msg)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq)]
|
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||||
|
@ -102,9 +106,10 @@ pub enum Verbosity {
|
||||||
Quiet,
|
Quiet,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn format_crate(verbosity: Verbosity,
|
fn format_crate(
|
||||||
workspace_hitlist: WorkspaceHitlist)
|
verbosity: Verbosity,
|
||||||
-> Result<ExitStatus, std::io::Error> {
|
workspace_hitlist: WorkspaceHitlist,
|
||||||
|
) -> Result<ExitStatus, std::io::Error> {
|
||||||
let targets = get_targets(workspace_hitlist)?;
|
let targets = get_targets(workspace_hitlist)?;
|
||||||
|
|
||||||
// Currently only bin and lib files get formatted
|
// Currently only bin and lib files get formatted
|
||||||
|
@ -112,8 +117,8 @@ fn format_crate(verbosity: Verbosity,
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.filter(|t| t.kind.should_format())
|
.filter(|t| t.kind.should_format())
|
||||||
.inspect(|t| if verbosity == Verbosity::Verbose {
|
.inspect(|t| if verbosity == Verbosity::Verbose {
|
||||||
println!("[{:?}] {:?}", t.kind, t.path)
|
println!("[{:?}] {:?}", t.kind, t.path)
|
||||||
})
|
})
|
||||||
.map(|t| t.path)
|
.map(|t| t.path)
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
|
@ -194,8 +199,10 @@ fn get_targets(workspace_hitlist: WorkspaceHitlist) -> Result<Vec<Target>, std::
|
||||||
|
|
||||||
return Ok(targets);
|
return Ok(targets);
|
||||||
}
|
}
|
||||||
return Err(std::io::Error::new(std::io::ErrorKind::NotFound,
|
return Err(std::io::Error::new(
|
||||||
str::from_utf8(&output.stderr).unwrap()));
|
std::io::ErrorKind::NotFound,
|
||||||
|
str::from_utf8(&output.stderr).unwrap(),
|
||||||
|
));
|
||||||
}
|
}
|
||||||
// This happens when cargo-fmt is not used inside a crate or
|
// This happens when cargo-fmt is not used inside a crate or
|
||||||
// is used inside a workspace.
|
// is used inside a workspace.
|
||||||
|
@ -221,18 +228,22 @@ fn get_targets(workspace_hitlist: WorkspaceHitlist) -> Result<Vec<Target>, std::
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.filter(|member| if workspace_hitlist == WorkspaceHitlist::All {
|
.filter(|member| if workspace_hitlist == WorkspaceHitlist::All {
|
||||||
true
|
true
|
||||||
} else {
|
} else {
|
||||||
let member_obj = member.as_object().unwrap();
|
let member_obj = member.as_object().unwrap();
|
||||||
let member_name = member_obj.get("name").unwrap().as_str().unwrap();
|
let member_name = member_obj.get("name").unwrap().as_str().unwrap();
|
||||||
hitlist.take(&member_name.to_string()).is_some()
|
hitlist.take(&member_name.to_string()).is_some()
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
if hitlist.len() != 0 {
|
if hitlist.len() != 0 {
|
||||||
// Mimick cargo of only outputting one <package> spec.
|
// Mimick cargo of only outputting one <package> spec.
|
||||||
return Err(std::io::Error::new(std::io::ErrorKind::InvalidInput,
|
return Err(std::io::Error::new(
|
||||||
format!("package `{}` is not a member of the workspace",
|
std::io::ErrorKind::InvalidInput,
|
||||||
hitlist.iter().next().unwrap())));
|
format!(
|
||||||
|
"package `{}` is not a member of the workspace",
|
||||||
|
hitlist.iter().next().unwrap()
|
||||||
|
),
|
||||||
|
));
|
||||||
}
|
}
|
||||||
for member in members {
|
for member in members {
|
||||||
let member_obj = member.as_object().unwrap();
|
let member_obj = member.as_object().unwrap();
|
||||||
|
@ -243,8 +254,10 @@ fn get_targets(workspace_hitlist: WorkspaceHitlist) -> Result<Vec<Target>, std::
|
||||||
}
|
}
|
||||||
return Ok(targets);
|
return Ok(targets);
|
||||||
}
|
}
|
||||||
Err(std::io::Error::new(std::io::ErrorKind::NotFound,
|
Err(std::io::Error::new(
|
||||||
str::from_utf8(&output.stderr).unwrap()))
|
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],
|
fn format_files(
|
||||||
fmt_args: &[String],
|
files: &[PathBuf],
|
||||||
verbosity: Verbosity)
|
fmt_args: &[String],
|
||||||
-> Result<ExitStatus, std::io::Error> {
|
verbosity: Verbosity,
|
||||||
|
) -> Result<ExitStatus, std::io::Error> {
|
||||||
let stdout = if verbosity == Verbosity::Quiet {
|
let stdout = if verbosity == Verbosity::Quiet {
|
||||||
std::process::Stdio::null()
|
std::process::Stdio::null()
|
||||||
} else {
|
} else {
|
||||||
|
@ -294,8 +308,10 @@ fn format_files(files: &[PathBuf],
|
||||||
.spawn()
|
.spawn()
|
||||||
.map_err(|e| match e.kind() {
|
.map_err(|e| match e.kind() {
|
||||||
std::io::ErrorKind::NotFound => {
|
std::io::ErrorKind::NotFound => {
|
||||||
std::io::Error::new(std::io::ErrorKind::Other,
|
std::io::Error::new(
|
||||||
"Could not run rustfmt, please make sure it is in your PATH.")
|
std::io::ErrorKind::Other,
|
||||||
|
"Could not run rustfmt, please make sure it is in your PATH.",
|
||||||
|
)
|
||||||
}
|
}
|
||||||
_ => e,
|
_ => e,
|
||||||
})?;
|
})?;
|
||||||
|
|
|
@ -74,7 +74,9 @@ impl CliOptions {
|
||||||
if let Ok(write_mode) = WriteMode::from_str(write_mode) {
|
if let Ok(write_mode) = WriteMode::from_str(write_mode) {
|
||||||
options.write_mode = Some(write_mode);
|
options.write_mode = Some(write_mode);
|
||||||
} else {
|
} 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
|
/// 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>,
|
fn match_cli_path_or_file(
|
||||||
input_file: &Path)
|
config_path: Option<PathBuf>,
|
||||||
-> FmtResult<(Config, Option<PathBuf>)> {
|
input_file: &Path,
|
||||||
|
) -> FmtResult<(Config, Option<PathBuf>)> {
|
||||||
|
|
||||||
if let Some(config_file) = config_path {
|
if let Some(config_file) = config_path {
|
||||||
let toml = Config::from_toml_path(config_file.as_ref())?;
|
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("h", "help", "show this message");
|
||||||
opts.optflag("V", "version", "show version information");
|
opts.optflag("V", "version", "show version information");
|
||||||
opts.optflag("v", "verbose", "print verbose output");
|
opts.optflag("v", "verbose", "print verbose output");
|
||||||
opts.optopt("",
|
opts.optopt(
|
||||||
"write-mode",
|
"",
|
||||||
"mode to write in (not usable when piping from stdin)",
|
"write-mode",
|
||||||
"[replace|overwrite|display|diff|coverage|checkstyle]");
|
"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("", "skip-children", "don't reformat child modules");
|
||||||
|
|
||||||
opts.optflag("",
|
opts.optflag(
|
||||||
"config-help",
|
"",
|
||||||
"show details of rustfmt configuration options");
|
"config-help",
|
||||||
opts.optopt("",
|
"show details of rustfmt configuration options",
|
||||||
"dump-default-config",
|
);
|
||||||
"Dumps the default configuration to a file and exits.",
|
opts.optopt(
|
||||||
"PATH");
|
"",
|
||||||
opts.optopt("",
|
"dump-default-config",
|
||||||
"dump-minimal-config",
|
"Dumps the default configuration to a file and exits.",
|
||||||
"Dumps configuration options that were checked during formatting to a file.",
|
"PATH",
|
||||||
"PATH");
|
);
|
||||||
opts.optopt("",
|
opts.optopt(
|
||||||
"config-path",
|
"",
|
||||||
"Recursively searches the given path for the rustfmt.toml config file. If not \
|
"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",
|
found reverts to the input file path",
|
||||||
"[Path for the configuration file]");
|
"[Path for the configuration file]",
|
||||||
opts.optopt("",
|
);
|
||||||
"file-lines",
|
opts.optopt(
|
||||||
"Format specified line ranges. See README for more detail on the JSON format.",
|
"",
|
||||||
"JSON");
|
"file-lines",
|
||||||
|
"Format specified line ranges. See README for more detail on the JSON format.",
|
||||||
|
"JSON",
|
||||||
|
);
|
||||||
|
|
||||||
opts
|
opts
|
||||||
}
|
}
|
||||||
|
@ -167,8 +182,8 @@ fn execute(opts: &Options) -> FmtResult<Summary> {
|
||||||
}
|
}
|
||||||
Operation::Stdin { input, config_path } => {
|
Operation::Stdin { input, config_path } => {
|
||||||
// try to read config from local directory
|
// try to read config from local directory
|
||||||
let (mut config, _) = match_cli_path_or_file(config_path,
|
let (mut config, _) =
|
||||||
&env::current_dir().unwrap())?;
|
match_cli_path_or_file(config_path, &env::current_dir().unwrap())?;
|
||||||
|
|
||||||
// write_mode is always Plain for Stdin.
|
// write_mode is always Plain for Stdin.
|
||||||
config.set().write_mode(WriteMode::Plain);
|
config.set().write_mode(WriteMode::Plain);
|
||||||
|
@ -225,9 +240,11 @@ fn execute(opts: &Options) -> FmtResult<Summary> {
|
||||||
Config::from_resolved_toml_path(file.parent().unwrap())?;
|
Config::from_resolved_toml_path(file.parent().unwrap())?;
|
||||||
if options.verbose {
|
if options.verbose {
|
||||||
if let Some(path) = path_tmp.as_ref() {
|
if let Some(path) = path_tmp.as_ref() {
|
||||||
println!("Using rustfmt config file {} for {}",
|
println!(
|
||||||
path.display(),
|
"Using rustfmt config file {} for {}",
|
||||||
file.display());
|
path.display(),
|
||||||
|
file.display()
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
config = config_tmp;
|
config = config_tmp;
|
||||||
|
@ -288,16 +305,20 @@ fn main() {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn print_usage(opts: &Options, reason: &str) {
|
fn print_usage(opts: &Options, reason: &str) {
|
||||||
let reason = format!("{}\n\nusage: {} [options] <file>...",
|
let reason = format!(
|
||||||
reason,
|
"{}\n\nusage: {} [options] <file>...",
|
||||||
env::args_os().next().unwrap().to_string_lossy());
|
reason,
|
||||||
|
env::args_os().next().unwrap().to_string_lossy()
|
||||||
|
);
|
||||||
println!("{}", opts.usage(&reason));
|
println!("{}", opts.usage(&reason));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn print_version() {
|
fn print_version() {
|
||||||
println!("{}-nightly{}",
|
println!(
|
||||||
env!("CARGO_PKG_VERSION"),
|
"{}-nightly{}",
|
||||||
include_str!(concat!(env!("OUT_DIR"), "/commit-info.txt")))
|
env!("CARGO_PKG_VERSION"),
|
||||||
|
include_str!(concat!(env!("OUT_DIR"), "/commit-info.txt"))
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn determine_operation(matches: &Matches) -> FmtResult<Operation> {
|
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> {
|
let config_path_not_found = |path: &str| -> FmtResult<Operation> {
|
||||||
Err(FmtError::from(format!("Error: unable to find a config file for the given path: `{}`",
|
Err(FmtError::from(format!(
|
||||||
path)))
|
"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.
|
// 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)?;
|
io::stdin().read_to_string(&mut buffer)?;
|
||||||
|
|
||||||
return Ok(Operation::Stdin {
|
return Ok(Operation::Stdin {
|
||||||
input: buffer,
|
input: buffer,
|
||||||
config_path: config_path,
|
config_path: config_path,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
let files: Vec<_> = matches
|
let files: Vec<_> = matches
|
||||||
.free
|
.free
|
||||||
.iter()
|
.iter()
|
||||||
.map(|s| {
|
.map(|s| {
|
||||||
let p = PathBuf::from(s);
|
let p = PathBuf::from(s);
|
||||||
// we will do comparison later, so here tries to canonicalize first
|
// we will do comparison later, so here tries to canonicalize first
|
||||||
// to get the expected behavior.
|
// to get the expected behavior.
|
||||||
p.canonicalize().unwrap_or(p)
|
p.canonicalize().unwrap_or(p)
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
Ok(Operation::Format {
|
Ok(Operation::Format {
|
||||||
files: files,
|
files: files,
|
||||||
config_path: config_path,
|
config_path: config_path,
|
||||||
minimal_config_path: minimal_config_path,
|
minimal_config_path: minimal_config_path,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
280
src/chains.rs
280
src/chains.rs
|
@ -101,9 +101,9 @@ pub fn rewrite_chain(expr: &ast::Expr, context: &RewriteContext, shape: Shape) -
|
||||||
let trailing_try_num = subexpr_list
|
let trailing_try_num = subexpr_list
|
||||||
.iter()
|
.iter()
|
||||||
.take_while(|e| match e.node {
|
.take_while(|e| match e.node {
|
||||||
ast::ExprKind::Try(..) => true,
|
ast::ExprKind::Try(..) => true,
|
||||||
_ => false,
|
_ => false,
|
||||||
})
|
})
|
||||||
.count();
|
.count();
|
||||||
|
|
||||||
// Parent is the first item in the chain, e.g., `foo` in `foo.bar.baz()`.
|
// 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 {
|
} else {
|
||||||
chain_indent(context, shape.add_offset(parent_rewrite.len()))
|
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) {
|
} else if is_block_expr(context, &parent, &parent_rewrite) {
|
||||||
match context.config.chain_indent() {
|
match context.config.chain_indent() {
|
||||||
// Try to put the first child on the same line with parent's last line
|
// 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 {
|
} else {
|
||||||
other_child_shape
|
other_child_shape
|
||||||
};
|
};
|
||||||
debug!("child_shapes {:?} {:?}",
|
debug!(
|
||||||
first_child_shape,
|
"child_shapes {:?} {:?}",
|
||||||
other_child_shape);
|
first_child_shape,
|
||||||
|
other_child_shape
|
||||||
|
);
|
||||||
|
|
||||||
let child_shape_iter =
|
let child_shape_iter = Some(first_child_shape).into_iter().chain(
|
||||||
Some(first_child_shape)
|
::std::iter::repeat(
|
||||||
.into_iter()
|
other_child_shape,
|
||||||
.chain(::std::iter::repeat(other_child_shape).take(subexpr_list.len() - 1));
|
).take(
|
||||||
|
subexpr_list.len() - 1,
|
||||||
|
),
|
||||||
|
);
|
||||||
let iter = subexpr_list.iter().rev().zip(child_shape_iter);
|
let iter = subexpr_list.iter().rev().zip(child_shape_iter);
|
||||||
let mut rewrites = try_opt!(iter.map(|(e, shape)| {
|
let mut rewrites = try_opt!(
|
||||||
rewrite_chain_subexpr(e, total_span, context, shape)
|
iter.map(|(e, shape)| {
|
||||||
}).collect::<Option<Vec<_>>>());
|
rewrite_chain_subexpr(e, total_span, context, shape)
|
||||||
|
}).collect::<Option<Vec<_>>>()
|
||||||
|
);
|
||||||
|
|
||||||
// Total of all items excluding the last.
|
// Total of all items excluding the last.
|
||||||
let last_non_try_index = rewrites.len() - (1 + trailing_try_num);
|
let last_non_try_index = rewrites.len() - (1 + trailing_try_num);
|
||||||
let almost_total = rewrites[..last_non_try_index]
|
let almost_total = rewrites[..last_non_try_index].iter().fold(0, |a, b| {
|
||||||
.iter()
|
a + first_line_width(b)
|
||||||
.fold(0, |a, b| a + first_line_width(b)) + parent_rewrite.len();
|
}) + parent_rewrite.len();
|
||||||
let one_line_len = rewrites.iter().fold(0, |a, r| a + first_line_width(r)) +
|
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 one_line_budget = min(shape.width, context.config.chain_one_line_max());
|
||||||
let veto_single_line = if one_line_len > one_line_budget {
|
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 {
|
if fits_single_line {
|
||||||
fits_single_line = match expr.node {
|
fits_single_line = match expr.node {
|
||||||
ref e @ ast::ExprKind::MethodCall(..) => {
|
ref e @ ast::ExprKind::MethodCall(..) => {
|
||||||
if rewrite_method_call_with_overflow(e,
|
if rewrite_method_call_with_overflow(
|
||||||
&mut last[0],
|
e,
|
||||||
almost_total,
|
&mut last[0],
|
||||||
total_span,
|
almost_total,
|
||||||
context,
|
total_span,
|
||||||
shape) {
|
context,
|
||||||
|
shape,
|
||||||
|
)
|
||||||
|
{
|
||||||
// If the first line of the last method does not fit into a single line
|
// If the first line of the last method does not fit into a single line
|
||||||
// after the others, allow new lines.
|
// after the others, allow new lines.
|
||||||
almost_total + first_line_width(&last[0]) < context.config.max_width()
|
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,
|
width: one_line_budget,
|
||||||
..parent_shape
|
..parent_shape
|
||||||
};
|
};
|
||||||
fits_single_line = rewrite_last_child_with_overflow(context,
|
fits_single_line = rewrite_last_child_with_overflow(
|
||||||
&subexpr_list[trailing_try_num],
|
context,
|
||||||
overflow_shape,
|
&subexpr_list[trailing_try_num],
|
||||||
total_span,
|
overflow_shape,
|
||||||
almost_total,
|
total_span,
|
||||||
one_line_budget,
|
almost_total,
|
||||||
&mut last[0]);
|
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))
|
format!("\n{}", nested_shape.indent.to_string(context.config))
|
||||||
};
|
};
|
||||||
|
|
||||||
let first_connector = choose_first_connector(context,
|
let first_connector = choose_first_connector(
|
||||||
&parent_rewrite,
|
context,
|
||||||
&rewrites[0],
|
&parent_rewrite,
|
||||||
&connector,
|
&rewrites[0],
|
||||||
&subexpr_list,
|
&connector,
|
||||||
extend);
|
&subexpr_list,
|
||||||
|
extend,
|
||||||
|
);
|
||||||
|
|
||||||
if is_small_parent && rewrites.len() > 1 {
|
if is_small_parent && rewrites.len() > 1 {
|
||||||
let second_connector = choose_first_connector(context,
|
let second_connector = choose_first_connector(
|
||||||
&rewrites[0],
|
context,
|
||||||
&rewrites[1],
|
&rewrites[0],
|
||||||
&connector,
|
&rewrites[1],
|
||||||
&subexpr_list[0..subexpr_list.len() - 1],
|
&connector,
|
||||||
false);
|
&subexpr_list[0..subexpr_list.len() - 1],
|
||||||
wrap_str(format!("{}{}{}{}{}",
|
false,
|
||||||
parent_rewrite,
|
);
|
||||||
first_connector,
|
wrap_str(
|
||||||
rewrites[0],
|
format!(
|
||||||
second_connector,
|
"{}{}{}{}{}",
|
||||||
join_rewrites(&rewrites[1..],
|
parent_rewrite,
|
||||||
&subexpr_list[0..subexpr_list.len() - 1],
|
first_connector,
|
||||||
&connector)),
|
rewrites[0],
|
||||||
context.config.max_width(),
|
second_connector,
|
||||||
shape)
|
join_rewrites(
|
||||||
|
&rewrites[1..],
|
||||||
|
&subexpr_list[0..subexpr_list.len() - 1],
|
||||||
|
&connector,
|
||||||
|
)
|
||||||
|
),
|
||||||
|
context.config.max_width(),
|
||||||
|
shape,
|
||||||
|
)
|
||||||
} else {
|
} else {
|
||||||
wrap_str(format!("{}{}{}",
|
wrap_str(
|
||||||
parent_rewrite,
|
format!(
|
||||||
first_connector,
|
"{}{}{}",
|
||||||
join_rewrites(&rewrites, &subexpr_list, &connector)),
|
parent_rewrite,
|
||||||
context.config.max_width(),
|
first_connector,
|
||||||
shape)
|
join_rewrites(&rewrites, &subexpr_list, &connector)
|
||||||
|
),
|
||||||
|
context.config.max_width(),
|
||||||
|
shape,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_extendable_parent(context: &RewriteContext, parent_str: &str) -> bool {
|
fn is_extendable_parent(context: &RewriteContext, parent_str: &str) -> bool {
|
||||||
context.config.chain_indent() == IndentStyle::Block &&
|
context.config.chain_indent() == IndentStyle::Block &&
|
||||||
parent_str.lines().last().map_or(false, |s| {
|
parent_str.lines().last().map_or(false, |s| {
|
||||||
s.trim()
|
s.trim().chars().all(|c| {
|
||||||
.chars()
|
c == ')' || c == ']' || c == '}' || c == '?'
|
||||||
.all(|c| c == ')' || c == ']' || c == '}' || c == '?')
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// True if the chain is only `?`s.
|
// True if the chain is only `?`s.
|
||||||
fn chain_only_try(exprs: &[ast::Expr]) -> bool {
|
fn chain_only_try(exprs: &[ast::Expr]) -> bool {
|
||||||
exprs.iter().all(|e| if let ast::ExprKind::Try(_) = e.node {
|
exprs.iter().all(|e| if let ast::ExprKind::Try(_) = e.node {
|
||||||
true
|
true
|
||||||
} else {
|
} else {
|
||||||
false
|
false
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// Try to rewrite and replace the last non-try child. Return `true` if
|
// Try to rewrite and replace the last non-try child. Return `true` if
|
||||||
// replacing succeeds.
|
// replacing succeeds.
|
||||||
fn rewrite_last_child_with_overflow(context: &RewriteContext,
|
fn rewrite_last_child_with_overflow(
|
||||||
expr: &ast::Expr,
|
context: &RewriteContext,
|
||||||
shape: Shape,
|
expr: &ast::Expr,
|
||||||
span: Span,
|
shape: Shape,
|
||||||
almost_total: usize,
|
span: Span,
|
||||||
one_line_budget: usize,
|
almost_total: usize,
|
||||||
last_child: &mut String)
|
one_line_budget: usize,
|
||||||
-> bool {
|
last_child: &mut String,
|
||||||
|
) -> bool {
|
||||||
if let Some(shape) = shape.shrink_left(almost_total) {
|
if let Some(shape) = shape.shrink_left(almost_total) {
|
||||||
if let Some(ref mut rw) = rewrite_chain_subexpr(expr, span, context, shape) {
|
if let Some(ref mut rw) = rewrite_chain_subexpr(expr, span, context, shape) {
|
||||||
if almost_total + first_line_width(rw) <= one_line_budget {
|
if almost_total + first_line_width(rw) <= one_line_budget {
|
||||||
|
@ -327,15 +357,18 @@ fn rewrite_last_child_with_overflow(context: &RewriteContext,
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn rewrite_try(expr: &ast::Expr,
|
pub fn rewrite_try(
|
||||||
try_count: usize,
|
expr: &ast::Expr,
|
||||||
context: &RewriteContext,
|
try_count: usize,
|
||||||
shape: Shape)
|
context: &RewriteContext,
|
||||||
-> Option<String> {
|
shape: Shape,
|
||||||
|
) -> Option<String> {
|
||||||
let sub_expr = try_opt!(expr.rewrite(context, try_opt!(shape.sub_width(try_count))));
|
let sub_expr = try_opt!(expr.rewrite(context, try_opt!(shape.sub_width(try_count))));
|
||||||
Some(format!("{}{}",
|
Some(format!(
|
||||||
sub_expr,
|
"{}{}",
|
||||||
iter::repeat("?").take(try_count).collect::<String>()))
|
sub_expr,
|
||||||
|
iter::repeat("?").take(try_count).collect::<String>()
|
||||||
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn join_rewrites(rewrites: &[String], subexps: &[ast::Expr], connector: &str) -> 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,
|
fn rewrite_method_call_with_overflow(
|
||||||
last: &mut String,
|
expr_kind: &ast::ExprKind,
|
||||||
almost_total: usize,
|
last: &mut String,
|
||||||
total_span: Span,
|
almost_total: usize,
|
||||||
context: &RewriteContext,
|
total_span: Span,
|
||||||
shape: Shape)
|
context: &RewriteContext,
|
||||||
-> bool {
|
shape: Shape,
|
||||||
|
) -> bool {
|
||||||
if let &ast::ExprKind::MethodCall(ref method_name, ref types, ref expressions) = expr_kind {
|
if let &ast::ExprKind::MethodCall(ref method_name, ref types, ref expressions) = expr_kind {
|
||||||
let shape = match shape.shrink_left(almost_total) {
|
let shape = match shape.shrink_left(almost_total) {
|
||||||
Some(b) => b,
|
Some(b) => b,
|
||||||
None => return false,
|
None => return false,
|
||||||
};
|
};
|
||||||
let mut last_rewrite = rewrite_method_call(method_name.node,
|
let mut last_rewrite = rewrite_method_call(
|
||||||
types,
|
method_name.node,
|
||||||
expressions,
|
types,
|
||||||
total_span,
|
expressions,
|
||||||
context,
|
total_span,
|
||||||
shape);
|
context,
|
||||||
|
shape,
|
||||||
|
);
|
||||||
|
|
||||||
if let Some(ref mut s) = last_rewrite {
|
if let Some(ref mut s) = last_rewrite {
|
||||||
::std::mem::swap(s, last);
|
::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
|
// Rewrite the last element in the chain `expr`. E.g., given `a.b.c` we rewrite
|
||||||
// `.c`.
|
// `.c`.
|
||||||
fn rewrite_chain_subexpr(expr: &ast::Expr,
|
fn rewrite_chain_subexpr(
|
||||||
span: Span,
|
expr: &ast::Expr,
|
||||||
context: &RewriteContext,
|
span: Span,
|
||||||
shape: Shape)
|
context: &RewriteContext,
|
||||||
-> Option<String> {
|
shape: Shape,
|
||||||
|
) -> Option<String> {
|
||||||
let rewrite_element = |expr_str: String| if expr_str.len() <= shape.width {
|
let rewrite_element = |expr_str: String| if expr_str.len() <= shape.width {
|
||||||
Some(expr_str)
|
Some(expr_str)
|
||||||
} else {
|
} else {
|
||||||
|
@ -500,20 +537,23 @@ fn is_try(expr: &ast::Expr) -> bool {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn choose_first_connector<'a>(context: &RewriteContext,
|
fn choose_first_connector<'a>(
|
||||||
parent_str: &str,
|
context: &RewriteContext,
|
||||||
first_child_str: &str,
|
parent_str: &str,
|
||||||
connector: &'a str,
|
first_child_str: &str,
|
||||||
subexpr_list: &[ast::Expr],
|
connector: &'a str,
|
||||||
extend: bool)
|
subexpr_list: &[ast::Expr],
|
||||||
-> &'a str {
|
extend: bool,
|
||||||
|
) -> &'a str {
|
||||||
if subexpr_list.is_empty() {
|
if subexpr_list.is_empty() {
|
||||||
""
|
""
|
||||||
} else if extend || subexpr_list.last().map_or(false, is_try) ||
|
} 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.
|
// 1 = ";", being conservative here.
|
||||||
if last_line_width(parent_str) + first_line_width(first_child_str) + 1 <=
|
if last_line_width(parent_str) + first_line_width(first_child_str) + 1 <=
|
||||||
context.config.max_width() {
|
context.config.max_width()
|
||||||
|
{
|
||||||
""
|
""
|
||||||
} else {
|
} else {
|
||||||
connector
|
connector
|
||||||
|
@ -523,18 +563,18 @@ fn choose_first_connector<'a>(context: &RewriteContext,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn rewrite_method_call(method_name: ast::Ident,
|
fn rewrite_method_call(
|
||||||
types: &[ptr::P<ast::Ty>],
|
method_name: ast::Ident,
|
||||||
args: &[ptr::P<ast::Expr>],
|
types: &[ptr::P<ast::Ty>],
|
||||||
span: Span,
|
args: &[ptr::P<ast::Expr>],
|
||||||
context: &RewriteContext,
|
span: Span,
|
||||||
shape: Shape)
|
context: &RewriteContext,
|
||||||
-> Option<String> {
|
shape: Shape,
|
||||||
|
) -> Option<String> {
|
||||||
let (lo, type_str) = if types.is_empty() {
|
let (lo, type_str) = if types.is_empty() {
|
||||||
(args[0].span.hi, String::new())
|
(args[0].span.hi, String::new())
|
||||||
} else {
|
} else {
|
||||||
let type_list: Vec<_> =
|
let type_list: Vec<_> = try_opt!(types.iter().map(|ty| ty.rewrite(context, shape)).collect());
|
||||||
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 {
|
let type_str = if context.config.spaces_within_angle_brackets() && type_list.len() > 0 {
|
||||||
format!("::< {} >", type_list.join(", "))
|
format!("::< {} >", type_list.join(", "))
|
||||||
|
|
|
@ -13,7 +13,8 @@ use config::WriteMode;
|
||||||
|
|
||||||
|
|
||||||
pub fn output_header<T>(out: &mut T, mode: WriteMode) -> Result<(), io::Error>
|
pub fn output_header<T>(out: &mut T, mode: WriteMode) -> Result<(), io::Error>
|
||||||
where T: Write
|
where
|
||||||
|
T: Write,
|
||||||
{
|
{
|
||||||
if mode == WriteMode::Checkstyle {
|
if mode == WriteMode::Checkstyle {
|
||||||
let mut xml_heading = String::new();
|
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>
|
pub fn output_footer<T>(out: &mut T, mode: WriteMode) -> Result<(), io::Error>
|
||||||
where T: Write
|
where
|
||||||
|
T: Write,
|
||||||
{
|
{
|
||||||
if mode == WriteMode::Checkstyle {
|
if mode == WriteMode::Checkstyle {
|
||||||
let mut xml_tail = String::new();
|
let mut xml_tail = String::new();
|
||||||
|
@ -36,11 +38,13 @@ pub fn output_footer<T>(out: &mut T, mode: WriteMode) -> Result<(), io::Error>
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn output_checkstyle_file<T>(mut writer: T,
|
pub fn output_checkstyle_file<T>(
|
||||||
filename: &str,
|
mut writer: T,
|
||||||
diff: Vec<Mismatch>)
|
filename: &str,
|
||||||
-> Result<(), io::Error>
|
diff: Vec<Mismatch>,
|
||||||
where T: Write
|
) -> Result<(), io::Error>
|
||||||
|
where
|
||||||
|
T: Write,
|
||||||
{
|
{
|
||||||
write!(writer, "<file name=\"{}\">", filename)?;
|
write!(writer, "<file name=\"{}\">", filename)?;
|
||||||
for mismatch in diff {
|
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`.
|
// Do nothing with `DiffLine::Context` and `DiffLine::Resulting`.
|
||||||
if let DiffLine::Expected(ref str) = line {
|
if let DiffLine::Expected(ref str) = line {
|
||||||
let message = xml_escape_str(str);
|
let message = xml_escape_str(str);
|
||||||
write!(writer,
|
write!(
|
||||||
"<error line=\"{}\" severity=\"warning\" message=\"Should be `{}`\" \
|
writer,
|
||||||
|
"<error line=\"{}\" severity=\"warning\" message=\"Should be `{}`\" \
|
||||||
/>",
|
/>",
|
||||||
mismatch.line_number,
|
mismatch.line_number,
|
||||||
message)?;
|
message
|
||||||
|
)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -77,10 +77,12 @@ impl LineRangeUtils for CodeMap {
|
||||||
let lo = self.lookup_char_pos(span.lo);
|
let lo = self.lookup_char_pos(span.lo);
|
||||||
let hi = self.lookup_char_pos(span.hi);
|
let hi = self.lookup_char_pos(span.hi);
|
||||||
|
|
||||||
assert!(lo.file.name == hi.file.name,
|
assert!(
|
||||||
"span crossed file boundary: lo: {:?}, hi: {:?}",
|
lo.file.name == hi.file.name,
|
||||||
lo,
|
"span crossed file boundary: lo: {:?}, hi: {:?}",
|
||||||
hi);
|
lo,
|
||||||
|
hi
|
||||||
|
);
|
||||||
|
|
||||||
LineRange {
|
LineRange {
|
||||||
file: lo.file.clone(),
|
file: lo.file.clone(),
|
||||||
|
|
219
src/comment.rs
219
src/comment.rs
|
@ -45,9 +45,9 @@ pub enum CommentStyle<'a> {
|
||||||
|
|
||||||
fn custom_opener(s: &str) -> &str {
|
fn custom_opener(s: &str) -> &str {
|
||||||
s.lines().next().map_or("", |first_line| {
|
s.lines().next().map_or("", |first_line| {
|
||||||
first_line
|
first_line.find(' ').map_or(first_line, |space_index| {
|
||||||
.find(' ')
|
&first_line[0..space_index + 1]
|
||||||
.map_or(first_line, |space_index| &first_line[0..space_index + 1])
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -98,14 +98,14 @@ impl<'a> CommentStyle<'a> {
|
||||||
CommentStyle::TripleSlash |
|
CommentStyle::TripleSlash |
|
||||||
CommentStyle::Doc => {
|
CommentStyle::Doc => {
|
||||||
line.trim_left().starts_with(self.line_start().trim_left()) ||
|
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::DoubleBullet |
|
||||||
CommentStyle::SingleBullet |
|
CommentStyle::SingleBullet |
|
||||||
CommentStyle::Exclamation => {
|
CommentStyle::Exclamation => {
|
||||||
line.trim_left().starts_with(self.closer().trim_left()) ||
|
line.trim_left().starts_with(self.closer().trim_left()) ||
|
||||||
line.trim_left().starts_with(self.line_start().trim_left()) ||
|
line.trim_left().starts_with(self.line_start().trim_left()) ||
|
||||||
comment_style(line, normalize_comments) == *self
|
comment_style(line, normalize_comments) == *self
|
||||||
}
|
}
|
||||||
CommentStyle::Custom(opener) => line.trim_left().starts_with(opener.trim_right()),
|
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
|
CommentStyle::DoubleSlash
|
||||||
}
|
}
|
||||||
} else if (orig.starts_with("///") && orig.chars().nth(3).map_or(true, |c| c != '/')) ||
|
} 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
|
CommentStyle::TripleSlash
|
||||||
} else if orig.starts_with("//!") || orig.starts_with("/*!") {
|
} else if orig.starts_with("//!") || orig.starts_with("/*!") {
|
||||||
CommentStyle::Doc
|
CommentStyle::Doc
|
||||||
|
@ -141,17 +142,20 @@ fn comment_style(orig: &str, normalize_comments: bool) -> CommentStyle {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn rewrite_comment(orig: &str,
|
pub fn rewrite_comment(
|
||||||
block_style: bool,
|
orig: &str,
|
||||||
shape: Shape,
|
block_style: bool,
|
||||||
config: &Config)
|
shape: Shape,
|
||||||
-> Option<String> {
|
config: &Config,
|
||||||
|
) -> Option<String> {
|
||||||
// If there are lines without a starting sigil, we won't format them correctly
|
// 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
|
// so in that case we won't even re-align (if !config.normalize_comments()) and
|
||||||
// we should stop now.
|
// we should stop now.
|
||||||
let num_bare_lines = orig.lines()
|
let num_bare_lines = orig.lines()
|
||||||
.map(|line| line.trim())
|
.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();
|
.count();
|
||||||
if num_bare_lines > 0 && !config.normalize_comments() {
|
if num_bare_lines > 0 && !config.normalize_comments() {
|
||||||
return Some(orig.to_owned());
|
return Some(orig.to_owned());
|
||||||
|
@ -163,11 +167,12 @@ pub fn rewrite_comment(orig: &str,
|
||||||
identify_comment(orig, block_style, shape, config)
|
identify_comment(orig, block_style, shape, config)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn identify_comment(orig: &str,
|
fn identify_comment(
|
||||||
block_style: bool,
|
orig: &str,
|
||||||
shape: Shape,
|
block_style: bool,
|
||||||
config: &Config)
|
shape: Shape,
|
||||||
-> Option<String> {
|
config: &Config,
|
||||||
|
) -> Option<String> {
|
||||||
let style = comment_style(orig, false);
|
let style = comment_style(orig, false);
|
||||||
let first_group = orig.lines()
|
let first_group = orig.lines()
|
||||||
.take_while(|l| style.line_with_same_comment_style(l, false))
|
.take_while(|l| style.line_with_same_comment_style(l, false))
|
||||||
|
@ -178,28 +183,34 @@ fn identify_comment(orig: &str,
|
||||||
.collect::<Vec<_>>()
|
.collect::<Vec<_>>()
|
||||||
.join("\n");
|
.join("\n");
|
||||||
|
|
||||||
let first_group_str =
|
let first_group_str = try_opt!(rewrite_comment_inner(
|
||||||
try_opt!(rewrite_comment_inner(&first_group, block_style, style, shape, config));
|
&first_group,
|
||||||
|
block_style,
|
||||||
|
style,
|
||||||
|
shape,
|
||||||
|
config,
|
||||||
|
));
|
||||||
if rest.is_empty() {
|
if rest.is_empty() {
|
||||||
Some(first_group_str)
|
Some(first_group_str)
|
||||||
} else {
|
} else {
|
||||||
identify_comment(&rest, block_style, shape, config).map(|rest_str| {
|
identify_comment(&rest, block_style, shape, config).map(|rest_str| {
|
||||||
format!("{}\n{}{}",
|
format!(
|
||||||
first_group_str,
|
"{}\n{}{}",
|
||||||
shape
|
first_group_str,
|
||||||
.indent
|
shape.indent.to_string(config),
|
||||||
.to_string(config),
|
rest_str
|
||||||
rest_str)
|
)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn rewrite_comment_inner(orig: &str,
|
fn rewrite_comment_inner(
|
||||||
block_style: bool,
|
orig: &str,
|
||||||
style: CommentStyle,
|
block_style: bool,
|
||||||
shape: Shape,
|
style: CommentStyle,
|
||||||
config: &Config)
|
shape: Shape,
|
||||||
-> Option<String> {
|
config: &Config,
|
||||||
|
) -> Option<String> {
|
||||||
let (opener, closer, line_start) = if block_style {
|
let (opener, closer, line_start) = if block_style {
|
||||||
CommentStyle::SingleBullet.to_str_tuplet()
|
CommentStyle::SingleBullet.to_str_tuplet()
|
||||||
} else {
|
} else {
|
||||||
|
@ -235,10 +246,10 @@ fn rewrite_comment_inner(orig: &str,
|
||||||
})
|
})
|
||||||
.map(|s| left_trim_comment_line(s, &style))
|
.map(|s| left_trim_comment_line(s, &style))
|
||||||
.map(|line| if orig.starts_with("/*") && line_breaks == 0 {
|
.map(|line| if orig.starts_with("/*") && line_breaks == 0 {
|
||||||
line.trim_left()
|
line.trim_left()
|
||||||
} else {
|
} else {
|
||||||
line
|
line
|
||||||
});
|
});
|
||||||
|
|
||||||
let mut result = opener.to_owned();
|
let mut result = opener.to_owned();
|
||||||
for line in lines {
|
for line in lines {
|
||||||
|
@ -299,7 +310,8 @@ fn light_rewrite_comment(orig: &str, offset: Indent, config: &Config) -> Option<
|
||||||
/// Does not trim all whitespace.
|
/// Does not trim all whitespace.
|
||||||
fn left_trim_comment_line<'a>(line: &'a str, style: &CommentStyle) -> &'a str {
|
fn left_trim_comment_line<'a>(line: &'a str, style: &CommentStyle) -> &'a str {
|
||||||
if line.starts_with("//! ") || line.starts_with("/// ") || line.starts_with("/*! ") ||
|
if line.starts_with("//! ") || line.starts_with("/// ") || line.starts_with("/*! ") ||
|
||||||
line.starts_with("/** ") {
|
line.starts_with("/** ")
|
||||||
|
{
|
||||||
&line[4..]
|
&line[4..]
|
||||||
} else if let &CommentStyle::Custom(opener) = style {
|
} else if let &CommentStyle::Custom(opener) = style {
|
||||||
if line.starts_with(opener) {
|
if line.starts_with(opener) {
|
||||||
|
@ -307,13 +319,15 @@ fn left_trim_comment_line<'a>(line: &'a str, style: &CommentStyle) -> &'a str {
|
||||||
} else {
|
} else {
|
||||||
&line[opener.trim_right().len()..]
|
&line[opener.trim_right().len()..]
|
||||||
}
|
}
|
||||||
} else if 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.starts_with("/*!") ||
|
||||||
(line.starts_with("/**") && !line.starts_with("/**/")) {
|
(line.starts_with("/**") && !line.starts_with("/**/"))
|
||||||
|
{
|
||||||
&line[3..]
|
&line[3..]
|
||||||
} else if 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[2..]
|
&line[2..]
|
||||||
} else if line.starts_with('*') {
|
} else if line.starts_with('*') {
|
||||||
&line[1..]
|
&line[1..]
|
||||||
|
@ -379,8 +393,9 @@ pub fn contains_comment(text: &str) -> bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
struct CharClasses<T>
|
struct CharClasses<T>
|
||||||
where T: Iterator,
|
where
|
||||||
T::Item: RichChar
|
T: Iterator,
|
||||||
|
T::Item: RichChar,
|
||||||
{
|
{
|
||||||
base: iter::Peekable<T>,
|
base: iter::Peekable<T>,
|
||||||
status: CharClassesStatus,
|
status: CharClassesStatus,
|
||||||
|
@ -462,8 +477,9 @@ impl FullCodeCharKind {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> CharClasses<T>
|
impl<T> CharClasses<T>
|
||||||
where T: Iterator,
|
where
|
||||||
T::Item: RichChar
|
T: Iterator,
|
||||||
|
T::Item: RichChar,
|
||||||
{
|
{
|
||||||
fn new(base: T) -> CharClasses<T> {
|
fn new(base: T) -> CharClasses<T> {
|
||||||
CharClasses {
|
CharClasses {
|
||||||
|
@ -474,8 +490,9 @@ impl<T> CharClasses<T>
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> Iterator for CharClasses<T>
|
impl<T> Iterator for CharClasses<T>
|
||||||
where T: Iterator,
|
where
|
||||||
T::Item: RichChar
|
T: Iterator,
|
||||||
|
T::Item: RichChar,
|
||||||
{
|
{
|
||||||
type Item = (FullCodeCharKind, T::Item);
|
type Item = (FullCodeCharKind, T::Item);
|
||||||
|
|
||||||
|
@ -603,13 +620,15 @@ impl<'a> Iterator for UngroupedCommentCodeSlices<'a> {
|
||||||
Some(&(_, (end_idx, _))) => &self.slice[start_idx..end_idx],
|
Some(&(_, (end_idx, _))) => &self.slice[start_idx..end_idx],
|
||||||
None => &self.slice[start_idx..],
|
None => &self.slice[start_idx..],
|
||||||
};
|
};
|
||||||
Some((if kind.is_comment() {
|
Some((
|
||||||
CodeCharKind::Comment
|
if kind.is_comment() {
|
||||||
} else {
|
CodeCharKind::Comment
|
||||||
CodeCharKind::Normal
|
} else {
|
||||||
},
|
CodeCharKind::Normal
|
||||||
start_idx,
|
},
|
||||||
slice))
|
start_idx,
|
||||||
|
slice,
|
||||||
|
))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -650,8 +669,8 @@ impl<'a> Iterator for CommentCodeSlices<'a> {
|
||||||
|
|
||||||
for (kind, (i, c)) in &mut iter {
|
for (kind, (i, c)) in &mut iter {
|
||||||
let is_comment_connector = self.last_slice_kind == CodeCharKind::Normal &&
|
let is_comment_connector = self.last_slice_kind == CodeCharKind::Normal &&
|
||||||
&subslice[..2] == "//" &&
|
&subslice[..2] == "//" &&
|
||||||
[' ', '\t'].contains(&c);
|
[' ', '\t'].contains(&c);
|
||||||
|
|
||||||
if is_comment_connector && first_whitespace.is_none() {
|
if is_comment_connector && first_whitespace.is_none() {
|
||||||
first_whitespace = Some(i);
|
first_whitespace = Some(i);
|
||||||
|
@ -683,7 +702,11 @@ impl<'a> Iterator for CommentCodeSlices<'a> {
|
||||||
CodeCharKind::Comment => CodeCharKind::Normal,
|
CodeCharKind::Comment => CodeCharKind::Normal,
|
||||||
CodeCharKind::Normal => CodeCharKind::Comment,
|
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_end = sub_slice_end;
|
||||||
self.last_slice_kind = kind;
|
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
|
/// 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`
|
/// (if it fits in the width/offset, else return None), else return `new`
|
||||||
pub fn recover_comment_removed(new: String,
|
pub fn recover_comment_removed(
|
||||||
span: Span,
|
new: String,
|
||||||
context: &RewriteContext,
|
span: Span,
|
||||||
shape: Shape)
|
context: &RewriteContext,
|
||||||
-> Option<String> {
|
shape: Shape,
|
||||||
|
) -> Option<String> {
|
||||||
let snippet = context.snippet(span);
|
let snippet = context.snippet(span);
|
||||||
if changed_comment_content(&snippet, &new) {
|
if changed_comment_content(&snippet, &new) {
|
||||||
// We missed some comments
|
// We missed some comments
|
||||||
|
@ -723,12 +747,14 @@ fn changed_comment_content(orig: &str, new: &str) -> bool {
|
||||||
.flat_map(|(_, _, s)| CommentReducer::new(s))
|
.flat_map(|(_, _, s)| CommentReducer::new(s))
|
||||||
};
|
};
|
||||||
let res = code_comment_content(orig).ne(code_comment_content(new));
|
let res = code_comment_content(orig).ne(code_comment_content(new));
|
||||||
debug!("comment::changed_comment_content: {}\norig: '{}'\nnew: '{}'\nraw_old: {}\nraw_new: {}",
|
debug!(
|
||||||
res,
|
"comment::changed_comment_content: {}\norig: '{}'\nnew: '{}'\nraw_old: {}\nraw_new: {}",
|
||||||
orig,
|
res,
|
||||||
new,
|
orig,
|
||||||
code_comment_content(orig).collect::<String>(),
|
new,
|
||||||
code_comment_content(new).collect::<String>());
|
code_comment_content(orig).collect::<String>(),
|
||||||
|
code_comment_content(new).collect::<String>()
|
||||||
|
);
|
||||||
res
|
res
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -787,11 +813,14 @@ fn remove_comment_header(comment: &str) -> &str {
|
||||||
} else if comment.starts_with("//") {
|
} else if comment.starts_with("//") {
|
||||||
&comment[2..]
|
&comment[2..]
|
||||||
} else if (comment.starts_with("/**") && !comment.starts_with("/**/")) ||
|
} else if (comment.starts_with("/**") && !comment.starts_with("/**/")) ||
|
||||||
comment.starts_with("/*!") {
|
comment.starts_with("/*!")
|
||||||
|
{
|
||||||
&comment[3..comment.len() - 2]
|
&comment[3..comment.len() - 2]
|
||||||
} else {
|
} else {
|
||||||
assert!(comment.starts_with("/*"),
|
assert!(
|
||||||
format!("string '{}' is not a comment", comment));
|
comment.starts_with("/*"),
|
||||||
|
format!("string '{}' is not a comment", comment)
|
||||||
|
);
|
||||||
&comment[2..comment.len() - 2]
|
&comment[2..comment.len() - 2]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -819,8 +848,10 @@ mod test {
|
||||||
let mut iter = CommentCodeSlices::new(input);
|
let mut iter = CommentCodeSlices::new(input);
|
||||||
|
|
||||||
assert_eq!((CodeCharKind::Normal, 0, "code(); "), iter.next().unwrap());
|
assert_eq!((CodeCharKind::Normal, 0, "code(); "), iter.next().unwrap());
|
||||||
assert_eq!((CodeCharKind::Comment, 8, "/* test */"),
|
assert_eq!(
|
||||||
iter.next().unwrap());
|
(CodeCharKind::Comment, 8, "/* test */"),
|
||||||
|
iter.next().unwrap()
|
||||||
|
);
|
||||||
assert_eq!((CodeCharKind::Normal, 18, " 1 + 1"), iter.next().unwrap());
|
assert_eq!((CodeCharKind::Normal, 18, " 1 + 1"), iter.next().unwrap());
|
||||||
assert_eq!(None, iter.next());
|
assert_eq!(None, iter.next());
|
||||||
}
|
}
|
||||||
|
@ -831,10 +862,14 @@ mod test {
|
||||||
let mut iter = CommentCodeSlices::new(input);
|
let mut iter = CommentCodeSlices::new(input);
|
||||||
|
|
||||||
assert_eq!((CodeCharKind::Normal, 0, ""), iter.next().unwrap());
|
assert_eq!((CodeCharKind::Normal, 0, ""), iter.next().unwrap());
|
||||||
assert_eq!((CodeCharKind::Comment, 0, "// comment\n"),
|
assert_eq!(
|
||||||
iter.next().unwrap());
|
(CodeCharKind::Comment, 0, "// comment\n"),
|
||||||
assert_eq!((CodeCharKind::Normal, 11, " test();"),
|
iter.next().unwrap()
|
||||||
iter.next().unwrap());
|
);
|
||||||
|
assert_eq!(
|
||||||
|
(CodeCharKind::Normal, 11, " test();"),
|
||||||
|
iter.next().unwrap()
|
||||||
|
);
|
||||||
assert_eq!(None, iter.next());
|
assert_eq!(None, iter.next());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -844,8 +879,10 @@ mod test {
|
||||||
let mut iter = CommentCodeSlices::new(input);
|
let mut iter = CommentCodeSlices::new(input);
|
||||||
|
|
||||||
assert_eq!((CodeCharKind::Normal, 0, "1 "), iter.next().unwrap());
|
assert_eq!((CodeCharKind::Normal, 0, "1 "), iter.next().unwrap());
|
||||||
assert_eq!((CodeCharKind::Comment, 2, "// comment\n // comment2\n"),
|
assert_eq!(
|
||||||
iter.next().unwrap());
|
(CodeCharKind::Comment, 2, "// comment\n // comment2\n"),
|
||||||
|
iter.next().unwrap()
|
||||||
|
);
|
||||||
assert_eq!((CodeCharKind::Normal, 29, "\n"), iter.next().unwrap());
|
assert_eq!((CodeCharKind::Normal, 29, "\n"), iter.next().unwrap());
|
||||||
assert_eq!(None, iter.next());
|
assert_eq!(None, iter.next());
|
||||||
}
|
}
|
||||||
|
@ -896,17 +933,19 @@ mod test {
|
||||||
fn uncommented(text: &str) -> String {
|
fn uncommented(text: &str) -> String {
|
||||||
CharClasses::new(text.chars())
|
CharClasses::new(text.chars())
|
||||||
.filter_map(|(s, c)| match s {
|
.filter_map(|(s, c)| match s {
|
||||||
FullCodeCharKind::Normal => Some(c),
|
FullCodeCharKind::Normal => Some(c),
|
||||||
_ => None,
|
_ => None,
|
||||||
})
|
})
|
||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_uncommented() {
|
fn test_uncommented() {
|
||||||
assert_eq!(&uncommented("abc/*...*/"), "abc");
|
assert_eq!(&uncommented("abc/*...*/"), "abc");
|
||||||
assert_eq!(&uncommented("// .... /* \n../* /* *** / */ */a/* // */c\n"),
|
assert_eq!(
|
||||||
"..ac\n");
|
&uncommented("// .... /* \n../* /* *** / */ */a/* // */c\n"),
|
||||||
|
"..ac\n"
|
||||||
|
);
|
||||||
assert_eq!(&uncommented("abc \" /* */\" qsdf"), "abc \" /* */\" qsdf");
|
assert_eq!(&uncommented("abc \" /* */\" qsdf"), "abc \" /* */\" qsdf");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -927,9 +966,11 @@ mod test {
|
||||||
check("/*/ */test", "test", Some(6));
|
check("/*/ */test", "test", Some(6));
|
||||||
check("//test\ntest", "test", Some(7));
|
check("//test\ntest", "test", Some(7));
|
||||||
check("/* comment only */", "whatever", None);
|
check("/* comment only */", "whatever", None);
|
||||||
check("/* comment */ some text /* more commentary */ result",
|
check(
|
||||||
"result",
|
"/* comment */ some text /* more commentary */ result",
|
||||||
Some(46));
|
"result",
|
||||||
|
Some(46),
|
||||||
|
);
|
||||||
check("sup // sup", "p", Some(2));
|
check("sup // sup", "p", Some(2));
|
||||||
check("sup", "x", None);
|
check("sup", "x", None);
|
||||||
check(r#"π? /**/ π is nice!"#, r#"π is nice"#, Some(9));
|
check(r#"π? /**/ π is nice!"#, r#"π is nice"#, Some(9));
|
||||||
|
|
|
@ -605,7 +605,9 @@ mod test {
|
||||||
|
|
||||||
let used_options = config.used_options();
|
let used_options = config.used_options();
|
||||||
let toml = used_options.to_toml().unwrap();
|
let toml = used_options.to_toml().unwrap();
|
||||||
assert_eq!(toml,
|
assert_eq!(
|
||||||
format!("verbose = {}\nskip_children = {}\n", verbose, skip_children));
|
toml,
|
||||||
|
format!("verbose = {}\nskip_children = {}\n", verbose, skip_children)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
1340
src/expr.rs
1340
src/expr.rs
File diff suppressed because it is too large
Load diff
|
@ -52,7 +52,7 @@ impl Range {
|
||||||
false
|
false
|
||||||
} else {
|
} else {
|
||||||
(self.lo <= other.hi && other.hi <= self.hi) ||
|
(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.
|
/// intersect; returns `None` otherwise.
|
||||||
fn merge(self, other: Range) -> Option<Range> {
|
fn merge(self, other: Range) -> Option<Range> {
|
||||||
if self.adjacent_to(other) || self.intersects(other) {
|
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 {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
@ -127,7 +130,8 @@ impl FileLines {
|
||||||
/// Returns true if `self` includes all lines in all files. Otherwise runs `f` on all ranges in
|
/// 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.
|
/// the designated file (if any) and returns true if `f` ever does.
|
||||||
fn file_range_matches<F>(&self, file_name: &str, f: F) -> bool
|
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 {
|
let map = match self.0 {
|
||||||
// `None` means "all lines in all files".
|
// `None` means "all lines in all files".
|
||||||
|
@ -209,8 +213,9 @@ struct JsonSpan {
|
||||||
impl JsonSpan {
|
impl JsonSpan {
|
||||||
fn into_tuple(self) -> Result<(String, Range), String> {
|
fn into_tuple(self) -> Result<(String, Range), String> {
|
||||||
let (lo, hi) = self.range;
|
let (lo, hi) = self.range;
|
||||||
let canonical = canonicalize_path_string(&self.file)
|
let canonical = canonicalize_path_string(&self.file).ok_or_else(|| {
|
||||||
.ok_or_else(|| format!("Can't canonicalize {}", &self.file))?;
|
format!("Can't canonicalize {}", &self.file)
|
||||||
|
})?;
|
||||||
Ok((canonical, Range::new(lo, hi)))
|
Ok((canonical, Range::new(lo, hi)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -219,10 +224,13 @@ impl JsonSpan {
|
||||||
// for `FileLines`, so it will just panic instead.
|
// for `FileLines`, so it will just panic instead.
|
||||||
impl<'de> ::serde::de::Deserialize<'de> for FileLines {
|
impl<'de> ::serde::de::Deserialize<'de> for FileLines {
|
||||||
fn deserialize<D>(_: D) -> Result<Self, D::Error>
|
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 \
|
panic!(
|
||||||
specify it via the `--file-lines` option instead");
|
"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.
|
// `Config` struct should ensure this impl is never reached.
|
||||||
impl ::serde::ser::Serialize for FileLines {
|
impl ::serde::ser::Serialize for FileLines {
|
||||||
fn serialize<S>(&self, _: S) -> Result<S::Ok, S::Error>
|
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.");
|
unreachable!("FileLines cannot be serialized. This is a rustfmt bug.");
|
||||||
}
|
}
|
||||||
|
@ -270,13 +279,21 @@ mod test {
|
||||||
fn test_range_merge() {
|
fn test_range_merge() {
|
||||||
assert_eq!(None, Range::new(1, 3).merge(Range::new(5, 5)));
|
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!(None, Range::new(4, 7).merge(Range::new(0, 1)));
|
||||||
assert_eq!(Some(Range::new(3, 7)),
|
assert_eq!(
|
||||||
Range::new(3, 5).merge(Range::new(4, 7)));
|
Some(Range::new(3, 7)),
|
||||||
assert_eq!(Some(Range::new(3, 7)),
|
Range::new(3, 5).merge(Range::new(4, 7))
|
||||||
Range::new(3, 5).merge(Range::new(5, 7)));
|
);
|
||||||
assert_eq!(Some(Range::new(3, 7)),
|
assert_eq!(
|
||||||
Range::new(3, 5).merge(Range::new(6, 7)));
|
Some(Range::new(3, 7)),
|
||||||
assert_eq!(Some(Range::new(3, 7)),
|
Range::new(3, 5).merge(Range::new(5, 7))
|
||||||
Range::new(3, 7).merge(Range::new(4, 5)));
|
);
|
||||||
|
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))
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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>
|
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();
|
output_header(out, config.write_mode()).ok();
|
||||||
for &(ref filename, ref text) in file_map {
|
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`.
|
// Prints all newlines either as `\n` or as `\r\n`.
|
||||||
pub fn write_system_newlines<T>(writer: T,
|
pub fn write_system_newlines<T>(
|
||||||
text: &StringBuffer,
|
writer: T,
|
||||||
config: &Config)
|
text: &StringBuffer,
|
||||||
-> Result<(), io::Error>
|
config: &Config,
|
||||||
where T: Write
|
) -> Result<(), io::Error>
|
||||||
|
where
|
||||||
|
T: Write,
|
||||||
{
|
{
|
||||||
// Buffer output, since we're writing a since char at a time.
|
// Buffer output, since we're writing a since char at a time.
|
||||||
let mut writer = BufWriter::new(writer);
|
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,
|
pub fn write_file<T>(
|
||||||
filename: &str,
|
text: &StringBuffer,
|
||||||
out: &mut T,
|
filename: &str,
|
||||||
config: &Config)
|
out: &mut T,
|
||||||
-> Result<bool, io::Error>
|
config: &Config,
|
||||||
where T: Write
|
) -> Result<bool, io::Error>
|
||||||
|
where
|
||||||
|
T: Write,
|
||||||
{
|
{
|
||||||
|
|
||||||
fn source_and_formatted_text(text: &StringBuffer,
|
fn source_and_formatted_text(
|
||||||
filename: &str,
|
text: &StringBuffer,
|
||||||
config: &Config)
|
filename: &str,
|
||||||
-> Result<(String, String), io::Error> {
|
config: &Config,
|
||||||
|
) -> Result<(String, String), io::Error> {
|
||||||
let mut f = File::open(filename)?;
|
let mut f = File::open(filename)?;
|
||||||
let mut ori_text = String::new();
|
let mut ori_text = String::new();
|
||||||
f.read_to_string(&mut ori_text)?;
|
f.read_to_string(&mut ori_text)?;
|
||||||
|
@ -99,10 +105,11 @@ pub fn write_file<T>(text: &StringBuffer,
|
||||||
Ok((ori_text, fmt_text))
|
Ok((ori_text, fmt_text))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn create_diff(filename: &str,
|
fn create_diff(
|
||||||
text: &StringBuffer,
|
filename: &str,
|
||||||
config: &Config)
|
text: &StringBuffer,
|
||||||
-> Result<Vec<Mismatch>, io::Error> {
|
config: &Config,
|
||||||
|
) -> Result<Vec<Mismatch>, io::Error> {
|
||||||
let (ori, fmt) = source_and_formatted_text(text, filename, config)?;
|
let (ori, fmt) = source_and_formatted_text(text, filename, config)?;
|
||||||
Ok(make_diff(&ori, &fmt, 3))
|
Ok(make_diff(&ori, &fmt, 3))
|
||||||
}
|
}
|
||||||
|
|
146
src/imports.rs
146
src/imports.rs
|
@ -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>,
|
fn compare_path_list_item_lists(
|
||||||
b_items: &Vec<ast::PathListItem>)
|
a_items: &Vec<ast::PathListItem>,
|
||||||
-> Ordering {
|
b_items: &Vec<ast::PathListItem>,
|
||||||
|
) -> Ordering {
|
||||||
let mut a = a_items.clone();
|
let mut a = a_items.clone();
|
||||||
let mut b = b_items.clone();
|
let mut b = b_items.clone();
|
||||||
a.sort_by(|a, b| compare_path_list_items(a, b));
|
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
|
// TODO (some day) remove unused imports, expand globs, compress many single
|
||||||
// imports into a list import.
|
// imports into a list import.
|
||||||
|
|
||||||
fn rewrite_view_path_prefix(path: &ast::Path,
|
fn rewrite_view_path_prefix(
|
||||||
context: &RewriteContext,
|
path: &ast::Path,
|
||||||
shape: Shape)
|
context: &RewriteContext,
|
||||||
-> Option<String> {
|
shape: Shape,
|
||||||
|
) -> Option<String> {
|
||||||
let path_str = if path.segments.last().unwrap().identifier.to_string() == "self" &&
|
let path_str = if path.segments.last().unwrap().identifier.to_string() == "self" &&
|
||||||
path.segments.len() > 1 {
|
path.segments.len() > 1
|
||||||
|
{
|
||||||
let path = &ast::Path {
|
let path = &ast::Path {
|
||||||
span: path.span.clone(),
|
span: path.span.clone(),
|
||||||
segments: path.segments[..path.segments.len() - 1].to_owned(),
|
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 {
|
} else {
|
||||||
try_opt!(rewrite_path(context, PathContext::Import, None, path, shape))
|
try_opt!(rewrite_path(
|
||||||
|
context,
|
||||||
|
PathContext::Import,
|
||||||
|
None,
|
||||||
|
path,
|
||||||
|
shape,
|
||||||
|
))
|
||||||
};
|
};
|
||||||
Some(path_str)
|
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 prefix_shape = try_opt!(shape.sub_width(ident_str.len() + 4));
|
||||||
let path_str = try_opt!(rewrite_view_path_prefix(path, context, prefix_shape));
|
let path_str = try_opt!(rewrite_view_path_prefix(path, context, prefix_shape));
|
||||||
|
|
||||||
Some(if path.segments.last().unwrap().identifier == ident {
|
Some(
|
||||||
path_str
|
if path.segments.last().unwrap().identifier == ident {
|
||||||
} else {
|
path_str
|
||||||
format!("{} as {}", path_str, ident_str)
|
} else {
|
||||||
})
|
format!("{} as {}", path_str, ident_str)
|
||||||
|
},
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -179,13 +196,13 @@ impl<'a> FmtVisitor<'a> {
|
||||||
let pos_before_first_use_item = use_items
|
let pos_before_first_use_item = use_items
|
||||||
.first()
|
.first()
|
||||||
.map(|p_i| {
|
.map(|p_i| {
|
||||||
cmp::max(self.last_pos,
|
cmp::max(
|
||||||
p_i.attrs
|
self.last_pos,
|
||||||
.iter()
|
p_i.attrs.iter().map(|attr| attr.span.lo).min().unwrap_or(
|
||||||
.map(|attr| attr.span.lo)
|
p_i.span.lo,
|
||||||
.min()
|
),
|
||||||
.unwrap_or(p_i.span.lo))
|
)
|
||||||
})
|
})
|
||||||
.unwrap_or(self.last_pos);
|
.unwrap_or(self.last_pos);
|
||||||
// Construct a list of pairs, each containing a `use` item and the start of span before
|
// Construct a list of pairs, each containing a `use` item and the start of span before
|
||||||
// that `use` item.
|
// that `use` item.
|
||||||
|
@ -193,10 +210,10 @@ impl<'a> FmtVisitor<'a> {
|
||||||
let mut ordered_use_items = use_items
|
let mut ordered_use_items = use_items
|
||||||
.iter()
|
.iter()
|
||||||
.map(|p_i| {
|
.map(|p_i| {
|
||||||
let new_item = (&*p_i, last_pos_of_prev_use_item);
|
let new_item = (&*p_i, last_pos_of_prev_use_item);
|
||||||
last_pos_of_prev_use_item = p_i.span.hi;
|
last_pos_of_prev_use_item = p_i.span.hi;
|
||||||
new_item
|
new_item
|
||||||
})
|
})
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
let pos_after_last_use_item = last_pos_of_prev_use_item;
|
let pos_after_last_use_item = last_pos_of_prev_use_item;
|
||||||
// Order the imports by view-path & other import path properties
|
// Order the imports by view-path & other import path properties
|
||||||
|
@ -237,8 +254,10 @@ impl<'a> FmtVisitor<'a> {
|
||||||
let mut offset = self.block_indent;
|
let mut offset = self.block_indent;
|
||||||
offset.alignment += vis.len() + "use ".len();
|
offset.alignment += vis.len() + "use ".len();
|
||||||
// 1 = ";"
|
// 1 = ";"
|
||||||
match vp.rewrite(&self.get_context(),
|
match vp.rewrite(
|
||||||
Shape::legacy(self.config.max_width() - offset.width() - 1, offset)) {
|
&self.get_context(),
|
||||||
|
Shape::legacy(self.config.max_width() - offset.width() - 1, offset),
|
||||||
|
) {
|
||||||
Some(ref s) if s.is_empty() => {
|
Some(ref s) if s.is_empty() => {
|
||||||
// Format up to last newline
|
// Format up to last newline
|
||||||
let prev_span = utils::mk_sp(self.last_pos, source!(self, span).lo);
|
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.
|
// Pretty prints a multi-item import.
|
||||||
// Assumes that path_list.len() > 0.
|
// Assumes that path_list.len() > 0.
|
||||||
pub fn rewrite_use_list(shape: Shape,
|
pub fn rewrite_use_list(
|
||||||
path: &ast::Path,
|
shape: Shape,
|
||||||
path_list: &[ast::PathListItem],
|
path: &ast::Path,
|
||||||
span: Span,
|
path_list: &[ast::PathListItem],
|
||||||
context: &RewriteContext)
|
span: Span,
|
||||||
-> Option<String> {
|
context: &RewriteContext,
|
||||||
|
) -> Option<String> {
|
||||||
// Returns a different option to distinguish `::foo` and `foo`
|
// 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() {
|
match path_list.len() {
|
||||||
0 => unreachable!(),
|
0 => unreachable!(),
|
||||||
|
@ -321,14 +347,16 @@ pub fn rewrite_use_list(shape: Shape,
|
||||||
let mut items = {
|
let mut items = {
|
||||||
// Dummy value, see explanation below.
|
// Dummy value, see explanation below.
|
||||||
let mut items = vec![ListItem::from_str("")];
|
let mut items = vec![ListItem::from_str("")];
|
||||||
let iter = itemize_list(context.codemap,
|
let iter = itemize_list(
|
||||||
path_list.iter(),
|
context.codemap,
|
||||||
"}",
|
path_list.iter(),
|
||||||
|vpi| vpi.span.lo,
|
"}",
|
||||||
|vpi| vpi.span.hi,
|
|vpi| vpi.span.lo,
|
||||||
rewrite_path_item,
|
|vpi| vpi.span.hi,
|
||||||
context.codemap.span_after(span, "{"),
|
rewrite_path_item,
|
||||||
span.hi);
|
context.codemap.span_after(span, "{"),
|
||||||
|
span.hi,
|
||||||
|
);
|
||||||
items.extend(iter);
|
items.extend(iter);
|
||||||
items
|
items
|
||||||
};
|
};
|
||||||
|
@ -344,34 +372,40 @@ pub fn rewrite_use_list(shape: Shape,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
let tactic = definitive_tactic(&items[first_index..],
|
let tactic = definitive_tactic(
|
||||||
::lists::ListTactic::Mixed,
|
&items[first_index..],
|
||||||
remaining_width);
|
::lists::ListTactic::Mixed,
|
||||||
|
remaining_width,
|
||||||
|
);
|
||||||
|
|
||||||
let fmt = ListFormatting {
|
let fmt = ListFormatting {
|
||||||
tactic: tactic,
|
tactic: tactic,
|
||||||
separator: ",",
|
separator: ",",
|
||||||
trailing_separator: SeparatorTactic::Never,
|
trailing_separator: SeparatorTactic::Never,
|
||||||
// Add one to the indent to account for "{"
|
// Add one to the indent to account for "{"
|
||||||
shape: Shape::legacy(remaining_width,
|
shape: Shape::legacy(
|
||||||
shape.indent + path_str.len() + colons_offset + 1),
|
remaining_width,
|
||||||
|
shape.indent + path_str.len() + colons_offset + 1,
|
||||||
|
),
|
||||||
ends_with_newline: false,
|
ends_with_newline: false,
|
||||||
config: context.config,
|
config: context.config,
|
||||||
};
|
};
|
||||||
let list_str = try_opt!(write_list(&items[first_index..], &fmt));
|
let list_str = try_opt!(write_list(&items[first_index..], &fmt));
|
||||||
|
|
||||||
Some(if path_str.is_empty() {
|
Some(
|
||||||
format!("{{{}}}", list_str)
|
if path_str.is_empty() {
|
||||||
} else {
|
format!("{{{}}}", list_str)
|
||||||
format!("{}::{{{}}}", path_str, list_str)
|
} else {
|
||||||
})
|
format!("{}::{{{}}}", path_str, list_str)
|
||||||
|
},
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns true when self item was found.
|
// Returns true when self item was found.
|
||||||
fn move_self_to_front(items: &mut Vec<ListItem>) -> bool {
|
fn move_self_to_front(items: &mut Vec<ListItem>) -> bool {
|
||||||
match items
|
match items.iter().position(|item| {
|
||||||
.iter()
|
item.item.as_ref().map(|x| &x[..]) == Some("self")
|
||||||
.position(|item| item.item.as_ref().map(|x| &x[..]) == Some("self")) {
|
}) {
|
||||||
Some(pos) => {
|
Some(pos) => {
|
||||||
items[0] = items.remove(pos);
|
items[0] = items.remove(pos);
|
||||||
true
|
true
|
||||||
|
|
|
@ -172,11 +172,12 @@ impl BadIssueSeeker {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn inspect_number(&mut self,
|
fn inspect_number(
|
||||||
c: char,
|
&mut self,
|
||||||
issue: Issue,
|
c: char,
|
||||||
mut part: NumberPart)
|
issue: Issue,
|
||||||
-> IssueClassification {
|
mut part: NumberPart,
|
||||||
|
) -> IssueClassification {
|
||||||
if !issue.missing_number || c == '\n' {
|
if !issue.missing_number || c == '\n' {
|
||||||
return IssueClassification::Bad(issue);
|
return IssueClassification::Bad(issue);
|
||||||
} else if c == ')' {
|
} else if c == ')' {
|
||||||
|
@ -223,8 +224,10 @@ impl BadIssueSeeker {
|
||||||
fn find_unnumbered_issue() {
|
fn find_unnumbered_issue() {
|
||||||
fn check_fail(text: &str, failing_pos: usize) {
|
fn check_fail(text: &str, failing_pos: usize) {
|
||||||
let mut seeker = BadIssueSeeker::new(ReportTactic::Unnumbered, ReportTactic::Unnumbered);
|
let mut seeker = BadIssueSeeker::new(ReportTactic::Unnumbered, ReportTactic::Unnumbered);
|
||||||
assert_eq!(Some(failing_pos),
|
assert_eq!(
|
||||||
text.chars().position(|c| seeker.inspect(c).is_some()));
|
Some(failing_pos),
|
||||||
|
text.chars().position(|c| seeker.inspect(c).is_some())
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_pass(text: &str) {
|
fn check_pass(text: &str) {
|
||||||
|
@ -252,46 +255,60 @@ fn find_issue() {
|
||||||
text.chars().any(|c| seeker.inspect(c).is_some())
|
text.chars().any(|c| seeker.inspect(c).is_some())
|
||||||
}
|
}
|
||||||
|
|
||||||
assert!(is_bad_issue("TODO(@maintainer, #1222, hello)\n",
|
assert!(is_bad_issue(
|
||||||
ReportTactic::Always,
|
"TODO(@maintainer, #1222, hello)\n",
|
||||||
ReportTactic::Never));
|
ReportTactic::Always,
|
||||||
|
ReportTactic::Never,
|
||||||
|
));
|
||||||
|
|
||||||
assert!(!is_bad_issue("TODO: no number\n",
|
assert!(!is_bad_issue(
|
||||||
ReportTactic::Never,
|
"TODO: no number\n",
|
||||||
ReportTactic::Always));
|
ReportTactic::Never,
|
||||||
|
ReportTactic::Always,
|
||||||
|
));
|
||||||
|
|
||||||
assert!(is_bad_issue("This is a FIXME(#1)\n",
|
assert!(is_bad_issue(
|
||||||
ReportTactic::Never,
|
"This is a FIXME(#1)\n",
|
||||||
ReportTactic::Always));
|
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]
|
#[test]
|
||||||
fn issue_type() {
|
fn issue_type() {
|
||||||
let mut seeker = BadIssueSeeker::new(ReportTactic::Always, ReportTactic::Never);
|
let mut seeker = BadIssueSeeker::new(ReportTactic::Always, ReportTactic::Never);
|
||||||
let expected = Some(Issue {
|
let expected = Some(Issue {
|
||||||
issue_type: IssueType::Todo,
|
issue_type: IssueType::Todo,
|
||||||
missing_number: false,
|
missing_number: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
assert_eq!(expected,
|
assert_eq!(
|
||||||
"TODO(#100): more awesomeness"
|
expected,
|
||||||
.chars()
|
"TODO(#100): more awesomeness"
|
||||||
.map(|c| seeker.inspect(c))
|
.chars()
|
||||||
.find(Option::is_some)
|
.map(|c| seeker.inspect(c))
|
||||||
.unwrap());
|
.find(Option::is_some)
|
||||||
|
.unwrap()
|
||||||
|
);
|
||||||
|
|
||||||
let mut seeker = BadIssueSeeker::new(ReportTactic::Never, ReportTactic::Unnumbered);
|
let mut seeker = BadIssueSeeker::new(ReportTactic::Never, ReportTactic::Unnumbered);
|
||||||
let expected = Some(Issue {
|
let expected = Some(Issue {
|
||||||
issue_type: IssueType::Fixme,
|
issue_type: IssueType::Fixme,
|
||||||
missing_number: true,
|
missing_number: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
assert_eq!(expected,
|
assert_eq!(
|
||||||
"Test. FIXME: bad, bad, not good"
|
expected,
|
||||||
.chars()
|
"Test. FIXME: bad, bad, not good"
|
||||||
.map(|c| seeker.inspect(c))
|
.chars()
|
||||||
.find(Option::is_some)
|
.map(|c| seeker.inspect(c))
|
||||||
.unwrap());
|
.find(Option::is_some)
|
||||||
|
.unwrap()
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
1537
src/items.rs
1537
src/items.rs
File diff suppressed because it is too large
Load diff
103
src/lib.rs
103
src/lib.rs
|
@ -189,8 +189,10 @@ impl Sub for Indent {
|
||||||
type Output = Indent;
|
type Output = Indent;
|
||||||
|
|
||||||
fn sub(self, rhs: Indent) -> Indent {
|
fn sub(self, rhs: Indent) -> Indent {
|
||||||
Indent::new(self.block_indent - rhs.block_indent,
|
Indent::new(
|
||||||
self.alignment - rhs.alignment)
|
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> {
|
pub fn sub_width(&self, width: usize) -> Option<Shape> {
|
||||||
Some(Shape {
|
Some(Shape {
|
||||||
width: try_opt!(self.width.checked_sub(width)),
|
width: try_opt!(self.width.checked_sub(width)),
|
||||||
..*self
|
..*self
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn shrink_left(&self, width: usize) -> Option<Shape> {
|
pub fn shrink_left(&self, width: usize) -> Option<Shape> {
|
||||||
Some(Shape {
|
Some(Shape {
|
||||||
width: try_opt!(self.width.checked_sub(width)),
|
width: try_opt!(self.width.checked_sub(width)),
|
||||||
indent: self.indent + width,
|
indent: self.indent + width,
|
||||||
offset: self.offset + width,
|
offset: self.offset + width,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn offset_left(&self, width: usize) -> Option<Shape> {
|
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> {
|
fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
|
||||||
match *self {
|
match *self {
|
||||||
ErrorKind::LineOverflow(found, maximum) => {
|
ErrorKind::LineOverflow(found, maximum) => {
|
||||||
write!(fmt,
|
write!(
|
||||||
"line exceeded maximum length (maximum: {}, found: {})",
|
fmt,
|
||||||
maximum,
|
"line exceeded maximum length (maximum: {}, found: {})",
|
||||||
found)
|
maximum,
|
||||||
|
found
|
||||||
|
)
|
||||||
}
|
}
|
||||||
ErrorKind::TrailingWhitespace => write!(fmt, "left behind trailing whitespace"),
|
ErrorKind::TrailingWhitespace => write!(fmt, "left behind trailing whitespace"),
|
||||||
ErrorKind::BadIssue(issue) => write!(fmt, "found {}", issue),
|
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> {
|
fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
|
||||||
for (file, errors) in &self.file_error_map {
|
for (file, errors) in &self.file_error_map {
|
||||||
for error in errors {
|
for error in errors {
|
||||||
write!(fmt,
|
write!(
|
||||||
"{} {}:{}: {} {}\n",
|
fmt,
|
||||||
error.msg_prefix(),
|
"{} {}:{}: {} {}\n",
|
||||||
file,
|
error.msg_prefix(),
|
||||||
error.line,
|
file,
|
||||||
error.kind,
|
error.line,
|
||||||
error.msg_suffix())?;
|
error.kind,
|
||||||
|
error.msg_suffix()
|
||||||
|
)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -426,14 +432,16 @@ impl fmt::Display for FormatReport {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Formatting which depends on the AST.
|
// Formatting which depends on the AST.
|
||||||
fn format_ast<F>(krate: &ast::Crate,
|
fn format_ast<F>(
|
||||||
mut parse_session: &mut ParseSess,
|
krate: &ast::Crate,
|
||||||
main_file: &Path,
|
mut parse_session: &mut ParseSess,
|
||||||
config: &Config,
|
main_file: &Path,
|
||||||
codemap: &Rc<CodeMap>,
|
config: &Config,
|
||||||
mut after_file: F)
|
codemap: &Rc<CodeMap>,
|
||||||
-> Result<(FileMap, bool), io::Error>
|
mut after_file: F,
|
||||||
where F: FnMut(&str, &mut StringBuffer) -> Result<bool, io::Error>
|
) -> Result<(FileMap, bool), io::Error>
|
||||||
|
where
|
||||||
|
F: FnMut(&str, &mut StringBuffer) -> Result<bool, io::Error>,
|
||||||
{
|
{
|
||||||
let mut result = FileMap::new();
|
let mut result = FileMap::new();
|
||||||
// diff mode: check if any files are differing
|
// 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
|
// Add warnings for bad todos/ fixmes
|
||||||
if let Some(issue) = issue_seeker.inspect(c) {
|
if let Some(issue) = issue_seeker.inspect(c) {
|
||||||
errors.push(FormattingError {
|
errors.push(FormattingError {
|
||||||
line: cur_line,
|
line: cur_line,
|
||||||
kind: ErrorKind::BadIssue(issue),
|
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.
|
// Check for any line width errors we couldn't correct.
|
||||||
if config.error_on_line_overflow() && line_len > config.max_width() {
|
if config.error_on_line_overflow() && line_len > config.max_width() {
|
||||||
errors.push(FormattingError {
|
errors.push(FormattingError {
|
||||||
line: cur_line,
|
line: cur_line,
|
||||||
kind: ErrorKind::LineOverflow(line_len, config.max_width()),
|
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 {
|
for &(l, _, _) in &trims {
|
||||||
errors.push(FormattingError {
|
errors.push(FormattingError {
|
||||||
line: l,
|
line: l,
|
||||||
kind: ErrorKind::TrailingWhitespace,
|
kind: ErrorKind::TrailingWhitespace,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
report.file_error_map.insert(name.to_owned(), errors);
|
report.file_error_map.insert(name.to_owned(), errors);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_input(input: Input,
|
fn parse_input(
|
||||||
parse_session: &ParseSess)
|
input: Input,
|
||||||
-> Result<ast::Crate, Option<DiagnosticBuilder>> {
|
parse_session: &ParseSess,
|
||||||
|
) -> Result<ast::Crate, Option<DiagnosticBuilder>> {
|
||||||
let result = match input {
|
let result = match input {
|
||||||
Input::File(file) => {
|
Input::File(file) => {
|
||||||
let mut parser = parse::new_parser_from_file(parse_session, &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,
|
pub fn format_input<T: Write>(
|
||||||
config: &Config,
|
input: Input,
|
||||||
mut out: Option<&mut T>)
|
config: &Config,
|
||||||
-> Result<(Summary, FileMap, FormatReport), (io::Error, Summary)> {
|
mut out: Option<&mut T>,
|
||||||
|
) -> Result<(Summary, FileMap, FormatReport), (io::Error, Summary)> {
|
||||||
let mut summary = Summary::new();
|
let mut summary = Summary::new();
|
||||||
if config.disable_all_formatting() {
|
if config.disable_all_formatting() {
|
||||||
return Ok((summary, FileMap::new(), FormatReport::new()));
|
return Ok((summary, FileMap::new(), FormatReport::new()));
|
||||||
|
@ -614,7 +624,10 @@ pub fn format_input<T: Write>(input: Input,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Suppress error output after parsing.
|
// 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);
|
parse_session.span_diagnostic = Handler::with_emitter(true, false, silent_emitter);
|
||||||
|
|
||||||
let mut report = FormatReport::new();
|
let mut report = FormatReport::new();
|
||||||
|
|
234
src/lists.rs
234
src/lists.rs
|
@ -69,22 +69,27 @@ pub struct ListFormatting<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn format_fn_args<I>(items: I, shape: Shape, config: &Config) -> Option<String>
|
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,
|
list_helper(
|
||||||
shape,
|
items,
|
||||||
config,
|
shape,
|
||||||
ListTactic::LimitedHorizontalVertical(config.fn_call_width()))
|
config,
|
||||||
|
ListTactic::LimitedHorizontalVertical(config.fn_call_width()),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn format_item_list<I>(items: I, shape: Shape, config: &Config) -> Option<String>
|
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)
|
list_helper(items, shape, config, ListTactic::HorizontalVertical)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn list_helper<I>(items: I, shape: Shape, config: &Config, tactic: ListTactic) -> Option<String>
|
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 item_vec: Vec<_> = items.collect();
|
||||||
let tactic = definitive_tactic(&item_vec, tactic, shape.width);
|
let tactic = definitive_tactic(&item_vec, tactic, shape.width);
|
||||||
|
@ -120,15 +125,16 @@ pub struct ListItem {
|
||||||
impl ListItem {
|
impl ListItem {
|
||||||
pub fn is_multiline(&self) -> bool {
|
pub fn is_multiline(&self) -> bool {
|
||||||
self.item.as_ref().map_or(false, |s| s.contains('\n')) || self.pre_comment.is_some() ||
|
self.item.as_ref().map_or(false, |s| s.contains('\n')) || self.pre_comment.is_some() ||
|
||||||
self.post_comment
|
self.post_comment.as_ref().map_or(
|
||||||
.as_ref()
|
false,
|
||||||
.map_or(false, |s| s.contains('\n'))
|
|s| s.contains('\n'),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn has_line_pre_comment(&self) -> bool {
|
pub fn has_line_pre_comment(&self) -> bool {
|
||||||
self.pre_comment
|
self.pre_comment.as_ref().map_or(false, |comment| {
|
||||||
.as_ref()
|
comment.starts_with("//")
|
||||||
.map_or(false, |comment| comment.starts_with("//"))
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn from_str<S: Into<String>>(s: S) -> ListItem {
|
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
|
pub fn definitive_tactic<I, T>(items: I, tactic: ListTactic, width: usize) -> DefinitiveListTactic
|
||||||
where I: IntoIterator<Item = T> + Clone,
|
where
|
||||||
T: AsRef<ListItem>
|
I: IntoIterator<Item = T> + Clone,
|
||||||
|
T: AsRef<ListItem>,
|
||||||
{
|
{
|
||||||
let pre_line_comments = items
|
let pre_line_comments = items.clone().into_iter().any(|item| {
|
||||||
.clone()
|
item.as_ref().has_line_pre_comment()
|
||||||
.into_iter()
|
});
|
||||||
.any(|item| item.as_ref().has_line_pre_comment());
|
|
||||||
|
|
||||||
let limit = match tactic {
|
let limit = match tactic {
|
||||||
_ if pre_line_comments => return DefinitiveListTactic::Vertical,
|
_ 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;
|
let real_total = total_width + total_sep_len;
|
||||||
|
|
||||||
if real_total <= limit && !pre_line_comments &&
|
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
|
DefinitiveListTactic::Horizontal
|
||||||
} else {
|
} else {
|
||||||
DefinitiveListTactic::Vertical
|
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.
|
// Format a list of commented items into a string.
|
||||||
// TODO: add unit tests
|
// TODO: add unit tests
|
||||||
pub fn write_list<I, T>(items: I, formatting: &ListFormatting) -> Option<String>
|
pub fn write_list<I, T>(items: I, formatting: &ListFormatting) -> Option<String>
|
||||||
where I: IntoIterator<Item = T>,
|
where
|
||||||
T: AsRef<ListItem>
|
I: IntoIterator<Item = T>,
|
||||||
|
T: AsRef<ListItem>,
|
||||||
{
|
{
|
||||||
let tactic = formatting.tactic;
|
let tactic = formatting.tactic;
|
||||||
let sep_len = formatting.separator.len();
|
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.
|
// Block style in non-vertical mode.
|
||||||
let block_mode = tactic != DefinitiveListTactic::Vertical;
|
let block_mode = tactic != DefinitiveListTactic::Vertical;
|
||||||
// Width restriction is only relevant in vertical mode.
|
// Width restriction is only relevant in vertical mode.
|
||||||
let comment =
|
let comment = try_opt!(rewrite_comment(
|
||||||
try_opt!(rewrite_comment(comment, block_mode, formatting.shape, formatting.config));
|
comment,
|
||||||
|
block_mode,
|
||||||
|
formatting.shape,
|
||||||
|
formatting.config,
|
||||||
|
));
|
||||||
result.push_str(&comment);
|
result.push_str(&comment);
|
||||||
|
|
||||||
if tactic == DefinitiveListTactic::Vertical {
|
if tactic == DefinitiveListTactic::Vertical {
|
||||||
|
@ -267,11 +279,12 @@ pub fn write_list<I, T>(items: I, formatting: &ListFormatting) -> Option<String>
|
||||||
// Post-comments
|
// Post-comments
|
||||||
if tactic != DefinitiveListTactic::Vertical && item.post_comment.is_some() {
|
if tactic != DefinitiveListTactic::Vertical && item.post_comment.is_some() {
|
||||||
let comment = item.post_comment.as_ref().unwrap();
|
let comment = item.post_comment.as_ref().unwrap();
|
||||||
let formatted_comment =
|
let formatted_comment = try_opt!(rewrite_comment(
|
||||||
try_opt!(rewrite_comment(comment,
|
comment,
|
||||||
true,
|
true,
|
||||||
Shape::legacy(formatting.shape.width, Indent::empty()),
|
Shape::legacy(formatting.shape.width, Indent::empty()),
|
||||||
formatting.config));
|
formatting.config,
|
||||||
|
));
|
||||||
|
|
||||||
result.push(' ');
|
result.push(' ');
|
||||||
result.push_str(&formatted_comment);
|
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);
|
debug!("Width = {}, offset = {:?}", width, offset);
|
||||||
// Use block-style only for the last item or multiline comments.
|
// Use block-style only for the last item or multiline comments.
|
||||||
let block_style = !formatting.ends_with_newline && last ||
|
let block_style = !formatting.ends_with_newline && last ||
|
||||||
comment.trim().contains('\n') ||
|
comment.trim().contains('\n') ||
|
||||||
comment.trim().len() > width;
|
comment.trim().len() > width;
|
||||||
|
|
||||||
let formatted_comment = try_opt!(rewrite_comment(comment,
|
let formatted_comment = try_opt!(rewrite_comment(
|
||||||
block_style,
|
comment,
|
||||||
Shape::legacy(width, offset),
|
block_style,
|
||||||
formatting.config));
|
Shape::legacy(width, offset),
|
||||||
|
formatting.config,
|
||||||
|
));
|
||||||
|
|
||||||
if !formatted_comment.starts_with('\n') {
|
if !formatted_comment.starts_with('\n') {
|
||||||
result.push(' ');
|
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>
|
pub struct ListItems<'a, I, F1, F2, F3>
|
||||||
where I: Iterator
|
where
|
||||||
|
I: Iterator,
|
||||||
{
|
{
|
||||||
codemap: &'a CodeMap,
|
codemap: &'a CodeMap,
|
||||||
inner: Peekable<I>,
|
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>
|
impl<'a, T, I, F1, F2, F3> Iterator for ListItems<'a, I, F1, F2, F3>
|
||||||
where I: Iterator<Item = T>,
|
where
|
||||||
F1: Fn(&T) -> BytePos,
|
I: Iterator<Item = T>,
|
||||||
F2: Fn(&T) -> BytePos,
|
F1: Fn(&T) -> BytePos,
|
||||||
F3: Fn(&T) -> Option<String>
|
F2: Fn(&T) -> BytePos,
|
||||||
|
F3: Fn(&T) -> Option<String>,
|
||||||
{
|
{
|
||||||
type Item = ListItem;
|
type Item = ListItem;
|
||||||
|
|
||||||
|
@ -349,7 +366,7 @@ impl<'a, T, I, F1, F2, F3> Iterator for ListItems<'a, I, F1, F2, F3>
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let trimmed_pre_snippet = pre_snippet.trim();
|
let trimmed_pre_snippet = pre_snippet.trim();
|
||||||
let has_pre_comment = trimmed_pre_snippet.contains("//") ||
|
let has_pre_comment = trimmed_pre_snippet.contains("//") ||
|
||||||
trimmed_pre_snippet.contains("/*");
|
trimmed_pre_snippet.contains("/*");
|
||||||
let pre_comment = if has_pre_comment {
|
let pre_comment = if has_pre_comment {
|
||||||
Some(trimmed_pre_snippet.to_owned())
|
Some(trimmed_pre_snippet.to_owned())
|
||||||
} else {
|
} 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,
|
(Some(i), None) if i > separator_index => separator_index + 1,
|
||||||
// Block-style post-comment before the separator.
|
// Block-style post-comment before the separator.
|
||||||
(Some(i), None) => {
|
(Some(i), None) => {
|
||||||
cmp::max(find_comment_end(&post_snippet[i..]).unwrap() + i,
|
cmp::max(
|
||||||
separator_index + 1)
|
find_comment_end(&post_snippet[i..]).unwrap() + i,
|
||||||
|
separator_index + 1,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
// Block-style post-comment. Either before or after the separator.
|
// Block-style post-comment. Either before or after the separator.
|
||||||
(Some(i), Some(j)) if i < j => {
|
(Some(i), Some(j)) if i < j => {
|
||||||
cmp::max(find_comment_end(&post_snippet[i..]).unwrap() + i,
|
cmp::max(
|
||||||
separator_index + 1)
|
find_comment_end(&post_snippet[i..]).unwrap() + i,
|
||||||
|
separator_index + 1,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
// Potential *single* line comment.
|
// Potential *single* line comment.
|
||||||
(_, Some(j)) if j > separator_index => j + 1,
|
(_, 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 => {
|
None => {
|
||||||
post_snippet
|
post_snippet.find_uncommented(self.terminator).unwrap_or(
|
||||||
.find_uncommented(self.terminator)
|
post_snippet
|
||||||
.unwrap_or(post_snippet.len())
|
.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());
|
let first_newline = test_snippet.find('\n').unwrap_or(test_snippet.len());
|
||||||
// From the end of the first line of comments.
|
// From the end of the first line of comments.
|
||||||
let test_snippet = &test_snippet[first_newline..];
|
let test_snippet = &test_snippet[first_newline..];
|
||||||
let first = test_snippet
|
let first = test_snippet.find(|c: char| !c.is_whitespace()).unwrap_or(
|
||||||
.find(|c: char| !c.is_whitespace())
|
test_snippet
|
||||||
.unwrap_or(test_snippet.len());
|
.len(),
|
||||||
|
);
|
||||||
// From the end of the first line of comments to the next non-whitespace char.
|
// From the end of the first line of comments to the next non-whitespace char.
|
||||||
let test_snippet = &test_snippet[..first];
|
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.
|
// Creates an iterator over a list's items with associated comments.
|
||||||
pub fn itemize_list<'a, T, I, F1, F2, F3>(codemap: &'a CodeMap,
|
pub fn itemize_list<'a, T, I, F1, F2, F3>(
|
||||||
inner: I,
|
codemap: &'a CodeMap,
|
||||||
terminator: &'a str,
|
inner: I,
|
||||||
get_lo: F1,
|
terminator: &'a str,
|
||||||
get_hi: F2,
|
get_lo: F1,
|
||||||
get_item_string: F3,
|
get_hi: F2,
|
||||||
prev_span_end: BytePos,
|
get_item_string: F3,
|
||||||
next_span_start: BytePos)
|
prev_span_end: BytePos,
|
||||||
-> ListItems<'a, I, F1, F2, F3>
|
next_span_start: BytePos,
|
||||||
where I: Iterator<Item = T>,
|
) -> ListItems<'a, I, F1, F2, F3>
|
||||||
F1: Fn(&T) -> BytePos,
|
where
|
||||||
F2: Fn(&T) -> BytePos,
|
I: Iterator<Item = T>,
|
||||||
F3: Fn(&T) -> Option<String>
|
F1: Fn(&T) -> BytePos,
|
||||||
|
F2: Fn(&T) -> BytePos,
|
||||||
|
F3: Fn(&T) -> Option<String>,
|
||||||
{
|
{
|
||||||
ListItems {
|
ListItems {
|
||||||
codemap: codemap,
|
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,
|
fn needs_trailing_separator(
|
||||||
list_tactic: DefinitiveListTactic)
|
separator_tactic: SeparatorTactic,
|
||||||
-> bool {
|
list_tactic: DefinitiveListTactic,
|
||||||
|
) -> bool {
|
||||||
match separator_tactic {
|
match separator_tactic {
|
||||||
SeparatorTactic::Always => true,
|
SeparatorTactic::Always => true,
|
||||||
SeparatorTactic::Vertical => list_tactic == DefinitiveListTactic::Vertical,
|
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.
|
/// Returns the count and total width of the list items.
|
||||||
fn calculate_width<I, T>(items: I) -> (usize, usize)
|
fn calculate_width<I, T>(items: I) -> (usize, usize)
|
||||||
where I: IntoIterator<Item = T>,
|
where
|
||||||
T: AsRef<ListItem>
|
I: IntoIterator<Item = T>,
|
||||||
|
T: AsRef<ListItem>,
|
||||||
{
|
{
|
||||||
items
|
items
|
||||||
.into_iter()
|
.into_iter()
|
||||||
|
@ -502,8 +529,8 @@ fn calculate_width<I, T>(items: I) -> (usize, usize)
|
||||||
|
|
||||||
fn total_item_width(item: &ListItem) -> usize {
|
fn total_item_width(item: &ListItem) -> usize {
|
||||||
comment_len(item.pre_comment.as_ref().map(|x| &(*x)[..])) +
|
comment_len(item.pre_comment.as_ref().map(|x| &(*x)[..])) +
|
||||||
comment_len(item.post_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())
|
item.item.as_ref().map_or(0, |str| str.len())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn comment_len(comment: Option<&str>) -> usize {
|
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.
|
// Compute horizontal and vertical shapes for a struct-lit-like thing.
|
||||||
pub fn struct_lit_shape(shape: Shape,
|
pub fn struct_lit_shape(
|
||||||
context: &RewriteContext,
|
shape: Shape,
|
||||||
prefix_width: usize,
|
context: &RewriteContext,
|
||||||
suffix_width: usize)
|
prefix_width: usize,
|
||||||
-> Option<(Option<Shape>, Shape)> {
|
suffix_width: usize,
|
||||||
let v_shape = match context.config.struct_lit_style() {
|
) -> Option<(Option<Shape>, Shape)> {
|
||||||
IndentStyle::Visual => {
|
let v_shape =
|
||||||
try_opt!(try_opt!(shape.visual_indent(0).shrink_left(prefix_width))
|
match context.config.struct_lit_style() {
|
||||||
|
IndentStyle::Visual => {
|
||||||
|
try_opt!(try_opt!(shape.visual_indent(0).shrink_left(prefix_width))
|
||||||
.sub_width(suffix_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);
|
let h_shape = shape.sub_width(prefix_width + suffix_width);
|
||||||
Some((h_shape, v_shape))
|
Some((h_shape, v_shape))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Compute the tactic for the internals of a struct-lit-like thing.
|
// Compute the tactic for the internals of a struct-lit-like thing.
|
||||||
pub fn struct_lit_tactic(h_shape: Option<Shape>,
|
pub fn struct_lit_tactic(
|
||||||
context: &RewriteContext,
|
h_shape: Option<Shape>,
|
||||||
items: &[ListItem])
|
context: &RewriteContext,
|
||||||
-> DefinitiveListTactic {
|
items: &[ListItem],
|
||||||
|
) -> DefinitiveListTactic {
|
||||||
if let Some(h_shape) = h_shape {
|
if let Some(h_shape) = h_shape {
|
||||||
let mut prelim_tactic = match (context.config.struct_lit_style(), items.len()) {
|
let mut prelim_tactic = match (context.config.struct_lit_style(), items.len()) {
|
||||||
(IndentStyle::Visual, 1) => ListTactic::HorizontalVertical,
|
(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,
|
// Given a tactic and possible shapes for horizontal and vertical layout,
|
||||||
// come up with the actual shape to use.
|
// come up with the actual shape to use.
|
||||||
pub fn shape_for_tactic(tactic: DefinitiveListTactic,
|
pub fn shape_for_tactic(
|
||||||
h_shape: Option<Shape>,
|
tactic: DefinitiveListTactic,
|
||||||
v_shape: Shape)
|
h_shape: Option<Shape>,
|
||||||
-> Shape {
|
v_shape: Shape,
|
||||||
|
) -> Shape {
|
||||||
match tactic {
|
match tactic {
|
||||||
DefinitiveListTactic::Horizontal => h_shape.unwrap(),
|
DefinitiveListTactic::Horizontal => h_shape.unwrap(),
|
||||||
_ => v_shape,
|
_ => v_shape,
|
||||||
|
@ -580,13 +611,14 @@ pub fn shape_for_tactic(tactic: DefinitiveListTactic,
|
||||||
|
|
||||||
// Create a ListFormatting object for formatting the internals of a
|
// Create a ListFormatting object for formatting the internals of a
|
||||||
// struct-lit-like thing, that is a series of fields.
|
// struct-lit-like thing, that is a series of fields.
|
||||||
pub fn struct_lit_formatting<'a>(shape: Shape,
|
pub fn struct_lit_formatting<'a>(
|
||||||
tactic: DefinitiveListTactic,
|
shape: Shape,
|
||||||
context: &'a RewriteContext,
|
tactic: DefinitiveListTactic,
|
||||||
force_no_trailing_comma: bool)
|
context: &'a RewriteContext,
|
||||||
-> ListFormatting<'a> {
|
force_no_trailing_comma: bool,
|
||||||
|
) -> ListFormatting<'a> {
|
||||||
let ends_with_newline = context.config.struct_lit_style() != IndentStyle::Visual &&
|
let ends_with_newline = context.config.struct_lit_style() != IndentStyle::Visual &&
|
||||||
tactic == DefinitiveListTactic::Vertical;
|
tactic == DefinitiveListTactic::Vertical;
|
||||||
ListFormatting {
|
ListFormatting {
|
||||||
tactic: tactic,
|
tactic: tactic,
|
||||||
separator: ",",
|
separator: ",",
|
||||||
|
|
|
@ -61,12 +61,13 @@ impl MacroStyle {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn rewrite_macro(mac: &ast::Mac,
|
pub fn rewrite_macro(
|
||||||
extra_ident: Option<ast::Ident>,
|
mac: &ast::Mac,
|
||||||
context: &RewriteContext,
|
extra_ident: Option<ast::Ident>,
|
||||||
shape: Shape,
|
context: &RewriteContext,
|
||||||
position: MacroPosition)
|
shape: Shape,
|
||||||
-> Option<String> {
|
position: MacroPosition,
|
||||||
|
) -> Option<String> {
|
||||||
let mut context = &mut context.clone();
|
let mut context = &mut context.clone();
|
||||||
context.inside_macro = true;
|
context.inside_macro = true;
|
||||||
if context.config.use_try_shorthand() {
|
if context.config.use_try_shorthand() {
|
||||||
|
@ -191,24 +192,29 @@ pub fn rewrite_macro(mac: &ast::Mac,
|
||||||
} else {
|
} else {
|
||||||
("[", "]")
|
("[", "]")
|
||||||
};
|
};
|
||||||
rewrite_pair(&*expr_vec[0],
|
rewrite_pair(
|
||||||
&*expr_vec[1],
|
&*expr_vec[0],
|
||||||
lbr,
|
&*expr_vec[1],
|
||||||
"; ",
|
lbr,
|
||||||
rbr,
|
"; ",
|
||||||
context,
|
rbr,
|
||||||
mac_shape)
|
context,
|
||||||
.map(|s| format!("{}{}", macro_name, s))
|
mac_shape,
|
||||||
|
).map(|s| format!("{}{}", macro_name, s))
|
||||||
} else {
|
} else {
|
||||||
// Format macro invocation as array literal.
|
// Format macro invocation as array literal.
|
||||||
let rewrite =
|
let rewrite = try_opt!(rewrite_array(
|
||||||
try_opt!(rewrite_array(expr_vec.iter().map(|x| &**x),
|
expr_vec.iter().map(|x| &**x),
|
||||||
mk_sp(context
|
mk_sp(
|
||||||
.codemap
|
context.codemap.span_after(
|
||||||
.span_after(mac.span, original_style.opener()),
|
mac.span,
|
||||||
mac.span.hi - BytePos(1)),
|
original_style.opener(),
|
||||||
context,
|
),
|
||||||
mac_shape));
|
mac.span.hi - BytePos(1),
|
||||||
|
),
|
||||||
|
context,
|
||||||
|
mac_shape,
|
||||||
|
));
|
||||||
|
|
||||||
Some(format!("{}{}", macro_name, rewrite))
|
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());
|
let mut parser = new_parser_from_tts(context.parse_session, ts.trees().collect());
|
||||||
|
|
||||||
Some(ast::Expr {
|
Some(ast::Expr {
|
||||||
id: ast::NodeId::new(0), // dummy value
|
id: ast::NodeId::new(0), // dummy value
|
||||||
node: ast::ExprKind::Try(try_opt!(parser.parse_expr().ok())),
|
node: ast::ExprKind::Try(try_opt!(parser.parse_expr().ok())),
|
||||||
span: mac.span, // incorrect span, but shouldn't matter too much
|
span: mac.span, // incorrect span, but shouldn't matter too much
|
||||||
attrs: ThinVec::new(),
|
attrs: ThinVec::new(),
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
|
@ -47,9 +47,11 @@ impl<'a> FmtVisitor<'a> {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn format_missing_inner<F: Fn(&mut FmtVisitor, &str, &str)>(&mut self,
|
fn format_missing_inner<F: Fn(&mut FmtVisitor, &str, &str)>(
|
||||||
end: BytePos,
|
&mut self,
|
||||||
process_last_snippet: F) {
|
end: BytePos,
|
||||||
|
process_last_snippet: F,
|
||||||
|
) {
|
||||||
let start = self.last_pos;
|
let start = self.last_pos;
|
||||||
|
|
||||||
if start == end {
|
if start == end {
|
||||||
|
@ -60,10 +62,12 @@ impl<'a> FmtVisitor<'a> {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
assert!(start < end,
|
assert!(
|
||||||
"Request to format inverted span: {:?} to {:?}",
|
start < end,
|
||||||
self.codemap.lookup_char_pos(start),
|
"Request to format inverted span: {:?} to {:?}",
|
||||||
self.codemap.lookup_char_pos(end));
|
self.codemap.lookup_char_pos(start),
|
||||||
|
self.codemap.lookup_char_pos(end)
|
||||||
|
);
|
||||||
|
|
||||||
self.last_pos = end;
|
self.last_pos = end;
|
||||||
let span = mk_sp(start, 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)
|
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.
|
// 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
|
// 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);
|
self.write_snippet_inner(big_snippet, big_diff, &snippet, span, process_last_snippet);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn write_snippet_inner<F>(&mut self,
|
fn write_snippet_inner<F>(
|
||||||
big_snippet: &str,
|
&mut self,
|
||||||
big_diff: usize,
|
big_snippet: &str,
|
||||||
old_snippet: &str,
|
big_diff: usize,
|
||||||
span: Span,
|
old_snippet: &str,
|
||||||
process_last_snippet: F)
|
span: Span,
|
||||||
where F: Fn(&mut FmtVisitor, &str, &str)
|
process_last_snippet: F,
|
||||||
|
) where
|
||||||
|
F: Fn(&mut FmtVisitor, &str, &str),
|
||||||
{
|
{
|
||||||
// Trim whitespace from the right hand side of each line.
|
// Trim whitespace from the right hand side of each line.
|
||||||
// Annoyingly, the library functions for splitting by lines etc. are not
|
// 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();
|
let subslice_num_lines = subslice.chars().filter(|c| *c == '\n').count();
|
||||||
|
|
||||||
if rewrite_next_comment &&
|
if rewrite_next_comment &&
|
||||||
!self.config
|
!self.config.file_lines().intersects_range(
|
||||||
.file_lines()
|
file_name,
|
||||||
.intersects_range(file_name, cur_line, cur_line + subslice_num_lines) {
|
cur_line,
|
||||||
|
cur_line + subslice_num_lines,
|
||||||
|
)
|
||||||
|
{
|
||||||
rewrite_next_comment = false;
|
rewrite_next_comment = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -150,32 +160,34 @@ impl<'a> FmtVisitor<'a> {
|
||||||
if let Some('{') = last_char {
|
if let Some('{') = last_char {
|
||||||
self.buffer.push_str("\n");
|
self.buffer.push_str("\n");
|
||||||
}
|
}
|
||||||
self.buffer
|
self.buffer.push_str(
|
||||||
.push_str(&self.block_indent.to_string(self.config));
|
&self.block_indent.to_string(self.config),
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
self.buffer.push_str(" ");
|
self.buffer.push_str(" ");
|
||||||
}
|
}
|
||||||
|
|
||||||
let comment_width = ::std::cmp::min(self.config.comment_width(),
|
let comment_width = ::std::cmp::min(
|
||||||
self.config.max_width() -
|
self.config.comment_width(),
|
||||||
self.block_indent.width());
|
self.config.max_width() - self.block_indent.width(),
|
||||||
|
);
|
||||||
|
|
||||||
self.buffer.push_str(&rewrite_comment(subslice,
|
self.buffer.push_str(&rewrite_comment(
|
||||||
false,
|
subslice,
|
||||||
Shape::legacy(comment_width,
|
false,
|
||||||
self.block_indent),
|
Shape::legacy(comment_width, self.block_indent),
|
||||||
self.config)
|
self.config,
|
||||||
.unwrap());
|
).unwrap());
|
||||||
|
|
||||||
last_wspace = None;
|
last_wspace = None;
|
||||||
line_start = offset + subslice.len();
|
line_start = offset + subslice.len();
|
||||||
|
|
||||||
if let Some('/') = subslice.chars().skip(1).next() {
|
if let Some('/') = subslice.chars().skip(1).next() {
|
||||||
// check that there are no contained block comments
|
// check that there are no contained block comments
|
||||||
if !subslice
|
if !subslice.split('\n').map(|s| s.trim_left()).any(|s| {
|
||||||
.split('\n')
|
s.len() >= 2 && &s[0..2] == "/*"
|
||||||
.map(|s| s.trim_left())
|
})
|
||||||
.any(|s| s.len() >= 2 && &s[0..2] == "/*") {
|
{
|
||||||
// Add a newline after line comments
|
// Add a newline after line comments
|
||||||
self.buffer.push_str("\n");
|
self.buffer.push_str("\n");
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,30 +20,35 @@ use syntax::parse::parser;
|
||||||
|
|
||||||
/// List all the files containing modules of a crate.
|
/// List all the files containing modules of a crate.
|
||||||
/// If a file is used twice in a crate, it appears only once.
|
/// If a file is used twice in a crate, it appears only once.
|
||||||
pub fn list_files<'a>(krate: &'a ast::Crate,
|
pub fn list_files<'a>(
|
||||||
codemap: &codemap::CodeMap)
|
krate: &'a ast::Crate,
|
||||||
-> BTreeMap<PathBuf, &'a ast::Mod> {
|
codemap: &codemap::CodeMap,
|
||||||
|
) -> BTreeMap<PathBuf, &'a ast::Mod> {
|
||||||
let mut result = BTreeMap::new(); // Enforce file order determinism
|
let mut result = BTreeMap::new(); // Enforce file order determinism
|
||||||
let root_filename: PathBuf = codemap.span_to_filename(krate.span).into();
|
let root_filename: PathBuf = codemap.span_to_filename(krate.span).into();
|
||||||
list_submodules(&krate.module,
|
list_submodules(
|
||||||
root_filename.parent().unwrap(),
|
&krate.module,
|
||||||
codemap,
|
root_filename.parent().unwrap(),
|
||||||
&mut result);
|
codemap,
|
||||||
|
&mut result,
|
||||||
|
);
|
||||||
result.insert(root_filename, &krate.module);
|
result.insert(root_filename, &krate.module);
|
||||||
result
|
result
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Recursively list all external modules included in a module.
|
/// Recursively list all external modules included in a module.
|
||||||
fn list_submodules<'a>(module: &'a ast::Mod,
|
fn list_submodules<'a>(
|
||||||
search_dir: &Path,
|
module: &'a ast::Mod,
|
||||||
codemap: &codemap::CodeMap,
|
search_dir: &Path,
|
||||||
result: &mut BTreeMap<PathBuf, &'a ast::Mod>) {
|
codemap: &codemap::CodeMap,
|
||||||
|
result: &mut BTreeMap<PathBuf, &'a ast::Mod>,
|
||||||
|
) {
|
||||||
debug!("list_submodules: search_dir: {:?}", search_dir);
|
debug!("list_submodules: search_dir: {:?}", search_dir);
|
||||||
for item in &module.items {
|
for item in &module.items {
|
||||||
if let ast::ItemKind::Mod(ref sub_mod) = item.node {
|
if let ast::ItemKind::Mod(ref sub_mod) = item.node {
|
||||||
if !utils::contains_skip(&item.attrs) {
|
if !utils::contains_skip(&item.attrs) {
|
||||||
let is_internal = codemap.span_to_filename(item.span) ==
|
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 {
|
let dir_path = if is_internal {
|
||||||
search_dir.join(&item.ident.to_string())
|
search_dir.join(&item.ident.to_string())
|
||||||
} else {
|
} else {
|
||||||
|
@ -59,11 +64,12 @@ fn list_submodules<'a>(module: &'a ast::Mod,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Find the file corresponding to an external mod
|
/// Find the file corresponding to an external mod
|
||||||
fn module_file(id: ast::Ident,
|
fn module_file(
|
||||||
attrs: &[ast::Attribute],
|
id: ast::Ident,
|
||||||
dir_path: &Path,
|
attrs: &[ast::Attribute],
|
||||||
codemap: &codemap::CodeMap)
|
dir_path: &Path,
|
||||||
-> PathBuf {
|
codemap: &codemap::CodeMap,
|
||||||
|
) -> PathBuf {
|
||||||
if let Some(path) = parser::Parser::submod_path_from_attr(attrs, dir_path) {
|
if let Some(path) = parser::Parser::submod_path_from_attr(attrs, dir_path) {
|
||||||
return path;
|
return path;
|
||||||
}
|
}
|
||||||
|
|
192
src/patterns.rs
192
src/patterns.rs
|
@ -39,12 +39,13 @@ impl Rewrite for Pat {
|
||||||
let sub_pat = match *sub_pat {
|
let sub_pat = match *sub_pat {
|
||||||
Some(ref p) => {
|
Some(ref p) => {
|
||||||
// 3 - ` @ `.
|
// 3 - ` @ `.
|
||||||
let width =
|
let width = try_opt!(shape.width.checked_sub(
|
||||||
try_opt!(shape.width.checked_sub(prefix.len() + mut_infix.len() +
|
prefix.len() + mut_infix.len() + id_str.len() + 3,
|
||||||
id_str.len() +
|
));
|
||||||
3));
|
format!(
|
||||||
format!(" @ {}",
|
" @ {}",
|
||||||
try_opt!(p.rewrite(context, Shape::legacy(width, shape.indent))))
|
try_opt!(p.rewrite(context, Shape::legacy(width, shape.indent)))
|
||||||
|
)
|
||||||
}
|
}
|
||||||
None => "".to_owned(),
|
None => "".to_owned(),
|
||||||
};
|
};
|
||||||
|
@ -80,23 +81,23 @@ impl Rewrite for Pat {
|
||||||
rewrite_path(context, PathContext::Expr, q_self.as_ref(), path, shape)
|
rewrite_path(context, PathContext::Expr, q_self.as_ref(), path, shape)
|
||||||
}
|
}
|
||||||
PatKind::TupleStruct(ref path, ref pat_vec, dotdot_pos) => {
|
PatKind::TupleStruct(ref path, ref pat_vec, dotdot_pos) => {
|
||||||
let path_str =
|
let path_str = try_opt!(rewrite_path(context, PathContext::Expr, None, path, shape));
|
||||||
try_opt!(rewrite_path(context, PathContext::Expr, None, path, shape));
|
rewrite_tuple_pat(
|
||||||
rewrite_tuple_pat(pat_vec,
|
pat_vec,
|
||||||
dotdot_pos,
|
dotdot_pos,
|
||||||
Some(path_str),
|
Some(path_str),
|
||||||
self.span,
|
self.span,
|
||||||
context,
|
context,
|
||||||
shape)
|
shape,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
PatKind::Lit(ref expr) => expr.rewrite(context, shape),
|
PatKind::Lit(ref expr) => expr.rewrite(context, shape),
|
||||||
PatKind::Slice(ref prefix, ref slice_pat, ref suffix) => {
|
PatKind::Slice(ref prefix, ref slice_pat, ref suffix) => {
|
||||||
// Rewrite all the sub-patterns.
|
// Rewrite all the sub-patterns.
|
||||||
let prefix = prefix.iter().map(|p| p.rewrite(context, shape));
|
let prefix = prefix.iter().map(|p| p.rewrite(context, shape));
|
||||||
let slice_pat =
|
let slice_pat = slice_pat.as_ref().map(|p| {
|
||||||
slice_pat
|
Some(format!("{}..", try_opt!(p.rewrite(context, shape))))
|
||||||
.as_ref()
|
});
|
||||||
.map(|p| Some(format!("{}..", try_opt!(p.rewrite(context, shape)))));
|
|
||||||
let suffix = suffix.iter().map(|p| p.rewrite(context, shape));
|
let suffix = suffix.iter().map(|p| p.rewrite(context, shape));
|
||||||
|
|
||||||
// Munge them together.
|
// Munge them together.
|
||||||
|
@ -119,24 +120,33 @@ impl Rewrite for Pat {
|
||||||
}
|
}
|
||||||
// FIXME(#819) format pattern macros.
|
// FIXME(#819) format pattern macros.
|
||||||
PatKind::Mac(..) => {
|
PatKind::Mac(..) => {
|
||||||
wrap_str(context.snippet(self.span),
|
wrap_str(
|
||||||
context.config.max_width(),
|
context.snippet(self.span),
|
||||||
shape)
|
context.config.max_width(),
|
||||||
|
shape,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn rewrite_struct_pat(path: &ast::Path,
|
fn rewrite_struct_pat(
|
||||||
fields: &[codemap::Spanned<ast::FieldPat>],
|
path: &ast::Path,
|
||||||
elipses: bool,
|
fields: &[codemap::Spanned<ast::FieldPat>],
|
||||||
span: Span,
|
elipses: bool,
|
||||||
context: &RewriteContext,
|
span: Span,
|
||||||
shape: Shape)
|
context: &RewriteContext,
|
||||||
-> Option<String> {
|
shape: Shape,
|
||||||
|
) -> Option<String> {
|
||||||
// 2 = ` {`
|
// 2 = ` {`
|
||||||
let path_shape = try_opt!(shape.sub_width(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 {
|
if fields.len() == 0 && !elipses {
|
||||||
return Some(format!("{} {{}}", path_str));
|
return Some(format!("{} {{}}", path_str));
|
||||||
|
@ -145,17 +155,23 @@ fn rewrite_struct_pat(path: &ast::Path,
|
||||||
let (elipses_str, terminator) = if elipses { (", ..", "..") } else { ("", "}") };
|
let (elipses_str, terminator) = if elipses { (", ..", "..") } else { ("", "}") };
|
||||||
|
|
||||||
// 3 = ` { `, 2 = ` }`.
|
// 3 = ` { `, 2 = ` }`.
|
||||||
let (h_shape, v_shape) =
|
let (h_shape, v_shape) = try_opt!(struct_lit_shape(
|
||||||
try_opt!(struct_lit_shape(shape, context, path_str.len() + 3, elipses_str.len() + 2));
|
shape,
|
||||||
|
context,
|
||||||
|
path_str.len() + 3,
|
||||||
|
elipses_str.len() + 2,
|
||||||
|
));
|
||||||
|
|
||||||
let items = itemize_list(context.codemap,
|
let items = itemize_list(
|
||||||
fields.iter(),
|
context.codemap,
|
||||||
terminator,
|
fields.iter(),
|
||||||
|f| f.span.lo,
|
terminator,
|
||||||
|f| f.span.hi,
|
|f| f.span.lo,
|
||||||
|f| f.node.rewrite(context, v_shape),
|
|f| f.span.hi,
|
||||||
context.codemap.span_after(span, "{"),
|
|f| f.node.rewrite(context, v_shape),
|
||||||
span.hi);
|
context.codemap.span_after(span, "{"),
|
||||||
|
span.hi,
|
||||||
|
);
|
||||||
let item_vec = items.collect::<Vec<_>>();
|
let item_vec = items.collect::<Vec<_>>();
|
||||||
|
|
||||||
let tactic = struct_lit_tactic(h_shape, context, &item_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 &&
|
let fields_str = if context.config.struct_lit_style() == IndentStyle::Block &&
|
||||||
(fields_str.contains('\n') ||
|
(fields_str.contains('\n') ||
|
||||||
context.config.struct_lit_multiline_style() ==
|
context.config.struct_lit_multiline_style() == MultilineStyle::ForceMulti ||
|
||||||
MultilineStyle::ForceMulti ||
|
fields_str.len() > h_shape.map(|s| s.width).unwrap_or(0))
|
||||||
fields_str.len() > h_shape.map(|s| s.width).unwrap_or(0)) {
|
{
|
||||||
format!("\n{}{}\n{}",
|
format!(
|
||||||
v_shape.indent.to_string(context.config),
|
"\n{}{}\n{}",
|
||||||
fields_str,
|
v_shape.indent.to_string(context.config),
|
||||||
shape.indent.to_string(context.config))
|
fields_str,
|
||||||
|
shape.indent.to_string(context.config)
|
||||||
|
)
|
||||||
} else {
|
} else {
|
||||||
// One liner or visual indent.
|
// One liner or visual indent.
|
||||||
format!(" {} ", fields_str)
|
format!(" {} ", fields_str)
|
||||||
|
@ -211,9 +229,11 @@ impl Rewrite for FieldPat {
|
||||||
if self.is_shorthand {
|
if self.is_shorthand {
|
||||||
pat
|
pat
|
||||||
} else {
|
} else {
|
||||||
wrap_str(format!("{}: {}", self.ident.to_string(), try_opt!(pat)),
|
wrap_str(
|
||||||
context.config.max_width(),
|
format!("{}: {}", self.ident.to_string(), try_opt!(pat)),
|
||||||
shape)
|
context.config.max_width(),
|
||||||
|
shape,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -241,13 +261,14 @@ impl<'a> Spanned for TuplePatField<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn rewrite_tuple_pat(pats: &[ptr::P<ast::Pat>],
|
fn rewrite_tuple_pat(
|
||||||
dotdot_pos: Option<usize>,
|
pats: &[ptr::P<ast::Pat>],
|
||||||
path_str: Option<String>,
|
dotdot_pos: Option<usize>,
|
||||||
span: Span,
|
path_str: Option<String>,
|
||||||
context: &RewriteContext,
|
span: Span,
|
||||||
shape: Shape)
|
context: &RewriteContext,
|
||||||
-> Option<String> {
|
shape: Shape,
|
||||||
|
) -> Option<String> {
|
||||||
let mut pat_vec: Vec<_> = pats.into_iter().map(|x| TuplePatField::Pat(x)).collect();
|
let mut pat_vec: Vec<_> = pats.into_iter().map(|x| TuplePatField::Pat(x)).collect();
|
||||||
|
|
||||||
if let Some(pos) = dotdot_pos {
|
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 }));
|
let nested_shape = try_opt!(shape.sub_width(path_len + if add_comma { 3 } else { 2 }));
|
||||||
// 1 = "(".len()
|
// 1 = "(".len()
|
||||||
let nested_shape = nested_shape.visual_indent(path_len + 1);
|
let nested_shape = nested_shape.visual_indent(path_len + 1);
|
||||||
let mut items: Vec<_> = itemize_list(context.codemap,
|
let mut items: Vec<_> = itemize_list(
|
||||||
pat_vec.iter(),
|
context.codemap,
|
||||||
if add_comma { ",)" } else { ")" },
|
pat_vec.iter(),
|
||||||
|item| item.span().lo,
|
if add_comma { ",)" } else { ")" },
|
||||||
|item| item.span().hi,
|
|item| item.span().lo,
|
||||||
|item| item.rewrite(context, nested_shape),
|
|item| item.span().hi,
|
||||||
context.codemap.span_after(span, "("),
|
|item| item.rewrite(context, nested_shape),
|
||||||
span.hi - BytePos(1))
|
context.codemap.span_after(span, "("),
|
||||||
.collect();
|
span.hi - BytePos(1),
|
||||||
|
).collect();
|
||||||
|
|
||||||
// Condense wildcard string suffix into a single ..
|
// Condense wildcard string suffix into a single ..
|
||||||
let wildcard_suffix_len = count_wildcard_suffix_len(&items);
|
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);
|
let da_iter = items.into_iter().take(new_item_count);
|
||||||
try_opt!(format_item_list(da_iter, nested_shape, context.config))
|
try_opt!(format_item_list(da_iter, nested_shape, context.config))
|
||||||
} else {
|
} 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 {
|
match path_str {
|
||||||
Some(path_str) => {
|
Some(path_str) => {
|
||||||
Some(if context.config.spaces_within_parens() {
|
Some(
|
||||||
format!("{}( {} )", path_str, list)
|
if context.config.spaces_within_parens() {
|
||||||
} else {
|
format!("{}( {} )", path_str, list)
|
||||||
format!("{}({})", path_str, list)
|
} else {
|
||||||
})
|
format!("{}({})", path_str, list)
|
||||||
|
},
|
||||||
|
)
|
||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
let comma = if add_comma { "," } else { "" };
|
let comma = if add_comma { "," } else { "" };
|
||||||
Some(if context.config.spaces_within_parens() {
|
Some(
|
||||||
format!("( {}{} )", list, comma)
|
if context.config.spaces_within_parens() {
|
||||||
} else {
|
format!("( {}{} )", list, comma)
|
||||||
format!("({}{})", list, comma)
|
} else {
|
||||||
})
|
format!("({}{})", list, comma)
|
||||||
|
},
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -331,10 +361,10 @@ fn count_wildcard_suffix_len(items: &[ListItem]) -> usize {
|
||||||
let mut suffix_len = 0;
|
let mut suffix_len = 0;
|
||||||
|
|
||||||
for item in items.iter().rev().take_while(|i| match i.item {
|
for item in items.iter().rev().take_while(|i| match i.item {
|
||||||
Some(ref internal_string) if internal_string ==
|
Some(ref internal_string) if internal_string == "_" => true,
|
||||||
"_" => true,
|
_ => false,
|
||||||
_ => false,
|
})
|
||||||
}) {
|
{
|
||||||
suffix_len += 1;
|
suffix_len += 1;
|
||||||
|
|
||||||
if item.pre_comment.is_some() || item.post_comment.is_some() {
|
if item.pre_comment.is_some() || item.post_comment.is_some() {
|
||||||
|
|
|
@ -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)
|
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() {
|
match term::stdout() {
|
||||||
Some(ref t) if isatty() && t.supports_color() => {
|
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>,
|
fn print_diff_fancy<F>(
|
||||||
get_section_title: F,
|
diff: Vec<Mismatch>,
|
||||||
mut t: Box<term::Terminal<Output = io::Stdout>>)
|
get_section_title: F,
|
||||||
where F: Fn(u32) -> String
|
mut t: Box<term::Terminal<Output = io::Stdout>>,
|
||||||
|
) where
|
||||||
|
F: Fn(u32) -> String,
|
||||||
{
|
{
|
||||||
for mismatch in diff {
|
for mismatch in diff {
|
||||||
let title = get_section_title(mismatch.line_number);
|
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)
|
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 {
|
for mismatch in diff {
|
||||||
let title = get_section_title(mismatch.line_number);
|
let title = get_section_title(mismatch.line_number);
|
||||||
|
|
|
@ -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.
|
// `cur_start` is the position in `orig` of the start of the current line.
|
||||||
let mut cur_start = 0;
|
let mut cur_start = 0;
|
||||||
let mut result = String::with_capacity(stripped_str
|
let mut result = String::with_capacity(
|
||||||
.len()
|
stripped_str
|
||||||
.checked_next_power_of_two()
|
.len()
|
||||||
.unwrap_or(usize::max_value()));
|
.checked_next_power_of_two()
|
||||||
|
.unwrap_or(usize::max_value()),
|
||||||
|
);
|
||||||
result.push_str(fmt.opener);
|
result.push_str(fmt.opener);
|
||||||
|
|
||||||
let ender_length = fmt.line_end.len();
|
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 {
|
if cur_end < cur_start + MIN_STRING {
|
||||||
cur_end = cur_start + max_chars;
|
cur_end = cur_start + max_chars;
|
||||||
while !(punctuation.contains(graphemes[cur_end - 1]) ||
|
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() {
|
if cur_end >= graphemes.len() {
|
||||||
let line = &graphemes[cur_start..].join("");
|
let line = &graphemes[cur_start..].join("");
|
||||||
result.push_str(line);
|
result.push_str(line);
|
||||||
|
|
|
@ -54,7 +54,7 @@ impl Summary {
|
||||||
|
|
||||||
pub fn has_no_errors(&self) -> bool {
|
pub fn has_no_errors(&self) -> bool {
|
||||||
!(self.has_operational_errors || self.has_parsing_errors || self.has_formatting_errors ||
|
!(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) {
|
pub fn add(&mut self, other: Summary) {
|
||||||
|
|
465
src/types.rs
465
src/types.rs
|
@ -34,20 +34,21 @@ pub enum PathContext {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Does not wrap on simple segments.
|
// Does not wrap on simple segments.
|
||||||
pub fn rewrite_path(context: &RewriteContext,
|
pub fn rewrite_path(
|
||||||
path_context: PathContext,
|
context: &RewriteContext,
|
||||||
qself: Option<&ast::QSelf>,
|
path_context: PathContext,
|
||||||
path: &ast::Path,
|
qself: Option<&ast::QSelf>,
|
||||||
shape: Shape)
|
path: &ast::Path,
|
||||||
-> Option<String> {
|
shape: Shape,
|
||||||
|
) -> Option<String> {
|
||||||
let skip_count = qself.map_or(0, |x| x.position);
|
let skip_count = qself.map_or(0, |x| x.position);
|
||||||
|
|
||||||
let mut result = if path.is_global() && qself.is_none() &&
|
let mut result =
|
||||||
path_context != PathContext::Import {
|
if path.is_global() && qself.is_none() && path_context != PathContext::Import {
|
||||||
"::".to_owned()
|
"::".to_owned()
|
||||||
} else {
|
} else {
|
||||||
String::new()
|
String::new()
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut span_lo = path.span.lo;
|
let mut span_lo = path.span.lo;
|
||||||
|
|
||||||
|
@ -70,13 +71,15 @@ pub fn rewrite_path(context: &RewriteContext,
|
||||||
// 3 = ">::".len()
|
// 3 = ">::".len()
|
||||||
let shape = try_opt!(try_opt!(shape.shrink_left(extra_offset)).sub_width(3));
|
let shape = try_opt!(try_opt!(shape.shrink_left(extra_offset)).sub_width(3));
|
||||||
|
|
||||||
result = try_opt!(rewrite_path_segments(PathContext::Type,
|
result = try_opt!(rewrite_path_segments(
|
||||||
result,
|
PathContext::Type,
|
||||||
path.segments.iter().take(skip_count),
|
result,
|
||||||
span_lo,
|
path.segments.iter().take(skip_count),
|
||||||
path.span.hi,
|
span_lo,
|
||||||
context,
|
path.span.hi,
|
||||||
shape));
|
context,
|
||||||
|
shape,
|
||||||
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
if context.config.spaces_within_angle_brackets() {
|
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);
|
span_lo = qself.ty.span.hi + BytePos(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
rewrite_path_segments(path_context,
|
rewrite_path_segments(
|
||||||
result,
|
path_context,
|
||||||
path.segments.iter().skip(skip_count),
|
result,
|
||||||
span_lo,
|
path.segments.iter().skip(skip_count),
|
||||||
path.span.hi,
|
span_lo,
|
||||||
context,
|
path.span.hi,
|
||||||
shape)
|
context,
|
||||||
|
shape,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn rewrite_path_segments<'a, I>(path_context: PathContext,
|
fn rewrite_path_segments<'a, I>(
|
||||||
mut buffer: String,
|
path_context: PathContext,
|
||||||
iter: I,
|
mut buffer: String,
|
||||||
mut span_lo: BytePos,
|
iter: I,
|
||||||
span_hi: BytePos,
|
mut span_lo: BytePos,
|
||||||
context: &RewriteContext,
|
span_hi: BytePos,
|
||||||
shape: Shape)
|
context: &RewriteContext,
|
||||||
-> Option<String>
|
shape: Shape,
|
||||||
where I: Iterator<Item = &'a ast::PathSegment>
|
) -> Option<String>
|
||||||
|
where
|
||||||
|
I: Iterator<Item = &'a ast::PathSegment>,
|
||||||
{
|
{
|
||||||
let mut first = true;
|
let mut first = true;
|
||||||
let shape = shape.visual_indent(0);
|
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 extra_offset = extra_offset(&buffer, shape);
|
||||||
let new_shape = try_opt!(shape.shrink_left(extra_offset));
|
let new_shape = try_opt!(shape.shrink_left(extra_offset));
|
||||||
let segment_string = try_opt!(rewrite_segment(path_context,
|
let segment_string = try_opt!(rewrite_segment(
|
||||||
segment,
|
path_context,
|
||||||
&mut span_lo,
|
segment,
|
||||||
span_hi,
|
&mut span_lo,
|
||||||
context,
|
span_hi,
|
||||||
new_shape));
|
context,
|
||||||
|
new_shape,
|
||||||
|
));
|
||||||
|
|
||||||
buffer.push_str(&segment_string);
|
buffer.push_str(&segment_string);
|
||||||
}
|
}
|
||||||
|
@ -163,10 +172,10 @@ impl<'a> Rewrite for SegmentParam<'a> {
|
||||||
TypeDensity::Compressed => format!("{}=", binding.ident),
|
TypeDensity::Compressed => format!("{}=", binding.ident),
|
||||||
};
|
};
|
||||||
let budget = try_opt!(shape.width.checked_sub(result.len()));
|
let budget = try_opt!(shape.width.checked_sub(result.len()));
|
||||||
let rewrite = try_opt!(binding.ty.rewrite(context,
|
let rewrite = try_opt!(binding.ty.rewrite(
|
||||||
Shape::legacy(budget,
|
context,
|
||||||
shape.indent +
|
Shape::legacy(budget, shape.indent + result.len()),
|
||||||
result.len())));
|
));
|
||||||
result.push_str(&rewrite);
|
result.push_str(&rewrite);
|
||||||
Some(result)
|
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
|
// When the segment contains a positive number of parameters, we update span_lo
|
||||||
// so that invariants described above will hold for the next segment.
|
// so that invariants described above will hold for the next segment.
|
||||||
fn rewrite_segment(path_context: PathContext,
|
fn rewrite_segment(
|
||||||
segment: &ast::PathSegment,
|
path_context: PathContext,
|
||||||
span_lo: &mut BytePos,
|
segment: &ast::PathSegment,
|
||||||
span_hi: BytePos,
|
span_lo: &mut BytePos,
|
||||||
context: &RewriteContext,
|
span_hi: BytePos,
|
||||||
shape: Shape)
|
context: &RewriteContext,
|
||||||
-> Option<String> {
|
shape: Shape,
|
||||||
|
) -> Option<String> {
|
||||||
let ident_len = segment.identifier.to_string().len();
|
let ident_len = segment.identifier.to_string().len();
|
||||||
let shape = try_opt!(shape.shrink_left(ident_len));
|
let shape = try_opt!(shape.shrink_left(ident_len));
|
||||||
|
|
||||||
let params = if let Some(ref params) = segment.parameters {
|
let params = if let Some(ref params) = segment.parameters {
|
||||||
match **params {
|
match **params {
|
||||||
ast::PathParameters::AngleBracketed(ref data) if !data.lifetimes.is_empty() ||
|
ast::PathParameters::AngleBracketed(ref data) if !data.lifetimes.is_empty() ||
|
||||||
!data.types.is_empty() ||
|
!data.types.is_empty() ||
|
||||||
!data.bindings.is_empty() => {
|
!data.bindings.is_empty() => {
|
||||||
let param_list = data.lifetimes
|
let param_list = data.lifetimes
|
||||||
.iter()
|
.iter()
|
||||||
.map(SegmentParam::LifeTime)
|
.map(SegmentParam::LifeTime)
|
||||||
|
@ -239,12 +249,14 @@ fn rewrite_segment(path_context: PathContext,
|
||||||
Some(ref ty) => FunctionRetTy::Ty(ty.clone()),
|
Some(ref ty) => FunctionRetTy::Ty(ty.clone()),
|
||||||
None => FunctionRetTy::Default(codemap::DUMMY_SP),
|
None => FunctionRetTy::Default(codemap::DUMMY_SP),
|
||||||
};
|
};
|
||||||
try_opt!(format_function_type(data.inputs.iter().map(|x| &**x),
|
try_opt!(format_function_type(
|
||||||
&output,
|
data.inputs.iter().map(|x| &**x),
|
||||||
false,
|
&output,
|
||||||
data.span,
|
false,
|
||||||
context,
|
data.span,
|
||||||
shape))
|
context,
|
||||||
|
shape,
|
||||||
|
))
|
||||||
}
|
}
|
||||||
_ => String::new(),
|
_ => String::new(),
|
||||||
}
|
}
|
||||||
|
@ -255,22 +267,25 @@ fn rewrite_segment(path_context: PathContext,
|
||||||
Some(format!("{}{}", segment.identifier, params))
|
Some(format!("{}{}", segment.identifier, params))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn format_function_type<'a, I>(inputs: I,
|
fn format_function_type<'a, I>(
|
||||||
output: &FunctionRetTy,
|
inputs: I,
|
||||||
variadic: bool,
|
output: &FunctionRetTy,
|
||||||
span: Span,
|
variadic: bool,
|
||||||
context: &RewriteContext,
|
span: Span,
|
||||||
shape: Shape)
|
context: &RewriteContext,
|
||||||
-> Option<String>
|
shape: Shape,
|
||||||
where I: ExactSizeIterator,
|
) -> Option<String>
|
||||||
<I as Iterator>::Item: Deref,
|
where
|
||||||
<I::Item as Deref>::Target: Rewrite + Spanned + 'a
|
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
|
// Code for handling variadics is somewhat duplicated for items, but they
|
||||||
// are different enough to need some serious refactoring to share code.
|
// are different enough to need some serious refactoring to share code.
|
||||||
enum ArgumentKind<T>
|
enum ArgumentKind<T>
|
||||||
where T: Deref,
|
where
|
||||||
<T as Deref>::Target: Rewrite + Spanned
|
T: Deref,
|
||||||
|
<T as Deref>::Target: Rewrite + Spanned,
|
||||||
{
|
{
|
||||||
Regular(Box<T>),
|
Regular(Box<T>),
|
||||||
Variadic(BytePos),
|
Variadic(BytePos),
|
||||||
|
@ -288,31 +303,35 @@ fn format_function_type<'a, I>(inputs: I,
|
||||||
// 1 for (
|
// 1 for (
|
||||||
let offset = shape.indent + 1;
|
let offset = shape.indent + 1;
|
||||||
let list_lo = context.codemap.span_after(span, "(");
|
let list_lo = context.codemap.span_after(span, "(");
|
||||||
let items = itemize_list(context.codemap,
|
let items = itemize_list(
|
||||||
// FIXME Would be nice to avoid this allocation,
|
context.codemap,
|
||||||
// but I couldn't get the types to work out.
|
// FIXME Would be nice to avoid this allocation,
|
||||||
inputs
|
// but I couldn't get the types to work out.
|
||||||
.map(|i| ArgumentKind::Regular(Box::new(i)))
|
inputs
|
||||||
.chain(variadic_arg),
|
.map(|i| ArgumentKind::Regular(Box::new(i)))
|
||||||
")",
|
.chain(variadic_arg),
|
||||||
|arg| match *arg {
|
")",
|
||||||
ArgumentKind::Regular(ref ty) => ty.span().lo,
|
|arg| match *arg {
|
||||||
ArgumentKind::Variadic(start) => start,
|
ArgumentKind::Regular(ref ty) => ty.span().lo,
|
||||||
},
|
ArgumentKind::Variadic(start) => start,
|
||||||
|arg| match *arg {
|
},
|
||||||
ArgumentKind::Regular(ref ty) => ty.span().hi,
|
|arg| match *arg {
|
||||||
ArgumentKind::Variadic(start) => start + BytePos(3),
|
ArgumentKind::Regular(ref ty) => ty.span().hi,
|
||||||
},
|
ArgumentKind::Variadic(start) => start + BytePos(3),
|
||||||
|arg| match *arg {
|
},
|
||||||
ArgumentKind::Regular(ref ty) => {
|
|arg| match *arg {
|
||||||
ty.rewrite(context, Shape::legacy(budget, offset))
|
ArgumentKind::Regular(ref ty) => ty.rewrite(context, Shape::legacy(budget, offset)),
|
||||||
}
|
ArgumentKind::Variadic(_) => Some("...".to_owned()),
|
||||||
ArgumentKind::Variadic(_) => Some("...".to_owned()),
|
},
|
||||||
},
|
list_lo,
|
||||||
list_lo,
|
span.hi,
|
||||||
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 {
|
let output = match *output {
|
||||||
FunctionRetTy::Ty(ref ty) => {
|
FunctionRetTy::Ty(ref ty) => {
|
||||||
|
@ -329,16 +348,20 @@ fn format_function_type<'a, I>(inputs: I,
|
||||||
String::new()
|
String::new()
|
||||||
};
|
};
|
||||||
|
|
||||||
Some(if context.config.spaces_within_parens() {
|
Some(
|
||||||
format!("( {} ){}{}", list_str, infix, output)
|
if context.config.spaces_within_parens() {
|
||||||
} else {
|
format!("( {} ){}{}", list_str, infix, output)
|
||||||
format!("({}){}{}", list_str, infix, output)
|
} else {
|
||||||
})
|
format!("({}){}{}", list_str, infix, output)
|
||||||
|
},
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn type_bound_colon(context: &RewriteContext) -> &'static str {
|
fn type_bound_colon(context: &RewriteContext) -> &'static str {
|
||||||
colon_spaces(context.config.space_before_bound(),
|
colon_spaces(
|
||||||
context.config.space_after_bound_colon())
|
context.config.space_before_bound(),
|
||||||
|
context.config.space_after_bound_colon(),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Rewrite for ast::WherePredicate {
|
impl Rewrite for ast::WherePredicate {
|
||||||
|
@ -356,11 +379,12 @@ impl Rewrite for ast::WherePredicate {
|
||||||
let colon = type_bound_colon(context);
|
let colon = type_bound_colon(context);
|
||||||
|
|
||||||
if !bound_lifetimes.is_empty() {
|
if !bound_lifetimes.is_empty() {
|
||||||
let lifetime_str: String = try_opt!(bound_lifetimes
|
let lifetime_str: String = try_opt!(
|
||||||
.iter()
|
bound_lifetimes
|
||||||
.map(|lt| lt.rewrite(context, shape))
|
.iter()
|
||||||
.collect::<Option<Vec<_>>>())
|
.map(|lt| lt.rewrite(context, shape))
|
||||||
.join(", ");
|
.collect::<Option<Vec<_>>>()
|
||||||
|
).join(", ");
|
||||||
|
|
||||||
// 6 = "for<> ".len()
|
// 6 = "for<> ".len()
|
||||||
let used_width = lifetime_str.len() + type_str.len() + colon.len() + 6;
|
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);
|
let bounds_str = join_bounds(context, ty_shape, &bounds);
|
||||||
|
|
||||||
if context.config.spaces_within_angle_brackets() && lifetime_str.len() > 0 {
|
if context.config.spaces_within_angle_brackets() && lifetime_str.len() > 0 {
|
||||||
format!("for< {} > {}{}{}",
|
format!(
|
||||||
lifetime_str,
|
"for< {} > {}{}{}",
|
||||||
type_str,
|
lifetime_str,
|
||||||
colon,
|
type_str,
|
||||||
bounds_str)
|
colon,
|
||||||
|
bounds_str
|
||||||
|
)
|
||||||
} else {
|
} else {
|
||||||
format!("for<{}> {}{}{}", lifetime_str, type_str, colon, bounds_str)
|
format!("for<{}> {}{}{}", lifetime_str, type_str, colon, bounds_str)
|
||||||
}
|
}
|
||||||
|
@ -402,7 +428,12 @@ impl Rewrite for ast::WherePredicate {
|
||||||
ref bounds,
|
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 {
|
ast::WherePredicate::EqPredicate(ast::WhereEqPredicate {
|
||||||
ref lhs_ty,
|
ref lhs_ty,
|
||||||
|
@ -413,9 +444,10 @@ impl Rewrite for ast::WherePredicate {
|
||||||
// 3 = " = ".len()
|
// 3 = " = ".len()
|
||||||
let used_width = 3 + lhs_ty_str.len();
|
let used_width = 3 + lhs_ty_str.len();
|
||||||
let budget = try_opt!(shape.width.checked_sub(used_width));
|
let budget = try_opt!(shape.width.checked_sub(used_width));
|
||||||
let rhs_ty_str = try_opt!(rhs_ty.rewrite(context,
|
let rhs_ty_str = try_opt!(rhs_ty.rewrite(
|
||||||
Shape::legacy(budget,
|
context,
|
||||||
shape.indent + used_width)));
|
Shape::legacy(budget, shape.indent + used_width),
|
||||||
|
));
|
||||||
format!("{} = {}", lhs_ty_str, rhs_ty_str)
|
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,
|
fn rewrite_bounded_lifetime<'b, I>(
|
||||||
bounds: I,
|
lt: &ast::Lifetime,
|
||||||
context: &RewriteContext,
|
bounds: I,
|
||||||
shape: Shape)
|
context: &RewriteContext,
|
||||||
-> Option<String>
|
shape: Shape,
|
||||||
where I: ExactSizeIterator<Item = &'b ast::Lifetime>
|
) -> Option<String>
|
||||||
|
where
|
||||||
|
I: ExactSizeIterator<Item = &'b ast::Lifetime>,
|
||||||
{
|
{
|
||||||
let result = try_opt!(lt.rewrite(context, shape));
|
let result = try_opt!(lt.rewrite(context, shape));
|
||||||
|
|
||||||
if bounds.len() == 0 {
|
if bounds.len() == 0 {
|
||||||
Some(result)
|
Some(result)
|
||||||
} else {
|
} else {
|
||||||
let appendix: Vec<_> = try_opt!(bounds
|
let appendix: Vec<_> = try_opt!(
|
||||||
.into_iter()
|
bounds
|
||||||
.map(|b| b.rewrite(context, shape))
|
.into_iter()
|
||||||
.collect());
|
.map(|b| b.rewrite(context, shape))
|
||||||
|
.collect()
|
||||||
|
);
|
||||||
let colon = type_bound_colon(context);
|
let colon = type_bound_colon(context);
|
||||||
let overhead = last_line_width(&result) + colon.len();
|
let overhead = last_line_width(&result) + colon.len();
|
||||||
let result = format!("{}{}{}",
|
let result = format!("{}{}{}",
|
||||||
|
@ -464,9 +500,13 @@ impl Rewrite for ast::TyParamBound {
|
||||||
}
|
}
|
||||||
ast::TyParamBound::TraitTyParamBound(ref tref, ast::TraitBoundModifier::Maybe) => {
|
ast::TyParamBound::TraitTyParamBound(ref tref, ast::TraitBoundModifier::Maybe) => {
|
||||||
let budget = try_opt!(shape.width.checked_sub(1));
|
let budget = try_opt!(shape.width.checked_sub(1));
|
||||||
Some(format!("?{}",
|
Some(format!(
|
||||||
try_opt!(tref.rewrite(context,
|
"?{}",
|
||||||
Shape::legacy(budget, shape.indent + 1)))))
|
try_opt!(tref.rewrite(
|
||||||
|
context,
|
||||||
|
Shape::legacy(budget, shape.indent + 1),
|
||||||
|
))
|
||||||
|
))
|
||||||
}
|
}
|
||||||
ast::TyParamBound::RegionTyParamBound(ref l) => l.rewrite(context, shape),
|
ast::TyParamBound::RegionTyParamBound(ref l) => l.rewrite(context, shape),
|
||||||
}
|
}
|
||||||
|
@ -475,9 +515,11 @@ impl Rewrite for ast::TyParamBound {
|
||||||
|
|
||||||
impl Rewrite for ast::Lifetime {
|
impl Rewrite for ast::Lifetime {
|
||||||
fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option<String> {
|
fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option<String> {
|
||||||
wrap_str(pprust::lifetime_to_string(self),
|
wrap_str(
|
||||||
context.config.max_width(),
|
pprust::lifetime_to_string(self),
|
||||||
shape)
|
context.config.max_width(),
|
||||||
|
shape,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -514,8 +556,10 @@ impl Rewrite for ast::TyParam {
|
||||||
};
|
};
|
||||||
result.push_str(eq_str);
|
result.push_str(eq_str);
|
||||||
let budget = try_opt!(shape.width.checked_sub(result.len()));
|
let budget = try_opt!(shape.width.checked_sub(result.len()));
|
||||||
let rewrite = try_opt!(def.rewrite(context,
|
let rewrite = try_opt!(def.rewrite(
|
||||||
Shape::legacy(budget, shape.indent + result.len())));
|
context,
|
||||||
|
Shape::legacy(budget, shape.indent + result.len()),
|
||||||
|
));
|
||||||
result.push_str(&rewrite);
|
result.push_str(&rewrite);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -526,25 +570,31 @@ impl Rewrite for ast::TyParam {
|
||||||
impl Rewrite for ast::PolyTraitRef {
|
impl Rewrite for ast::PolyTraitRef {
|
||||||
fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option<String> {
|
fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option<String> {
|
||||||
if !self.bound_lifetimes.is_empty() {
|
if !self.bound_lifetimes.is_empty() {
|
||||||
let lifetime_str: String = try_opt!(self.bound_lifetimes
|
let lifetime_str: String = try_opt!(
|
||||||
.iter()
|
self.bound_lifetimes
|
||||||
.map(|lt| lt.rewrite(context, shape))
|
.iter()
|
||||||
.collect::<Option<Vec<_>>>())
|
.map(|lt| lt.rewrite(context, shape))
|
||||||
.join(", ");
|
.collect::<Option<Vec<_>>>()
|
||||||
|
).join(", ");
|
||||||
|
|
||||||
// 6 is "for<> ".len()
|
// 6 is "for<> ".len()
|
||||||
let extra_offset = lifetime_str.len() + 6;
|
let extra_offset = lifetime_str.len() + 6;
|
||||||
let max_path_width = try_opt!(shape.width.checked_sub(extra_offset));
|
let max_path_width = try_opt!(shape.width.checked_sub(extra_offset));
|
||||||
let path_str = try_opt!(self.trait_ref.rewrite(context,
|
let path_str = try_opt!(self.trait_ref.rewrite(
|
||||||
Shape::legacy(max_path_width,
|
context,
|
||||||
shape.indent +
|
Shape::legacy(
|
||||||
extra_offset)));
|
max_path_width,
|
||||||
|
shape.indent + extra_offset,
|
||||||
|
),
|
||||||
|
));
|
||||||
|
|
||||||
Some(if context.config.spaces_within_angle_brackets() && lifetime_str.len() > 0 {
|
Some(
|
||||||
format!("for< {} > {}", lifetime_str, path_str)
|
if context.config.spaces_within_angle_brackets() && lifetime_str.len() > 0 {
|
||||||
} else {
|
format!("for< {} > {}", lifetime_str, path_str)
|
||||||
format!("for<{}> {}", lifetime_str, path_str)
|
} else {
|
||||||
})
|
format!("for<{}> {}", lifetime_str, path_str)
|
||||||
|
},
|
||||||
|
)
|
||||||
} else {
|
} else {
|
||||||
self.trait_ref.rewrite(context, shape)
|
self.trait_ref.rewrite(context, shape)
|
||||||
}
|
}
|
||||||
|
@ -573,33 +623,39 @@ impl Rewrite for ast::Ty {
|
||||||
let mut_str = format_mutability(mt.mutbl);
|
let mut_str = format_mutability(mt.mutbl);
|
||||||
let mut_len = mut_str.len();
|
let mut_len = mut_str.len();
|
||||||
Some(match *lifetime {
|
Some(match *lifetime {
|
||||||
Some(ref lifetime) => {
|
Some(ref lifetime) => {
|
||||||
let lt_budget = try_opt!(shape.width.checked_sub(2 + mut_len));
|
let lt_budget = try_opt!(shape.width.checked_sub(2 + mut_len));
|
||||||
let lt_str = try_opt!(lifetime.rewrite(context,
|
let lt_str = try_opt!(lifetime.rewrite(
|
||||||
Shape::legacy(lt_budget,
|
context,
|
||||||
shape.indent + 2 +
|
Shape::legacy(lt_budget, shape.indent + 2 + mut_len),
|
||||||
mut_len)));
|
));
|
||||||
let lt_len = lt_str.len();
|
let lt_len = lt_str.len();
|
||||||
let budget = try_opt!(shape.width.checked_sub(2 + mut_len + lt_len));
|
let budget = try_opt!(shape.width.checked_sub(2 + mut_len + lt_len));
|
||||||
format!("&{} {}{}",
|
format!(
|
||||||
lt_str,
|
"&{} {}{}",
|
||||||
mut_str,
|
lt_str,
|
||||||
try_opt!(mt.ty.rewrite(context,
|
mut_str,
|
||||||
Shape::legacy(budget,
|
try_opt!(mt.ty.rewrite(
|
||||||
shape.indent + 2 +
|
context,
|
||||||
mut_len +
|
Shape::legacy(
|
||||||
lt_len))))
|
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,
|
None => {
|
||||||
Shape::legacy(budget,
|
let budget = try_opt!(shape.width.checked_sub(1 + mut_len));
|
||||||
shape.indent + 1 +
|
format!(
|
||||||
mut_len))))
|
"&{}{}",
|
||||||
}
|
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
|
// FIXME: we drop any comments here, even though it's a silly place to put
|
||||||
// comments.
|
// comments.
|
||||||
|
@ -607,10 +663,10 @@ impl Rewrite for ast::Ty {
|
||||||
let budget = try_opt!(shape.width.checked_sub(2));
|
let budget = try_opt!(shape.width.checked_sub(2));
|
||||||
ty.rewrite(context, Shape::legacy(budget, shape.indent + 1))
|
ty.rewrite(context, Shape::legacy(budget, shape.indent + 1))
|
||||||
.map(|ty_str| if context.config.spaces_within_parens() {
|
.map(|ty_str| if context.config.spaces_within_parens() {
|
||||||
format!("( {} )", ty_str)
|
format!("( {} )", ty_str)
|
||||||
} else {
|
} else {
|
||||||
format!("({})", ty_str)
|
format!("({})", ty_str)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
ast::TyKind::Slice(ref ty) => {
|
ast::TyKind::Slice(ref ty) => {
|
||||||
let budget = if context.config.spaces_within_square_brackets() {
|
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))
|
ty.rewrite(context, Shape::legacy(budget, shape.indent + 1))
|
||||||
.map(|ty_str| if context.config.spaces_within_square_brackets() {
|
.map(|ty_str| if context.config.spaces_within_square_brackets() {
|
||||||
format!("[ {} ]", ty_str)
|
format!("[ {} ]", ty_str)
|
||||||
} else {
|
} else {
|
||||||
format!("[{}]", ty_str)
|
format!("[{}]", ty_str)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
ast::TyKind::Tup(ref items) => {
|
ast::TyKind::Tup(ref items) => {
|
||||||
rewrite_tuple_type(context, items.iter().map(|x| &**x), self.span, shape)
|
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::Mac(..) => None,
|
||||||
ast::TyKind::ImplicitSelf => Some(String::from("")),
|
ast::TyKind::ImplicitSelf => Some(String::from("")),
|
||||||
ast::TyKind::ImplTrait(ref it) => {
|
ast::TyKind::ImplTrait(ref it) => {
|
||||||
it.rewrite(context, shape)
|
it.rewrite(context, shape).map(|it_str| {
|
||||||
.map(|it_str| format!("impl {}", it_str))
|
format!("impl {}", it_str)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
ast::TyKind::Err |
|
ast::TyKind::Err |
|
||||||
ast::TyKind::Typeof(..) => unreachable!(),
|
ast::TyKind::Typeof(..) => unreachable!(),
|
||||||
|
@ -658,11 +715,12 @@ impl Rewrite for ast::Ty {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn rewrite_bare_fn(bare_fn: &ast::BareFnTy,
|
fn rewrite_bare_fn(
|
||||||
span: Span,
|
bare_fn: &ast::BareFnTy,
|
||||||
context: &RewriteContext,
|
span: Span,
|
||||||
shape: Shape)
|
context: &RewriteContext,
|
||||||
-> Option<String> {
|
shape: Shape,
|
||||||
|
) -> Option<String> {
|
||||||
let mut result = String::with_capacity(128);
|
let mut result = String::with_capacity(128);
|
||||||
|
|
||||||
if !bare_fn.lifetimes.is_empty() {
|
if !bare_fn.lifetimes.is_empty() {
|
||||||
|
@ -675,8 +733,10 @@ fn rewrite_bare_fn(bare_fn: &ast::BareFnTy,
|
||||||
.lifetimes
|
.lifetimes
|
||||||
.iter()
|
.iter()
|
||||||
.map(|l| {
|
.map(|l| {
|
||||||
l.rewrite(context,
|
l.rewrite(
|
||||||
Shape::legacy(try_opt!(shape.width.checked_sub(6)), shape.indent + 4))
|
context,
|
||||||
|
Shape::legacy(try_opt!(shape.width.checked_sub(6)), shape.indent + 4),
|
||||||
|
)
|
||||||
})
|
})
|
||||||
.collect::<Option<Vec<_>>>()
|
.collect::<Option<Vec<_>>>()
|
||||||
).join(", "));
|
).join(", "));
|
||||||
|
@ -686,7 +746,10 @@ fn rewrite_bare_fn(bare_fn: &ast::BareFnTy,
|
||||||
result.push_str(::utils::format_unsafety(bare_fn.unsafety));
|
result.push_str(::utils::format_unsafety(bare_fn.unsafety));
|
||||||
|
|
||||||
if bare_fn.abi != abi::Abi::Rust {
|
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");
|
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 budget = try_opt!(shape.width.checked_sub(result.len()));
|
||||||
let indent = shape.indent + result.len();
|
let indent = shape.indent + result.len();
|
||||||
|
|
||||||
let rewrite = try_opt!(format_function_type(bare_fn.decl.inputs.iter(),
|
let rewrite = try_opt!(format_function_type(
|
||||||
&bare_fn.decl.output,
|
bare_fn.decl.inputs.iter(),
|
||||||
bare_fn.decl.variadic,
|
&bare_fn.decl.output,
|
||||||
span,
|
bare_fn.decl.variadic,
|
||||||
context,
|
span,
|
||||||
Shape::legacy(budget, indent)));
|
context,
|
||||||
|
Shape::legacy(budget, indent),
|
||||||
|
));
|
||||||
|
|
||||||
result.push_str(&rewrite);
|
result.push_str(&rewrite);
|
||||||
|
|
||||||
|
|
18
src/utils.rs
18
src/utils.rs
|
@ -44,9 +44,9 @@ pub fn format_visibility(vis: &Visibility) -> Cow<'static, str> {
|
||||||
let Path { ref segments, .. } = **path;
|
let Path { ref segments, .. } = **path;
|
||||||
let mut segments_iter = segments.iter().map(|seg| seg.identifier.name.to_string());
|
let mut segments_iter = segments.iter().map(|seg| seg.identifier.name.to_string());
|
||||||
if path.is_global() {
|
if path.is_global() {
|
||||||
segments_iter
|
segments_iter.next().expect(
|
||||||
.next()
|
"Non-global path in pub(restricted)?",
|
||||||
.expect("Non-global path in pub(restricted)?");
|
);
|
||||||
}
|
}
|
||||||
let is_keyword = |s: &str| s == "self" || s == "super";
|
let is_keyword = |s: &str| s == "self" || s == "super";
|
||||||
let path = segments_iter.collect::<Vec<_>>().join("::");
|
let path = segments_iter.collect::<Vec<_>>().join("::");
|
||||||
|
@ -128,9 +128,9 @@ fn is_skip_nested(meta_item: &NestedMetaItem) -> bool {
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn contains_skip(attrs: &[Attribute]) -> bool {
|
pub fn contains_skip(attrs: &[Attribute]) -> bool {
|
||||||
attrs
|
attrs.iter().any(
|
||||||
.iter()
|
|a| a.meta().map_or(false, |a| is_skip(&a)),
|
||||||
.any(|a| a.meta().map_or(false, |a| is_skip(&a)))
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Find the end of a TyParam
|
// 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
|
// A special check for the last line, since the caller may
|
||||||
// place trailing characters on this line.
|
// place trailing characters on this line.
|
||||||
if snippet.lines().rev().next().unwrap().len() >
|
if snippet.lines().rev().next().unwrap().len() >
|
||||||
shape.indent.width() + shape.width {
|
shape.indent.width() + shape.width
|
||||||
|
{
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -355,7 +356,8 @@ impl Rewrite for String {
|
||||||
// whether the `guess' was too high (Ordering::Less), or too low.
|
// whether the `guess' was too high (Ordering::Less), or too low.
|
||||||
// This function is guaranteed to try to the hi value first.
|
// 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>
|
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;
|
let mut middle = hi;
|
||||||
|
|
||||||
|
|
492
src/visitor.rs
492
src/visitor.rs
|
@ -36,16 +36,16 @@ fn is_use_item(item: &ast::Item) -> bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn item_bound(item: &ast::Item) -> Span {
|
fn item_bound(item: &ast::Item) -> Span {
|
||||||
item.attrs
|
item.attrs.iter().map(|attr| attr.span).fold(
|
||||||
.iter()
|
item.span,
|
||||||
.map(|attr| attr.span)
|
|bound, span| {
|
||||||
.fold(item.span, |bound, span| {
|
|
||||||
Span {
|
Span {
|
||||||
lo: cmp::min(bound.lo, span.lo),
|
lo: cmp::min(bound.lo, span.lo),
|
||||||
hi: cmp::max(bound.hi, span.hi),
|
hi: cmp::max(bound.hi, span.hi),
|
||||||
ctxt: span.ctxt,
|
ctxt: span.ctxt,
|
||||||
}
|
}
|
||||||
})
|
},
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct FmtVisitor<'a> {
|
pub struct FmtVisitor<'a> {
|
||||||
|
@ -62,14 +62,19 @@ pub struct FmtVisitor<'a> {
|
||||||
|
|
||||||
impl<'a> FmtVisitor<'a> {
|
impl<'a> FmtVisitor<'a> {
|
||||||
fn visit_stmt(&mut self, stmt: &ast::Stmt) {
|
fn visit_stmt(&mut self, stmt: &ast::Stmt) {
|
||||||
debug!("visit_stmt: {:?} {:?}",
|
debug!(
|
||||||
self.codemap.lookup_char_pos(stmt.span.lo),
|
"visit_stmt: {:?} {:?}",
|
||||||
self.codemap.lookup_char_pos(stmt.span.hi));
|
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.
|
// FIXME(#434): Move this check to somewhere more central, eg Rewrite.
|
||||||
if !self.config
|
if !self.config.file_lines().intersects(
|
||||||
.file_lines()
|
&self.codemap.lookup_line_range(
|
||||||
.intersects(&self.codemap.lookup_line_range(stmt.span)) {
|
stmt.span,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -80,9 +85,10 @@ impl<'a> FmtVisitor<'a> {
|
||||||
ast::StmtKind::Local(..) |
|
ast::StmtKind::Local(..) |
|
||||||
ast::StmtKind::Expr(..) |
|
ast::StmtKind::Expr(..) |
|
||||||
ast::StmtKind::Semi(..) => {
|
ast::StmtKind::Semi(..) => {
|
||||||
let rewrite =
|
let rewrite = stmt.rewrite(
|
||||||
stmt.rewrite(&self.get_context(),
|
&self.get_context(),
|
||||||
Shape::indented(self.block_indent, self.config));
|
Shape::indented(self.block_indent, self.config),
|
||||||
|
);
|
||||||
self.push_rewrite(stmt.span, rewrite);
|
self.push_rewrite(stmt.span, rewrite);
|
||||||
}
|
}
|
||||||
ast::StmtKind::Mac(ref mac) => {
|
ast::StmtKind::Mac(ref mac) => {
|
||||||
|
@ -94,9 +100,11 @@ impl<'a> FmtVisitor<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn visit_block(&mut self, b: &ast::Block) {
|
pub fn visit_block(&mut self, b: &ast::Block) {
|
||||||
debug!("visit_block: {:?} {:?}",
|
debug!(
|
||||||
self.codemap.lookup_char_pos(b.span.lo),
|
"visit_block: {:?} {:?}",
|
||||||
self.codemap.lookup_char_pos(b.span.hi));
|
self.codemap.lookup_char_pos(b.span.lo),
|
||||||
|
self.codemap.lookup_char_pos(b.span.hi)
|
||||||
|
);
|
||||||
|
|
||||||
// Check if this block has braces.
|
// Check if this block has braces.
|
||||||
let snippet = self.snippet(b.span);
|
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
|
// Note that this only gets called for function definitions. Required methods
|
||||||
// on traits do not get handled here.
|
// on traits do not get handled here.
|
||||||
fn visit_fn(&mut self,
|
fn visit_fn(
|
||||||
fk: visit::FnKind,
|
&mut self,
|
||||||
fd: &ast::FnDecl,
|
fk: visit::FnKind,
|
||||||
s: Span,
|
fd: &ast::FnDecl,
|
||||||
_: ast::NodeId,
|
s: Span,
|
||||||
defaultness: ast::Defaultness) {
|
_: ast::NodeId,
|
||||||
|
defaultness: ast::Defaultness,
|
||||||
|
) {
|
||||||
let indent = self.block_indent;
|
let indent = self.block_indent;
|
||||||
let block;
|
let block;
|
||||||
let rewrite = match fk {
|
let rewrite = match fk {
|
||||||
visit::FnKind::ItemFn(ident, generics, unsafety, constness, abi, vis, b) => {
|
visit::FnKind::ItemFn(ident, generics, unsafety, constness, abi, vis, b) => {
|
||||||
block = b;
|
block = b;
|
||||||
self.rewrite_fn(indent,
|
self.rewrite_fn(
|
||||||
ident,
|
indent,
|
||||||
fd,
|
ident,
|
||||||
generics,
|
fd,
|
||||||
unsafety,
|
generics,
|
||||||
constness.node,
|
unsafety,
|
||||||
defaultness,
|
constness.node,
|
||||||
abi,
|
defaultness,
|
||||||
vis,
|
abi,
|
||||||
mk_sp(s.lo, b.span.lo),
|
vis,
|
||||||
&b)
|
mk_sp(s.lo, b.span.lo),
|
||||||
|
&b,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
visit::FnKind::Method(ident, sig, vis, b) => {
|
visit::FnKind::Method(ident, sig, vis, b) => {
|
||||||
block = b;
|
block = b;
|
||||||
self.rewrite_fn(indent,
|
self.rewrite_fn(
|
||||||
ident,
|
indent,
|
||||||
fd,
|
ident,
|
||||||
&sig.generics,
|
fd,
|
||||||
sig.unsafety,
|
&sig.generics,
|
||||||
sig.constness.node,
|
sig.unsafety,
|
||||||
defaultness,
|
sig.constness.node,
|
||||||
sig.abi,
|
defaultness,
|
||||||
vis.unwrap_or(&ast::Visibility::Inherited),
|
sig.abi,
|
||||||
mk_sp(s.lo, b.span.lo),
|
vis.unwrap_or(&ast::Visibility::Inherited),
|
||||||
&b)
|
mk_sp(s.lo, b.span.lo),
|
||||||
|
&b,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
visit::FnKind::Closure(_) => unreachable!(),
|
visit::FnKind::Closure(_) => unreachable!(),
|
||||||
};
|
};
|
||||||
|
@ -267,23 +281,28 @@ impl<'a> FmtVisitor<'a> {
|
||||||
ast::ItemKind::Impl(..) => {
|
ast::ItemKind::Impl(..) => {
|
||||||
self.format_missing_with_indent(source!(self, item.span).lo);
|
self.format_missing_with_indent(source!(self, item.span).lo);
|
||||||
let snippet = self.get_context().snippet(item.span);
|
let snippet = self.get_context().snippet(item.span);
|
||||||
let where_span_end =
|
let where_span_end = snippet.find_uncommented("{").map(|x| {
|
||||||
snippet
|
(BytePos(x as u32)) + source!(self, item.span).lo
|
||||||
.find_uncommented("{")
|
});
|
||||||
.map(|x| (BytePos(x as u32)) + source!(self, item.span).lo);
|
if let Some(impl_str) = format_impl(
|
||||||
if let Some(impl_str) = format_impl(&self.get_context(),
|
&self.get_context(),
|
||||||
item,
|
item,
|
||||||
self.block_indent,
|
self.block_indent,
|
||||||
where_span_end) {
|
where_span_end,
|
||||||
|
)
|
||||||
|
{
|
||||||
self.buffer.push_str(&impl_str);
|
self.buffer.push_str(&impl_str);
|
||||||
self.last_pos = source!(self, item.span).hi;
|
self.last_pos = source!(self, item.span).hi;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ast::ItemKind::Trait(..) => {
|
ast::ItemKind::Trait(..) => {
|
||||||
self.format_missing_with_indent(item.span.lo);
|
self.format_missing_with_indent(item.span.lo);
|
||||||
if let Some(trait_str) = format_trait(&self.get_context(),
|
if let Some(trait_str) = format_trait(
|
||||||
item,
|
&self.get_context(),
|
||||||
self.block_indent) {
|
item,
|
||||||
|
self.block_indent,
|
||||||
|
)
|
||||||
|
{
|
||||||
self.buffer.push_str(&trait_str);
|
self.buffer.push_str(&trait_str);
|
||||||
self.last_pos = source!(self, item.span).hi;
|
self.last_pos = source!(self, item.span).hi;
|
||||||
}
|
}
|
||||||
|
@ -298,19 +317,20 @@ impl<'a> FmtVisitor<'a> {
|
||||||
let rewrite = {
|
let rewrite = {
|
||||||
let indent = self.block_indent;
|
let indent = self.block_indent;
|
||||||
let context = self.get_context();
|
let context = self.get_context();
|
||||||
::items::format_struct(&context,
|
::items::format_struct(
|
||||||
"struct ",
|
&context,
|
||||||
item.ident,
|
"struct ",
|
||||||
&item.vis,
|
item.ident,
|
||||||
def,
|
&item.vis,
|
||||||
Some(generics),
|
def,
|
||||||
item.span,
|
Some(generics),
|
||||||
indent,
|
item.span,
|
||||||
None)
|
indent,
|
||||||
.map(|s| match *def {
|
None,
|
||||||
ast::VariantData::Tuple(..) => s + ";",
|
).map(|s| match *def {
|
||||||
_ => s,
|
ast::VariantData::Tuple(..) => s + ";",
|
||||||
})
|
_ => s,
|
||||||
|
})
|
||||||
};
|
};
|
||||||
self.push_rewrite(item.span, rewrite);
|
self.push_rewrite(item.span, rewrite);
|
||||||
}
|
}
|
||||||
|
@ -331,53 +351,63 @@ impl<'a> FmtVisitor<'a> {
|
||||||
self.format_foreign_mod(foreign_mod, item.span);
|
self.format_foreign_mod(foreign_mod, item.span);
|
||||||
}
|
}
|
||||||
ast::ItemKind::Static(ref ty, mutability, ref expr) => {
|
ast::ItemKind::Static(ref ty, mutability, ref expr) => {
|
||||||
let rewrite = rewrite_static("static",
|
let rewrite = rewrite_static(
|
||||||
&item.vis,
|
"static",
|
||||||
item.ident,
|
&item.vis,
|
||||||
ty,
|
item.ident,
|
||||||
mutability,
|
ty,
|
||||||
Some(expr),
|
mutability,
|
||||||
self.block_indent,
|
Some(expr),
|
||||||
item.span,
|
self.block_indent,
|
||||||
&self.get_context());
|
item.span,
|
||||||
|
&self.get_context(),
|
||||||
|
);
|
||||||
self.push_rewrite(item.span, rewrite);
|
self.push_rewrite(item.span, rewrite);
|
||||||
}
|
}
|
||||||
ast::ItemKind::Const(ref ty, ref expr) => {
|
ast::ItemKind::Const(ref ty, ref expr) => {
|
||||||
let rewrite = rewrite_static("const",
|
let rewrite = rewrite_static(
|
||||||
&item.vis,
|
"const",
|
||||||
item.ident,
|
&item.vis,
|
||||||
ty,
|
item.ident,
|
||||||
ast::Mutability::Immutable,
|
ty,
|
||||||
Some(expr),
|
ast::Mutability::Immutable,
|
||||||
self.block_indent,
|
Some(expr),
|
||||||
item.span,
|
self.block_indent,
|
||||||
&self.get_context());
|
item.span,
|
||||||
|
&self.get_context(),
|
||||||
|
);
|
||||||
self.push_rewrite(item.span, rewrite);
|
self.push_rewrite(item.span, rewrite);
|
||||||
}
|
}
|
||||||
ast::ItemKind::DefaultImpl(..) => {
|
ast::ItemKind::DefaultImpl(..) => {
|
||||||
// FIXME(#78): format impl definitions.
|
// FIXME(#78): format impl definitions.
|
||||||
}
|
}
|
||||||
ast::ItemKind::Fn(ref decl, unsafety, constness, abi, ref generics, ref body) => {
|
ast::ItemKind::Fn(ref decl, unsafety, constness, abi, ref generics, ref body) => {
|
||||||
self.visit_fn(visit::FnKind::ItemFn(item.ident,
|
self.visit_fn(
|
||||||
generics,
|
visit::FnKind::ItemFn(
|
||||||
unsafety,
|
item.ident,
|
||||||
constness,
|
generics,
|
||||||
abi,
|
unsafety,
|
||||||
&item.vis,
|
constness,
|
||||||
body),
|
abi,
|
||||||
decl,
|
&item.vis,
|
||||||
item.span,
|
body,
|
||||||
item.id,
|
),
|
||||||
ast::Defaultness::Final)
|
decl,
|
||||||
|
item.span,
|
||||||
|
item.id,
|
||||||
|
ast::Defaultness::Final,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
ast::ItemKind::Ty(ref ty, ref generics) => {
|
ast::ItemKind::Ty(ref ty, ref generics) => {
|
||||||
let rewrite = rewrite_type_alias(&self.get_context(),
|
let rewrite = rewrite_type_alias(
|
||||||
self.block_indent,
|
&self.get_context(),
|
||||||
item.ident,
|
self.block_indent,
|
||||||
ty,
|
item.ident,
|
||||||
generics,
|
ty,
|
||||||
&item.vis,
|
generics,
|
||||||
item.span);
|
&item.vis,
|
||||||
|
item.span,
|
||||||
|
);
|
||||||
self.push_rewrite(item.span, rewrite);
|
self.push_rewrite(item.span, rewrite);
|
||||||
}
|
}
|
||||||
ast::ItemKind::Union(..) => {
|
ast::ItemKind::Union(..) => {
|
||||||
|
@ -403,15 +433,17 @@ impl<'a> FmtVisitor<'a> {
|
||||||
|
|
||||||
match ti.node {
|
match ti.node {
|
||||||
ast::TraitItemKind::Const(ref ty, ref expr_opt) => {
|
ast::TraitItemKind::Const(ref ty, ref expr_opt) => {
|
||||||
let rewrite = rewrite_static("const",
|
let rewrite = rewrite_static(
|
||||||
&ast::Visibility::Inherited,
|
"const",
|
||||||
ti.ident,
|
&ast::Visibility::Inherited,
|
||||||
ty,
|
ti.ident,
|
||||||
ast::Mutability::Immutable,
|
ty,
|
||||||
expr_opt.as_ref(),
|
ast::Mutability::Immutable,
|
||||||
self.block_indent,
|
expr_opt.as_ref(),
|
||||||
ti.span,
|
self.block_indent,
|
||||||
&self.get_context());
|
ti.span,
|
||||||
|
&self.get_context(),
|
||||||
|
);
|
||||||
self.push_rewrite(ti.span, rewrite);
|
self.push_rewrite(ti.span, rewrite);
|
||||||
}
|
}
|
||||||
ast::TraitItemKind::Method(ref sig, None) => {
|
ast::TraitItemKind::Method(ref sig, None) => {
|
||||||
|
@ -420,18 +452,22 @@ impl<'a> FmtVisitor<'a> {
|
||||||
self.push_rewrite(ti.span, rewrite);
|
self.push_rewrite(ti.span, rewrite);
|
||||||
}
|
}
|
||||||
ast::TraitItemKind::Method(ref sig, Some(ref body)) => {
|
ast::TraitItemKind::Method(ref sig, Some(ref body)) => {
|
||||||
self.visit_fn(visit::FnKind::Method(ti.ident, sig, None, body),
|
self.visit_fn(
|
||||||
&sig.decl,
|
visit::FnKind::Method(ti.ident, sig, None, body),
|
||||||
ti.span,
|
&sig.decl,
|
||||||
ti.id,
|
ti.span,
|
||||||
ast::Defaultness::Final);
|
ti.id,
|
||||||
|
ast::Defaultness::Final,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
ast::TraitItemKind::Type(ref type_param_bounds, ref type_default) => {
|
ast::TraitItemKind::Type(ref type_param_bounds, ref type_default) => {
|
||||||
let rewrite = rewrite_associated_type(ti.ident,
|
let rewrite = rewrite_associated_type(
|
||||||
type_default.as_ref(),
|
ti.ident,
|
||||||
Some(type_param_bounds),
|
type_default.as_ref(),
|
||||||
&self.get_context(),
|
Some(type_param_bounds),
|
||||||
self.block_indent);
|
&self.get_context(),
|
||||||
|
self.block_indent,
|
||||||
|
);
|
||||||
self.push_rewrite(ti.span, rewrite);
|
self.push_rewrite(ti.span, rewrite);
|
||||||
}
|
}
|
||||||
ast::TraitItemKind::Macro(ref mac) => {
|
ast::TraitItemKind::Macro(ref mac) => {
|
||||||
|
@ -448,31 +484,37 @@ impl<'a> FmtVisitor<'a> {
|
||||||
|
|
||||||
match ii.node {
|
match ii.node {
|
||||||
ast::ImplItemKind::Method(ref sig, ref body) => {
|
ast::ImplItemKind::Method(ref sig, ref body) => {
|
||||||
self.visit_fn(visit::FnKind::Method(ii.ident, sig, Some(&ii.vis), body),
|
self.visit_fn(
|
||||||
&sig.decl,
|
visit::FnKind::Method(ii.ident, sig, Some(&ii.vis), body),
|
||||||
ii.span,
|
&sig.decl,
|
||||||
ii.id,
|
ii.span,
|
||||||
ii.defaultness);
|
ii.id,
|
||||||
|
ii.defaultness,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
ast::ImplItemKind::Const(ref ty, ref expr) => {
|
ast::ImplItemKind::Const(ref ty, ref expr) => {
|
||||||
let rewrite = rewrite_static("const",
|
let rewrite = rewrite_static(
|
||||||
&ii.vis,
|
"const",
|
||||||
ii.ident,
|
&ii.vis,
|
||||||
ty,
|
ii.ident,
|
||||||
ast::Mutability::Immutable,
|
ty,
|
||||||
Some(expr),
|
ast::Mutability::Immutable,
|
||||||
self.block_indent,
|
Some(expr),
|
||||||
ii.span,
|
self.block_indent,
|
||||||
&self.get_context());
|
ii.span,
|
||||||
|
&self.get_context(),
|
||||||
|
);
|
||||||
self.push_rewrite(ii.span, rewrite);
|
self.push_rewrite(ii.span, rewrite);
|
||||||
}
|
}
|
||||||
ast::ImplItemKind::Type(ref ty) => {
|
ast::ImplItemKind::Type(ref ty) => {
|
||||||
let rewrite = rewrite_associated_impl_type(ii.ident,
|
let rewrite = rewrite_associated_impl_type(
|
||||||
ii.defaultness,
|
ii.ident,
|
||||||
Some(ty),
|
ii.defaultness,
|
||||||
None,
|
Some(ty),
|
||||||
&self.get_context(),
|
None,
|
||||||
self.block_indent);
|
&self.get_context(),
|
||||||
|
self.block_indent,
|
||||||
|
);
|
||||||
self.push_rewrite(ii.span, rewrite);
|
self.push_rewrite(ii.span, rewrite);
|
||||||
}
|
}
|
||||||
ast::ImplItemKind::Macro(ref mac) => {
|
ast::ImplItemKind::Macro(ref mac) => {
|
||||||
|
@ -493,9 +535,10 @@ impl<'a> FmtVisitor<'a> {
|
||||||
fn push_rewrite(&mut self, span: Span, rewrite: Option<String>) {
|
fn push_rewrite(&mut self, span: Span, rewrite: Option<String>) {
|
||||||
self.format_missing_with_indent(source!(self, span).lo);
|
self.format_missing_with_indent(source!(self, span).lo);
|
||||||
self.failed = match rewrite {
|
self.failed = match rewrite {
|
||||||
Some(ref s) if s.rewrite(&self.get_context(),
|
Some(ref s) if s.rewrite(
|
||||||
Shape::indented(self.block_indent, self.config))
|
&self.get_context(),
|
||||||
.is_none() => true,
|
Shape::indented(self.block_indent, self.config),
|
||||||
|
).is_none() => true,
|
||||||
None => true,
|
None => true,
|
||||||
_ => self.failed,
|
_ => self.failed,
|
||||||
};
|
};
|
||||||
|
@ -521,9 +564,11 @@ impl<'a> FmtVisitor<'a> {
|
||||||
match self.codemap.span_to_snippet(span) {
|
match self.codemap.span_to_snippet(span) {
|
||||||
Ok(s) => s,
|
Ok(s) => s,
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
println!("Couldn't make snippet for span {:?}->{:?}",
|
println!(
|
||||||
self.codemap.lookup_char_pos(span.lo),
|
"Couldn't make snippet for span {:?}->{:?}",
|
||||||
self.codemap.lookup_char_pos(span.hi));
|
self.codemap.lookup_char_pos(span.lo),
|
||||||
|
self.codemap.lookup_char_pos(span.hi)
|
||||||
|
);
|
||||||
"".to_owned()
|
"".to_owned()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -548,8 +593,10 @@ impl<'a> FmtVisitor<'a> {
|
||||||
self.format_missing_with_indent(source!(self, first.span).lo);
|
self.format_missing_with_indent(source!(self, first.span).lo);
|
||||||
|
|
||||||
let rewrite = outers
|
let rewrite = outers
|
||||||
.rewrite(&self.get_context(),
|
.rewrite(
|
||||||
Shape::indented(self.block_indent, self.config))
|
&self.get_context(),
|
||||||
|
Shape::indented(self.block_indent, self.config),
|
||||||
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
self.buffer.push_str(&rewrite);
|
self.buffer.push_str(&rewrite);
|
||||||
let last = outers.last().unwrap();
|
let last = outers.last().unwrap();
|
||||||
|
@ -570,13 +617,13 @@ impl<'a> FmtVisitor<'a> {
|
||||||
.iter()
|
.iter()
|
||||||
.take_while(|ppi| {
|
.take_while(|ppi| {
|
||||||
is_use_item(&***ppi) &&
|
is_use_item(&***ppi) &&
|
||||||
(!reorder_imports_in_group ||
|
(!reorder_imports_in_group ||
|
||||||
{
|
{
|
||||||
let current = self.codemap.lookup_line_range(item_bound(&ppi));
|
let current = self.codemap.lookup_line_range(item_bound(&ppi));
|
||||||
let in_same_group = current.lo < last.hi + 2;
|
let in_same_group = current.lo < last.hi + 2;
|
||||||
last = current;
|
last = current;
|
||||||
in_same_group
|
in_same_group
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
.count();
|
.count();
|
||||||
let (use_items, rest) = items_left.split_at(use_item_length);
|
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 local_file_name = self.codemap.span_to_filename(s);
|
||||||
let inner_span = source!(self, m.inner);
|
let inner_span = source!(self, m.inner);
|
||||||
let is_internal = !(inner_span.lo.0 == 0 && inner_span.hi.0 == 0) &&
|
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(&*utils::format_visibility(vis));
|
||||||
self.buffer.push_str("mod ");
|
self.buffer.push_str("mod ");
|
||||||
|
@ -658,66 +705,65 @@ impl Rewrite for ast::NestedMetaItem {
|
||||||
impl Rewrite for ast::MetaItem {
|
impl Rewrite for ast::MetaItem {
|
||||||
fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option<String> {
|
fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option<String> {
|
||||||
Some(match self.node {
|
Some(match self.node {
|
||||||
ast::MetaItemKind::Word => String::from(&*self.name.as_str()),
|
ast::MetaItemKind::Word => String::from(&*self.name.as_str()),
|
||||||
ast::MetaItemKind::List(ref list) => {
|
ast::MetaItemKind::List(ref list) => {
|
||||||
let name = self.name.as_str();
|
let name = self.name.as_str();
|
||||||
// 3 = `#[` and `(`, 2 = `]` and `)`
|
// 3 = `#[` and `(`, 2 = `]` and `)`
|
||||||
let item_shape = try_opt!(shape
|
let item_shape = try_opt!(shape.shrink_left(name.len() + 3).and_then(
|
||||||
.shrink_left(name.len() + 3)
|
|s| s.sub_width(2),
|
||||||
.and_then(|s| s.sub_width(2)));
|
));
|
||||||
let items = itemize_list(context.codemap,
|
let items = itemize_list(
|
||||||
list.iter(),
|
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.span.lo,
|
||||||
|nested_meta_item| {
|
|nested_meta_item| nested_meta_item.span.hi,
|
||||||
nested_meta_item.rewrite(context, item_shape)
|
|nested_meta_item| nested_meta_item.rewrite(context, item_shape),
|
||||||
},
|
self.span.lo,
|
||||||
self.span.lo,
|
self.span.hi,
|
||||||
self.span.hi);
|
);
|
||||||
let item_vec = items.collect::<Vec<_>>();
|
let item_vec = items.collect::<Vec<_>>();
|
||||||
let fmt = ListFormatting {
|
let fmt = ListFormatting {
|
||||||
tactic: DefinitiveListTactic::Mixed,
|
tactic: DefinitiveListTactic::Mixed,
|
||||||
separator: ",",
|
separator: ",",
|
||||||
trailing_separator: SeparatorTactic::Never,
|
trailing_separator: SeparatorTactic::Never,
|
||||||
shape: item_shape,
|
shape: item_shape,
|
||||||
ends_with_newline: false,
|
ends_with_newline: false,
|
||||||
config: context.config,
|
config: context.config,
|
||||||
};
|
};
|
||||||
format!("{}({})", name, try_opt!(write_list(&item_vec, &fmt)))
|
format!("{}({})", name, try_opt!(write_list(&item_vec, &fmt)))
|
||||||
}
|
}
|
||||||
ast::MetaItemKind::NameValue(ref literal) => {
|
ast::MetaItemKind::NameValue(ref literal) => {
|
||||||
let name = self.name.as_str();
|
let name = self.name.as_str();
|
||||||
let value = context.snippet(literal.span);
|
let value = context.snippet(literal.span);
|
||||||
if &*name == "doc" && value.starts_with("///") {
|
if &*name == "doc" && value.starts_with("///") {
|
||||||
let doc_shape = Shape {
|
let doc_shape = Shape {
|
||||||
width: cmp::min(shape.width, context.config.comment_width())
|
width: cmp::min(shape.width, context.config.comment_width())
|
||||||
.checked_sub(shape.indent.width())
|
.checked_sub(shape.indent.width())
|
||||||
.unwrap_or(0),
|
.unwrap_or(0),
|
||||||
..shape
|
..shape
|
||||||
};
|
};
|
||||||
format!("{}",
|
format!(
|
||||||
try_opt!(rewrite_comment(&value,
|
"{}",
|
||||||
false,
|
try_opt!(rewrite_comment(&value, false, doc_shape, context.config))
|
||||||
doc_shape,
|
)
|
||||||
context.config)))
|
} else {
|
||||||
} else {
|
format!("{} = {}", name, value)
|
||||||
format!("{} = {}", name, value)
|
}
|
||||||
}
|
}
|
||||||
}
|
})
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Rewrite for ast::Attribute {
|
impl Rewrite for ast::Attribute {
|
||||||
fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option<String> {
|
fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option<String> {
|
||||||
try_opt!(self.meta())
|
try_opt!(self.meta()).rewrite(context, shape).map(|rw| {
|
||||||
.rewrite(context, shape)
|
if rw.starts_with("///") {
|
||||||
.map(|rw| if rw.starts_with("///") {
|
rw
|
||||||
rw
|
} else {
|
||||||
} else {
|
format!("#[{}]", rw)
|
||||||
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 multi_line = a_str.starts_with("//") && comment.matches('\n').count() > 1;
|
||||||
let comment = comment.trim();
|
let comment = comment.trim();
|
||||||
if !comment.is_empty() {
|
if !comment.is_empty() {
|
||||||
let comment =
|
let comment = try_opt!(rewrite_comment(
|
||||||
try_opt!(rewrite_comment(comment,
|
comment,
|
||||||
false,
|
false,
|
||||||
Shape::legacy(context.config.comment_width() -
|
Shape::legacy(
|
||||||
shape.indent.width(),
|
context.config.comment_width() - shape.indent.width(),
|
||||||
shape.indent),
|
shape.indent,
|
||||||
context.config));
|
),
|
||||||
|
context.config,
|
||||||
|
));
|
||||||
result.push_str(&indent);
|
result.push_str(&indent);
|
||||||
result.push_str(&comment);
|
result.push_str(&comment);
|
||||||
result.push('\n');
|
result.push('\n');
|
||||||
|
|
Loading…
Add table
Reference in a new issue