diff options
| author | Nick Cameron <ncameron@mozilla.com> | 2015-05-25 11:03:26 +1200 |
|---|---|---|
| committer | Nick Cameron <ncameron@mozilla.com> | 2015-05-25 17:07:55 +1200 |
| commit | e7adf64155abb3bdc2dcb6bb52ee24ed87206eff (patch) | |
| tree | 6a908b645ba344ff537671e3235db6cf733e2bc2 /src | |
| parent | c3856880f6c40649d3bb9a330c65de79db6c56a4 (diff) | |
Format structs
Diffstat (limited to 'src')
| -rw-r--r-- | src/bin/rustfmt.rs | 4 | ||||
| -rw-r--r-- | src/config.rs | 1 | ||||
| -rw-r--r-- | src/items.rs (renamed from src/functions.rs) | 126 | ||||
| -rw-r--r-- | src/lib.rs | 2 | ||||
| -rw-r--r-- | src/visitor.rs | 11 |
5 files changed, 136 insertions, 8 deletions
diff --git a/src/bin/rustfmt.rs b/src/bin/rustfmt.rs index 5a12dbd639b..3b87ac7eb03 100644 --- a/src/bin/rustfmt.rs +++ b/src/bin/rustfmt.rs @@ -24,8 +24,8 @@ fn main() { let mut def_config = String::new(); def_config_file.read_to_string(&mut def_config).unwrap(); - //run(args, WriteMode::Display, &def_config); - run(args, WriteMode::Overwrite, &def_config); + run(args, WriteMode::Display, &def_config); + //run(args, WriteMode::Overwrite, &def_config); std::env::set_exit_status(0); diff --git a/src/config.rs b/src/config.rs index d1045293ee3..080926b03a2 100644 --- a/src/config.rs +++ b/src/config.rs @@ -23,7 +23,6 @@ pub struct Config { impl Config { fn from_toml(toml: &str) -> Config { - println!("About to parse: {}", toml); let parsed = toml.parse().unwrap(); toml::decode(parsed).unwrap() } diff --git a/src/functions.rs b/src/items.rs index 2ca5423f0c8..a2027d89b88 100644 --- a/src/functions.rs +++ b/src/items.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// Formatting top-level items - functions, structs, enums, traits, impls. + use {ReturnIndent, BraceStyle}; use utils::make_indent; use lists::{write_list, ListFormatting, SeparatorTactic, ListTactic}; @@ -123,7 +125,7 @@ impl<'a> FmtVisitor<'a> { let generics_indent = indent + result.len(); result.push_str(&self.rewrite_generics(generics, generics_indent, - span_for_return(&fd.output))); + span_for_return(&fd.output).lo)); let ret_str = self.rewrite_return(&fd.output); @@ -388,7 +390,125 @@ impl<'a> FmtVisitor<'a> { } } - fn rewrite_generics(&self, generics: &ast::Generics, indent: usize, ret_span: Span) -> String { + pub fn visit_struct(&mut self, + ident: ast::Ident, + vis: ast::Visibility, + struct_def: &ast::StructDef, + generics: &ast::Generics, + span: Span) + { + let header_str = self.struct_header(ident, vis); + self.changes.push_str_span(span, &header_str); + + if struct_def.fields.len() == 0 { + assert!(generics.where_clause.predicates.len() == 0, + "No-field struct with where clause?"); + assert!(generics.lifetimes.len() == 0, "No-field struct with generics?"); + assert!(generics.ty_params.len() == 0, "No-field struct with generics?"); + + self.changes.push_str_span(span, ";"); + return; + } + + let mut generics_buf = String::new(); + let generics_str = self.rewrite_generics(generics, self.block_indent, struct_def.fields[0].span.lo); + generics_buf.push_str(&generics_str); + + if generics.where_clause.predicates.len() > 0 { + generics_buf.push_str(&self.rewrite_where_clause(&generics.where_clause, + self.block_indent, + struct_def.fields[0].span.lo)); + generics_buf.push_str(&make_indent(self.block_indent)); + generics_buf.push_str("\n{"); + + } else { + generics_buf.push_str(" {"); + } + self.changes.push_str_span(span, &generics_buf); + + let struct_snippet = self.snippet(span); + // FIXME this will give incorrect results if there is a { in a commet. + self.last_pos = span.lo + BytePos(struct_snippet.find('{').unwrap() as u32 + 1); + + self.block_indent += config!(tab_spaces); + for f in &struct_def.fields { + self.visit_field(f, span.lo, &struct_snippet); + } + self.block_indent -= config!(tab_spaces); + + self.format_missing_with_indent(span.lo + BytePos(struct_snippet.rfind('}').unwrap() as u32)); + self.changes.push_str_span(span, "}"); + } + + fn struct_header(&self, + ident: ast::Ident, + vis: ast::Visibility) + -> String + { + let vis = if vis == ast::Visibility::Public { + "pub " + } else { + "" + }; + + format!("{}struct {}", vis, &token::get_ident(ident)) + } + + // Field of a struct + fn visit_field(&mut self, + field: &ast::StructField, + // These two args are for missing spans hacks. + struct_start: BytePos, + struct_snippet: &str) + { + if self.visit_attrs(&field.node.attrs) { + return; + } + self.format_missing_with_indent(field.span.lo); + + let name = match field.node.kind { + ast::StructFieldKind::NamedField(ident, _) => Some(token::get_ident(ident)), + ast::StructFieldKind::UnnamedField(_) => None, + }; + let vis = match field.node.kind { + ast::StructFieldKind::NamedField(_, vis) | + ast::StructFieldKind::UnnamedField(vis) => if vis == ast::Visibility::Public { + "pub " + } else { + "" + } + }; + let typ = pprust::ty_to_string(&field.node.ty); + + let field_str = match name { + Some(name) => { + let budget = config!(ideal_width) - self.block_indent; + if self.block_indent + vis.len() + name.len() + typ.len() + 3 > budget { + format!("{}{}:\n{}{},", + vis, + name, + &make_indent(self.block_indent + config!(tab_spaces)), + typ) + } else { + format!("{}{}: {},", vis, name, typ) + } + } + None => format!("{}{},", vis, typ), + }; + self.changes.push_str_span(field.span, &field_str); + + // This hack makes sure we only add comments etc. after the comma, and + // makes sure we don't repeat any commas. + let hi = field.span.hi; + // FIXME a comma in a comment will break this hack. + let comma_pos = match struct_snippet[(hi.0 - struct_start.0) as usize..].find(',') { + Some(i) => i, + None => 0, + }; + self.last_pos = hi + BytePos(comma_pos as u32 + 1); + } + + fn rewrite_generics(&self, generics: &ast::Generics, indent: usize, span_end: BytePos) -> String { // FIXME convert bounds to where clauses where they get too big or if // there is a where clause at all. let mut result = String::new(); @@ -422,7 +542,7 @@ impl<'a> FmtVisitor<'a> { ">", |sp| sp.lo, |sp| sp.hi, - ret_span.lo); + span_end); // If there are // comments, keep them multi-line. let mut list_tactic = ListTactic::HorizontalVertical; diff --git a/src/lib.rs b/src/lib.rs index 386c39ad472..1a690b4945a 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -50,7 +50,7 @@ use visitor::FmtVisitor; mod config; mod changes; mod visitor; -mod functions; +mod items; mod missed_spans; mod lists; mod utils; diff --git a/src/visitor.rs b/src/visitor.rs index 2aac931c4e6..256c1e6e132 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -180,6 +180,15 @@ impl<'a, 'v> visit::Visitor<'v> for FmtVisitor<'a> { self.changes.push_str_span(item.span, &new_str); self.last_pos = item.span.hi; } + ast::Item_::ItemStruct(ref def, ref generics) => { + self.format_missing_with_indent(item.span.lo); + self.visit_struct(item.ident, + item.vis, + def, + generics, + item.span); + self.last_pos = item.span.hi; + } _ => { visit::walk_item(self, item); } @@ -252,7 +261,7 @@ impl<'a> FmtVisitor<'a> { } // Returns true if we should skip the following item. - fn visit_attrs(&mut self, attrs: &[ast::Attribute]) -> bool { + pub fn visit_attrs(&mut self, attrs: &[ast::Attribute]) -> bool { if attrs.len() == 0 { return false; } |
