-// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
// Formatting top-level items - functions, structs, enums, traits, impls.
use std::borrow::Cow;
format_expr, is_empty_block, is_simple_block_stmt, rewrite_assign_rhs, rewrite_assign_rhs_with,
ExprType, RhsTactics,
};
-use crate::lists::{
- definitive_tactic, itemize_list, write_list, ListFormatting, ListItem, Separator,
-};
+use crate::lists::{definitive_tactic, itemize_list, write_list, ListFormatting, Separator};
use crate::macros::{rewrite_macro, MacroPosition};
use crate::overflow;
use crate::rewrite::{Rewrite, RewriteContext};
) -> FnSig<'a> {
FnSig {
unsafety: method_sig.header.unsafety,
- is_async: method_sig.header.asyncness,
+ is_async: method_sig.header.asyncness.node,
constness: method_sig.header.constness.node,
defaultness: ast::Defaultness::Final,
abi: method_sig.header.abi,
generics,
abi: fn_header.abi,
constness: fn_header.constness.node,
- is_async: fn_header.asyncness,
+ is_async: fn_header.asyncness.node,
defaultness,
unsafety: fn_header.unsafety,
visibility: visibility.clone(),
false,
)?;
- // If there is no where clause, we may have missing comments between the trait name and
+ // If there is no where-clause, we may have missing comments between the trait name and
// the opening brace.
if generics.where_clause.predicates.is_empty() {
if let Some(hi) = where_span_end {
result.push_str(&where_clause_str);
if where_clause_str.contains('\n') || last_line_contains_single_line_comment(&result) {
// if the where_clause contains extra comments AND
- // there is only one where clause predicate
+ // there is only one where-clause predicate
// recover the suppressed comma in single line where_clause formatting
if generics.where_clause.predicates.len() == 1 {
result.push_str(",");
// ` for`
let trait_ref_overhead = if trait_ref.is_some() { 4 } else { 0 };
let curly_brace_overhead = if generics.where_clause.predicates.is_empty() {
- // If there is no where clause adapt budget for type formatting to take space and curly
+ // If there is no where-clause adapt budget for type formatting to take space and curly
// brace into account.
match context.config.brace_style() {
BraceStyle::AlwaysNextLine => 0,
)?;
}
- // Rewrite where clause.
+ // Rewrite where-clause.
if !generics.where_clause.predicates.is_empty() {
let where_density = if context.config.indent_style() == IndentStyle::Block {
Density::Compressed
option,
false,
)?;
- // If the where clause cannot fit on the same line,
- // put the where clause on a new line
+ // If the where-clause cannot fit on the same line,
+ // put the where-clause on a new line
if !where_clause_str.contains('\n')
&& last_line_width(&result) + where_clause_str.len() + offset.width()
> context.config.comment_width()
|| offset.block_indent + result.len() + where_clause_str.len() + 1
> context.config.max_width())
{
- // We need to put the where clause on a new line, but we didn't
- // know that earlier, so the where clause will not be indented properly.
+ // We need to put the where-clause on a new line, but we didn't
+ // know that earlier, so the where-clause will not be indented properly.
result.push('\n');
result.push_str(
&(offset.block_only() + (context.config.tab_spaces() - 1)).to_string(context.config),
impl Rewrite for ast::Arg {
fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option<String> {
- if is_named_arg(self) {
+ if let Some(ref explicit_self) = self.to_self() {
+ rewrite_explicit_self(context, explicit_self)
+ } else if is_named_arg(self) {
let mut result = self
.pat
.rewrite(context, Shape::legacy(shape.width, shape.indent))?;
}
fn rewrite_explicit_self(
- explicit_self: &ast::ExplicitSelf,
- args: &[ast::Arg],
context: &RewriteContext<'_>,
+ explicit_self: &ast::ExplicitSelf,
) -> Option<String> {
match explicit_self.node {
ast::SelfKind::Region(lt, m) => {
None => Some(format!("&{}self", mut_str)),
}
}
- ast::SelfKind::Explicit(ref ty, _) => {
- assert!(!args.is_empty(), "&[ast::Arg] shouldn't be empty.");
-
- let mutability = explicit_self_mutability(&args[0]);
+ ast::SelfKind::Explicit(ref ty, mutability) => {
let type_str = ty.rewrite(
context,
Shape::legacy(context.config.max_width(), Indent::empty()),
type_str
))
}
- ast::SelfKind::Value(_) => {
- assert!(!args.is_empty(), "&[ast::Arg] shouldn't be empty.");
-
- let mutability = explicit_self_mutability(&args[0]);
-
- Some(format!("{}self", format_mutability(mutability)))
- }
- }
-}
-
-// Hacky solution caused by absence of `Mutability` in `SelfValue` and
-// `SelfExplicit` variants of `ast::ExplicitSelf_`.
-fn explicit_self_mutability(arg: &ast::Arg) -> ast::Mutability {
- if let ast::PatKind::Ident(ast::BindingMode::ByValue(mutability), _, _) = arg.pat.node {
- mutability
- } else {
- unreachable!()
+ ast::SelfKind::Value(mutability) => Some(format!("{}self", format_mutability(mutability))),
}
}
let arg_str = rewrite_args(
context,
&fd.inputs,
- fd.get_self().as_ref(),
one_line_budget,
multi_line_budget,
indent,
arg_indent,
args_span,
- fd.variadic,
- generics_str.contains('\n'),
+ fd.c_variadic,
)?;
let put_args_in_block = match context.config.indent_style() {
// the closing parenthesis of the argument and the arrow '->' is considered.
let mut sig_length = result.len() + indent.width() + ret_str_len + 1;
- // If there is no where clause, take into account the space after the return type
+ // If there is no where-clause, take into account the space after the return type
// and the brace.
if where_clause.predicates.is_empty() {
sig_length += 2;
} else {
// FIXME: we might want to check that using the arg indent
// doesn't blow our budget, and if it does, then fallback to
- // the where clause indent.
+ // the where-clause indent.
arg_indent
};
option,
is_args_multi_lined,
)?;
- // If there are neither where clause nor return type, we may be missing comments between
+ // If there are neither where-clause nor return type, we may be missing comments between
// args and `{`.
if where_clause_str.is_empty() {
if let ast::FunctionRetTy::Default(ret_span) = fd.output {
struct WhereClauseOption {
suppress_comma: bool, // Force no trailing comma
snuggle: bool, // Do not insert newline before `where`
- compress_where: bool, // Try single line where clause instead of vertical layout
+ compress_where: bool, // Try single line where-clause instead of vertical layout
}
impl WhereClauseOption {
fn rewrite_args(
context: &RewriteContext<'_>,
args: &[ast::Arg],
- explicit_self: Option<&ast::ExplicitSelf>,
one_line_budget: usize,
multi_line_budget: usize,
indent: Indent,
arg_indent: Indent,
span: Span,
variadic: bool,
- generics_str_contains_newline: bool,
) -> Option<String> {
- let mut arg_item_strs = args
- .iter()
- .map(|arg| {
- arg.rewrite(context, Shape::legacy(multi_line_budget, arg_indent))
- .unwrap_or_else(|| context.snippet(arg.span()).to_owned())
- })
- .collect::<Vec<_>>();
-
- // Account for sugary self.
- // FIXME: the comment for the self argument is dropped. This is blocked
- // on rust issue #27522.
- let min_args = explicit_self
- .and_then(|explicit_self| rewrite_explicit_self(explicit_self, args, context))
- .map_or(1, |self_str| {
- arg_item_strs[0] = self_str;
- 2
- });
-
- // Comments between args.
- let mut arg_items = Vec::new();
- if min_args == 2 {
- arg_items.push(ListItem::from_str(""));
- }
-
- // FIXME(#21): if there are no args, there might still be a comment, but
- // without spans for the comment or parens, there is no chance of
- // getting it right. You also don't get to put a comment on self, unless
- // it is explicit.
- if args.len() >= min_args || variadic {
- let comment_span_start = if min_args == 2 {
- let second_arg_start = if arg_has_pattern(&args[1]) {
- args[1].pat.span.lo()
- } else {
- args[1].ty.span.lo()
- };
- let reduced_span = mk_sp(span.lo(), second_arg_start);
-
- context.snippet_provider.span_after_last(reduced_span, ",")
- } else {
- span.lo()
- };
-
- enum ArgumentKind<'a> {
- Regular(&'a ast::Arg),
- Variadic(BytePos),
- }
-
- let variadic_arg = if variadic {
- let variadic_span = mk_sp(args.last().unwrap().ty.span.hi(), span.hi());
- let variadic_start =
- context.snippet_provider.span_after(variadic_span, "...") - BytePos(3);
- Some(ArgumentKind::Variadic(variadic_start))
- } else {
- None
- };
-
- let more_items = itemize_list(
- context.snippet_provider,
- args[min_args - 1..]
- .iter()
- .map(ArgumentKind::Regular)
- .chain(variadic_arg),
- ")",
- ",",
- |arg| match *arg {
- ArgumentKind::Regular(arg) => span_lo_for_arg(arg),
- ArgumentKind::Variadic(start) => start,
- },
- |arg| match *arg {
- ArgumentKind::Regular(arg) => arg.ty.span.hi(),
- ArgumentKind::Variadic(start) => start + BytePos(3),
- },
- |arg| match *arg {
- ArgumentKind::Regular(..) => None,
- ArgumentKind::Variadic(..) => Some("...".to_owned()),
- },
- comment_span_start,
- span.hi(),
- false,
- );
-
- arg_items.extend(more_items);
- }
-
- let fits_in_one_line = !generics_str_contains_newline
- && (arg_items.is_empty()
- || arg_items.len() == 1 && arg_item_strs[0].len() <= one_line_budget);
-
- for (item, arg) in arg_items.iter_mut().zip(arg_item_strs) {
- item.item = Some(arg);
+ if args.len() == 0 {
+ let comment = context
+ .snippet(mk_sp(
+ span.lo(),
+ // to remove ')'
+ span.hi() - BytePos(1),
+ ))
+ .trim();
+ return Some(comment.to_owned());
}
-
- let last_line_ends_with_comment = arg_items
- .iter()
- .last()
- .and_then(|item| item.post_comment.as_ref())
- .map_or(false, |s| s.trim().starts_with("//"));
-
- let (indent, trailing_comma) = match context.config.indent_style() {
- IndentStyle::Block if fits_in_one_line => {
- (indent.block_indent(context.config), SeparatorTactic::Never)
- }
- IndentStyle::Block => (
- indent.block_indent(context.config),
- context.config.trailing_comma(),
- ),
- IndentStyle::Visual if last_line_ends_with_comment => {
- (arg_indent, context.config.trailing_comma())
- }
- IndentStyle::Visual => (arg_indent, SeparatorTactic::Never),
- };
+ let arg_items: Vec<_> = itemize_list(
+ context.snippet_provider,
+ args.iter(),
+ ")",
+ ",",
+ |arg| span_lo_for_arg(arg),
+ |arg| arg.ty.span.hi(),
+ |arg| {
+ arg.rewrite(context, Shape::legacy(multi_line_budget, arg_indent))
+ .or_else(|| Some(context.snippet(arg.span()).to_owned()))
+ },
+ span.lo(),
+ span.hi(),
+ false,
+ )
+ .collect();
let tactic = definitive_tactic(
&arg_items,
- context.config.fn_args_density().to_list_tactic(),
+ context
+ .config
+ .fn_args_density()
+ .to_list_tactic(arg_items.len()),
Separator::Comma,
one_line_budget,
);
DefinitiveListTactic::Horizontal => one_line_budget,
_ => multi_line_budget,
};
-
- debug!("rewrite_args: budget: {}, tactic: {:?}", budget, tactic);
-
+ let indent = match context.config.indent_style() {
+ IndentStyle::Block => indent.block_indent(context.config),
+ IndentStyle::Visual => arg_indent,
+ };
let trailing_separator = if variadic {
SeparatorTactic::Never
} else {
- trailing_comma
+ match context.config.indent_style() {
+ IndentStyle::Block => context.config.trailing_comma(),
+ IndentStyle::Visual => SeparatorTactic::Never,
+ }
};
let fmt = ListFormatting::new(Shape::legacy(budget, indent), context.config)
.tactic(tactic)
write_list(&arg_items, &fmt)
}
-fn arg_has_pattern(arg: &ast::Arg) -> bool {
- if let ast::PatKind::Ident(_, ident, _) = arg.pat.node {
- ident != symbol::keywords::Invalid.ident()
- } else {
- true
- }
-}
-
fn compute_budgets_for_args(
context: &RewriteContext<'_>,
result: &str,
generics: &ast::Generics,
shape: Shape,
) -> Option<String> {
- // FIXME: convert bounds to where clauses where they get too big or if
- // there is a where clause at all.
+ // FIXME: convert bounds to where-clauses where they get too big or if
+ // there is a where-clause at all.
if generics.params.is_empty() {
return Some(ident.to_owned());
};
// shape should be vertical only and only if we have `where_single_line` option enabled
- // and the number of items of the where clause is equal to 1
+ // and the number of items of the where-clause is equal to 1
let shape_tactic = if where_single_line {
DefinitiveListTactic::Horizontal
} else {
let tactic = definitive_tactic(&item_vec, ListTactic::Vertical, Separator::Comma, budget);
let mut comma_tactic = context.config.trailing_comma();
- // Kind of a hack because we don't usually have trailing commas in where clauses.
+ // Kind of a hack because we don't usually have trailing commas in where-clauses.
if comma_tactic == SeparatorTactic::Vertical || where_clause_option.suppress_comma {
comma_tactic = SeparatorTactic::Never;
}
})
}
-/// Returns true for `mod foo;`, false for `mod foo { .. }`.
+/// Returns `true` for `mod foo;`, false for `mod foo { .. }`.
pub fn is_mod_decl(item: &ast::Item) -> bool {
match item.node {
ast::ItemKind::Mod(ref m) => m.inner.hi() != item.span.hi(),