-// Copyright 2017 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.
-
// Format with vertical alignment.
use std::cmp;
-use syntax::ast;
-use syntax::source_map::{BytePos, Span};
+use itertools::Itertools;
+use rustc_ast::ast;
+use rustc_span::{BytePos, Span};
-use crate::comment::{combine_strs_with_missing_comments, contains_comment};
+use crate::comment::combine_strs_with_missing_comments;
use crate::config::lists::*;
use crate::expr::rewrite_field;
use crate::items::{rewrite_struct_field, rewrite_struct_field_prefix};
use crate::shape::{Indent, Shape};
use crate::source_map::SpanUtils;
use crate::spanned::Spanned;
-use crate::utils::{contains_skip, is_attributes_extendable, mk_sp, rewrite_ident};
+use crate::utils::{
+ contains_skip, is_attributes_extendable, mk_sp, rewrite_ident, trimmed_last_line_width,
+};
-pub trait AlignedItem {
+pub(crate) trait AlignedItem {
fn skip(&self) -> bool;
fn get_span(&self) -> Span;
fn rewrite_prefix(&self, context: &RewriteContext<'_>, shape: Shape) -> Option<String>;
) -> Option<String>;
}
-impl AlignedItem for ast::StructField {
+impl AlignedItem for ast::FieldDef {
fn skip(&self) -> bool {
contains_skip(&self.attrs)
}
}
}
-impl AlignedItem for ast::Field {
+impl AlignedItem for ast::ExprField {
fn skip(&self) -> bool {
contains_skip(&self.attrs)
}
}
}
-pub fn rewrite_with_alignment<T: AlignedItem>(
+pub(crate) fn rewrite_with_alignment<T: AlignedItem>(
fields: &[T],
context: &RewriteContext<'_>,
shape: Shape,
let snippet = context.snippet(missing_span);
if snippet.trim_start().starts_with("//") {
- let offset = snippet.lines().next().map_or(0, |l| l.len());
+ let offset = snippet.lines().next().map_or(0, str::len);
// 2 = "," + "\n"
init_hi + BytePos(offset as u32 + 2)
} else if snippet.trim_start().starts_with("/*") {
fields
.iter()
.map(|field| {
- field.rewrite_prefix(context, shape).and_then(|field_str| {
- if field_str.contains('\n') {
- None
- } else {
- Some(field_str.len())
- }
- })
+ field
+ .rewrite_prefix(context, shape)
+ .map(|field_str| trimmed_last_line_width(&field_str))
})
- .fold(Some((0, ::std::usize::MAX)), |acc, len| match (acc, len) {
- (Some((max_len, min_len)), Some(len)) => {
- Some((cmp::max(max_len, len), cmp::min(min_len, len)))
- }
- _ => None,
+ .fold_options((0, ::std::usize::MAX), |(max_len, min_len), len| {
+ (cmp::max(max_len, len), cmp::min(min_len, len))
})
.unwrap_or((0, 0))
}
write_list(&items, &fmt)
}
+/// Returns the index in `fields` up to which a field belongs to the current group.
+/// The returned string is the group separator to use when rewriting the fields.
+/// Groups are defined by blank lines.
fn group_aligned_items<T: AlignedItem>(
context: &RewriteContext<'_>,
fields: &[T],
if fields[i].skip() {
return ("", index);
}
- // See if there are comments or empty lines between fields.
let span = mk_sp(fields[i].get_span().hi(), fields[i + 1].get_span().lo());
let snippet = context
.snippet(span)
.skip(1)
.collect::<Vec<_>>()
.join("\n");
- let spacings = if snippet.lines().rev().skip(1).any(|l| l.trim().is_empty()) {
- "\n"
- } else {
- ""
- };
- if contains_comment(&snippet) || snippet.lines().count() > 1 {
- return (spacings, index);
+ let has_blank_line = snippet
+ .lines()
+ .dropping_back(1)
+ .any(|l| l.trim().is_empty());
+ if has_blank_line {
+ return ("\n", index);
}
index += 1;
}