From 35dfcc007868e3fe1118c677efc1594bfce9c575 Mon Sep 17 00:00:00 2001 From: Connor Brewster Date: Fri, 11 Mar 2016 14:18:30 -0700 Subject: [PATCH 01/11] Adding trait formatting trait header formatting finished generic formatting finished added basic trait bounds formatting --- src/items.rs | 68 ++++++++++++++++++++++++++++++++++++++++++- src/missed_spans.rs | 8 ++--- src/visitor.rs | 10 +++++-- tests/source/trait.rs | 2 ++ tests/target/trait.rs | 2 ++ 5 files changed, 83 insertions(+), 7 deletions(-) diff --git a/src/items.rs b/src/items.rs index d9c21c339cbc..5586ad165649 100644 --- a/src/items.rs +++ b/src/items.rs @@ -22,7 +22,7 @@ use rewrite::{Rewrite, RewriteContext}; use config::{Config, BlockIndentStyle, Density, ReturnIndent, BraceStyle, StructLitStyle}; -use syntax::{ast, abi}; +use syntax::{ast, abi, ptr}; use syntax::codemap::{Span, BytePos, mk_sp}; use syntax::parse::token; @@ -572,6 +572,50 @@ pub fn format_struct(context: &RewriteContext, } } +pub fn format_trait(context: &RewriteContext, item: &ast::Item, offset: Indent) -> Option { + if let ast::Item_::ItemTrait(unsafety, ref generics, ref type_param_bounds, ref trait_items) = + item.node { + let mut result = String::new(); + let header = format!("{}{}trait {}", + format_visibility(item.vis), + format_unsafety(unsafety), + item.ident); + + result.push_str(&header); + + // TODO: Add max_width checking + // let budget = try_opt!(context.config.max_width.checked_sub(result.len())); + // let indent = offset + result.len(); + + let body_lo = span_after(item.span, "{", context.codemap); + + let generics_str = try_opt!(rewrite_generics(context, + generics, + offset, + context.config.max_width, + offset + result.len(), + mk_sp(item.span.lo, body_lo))); + result.push_str(&generics_str); + + let trait_bound_str = try_opt!(rewrite_trait_bounds(context, + type_param_bounds, + offset, + 0)); + + result.push_str(&trait_bound_str); + + if trait_items.len() > 0 { + result.push_str(" {"); + } else { + result.push_str(" {}"); + } + + Some(result) + } else { + unreachable!(); + } +} + fn format_unit_struct(item_name: &str, ident: ast::Ident, vis: ast::Visibility) -> Option { let mut result = String::with_capacity(1024); @@ -1437,6 +1481,28 @@ fn rewrite_generics(context: &RewriteContext, Some(format!("<{}>", list_str)) } +fn rewrite_trait_bounds(context: &RewriteContext, + param_bounds: &ast::TyParamBounds, + indent: Indent, + width: usize) + -> Option { + let bounds: &[_] = ¶m_bounds.as_slice(); + + if bounds.is_empty() { + return Some(String::new()); + } + + let bound_str = bounds.iter() + .filter_map(|ty_bound| ty_bound.rewrite(&context, 100, indent)) + .collect::>() + .join(" + "); + + let mut result = String::new(); + result.push_str(" : "); + result.push_str(&bound_str); + Some(result) +} + fn rewrite_where_clause(context: &RewriteContext, where_clause: &ast::WhereClause, config: &Config, diff --git a/src/missed_spans.rs b/src/missed_spans.rs index 67661143ddf2..8e4c22814424 100644 --- a/src/missed_spans.rs +++ b/src/missed_spans.rs @@ -47,10 +47,10 @@ fn format_missing_inner(&mut self, return; } - assert!(start < end, - "Request to format inverted span: {:?} to {:?}", - self.codemap.lookup_char_pos(start), - self.codemap.lookup_char_pos(end)); + // assert!(start < end, + // "Request to format inverted span: {:?} to {:?}", + // self.codemap.lookup_char_pos(start), + // self.codemap.lookup_char_pos(end)); self.last_pos = end; let span = codemap::mk_sp(start, end); diff --git a/src/visitor.rs b/src/visitor.rs index f0efde9de642..3a8bb0bae8f3 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -21,7 +21,7 @@ use rewrite::{Rewrite, RewriteContext}; use comment::rewrite_comment; use macros::rewrite_macro; -use items::{rewrite_static, rewrite_type_alias, format_impl}; +use items::{rewrite_static, rewrite_type_alias, format_impl, format_trait}; pub struct FmtVisitor<'a> { pub parse_session: &'a ParseSess, @@ -209,8 +209,14 @@ fn visit_item(&mut self, item: &ast::Item) { } } // FIXME(#78): format traits. - ast::Item_::ItemTrait(_, _, _, ref trait_items) => { + ast::Item_::ItemTrait(unsafety, ref generics, ref param_bounds, ref trait_items) => { self.format_missing_with_indent(item.span.lo); + if let Some(trait_str) = format_trait(&self.get_context(), + item, + self.block_indent) { + self.buffer.push_str(&trait_str); + self.last_pos = item.span.hi; + } self.block_indent = self.block_indent.block_indent(self.config); for item in trait_items { self.visit_trait_item(&item); diff --git a/tests/source/trait.rs b/tests/source/trait.rs index 5e7a0c78ba70..49b314358f2e 100644 --- a/tests/source/trait.rs +++ b/tests/source/trait.rs @@ -35,3 +35,5 @@ trait TraitWithExpr { trait Test { fn read_struct(&mut self, s_name: &str, len: usize, f: F) -> Result where F: FnOnce(&mut Self) -> Result; } + +trait T<> {} diff --git a/tests/target/trait.rs b/tests/target/trait.rs index 241f5d05b7c8..32389431284a 100644 --- a/tests/target/trait.rs +++ b/tests/target/trait.rs @@ -34,3 +34,5 @@ trait Test { fn read_struct(&mut self, s_name: &str, len: usize, f: F) -> Result where F: FnOnce(&mut Self) -> Result; } + +trait T {} From 9e583ce7a7bda498ed256216a040b8c660eb15b4 Mon Sep 17 00:00:00 2001 From: Connor Brewster Date: Fri, 11 Mar 2016 14:49:11 -0700 Subject: [PATCH 02/11] Added where clause formatting --- src/items.rs | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/src/items.rs b/src/items.rs index 5586ad165649..85e25c0b95af 100644 --- a/src/items.rs +++ b/src/items.rs @@ -604,6 +604,25 @@ pub fn format_trait(context: &RewriteContext, item: &ast::Item, offset: Indent) result.push_str(&trait_bound_str); + let where_budget = try_opt!(context.config.max_width.checked_sub(last_line_width(&result))); + let where_clause_str = try_opt!(rewrite_where_clause(context, + &generics.where_clause, + context.config, + context.config.item_brace_style, + context.block_indent, + where_budget, + context.config.where_density, + "{", + None)); + if !where_clause_str.contains('\n') && + result.len() + where_clause_str.len() + offset.width() > context.config.max_width { + result.push('\n'); + let width = context.block_indent.width() + context.config.tab_spaces - 1; + let where_indent = Indent::new(0, width); + result.push_str(&where_indent.to_string(context.config)); + } + result.push_str(&where_clause_str); + if trait_items.len() > 0 { result.push_str(" {"); } else { From d24c31f74ca9f7c51576ce7151c99de0e2ffcb0a Mon Sep 17 00:00:00 2001 From: Connor Brewster Date: Fri, 11 Mar 2016 22:32:08 -0700 Subject: [PATCH 03/11] Added support for associated type rewriting --- src/items.rs | 60 ++++++++++++++++++++++++++++++++++++++++++-------- src/visitor.rs | 30 ++++++++++++++++++------- 2 files changed, 73 insertions(+), 17 deletions(-) diff --git a/src/items.rs b/src/items.rs index 85e25c0b95af..38ae285197e5 100644 --- a/src/items.rs +++ b/src/items.rs @@ -22,7 +22,7 @@ use rewrite::{Rewrite, RewriteContext}; use config::{Config, BlockIndentStyle, Density, ReturnIndent, BraceStyle, StructLitStyle}; -use syntax::{ast, abi, ptr}; +use syntax::{ast, abi}; use syntax::codemap::{Span, BytePos, mk_sp}; use syntax::parse::token; @@ -600,8 +600,14 @@ pub fn format_trait(context: &RewriteContext, item: &ast::Item, offset: Indent) let trait_bound_str = try_opt!(rewrite_trait_bounds(context, type_param_bounds, offset, - 0)); + context.config.max_width)); + if offset.width() + result.len() + trait_bound_str.len() > context.config.max_width { + result.push('\n'); + let width = context.block_indent.width() + context.config.tab_spaces - 1; + let trait_indent = Indent::new(0, width); + result.push_str(&trait_indent.to_string(context.config)); + } result.push_str(&trait_bound_str); let where_budget = try_opt!(context.config.max_width.checked_sub(last_line_width(&result))); @@ -623,12 +629,48 @@ pub fn format_trait(context: &RewriteContext, item: &ast::Item, offset: Indent) } result.push_str(&where_clause_str); - if trait_items.len() > 0 { - result.push_str(" {"); - } else { - result.push_str(" {}"); + match context.config.item_brace_style { + BraceStyle::AlwaysNextLine => { + result.push('\n'); + result.push_str(&offset.to_string(context.config)); + }, + BraceStyle::PreferSameLine => result.push(' '), + BraceStyle::SameLineWhere => { + if !where_clause_str.is_empty() { + result.push('\n'); + result.push_str(&offset.to_string(context.config)); + } else { + result.push(' '); + } + } + } + result.push('{'); + + let snippet = context.snippet(item.span); + let open_pos = try_opt!(snippet.find_uncommented("{")) + 1; + + if !trait_items.is_empty() || contains_comment(&snippet[open_pos..]) { + let mut visitor = FmtVisitor::from_codemap(context.parse_session, context.config, None); + visitor.block_indent = context.block_indent.block_indent(context.config); + visitor.last_pos = item.span.lo + BytePos(open_pos as u32); + + for item in trait_items { + visitor.visit_trait_item(&item); + } + + visitor.format_missing(item.span.hi - BytePos(1)); + + let inner_indent_str = visitor.block_indent.to_string(context.config); + let outer_indent_str = context.block_indent.to_string(context.config); + + result.push('\n'); + result.push_str(&inner_indent_str); + result.push_str(&trim_newlines(&visitor.buffer.to_string().trim())); + result.push('\n'); + result.push_str(&outer_indent_str); } + result.push('}'); Some(result) } else { unreachable!(); @@ -1501,18 +1543,18 @@ fn rewrite_generics(context: &RewriteContext, } fn rewrite_trait_bounds(context: &RewriteContext, - param_bounds: &ast::TyParamBounds, + type_param_bounds: &ast::TyParamBounds, indent: Indent, width: usize) -> Option { - let bounds: &[_] = ¶m_bounds.as_slice(); + let bounds: &[_] = &type_param_bounds.as_slice(); if bounds.is_empty() { return Some(String::new()); } let bound_str = bounds.iter() - .filter_map(|ty_bound| ty_bound.rewrite(&context, 100, indent)) + .filter_map(|ty_bound| ty_bound.rewrite(&context, width, indent)) .collect::>() .join(" + "); diff --git a/src/visitor.rs b/src/visitor.rs index 3a8bb0bae8f3..22f9807b8c55 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -217,11 +217,11 @@ fn visit_item(&mut self, item: &ast::Item) { self.buffer.push_str(&trait_str); self.last_pos = item.span.hi; } - self.block_indent = self.block_indent.block_indent(self.config); - for item in trait_items { - self.visit_trait_item(&item); - } - self.block_indent = self.block_indent.block_unindent(self.config); + // self.block_indent = self.block_indent.block_indent(self.config); + // for item in trait_items { + // self.visit_trait_item(&item); + // } + // self.block_indent = self.block_indent.block_unindent(self.config); } ast::Item_::ItemExternCrate(_) => { self.format_missing_with_indent(item.span.lo); @@ -319,7 +319,7 @@ fn visit_item(&mut self, item: &ast::Item) { } } - fn visit_trait_item(&mut self, ti: &ast::TraitItem) { + pub fn visit_trait_item(&mut self, ti: &ast::TraitItem) { if self.visit_attrs(&ti.attrs) { return; } @@ -340,8 +340,22 @@ fn visit_trait_item(&mut self, ti: &ast::TraitItem) { ti.span, ti.id); } - ast::TypeTraitItem(..) => { - // FIXME: Implement + ast::TypeTraitItem(ref type_param_bounds, _) => { + let indent = self.block_indent; + let mut result = String::new(); + result.push_str(&format!("type {}", ti.ident)); + + let bounds: &[_] = &type_param_bounds.as_slice(); + let bound_str = bounds.iter() + .filter_map(|ty_bound| ty_bound.rewrite(&self.get_context(), self.config.max_width, indent)) + .collect::>() + .join(" + "); + if bounds.len() > 0 { + result.push_str(&format!(": {}", bound_str)); + } + + result.push(';'); + self.push_rewrite(ti.span, Some(result)); } } } From 34651c4f78d811e01a87d6705c85c978d2ed452d Mon Sep 17 00:00:00 2001 From: Connor Brewster Date: Fri, 11 Mar 2016 22:41:22 -0700 Subject: [PATCH 04/11] Fixed formatting --- src/items.rs | 16 ++++++++-------- src/visitor.rs | 10 +++++++--- 2 files changed, 15 insertions(+), 11 deletions(-) diff --git a/src/items.rs b/src/items.rs index 38ae285197e5..145c5ee1756f 100644 --- a/src/items.rs +++ b/src/items.rs @@ -633,7 +633,7 @@ pub fn format_trait(context: &RewriteContext, item: &ast::Item, offset: Indent) BraceStyle::AlwaysNextLine => { result.push('\n'); result.push_str(&offset.to_string(context.config)); - }, + } BraceStyle::PreferSameLine => result.push(' '), BraceStyle::SameLineWhere => { if !where_clause_str.is_empty() { @@ -1543,10 +1543,10 @@ fn rewrite_generics(context: &RewriteContext, } fn rewrite_trait_bounds(context: &RewriteContext, - type_param_bounds: &ast::TyParamBounds, - indent: Indent, - width: usize) - -> Option { + type_param_bounds: &ast::TyParamBounds, + indent: Indent, + width: usize) + -> Option { let bounds: &[_] = &type_param_bounds.as_slice(); if bounds.is_empty() { @@ -1554,9 +1554,9 @@ fn rewrite_trait_bounds(context: &RewriteContext, } let bound_str = bounds.iter() - .filter_map(|ty_bound| ty_bound.rewrite(&context, width, indent)) - .collect::>() - .join(" + "); + .filter_map(|ty_bound| ty_bound.rewrite(&context, width, indent)) + .collect::>() + .join(" + "); let mut result = String::new(); result.push_str(" : "); diff --git a/src/visitor.rs b/src/visitor.rs index 22f9807b8c55..31e5fb9a27ae 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -347,9 +347,13 @@ pub fn visit_trait_item(&mut self, ti: &ast::TraitItem) { let bounds: &[_] = &type_param_bounds.as_slice(); let bound_str = bounds.iter() - .filter_map(|ty_bound| ty_bound.rewrite(&self.get_context(), self.config.max_width, indent)) - .collect::>() - .join(" + "); + .filter_map(|ty_bound| { + ty_bound.rewrite(&self.get_context(), + self.config.max_width, + indent) + }) + .collect::>() + .join(" + "); if bounds.len() > 0 { result.push_str(&format!(": {}", bound_str)); } From de95b4cefb5acb9bad4048551575b2b3a33d437b Mon Sep 17 00:00:00 2001 From: Connor Brewster Date: Fri, 11 Mar 2016 22:50:30 -0700 Subject: [PATCH 05/11] Removed unneeded pattern matching --- src/visitor.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/visitor.rs b/src/visitor.rs index 31e5fb9a27ae..2eb4afa22fba 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -209,7 +209,7 @@ fn visit_item(&mut self, item: &ast::Item) { } } // FIXME(#78): format traits. - ast::Item_::ItemTrait(unsafety, ref generics, ref param_bounds, ref trait_items) => { + ast::Item_::ItemTrait(..) => { self.format_missing_with_indent(item.span.lo); if let Some(trait_str) = format_trait(&self.get_context(), item, From 87a5d88aeb0cda9fcd82c8e24080ed85c85a465f Mon Sep 17 00:00:00 2001 From: Connor Brewster Date: Sat, 12 Mar 2016 10:53:47 -0700 Subject: [PATCH 06/11] Uncommented missed spans check --- src/missed_spans.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/missed_spans.rs b/src/missed_spans.rs index 8e4c22814424..67661143ddf2 100644 --- a/src/missed_spans.rs +++ b/src/missed_spans.rs @@ -47,10 +47,10 @@ fn format_missing_inner(&mut self, return; } - // assert!(start < end, - // "Request to format inverted span: {:?} to {:?}", - // self.codemap.lookup_char_pos(start), - // self.codemap.lookup_char_pos(end)); + assert!(start < end, + "Request to format inverted span: {:?} to {:?}", + self.codemap.lookup_char_pos(start), + self.codemap.lookup_char_pos(end)); self.last_pos = end; let span = codemap::mk_sp(start, end); From 7ba43ff06edfd4c3d578d9c4ff2a11885275cae1 Mon Sep 17 00:00:00 2001 From: Connor Brewster Date: Mon, 14 Mar 2016 19:52:07 -0600 Subject: [PATCH 07/11] Finished implementing impl and trait type/const --- src/items.rs | 74 ++++++++++++++++++++++++++++++++++++++++++++++++-- src/visitor.rs | 66 ++++++++++++++++++++++---------------------- 2 files changed, 106 insertions(+), 34 deletions(-) diff --git a/src/items.rs b/src/items.rs index 550a66132417..ccf99c5dae72 100644 --- a/src/items.rs +++ b/src/items.rs @@ -23,7 +23,7 @@ use config::{Config, BlockIndentStyle, Density, ReturnIndent, BraceStyle, StructLitStyle}; use syntax::codemap; -use syntax::{ast, abi}; +use syntax::{ast, abi, ptr}; use syntax::codemap::{Span, BytePos, mk_sp}; use syntax::parse::token; use syntax::ast::ImplItem; @@ -640,7 +640,7 @@ pub fn format_trait(context: &RewriteContext, item: &ast::Item, offset: Indent) if offset.width() + result.len() + trait_bound_str.len() > context.config.max_width { result.push('\n'); - let width = context.block_indent.width() + context.config.tab_spaces - 1; + let width = context.block_indent.width() + context.config.tab_spaces; let trait_indent = Indent::new(0, width); result.push_str(&trait_indent.to_string(context.config)); } @@ -1021,6 +1021,75 @@ pub fn rewrite_static(prefix: &str, rewrite_assign_rhs(context, lhs, expr, remaining_width, context.block_indent).map(|s| s + ";") } +pub fn rewrite_associated_type(prefix: &str, + ident: ast::Ident, + ty_opt: Option<&ptr::P>, + ty_param_bounds_opt: Option<&ast::TyParamBounds>, + context: &RewriteContext, + indent: Indent) + -> Option { + let prefix = format!("{} {}", prefix, ident); + + let type_bounds_str = if let Some(ty_param_bounds) = ty_param_bounds_opt { + let bounds: &[_] = &ty_param_bounds.as_slice(); + let bound_str = bounds.iter() + .filter_map(|ty_bound| { + ty_bound.rewrite(context, + context.config.max_width, + indent) + }) + .collect::>() + .join(" + "); + if bounds.len() > 0 { + format!(": {}", bound_str) + } else { + String::new() + } + } else { + String::new() + }; + + if let Some(ty) = ty_opt { + let ty_str = try_opt!(ty.rewrite(context, + context.config.max_width - context.block_indent.width() - + prefix.len() - 2, + context.block_indent)); + Some(format!("{} = {};", prefix, ty_str)) + } else { + Some(format!("{}{};", prefix, type_bounds_str)) + } +} + +pub fn rewrite_associated_static(prefix: &str, + vis: ast::Visibility, + ident: ast::Ident, + ty: &ast::Ty, + mutability: ast::Mutability, + expr_opt: &Option>, + context: &RewriteContext) + -> Option { + let prefix = format!("{}{} {}{}: ", + format_visibility(vis), + prefix, + format_mutability(mutability), + ident); + // 2 = " =".len() + let ty_str = try_opt!(ty.rewrite(context, + context.config.max_width - context.block_indent.width() - + prefix.len() - 2, + context.block_indent)); + + if let &Some(ref expr) = expr_opt { + let lhs = format!("{}{} =", prefix, ty_str); + // 1 = ; + let remaining_width = context.config.max_width - context.block_indent.width() - 1; + rewrite_assign_rhs(context, lhs, expr, remaining_width, context.block_indent).map(|s| s + ";") + } else { + let lhs = format!("{}{};", prefix, ty_str); + Some(lhs) + } +} + impl Rewrite for ast::FunctionRetTy { fn rewrite(&self, context: &RewriteContext, width: usize, offset: Indent) -> Option { match *self { @@ -1671,6 +1740,7 @@ fn rewrite_where_clause(context: &RewriteContext, config: context.config, }; let preds_str = try_opt!(write_list(&item_vec, &fmt)); + println!("{:?}", preds_str); let end_length = if terminator == "{" { // If the brace is on the next line we don't need to count it otherwise it needs two diff --git a/src/visitor.rs b/src/visitor.rs index 02bc29e32692..2339a47dd21a 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -21,7 +21,7 @@ use rewrite::{Rewrite, RewriteContext}; use comment::rewrite_comment; use macros::rewrite_macro; -use items::{rewrite_static, rewrite_type_alias, format_impl, format_trait}; +use items::{rewrite_static, rewrite_associated_static, rewrite_associated_type, rewrite_type_alias, format_impl, format_trait}; pub struct FmtVisitor<'a> { pub parse_session: &'a ParseSess, @@ -207,7 +207,6 @@ fn visit_item(&mut self, item: &ast::Item) { self.last_pos = item.span.hi; } } - // FIXME(#78): format traits. ast::ItemKind::Trait(..) => { self.format_missing_with_indent(item.span.lo); if let Some(trait_str) = format_trait(&self.get_context(), @@ -216,11 +215,6 @@ fn visit_item(&mut self, item: &ast::Item) { self.buffer.push_str(&trait_str); self.last_pos = item.span.hi; } - // self.block_indent = self.block_indent.block_indent(self.config); - // for item in trait_items { - // self.visit_trait_item(&item); - // } - // self.block_indent = self.block_indent.block_unindent(self.config); } ast::ItemKind::ExternCrate(_) => { self.format_missing_with_indent(item.span.lo); @@ -320,8 +314,15 @@ pub fn visit_trait_item(&mut self, ti: &ast::TraitItem) { } match ti.node { - ast::TraitItemKind::Const(..) => { - // FIXME: Implement + ast::TraitItemKind::Const(ref ty, ref expr) => { + let rewrite = rewrite_associated_static("const", + ast::Visibility::Inherited, + ti.ident, + ty, + ast::Mutability::Immutable, + expr, + &self.get_context()); + self.push_rewrite(ti.span, rewrite); } ast::TraitItemKind::Method(ref sig, None) => { let indent = self.block_indent; @@ -336,25 +337,13 @@ pub fn visit_trait_item(&mut self, ti: &ast::TraitItem) { ti.id); } ast::TraitItemKind::Type(ref type_param_bounds, _) => { - let indent = self.block_indent; - let mut result = String::new(); - result.push_str(&format!("type {}", ti.ident)); - - let bounds: &[_] = &type_param_bounds.as_slice(); - let bound_str = bounds.iter() - .filter_map(|ty_bound| { - ty_bound.rewrite(&self.get_context(), - self.config.max_width, - indent) - }) - .collect::>() - .join(" + "); - if bounds.len() > 0 { - result.push_str(&format!(": {}", bound_str)); - } - - result.push(';'); - self.push_rewrite(ti.span, Some(result)); + let rewrite = rewrite_associated_type("type", + ti.ident, + None, + Some(type_param_bounds), + &self.get_context(), + self.block_indent); + self.push_rewrite(ti.span, rewrite); } } } @@ -372,11 +361,24 @@ pub fn visit_impl_item(&mut self, ii: &ast::ImplItem) { ii.span, ii.id); } - ast::ImplItemKind::Const(..) => { - // FIXME: Implement + ast::ImplItemKind::Const(ref ty, ref expr) => { + let rewrite = rewrite_static("const", + ast::Visibility::Inherited, + ii.ident, + ty, + ast::Mutability::Immutable, + &expr, + &self.get_context()); + self.push_rewrite(ii.span, rewrite); } - ast::ImplItemKind::Type(_) => { - // FIXME: Implement + ast::ImplItemKind::Type(ref ty) => { + let rewrite = rewrite_associated_type("type", + ii.ident, + Some(ty), + None, + &self.get_context(), + self.block_indent); + self.push_rewrite(ii.span, rewrite); } ast::ImplItemKind::Macro(ref mac) => { self.format_missing_with_indent(ii.span.lo); From 2793b4090c2acef5380bfb6f972f79a3d338f968 Mon Sep 17 00:00:00 2001 From: Connor Brewster Date: Mon, 14 Mar 2016 20:05:20 -0600 Subject: [PATCH 08/11] Added tests --- src/items.rs | 11 +++++------ src/visitor.rs | 15 ++++++++------- tests/source/impls.rs | 16 ++++++++++------ tests/source/trait.rs | 6 ++++++ tests/source/where-trailing-comma.rs | 3 +-- tests/target/impls.rs | 4 ++++ tests/target/trait.rs | 9 +++++++++ tests/target/where-trailing-comma.rs | 5 +++-- 8 files changed, 46 insertions(+), 23 deletions(-) diff --git a/src/items.rs b/src/items.rs index ccf99c5dae72..5f8345593ee4 100644 --- a/src/items.rs +++ b/src/items.rs @@ -1034,9 +1034,7 @@ pub fn rewrite_associated_type(prefix: &str, let bounds: &[_] = &ty_param_bounds.as_slice(); let bound_str = bounds.iter() .filter_map(|ty_bound| { - ty_bound.rewrite(context, - context.config.max_width, - indent) + ty_bound.rewrite(context, context.config.max_width, indent) }) .collect::>() .join(" + "); @@ -1052,7 +1050,8 @@ pub fn rewrite_associated_type(prefix: &str, if let Some(ty) = ty_opt { let ty_str = try_opt!(ty.rewrite(context, context.config.max_width - context.block_indent.width() - - prefix.len() - 2, + prefix.len() - + 2, context.block_indent)); Some(format!("{} = {};", prefix, ty_str)) } else { @@ -1083,7 +1082,8 @@ pub fn rewrite_associated_static(prefix: &str, let lhs = format!("{}{} =", prefix, ty_str); // 1 = ; let remaining_width = context.config.max_width - context.block_indent.width() - 1; - rewrite_assign_rhs(context, lhs, expr, remaining_width, context.block_indent).map(|s| s + ";") + rewrite_assign_rhs(context, lhs, expr, remaining_width, context.block_indent) + .map(|s| s + ";") } else { let lhs = format!("{}{};", prefix, ty_str); Some(lhs) @@ -1740,7 +1740,6 @@ fn rewrite_where_clause(context: &RewriteContext, config: context.config, }; let preds_str = try_opt!(write_list(&item_vec, &fmt)); - println!("{:?}", preds_str); let end_length = if terminator == "{" { // If the brace is on the next line we don't need to count it otherwise it needs two diff --git a/src/visitor.rs b/src/visitor.rs index 2339a47dd21a..5db7b3960322 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -21,7 +21,8 @@ use rewrite::{Rewrite, RewriteContext}; use comment::rewrite_comment; use macros::rewrite_macro; -use items::{rewrite_static, rewrite_associated_static, rewrite_associated_type, rewrite_type_alias, format_impl, format_trait}; +use items::{rewrite_static, rewrite_associated_static, rewrite_associated_type, + rewrite_type_alias, format_impl, format_trait}; pub struct FmtVisitor<'a> { pub parse_session: &'a ParseSess, @@ -316,12 +317,12 @@ pub fn visit_trait_item(&mut self, ti: &ast::TraitItem) { match ti.node { ast::TraitItemKind::Const(ref ty, ref expr) => { let rewrite = rewrite_associated_static("const", - ast::Visibility::Inherited, - ti.ident, - ty, - ast::Mutability::Immutable, - expr, - &self.get_context()); + ast::Visibility::Inherited, + ti.ident, + ty, + ast::Mutability::Immutable, + expr, + &self.get_context()); self.push_rewrite(ti.span, rewrite); } ast::TraitItemKind::Method(ref sig, None) => { diff --git a/tests/source/impls.rs b/tests/source/impls.rs index d04b5ce1eebd..9f34db7ae078 100644 --- a/tests/source/impls.rs +++ b/tests/source/impls.rs @@ -1,6 +1,10 @@ impl Foo for Bar { fn foo() { "hi" } } pub impl Foo for Bar { + // Associated Constants + const Baz: i32 = 16; + // Associated Types + type FooBar = usize; // Comment 1 fn foo() { "hi" } // Comment 2 @@ -9,20 +13,20 @@ fn foo() { "hi" } } pub unsafe impl<'a, 'b, X, Y: Foo> !Foo<'a, X> for Bar<'b, Y> where X: Foo<'a, Z> { - fn foo() { "hi" } + fn foo() { "hi" } } impl<'a, 'b, X, Y: Foo> Foo<'a, X> for Bar<'b, Y> where X: Fooooooooooooooooooooooooooooo<'a, Z> { - fn foo() { "hi" } + fn foo() { "hi" } } impl<'a, 'b, X, Y: Foo> Foo<'a, X> for Bar<'b, Y> where X: Foooooooooooooooooooooooooooo<'a, Z> { - fn foo() { "hi" } + fn foo() { "hi" } } -impl Foo for Bar where T: Baz +impl Foo for Bar where T: Baz { } @@ -38,8 +42,8 @@ impl Boo { fn boo() {} // FOO - - + + } mod a { diff --git a/tests/source/trait.rs b/tests/source/trait.rs index 49b314358f2e..3fb6a1b85e22 100644 --- a/tests/source/trait.rs +++ b/tests/source/trait.rs @@ -37,3 +37,9 @@ trait Test { } trait T<> {} + +trait Foo { type Bar: Baz;} + +trait ConstCheck:Foo where T: Baz { + const J: i32; +} diff --git a/tests/source/where-trailing-comma.rs b/tests/source/where-trailing-comma.rs index 8f951d199e42..c2c1a3185bcb 100644 --- a/tests/source/where-trailing-comma.rs +++ b/tests/source/where-trailing-comma.rs @@ -20,7 +20,7 @@ struct Pair where T: P, S: P + Q { struct TupPair (S, T) where T: P, S: P + Q; -enum E where S: P, T: P { +enum E where S: P, T: P { A {a: T}, } @@ -30,7 +30,6 @@ enum E where S: P, T: P { fn f(x: T, y: S) -> T where T: P, S: Q; } -// Note: trait declarations are not fully formatted (issue #78) trait Q where T: P, S: R { fn f(self, x: T, y: S, z: U) -> Self where U: P, V: P; diff --git a/tests/target/impls.rs b/tests/target/impls.rs index 33bc74819050..c81de4d40fea 100644 --- a/tests/target/impls.rs +++ b/tests/target/impls.rs @@ -5,6 +5,10 @@ fn foo() { } pub impl Foo for Bar { + // Associated Constants + const Baz: i32 = 16; + // Associated Types + type FooBar = usize; // Comment 1 fn foo() { "hi" diff --git a/tests/target/trait.rs b/tests/target/trait.rs index 32389431284a..f784fa145301 100644 --- a/tests/target/trait.rs +++ b/tests/target/trait.rs @@ -36,3 +36,12 @@ fn read_struct(&mut self, s_name: &str, len: usize, f: F) -> Result: Foo where T: Baz +{ + const J: i32; +} diff --git a/tests/target/where-trailing-comma.rs b/tests/target/where-trailing-comma.rs index bd7108f992a8..c8682237ae6a 100644 --- a/tests/target/where-trailing-comma.rs +++ b/tests/target/where-trailing-comma.rs @@ -48,8 +48,9 @@ fn f(x: T, y: S) -> T S: Q; } -// Note: trait declarations are not fully formatted (issue #78) -trait Q where T: P, S: R +trait Q + where T: P, + S: R, { fn f(self, x: T, y: S, z: U) -> Self where U: P, From 54a9f0ebd0c940af7b30ac0163c0141f3254ab9e Mon Sep 17 00:00:00 2001 From: Connor Brewster Date: Mon, 14 Mar 2016 20:11:39 -0600 Subject: [PATCH 09/11] Readded spaces to source test --- tests/source/impls.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/tests/source/impls.rs b/tests/source/impls.rs index 9f34db7ae078..a3a8033b07f2 100644 --- a/tests/source/impls.rs +++ b/tests/source/impls.rs @@ -13,20 +13,20 @@ fn foo() { "hi" } } pub unsafe impl<'a, 'b, X, Y: Foo> !Foo<'a, X> for Bar<'b, Y> where X: Foo<'a, Z> { - fn foo() { "hi" } + fn foo() { "hi" } } impl<'a, 'b, X, Y: Foo> Foo<'a, X> for Bar<'b, Y> where X: Fooooooooooooooooooooooooooooo<'a, Z> { - fn foo() { "hi" } + fn foo() { "hi" } } impl<'a, 'b, X, Y: Foo> Foo<'a, X> for Bar<'b, Y> where X: Foooooooooooooooooooooooooooo<'a, Z> { - fn foo() { "hi" } + fn foo() { "hi" } } -impl Foo for Bar where T: Baz +impl Foo for Bar where T: Baz { } @@ -42,8 +42,8 @@ impl Boo { fn boo() {} // FOO - - + + } mod a { From a0a53356341b9bd71e994713c266746b64105a74 Mon Sep 17 00:00:00 2001 From: Connor Brewster Date: Mon, 14 Mar 2016 20:51:41 -0600 Subject: [PATCH 10/11] Fixed span_after issue --- src/items.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/items.rs b/src/items.rs index c2447aa8c167..0fb5520f6bdd 100644 --- a/src/items.rs +++ b/src/items.rs @@ -622,7 +622,7 @@ pub fn format_trait(context: &RewriteContext, item: &ast::Item, offset: Indent) // let budget = try_opt!(context.config.max_width.checked_sub(result.len())); // let indent = offset + result.len(); - let body_lo = span_after(item.span, "{", context.codemap); + let body_lo = context.codemap.span_after(item.span, "{"); let generics_str = try_opt!(rewrite_generics(context, generics, From 0a665aacebd5b2b4fa579c49fbb16dbb67e9347e Mon Sep 17 00:00:00 2001 From: Connor Brewster Date: Tue, 15 Mar 2016 14:08:12 -0600 Subject: [PATCH 11/11] Fixed nitpicks Removed unneeded comment Commented line wrapping conditions Removed prefix param on `rewrite_associated_type` Merged `rewrite_associated_static` into `rewrite_static` Added extra tests --- src/items.rs | 95 ++++++++++++++++++++----------------------- src/visitor.rs | 31 +++++++------- tests/source/trait.rs | 10 +++++ tests/target/trait.rs | 23 ++++++++++- 4 files changed, 91 insertions(+), 68 deletions(-) diff --git a/src/items.rs b/src/items.rs index 0fb5520f6bdd..8435de621475 100644 --- a/src/items.rs +++ b/src/items.rs @@ -618,10 +618,6 @@ pub fn format_trait(context: &RewriteContext, item: &ast::Item, offset: Indent) result.push_str(&header); - // TODO: Add max_width checking - // let budget = try_opt!(context.config.max_width.checked_sub(result.len())); - // let indent = offset + result.len(); - let body_lo = context.codemap.span_after(item.span, "{"); let generics_str = try_opt!(rewrite_generics(context, @@ -636,8 +632,10 @@ pub fn format_trait(context: &RewriteContext, item: &ast::Item, offset: Indent) type_param_bounds, offset, context.config.max_width)); - - if offset.width() + result.len() + trait_bound_str.len() > context.config.max_width { + // If the trait, generics, and trait bound cannot fit on the same line, + // put the trait bounds on an indented new line + if offset.width() + last_line_width(&result) + trait_bound_str.len() > + context.config.ideal_width { result.push('\n'); let width = context.block_indent.width() + context.config.tab_spaces; let trait_indent = Indent::new(0, width); @@ -645,19 +643,39 @@ pub fn format_trait(context: &RewriteContext, item: &ast::Item, offset: Indent) } result.push_str(&trait_bound_str); - let where_budget = try_opt!(context.config.max_width.checked_sub(last_line_width(&result))); + let has_body = !trait_items.is_empty(); + + let where_density = if (context.config.where_density == Density::Compressed && + (!result.contains('\n') || + context.config.fn_args_layout == StructLitStyle::Block)) || + (context.config.fn_args_layout == StructLitStyle::Block && + result.is_empty()) || + (context.config.where_density == Density::CompressedIfEmpty && + !has_body && + !result.contains('\n')) { + Density::Compressed + } else { + Density::Tall + }; + + let where_budget = try_opt!(context.config + .max_width + .checked_sub(last_line_width(&result))); let where_clause_str = try_opt!(rewrite_where_clause(context, &generics.where_clause, context.config, context.config.item_brace_style, context.block_indent, where_budget, - context.config.where_density, + where_density, "{", - context.config.where_trailing_comma, + has_body, None)); + // If the where clause cannot fit on the same line, + // put the where clause on a new line if !where_clause_str.contains('\n') && - result.len() + where_clause_str.len() + offset.width() > context.config.max_width { + last_line_width(&result) + where_clause_str.len() + offset.width() > + context.config.ideal_width { result.push('\n'); let width = context.block_indent.width() + context.config.tab_spaces - 1; let where_indent = Indent::new(0, width); @@ -672,7 +690,8 @@ pub fn format_trait(context: &RewriteContext, item: &ast::Item, offset: Indent) } BraceStyle::PreferSameLine => result.push(' '), BraceStyle::SameLineWhere => { - if !where_clause_str.is_empty() { + if !where_clause_str.is_empty() && + (trait_items.len() > 0 || result.contains('\n')) { result.push('\n'); result.push_str(&offset.to_string(context.config)); } else { @@ -704,6 +723,8 @@ pub fn format_trait(context: &RewriteContext, item: &ast::Item, offset: Indent) result.push_str(&trim_newlines(&visitor.buffer.to_string().trim())); result.push('\n'); result.push_str(&outer_indent_str); + } else if result.contains('\n') { + result.push('\n'); } result.push('}'); @@ -1000,7 +1021,7 @@ pub fn rewrite_static(prefix: &str, ident: ast::Ident, ty: &ast::Ty, mutability: ast::Mutability, - expr: &ast::Expr, + expr_opt: Option<&ptr::P>, context: &RewriteContext) -> Option { let prefix = format!("{}{} {}{}: ", @@ -1013,21 +1034,26 @@ pub fn rewrite_static(prefix: &str, context.config.max_width - context.block_indent.width() - prefix.len() - 2, context.block_indent)); - let lhs = format!("{}{} =", prefix, ty_str); - // 1 = ; - let remaining_width = context.config.max_width - context.block_indent.width() - 1; - rewrite_assign_rhs(context, lhs, expr, remaining_width, context.block_indent).map(|s| s + ";") + if let Some(ref expr) = expr_opt { + let lhs = format!("{}{} =", prefix, ty_str); + // 1 = ; + let remaining_width = context.config.max_width - context.block_indent.width() - 1; + rewrite_assign_rhs(context, lhs, expr, remaining_width, context.block_indent) + .map(|s| s + ";") + } else { + let lhs = format!("{}{};", prefix, ty_str); + Some(lhs) + } } -pub fn rewrite_associated_type(prefix: &str, - ident: ast::Ident, +pub fn rewrite_associated_type(ident: ast::Ident, ty_opt: Option<&ptr::P>, ty_param_bounds_opt: Option<&ast::TyParamBounds>, context: &RewriteContext, indent: Indent) -> Option { - let prefix = format!("{} {}", prefix, ident); + let prefix = format!("type {}", ident); let type_bounds_str = if let Some(ty_param_bounds) = ty_param_bounds_opt { let bounds: &[_] = &ty_param_bounds.as_slice(); @@ -1058,37 +1084,6 @@ pub fn rewrite_associated_type(prefix: &str, } } -pub fn rewrite_associated_static(prefix: &str, - vis: ast::Visibility, - ident: ast::Ident, - ty: &ast::Ty, - mutability: ast::Mutability, - expr_opt: &Option>, - context: &RewriteContext) - -> Option { - let prefix = format!("{}{} {}{}: ", - format_visibility(vis), - prefix, - format_mutability(mutability), - ident); - // 2 = " =".len() - let ty_str = try_opt!(ty.rewrite(context, - context.config.max_width - context.block_indent.width() - - prefix.len() - 2, - context.block_indent)); - - if let &Some(ref expr) = expr_opt { - let lhs = format!("{}{} =", prefix, ty_str); - // 1 = ; - let remaining_width = context.config.max_width - context.block_indent.width() - 1; - rewrite_assign_rhs(context, lhs, expr, remaining_width, context.block_indent) - .map(|s| s + ";") - } else { - let lhs = format!("{}{};", prefix, ty_str); - Some(lhs) - } -} - impl Rewrite for ast::FunctionRetTy { fn rewrite(&self, context: &RewriteContext, width: usize, offset: Indent) -> Option { match *self { diff --git a/src/visitor.rs b/src/visitor.rs index f5774da7d649..62fbfd7613fa 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -21,8 +21,7 @@ use rewrite::{Rewrite, RewriteContext}; use comment::rewrite_comment; use macros::rewrite_macro; -use items::{rewrite_static, rewrite_associated_static, rewrite_associated_type, - rewrite_type_alias, format_impl, format_trait}; +use items::{rewrite_static, rewrite_associated_type, rewrite_type_alias, format_impl, format_trait}; pub struct FmtVisitor<'a> { pub parse_session: &'a ParseSess, @@ -267,7 +266,7 @@ fn visit_item(&mut self, item: &ast::Item) { item.ident, ty, mutability, - expr, + Some(expr), &self.get_context()); self.push_rewrite(item.span, rewrite); } @@ -277,7 +276,7 @@ fn visit_item(&mut self, item: &ast::Item) { item.ident, ty, ast::Mutability::Immutable, - expr, + Some(expr), &self.get_context()); self.push_rewrite(item.span, rewrite); } @@ -315,14 +314,14 @@ pub fn visit_trait_item(&mut self, ti: &ast::TraitItem) { } match ti.node { - ast::TraitItemKind::Const(ref ty, ref expr) => { - let rewrite = rewrite_associated_static("const", - ast::Visibility::Inherited, - ti.ident, - ty, - ast::Mutability::Immutable, - expr, - &self.get_context()); + ast::TraitItemKind::Const(ref ty, ref expr_opt) => { + let rewrite = rewrite_static("const", + ast::Visibility::Inherited, + ti.ident, + ty, + ast::Mutability::Immutable, + expr_opt.as_ref(), + &self.get_context()); self.push_rewrite(ti.span, rewrite); } ast::TraitItemKind::Method(ref sig, None) => { @@ -338,8 +337,7 @@ pub fn visit_trait_item(&mut self, ti: &ast::TraitItem) { ti.id); } ast::TraitItemKind::Type(ref type_param_bounds, _) => { - let rewrite = rewrite_associated_type("type", - ti.ident, + let rewrite = rewrite_associated_type(ti.ident, None, Some(type_param_bounds), &self.get_context(), @@ -368,13 +366,12 @@ pub fn visit_impl_item(&mut self, ii: &ast::ImplItem) { ii.ident, ty, ast::Mutability::Immutable, - &expr, + Some(expr), &self.get_context()); self.push_rewrite(ii.span, rewrite); } ast::ImplItemKind::Type(ref ty) => { - let rewrite = rewrite_associated_type("type", - ii.ident, + let rewrite = rewrite_associated_type(ii.ident, Some(ty), None, &self.get_context(), diff --git a/tests/source/trait.rs b/tests/source/trait.rs index 3fb6a1b85e22..faac57179c20 100644 --- a/tests/source/trait.rs +++ b/tests/source/trait.rs @@ -43,3 +43,13 @@ trait T<> {} trait ConstCheck:Foo where T: Baz { const J: i32; } + +trait Tttttttttttttttttttttttttttttttttttttttttttttttttttttttttt + where T: Foo {} + +trait Ttttttttttttttttttttttttttttttttttttttttttttttttttttttttttt where T: Foo {} + +trait FooBar : Tttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttt where J: Bar { fn test(); } + +trait WhereList where T: Foo, J: Bar {} + diff --git a/tests/target/trait.rs b/tests/target/trait.rs index f784fa145301..d8acc1ba229b 100644 --- a/tests/target/trait.rs +++ b/tests/target/trait.rs @@ -41,7 +41,28 @@ trait Foo { type Bar: Baz; } -trait ConstCheck: Foo where T: Baz +trait ConstCheck: Foo + where T: Baz { const J: i32; } + +trait Tttttttttttttttttttttttttttttttttttttttttttttttttttttttttt where T: Foo {} + +trait Ttttttttttttttttttttttttttttttttttttttttttttttttttttttttttt + where T: Foo +{ +} + +trait FooBar + : Tttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttt + where J: Bar +{ + fn test(); +} + +trait WhereList + where T: Foo, + J: Bar +{ +}