// 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, WriteMode};
+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,
// FIXME: use an RAII util or closure for indenting
pub block_indent: Indent,
pub config: &'a Config,
- pub write_mode: Option<WriteMode>,
}
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);
}
}
}
// 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
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));
}
}
_ => {
if self.visit_attrs(&item.attrs) {
+ self.push_rewrite(item.span, None);
return;
}
}
}
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(..) => {
- self.format_missing_with_indent(item.span.lo);
- let snippet = self.snippet(item.span);
- self.buffer.push_str(&snippet);
- self.last_pos = item.span.hi;
- // FIXME: we cannot format these yet, because of a bad span.
- // See rust lang issue #28424.
+ 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.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);
-
- if let Some(res) = rewrite {
- self.buffer.push_str(&res);
- self.last_pos = span.hi;
- }
+ 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 = source!(self, span).hi;
}
- pub fn from_codemap(parse_session: &'a ParseSess,
- config: &'a Config,
- mode: Option<WriteMode>)
- -> FmtVisitor<'a> {
+ pub fn from_codemap(parse_session: &'a ParseSess, config: &'a Config) -> FmtVisitor<'a> {
FmtVisitor {
parse_session: parse_session,
codemap: parse_session.codemap(),
alignment: 0,
},
config: config,
- write_mode: mode,
}
}
}
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(" {");
- self.last_pos = ::utils::span_after(s, "{", self.codemap);
- 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.close_block();
- self.last_pos = m.inner.hi;
+ // Hackery to account for the closing }.
+ 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("}");
+ } else {
+ 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(source!(self, m.inner).hi - BytePos(1));
+ self.close_block();
+ }
+ 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;
}
}
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 {
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 {
let comment = context.snippet(codemap::mk_sp(self[i - 1].span.hi, a.span.lo));
// This particular horror show is to preserve line breaks in between doc
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);
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);
if i < self.len() - 1 {