From 905ca5483b1f38a4edbb2be87b2e94fec69e2166 Mon Sep 17 00:00:00 2001 From: ding-young Date: Wed, 19 Jun 2024 16:32:03 +0900 Subject: [PATCH] add rewrite_result method to Rewrite trait impl rewrite_result for ast::Local, ast::FieldDef, ast::Param, ast::FnRetTy --- src/items.rs | 146 ++++++++++++++++++++++++++++++++++++++----------- src/rewrite.rs | 22 +++++++- src/utils.rs | 8 +++ 3 files changed, 142 insertions(+), 34 deletions(-) diff --git a/src/items.rs b/src/items.rs index eb11604b277..eb808678403 100644 --- a/src/items.rs +++ b/src/items.rs @@ -24,7 +24,7 @@ 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}; +use crate::rewrite::{Rewrite, RewriteContext, RewriteError}; use crate::shape::{Indent, Shape}; use crate::source_map::{LineRangeUtils, SpanUtils}; use crate::spanned::Spanned; @@ -48,18 +48,26 @@ fn type_annotation_separator(config: &Config) -> &str { // let pat: ty = init; or let pat: ty = init else { .. }; impl Rewrite for ast::Local { fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option { + self.rewrite_result(context, shape).ok() + } + + fn rewrite_result( + &self, + context: &RewriteContext<'_>, + shape: Shape, + ) -> Result { debug!( "Local::rewrite {:?} {} {:?}", self, shape.width, shape.indent ); - skip_out_of_file_lines_range!(context, self.span); + skip_out_of_file_lines_range_err!(context, self.span); if contains_skip(&self.attrs) { - return None; + return Err(RewriteError::SkipFormatting); } - let attrs_str = self.attrs.rewrite(context, shape)?; + let attrs_str = self.attrs.rewrite_result(context, shape)?; let mut result = if attrs_str.is_empty() { "let ".to_owned() } else { @@ -73,15 +81,27 @@ fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option ), shape, false, - )? + ) + .ok_or_else(|| RewriteError::Unknown)? }; let let_kw_offset = result.len() - "let ".len(); // 4 = "let ".len() - let pat_shape = shape.offset_left(4)?; + let pat_shape = shape.offset_left(4).ok_or_else(|| RewriteError::Unknown)?; // 1 = ; - let pat_shape = pat_shape.sub_width(1)?; - let pat_str = self.pat.rewrite(context, pat_shape)?; + let pat_shape = pat_shape + .sub_width(1) + .ok_or_else(|| RewriteError::ExceedsMaxWidth { + configured_width: shape.width, + span: self.span(), + })?; + let pat_str = + self.pat + .rewrite(context, pat_shape) + .ok_or_else(|| RewriteError::ExceedsMaxWidth { + configured_width: shape.width, + span: self.span(), + })?; result.push_str(&pat_str); // String that is placed within the assignment pattern and expression. @@ -95,11 +115,19 @@ fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option } else { shape } - .offset_left(last_line_width(&result) + separator.len())? + .offset_left(last_line_width(&result) + separator.len()) + .ok_or_else(|| RewriteError::ExceedsMaxWidth { + configured_width: shape.width, + span: self.span(), + })? // 2 = ` =` - .sub_width(2)?; + .sub_width(2) + .ok_or_else(|| RewriteError::ExceedsMaxWidth { + configured_width: shape.width, + span: self.span(), + })?; - let rewrite = ty.rewrite(context, ty_shape)?; + let rewrite = ty.rewrite_result(context, ty_shape)?; infix.push_str(separator); infix.push_str(&rewrite); @@ -116,7 +144,7 @@ fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option if let Some((init, else_block)) = self.kind.init_else_opt() { // 1 = trailing semicolon; - let nested_shape = shape.sub_width(1)?; + let nested_shape = shape.sub_width(1).ok_or_else(|| RewriteError::Unknown)?; result = rewrite_assign_rhs( context, @@ -124,7 +152,8 @@ fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option init, &RhsAssignKind::Expr(&init.kind, init.span), nested_shape, - )?; + ) + .ok_or_else(|| RewriteError::Unknown)?; if let Some(block) = else_block { let else_kw_span = init.span.between(block.span); @@ -166,7 +195,8 @@ fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option && allow_single_line_let_else_block(assign_str_with_else_kw, block); let mut rw_else_block = - rewrite_let_else_block(block, allow_single_line, context, shape)?; + rewrite_let_else_block(block, allow_single_line, context, shape) + .ok_or_else(|| RewriteError::Unknown)?; let single_line_else = !rw_else_block.contains('\n'); // +1 for the trailing `;` @@ -175,7 +205,8 @@ fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option if allow_single_line && single_line_else && else_block_exceeds_width { // writing this on one line would exceed the available width // so rewrite the else block over multiple lines. - rw_else_block = rewrite_let_else_block(block, false, context, shape)?; + rw_else_block = rewrite_let_else_block(block, false, context, shape) + .ok_or_else(|| RewriteError::Unknown)?; } result.push_str(&rw_else_block); @@ -183,7 +214,7 @@ fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option } result.push(';'); - Some(result) + Ok(result) } } @@ -1845,7 +1876,15 @@ pub(crate) fn rewrite_struct_field_prefix( impl Rewrite for ast::FieldDef { fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option { - rewrite_struct_field(context, self, shape, 0) + self.rewrite_result(context, shape).ok() + } + + fn rewrite_result( + &self, + context: &RewriteContext<'_>, + shape: Shape, + ) -> Result { + rewrite_struct_field(context, self, shape, 0).ok_or_else(|| RewriteError::Unknown) } } @@ -2071,20 +2110,40 @@ fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option impl Rewrite for ast::FnRetTy { fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option { + self.rewrite_result(context, shape).ok() + } + fn rewrite_result( + &self, + context: &RewriteContext<'_>, + shape: Shape, + ) -> Result { match *self { - ast::FnRetTy::Default(_) => Some(String::new()), + ast::FnRetTy::Default(_) => Ok(String::new()), ast::FnRetTy::Ty(ref ty) => { if context.config.version() == Version::One || context.config.indent_style() == IndentStyle::Visual { - let inner_width = shape.width.checked_sub(3)?; + let inner_width = shape.width.checked_sub(3).ok_or_else(|| { + RewriteError::ExceedsMaxWidth { + configured_width: shape.width, + span: self.span(), + } + })?; return ty - .rewrite(context, Shape::legacy(inner_width, shape.indent + 3)) + .rewrite_result(context, Shape::legacy(inner_width, shape.indent + 3)) .map(|r| format!("-> {}", r)); } - ty.rewrite(context, shape.offset_left(3)?) - .map(|s| format!("-> {}", s)) + ty.rewrite_result( + context, + shape + .offset_left(3) + .ok_or_else(|| RewriteError::ExceedsMaxWidth { + configured_width: shape.width, + span: self.span(), + })?, + ) + .map(|s| format!("-> {}", s)) } } } @@ -2135,9 +2194,17 @@ fn get_missing_param_comments( impl Rewrite for ast::Param { fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option { + self.rewrite_result(context, shape).ok() + } + + fn rewrite_result( + &self, + context: &RewriteContext<'_>, + shape: Shape, + ) -> Result { let param_attrs_result = self .attrs - .rewrite(context, Shape::legacy(shape.width, shape.indent))?; + .rewrite_result(context, Shape::legacy(shape.width, shape.indent))?; // N.B. Doc comments aren't typically valid syntax, but could appear // in the presence of certain macros - https://github.com/rust-lang/rustfmt/issues/4936 let (span, has_multiple_attr_lines, has_doc_comments) = if !self.attrs.is_empty() { @@ -2160,10 +2227,11 @@ fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option shape, has_multiple_attr_lines, ) + .ok_or_else(|| RewriteError::Unknown) } else if is_named_param(self) { let param_name = &self .pat - .rewrite(context, Shape::legacy(shape.width, shape.indent))?; + .rewrite_result(context, Shape::legacy(shape.width, shape.indent))?; let mut result = combine_strs_with_missing_comments( context, ¶m_attrs_result, @@ -2171,7 +2239,8 @@ fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option span, shape, !has_multiple_attr_lines && !has_doc_comments, - )?; + ) + .ok_or_else(|| RewriteError::Unknown)?; if !is_empty_infer(&*self.ty, self.pat.span) { let (before_comment, after_comment) = @@ -2180,10 +2249,15 @@ fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option result.push_str(colon_spaces(context.config)); result.push_str(&after_comment); let overhead = last_line_width(&result); - let max_width = shape.width.checked_sub(overhead)?; - if let Some(ty_str) = self + let max_width = shape.width.checked_sub(overhead).ok_or_else(|| { + RewriteError::ExceedsMaxWidth { + configured_width: shape.width, + span: self.span(), + } + })?; + if let Ok(ty_str) = self .ty - .rewrite(context, Shape::legacy(max_width, shape.indent)) + .rewrite_result(context, Shape::legacy(max_width, shape.indent)) { result.push_str(&ty_str); } else { @@ -2200,22 +2274,28 @@ fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option span, shape, !has_multiple_attr_lines, - )?; + ) + .ok_or_else(|| RewriteError::Unknown)?; result.push_str(&before_comment); result.push_str(colon_spaces(context.config)); result.push_str(&after_comment); let overhead = last_line_width(&result); - let max_width = shape.width.checked_sub(overhead)?; + let max_width = shape.width.checked_sub(overhead).ok_or_else(|| { + RewriteError::ExceedsMaxWidth { + configured_width: shape.width, + span: self.span(), + } + })?; let ty_str = self .ty - .rewrite(context, Shape::legacy(max_width, shape.indent))?; + .rewrite_result(context, Shape::legacy(max_width, shape.indent))?; result.push_str(&ty_str); } } - Some(result) + Ok(result) } else { - self.ty.rewrite(context, shape) + self.ty.rewrite_result(context, shape) } } } diff --git a/src/rewrite.rs b/src/rewrite.rs index e2498a3500a..5467bf9d1f4 100644 --- a/src/rewrite.rs +++ b/src/rewrite.rs @@ -5,6 +5,7 @@ use rustc_ast::ptr; use rustc_span::Span; +use thiserror::Error; use crate::config::{Config, IndentStyle}; use crate::parse::session::ParseSess; @@ -16,6 +17,13 @@ pub(crate) trait Rewrite { /// Rewrite self into shape. fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option; + fn rewrite_result( + &self, + context: &RewriteContext<'_>, + shape: Shape, + ) -> Result { + self.rewrite(context, shape).ok_or(RewriteError::Unknown) + } } impl Rewrite for ptr::P { @@ -24,6 +32,19 @@ fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option } } +#[derive(Error, Debug)] +pub(crate) enum RewriteError { + #[error("Formatting was skipped due to skip attribute or out of file range.")] + SkipFormatting, + + #[error("It exceeds the required width of {configured_width} for the span: {span:?}")] + ExceedsMaxWidth { configured_width: usize, span: Span }, + + /// Format failure that does not fit to above categories. + #[error("An unknown error occurred during formatting.")] + Unknown, +} + #[derive(Clone)] pub(crate) struct RewriteContext<'a> { pub(crate) psess: &'a ParseSess, @@ -44,7 +65,6 @@ pub(crate) struct RewriteContext<'a> { pub(crate) skip_context: SkipContext, pub(crate) skipped_range: Rc>>, } - pub(crate) struct InsideMacroGuard { is_nested_macro_context: bool, inside_macro_ref: Rc>, diff --git a/src/utils.rs b/src/utils.rs index fd59aedadfe..eaf24f3f204 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -375,6 +375,14 @@ macro_rules! skip_out_of_file_lines_range { }; } +macro_rules! skip_out_of_file_lines_range_err { + ($self:ident, $span:expr) => { + if out_of_file_lines_range!($self, $span) { + return Err(RewriteError::SkipFormatting); + } + }; +} + macro_rules! skip_out_of_file_lines_range_visitor { ($self:ident, $span:expr) => { if out_of_file_lines_range!($self, $span) {