diff --git a/sway-fmt-v2/src/fmt.rs b/sway-fmt-v2/src/fmt.rs index f40d2d70028..bbbb00c4bc1 100644 --- a/sway-fmt-v2/src/fmt.rs +++ b/sway-fmt-v2/src/fmt.rs @@ -606,7 +606,8 @@ fn hello_world(baz: /* this is a comment */ u64) { // This is a comment inside t abi StorageMapExample { // insert_into_map is blah blah #[storage(write)] // this is some other comment - fn insert_into_map(key: u64, value: u64); // this is the last comment inside the StorageMapExample + fn insert_into_map(key: u64, value: u64); + // this is the last comment inside the StorageMapExample }"#; let correct_sway_code = r#"contract; @@ -614,7 +615,8 @@ abi StorageMapExample { abi StorageMapExample { // insert_into_map is blah blah #[storage(write)] // this is some other comment - fn insert_into_map(key: u64, value: u64); // this is the last comment inside the StorageMapExample + fn insert_into_map(key: u64, value: u64); + // this is the last comment inside the StorageMapExample }"#; let mut formatter = Formatter::default(); let formatted_sway_code = @@ -680,4 +682,24 @@ trait Programmer { Formatter::format(&mut formatter, Arc::from(sway_code_to_format), None).unwrap(); assert_eq!(correct_sway_code, formatted_sway_code) } + + #[test] + fn test_where_comment() { + let sway_code_to_format = r#"contract; + +pub fn hello( person: String ) -> String where /* This is next to where */ T: Eq, /*Here is a comment*/{let greeting = 42;greeting.to_string()}"#; + let correct_sway_code = r#"contract; + +pub fn hello(person: String) -> String +where /* This is next to where */ + T: Eq, /*Here is a comment*/ +{ + let greeting = 42; + greeting.to_string() +}"#; + let mut formatter = Formatter::default(); + let formatted_sway_code = + Formatter::format(&mut formatter, Arc::from(sway_code_to_format), None).unwrap(); + assert_eq!(correct_sway_code, formatted_sway_code) + } } diff --git a/sway-fmt-v2/src/items/item_abi.rs b/sway-fmt-v2/src/items/item_abi.rs index c55ae82eca8..4e05925cd6f 100644 --- a/sway-fmt-v2/src/items/item_abi.rs +++ b/sway-fmt-v2/src/items/item_abi.rs @@ -2,7 +2,6 @@ use crate::{ config::items::ItemBraceStyle, fmt::{Format, FormattedCode, Formatter}, utils::{ - attribute::FormatDecl, bracket::CurlyBrace, comments::{ByteSpan, LeafSpans}, }, @@ -29,32 +28,14 @@ impl Format for ItemAbi { // abi_items let mut abi_items_iter = self.abi_items.get().iter().peekable(); - while let Some(item) = abi_items_iter.next() { - let attribute_list = item.0.attribute_list.clone(); - // add indent + format attribute if it exists - if !attribute_list.is_empty() { - write!( - formatted_code, - "{}", - &formatter.shape.indent.to_string(formatter), - )?; - for attr in attribute_list { - attr.format(formatted_code, formatter)?; - } - } + while let Some((fn_signature, semicolon)) = abi_items_iter.next() { // add indent + format item - write!( - formatted_code, - "{}", - &formatter.shape.indent.to_string(formatter), - )?; + fn_signature.format(formatted_code, formatter)?; writeln!( formatted_code, - "{}{}", - item.0.value.span().as_str(), // TODO(PR #2173): FnSignature formatting - item.1.span().as_str() // SemicolonToken + "{}", + semicolon.ident().as_str() // SemicolonToken )?; - if abi_items_iter.peek().is_some() { writeln!(formatted_code)?; } @@ -64,27 +45,8 @@ impl Format for ItemAbi { if let Some(abi_defs) = self.abi_defs_opt.clone() { let mut iter = abi_defs.get().iter().peekable(); while let Some(item) = iter.next() { - let attribute_list = item.attribute_list.clone(); - // add indent + format attribute if it exists - if !attribute_list.is_empty() { - write!( - formatted_code, - "{}", - &formatter.shape.indent.to_string(formatter), - )?; - for attr in attribute_list { - attr.format(formatted_code, formatter)?; - } - } - // add indent + format item - write!( - formatted_code, - "{}", - &formatter.shape.indent.to_string(formatter), - )?; - item.value.format(formatted_code, formatter)?; // TODO(PR #2173): ItemFn formatting - + item.format(formatted_code, formatter)?; if iter.peek().is_some() { writeln!(formatted_code)?; } diff --git a/sway-fmt-v2/src/items/item_const.rs b/sway-fmt-v2/src/items/item_const.rs index acc589c130c..ebf3ec6eaab 100644 --- a/sway-fmt-v2/src/items/item_const.rs +++ b/sway-fmt-v2/src/items/item_const.rs @@ -25,22 +25,17 @@ impl Format for ItemConst { write!(formatted_code, "{}", self.name.as_str())?; // Check if ty exists - if let Some(ty) = &self.ty_opt { + if let Some((colon_token, ty)) = &self.ty_opt { // Add colon - write!(formatted_code, "{} ", ty.0.span().as_str())?; - ty.1.format(formatted_code, formatter)?; + write!(formatted_code, "{} ", colon_token.ident().as_str())?; + ty.format(formatted_code, formatter)?; } // ` = ` write!(formatted_code, " {} ", self.eq_token.ident().as_str())?; - // TODO: We are not applying any custom formatting to expr, probably we will need to in the future. - write!( - formatted_code, - "{}{}", - self.expr.span().as_str(), - self.semicolon_token.ident().as_str() - )?; + self.expr.format(formatted_code, formatter)?; + write!(formatted_code, "{}", self.semicolon_token.ident().as_str())?; Ok(()) } @@ -56,7 +51,6 @@ impl LeafSpans for ItemConst { collected_spans.push(ByteSpan::from(self.name.span())); if let Some(ty) = &self.ty_opt { collected_spans.append(&mut ty.leaf_spans()); - // TODO: determine if we allow comments in between `:` and ty } collected_spans.push(ByteSpan::from(self.eq_token.span())); collected_spans.append(&mut self.expr.leaf_spans()); diff --git a/sway-fmt-v2/src/items/item_enum.rs b/sway-fmt-v2/src/items/item_enum.rs index d84a1dc06a8..1ee2a9f2d72 100644 --- a/sway-fmt-v2/src/items/item_enum.rs +++ b/sway-fmt-v2/src/items/item_enum.rs @@ -107,10 +107,9 @@ fn format_enum( }); let mut value_pairs_iter = value_pairs.iter().enumerate().peekable(); - for (var_index, variant) in value_pairs_iter.clone() { + for (var_index, (type_field, comma_token)) in value_pairs_iter.clone() { formatted_code.push_str(&formatter.shape.indent.to_string(formatter)); - let type_field = &variant.0; // Add name write!(formatted_code, "{}", type_field.name.as_str())?; let current_variant_length = variant_length[var_index]; @@ -133,7 +132,7 @@ fn format_enum( )?; type_field.ty.format(formatted_code, formatter)?; if value_pairs_iter.peek().is_some() { - writeln!(formatted_code, "{}", variant.1.span().as_str())?; + writeln!(formatted_code, "{}", comma_token.ident().as_str())?; } else if let Some(final_value) = &variants.final_value_opt { write!(formatted_code, "{}", final_value.span().as_str())?; } @@ -141,17 +140,17 @@ fn format_enum( } FieldAlignment::Off => { let mut value_pairs_iter = variants.value_separator_pairs.iter().peekable(); - for variant in value_pairs_iter.clone() { + for (type_field, comma_token) in value_pairs_iter.clone() { write!( formatted_code, "{}", &formatter.shape.indent.to_string(formatter) )?; // TypeField - variant.0.format(formatted_code, formatter)?; + type_field.format(formatted_code, formatter)?; if value_pairs_iter.peek().is_some() { - writeln!(formatted_code, "{}", variant.1.span().as_str())?; + writeln!(formatted_code, "{}", comma_token.ident().as_str())?; } } if let Some(final_value) = &variants.final_value_opt { @@ -169,11 +168,11 @@ fn format_enum( // non-multiline formatting write!(formatted_code, " ")?; let mut value_pairs_iter = variants.value_separator_pairs.iter().peekable(); - for variant in value_pairs_iter.clone() { - variant.0.format(formatted_code, formatter)?; + for (ty, comma_token) in value_pairs_iter.clone() { + ty.format(formatted_code, formatter)?; if value_pairs_iter.peek().is_some() { - write!(formatted_code, "{} ", variant.1.span().as_str())?; + write!(formatted_code, "{} ", comma_token.ident().as_str())?; } } if let Some(final_value) = &variants.final_value_opt { diff --git a/sway-fmt-v2/src/items/item_fn.rs b/sway-fmt-v2/src/items/item_fn.rs index e7682ca6461..5fa9b373829 100644 --- a/sway-fmt-v2/src/items/item_fn.rs +++ b/sway-fmt-v2/src/items/item_fn.rs @@ -119,24 +119,24 @@ impl Format for FnSignature { // `self` formatted_code.push_str(self_token.span().as_str()); // `args_opt` - if let Some(args) = args_opt { + if let Some((comma, args)) = args_opt { // `, ` - write!(formatted_code, "{} ", args.0.span().as_str())?; + write!(formatted_code, "{} ", comma.ident().as_str())?; // `Punctuated` - args.1.format(formatted_code, formatter)?; + args.format(formatted_code, formatter)?; } } } // `)` Self::close_parenthesis(formatted_code, formatter)?; // `return_type_opt` - if let Some(return_type) = &self.return_type_opt { + if let Some((right_arrow, ty)) = &self.return_type_opt { write!( formatted_code, " {} ", - return_type.0.span().as_str() // `->` + right_arrow.ident().as_str() // `->` )?; - return_type.1.format(formatted_code, formatter)?; // `Ty` + ty.format(formatted_code, formatter)?; // `Ty` } // `WhereClause` if let Some(where_clause) = &self.where_clause_opt { @@ -244,7 +244,9 @@ impl LeafSpans for FnSignature { if let Some(return_type) = &self.return_type_opt { collected_spans.append(&mut return_type.leaf_spans()); } - // TODO add where, I will add where for all items at once. + if let Some(where_clause) = &self.where_clause_opt { + collected_spans.append(&mut where_clause.leaf_spans()); + } collected_spans } } diff --git a/sway-fmt-v2/src/items/item_impl.rs b/sway-fmt-v2/src/items/item_impl.rs index 07b85c6b590..f1d89770816 100644 --- a/sway-fmt-v2/src/items/item_impl.rs +++ b/sway-fmt-v2/src/items/item_impl.rs @@ -25,7 +25,9 @@ impl LeafSpans for ItemImpl { collected_spans.append(&mut trait_tuple.leaf_spans()); } collected_spans.append(&mut self.ty.leaf_spans()); - // TODO add where + if let Some(where_clause) = &self.where_clause_opt { + collected_spans.append(&mut where_clause.leaf_spans()); + } collected_spans.append(&mut self.contents.leaf_spans()); collected_spans } diff --git a/sway-fmt-v2/src/items/item_storage.rs b/sway-fmt-v2/src/items/item_storage.rs index 9d4189ffd5c..fa04363fcd7 100644 --- a/sway-fmt-v2/src/items/item_storage.rs +++ b/sway-fmt-v2/src/items/item_storage.rs @@ -87,14 +87,13 @@ fn format_storage( }); let mut value_pairs_iter = value_pairs.iter().enumerate().peekable(); - for (field_index, field) in value_pairs_iter.clone() { + for (field_index, (storage_field, comma_token)) in value_pairs_iter.clone() { write!( formatted_code, "{}", &formatter.shape.indent.to_string(formatter) )?; - let storage_field = &field.0; // Add name write!(formatted_code, "{}", storage_field.name.as_str())?; @@ -124,7 +123,7 @@ fn format_storage( .initializer .format(formatted_code, formatter)?; if value_pairs_iter.peek().is_some() { - writeln!(formatted_code, "{}", field.1.span().as_str())?; + writeln!(formatted_code, "{}", comma_token.ident().as_str())?; } else if let Some(final_value) = &fields.final_value_opt { final_value.format(formatted_code, formatter)?; } @@ -132,17 +131,17 @@ fn format_storage( } FieldAlignment::Off => { let mut value_pairs_iter = fields.value_separator_pairs.iter().peekable(); - for field in value_pairs_iter.clone() { + for (storage_field, comma_token) in value_pairs_iter.clone() { write!( formatted_code, "{}", &formatter.shape.indent.to_string(formatter) )?; // storage_field - field.0.format(formatted_code, formatter)?; + storage_field.format(formatted_code, formatter)?; if value_pairs_iter.peek().is_some() { - writeln!(formatted_code, "{}", field.1.span().as_str())?; + writeln!(formatted_code, "{}", comma_token.ident().as_str())?; } } if let Some(final_value) = &fields.final_value_opt { @@ -160,19 +159,25 @@ fn format_storage( // non-multiline formatting write!(formatted_code, " ")?; let mut value_pairs_iter = fields.value_separator_pairs.iter().peekable(); - for field in value_pairs_iter.clone() { + for (storage_field, comma_token) in value_pairs_iter.clone() { // storage_field write!( formatted_code, "{}{} ", - field.0.name.span().as_str(), - field.0.colon_token.span().as_str(), + storage_field.name.span().as_str(), + storage_field.colon_token.span().as_str(), )?; - field.0.ty.format(formatted_code, formatter)?; - write!(formatted_code, " {} ", field.0.eq_token.ident().as_str())?; - field.0.initializer.format(formatted_code, formatter)?; + storage_field.ty.format(formatted_code, formatter)?; + write!( + formatted_code, + " {} ", + storage_field.eq_token.ident().as_str() + )?; + storage_field + .initializer + .format(formatted_code, formatter)?; if value_pairs_iter.peek().is_some() { - write!(formatted_code, "{} ", field.1.span().as_str())?; + write!(formatted_code, "{} ", comma_token.span().as_str())?; } } if let Some(final_value) = &fields.final_value_opt { diff --git a/sway-fmt-v2/src/items/item_struct.rs b/sway-fmt-v2/src/items/item_struct.rs index c714fa2a37b..29bf8fef89d 100644 --- a/sway-fmt-v2/src/items/item_struct.rs +++ b/sway-fmt-v2/src/items/item_struct.rs @@ -108,14 +108,13 @@ fn format_struct( }); let mut value_pairs_iter = value_pairs.iter().enumerate().peekable(); - for (field_index, field) in value_pairs_iter.clone() { + for (field_index, (type_field, comma_token)) in value_pairs_iter.clone() { write!( formatted_code, "{}", &formatter.shape.indent.to_string(formatter) )?; - let type_field = &field.0; // Add name write!(formatted_code, "{}", type_field.name.as_str())?; @@ -137,7 +136,7 @@ fn format_struct( )?; type_field.ty.format(formatted_code, formatter)?; if value_pairs_iter.peek().is_some() { - writeln!(formatted_code, "{}", field.1.span().as_str())?; + writeln!(formatted_code, "{}", comma_token.ident().as_str())?; } else if let Some(final_value) = &fields.final_value_opt { write!(formatted_code, "{}", final_value.span().as_str())?; } @@ -145,17 +144,17 @@ fn format_struct( } FieldAlignment::Off => { let mut value_pairs_iter = fields.value_separator_pairs.iter().peekable(); - for field in value_pairs_iter.clone() { + for (type_field, comma_token) in value_pairs_iter.clone() { write!( formatted_code, "{}", &formatter.shape.indent.to_string(formatter) )?; // TypeField - field.0.format(formatted_code, formatter)?; + type_field.format(formatted_code, formatter)?; if value_pairs_iter.peek().is_some() { - writeln!(formatted_code, "{}", field.1.span().as_str())?; + writeln!(formatted_code, "{}", comma_token.ident().as_str())?; } } if let Some(final_value) = &fields.final_value_opt { diff --git a/sway-fmt-v2/src/items/item_trait.rs b/sway-fmt-v2/src/items/item_trait.rs index 1bdc05b5392..5ec1366eaab 100644 --- a/sway-fmt-v2/src/items/item_trait.rs +++ b/sway-fmt-v2/src/items/item_trait.rs @@ -28,31 +28,21 @@ impl Format for ItemTrait { self.name.span().as_str() )?; // `: super_trait + super_trait` - if let Some(super_traits) = &self.super_traits { - write!(formatted_code, "{} ", super_traits.0.span().as_str())?; - super_traits.1.format(formatted_code, formatter)?; + if let Some((colon_token, traits)) = &self.super_traits { + write!(formatted_code, "{} ", colon_token.ident().as_str())?; + traits.format(formatted_code, formatter)?; } write!(formatted_code, " ")?; Self::open_curly_brace(formatted_code, formatter)?; - for trait_items in self.trait_items.clone().into_inner() { - write!( - formatted_code, - "{}", - formatter.shape.indent.to_string(formatter) - )?; + for (fn_signature, semicolon_token) in self.trait_items.clone().into_inner() { // format `Annotated` - trait_items.0.format(formatted_code, formatter)?; - writeln!(formatted_code, "{}\n", trait_items.1.span().as_str())?; + fn_signature.format(formatted_code, formatter)?; + writeln!(formatted_code, "{}\n", semicolon_token.ident().as_str())?; } formatted_code.pop(); // pop last ending newline if let Some(trait_defs) = &self.trait_defs_opt { Self::open_curly_brace(formatted_code, formatter)?; for trait_items in trait_defs.clone().into_inner() { - write!( - formatted_code, - "{}", - formatter.shape.indent.to_string(formatter) - )?; // format `Annotated` trait_items.format(formatted_code, formatter)?; } diff --git a/sway-fmt-v2/src/utils/attribute.rs b/sway-fmt-v2/src/utils/attribute.rs index eb70567a008..6da25c3e06c 100644 --- a/sway-fmt-v2/src/utils/attribute.rs +++ b/sway-fmt-v2/src/utils/attribute.rs @@ -23,8 +23,18 @@ impl Format for Annotated { ) -> Result<(), FormatterError> { // format each `Attribute` for attr in &self.attribute_list { + write!( + formatted_code, + "{}", + &formatter.shape.indent.to_string(formatter), + )?; attr.format(formatted_code, formatter)?; } + write!( + formatted_code, + "{}", + &formatter.shape.indent.to_string(formatter), + )?; // format `ItemKind` self.value.format(formatted_code, formatter) } diff --git a/sway-fmt-v2/src/utils/expr.rs b/sway-fmt-v2/src/utils/expr.rs index 7220c91cb6f..0b63fec04e0 100644 --- a/sway-fmt-v2/src/utils/expr.rs +++ b/sway-fmt-v2/src/utils/expr.rs @@ -32,12 +32,12 @@ impl Format for Expr { writeln!(formatted_code)?; let fields = fields.clone().into_inner(); let mut value_pairs_iter = fields.value_separator_pairs.iter().peekable(); - for field in value_pairs_iter.clone() { + for (expr_struct_field, comma_token) in value_pairs_iter.clone() { // TypeField - field.0.format(formatted_code, formatter)?; + expr_struct_field.format(formatted_code, formatter)?; if value_pairs_iter.peek().is_some() { - writeln!(formatted_code, "{}", field.1.span().as_str())?; + writeln!(formatted_code, "{}", comma_token.ident().as_str())?; } } if let Some(final_value) = &fields.final_value_opt { @@ -208,9 +208,9 @@ impl Format for ExprStructField { formatter.shape.indent.to_string(formatter), self.field_name.span().as_str() )?; - if let Some(expr) = &self.expr_opt { - write!(formatted_code, "{} ", expr.0.span().as_str())?; - expr.1.format(formatted_code, formatter)?; + if let Some((colon_token, expr)) = &self.expr_opt { + write!(formatted_code, "{} ", colon_token.ident().as_str())?; + expr.format(formatted_code, formatter)?; } Ok(()) @@ -596,7 +596,6 @@ impl LeafSpans for ExprStructField { let mut collected_spans = vec![ByteSpan::from(self.field_name.span())]; if let Some(expr) = &self.expr_opt { collected_spans.push(ByteSpan::from(expr.0.span())); - // TODO: determine if we are allowing comments between `:` and expr collected_spans.append(&mut expr.1.leaf_spans()); } collected_spans @@ -651,7 +650,6 @@ impl LeafSpans for AsmRegisterDeclaration { let mut collected_spans = vec![ByteSpan::from(self.register.span())]; if let Some(value) = &self.value_opt { collected_spans.append(&mut value.leaf_spans()); - // TODO: determine if we are allowing comments between `:` and expr } collected_spans } @@ -662,7 +660,6 @@ impl LeafSpans for AsmBlockContents { let mut collected_spans = Vec::new(); for instruction in &self.instructions { collected_spans.append(&mut instruction.leaf_spans()); - // TODO: probably we shouldn't allow for comments in between the instruction and comma since it may/will result in build failure after formatting } collected_spans } @@ -680,7 +677,6 @@ impl LeafSpans for AsmFinalExpr { let mut collected_spans = vec![ByteSpan::from(self.register.span())]; if let Some(ty) = &self.ty_opt { collected_spans.append(&mut ty.leaf_spans()); - // TODO: determine if we are allowing comments between `:` and ty } collected_spans } @@ -742,14 +738,12 @@ impl LeafSpans for MatchBranchKind { comma_token_opt, } => { collected_spans.append(&mut block.leaf_spans()); - // TODO: determine if we allow comments between block and comma_token if let Some(comma_token) = comma_token_opt { collected_spans.push(ByteSpan::from(comma_token.span())); } } MatchBranchKind::Expr { expr, comma_token } => { collected_spans.append(&mut expr.leaf_spans()); - // TODO: determine if we allow comments between expr and comma_token collected_spans.push(ByteSpan::from(comma_token.span())); } }; diff --git a/sway-fmt-v2/src/utils/path.rs b/sway-fmt-v2/src/utils/path.rs index 5d4ff00a3bf..c4aae285d0f 100644 --- a/sway-fmt-v2/src/utils/path.rs +++ b/sway-fmt-v2/src/utils/path.rs @@ -12,8 +12,8 @@ impl Format for PathExpr { formatted_code: &mut FormattedCode, formatter: &mut Formatter, ) -> Result<(), FormatterError> { - if let Some(root_opt) = &self.root_opt { - if let Some(root) = &root_opt.0 { + if let Some((root, double_colon_token)) = &self.root_opt { + if let Some(root) = &root { write!( formatted_code, "{}", @@ -28,7 +28,7 @@ impl Format for PathExpr { root.close_angle_bracket_token.span().as_str() )?; } - write!(formatted_code, "{}", root_opt.1.span().as_str())?; + write!(formatted_code, "{}", double_colon_token.ident().as_str())?; } self.prefix.format(formatted_code, formatter)?; for suffix in self.suffix.iter() { diff --git a/sway-fmt-v2/src/utils/statement.rs b/sway-fmt-v2/src/utils/statement.rs index 32411492d42..d0b626300d3 100644 --- a/sway-fmt-v2/src/utils/statement.rs +++ b/sway-fmt-v2/src/utils/statement.rs @@ -88,7 +88,6 @@ impl LeafSpans for StatementLet { // Add ty's ByteSpan if it exists if let Some(ty) = &self.ty_opt { collected_spans.push(ByteSpan::from(ty.0.span())); - // TODO: determine if we are allowing comments between `:` and ty collected_spans.append(&mut ty.1.leaf_spans()); } // Add eq token's ByteSpan diff --git a/sway-fmt-v2/src/utils/ty.rs b/sway-fmt-v2/src/utils/ty.rs index 8c0959960d5..bcfea9adf8a 100644 --- a/sway-fmt-v2/src/utils/ty.rs +++ b/sway-fmt-v2/src/utils/ty.rs @@ -61,13 +61,8 @@ impl Format for TyArrayDescriptor { formatter: &mut Formatter, ) -> Result<(), FormatterError> { self.ty.format(formatted_code, formatter)?; - // TODO: once expr formatting is completly implemented switch this to use the actual formatting rather than the raw str coming from span - write!( - formatted_code, - "{} {}", - self.semicolon_token.span().as_str(), - self.length.span().as_str() - )?; + write!(formatted_code, "{} ", self.semicolon_token.span().as_str())?; + self.length.format(formatted_code, formatter)?; Ok(()) } } diff --git a/sway-fmt-v2/src/utils/where_clause.rs b/sway-fmt-v2/src/utils/where_clause.rs index ec85a56f72f..0f1d408bc39 100644 --- a/sway-fmt-v2/src/utils/where_clause.rs +++ b/sway-fmt-v2/src/utils/where_clause.rs @@ -3,6 +3,8 @@ use std::fmt::Write; use sway_parse::{WhereBound, WhereClause}; use sway_types::Spanned; +use super::comments::{ByteSpan, LeafSpans}; + impl Format for WhereClause { fn format( &self, @@ -49,12 +51,29 @@ impl Format for WhereBound { ) -> Result<(), FormatterError> { write!( formatted_code, - "{}{}{} {}", + "{}{}{} ", &formatter.shape.indent.to_string(formatter), // `Indent` self.ty_name.span().as_str(), // `Ident` self.colon_token.span().as_str(), // `ColonToken` - self.bounds.span().as_str() // TODO: `Traits` )?; + self.bounds.format(formatted_code, formatter)?; Ok(()) } } + +impl LeafSpans for WhereBound { + fn leaf_spans(&self) -> Vec { + let mut collected_spans = self.ty_name.leaf_spans(); + collected_spans.append(&mut self.colon_token.leaf_spans()); + collected_spans.append(&mut self.bounds.leaf_spans()); + collected_spans + } +} + +impl LeafSpans for WhereClause { + fn leaf_spans(&self) -> Vec { + let mut collected_spans = vec![ByteSpan::from(self.where_token.span())]; + collected_spans.append(&mut self.bounds.leaf_spans()); + collected_spans + } +}