diff --git a/src/bin/rustfmt.rs b/src/bin/rustfmt.rs index 67b2e6316a6..32c38ea15e4 100644 --- a/src/bin/rustfmt.rs +++ b/src/bin/rustfmt.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![cfg(not(test))] #![feature(exit_status)] extern crate rustfmt; diff --git a/src/functions.rs b/src/functions.rs index d4f06c1c7ac..2133b7c4418 100644 --- a/src/functions.rs +++ b/src/functions.rs @@ -28,15 +28,79 @@ impl<'a> FmtVisitor<'a> { unsafety: &ast::Unsafety, abi: &abi::Abi, vis: ast::Visibility, - next_span: Span) // next_span is a nasty hack, its a loose upper - // bound on any comments after the where clause. + span_end: BytePos) + -> String + { + let newline_brace = self.newline_for_brace(&generics.where_clause); + + let mut result = self.rewrite_fn_base(indent, + ident, + fd, + explicit_self, + generics, + unsafety, + abi, + vis, + span_end, + newline_brace); + + // Prepare for the function body by possibly adding a newline and indent. + // FIXME we'll miss anything between the end of the signature and the start + // of the body, but we need more spans from the compiler to solve this. + if newline_brace { + result.push('\n'); + result.push_str(&make_indent(indent)); + } else { + result.push(' '); + } + + result + } + + pub fn rewrite_required_fn(&mut self, + indent: usize, + ident: ast::Ident, + sig: &ast::MethodSig, + span: Span) + -> String + { + // Drop semicolon or it will be interpreted as comment + let span_end = span.hi - BytePos(1); + + let mut result = self.rewrite_fn_base(indent, + ident, + &sig.decl, + Some(&sig.explicit_self), + &sig.generics, + &sig.unsafety, + &sig.abi, + ast::Visibility::Inherited, + span_end, + false); + + // Re-attach semicolon + result.push(';'); + + result + } + + fn rewrite_fn_base(&mut self, + indent: usize, + ident: ast::Ident, + fd: &ast::FnDecl, + explicit_self: Option<&ast::ExplicitSelf>, + generics: &ast::Generics, + unsafety: &ast::Unsafety, + abi: &abi::Abi, + vis: ast::Visibility, + span_end: BytePos, + newline_brace: bool) -> String { // FIXME we'll lose any comments in between parts of the function decl, but anyone // who comments there probably deserves what they get. let where_clause = &generics.where_clause; - let newline_brace = self.newline_for_brace(where_clause); let mut result = String::with_capacity(1024); // Vis unsafety abi. @@ -104,7 +168,7 @@ impl<'a> FmtVisitor<'a> { // Comment between return type and the end of the decl. let snippet_lo = fd.output.span().hi; if where_clause.predicates.len() == 0 { - let snippet_hi = next_span.lo; + let snippet_hi = span_end; let snippet = self.snippet(codemap::mk_sp(snippet_lo, snippet_hi)); let snippet = snippet.trim(); if snippet.len() > 0 { @@ -119,17 +183,7 @@ impl<'a> FmtVisitor<'a> { } // Where clause. - result.push_str(&self.rewrite_where_clause(where_clause, indent, next_span)); - - // Prepare for the function body by possibly adding a newline and indent. - // FIXME we'll miss anything between the end of the signature and the start - // of the body, but we need more spans from the compiler to solve this. - if newline_brace { - result.push('\n'); - result.push_str(&make_indent(self.block_indent)); - } else { - result.push(' '); - } + result.push_str(&self.rewrite_where_clause(where_clause, indent, span_end)); result } @@ -396,7 +450,7 @@ impl<'a> FmtVisitor<'a> { fn rewrite_where_clause(&self, where_clause: &ast::WhereClause, indent: usize, - next_span: Span) + span_end: BytePos) -> String { let mut result = String::new(); @@ -414,7 +468,8 @@ impl<'a> FmtVisitor<'a> { "{", |pred| span_for_where_pred(pred).lo, |pred| span_for_where_pred(pred).hi, - next_span.lo); + span_end); + let where_strs: Vec<_> = where_clause.predicates.iter() .map(|p| (self.rewrite_pred(p))) .zip(comments.into_iter()) diff --git a/src/visitor.rs b/src/visitor.rs index 382dce97050..3cc9b36222b 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -107,7 +107,7 @@ impl<'a, 'v> visit::Visitor<'v> for FmtVisitor<'a> { unsafety, abi, vis, - b.span); + b.span.lo); self.changes.push_str_span(s, &new_fn); } visit::FkMethod(ident, ref sig, vis) => { @@ -119,7 +119,7 @@ impl<'a, 'v> visit::Visitor<'v> for FmtVisitor<'a> { &sig.unsafety, &sig.abi, vis.unwrap_or(ast::Visibility::Inherited), - b.span); + b.span.lo); self.changes.push_str_span(s, &new_fn); } visit::FkFnBlock(..) => {} @@ -190,6 +190,21 @@ impl<'a, 'v> visit::Visitor<'v> for FmtVisitor<'a> { if self.visit_attrs(&ti.attrs) { return; } + + if let ast::TraitItem_::MethodTraitItem(ref sig, None) = ti.node { + self.format_missing_with_indent(ti.span.lo); + + let indent = self.block_indent; + let new_fn = self.rewrite_required_fn(indent, + ti.ident, + sig, + ti.span); + + self.changes.push_str_span(ti.span, &new_fn); + self.last_pos = ti.span.hi; + } + // TODO format trait types + visit::walk_trait_item(self, ti) } diff --git a/tests/idem/trait.rs b/tests/idem/trait.rs new file mode 100644 index 00000000000..8f7f4be67c9 --- /dev/null +++ b/tests/idem/trait.rs @@ -0,0 +1,20 @@ +// Test traits + +trait Foo { + fn bar(x: i32) -> Baz { + Baz::new() + } + + fn baz(a: AAAAAAAAAAAAAAAAAAAAAA, b: BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB) -> RetType; + + fn foo(a: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA, // Another comment + b: BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB) + -> RetType; // Some comment + + fn baz(&mut self) -> i32; + + fn increment(&mut self, x: i32); + + fn read(&mut self, x: BufReader /* Used to be MemReader */) + where R: Read; +}