X-Git-Url: https://git.lizzy.rs/?a=blobdiff_plain;f=src%2Fvertical.rs;h=c4208848c6c2ab3ad6bbaf5414109ca7f5cba5dd;hb=ea1611c06eabb6c77d002a6ddc06697604e5077f;hp=e76f44ca39b05f6ebda4464817e3715975ff5796;hpb=3585706fa28c976c1ffad197da842c85a85dbd73;p=rust.git diff --git a/src/vertical.rs b/src/vertical.rs index e76f44ca39b..c4208848c6c 100644 --- a/src/vertical.rs +++ b/src/vertical.rs @@ -1,44 +1,39 @@ -// 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 or the MIT license -// , 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 config::lists::*; -use syntax::ast; -use syntax::source_map::{BytePos, Span}; +use itertools::Itertools; +use rustc_ast::ast; +use rustc_span::{BytePos, Span}; -use comment::{combine_strs_with_missing_comments, contains_comment}; -use expr::rewrite_field; -use items::{rewrite_struct_field, rewrite_struct_field_prefix}; -use lists::{definitive_tactic, itemize_list, write_list, ListFormatting, Separator}; -use rewrite::{Rewrite, RewriteContext}; -use shape::{Indent, Shape}; -use source_map::SpanUtils; -use spanned::Spanned; -use utils::{contains_skip, is_attributes_extendable, mk_sp, rewrite_ident}; +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::lists::{ + definitive_tactic, itemize_list, write_list, ListFormatting, ListItem, Separator, +}; +use crate::rewrite::{Rewrite, RewriteContext}; +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, 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; + fn rewrite_prefix(&self, context: &RewriteContext<'_>, shape: Shape) -> Option; fn rewrite_aligned_item( &self, - context: &RewriteContext, + context: &RewriteContext<'_>, shape: Shape, prefix_max_width: usize, ) -> Option; } -impl AlignedItem for ast::StructField { +impl AlignedItem for ast::FieldDef { fn skip(&self) -> bool { contains_skip(&self.attrs) } @@ -47,7 +42,7 @@ fn get_span(&self) -> Span { self.span() } - fn rewrite_prefix(&self, context: &RewriteContext, shape: Shape) -> Option { + fn rewrite_prefix(&self, context: &RewriteContext<'_>, shape: Shape) -> Option { let attrs_str = self.attrs.rewrite(context, shape)?; let missing_span = if self.attrs.is_empty() { mk_sp(self.span.lo(), self.span.lo()) @@ -69,7 +64,7 @@ fn rewrite_prefix(&self, context: &RewriteContext, shape: Shape) -> Option, shape: Shape, prefix_max_width: usize, ) -> Option { @@ -77,7 +72,7 @@ fn rewrite_aligned_item( } } -impl AlignedItem for ast::Field { +impl AlignedItem for ast::ExprField { fn skip(&self) -> bool { contains_skip(&self.attrs) } @@ -86,7 +81,7 @@ fn get_span(&self) -> Span { self.span() } - fn rewrite_prefix(&self, context: &RewriteContext, shape: Shape) -> Option { + fn rewrite_prefix(&self, context: &RewriteContext<'_>, shape: Shape) -> Option { let attrs_str = self.attrs.rewrite(context, shape)?; let name = rewrite_ident(context, self.ident); let missing_span = if self.attrs.is_empty() { @@ -106,7 +101,7 @@ fn rewrite_prefix(&self, context: &RewriteContext, shape: Shape) -> Option, shape: Shape, prefix_max_width: usize, ) -> Option { @@ -114,9 +109,9 @@ fn rewrite_aligned_item( } } -pub fn rewrite_with_alignment( +pub(crate) fn rewrite_with_alignment( fields: &[T], - context: &RewriteContext, + context: &RewriteContext<'_>, shape: Shape, span: Span, one_line_width: usize, @@ -126,7 +121,7 @@ pub fn rewrite_with_alignment( } else { ("", fields.len() - 1) }; - let init = &fields[0..group_index + 1]; + let init = &fields[0..=group_index]; let rest = &fields[group_index + 1..]; let init_last_pos = if rest.is_empty() { span.hi() @@ -141,14 +136,14 @@ pub fn rewrite_with_alignment( ); let snippet = context.snippet(missing_span); - if snippet.trim_left().starts_with("//") { - let offset = snippet.lines().next().map_or(0, |l| l.len()); + if snippet.trim_start().starts_with("//") { + let offset = snippet.lines().next().map_or(0, str::len); // 2 = "," + "\n" init_hi + BytePos(offset as u32 + 2) - } else if snippet.trim_left().starts_with("/*") { + } else if snippet.trim_start().starts_with("/*") { let comment_lines = snippet .lines() - .position(|line| line.trim_right().ends_with("*/")) + .position(|line| line.trim_end().ends_with("*/")) .unwrap_or(0); let offset = snippet @@ -172,52 +167,43 @@ pub fn rewrite_with_alignment( } else { let rest_span = mk_sp(init_last_pos, span.hi()); let rest_str = rewrite_with_alignment(rest, context, shape, rest_span, one_line_width)?; - Some( - result - + spaces - + "\n" - + &shape - .indent - .block_indent(context.config) - .to_string(context.config) - + &rest_str, - ) + Some(format!( + "{}{}\n{}{}", + result, + spaces, + &shape.indent.to_string(context.config), + &rest_str + )) } } fn struct_field_prefix_max_min_width( - context: &RewriteContext, + context: &RewriteContext<'_>, fields: &[T], shape: Shape, ) -> (usize, usize) { fields .iter() .map(|field| { - field.rewrite_prefix(context, shape).and_then(|field_str| { - if field_str.contains('\n') { - None - } else { - Some(field_str.len()) - } - }) - }).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, - }).unwrap_or((0, 0)) + field + .rewrite_prefix(context, shape) + .map(|field_str| trimmed_last_line_width(&field_str)) + }) + .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)) } fn rewrite_aligned_items_inner( - context: &RewriteContext, + context: &RewriteContext<'_>, fields: &[T], span: Span, offset: Indent, one_line_width: usize, ) -> Option { - let item_indent = offset.block_indent(context.config); // 1 = "," - let item_shape = Shape::indented(item_indent, context.config).sub_width(1)?; + let item_shape = Shape::indented(offset, context.config).sub_width(1)?; let (mut field_prefix_max_width, field_prefix_min_width) = struct_field_prefix_max_min_width(context, fields, item_shape); let max_diff = field_prefix_max_width.saturating_sub(field_prefix_min_width); @@ -225,7 +211,7 @@ fn rewrite_aligned_items_inner( field_prefix_max_width = 0; } - let items = itemize_list( + let mut items = itemize_list( context.snippet_provider, fields.iter(), "}", @@ -236,7 +222,8 @@ fn rewrite_aligned_items_inner( span.lo(), span.hi(), false, - ).collect::>(); + ) + .collect::>(); let tactic = definitive_tactic( &items, @@ -245,6 +232,20 @@ fn rewrite_aligned_items_inner( one_line_width, ); + if tactic == DefinitiveListTactic::Horizontal { + // since the items fits on a line, there is no need to align them + let do_rewrite = + |field: &T| -> Option { field.rewrite_aligned_item(context, item_shape, 0) }; + fields + .iter() + .zip(items.iter_mut()) + .for_each(|(field, list_item): (&T, &mut ListItem)| { + if list_item.item.is_some() { + list_item.item = do_rewrite(field); + } + }); + } + let fmt = ListFormatting::new(item_shape, context.config) .tactic(tactic) .trailing_separator(context.config.trailing_comma()) @@ -252,8 +253,11 @@ fn rewrite_aligned_items_inner( 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( - context: &RewriteContext, + context: &RewriteContext<'_>, fields: &[T], ) -> (&'static str, usize) { let mut index = 0; @@ -261,7 +265,6 @@ fn group_aligned_items( 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) @@ -269,13 +272,12 @@ fn group_aligned_items( .skip(1) .collect::>() .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; }