add rewrite_result method to Rewrite trait

impl rewrite_result for ast::Local, ast::FieldDef, ast::Param, ast::FnRetTy
This commit is contained in:
ding-young 2024-06-19 16:32:03 +09:00 committed by Yacin Tmimi
parent 533b760f8d
commit 905ca5483b
3 changed files with 142 additions and 34 deletions

View File

@ -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<String> {
self.rewrite_result(context, shape).ok()
}
fn rewrite_result(
&self,
context: &RewriteContext<'_>,
shape: Shape,
) -> Result<String, RewriteError> {
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<String>
),
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<String>
} 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<String>
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<String>
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<String>
&& 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<String>
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<String>
}
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<String> {
rewrite_struct_field(context, self, shape, 0)
self.rewrite_result(context, shape).ok()
}
fn rewrite_result(
&self,
context: &RewriteContext<'_>,
shape: Shape,
) -> Result<String, RewriteError> {
rewrite_struct_field(context, self, shape, 0).ok_or_else(|| RewriteError::Unknown)
}
}
@ -2071,20 +2110,40 @@ fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option<String>
impl Rewrite for ast::FnRetTy {
fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option<String> {
self.rewrite_result(context, shape).ok()
}
fn rewrite_result(
&self,
context: &RewriteContext<'_>,
shape: Shape,
) -> Result<String, RewriteError> {
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<String> {
self.rewrite_result(context, shape).ok()
}
fn rewrite_result(
&self,
context: &RewriteContext<'_>,
shape: Shape,
) -> Result<String, RewriteError> {
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<String>
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,
&param_attrs_result,
@ -2171,7 +2239,8 @@ fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option<String>
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<String>
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<String>
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)
}
}
}

View File

@ -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<String>;
fn rewrite_result(
&self,
context: &RewriteContext<'_>,
shape: Shape,
) -> Result<String, RewriteError> {
self.rewrite(context, shape).ok_or(RewriteError::Unknown)
}
}
impl<T: Rewrite> Rewrite for ptr::P<T> {
@ -24,6 +32,19 @@ fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option<String>
}
}
#[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<RefCell<Vec<(usize, usize)>>>,
}
pub(crate) struct InsideMacroGuard {
is_nested_macro_context: bool,
inside_macro_ref: Rc<Cell<bool>>,

View File

@ -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) {