]> git.lizzy.rs Git - rust.git/blobdiff - src/visitor.rs
Remove BlockIndentStyle::Inherit
[rust.git] / src / visitor.rs
index 76cdf54394652d392ac78f3cb0738579788e9ae4..2700287608de6f1944a3648c4f0fcdd5367fb476 100644 (file)
@@ -8,20 +8,28 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use syntax::ast;
+use syntax::{ast, ptr, visit};
 use syntax::codemap::{self, CodeMap, Span, BytePos};
 use syntax::parse::ParseSess;
-use syntax::visit;
 
 use strings::string_buffer::StringBuffer;
 
-use Indent;
-use utils::{self, CodeMapSpanUtils};
+use {Indent, Shape};
+use utils;
+use codemap::{LineRangeUtils, SpanUtils};
 use config::Config;
 use rewrite::{Rewrite, RewriteContext};
 use comment::rewrite_comment;
-use macros::rewrite_macro;
-use items::{rewrite_static, rewrite_type_alias, format_impl};
+use macros::{rewrite_macro, MacroPosition};
+use items::{rewrite_static, rewrite_associated_type, rewrite_associated_impl_type,
+            rewrite_type_alias, format_impl, format_trait};
+
+fn is_use_item(item: &ast::Item) -> bool {
+    match item.node {
+        ast::ItemKind::Use(_) => true,
+        _ => false,
+    }
+}
 
 pub struct FmtVisitor<'a> {
     pub parse_session: &'a ParseSess,
