use crate::{
formatter::{
shape::{ExprKind, LineStyle},
*,
},
utils::{
map::byte_span::{ByteSpan, LeafSpans},
{CurlyBrace, Parenthesis, SquareBracket},
},
};
use std::fmt::Write;
use sway_ast::{
brackets::Parens,
keywords::{CommaToken, DotToken},
punctuated::Punctuated,
Braces, CodeBlockContents, Expr, ExprStructField, IfExpr, MatchBranch, PathExpr,
PathExprSegment,
};
use sway_types::{ast::Delimiter, Spanned};
pub(crate) mod abi_cast;
pub(crate) mod asm_block;
pub(crate) mod assignable;
pub(crate) mod code_block;
pub(crate) mod collections;
pub(crate) mod conditional;
pub(crate) mod struct_field;
#[cfg(test)]
mod tests;
#[inline]
fn two_parts_expr(
lhs: &Expr,
operator: &str,
rhs: &Expr,
formatted_code: &mut FormattedCode,
formatter: &mut Formatter,
) -> Result<(), FormatterError> {
let mut rhs_code = FormattedCode::new();
rhs.format(&mut rhs_code, formatter)?;
if !formatter.shape.code_line.expr_new_line
&& rhs_code.len() > formatter.shape.width_heuristics.collection_width
{
formatter.with_shape(
formatter
.shape
.with_code_line_from(LineStyle::Multiline, ExprKind::Undetermined),
|formatter| -> Result<(), FormatterError> {
formatter.shape.code_line.update_expr_new_line(true);
lhs.format(formatted_code, formatter)?;
formatter.indent();
write!(
formatted_code,
"\n{}{} ",
formatter.indent_to_str()?,
operator,
)?;
rhs.format(formatted_code, formatter)?;
formatter.unindent();
Ok(())
},
)?;
} else {
lhs.format(formatted_code, formatter)?;
match formatter.shape.code_line.line_style {
LineStyle::Multiline => {
write!(
formatted_code,
"\n{}{} ",
formatter.indent_to_str()?,
operator,
)?;
}
_ => {
write!(formatted_code, " {} ", operator,)?;
}
}
write!(formatted_code, "{}", rhs_code)?;
}
Ok(())
}
impl Format for Expr {
fn format(
&self,
formatted_code: &mut FormattedCode,
formatter: &mut Formatter,
) -> Result<(), FormatterError> {
match self {
Self::Error(_, _) => {
return Err(FormatterError::SyntaxError);
}
Self::Path(path) => path.format(formatted_code, formatter)?,
Self::Literal(lit) => lit.format(formatted_code, formatter)?,
Self::AbiCast { abi_token, args } => {
write!(formatted_code, "{}", abi_token.span().as_str())?;
args.get().format(formatted_code, formatter)?;
}
Self::Struct { path, fields } => {
formatter.with_shape(
formatter
.shape
.with_code_line_from(LineStyle::default(), ExprKind::Struct),
|formatter| -> Result<(), FormatterError> {
let mut buf = FormattedCode::new();
let mut temp_formatter = Formatter::default();
temp_formatter
.shape
.code_line
.update_line_style(LineStyle::Inline);
format_expr_struct(path, fields, &mut buf, &mut temp_formatter)?;
let (field_width, body_width) =
get_field_width(fields.get(), &mut formatter.clone())?;
formatter.shape.code_line.update_expr_new_line(true);
let expr_width = buf.chars().count();
formatter.shape.code_line.update_width(expr_width);
formatter.shape.get_line_style(
Some(field_width),
Some(body_width),
&formatter.config,
);
format_expr_struct(path, fields, formatted_code, formatter)?;
Ok(())
},
)?;
}
Self::Tuple(tuple_descriptor) => {
formatter.with_shape(
formatter
.shape
.with_code_line_from(LineStyle::default(), ExprKind::Collection),
|formatter| -> Result<(), FormatterError> {
let mut buf = FormattedCode::new();
let mut temp_formatter = Formatter::default();
let tuple_descriptor = tuple_descriptor.get();
tuple_descriptor.format(&mut buf, &mut temp_formatter)?;
let body_width = buf.chars().count();
formatter.shape.code_line.update_width(body_width);
formatter
.shape
.get_line_style(None, Some(body_width), &formatter.config);
tuple_descriptor.format(formatted_code, formatter)?;
Ok(())
},
)?;
}
Self::Parens(expr) => {
if formatter.shape.code_line.expr_new_line {
formatter.indent();
}
Self::open_parenthesis(formatted_code, formatter)?;
expr.get().format(formatted_code, formatter)?;
Self::close_parenthesis(formatted_code, formatter)?;
if formatter.shape.code_line.expr_new_line {
formatter.unindent();
}
}
Self::Block(code_block) => {
if !code_block.get().statements.is_empty()
|| code_block.get().final_expr_opt.is_some()
{
CodeBlockContents::open_curly_brace(formatted_code, formatter)?;
code_block.get().format(formatted_code, formatter)?;
CodeBlockContents::close_curly_brace(formatted_code, formatter)?;
} else {
write!(formatted_code, "{{}}")?;
}
}
Self::Array(array_descriptor) => {
formatter.with_shape(
formatter
.shape
.with_code_line_from(LineStyle::default(), ExprKind::Collection),
|formatter| -> Result<(), FormatterError> {
let mut buf = FormattedCode::new();
let mut temp_formatter = Formatter::default();
let array_descriptor = array_descriptor.get();
array_descriptor.format(&mut buf, &mut temp_formatter)?;
let body_width = buf.chars().count();
formatter.shape.code_line.add_width(body_width);
formatter
.shape
.get_line_style(None, Some(body_width), &formatter.config);
if formatter.shape.code_line.line_style == LineStyle::Multiline {
array_descriptor.format(formatted_code, formatter)?;
} else {
write!(formatted_code, "{}", buf)?;
}
Ok(())
},
)?;
}
Self::Asm(asm_block) => asm_block.format(formatted_code, formatter)?,
Self::Return {
return_token,
expr_opt,
} => {
write!(formatted_code, "{}", return_token.span().as_str())?;
if let Some(expr) = &expr_opt {
write!(formatted_code, " ")?;
expr.format(formatted_code, formatter)?;
}
}
Self::If(if_expr) => if_expr.format(formatted_code, formatter)?,
Self::Match {
match_token,
value,
branches,
} => {
write!(formatted_code, "{} ", match_token.span().as_str())?;
value.format(formatted_code, formatter)?;
write!(formatted_code, " ")?;
if !branches.get().is_empty() {
MatchBranch::open_curly_brace(formatted_code, formatter)?;
let branches = branches.get();
for match_branch in branches.iter() {
write!(formatted_code, "{}", formatter.indent_to_str()?)?;
match_branch.format(formatted_code, formatter)?;
writeln!(formatted_code)?;
}
MatchBranch::close_curly_brace(formatted_code, formatter)?;
} else {
write!(formatted_code, "{{}}")?;
}
}
Self::While {
while_token,
condition,
block,
} => {
formatter.with_shape(
formatter
.shape
.with_code_line_from(LineStyle::Normal, ExprKind::Function),
|formatter| -> Result<(), FormatterError> {
write!(formatted_code, "{} ", while_token.span().as_str())?;
condition.format(formatted_code, formatter)?;
IfExpr::open_curly_brace(formatted_code, formatter)?;
block.get().format(formatted_code, formatter)?;
IfExpr::close_curly_brace(formatted_code, formatter)?;
Ok(())
},
)?;
}
Self::For {
for_token,
in_token,
value_pattern,
iterator,
block,
} => {
formatter.with_shape(
formatter
.shape
.with_code_line_from(LineStyle::Normal, ExprKind::Function),
|formatter| -> Result<(), FormatterError> {
write!(formatted_code, "{} ", for_token.span().as_str())?;
value_pattern.format(formatted_code, formatter)?;
write!(formatted_code, "{} ", in_token.span().as_str())?;
iterator.format(formatted_code, formatter)?;
IfExpr::open_curly_brace(formatted_code, formatter)?;
block.get().format(formatted_code, formatter)?;
IfExpr::close_curly_brace(formatted_code, formatter)?;
Ok(())
},
)?;
}
Self::FuncApp { func, args } => {
formatter.with_shape(
formatter
.shape
.with_code_line_from(LineStyle::Normal, ExprKind::Function),
|formatter| -> Result<(), FormatterError> {
if formatted_code.ends_with('\n') {
write!(formatted_code, "{}", formatter.indent_to_str()?)?;
}
func.format(formatted_code, formatter)?;
Self::open_parenthesis(formatted_code, formatter)?;
let (_, args_str) = write_function_call_arguments(args.get(), formatter)?;
write!(formatted_code, "{}", args_str,)?;
Self::close_parenthesis(formatted_code, formatter)?;
Ok(())
},
)?;
}
Self::Index { target, arg } => {
target.format(formatted_code, formatter)?;
Self::open_square_bracket(formatted_code, formatter)?;
arg.get().format(formatted_code, formatter)?;
Self::close_square_bracket(formatted_code, formatter)?;
}
Self::MethodCall {
target,
dot_token,
path_seg,
contract_args_opt,
args,
} => {
formatter.with_shape(
formatter.shape.with_default_code_line(),
|formatter| -> Result<(), FormatterError> {
let mut buf = FormattedCode::new();
let mut temp_formatter = Formatter::default();
temp_formatter
.shape
.code_line
.update_line_style(LineStyle::Inline);
let (function_call_length, args_inline) = format_method_call(
target,
dot_token,
path_seg,
contract_args_opt,
args,
&mut buf,
&mut temp_formatter,
)?;
let (field_width, body_width) = if args_inline {
(function_call_length, function_call_length)
} else if let Some(contract_args) = &contract_args_opt {
get_field_width(contract_args.get(), &mut formatter.clone())?
} else {
(0, 0)
};
let expr_width = buf.chars().count();
formatter.shape.code_line.add_width(expr_width);
formatter.shape.code_line.update_expr_kind(ExprKind::Struct);
formatter.shape.get_line_style(
Some(field_width),
Some(body_width),
&formatter.config,
);
let _ = format_method_call(
target,
dot_token,
path_seg,
contract_args_opt,
args,
formatted_code,
formatter,
)?;
Ok(())
},
)?;
}
Self::FieldProjection {
target,
dot_token,
name,
} => {
let prev_length = formatted_code.len();
target.format(formatted_code, formatter)?;
let diff = formatted_code.len() - prev_length;
if diff > 5 && formatter.shape.code_line.expr_new_line {
formatter.indent();
write!(
formatted_code,
"\n{}{}",
formatter.indent_to_str()?,
dot_token.span().as_str()
)?;
name.format(formatted_code, formatter)?;
formatter.unindent();
} else {
write!(formatted_code, "{}", dot_token.span().as_str())?;
name.format(formatted_code, formatter)?;
}
}
Self::TupleFieldProjection {
target,
dot_token,
field: _,
field_span,
} => {
target.format(formatted_code, formatter)?;
write!(
formatted_code,
"{}{}",
dot_token.span().as_str(),
field_span.as_str(),
)?;
}
Self::Ref {
ampersand_token,
mut_token,
expr,
} => {
write!(formatted_code, "{}", ampersand_token.span().as_str())?;
if let Some(mut_token) = mut_token {
write!(formatted_code, "{} ", mut_token.span().as_str())?;
}
expr.format(formatted_code, formatter)?;
}
Self::Deref { star_token, expr } => {
write!(formatted_code, "{}", star_token.span().as_str())?;
expr.format(formatted_code, formatter)?;
}
Self::Not { bang_token, expr } => {
write!(formatted_code, "{}", bang_token.span().as_str())?;
expr.format(formatted_code, formatter)?;
}
Self::Pow {
lhs,
double_star_token,
rhs,
} => {
lhs.format(formatted_code, formatter)?;
write!(formatted_code, " {} ", double_star_token.span().as_str())?;
rhs.format(formatted_code, formatter)?;
}
Self::Mul {
lhs,
star_token,
rhs,
} => {
lhs.format(formatted_code, formatter)?;
write!(formatted_code, " {} ", star_token.span().as_str())?;
rhs.format(formatted_code, formatter)?;
}
Self::Div {
lhs,
forward_slash_token,
rhs,
} => {
lhs.format(formatted_code, formatter)?;
write!(formatted_code, " {} ", forward_slash_token.span().as_str())?;
rhs.format(formatted_code, formatter)?;
}
Self::Modulo {
lhs,
percent_token,
rhs,
} => {
lhs.format(formatted_code, formatter)?;
write!(formatted_code, " {} ", percent_token.span().as_str())?;
rhs.format(formatted_code, formatter)?;
}
Self::Add {
lhs,
add_token,
rhs,
} => {
lhs.format(formatted_code, formatter)?;
write!(formatted_code, " {} ", add_token.span().as_str())?;
rhs.format(formatted_code, formatter)?;
}
Self::Sub {
lhs,
sub_token,
rhs,
} => {
lhs.format(formatted_code, formatter)?;
write!(formatted_code, " {} ", sub_token.span().as_str())?;
rhs.format(formatted_code, formatter)?;
}
Self::Shl {
lhs,
shl_token,
rhs,
} => {
lhs.format(formatted_code, formatter)?;
write!(formatted_code, " {} ", shl_token.span().as_str())?;
rhs.format(formatted_code, formatter)?;
}
Self::Shr {
lhs,
shr_token,
rhs,
} => {
lhs.format(formatted_code, formatter)?;
write!(formatted_code, " {} ", shr_token.span().as_str())?;
rhs.format(formatted_code, formatter)?;
}
Self::BitAnd {
lhs,
ampersand_token,
rhs,
} => {
lhs.format(formatted_code, formatter)?;
match formatter.shape.code_line.line_style {
LineStyle::Multiline => {
write!(
formatted_code,
"\n{}{} ",
formatter.indent_to_str()?,
ampersand_token.span().as_str()
)?;
}
_ => {
write!(formatted_code, " {} ", ampersand_token.span().as_str())?;
}
}
rhs.format(formatted_code, formatter)?;
}
Self::BitXor {
lhs,
caret_token,
rhs,
} => {
lhs.format(formatted_code, formatter)?;
match formatter.shape.code_line.line_style {
LineStyle::Multiline => {
write!(
formatted_code,
"\n{}{} ",
formatter.indent_to_str()?,
caret_token.span().as_str()
)?;
}
_ => {
write!(formatted_code, " {} ", caret_token.span().as_str())?;
}
}
rhs.format(formatted_code, formatter)?;
}
Self::BitOr {
lhs,
pipe_token,
rhs,
} => {
lhs.format(formatted_code, formatter)?;
match formatter.shape.code_line.line_style {
LineStyle::Multiline => {
write!(
formatted_code,
"\n{}{} ",
formatter.indent_to_str()?,
pipe_token.span().as_str()
)?;
}
_ => {
write!(formatted_code, " {} ", pipe_token.span().as_str())?;
}
}
rhs.format(formatted_code, formatter)?;
}
Self::Equal {
lhs,
double_eq_token,
rhs,
} => {
lhs.format(formatted_code, formatter)?;
write!(formatted_code, " {} ", double_eq_token.span().as_str())?;
rhs.format(formatted_code, formatter)?;
}
Self::NotEqual {
lhs,
bang_eq_token,
rhs,
} => {
lhs.format(formatted_code, formatter)?;
write!(formatted_code, " {} ", bang_eq_token.span().as_str())?;
rhs.format(formatted_code, formatter)?;
}
Self::LessThan {
lhs,
less_than_token,
rhs,
} => {
lhs.format(formatted_code, formatter)?;
write!(formatted_code, " {} ", less_than_token.span().as_str())?;
rhs.format(formatted_code, formatter)?;
}
Self::GreaterThan {
lhs,
greater_than_token,
rhs,
} => {
lhs.format(formatted_code, formatter)?;
write!(formatted_code, " {} ", greater_than_token.span().as_str())?;
rhs.format(formatted_code, formatter)?;
}
Self::LessThanEq {
lhs,
less_than_eq_token,
rhs,
} => {
lhs.format(formatted_code, formatter)?;
write!(formatted_code, " {} ", less_than_eq_token.span().as_str())?;
rhs.format(formatted_code, formatter)?;
}
Self::GreaterThanEq {
lhs,
greater_than_eq_token,
rhs,
} => {
lhs.format(formatted_code, formatter)?;
write!(
formatted_code,
" {} ",
greater_than_eq_token.span().as_str()
)?;
rhs.format(formatted_code, formatter)?;
}
Self::LogicalAnd {
lhs,
double_ampersand_token,
rhs,
} => {
two_parts_expr(
lhs,
double_ampersand_token.span().as_str(),
rhs,
formatted_code,
formatter,
)?;
}
Self::LogicalOr {
lhs,
double_pipe_token,
rhs,
} => {
two_parts_expr(
lhs,
double_pipe_token.span().as_str(),
rhs,
formatted_code,
formatter,
)?;
}
Self::Reassignment {
assignable,
reassignment_op,
expr,
} => {
assignable.format(formatted_code, formatter)?;
reassignment_op.format(formatted_code, formatter)?;
expr.format(formatted_code, formatter)?;
}
Self::Break { break_token } => {
write!(formatted_code, "{}", break_token.span().as_str())?;
}
Self::Continue { continue_token } => {
write!(formatted_code, "{}", continue_token.span().as_str())?;
}
}
Ok(())
}
}
impl Parenthesis for Expr {
fn open_parenthesis(
line: &mut FormattedCode,
_formatter: &mut Formatter,
) -> Result<(), FormatterError> {
write!(line, "{}", Delimiter::Parenthesis.as_open_char())?;
Ok(())
}
fn close_parenthesis(
line: &mut FormattedCode,
_formatter: &mut Formatter,
) -> Result<(), FormatterError> {
write!(line, "{}", Delimiter::Parenthesis.as_close_char())?;
Ok(())
}
}
impl SquareBracket for Expr {
fn open_square_bracket(
line: &mut FormattedCode,
_formatter: &mut Formatter,
) -> Result<(), FormatterError> {
write!(line, "{}", Delimiter::Bracket.as_open_char())?;
Ok(())
}
fn close_square_bracket(
line: &mut FormattedCode,
_formatter: &mut Formatter,
) -> Result<(), FormatterError> {
write!(line, "{}", Delimiter::Bracket.as_close_char())?;
Ok(())
}
}
pub(super) fn debug_expr(
buf: FormattedCode,
field_width: Option<usize>,
body_width: Option<usize>,
expr_width: usize,
formatter: &Formatter,
) {
println!(
"DEBUG:\nline: {buf}\nfield: {:?}, body: {:?}, expr: {expr_width}, Shape::width: {}",
field_width, body_width, formatter.shape.code_line.width
);
println!("{:?}", formatter.shape.code_line);
println!("{:?}\n", formatter.shape.width_heuristics);
}
fn format_expr_struct(
path: &PathExpr,
fields: &Braces<Punctuated<ExprStructField, CommaToken>>,
formatted_code: &mut FormattedCode,
formatter: &mut Formatter,
) -> Result<(), FormatterError> {
path.format(formatted_code, formatter)?;
ExprStructField::open_curly_brace(formatted_code, formatter)?;
let fields = &fields.get();
match formatter.shape.code_line.line_style {
LineStyle::Inline => fields.format(formatted_code, formatter)?,
_ => fields.format(formatted_code, formatter)?,
}
ExprStructField::close_curly_brace(formatted_code, formatter)?;
Ok(())
}
#[inline]
pub fn should_write_multiline(code: &str, formatter: &Formatter) -> bool {
if formatter.shape.code_line.expr_new_line {
true
} else {
let max_per_line = formatter.shape.width_heuristics.collection_width;
for (i, c) in code.chars().rev().enumerate() {
if c == '\n' {
return i > max_per_line;
}
}
false
}
}
#[inline]
fn same_line_if_only_argument(expr: &Expr) -> bool {
matches!(
expr,
Expr::Struct { path: _, fields: _ }
| Expr::Tuple(_)
| Expr::Array(_)
| Expr::Parens(_)
| Expr::Not {
bang_token: _,
expr: _
}
| Expr::Path(_)
| Expr::FuncApp { func: _, args: _ }
| Expr::Match {
match_token: _,
value: _,
branches: _
}
)
}
#[inline]
pub(crate) fn is_single_argument_and_can_be_inline<P>(
args: &Punctuated<Expr, P>,
formatter: &mut Formatter,
) -> bool
where
P: Format + std::fmt::Debug,
{
formatter.with_shape(
formatter
.shape
.with_code_line_from(LineStyle::Normal, ExprKind::Function),
|formatter| -> bool {
let mut buf = FormattedCode::new();
if args.value_separator_pairs.len() == 1 && args.final_value_opt.is_none() {
if same_line_if_only_argument(&args.value_separator_pairs[0].0) {
return true;
}
let _ = args.value_separator_pairs[0].0.format(&mut buf, formatter);
} else if args.value_separator_pairs.is_empty() && args.final_value_opt.is_some() {
if let Some(final_value) = &args.final_value_opt {
if same_line_if_only_argument(final_value) {
return true;
}
let _ = (**final_value).format(&mut buf, formatter);
}
} else {
return false;
}
buf.len() < formatter.shape.width_heuristics.collection_width
},
)
}
#[inline]
pub fn write_function_call_arguments<P>(
args: &Punctuated<Expr, P>,
formatter: &mut Formatter,
) -> Result<(bool, String), FormatterError>
where
P: Format + std::fmt::Debug,
{
let has_single_argument_and_can_be_inlined =
is_single_argument_and_can_be_inline(args, formatter);
formatter.with_shape(
formatter
.shape
.with_code_line_from(LineStyle::Normal, ExprKind::Function),
|formatter| -> Result<(bool, String), FormatterError> {
let mut buf = FormattedCode::new();
args.format(&mut buf, formatter)?;
Ok(if has_single_argument_and_can_be_inlined {
(true, buf.trim().to_owned())
} else {
let expr_width = buf.chars().count();
formatter.shape.code_line.add_width(expr_width);
formatter.shape.get_line_style(
Some(expr_width),
Some(expr_width),
&formatter.config,
);
if expr_width == 0 {
return Ok((true, "".to_owned()));
}
match formatter.shape.code_line.line_style {
LineStyle::Multiline => {
formatter.shape.code_line.update_expr_new_line(true);
formatter.indent();
let mut formatted_code = FormattedCode::new();
let mut buf = FormattedCode::new();
args.format(&mut buf, formatter)?;
formatter.unindent();
writeln!(formatted_code, "{}", buf.trim_end())?;
formatter.write_indent_into_buffer(&mut formatted_code)?;
(false, formatted_code)
}
_ => (true, buf.trim().to_owned()),
}
})
},
)
}
fn format_method_call(
target: &Expr,
dot_token: &DotToken,
path_seg: &PathExprSegment,
contract_args_opt: &Option<Braces<Punctuated<ExprStructField, CommaToken>>>,
args: &Parens<Punctuated<Expr, CommaToken>>,
formatted_code: &mut FormattedCode,
formatter: &mut Formatter,
) -> Result<(usize, bool), FormatterError> {
if formatted_code.ends_with('\n') {
write!(formatted_code, "{}", formatter.indent_to_str()?)?;
}
target.format(formatted_code, formatter)?;
if formatter.shape.code_line.expr_new_line {
formatter.indent();
write!(formatted_code, "\n{}", formatter.indent_to_str()?)?;
}
write!(formatted_code, "{}", dot_token.span().as_str())?;
path_seg.format(formatted_code, formatter)?;
if let Some(contract_args) = &contract_args_opt {
ExprStructField::open_curly_brace(formatted_code, formatter)?;
let contract_args = &contract_args.get();
match formatter.shape.code_line.line_style {
LineStyle::Inline => {
contract_args.format(formatted_code, formatter)?;
}
_ => {
contract_args.format(formatted_code, formatter)?;
}
}
ExprStructField::close_curly_brace(formatted_code, formatter)?;
}
let len_function_call = formatted_code.len();
Expr::open_parenthesis(formatted_code, formatter)?;
let (args_inline, args_str) = write_function_call_arguments(args.get(), formatter)?;
write!(formatted_code, "{}", args_str,)?;
Expr::close_parenthesis(formatted_code, formatter)?;
if formatter.shape.code_line.expr_new_line {
formatter.unindent();
}
Ok((len_function_call, args_inline))
}
fn get_field_width(
fields: &Punctuated<ExprStructField, CommaToken>,
formatter: &mut Formatter,
) -> Result<(usize, usize), FormatterError> {
let mut largest_field: usize = 0;
let mut body_width: usize = 3; for (field, comma_token) in &fields.value_separator_pairs {
let mut field_length = field.field_name.as_str().chars().count();
if let Some((colon_token, expr)) = &field.expr_opt {
let mut buf = String::new();
write!(buf, "{} ", colon_token.span().as_str())?;
expr.format(&mut buf, formatter)?;
field_length += buf.chars().count();
}
field_length += comma_token.span().as_str().chars().count();
body_width += &field_length + 1;
if field_length > largest_field {
largest_field = field_length;
}
}
if let Some(final_value) = &fields.final_value_opt {
let mut field_length = final_value.field_name.as_str().chars().count();
if let Some((colon_token, expr)) = &final_value.expr_opt {
let mut buf = String::new();
write!(buf, "{} ", colon_token.span().as_str())?;
expr.format(&mut buf, formatter)?;
field_length += buf.chars().count();
}
body_width += &field_length + 1;
if field_length > largest_field {
largest_field = field_length;
}
}
Ok((largest_field, body_width))
}
impl LeafSpans for Box<Expr> {
fn leaf_spans(&self) -> Vec<ByteSpan> {
expr_leaf_spans(self)
}
}
impl LeafSpans for Expr {
fn leaf_spans(&self) -> Vec<ByteSpan> {
expr_leaf_spans(self)
}
}
fn expr_leaf_spans(expr: &Expr) -> Vec<ByteSpan> {
match expr {
Expr::Error(_, _) => vec![expr.span().into()],
Expr::Path(path) => path.leaf_spans(),
Expr::Literal(literal) => literal.leaf_spans(),
Expr::AbiCast { abi_token, args } => {
let mut collected_spans = vec![ByteSpan::from(abi_token.span())];
collected_spans.append(&mut args.leaf_spans());
collected_spans
}
Expr::Struct { path, fields } => {
let mut collected_spans = path.leaf_spans();
collected_spans.append(&mut fields.leaf_spans());
collected_spans
}
Expr::Tuple(tuple) => tuple.leaf_spans(),
Expr::Parens(parens) => parens.leaf_spans(),
Expr::Block(block) => block.leaf_spans(),
Expr::Array(array) => array.leaf_spans(),
Expr::Asm(asm) => asm.leaf_spans(),
Expr::Return {
return_token,
expr_opt,
} => {
let mut collected_spans = vec![ByteSpan::from(return_token.span())];
if let Some(expr) = expr_opt {
collected_spans.append(&mut expr.leaf_spans());
}
collected_spans
}
Expr::If(expr_if) => expr_if.leaf_spans(),
Expr::Match {
match_token,
value,
branches,
} => {
let mut collected_spans = vec![ByteSpan::from(match_token.span())];
collected_spans.append(&mut value.leaf_spans());
collected_spans.append(&mut branches.leaf_spans());
collected_spans
}
Expr::While {
while_token,
condition,
block,
} => {
let mut collected_spans = vec![ByteSpan::from(while_token.span())];
collected_spans.append(&mut condition.leaf_spans());
collected_spans.append(&mut block.leaf_spans());
collected_spans
}
Expr::For {
for_token,
in_token,
value_pattern,
iterator,
block,
} => {
let mut collected_spans = vec![ByteSpan::from(for_token.span())];
collected_spans.append(&mut value_pattern.leaf_spans());
collected_spans.append(&mut vec![ByteSpan::from(in_token.span())]);
collected_spans.append(&mut iterator.leaf_spans());
collected_spans.append(&mut block.leaf_spans());
collected_spans
}
Expr::FuncApp { func, args } => {
let mut collected_spans = Vec::new();
collected_spans.append(&mut func.leaf_spans());
collected_spans.append(&mut args.leaf_spans());
collected_spans
}
Expr::Index { target, arg } => {
let mut collected_spans = Vec::new();
collected_spans.append(&mut target.leaf_spans());
collected_spans.append(&mut arg.leaf_spans());
collected_spans
}
Expr::MethodCall {
target,
dot_token,
path_seg,
contract_args_opt,
args,
} => {
let mut collected_spans = Vec::new();
collected_spans.append(&mut target.leaf_spans());
collected_spans.push(ByteSpan::from(dot_token.span()));
collected_spans.push(ByteSpan::from(path_seg.span()));
if let Some(contract_args) = contract_args_opt {
collected_spans.append(&mut contract_args.leaf_spans());
}
collected_spans.append(&mut args.leaf_spans());
collected_spans
}
Expr::FieldProjection {
target,
dot_token,
name,
} => {
let mut collected_spans = Vec::new();
collected_spans.append(&mut target.leaf_spans());
collected_spans.push(ByteSpan::from(dot_token.span()));
collected_spans.push(ByteSpan::from(name.span()));
collected_spans
}
Expr::TupleFieldProjection {
target,
dot_token,
field: _field,
field_span,
} => {
let mut collected_spans = Vec::new();
collected_spans.append(&mut target.leaf_spans());
collected_spans.push(ByteSpan::from(dot_token.span()));
collected_spans.push(ByteSpan::from(field_span.clone()));
collected_spans
}
Expr::Ref {
ampersand_token,
mut_token,
expr,
} => {
let mut collected_spans = vec![ByteSpan::from(ampersand_token.span())];
if let Some(mut_token) = mut_token {
collected_spans.push(ByteSpan::from(mut_token.span()));
}
collected_spans.append(&mut expr.leaf_spans());
collected_spans
}
Expr::Deref { star_token, expr } => {
let mut collected_spans = vec![ByteSpan::from(star_token.span())];
collected_spans.append(&mut expr.leaf_spans());
collected_spans
}
Expr::Not { bang_token, expr } => {
let mut collected_spans = vec![ByteSpan::from(bang_token.span())];
collected_spans.append(&mut expr.leaf_spans());
collected_spans
}
Expr::Pow {
lhs,
double_star_token,
rhs,
} => {
let mut collected_spans = lhs.leaf_spans();
collected_spans.push(ByteSpan::from(double_star_token.span()));
collected_spans.append(&mut rhs.leaf_spans());
collected_spans
}
Expr::Mul {
lhs,
star_token,
rhs,
} => {
let mut collected_spans = lhs.leaf_spans();
collected_spans.push(ByteSpan::from(star_token.span()));
collected_spans.append(&mut rhs.leaf_spans());
collected_spans
}
Expr::Div {
lhs,
forward_slash_token,
rhs,
} => {
let mut collected_spans = lhs.leaf_spans();
collected_spans.push(ByteSpan::from(forward_slash_token.span()));
collected_spans.append(&mut rhs.leaf_spans());
collected_spans
}
Expr::Modulo {
lhs,
percent_token,
rhs,
} => {
let mut collected_spans = lhs.leaf_spans();
collected_spans.push(ByteSpan::from(percent_token.span()));
collected_spans.append(&mut rhs.leaf_spans());
collected_spans
}
Expr::Add {
lhs,
add_token,
rhs,
} => {
let mut collected_spans = lhs.leaf_spans();
collected_spans.push(ByteSpan::from(add_token.span()));
collected_spans.append(&mut rhs.leaf_spans());
collected_spans
}
Expr::Sub {
lhs,
sub_token,
rhs,
} => {
let mut collected_spans = lhs.leaf_spans();
collected_spans.push(ByteSpan::from(sub_token.span()));
collected_spans.append(&mut rhs.leaf_spans());
collected_spans
}
Expr::Shl {
lhs,
shl_token,
rhs,
} => {
let mut collected_spans = lhs.leaf_spans();
collected_spans.push(ByteSpan::from(shl_token.span()));
collected_spans.append(&mut rhs.leaf_spans());
collected_spans
}
Expr::Shr {
lhs,
shr_token,
rhs,
} => {
let mut collected_spans = lhs.leaf_spans();
collected_spans.push(ByteSpan::from(shr_token.span()));
collected_spans.append(&mut rhs.leaf_spans());
collected_spans
}
Expr::BitAnd {
lhs,
ampersand_token,
rhs,
} => {
let mut collected_spans = lhs.leaf_spans();
collected_spans.push(ByteSpan::from(ampersand_token.span()));
collected_spans.append(&mut rhs.leaf_spans());
collected_spans
}
Expr::BitXor {
lhs,
caret_token,
rhs,
} => {
let mut collected_spans = lhs.leaf_spans();
collected_spans.push(ByteSpan::from(caret_token.span()));
collected_spans.append(&mut rhs.leaf_spans());
collected_spans
}
Expr::BitOr {
lhs,
pipe_token,
rhs,
} => {
let mut collected_spans = lhs.leaf_spans();
collected_spans.push(ByteSpan::from(pipe_token.span()));
collected_spans.append(&mut rhs.leaf_spans());
collected_spans
}
Expr::Equal {
lhs,
double_eq_token,
rhs,
} => {
let mut collected_spans = lhs.leaf_spans();
collected_spans.push(ByteSpan::from(double_eq_token.span()));
collected_spans.append(&mut rhs.leaf_spans());
collected_spans
}
Expr::NotEqual {
lhs,
bang_eq_token,
rhs,
} => {
let mut collected_spans = lhs.leaf_spans();
collected_spans.push(ByteSpan::from(bang_eq_token.span()));
collected_spans.append(&mut rhs.leaf_spans());
collected_spans
}
Expr::LessThan {
lhs,
less_than_token,
rhs,
} => {
let mut collected_spans = lhs.leaf_spans();
collected_spans.push(ByteSpan::from(less_than_token.span()));
collected_spans.append(&mut rhs.leaf_spans());
collected_spans
}
Expr::GreaterThan {
lhs,
greater_than_token,
rhs,
} => {
let mut collected_spans = lhs.leaf_spans();
collected_spans.push(ByteSpan::from(greater_than_token.span()));
collected_spans.append(&mut rhs.leaf_spans());
collected_spans
}
Expr::LessThanEq {
lhs,
less_than_eq_token,
rhs,
} => {
let mut collected_spans = lhs.leaf_spans();
collected_spans.push(ByteSpan::from(less_than_eq_token.span()));
collected_spans.append(&mut rhs.leaf_spans());
collected_spans
}
Expr::GreaterThanEq {
lhs,
greater_than_eq_token,
rhs,
} => {
let mut collected_spans = lhs.leaf_spans();
collected_spans.push(ByteSpan::from(greater_than_eq_token.span()));
collected_spans.append(&mut rhs.leaf_spans());
collected_spans
}
Expr::LogicalAnd {
lhs,
double_ampersand_token,
rhs,
} => {
let mut collected_spans = lhs.leaf_spans();
collected_spans.push(ByteSpan::from(double_ampersand_token.span()));
collected_spans.append(&mut rhs.leaf_spans());
collected_spans
}
Expr::LogicalOr {
lhs,
double_pipe_token,
rhs,
} => {
let mut collected_spans = lhs.leaf_spans();
collected_spans.push(ByteSpan::from(double_pipe_token.span()));
collected_spans.append(&mut rhs.leaf_spans());
collected_spans
}
Expr::Reassignment {
assignable,
reassignment_op,
expr,
} => {
let mut collected_spans = assignable.leaf_spans();
collected_spans.push(ByteSpan::from(reassignment_op.span.clone()));
collected_spans.append(&mut expr.leaf_spans());
collected_spans
}
Expr::Break { break_token } => {
vec![ByteSpan::from(break_token.span())]
}
Expr::Continue { continue_token } => {
vec![ByteSpan::from(continue_token.span())]
}
}
}