modify rewrite_struct_lit, rewrite_struct_pat

- refactor rewrite_*** functions that call rewrite_path to return RewriteResult
- modify rewrite_aligned_item method of AlignedItem
This commit is contained in:
ding-young 2024-07-11 00:18:32 +09:00 committed by Yacin Tmimi
parent 3cbc91e9d6
commit babc2f9b8a
3 changed files with 58 additions and 45 deletions

View File

@ -128,6 +128,7 @@ pub(crate) fn format_expr(
expr.span, expr.span,
shape, shape,
) )
.ok()
} }
ast::ExprKind::Tup(ref items) => { ast::ExprKind::Tup(ref items) => {
rewrite_tuple(context, items.iter(), expr.span, shape, items.len() == 1) rewrite_tuple(context, items.iter(), expr.span, shape, items.len() == 1)
@ -1603,7 +1604,7 @@ fn rewrite_struct_lit<'a>(
attrs: &[ast::Attribute], attrs: &[ast::Attribute],
span: Span, span: Span,
shape: Shape, shape: Shape,
) -> Option<String> { ) -> RewriteResult {
debug!("rewrite_struct_lit: shape {:?}", shape); debug!("rewrite_struct_lit: shape {:?}", shape);
enum StructLitField<'a> { enum StructLitField<'a> {
@ -1613,20 +1614,21 @@ fn rewrite_struct_lit<'a>(
} }
// 2 = " {".len() // 2 = " {".len()
let path_shape = shape.sub_width(2)?; let path_shape = shape.sub_width(2).max_width_error(shape.width, span)?;
let path_str = rewrite_path(context, PathContext::Expr, qself, path, path_shape).ok()?; let path_str = rewrite_path(context, PathContext::Expr, qself, path, path_shape)?;
let has_base_or_rest = match struct_rest { let has_base_or_rest = match struct_rest {
ast::StructRest::None if fields.is_empty() => return Some(format!("{path_str} {{}}")), ast::StructRest::None if fields.is_empty() => return Ok(format!("{path_str} {{}}")),
ast::StructRest::Rest(_) if fields.is_empty() => { ast::StructRest::Rest(_) if fields.is_empty() => {
return Some(format!("{path_str} {{ .. }}")); return Ok(format!("{path_str} {{ .. }}"));
} }
ast::StructRest::Rest(_) | ast::StructRest::Base(_) => true, ast::StructRest::Rest(_) | ast::StructRest::Base(_) => true,
_ => false, _ => false,
}; };
// Foo { a: Foo } - indent is +3, width is -5. // Foo { a: Foo } - indent is +3, width is -5.
let (h_shape, v_shape) = struct_lit_shape(shape, context, path_str.len() + 3, 2)?; let (h_shape, v_shape) = struct_lit_shape(shape, context, path_str.len() + 3, 2)
.max_width_error(shape.width, span)?;
let one_line_width = h_shape.map_or(0, |shape| shape.width); let one_line_width = h_shape.map_or(0, |shape| shape.width);
let body_lo = context.snippet_provider.span_after(span, "{"); let body_lo = context.snippet_provider.span_after(span, "{");
@ -1639,7 +1641,8 @@ fn rewrite_struct_lit<'a>(
v_shape, v_shape,
mk_sp(body_lo, span.hi()), mk_sp(body_lo, span.hi()),
one_line_width, one_line_width,
)? )
.unknown_error()?
} else { } else {
let field_iter = fields.iter().map(StructLitField::Regular).chain( let field_iter = fields.iter().map(StructLitField::Regular).chain(
match struct_rest { match struct_rest {
@ -1668,12 +1671,13 @@ fn rewrite_struct_lit<'a>(
let rewrite = |item: &StructLitField<'_>| match *item { let rewrite = |item: &StructLitField<'_>| match *item {
StructLitField::Regular(field) => { StructLitField::Regular(field) => {
// The 1 taken from the v_budget is for the comma. // The 1 taken from the v_budget is for the comma.
rewrite_field(context, field, v_shape.sub_width(1)?, 0) let v_shape = v_shape.sub_width(1)?;
rewrite_field(context, field, v_shape, 0).ok()
} }
StructLitField::Base(expr) => { StructLitField::Base(expr) => {
// 2 = .. // 2 = ..
expr.rewrite(context, v_shape.offset_left(2)?) let v_shape = v_shape.sub_width(2)?;
.map(|s| format!("..{}", s)) expr.rewrite(context, v_shape).map(|s| format!("..{}", s))
} }
StructLitField::Rest(_) => Some("..".to_owned()), StructLitField::Rest(_) => Some("..".to_owned()),
}; };
@ -1705,12 +1709,12 @@ fn rewrite_struct_lit<'a>(
force_no_trailing_comma || has_base_or_rest || !context.use_block_indent(), force_no_trailing_comma || has_base_or_rest || !context.use_block_indent(),
); );
write_list(&item_vec, &fmt)? write_list(&item_vec, &fmt).unknown_error()?
}; };
let fields_str = let fields_str =
wrap_struct_field(context, attrs, &fields_str, shape, v_shape, one_line_width)?; wrap_struct_field(context, attrs, &fields_str, shape, v_shape, one_line_width)?;
Some(format!("{path_str} {{{fields_str}}}")) Ok(format!("{path_str} {{{fields_str}}}"))
// FIXME if context.config.indent_style() == Visual, but we run out // FIXME if context.config.indent_style() == Visual, but we run out
// of space, we should fall back to BlockIndent. // of space, we should fall back to BlockIndent.
@ -1723,7 +1727,7 @@ pub(crate) fn wrap_struct_field(
shape: Shape, shape: Shape,
nested_shape: Shape, nested_shape: Shape,
one_line_width: usize, one_line_width: usize,
) -> Option<String> { ) -> RewriteResult {
let should_vertical = context.config.indent_style() == IndentStyle::Block let should_vertical = context.config.indent_style() == IndentStyle::Block
&& (fields_str.contains('\n') && (fields_str.contains('\n')
|| !context.config.struct_lit_single_line() || !context.config.struct_lit_single_line()
@ -1732,7 +1736,7 @@ pub(crate) fn wrap_struct_field(
let inner_attrs = &inner_attributes(attrs); let inner_attrs = &inner_attributes(attrs);
if inner_attrs.is_empty() { if inner_attrs.is_empty() {
if should_vertical { if should_vertical {
Some(format!( Ok(format!(
"{}{}{}", "{}{}{}",
nested_shape.indent.to_string_with_newline(context.config), nested_shape.indent.to_string_with_newline(context.config),
fields_str, fields_str,
@ -1740,13 +1744,13 @@ pub(crate) fn wrap_struct_field(
)) ))
} else { } else {
// One liner or visual indent. // One liner or visual indent.
Some(format!(" {fields_str} ")) Ok(format!(" {fields_str} "))
} }
} else { } else {
Some(format!( Ok(format!(
"{}{}{}{}{}", "{}{}{}{}{}",
nested_shape.indent.to_string_with_newline(context.config), nested_shape.indent.to_string_with_newline(context.config),
inner_attrs.rewrite(context, shape)?, inner_attrs.rewrite_result(context, shape)?,
nested_shape.indent.to_string_with_newline(context.config), nested_shape.indent.to_string_with_newline(context.config),
fields_str, fields_str,
shape.indent.to_string_with_newline(context.config) shape.indent.to_string_with_newline(context.config)
@ -1763,38 +1767,40 @@ pub(crate) fn rewrite_field(
field: &ast::ExprField, field: &ast::ExprField,
shape: Shape, shape: Shape,
prefix_max_width: usize, prefix_max_width: usize,
) -> Option<String> { ) -> RewriteResult {
if contains_skip(&field.attrs) { if contains_skip(&field.attrs) {
return Some(context.snippet(field.span()).to_owned()); return Ok(context.snippet(field.span()).to_owned());
} }
let mut attrs_str = field.attrs.rewrite(context, shape)?; let mut attrs_str = field.attrs.rewrite_result(context, shape)?;
if !attrs_str.is_empty() { if !attrs_str.is_empty() {
attrs_str.push_str(&shape.indent.to_string_with_newline(context.config)); attrs_str.push_str(&shape.indent.to_string_with_newline(context.config));
}; };
let name = context.snippet(field.ident.span); let name = context.snippet(field.ident.span);
if field.is_shorthand { if field.is_shorthand {
Some(attrs_str + name) Ok(attrs_str + name)
} else { } else {
let mut separator = String::from(struct_lit_field_separator(context.config)); let mut separator = String::from(struct_lit_field_separator(context.config));
for _ in 0..prefix_max_width.saturating_sub(name.len()) { for _ in 0..prefix_max_width.saturating_sub(name.len()) {
separator.push(' '); separator.push(' ');
} }
let overhead = name.len() + separator.len(); let overhead = name.len() + separator.len();
let expr_shape = shape.offset_left(overhead)?; let expr_shape = shape
let expr = field.expr.rewrite(context, expr_shape); .offset_left(overhead)
.max_width_error(shape.width, field.span)?;
let expr = field.expr.rewrite_result(context, expr_shape);
let is_lit = matches!(field.expr.kind, ast::ExprKind::Lit(_)); let is_lit = matches!(field.expr.kind, ast::ExprKind::Lit(_));
match expr { match expr {
Some(ref e) Ok(ref e)
if !is_lit && e.as_str() == name && context.config.use_field_init_shorthand() => if !is_lit && e.as_str() == name && context.config.use_field_init_shorthand() =>
{ {
Some(attrs_str + name) Ok(attrs_str + name)
} }
Some(e) => Some(format!("{attrs_str}{name}{separator}{e}")), Ok(e) => Ok(format!("{attrs_str}{name}{separator}{e}")),
None => { Err(_) => {
let expr_offset = shape.indent.block_indent(context.config); let expr_offset = shape.indent.block_indent(context.config);
let expr = field let expr = field
.expr .expr
.rewrite(context, Shape::indented(expr_offset, context.config)); .rewrite_result(context, Shape::indented(expr_offset, context.config));
expr.map(|s| { expr.map(|s| {
format!( format!(
"{}{}:\n{}{}", "{}{}:\n{}{}",

View File

@ -13,7 +13,7 @@ use crate::lists::{
use crate::macros::{rewrite_macro, MacroPosition}; use crate::macros::{rewrite_macro, MacroPosition};
use crate::overflow; use crate::overflow;
use crate::pairs::{rewrite_pair, PairParts}; use crate::pairs::{rewrite_pair, PairParts};
use crate::rewrite::{Rewrite, RewriteContext}; use crate::rewrite::{Rewrite, RewriteContext, RewriteErrorExt, RewriteResult};
use crate::shape::Shape; use crate::shape::Shape;
use crate::source_map::SpanUtils; use crate::source_map::SpanUtils;
use crate::spanned::Spanned; use crate::spanned::Spanned;
@ -292,7 +292,8 @@ impl Rewrite for Pat {
self.span, self.span,
context, context,
shape, shape,
), )
.ok(),
PatKind::MacCall(ref mac) => { PatKind::MacCall(ref mac) => {
rewrite_macro(mac, None, context, shape, MacroPosition::Pat) rewrite_macro(mac, None, context, shape, MacroPosition::Pat)
} }
@ -313,20 +314,21 @@ fn rewrite_struct_pat(
span: Span, span: Span,
context: &RewriteContext<'_>, context: &RewriteContext<'_>,
shape: Shape, shape: Shape,
) -> Option<String> { ) -> RewriteResult {
// 2 = ` {` // 2 = ` {`
let path_shape = shape.sub_width(2)?; let path_shape = shape.sub_width(2).max_width_error(shape.width, span)?;
let path_str = rewrite_path(context, PathContext::Expr, qself, path, path_shape).ok()?; let path_str = rewrite_path(context, PathContext::Expr, qself, path, path_shape)?;
if fields.is_empty() && !ellipsis { if fields.is_empty() && !ellipsis {
return Some(format!("{path_str} {{}}")); return Ok(format!("{path_str} {{}}"));
} }
let (ellipsis_str, terminator) = if ellipsis { (", ..", "..") } else { ("", "}") }; let (ellipsis_str, terminator) = if ellipsis { (", ..", "..") } else { ("", "}") };
// 3 = ` { `, 2 = ` }`. // 3 = ` { `, 2 = ` }`.
let (h_shape, v_shape) = let (h_shape, v_shape) =
struct_lit_shape(shape, context, path_str.len() + 3, ellipsis_str.len() + 2)?; struct_lit_shape(shape, context, path_str.len() + 3, ellipsis_str.len() + 2)
.max_width_error(shape.width, span)?;
let items = itemize_list( let items = itemize_list(
context.snippet_provider, context.snippet_provider,
@ -352,7 +354,7 @@ fn rewrite_struct_pat(
let nested_shape = shape_for_tactic(tactic, h_shape, v_shape); let nested_shape = shape_for_tactic(tactic, h_shape, v_shape);
let fmt = struct_lit_formatting(nested_shape, tactic, context, false); let fmt = struct_lit_formatting(nested_shape, tactic, context, false);
let mut fields_str = write_list(&item_vec, &fmt)?; let mut fields_str = write_list(&item_vec, &fmt).unknown_error()?;
let one_line_width = h_shape.map_or(0, |shape| shape.width); let one_line_width = h_shape.map_or(0, |shape| shape.width);
let has_trailing_comma = fmt.needs_trailing_separator(); let has_trailing_comma = fmt.needs_trailing_separator();
@ -380,7 +382,7 @@ fn rewrite_struct_pat(
// ast::Pat doesn't have attrs so use &[] // ast::Pat doesn't have attrs so use &[]
let fields_str = wrap_struct_field(context, &[], &fields_str, shape, v_shape, one_line_width)?; let fields_str = wrap_struct_field(context, &[], &fields_str, shape, v_shape, one_line_width)?;
Some(format!("{path_str} {{{fields_str}}}")) Ok(format!("{path_str} {{{fields_str}}}"))
} }
impl Rewrite for PatField { impl Rewrite for PatField {

View File

@ -13,7 +13,7 @@ use crate::items::{rewrite_struct_field, rewrite_struct_field_prefix};
use crate::lists::{ use crate::lists::{
definitive_tactic, itemize_list, write_list, ListFormatting, ListItem, Separator, definitive_tactic, itemize_list, write_list, ListFormatting, ListItem, Separator,
}; };
use crate::rewrite::{Rewrite, RewriteContext}; use crate::rewrite::{Rewrite, RewriteContext, RewriteResult};
use crate::shape::{Indent, Shape}; use crate::shape::{Indent, Shape};
use crate::source_map::SpanUtils; use crate::source_map::SpanUtils;
use crate::spanned::Spanned; use crate::spanned::Spanned;
@ -30,7 +30,7 @@ pub(crate) trait AlignedItem {
context: &RewriteContext<'_>, context: &RewriteContext<'_>,
shape: Shape, shape: Shape,
prefix_max_width: usize, prefix_max_width: usize,
) -> Option<String>; ) -> RewriteResult;
} }
impl AlignedItem for ast::FieldDef { impl AlignedItem for ast::FieldDef {
@ -66,8 +66,8 @@ impl AlignedItem for ast::FieldDef {
context: &RewriteContext<'_>, context: &RewriteContext<'_>,
shape: Shape, shape: Shape,
prefix_max_width: usize, prefix_max_width: usize,
) -> Option<String> { ) -> RewriteResult {
rewrite_struct_field(context, self, shape, prefix_max_width).ok() rewrite_struct_field(context, self, shape, prefix_max_width)
} }
} }
@ -103,7 +103,7 @@ impl AlignedItem for ast::ExprField {
context: &RewriteContext<'_>, context: &RewriteContext<'_>,
shape: Shape, shape: Shape,
prefix_max_width: usize, prefix_max_width: usize,
) -> Option<String> { ) -> RewriteResult {
rewrite_field(context, self, shape, prefix_max_width) rewrite_field(context, self, shape, prefix_max_width)
} }
} }
@ -228,7 +228,11 @@ fn rewrite_aligned_items_inner<T: AlignedItem>(
",", ",",
|field| field.get_span().lo(), |field| field.get_span().lo(),
|field| field.get_span().hi(), |field| field.get_span().hi(),
|field| field.rewrite_aligned_item(context, item_shape, field_prefix_max_width), |field| {
field
.rewrite_aligned_item(context, item_shape, field_prefix_max_width)
.ok()
},
span.lo(), span.lo(),
span.hi(), span.hi(),
false, false,
@ -244,8 +248,9 @@ fn rewrite_aligned_items_inner<T: AlignedItem>(
if tactic == DefinitiveListTactic::Horizontal { if tactic == DefinitiveListTactic::Horizontal {
// since the items fits on a line, there is no need to align them // since the items fits on a line, there is no need to align them
let do_rewrite = let do_rewrite = |field: &T| -> Option<String> {
|field: &T| -> Option<String> { field.rewrite_aligned_item(context, item_shape, 0) }; field.rewrite_aligned_item(context, item_shape, 0).ok()
};
fields fields
.iter() .iter()
.zip(items.iter_mut()) .zip(items.iter_mut())