@@ -35,28 +43,32 @@ pub struct FmtVisitor<'a> {
 
 impl<'a> FmtVisitor<'a> {
     fn visit_stmt(&mut self, stmt: &ast::Stmt) {
-        match stmt.node {
-            ast::Stmt_::StmtDecl(ref decl, _) => {
-                if let ast::Decl_::DeclItem(ref item) = decl.node {
-                    self.visit_item(item);
-                } else {
-                    let rewrite = stmt.rewrite(&self.get_context(),
-                                               self.config.max_width - self.block_indent.width(),
-                                               self.block_indent);
+        debug!("visit_stmt: {:?} {:?}",
+               self.codemap.lookup_char_pos(stmt.span.lo),
+               self.codemap.lookup_char_pos(stmt.span.hi));
 
-                    self.push_rewrite(stmt.span, rewrite);
-                }
+        // FIXME(#434): Move this check to somewhere more central, eg Rewrite.
+        if !self.config.file_lines.contains(&self.codemap.lookup_line_range(stmt.span)) {
+            return;
+        }
+
+        match stmt.node {
+            ast::StmtKind::Item(ref item) => {
+                self.visit_item(item);
             }
-            ast::Stmt_::StmtExpr(..) | ast::Stmt_::StmtSemi(..) => {
+            ast::StmtKind::Local(..) |
+            ast::StmtKind::Expr(..) |
+            ast::StmtKind::Semi(..) => {
                 let rewrite = stmt.rewrite(&self.get_context(),
-                                           self.config.max_width - self.block_indent.width(),
-                                           self.block_indent);
-
+                                           Shape::legacy(self.config.max_width -
+                                                         self.block_indent.width(),
+                                                         self.block_indent));
                 self.push_rewrite(stmt.span, rewrite);
             }
-            ast::Stmt_::StmtMac(ref mac, _macro_style, _) => {
-                self.format_missing_with_indent(stmt.span.lo);
-                self.visit_mac(mac);
+            ast::StmtKind::Mac(ref mac) => {
+                let (ref mac, _macro_style, _) = **mac;
+                self.visit_mac(mac, None, MacroPosition::Statement);
+                self.format_missing(stmt.span.hi);
             }
         }
     }
@@ -68,40 +80,29 @@ pub fn visit_block(&mut self, b: &ast::Block) {
 
         // Check if this block has braces.
         let snippet = self.snippet(b.span);
-        let has_braces = snippet.starts_with("{") || snippet.starts_with("unsafe");
-        let brace_compensation = if has_braces {
-            BytePos(1)
-        } else {
-            BytePos(0)
-        };
+        let has_braces = snippet.starts_with('{') || snippet.starts_with("unsafe");
+        let brace_compensation = if has_braces { BytePos(1) } else { BytePos(0) };
 
         self.last_pos = self.last_pos + brace_compensation;
         self.block_indent = self.block_indent.block_indent(self.config);
         self.buffer.push_str("{");
 
         for stmt in &b.stmts {
-            self.visit_stmt(&stmt)
+            self.visit_stmt(stmt)
         }
 
-        if let Some(ref e) = b.expr {
-            self.format_missing_with_indent(e.span.lo);
-            let rewrite = e.rewrite(&self.get_context(),
-                                    self.config.max_width - self.block_indent.width(),
-                                    self.block_indent)
-                           .unwrap_or_else(|| self.snippet(e.span));
-
-            self.buffer.push_str(&rewrite);
-            self.last_pos = e.span.hi;
-
-            if utils::semicolon_for_expr(e) {
-                self.buffer.push_str(";");
+        if !b.stmts.is_empty() {
+            if let Some(expr) = utils::stmt_expr(&b.stmts[b.stmts.len() - 1]) {
+                if utils::semicolon_for_expr(expr) {
+                    self.buffer.push_str(";");
+                }
             }
         }
 
         // FIXME: we should compress any newlines here to just one
-        self.format_missing_with_indent(b.span.hi - brace_compensation);
+        self.format_missing_with_indent(source!(self, b.span).hi - brace_compensation);
         self.close_block();
-        self.last_pos = b.span.hi;
+        self.last_pos = source!(self, b.span).hi;
     }
 
     // FIXME: this is a terrible hack to indent the comments between the last
@@ -125,67 +126,96 @@ fn close_block(&mut self) {
     fn visit_fn(&mut self,
                 fk: visit::FnKind,
                 fd: &ast::FnDecl,
-                b: &ast::Block,
                 s: Span,
-                _: ast::NodeId) {
+                _: ast::NodeId,
+                defaultness: ast::Defaultness) {
         let indent = self.block_indent;
+        let block;
         let rewrite = match fk {
-            visit::FnKind::ItemFn(ident, ref generics, unsafety, constness, abi, vis) => {
+            visit::FnKind::ItemFn(ident, generics, unsafety, constness, abi, vis, b) => {
+                block = b;
                 self.rewrite_fn(indent,
                                 ident,
                                 fd,
-                                None,
                                 generics,
                                 unsafety,
-                                constness,
+                                constness.node,
+                                defaultness,
                                 abi,
                                 vis,
                                 codemap::mk_sp(s.lo, b.span.lo),
                                 &b)
             }
-            visit::FnKind::Method(ident, ref sig, vis) => {
+            visit::FnKind::Method(ident, sig, vis, b) => {
+                block = b;
                 self.rewrite_fn(indent,
                                 ident,
                                 fd,
-                                Some(&sig.explicit_self),
                                 &sig.generics,
                                 sig.unsafety,
-                                sig.constness,
+                                sig.constness.node,
+                                defaultness,
                                 sig.abi,
-                                vis.unwrap_or(ast::Visibility::Inherited),
+                                vis.unwrap_or(&ast::Visibility::Inherited),
                                 codemap::mk_sp(s.lo, b.span.lo),
                                 &b)
             }
-            visit::FnKind::Closure => None,
+            visit::FnKind::Closure(_) => unreachable!(),
         };
 
         if let Some(fn_str) = rewrite {
-            self.format_missing_with_indent(s.lo);
+            self.format_missing_with_indent(source!(self, s).lo);
             self.buffer.push_str(&fn_str);
             if let Some(c) = fn_str.chars().last() {
                 if c == '}' {
-                    self.last_pos = b.span.hi;
+                    self.last_pos = source!(self, block.span).hi;
                     return;
                 }
             }
         } else {
-            self.format_missing(b.span.lo);
+            self.format_missing(source!(self, block.span).lo);
         }
 
-        self.last_pos = b.span.lo;
-        self.visit_block(b)
+        self.last_pos = source!(self, block.span).lo;
+        self.visit_block(block)
     }
 
-    fn visit_item(&mut self, item: &ast::Item) {
-        // Don't look at attributes for modules (except for rustfmt_skip).
-        // We want to avoid looking at attributes in another file, which the AST
-        // doesn't distinguish.
-        // FIXME This is overly conservative and means we miss attributes on
-        // inline modules.
+    pub fn visit_item(&mut self, item: &ast::Item) {
+        // This is where we bail out if there is a skip attribute. This is only
+        // complex in the module case. It is complex because the module could be
+        // in a separate file and there might be attributes in both files, but
+        // the AST lumps them all together.
         match item.node {
-            ast::Item_::ItemMod(_) => {
-                if utils::contains_skip(&item.attrs) {
+            ast::ItemKind::Mod(ref m) => {
+                let outer_file = self.codemap.lookup_char_pos(item.span.lo).file;
+                let inner_file = self.codemap.lookup_char_pos(m.inner.lo).file;
+                if outer_file.name == inner_file.name {
+                    // Module is inline, in this case we treat modules like any
+                    // other item.
+                    if self.visit_attrs(&item.attrs) {
+                        self.push_rewrite(item.span, None);
+                        return;
+                    }
+                } else if utils::contains_skip(&item.attrs) {
+                    // Module is not inline, but should be skipped.
                     return;
+                } else {
+                    // Module is not inline and should not be skipped. We want
+                    // to process only the attributes in the current file.
+                    let attrs = item.attrs
+                        .iter()
+                        .filter_map(|a| {
+                            let attr_file = self.codemap.lookup_char_pos(a.span.lo).file;
+                            if attr_file.name == outer_file.name {
+                                Some(a.clone())
+                            } else {
+                                None
+                            }
+                        })
+                        .collect::<Vec<_>>();
+                    // Assert because if we should skip it should be caught by
+                    // the above case.
+                    assert!(!self.visit_attrs(&attrs));
                 }
             }
             _ => {
@@ -197,186 +227,221 @@ fn visit_item(&mut self, item: &ast::Item) {
         }
 
         match item.node {
-            ast::Item_::ItemUse(ref vp) => {
-                self.format_import(item.vis, vp, item.span);
+            ast::ItemKind::Use(ref vp) => {
+                self.format_import(&item.vis, vp, item.span);
             }
-            ast::Item_::ItemImpl(..) => {
-                self.format_missing_with_indent(item.span.lo);
+            ast::ItemKind::Impl(..) => {
+                self.format_missing_with_indent(source!(self, item.span).lo);
                 if let Some(impl_str) = format_impl(&self.get_context(), item, self.block_indent) {
                     self.buffer.push_str(&impl_str);
-                    self.last_pos = item.span.hi;
+                    self.last_pos = source!(self, item.span).hi;
                 }
             }
-            // FIXME(#78): format traits.
-            ast::Item_::ItemTrait(_, _, _, ref trait_items) => {
+            ast::ItemKind::Trait(..) => {
                 self.format_missing_with_indent(item.span.lo);
-                self.block_indent = self.block_indent.block_indent(self.config);
-                for item in trait_items {
-                    self.visit_trait_item(&item);
+                if let Some(trait_str) = format_trait(&self.get_context(),
+                                                      item,
+                                                      self.block_indent) {
+                    self.buffer.push_str(&trait_str);
+                    self.last_pos = source!(self, item.span).hi;
                 }
-                self.block_indent = self.block_indent.block_unindent(self.config);
             }
-            ast::Item_::ItemExternCrate(_) => {
-                self.format_missing_with_indent(item.span.lo);
+            ast::ItemKind::ExternCrate(_) => {
+                self.format_missing_with_indent(source!(self, item.span).lo);
                 let new_str = self.snippet(item.span);
                 self.buffer.push_str(&new_str);
-                self.last_pos = item.span.hi;
+                self.last_pos = source!(self, item.span).hi;
             }
-            ast::Item_::ItemStruct(ref def, ref generics) => {
+            ast::ItemKind::Struct(ref def, ref generics) => {
                 let rewrite = {
                     let indent = self.block_indent;
                     let context = self.get_context();
                     ::items::format_struct(&context,
                                            "struct ",
                                            item.ident,
-                                           item.vis,
+                                           &item.vis,
                                            def,
                                            Some(generics),
                                            item.span,
-                                           indent)
-                        .map(|s| {
-                            match *def {
-                                ast::VariantData::Tuple(..) => s + ";",
-                                _ => s,
-                            }
-                        })
+                                           indent,
+                                           None)
+                            .map(|s| match *def {
+                                     ast::VariantData::Tuple(..) => s + ";",
+                                     _ => s,
+                                 })
                 };
                 self.push_rewrite(item.span, rewrite);
             }
-            ast::Item_::ItemEnum(ref def, ref generics) => {
-                self.format_missing_with_indent(item.span.lo);
-                self.visit_enum(item.ident, item.vis, def, generics, item.span);
-                self.last_pos = item.span.hi;
+            ast::ItemKind::Enum(ref def, ref generics) => {
+                self.format_missing_with_indent(source!(self, item.span).lo);
+                self.visit_enum(item.ident, &item.vis, def, generics, item.span);
+                self.last_pos = source!(self, item.span).hi;
             }
-            ast::Item_::ItemMod(ref module) => {
-                self.format_missing_with_indent(item.span.lo);
-                self.format_mod(module, item.vis, item.span, item.ident);
+            ast::ItemKind::Mod(ref module) => {
+                self.format_missing_with_indent(source!(self, item.span).lo);
+                self.format_mod(module, &item.vis, item.span, item.ident);
             }
-            ast::Item_::ItemMac(ref mac) => {
-                self.format_missing_with_indent(item.span.lo);
-                self.visit_mac(mac);
+            ast::ItemKind::Mac(ref mac) => {
+                self.visit_mac(mac, Some(item.ident), MacroPosition::Item);
             }
-            ast::Item_::ItemForeignMod(ref foreign_mod) => {
-                self.format_missing_with_indent(item.span.lo);
+            ast::ItemKind::ForeignMod(ref foreign_mod) => {
+                self.format_missing_with_indent(source!(self, item.span).lo);
                 self.format_foreign_mod(foreign_mod, item.span);
             }
-            ast::Item_::ItemStatic(ref ty, mutability, ref expr) => {
+            ast::ItemKind::Static(ref ty, mutability, ref expr) => {
                 let rewrite = rewrite_static("static",
-                                             item.vis,
+                                             &item.vis,
                                              item.ident,
                                              ty,
                                              mutability,
-                                             expr,
+                                             Some(expr),
+                                             self.block_indent,
                                              &self.get_context());
                 self.push_rewrite(item.span, rewrite);
             }
-            ast::Item_::ItemConst(ref ty, ref expr) => {
+            ast::ItemKind::Const(ref ty, ref expr) => {
                 let rewrite = rewrite_static("const",
-                                             item.vis,
+                                             &item.vis,
                                              item.ident,
                                              ty,
-                                             ast::Mutability::MutImmutable,
-                                             expr,
+                                             ast::Mutability::Immutable,
+                                             Some(expr),
+                                             self.block_indent,
                                              &self.get_context());
                 self.push_rewrite(item.span, rewrite);
             }
-            ast::Item_::ItemDefaultImpl(..) => {
+            ast::ItemKind::DefaultImpl(..) => {
                 // FIXME(#78): format impl definitions.
             }
-            ast::ItemFn(ref declaration, unsafety, constness, abi, ref generics, ref body) => {
+            ast::ItemKind::Fn(ref decl, unsafety, constness, abi, ref generics, ref body) => {
                 self.visit_fn(visit::FnKind::ItemFn(item.ident,
                                                     generics,
                                                     unsafety,
                                                     constness,
                                                     abi,
-                                                    item.vis),
-                              declaration,
-                              body,
+                                                    &item.vis,
+                                                    body),
+                              decl,
                               item.span,
-                              item.id)
+                              item.id,
+                              ast::Defaultness::Final)
             }
-            ast::Item_::ItemTy(ref ty, ref generics) => {
+            ast::ItemKind::Ty(ref ty, ref generics) => {
                 let rewrite = rewrite_type_alias(&self.get_context(),
                                                  self.block_indent,
                                                  item.ident,
                                                  ty,
                                                  generics,
-                                                 item.vis,
+                                                 &item.vis,
                                                  item.span);
                 self.push_rewrite(item.span, rewrite);
             }
+            ast::ItemKind::Union(..) => {
+                // FIXME(#1157): format union definitions.
+            }
         }
     }
 
-    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) {
+            self.push_rewrite(ti.span, None);
             return;
         }
 
         match ti.node {
-            ast::ConstTraitItem(..) => {
-                // FIXME: Implement
+            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.block_indent,
+                                             &self.get_context());
+                self.push_rewrite(ti.span, rewrite);
             }
-            ast::MethodTraitItem(ref sig, None) => {
+            ast::TraitItemKind::Method(ref sig, None) => {
                 let indent = self.block_indent;
                 let rewrite = self.rewrite_required_fn(indent, ti.ident, sig, ti.span);
                 self.push_rewrite(ti.span, rewrite);
             }
-            ast::MethodTraitItem(ref sig, Some(ref body)) => {
-                self.visit_fn(visit::FnKind::Method(ti.ident, sig, None),
+            ast::TraitItemKind::Method(ref sig, Some(ref body)) => {
+                self.visit_fn(visit::FnKind::Method(ti.ident, sig, None, body),
                               &sig.decl,
-                              &body,
                               ti.span,
-                              ti.id);
+                              ti.id,
+                              ast::Defaultness::Final);
+            }
+            ast::TraitItemKind::Type(ref type_param_bounds, _) => {
+                let rewrite = rewrite_associated_type(ti.ident,
+                                                      None,
+                                                      Some(type_param_bounds),
+                                                      &self.get_context(),
+                                                      self.block_indent);
+                self.push_rewrite(ti.span, rewrite);
             }
-            ast::TypeTraitItem(..) => {
-                // FIXME: Implement
+            ast::TraitItemKind::Macro(..) => {
+                // FIXME(#1158) Macros in trait item position
             }
         }
     }
 
     pub fn visit_impl_item(&mut self, ii: &ast::ImplItem) {
         if self.visit_attrs(&ii.attrs) {
+            self.push_rewrite(ii.span, None);
             return;
         }
 
         match ii.node {
             ast::ImplItemKind::Method(ref sig, ref body) => {
-                self.visit_fn(visit::FnKind::Method(ii.ident, sig, Some(ii.vis)),
+                self.visit_fn(visit::FnKind::Method(ii.ident, sig, Some(&ii.vis), body),
                               &sig.decl,
-                              body,
                               ii.span,
-                              ii.id);
+                              ii.id,
+                              ii.defaultness);
             }
-            ast::ImplItemKind::Const(..) => {
-                // FIXME: Implement
+            ast::ImplItemKind::Const(ref ty, ref expr) => {
+                let rewrite = rewrite_static("const",
+                                             &ii.vis,
+                                             ii.ident,
+                                             ty,
+                                             ast::Mutability::Immutable,
+                                             Some(expr),
+                                             self.block_indent,
+                                             &self.get_context());
+                self.push_rewrite(ii.span, rewrite);
             }
-            ast::ImplItemKind::Type(_) => {
-                // FIXME: Implement
+            ast::ImplItemKind::Type(ref ty) => {
+                let rewrite = rewrite_associated_impl_type(ii.ident,
+                                                           ii.defaultness,
+                                                           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);
-                self.visit_mac(mac);
+                self.visit_mac(mac, Some(ii.ident), MacroPosition::Item);
             }
         }
     }
 
-    fn visit_mac(&mut self, mac: &ast::Mac) {
+    fn visit_mac(&mut self, mac: &ast::Mac, ident: Option<ast::Ident>, pos: MacroPosition) {
         // 1 = ;
         let width = self.config.max_width - self.block_indent.width() - 1;
-        let rewrite = rewrite_macro(mac, &self.get_context(), width, self.block_indent);
-
-        if let Some(res) = rewrite {
-            self.buffer.push_str(&res);
-            self.last_pos = mac.span.hi;
-        }
+        let rewrite = rewrite_macro(mac,
+                                    ident,
+                                    &self.get_context(),
+                                    Shape::legacy(width, self.block_indent),
+                                    pos);
+        self.push_rewrite(mac.span, rewrite);
     }
 
     fn push_rewrite(&mut self, span: Span, rewrite: Option<String>) {
-        self.format_missing_with_indent(span.lo);
+        self.format_missing_with_indent(source!(self, span).lo);
         let result = rewrite.unwrap_or_else(|| self.snippet(span));
         self.buffer.push_str(&result);
-        self.last_pos = span.hi;
+        self.last_pos = source!(self, span).hi;
     }
 
     pub fn from_codemap(parse_session: &'a ParseSess, config: &'a Config) -> FmtVisitor<'a> {
@@ -412,46 +477,66 @@ pub fn visit_attrs(&mut self, attrs: &[ast::Attribute]) -> bool {
         }
 
         let outers: Vec<_> = attrs.iter()
-                                  .filter(|a| a.node.style == ast::AttrStyle::Outer)
-                                  .cloned()
-                                  .collect();
+            .filter(|a| a.style == ast::AttrStyle::Outer)
+            .cloned()
+            .collect();
         if outers.is_empty() {
             return false;
         }
 
         let first = &outers[0];
-        self.format_missing_with_indent(first.span.lo);
+        self.format_missing_with_indent(source!(self, first.span).lo);
 
         let rewrite = outers.rewrite(&self.get_context(),
-                                     self.config.max_width - self.block_indent.width(),
-                                     self.block_indent)
-                            .unwrap();
+                                     Shape::legacy(self.config.max_width -
+                                                   self.block_indent.width(),
+                                                   self.block_indent))
+            .unwrap();
         self.buffer.push_str(&rewrite);
         let last = outers.last().unwrap();
-        self.last_pos = last.span.hi;
+        self.last_pos = source!(self, last.span).hi;
         false
     }
 
     fn walk_mod_items(&mut self, m: &ast::Mod) {
-        for item in &m.items {
-            self.visit_item(&item);
+        let mut items_left: &[ptr::P<ast::Item>] = &m.items;
+        while !items_left.is_empty() {
+            // If the next item is a `use` declaration, then extract it and any subsequent `use`s
+            // to be potentially reordered within `format_imports`. Otherwise, just format the
+            // next item for output.
+            if self.config.reorder_imports && is_use_item(&*items_left[0]) {
+                let use_item_length =
+                    items_left.iter().take_while(|ppi| is_use_item(&***ppi)).count();
+                let (use_items, rest) = items_left.split_at(use_item_length);
+                self.format_imports(use_items);
+                items_left = rest;
+            } else {
+                // `unwrap()` is safe here because we know `items_left`
+                // has elements from the loop condition
+                let (item, rest) = items_left.split_first().unwrap();
+                self.visit_item(item);
+                items_left = rest;
+            }
         }
     }
 
-    fn format_mod(&mut self, m: &ast::Mod, vis: ast::Visibility, s: Span, ident: ast::Ident) {
+    fn format_mod(&mut self, m: &ast::Mod, vis: &ast::Visibility, s: Span, ident: ast::Ident) {
         // Decide whether this is an inline mod or an external mod.
         let local_file_name = self.codemap.span_to_filename(s);
-        let is_internal = local_file_name == self.codemap.span_to_filename(m.inner);
+        let inner_span = source!(self, m.inner);
+        let is_internal = !(inner_span.lo.0 == 0 && inner_span.hi.0 == 0) &&
+                          local_file_name == self.codemap.span_to_filename(inner_span);
 
-        self.buffer.push_str(utils::format_visibility(vis));
+        self.buffer.push_str(&*utils::format_visibility(vis));
         self.buffer.push_str("mod ");
         self.buffer.push_str(&ident.to_string());
 
         if is_internal {
             self.buffer.push_str(" {");
             // Hackery to account for the closing }.
-            let mod_lo = self.codemap.span_after(s, "{");
-            let body_snippet = self.snippet(codemap::mk_sp(mod_lo, m.inner.hi - BytePos(1)));
+            let mod_lo = self.codemap.span_after(source!(self, s), "{");
+            let body_snippet =
+                self.snippet(codemap::mk_sp(mod_lo, source!(self, m.inner).hi - BytePos(1)));
             let body_snippet = body_snippet.trim();
             if body_snippet.is_empty() {
                 self.buffer.push_str("}");
@@ -459,13 +544,13 @@ fn format_mod(&mut self, m: &ast::Mod, vis: ast::Visibility, s: Span, ident: ast
                 self.last_pos = mod_lo;
                 self.block_indent = self.block_indent.block_indent(self.config);
                 self.walk_mod_items(m);
-                self.format_missing_with_indent(m.inner.hi - BytePos(1));
+                self.format_missing_with_indent(source!(self, m.inner).hi - BytePos(1));
                 self.close_block();
             }
-            self.last_pos = m.inner.hi;
+            self.last_pos = source!(self, m.inner).hi;
         } else {
             self.buffer.push_str(";");
-            self.last_pos = s.hi;
+            self.last_pos = source!(self, s).hi;
         }
     }
 
@@ -474,38 +559,7 @@ pub fn format_separate_mod(&mut self, m: &ast::Mod) {
         self.last_pos = filemap.start_pos;
         self.block_indent = Indent::empty();
         self.walk_mod_items(m);
-        self.format_missing(filemap.end_pos);
-    }
-
-    fn format_import(&mut self, vis: ast::Visibility, vp: &ast::ViewPath, span: Span) {
-        let vis = utils::format_visibility(vis);
-        let mut offset = self.block_indent;
-        offset.alignment += vis.len() + "use ".len();
-        // 1 = ";"
-        match vp.rewrite(&self.get_context(),
-                         self.config.max_width - offset.width() - 1,
-                         offset) {
-            Some(ref s) if s.is_empty() => {
-                // Format up to last newline
-                let prev_span = codemap::mk_sp(self.last_pos, span.lo);
-                let span_end = match self.snippet(prev_span).rfind('\n') {
-                    Some(offset) => self.last_pos + BytePos(offset as u32),
-                    None => span.lo,
-                };
-                self.format_missing(span_end);
-                self.last_pos = span.hi;
-            }
-            Some(ref s) => {
-                let s = format!("{}use {};", vis, s);
-                self.format_missing_with_indent(span.lo);
-                self.buffer.push_str(&s);
-                self.last_pos = span.hi;
-            }
-            None => {
-                self.format_missing_with_indent(span.lo);
-                self.format_missing(span.hi);
-            }
-        }
+        self.format_missing_with_indent(filemap.end_pos);
     }
 
     pub fn get_context(&self) -> RewriteContext {
@@ -513,21 +567,20 @@ pub fn get_context(&self) -> RewriteContext {
             parse_session: self.parse_session,
             codemap: self.codemap,
             config: self.config,
-            block_indent: self.block_indent,
         }
     }
 }
 
 impl<'a> Rewrite for [ast::Attribute] {
-    fn rewrite(&self, context: &RewriteContext, _: usize, offset: Indent) -> Option<String> {
+    fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option<String> {
         let mut result = String::new();
         if self.is_empty() {
             return Some(result);
         }
-        let indent = offset.to_string(context.config);
+        let indent = shape.indent.to_string(context.config);
 
         for (i, a) in self.iter().enumerate() {
-            let a_str = context.snippet(a.span);
+            let mut a_str = context.snippet(a.span);
 
             // Write comments and blank lines between attributes.
             if i > 0 {
@@ -540,9 +593,10 @@ fn rewrite(&self, context: &RewriteContext, _: usize, offset: Indent) -> Option<
                 if !comment.is_empty() {
                     let comment = try_opt!(rewrite_comment(comment,
                                                            false,
-                                                           context.config.max_width -
-                                                           offset.width(),
-                                                           offset,
+                                                           Shape::legacy(context.config
+                                                                             .comment_width -
+                                                                         shape.indent.width(),
+                                                                         shape.indent),
                                                            context.config));
                     result.push_str(&indent);
                     result.push_str(&comment);
@@ -553,6 +607,15 @@ fn rewrite(&self, context: &RewriteContext, _: usize, offset: Indent) -> Option<
                 result.push_str(&indent);
             }
 
+            if a_str.starts_with("//") {
+                a_str = try_opt!(rewrite_comment(&a_str,
+                                                 false,
+                                                 Shape::legacy(context.config.comment_width -
+                                                               shape.indent.width(),
+                                                               shape.indent),
+                                                 context.config));
+            }
+
             // Write the attribute itself.
             result.push_str(&a_str);