]> git.lizzy.rs Git - rust.git/blob - src/items.rs
Merge pull request #2682 from topecongiro/issue-2670
[rust.git] / src / items.rs
1 // Copyright 2015 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
4 //
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
10
11 // Formatting top-level items - functions, structs, enums, traits, impls.
12
13 use std::borrow::Cow;
14 use std::cmp::{min, Ordering};
15
16 use config::lists::*;
17 use regex::Regex;
18 use rustc_target::spec::abi;
19 use syntax::codemap::{self, BytePos, Span};
20 use syntax::visit;
21 use syntax::{ast, ptr, symbol};
22
23 use codemap::{LineRangeUtils, SpanUtils};
24 use comment::{
25     combine_strs_with_missing_comments, contains_comment, recover_comment_removed,
26     recover_missing_comment_in_span, rewrite_missing_comment, FindUncommented,
27 };
28 use config::{BraceStyle, Config, Density, IndentStyle};
29 use expr::{
30     format_expr, is_empty_block, is_simple_block_stmt, rewrite_assign_rhs, rewrite_assign_rhs_with,
31     ExprType, RhsTactics,
32 };
33 use lists::{definitive_tactic, itemize_list, write_list, ListFormatting, ListItem, Separator};
34 use macros::{rewrite_macro, MacroPosition};
35 use overflow;
36 use rewrite::{Rewrite, RewriteContext};
37 use shape::{Indent, Shape};
38 use spanned::Spanned;
39 use types::TraitTyParamBounds;
40 use utils::*;
41 use vertical::rewrite_with_alignment;
42 use visitor::FmtVisitor;
43
44 const DEFAULT_VISIBILITY: ast::Visibility = codemap::Spanned {
45     node: ast::VisibilityKind::Inherited,
46     span: codemap::DUMMY_SP,
47 };
48
49 fn type_annotation_separator(config: &Config) -> &str {
50     colon_spaces(config.space_before_colon(), config.space_after_colon())
51 }
52
53 // Statements of the form
54 // let pat: ty = init;
55 impl Rewrite for ast::Local {
56     fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option<String> {
57         debug!(
58             "Local::rewrite {:?} {} {:?}",
59             self, shape.width, shape.indent
60         );
61
62         skip_out_of_file_lines_range!(context, self.span);
63
64         if contains_skip(&self.attrs) {
65             return None;
66         }
67
68         let attrs_str = self.attrs.rewrite(context, shape)?;
69         let mut result = if attrs_str.is_empty() {
70             "let ".to_owned()
71         } else {
72             combine_strs_with_missing_comments(
73                 context,
74                 &attrs_str,
75                 "let ",
76                 mk_sp(
77                     self.attrs.last().map(|a| a.span.hi()).unwrap(),
78                     self.span.lo(),
79                 ),
80                 shape,
81                 false,
82             )?
83         };
84
85         // 4 = "let ".len()
86         let pat_shape = shape.offset_left(4)?;
87         // 1 = ;
88         let pat_shape = pat_shape.sub_width(1)?;
89         let pat_str = self.pat.rewrite(context, pat_shape)?;
90         result.push_str(&pat_str);
91
92         // String that is placed within the assignment pattern and expression.
93         let infix = {
94             let mut infix = String::with_capacity(32);
95
96             if let Some(ref ty) = self.ty {
97                 let separator = type_annotation_separator(context.config);
98                 let indent = shape.indent + last_line_width(&result) + separator.len();
99                 // 1 = ;
100                 let budget = shape.width.checked_sub(indent.width() + 1)?;
101                 let rewrite = ty.rewrite(context, Shape::legacy(budget, indent))?;
102
103                 infix.push_str(separator);
104                 infix.push_str(&rewrite);
105             }
106
107             if self.init.is_some() {
108                 infix.push_str(" =");
109             }
110
111             infix
112         };
113
114         result.push_str(&infix);
115
116         if let Some(ref ex) = self.init {
117             // 1 = trailing semicolon;
118             let nested_shape = shape.sub_width(1)?;
119
120             result = rewrite_assign_rhs(context, result, &**ex, nested_shape)?;
121         }
122
123         result.push(';');
124         Some(result)
125     }
126 }
127
128 // TODO convert to using rewrite style rather than visitor
129 // TODO format modules in this style
130 #[allow(dead_code)]
131 struct Item<'a> {
132     keyword: &'static str,
133     abi: Cow<'static, str>,
134     vis: Option<&'a ast::Visibility>,
135     body: Vec<BodyElement<'a>>,
136     span: Span,
137 }
138
139 impl<'a> Item<'a> {
140     fn from_foreign_mod(fm: &'a ast::ForeignMod, span: Span, config: &Config) -> Item<'a> {
141         Item {
142             keyword: "",
143             abi: format_abi(fm.abi, config.force_explicit_abi(), true),
144             vis: None,
145             body: fm.items
146                 .iter()
147                 .map(|i| BodyElement::ForeignItem(i))
148                 .collect(),
149             span,
150         }
151     }
152 }
153
154 enum BodyElement<'a> {
155     // Stmt(&'a ast::Stmt),
156     // Field(&'a ast::Field),
157     // Variant(&'a ast::Variant),
158     // Item(&'a ast::Item),
159     ForeignItem(&'a ast::ForeignItem),
160 }
161
162 /// Represents a fn's signature.
163 pub struct FnSig<'a> {
164     decl: &'a ast::FnDecl,
165     generics: &'a ast::Generics,
166     abi: abi::Abi,
167     constness: ast::Constness,
168     defaultness: ast::Defaultness,
169     unsafety: ast::Unsafety,
170     visibility: ast::Visibility,
171 }
172
173 impl<'a> FnSig<'a> {
174     pub fn new(
175         decl: &'a ast::FnDecl,
176         generics: &'a ast::Generics,
177         vis: ast::Visibility,
178     ) -> FnSig<'a> {
179         FnSig {
180             decl,
181             generics,
182             abi: abi::Abi::Rust,
183             constness: ast::Constness::NotConst,
184             defaultness: ast::Defaultness::Final,
185             unsafety: ast::Unsafety::Normal,
186             visibility: vis,
187         }
188     }
189
190     pub fn from_method_sig(
191         method_sig: &'a ast::MethodSig,
192         generics: &'a ast::Generics,
193     ) -> FnSig<'a> {
194         FnSig {
195             unsafety: method_sig.unsafety,
196             constness: method_sig.constness.node,
197             defaultness: ast::Defaultness::Final,
198             abi: method_sig.abi,
199             decl: &*method_sig.decl,
200             generics,
201             visibility: DEFAULT_VISIBILITY,
202         }
203     }
204
205     pub fn from_fn_kind(
206         fn_kind: &'a visit::FnKind,
207         generics: &'a ast::Generics,
208         decl: &'a ast::FnDecl,
209         defaultness: ast::Defaultness,
210     ) -> FnSig<'a> {
211         match *fn_kind {
212             visit::FnKind::ItemFn(_, unsafety, constness, abi, visibility, _) => FnSig {
213                 decl,
214                 generics,
215                 abi,
216                 constness: constness.node,
217                 defaultness,
218                 unsafety,
219                 visibility: visibility.clone(),
220             },
221             visit::FnKind::Method(_, method_sig, vis, _) => {
222                 let mut fn_sig = FnSig::from_method_sig(method_sig, generics);
223                 fn_sig.defaultness = defaultness;
224                 if let Some(vis) = vis {
225                     fn_sig.visibility = vis.clone();
226                 }
227                 fn_sig
228             }
229             _ => unreachable!(),
230         }
231     }
232
233     fn to_str(&self, context: &RewriteContext) -> String {
234         let mut result = String::with_capacity(128);
235         // Vis defaultness constness unsafety abi.
236         result.push_str(&*format_visibility(&self.visibility));
237         result.push_str(format_defaultness(self.defaultness));
238         result.push_str(format_constness(self.constness));
239         result.push_str(format_unsafety(self.unsafety));
240         result.push_str(&format_abi(
241             self.abi,
242             context.config.force_explicit_abi(),
243             false,
244         ));
245         result
246     }
247 }
248
249 impl<'a> FmtVisitor<'a> {
250     fn format_item(&mut self, item: &Item) {
251         self.buffer.push_str(&item.abi);
252
253         let snippet = self.snippet(item.span);
254         let brace_pos = snippet.find_uncommented("{").unwrap();
255
256         self.push_str("{");
257         if !item.body.is_empty() || contains_comment(&snippet[brace_pos..]) {
258             // FIXME: this skips comments between the extern keyword and the opening
259             // brace.
260             self.last_pos = item.span.lo() + BytePos(brace_pos as u32 + 1);
261             self.block_indent = self.block_indent.block_indent(self.config);
262
263             if item.body.is_empty() {
264                 self.format_missing_no_indent(item.span.hi() - BytePos(1));
265                 self.block_indent = self.block_indent.block_unindent(self.config);
266                 let indent_str = self.block_indent.to_string(self.config);
267                 self.push_str(&indent_str);
268             } else {
269                 for item in &item.body {
270                     self.format_body_element(item);
271                 }
272
273                 self.block_indent = self.block_indent.block_unindent(self.config);
274                 self.format_missing_with_indent(item.span.hi() - BytePos(1));
275             }
276         }
277
278         self.push_str("}");
279         self.last_pos = item.span.hi();
280     }
281
282     fn format_body_element(&mut self, element: &BodyElement) {
283         match *element {
284             BodyElement::ForeignItem(item) => self.format_foreign_item(item),
285         }
286     }
287
288     pub fn format_foreign_mod(&mut self, fm: &ast::ForeignMod, span: Span) {
289         let item = Item::from_foreign_mod(fm, span, self.config);
290         self.format_item(&item);
291     }
292
293     fn format_foreign_item(&mut self, item: &ast::ForeignItem) {
294         let rewrite = item.rewrite(&self.get_context(), self.shape());
295         self.push_rewrite(item.span(), rewrite);
296         self.last_pos = item.span.hi();
297     }
298
299     pub fn rewrite_fn(
300         &mut self,
301         indent: Indent,
302         ident: ast::Ident,
303         fn_sig: &FnSig,
304         span: Span,
305         block: &ast::Block,
306         inner_attrs: Option<&[ast::Attribute]>,
307     ) -> Option<String> {
308         let context = self.get_context();
309
310         let mut newline_brace = newline_for_brace(self.config, &fn_sig.generics.where_clause);
311
312         let (mut result, force_newline_brace) =
313             rewrite_fn_base(&context, indent, ident, fn_sig, span, newline_brace, true)?;
314
315         // 2 = ` {`
316         if self.config.brace_style() == BraceStyle::AlwaysNextLine
317             || force_newline_brace
318             || last_line_width(&result) + 2 > self.shape().width
319         {
320             newline_brace = true;
321         } else if !result.contains('\n') {
322             newline_brace = false;
323         }
324
325         // Prepare for the function body by possibly adding a newline and
326         // indent.
327         // FIXME we'll miss anything between the end of the signature and the
328         // start of the body, but we need more spans from the compiler to solve
329         // this.
330         if newline_brace {
331             result.push_str(&indent.to_string_with_newline(self.config));
332         } else {
333             result.push(' ');
334         }
335
336         self.single_line_fn(&result, block, inner_attrs)
337             .or_else(|| Some(result))
338     }
339
340     pub fn rewrite_required_fn(
341         &mut self,
342         indent: Indent,
343         ident: ast::Ident,
344         sig: &ast::MethodSig,
345         generics: &ast::Generics,
346         span: Span,
347     ) -> Option<String> {
348         // Drop semicolon or it will be interpreted as comment.
349         let span = mk_sp(span.lo(), span.hi() - BytePos(1));
350         let context = self.get_context();
351
352         let (mut result, _) = rewrite_fn_base(
353             &context,
354             indent,
355             ident,
356             &FnSig::from_method_sig(sig, generics),
357             span,
358             false,
359             false,
360         )?;
361
362         // Re-attach semicolon
363         result.push(';');
364
365         Some(result)
366     }
367
368     fn single_line_fn(
369         &self,
370         fn_str: &str,
371         block: &ast::Block,
372         inner_attrs: Option<&[ast::Attribute]>,
373     ) -> Option<String> {
374         if fn_str.contains('\n') || inner_attrs.map_or(false, |a| !a.is_empty()) {
375             return None;
376         }
377
378         let codemap = self.get_context().codemap;
379
380         if self.config.empty_item_single_line()
381             && is_empty_block(block, None, codemap)
382             && self.block_indent.width() + fn_str.len() + 2 <= self.config.max_width()
383         {
384             return Some(format!("{}{{}}", fn_str));
385         }
386
387         if self.config.fn_single_line() && is_simple_block_stmt(block, None, codemap) {
388             let rewrite = {
389                 if let Some(stmt) = block.stmts.first() {
390                     match stmt_expr(stmt) {
391                         Some(e) => {
392                             let suffix = if semicolon_for_expr(&self.get_context(), e) {
393                                 ";"
394                             } else {
395                                 ""
396                             };
397
398                             format_expr(e, ExprType::Statement, &self.get_context(), self.shape())
399                                 .map(|s| s + suffix)
400                                 .or_else(|| Some(self.snippet(e.span).to_owned()))
401                         }
402                         None => stmt.rewrite(&self.get_context(), self.shape()),
403                     }
404                 } else {
405                     None
406                 }
407             };
408
409             if let Some(res) = rewrite {
410                 let width = self.block_indent.width() + fn_str.len() + res.len() + 4;
411                 if !res.contains('\n') && width <= self.config.max_width() {
412                     return Some(format!("{}{{ {} }}", fn_str, res));
413                 }
414             }
415         }
416
417         None
418     }
419
420     pub fn visit_static(&mut self, static_parts: &StaticParts) {
421         let rewrite = rewrite_static(&self.get_context(), static_parts, self.block_indent);
422         self.push_rewrite(static_parts.span, rewrite);
423     }
424
425     pub fn visit_struct(&mut self, struct_parts: &StructParts) {
426         let is_tuple = struct_parts.def.is_tuple();
427         let rewrite = format_struct(&self.get_context(), struct_parts, self.block_indent, None)
428             .map(|s| if is_tuple { s + ";" } else { s });
429         self.push_rewrite(struct_parts.span, rewrite);
430     }
431
432     pub fn visit_enum(
433         &mut self,
434         ident: ast::Ident,
435         vis: &ast::Visibility,
436         enum_def: &ast::EnumDef,
437         generics: &ast::Generics,
438         span: Span,
439     ) {
440         let enum_header = format_header("enum ", ident, vis);
441         self.push_str(&enum_header);
442
443         let enum_snippet = self.snippet(span);
444         let brace_pos = enum_snippet.find_uncommented("{").unwrap();
445         let body_start = span.lo() + BytePos(brace_pos as u32 + 1);
446         let generics_str = format_generics(
447             &self.get_context(),
448             generics,
449             self.config.brace_style(),
450             if enum_def.variants.is_empty() {
451                 BracePos::ForceSameLine
452             } else {
453                 BracePos::Auto
454             },
455             self.block_indent,
456             mk_sp(span.lo(), body_start),
457             last_line_width(&enum_header),
458         ).unwrap();
459         self.push_str(&generics_str);
460
461         self.last_pos = body_start;
462
463         match self.format_variant_list(enum_def, body_start, span.hi()) {
464             Some(ref s) if enum_def.variants.is_empty() => self.push_str(s),
465             rw => {
466                 self.push_rewrite(mk_sp(body_start, span.hi()), rw);
467                 self.block_indent = self.block_indent.block_unindent(self.config);
468             }
469         }
470     }
471
472     // Format the body of an enum definition
473     fn format_variant_list(
474         &mut self,
475         enum_def: &ast::EnumDef,
476         body_lo: BytePos,
477         body_hi: BytePos,
478     ) -> Option<String> {
479         if enum_def.variants.is_empty() {
480             let mut buffer = String::with_capacity(128);
481             // 1 = "}"
482             let span = mk_sp(body_lo, body_hi - BytePos(1));
483             format_empty_struct_or_tuple(
484                 &self.get_context(),
485                 span,
486                 self.block_indent,
487                 &mut buffer,
488                 "",
489                 "}",
490             );
491             return Some(buffer);
492         }
493         let mut result = String::with_capacity(1024);
494         let original_offset = self.block_indent;
495         self.block_indent = self.block_indent.block_indent(self.config);
496
497         let itemize_list_with = |one_line_width: usize| {
498             itemize_list(
499                 self.snippet_provider,
500                 enum_def.variants.iter(),
501                 "}",
502                 ",",
503                 |f| {
504                     if !f.node.attrs.is_empty() {
505                         f.node.attrs[0].span.lo()
506                     } else {
507                         f.span.lo()
508                     }
509                 },
510                 |f| f.span.hi(),
511                 |f| self.format_variant(f, one_line_width),
512                 body_lo,
513                 body_hi,
514                 false,
515             ).collect()
516         };
517         let mut items: Vec<_> =
518             itemize_list_with(self.config.width_heuristics().struct_variant_width);
519         // If one of the variants use multiple lines, use multi-lined formatting for all variants.
520         let has_multiline_variant = items.iter().any(|item| item.inner_as_ref().contains('\n'));
521         let has_single_line_variant = items.iter().any(|item| !item.inner_as_ref().contains('\n'));
522         if has_multiline_variant && has_single_line_variant {
523             items = itemize_list_with(0);
524         }
525
526         let shape = self.shape().sub_width(2)?;
527         let fmt = ListFormatting {
528             tactic: DefinitiveListTactic::Vertical,
529             separator: ",",
530             trailing_separator: self.config.trailing_comma(),
531             separator_place: SeparatorPlace::Back,
532             shape,
533             ends_with_newline: true,
534             preserve_newline: true,
535             config: self.config,
536         };
537
538         let list = write_list(&items, &fmt)?;
539         result.push_str(&list);
540         result.push_str(&original_offset.to_string_with_newline(self.config));
541         result.push('}');
542         Some(result)
543     }
544
545     // Variant of an enum.
546     fn format_variant(&self, field: &ast::Variant, one_line_width: usize) -> Option<String> {
547         if contains_skip(&field.node.attrs) {
548             let lo = field.node.attrs[0].span.lo();
549             let span = mk_sp(lo, field.span.hi());
550             return Some(self.snippet(span).to_owned());
551         }
552
553         let context = self.get_context();
554         // 1 = ','
555         let shape = self.shape().sub_width(1)?;
556         let attrs_str = field.node.attrs.rewrite(&context, shape)?;
557         let lo = field
558             .node
559             .attrs
560             .last()
561             .map_or(field.span.lo(), |attr| attr.span.hi());
562         let span = mk_sp(lo, field.span.lo());
563
564         let variant_body = match field.node.data {
565             ast::VariantData::Tuple(..) | ast::VariantData::Struct(..) => format_struct(
566                 &context,
567                 &StructParts::from_variant(field),
568                 self.block_indent,
569                 Some(one_line_width),
570             )?,
571             ast::VariantData::Unit(..) => {
572                 if let Some(ref expr) = field.node.disr_expr {
573                     let lhs = format!("{} =", field.node.ident.name);
574                     rewrite_assign_rhs(&context, lhs, &**expr, shape)?
575                 } else {
576                     field.node.ident.name.to_string()
577                 }
578             }
579         };
580
581         combine_strs_with_missing_comments(&context, &attrs_str, &variant_body, span, shape, false)
582     }
583
584     fn visit_impl_items(&mut self, items: &[ast::ImplItem]) {
585         if self.get_context().config.reorder_impl_items() {
586             // Create visitor for each items, then reorder them.
587             let mut buffer = vec![];
588             for item in items {
589                 self.visit_impl_item(item);
590                 buffer.push((self.buffer.clone(), item.clone()));
591                 self.buffer.clear();
592             }
593             // type -> const -> macro -> method
594             use ast::ImplItemKind::*;
595             fn need_empty_line(a: &ast::ImplItemKind, b: &ast::ImplItemKind) -> bool {
596                 match (a, b) {
597                     (Type(..), Type(..)) | (Const(..), Const(..)) => false,
598                     _ => true,
599                 }
600             }
601
602             buffer.sort_by(|(_, a), (_, b)| match (&a.node, &b.node) {
603                 (Type(..), _) => Ordering::Less,
604                 (_, Type(..)) => Ordering::Greater,
605                 (Const(..), _) => Ordering::Less,
606                 (_, Const(..)) => Ordering::Greater,
607                 (Macro(..), _) => Ordering::Less,
608                 (_, Macro(..)) => Ordering::Greater,
609                 _ => a.span.lo().cmp(&b.span.lo()),
610             });
611             let mut prev_kind = None;
612             for (buf, item) in buffer {
613                 // Make sure that there are at least a single empty line between
614                 // different impl items.
615                 if prev_kind
616                     .as_ref()
617                     .map_or(false, |prev_kind| need_empty_line(prev_kind, &item.node))
618                 {
619                     self.push_str("\n");
620                 }
621                 let indent_str = self.block_indent.to_string_with_newline(self.config);
622                 self.push_str(&indent_str);
623                 self.push_str(buf.trim());
624                 prev_kind = Some(item.node.clone());
625             }
626         } else {
627             for item in items {
628                 self.visit_impl_item(item);
629             }
630         }
631     }
632 }
633
634 pub fn format_impl(
635     context: &RewriteContext,
636     item: &ast::Item,
637     offset: Indent,
638     where_span_end: Option<BytePos>,
639 ) -> Option<String> {
640     if let ast::ItemKind::Impl(_, _, _, ref generics, _, ref self_ty, ref items) = item.node {
641         let mut result = String::with_capacity(128);
642         let ref_and_type = format_impl_ref_and_type(context, item, offset)?;
643         let sep = offset.to_string_with_newline(context.config);
644         result.push_str(&ref_and_type);
645
646         let where_budget = if result.contains('\n') {
647             context.config.max_width()
648         } else {
649             context.budget(last_line_width(&result))
650         };
651         let option = WhereClauseOption::snuggled(&ref_and_type);
652         let where_clause_str = rewrite_where_clause(
653             context,
654             &generics.where_clause,
655             context.config.brace_style(),
656             Shape::legacy(where_budget, offset.block_only()),
657             Density::Vertical,
658             "{",
659             where_span_end,
660             self_ty.span.hi(),
661             option,
662             false,
663         )?;
664
665         // If there is no where clause, we may have missing comments between the trait name and
666         // the opening brace.
667         if generics.where_clause.predicates.is_empty() {
668             if let Some(hi) = where_span_end {
669                 match recover_missing_comment_in_span(
670                     mk_sp(self_ty.span.hi(), hi),
671                     Shape::indented(offset, context.config),
672                     context,
673                     last_line_width(&result),
674                 ) {
675                     Some(ref missing_comment) if !missing_comment.is_empty() => {
676                         result.push_str(missing_comment);
677                     }
678                     _ => (),
679                 }
680             }
681         }
682
683         if is_impl_single_line(context, items, &result, &where_clause_str, item)? {
684             result.push_str(&where_clause_str);
685             if where_clause_str.contains('\n') || last_line_contains_single_line_comment(&result) {
686                 result.push_str(&format!("{}{{{}}}", &sep, &sep));
687             } else {
688                 result.push_str(" {}");
689             }
690             return Some(result);
691         }
692
693         if !where_clause_str.is_empty() && !where_clause_str.contains('\n') {
694             let width = offset.block_indent + context.config.tab_spaces() - 1;
695             let where_indent = Indent::new(0, width);
696             result.push_str(&where_indent.to_string_with_newline(context.config));
697         }
698         result.push_str(&where_clause_str);
699
700         let need_newline = last_line_contains_single_line_comment(&result) || result.contains('\n');
701         match context.config.brace_style() {
702             _ if need_newline => result.push_str(&sep),
703             BraceStyle::AlwaysNextLine => result.push_str(&sep),
704             BraceStyle::PreferSameLine => result.push(' '),
705             BraceStyle::SameLineWhere => {
706                 if !where_clause_str.is_empty() {
707                     result.push_str(&sep);
708                 } else {
709                     result.push(' ');
710                 }
711             }
712         }
713
714         result.push('{');
715
716         let snippet = context.snippet(item.span);
717         let open_pos = snippet.find_uncommented("{")? + 1;
718
719         if !items.is_empty() || contains_comment(&snippet[open_pos..]) {
720             let mut visitor = FmtVisitor::from_context(context);
721             let item_indent = offset.block_only().block_indent(context.config);
722             visitor.block_indent = item_indent;
723             visitor.last_pos = item.span.lo() + BytePos(open_pos as u32);
724
725             visitor.visit_attrs(&item.attrs, ast::AttrStyle::Inner);
726             visitor.visit_impl_items(items);
727
728             visitor.format_missing(item.span.hi() - BytePos(1));
729
730             let inner_indent_str = visitor.block_indent.to_string_with_newline(context.config);
731             let outer_indent_str = offset.block_only().to_string_with_newline(context.config);
732
733             result.push_str(&inner_indent_str);
734             result.push_str(visitor.buffer.to_string().trim());
735             result.push_str(&outer_indent_str);
736         }
737
738         if result.ends_with('{') {
739             result.push_str(&sep);
740         }
741         result.push('}');
742
743         Some(result)
744     } else {
745         unreachable!();
746     }
747 }
748
749 fn is_impl_single_line(
750     context: &RewriteContext,
751     items: &[ast::ImplItem],
752     result: &str,
753     where_clause_str: &str,
754     item: &ast::Item,
755 ) -> Option<bool> {
756     let snippet = context.snippet(item.span);
757     let open_pos = snippet.find_uncommented("{")? + 1;
758
759     Some(
760         context.config.empty_item_single_line()
761             && items.is_empty()
762             && !result.contains('\n')
763             && result.len() + where_clause_str.len() <= context.config.max_width()
764             && !contains_comment(&snippet[open_pos..]),
765     )
766 }
767
768 fn format_impl_ref_and_type(
769     context: &RewriteContext,
770     item: &ast::Item,
771     offset: Indent,
772 ) -> Option<String> {
773     if let ast::ItemKind::Impl(
774         unsafety,
775         polarity,
776         defaultness,
777         ref generics,
778         ref trait_ref,
779         ref self_ty,
780         _,
781     ) = item.node
782     {
783         let mut result = String::with_capacity(128);
784
785         result.push_str(&format_visibility(&item.vis));
786         result.push_str(format_defaultness(defaultness));
787         result.push_str(format_unsafety(unsafety));
788
789         let lo = context.snippet_provider.span_after(item.span, "impl");
790         let hi = match *trait_ref {
791             Some(ref tr) => tr.path.span.lo(),
792             None => self_ty.span.lo(),
793         };
794         let shape = generics_shape_from_config(
795             context.config,
796             Shape::indented(offset + last_line_width(&result), context.config),
797             0,
798         )?;
799         let generics_str = rewrite_generics(context, "impl", generics, shape, mk_sp(lo, hi))?;
800         result.push_str(&generics_str);
801
802         let polarity_str = if polarity == ast::ImplPolarity::Negative {
803             "!"
804         } else {
805             ""
806         };
807
808         if let Some(ref trait_ref) = *trait_ref {
809             let result_len = last_line_width(&result);
810             result.push_str(&rewrite_trait_ref(
811                 context,
812                 trait_ref,
813                 offset,
814                 polarity_str,
815                 result_len,
816             )?);
817         }
818
819         // Try to put the self type in a single line.
820         // ` for`
821         let trait_ref_overhead = if trait_ref.is_some() { 4 } else { 0 };
822         let curly_brace_overhead = if generics.where_clause.predicates.is_empty() {
823             // If there is no where clause adapt budget for type formatting to take space and curly
824             // brace into account.
825             match context.config.brace_style() {
826                 BraceStyle::AlwaysNextLine => 0,
827                 _ => 2,
828             }
829         } else {
830             0
831         };
832         let used_space = last_line_width(&result) + trait_ref_overhead + curly_brace_overhead;
833         // 1 = space before the type.
834         let budget = context.budget(used_space + 1);
835         if let Some(self_ty_str) = self_ty.rewrite(context, Shape::legacy(budget, offset)) {
836             if !self_ty_str.contains('\n') {
837                 if trait_ref.is_some() {
838                     result.push_str(" for ");
839                 } else {
840                     result.push(' ');
841                 }
842                 result.push_str(&self_ty_str);
843                 return Some(result);
844             }
845         }
846
847         // Couldn't fit the self type on a single line, put it on a new line.
848         result.push('\n');
849         // Add indentation of one additional tab.
850         let new_line_offset = offset.block_indent(context.config);
851         result.push_str(&new_line_offset.to_string(context.config));
852         if trait_ref.is_some() {
853             result.push_str("for ");
854         }
855         let budget = context.budget(last_line_width(&result));
856         let type_offset = match context.config.indent_style() {
857             IndentStyle::Visual => new_line_offset + trait_ref_overhead,
858             IndentStyle::Block => new_line_offset,
859         };
860         result.push_str(&*self_ty.rewrite(context, Shape::legacy(budget, type_offset))?);
861         Some(result)
862     } else {
863         unreachable!();
864     }
865 }
866
867 fn rewrite_trait_ref(
868     context: &RewriteContext,
869     trait_ref: &ast::TraitRef,
870     offset: Indent,
871     polarity_str: &str,
872     result_len: usize,
873 ) -> Option<String> {
874     // 1 = space between generics and trait_ref
875     let used_space = 1 + polarity_str.len() + result_len;
876     let shape = Shape::indented(offset + used_space, context.config);
877     if let Some(trait_ref_str) = trait_ref.rewrite(context, shape) {
878         if !trait_ref_str.contains('\n') {
879             return Some(format!(" {}{}", polarity_str, &trait_ref_str));
880         }
881     }
882     // We could not make enough space for trait_ref, so put it on new line.
883     let offset = offset.block_indent(context.config);
884     let shape = Shape::indented(offset, context.config);
885     let trait_ref_str = trait_ref.rewrite(context, shape)?;
886     Some(format!(
887         "{}{}{}",
888         &offset.to_string_with_newline(context.config),
889         polarity_str,
890         &trait_ref_str
891     ))
892 }
893
894 pub struct StructParts<'a> {
895     prefix: &'a str,
896     ident: ast::Ident,
897     vis: &'a ast::Visibility,
898     def: &'a ast::VariantData,
899     generics: Option<&'a ast::Generics>,
900     span: Span,
901 }
902
903 impl<'a> StructParts<'a> {
904     fn format_header(&self) -> String {
905         format_header(self.prefix, self.ident, self.vis)
906     }
907
908     fn from_variant(variant: &'a ast::Variant) -> Self {
909         StructParts {
910             prefix: "",
911             ident: variant.node.ident,
912             vis: &DEFAULT_VISIBILITY,
913             def: &variant.node.data,
914             generics: None,
915             span: variant.span,
916         }
917     }
918
919     pub fn from_item(item: &'a ast::Item) -> Self {
920         let (prefix, def, generics) = match item.node {
921             ast::ItemKind::Struct(ref def, ref generics) => ("struct ", def, generics),
922             ast::ItemKind::Union(ref def, ref generics) => ("union ", def, generics),
923             _ => unreachable!(),
924         };
925         StructParts {
926             prefix,
927             ident: item.ident,
928             vis: &item.vis,
929             def,
930             generics: Some(generics),
931             span: item.span,
932         }
933     }
934 }
935
936 fn format_struct(
937     context: &RewriteContext,
938     struct_parts: &StructParts,
939     offset: Indent,
940     one_line_width: Option<usize>,
941 ) -> Option<String> {
942     match *struct_parts.def {
943         ast::VariantData::Unit(..) => format_unit_struct(context, struct_parts, offset),
944         ast::VariantData::Tuple(ref fields, _) => {
945             format_tuple_struct(context, struct_parts, fields, offset)
946         }
947         ast::VariantData::Struct(ref fields, _) => {
948             format_struct_struct(context, struct_parts, fields, offset, one_line_width)
949         }
950     }
951 }
952
953 pub fn format_trait(context: &RewriteContext, item: &ast::Item, offset: Indent) -> Option<String> {
954     if let ast::ItemKind::Trait(
955         is_auto,
956         unsafety,
957         ref generics,
958         ref type_param_bounds,
959         ref trait_items,
960     ) = item.node
961     {
962         let mut result = String::with_capacity(128);
963         let header = format!(
964             "{}{}{}trait ",
965             format_auto(is_auto),
966             format_visibility(&item.vis),
967             format_unsafety(unsafety),
968         );
969         result.push_str(&header);
970
971         let body_lo = context.snippet_provider.span_after(item.span, "{");
972
973         let shape = Shape::indented(offset, context.config).offset_left(result.len())?;
974         let generics_str = rewrite_generics(
975             context,
976             &item.ident.to_string(),
977             generics,
978             shape,
979             mk_sp(item.span.lo(), body_lo),
980         )?;
981         result.push_str(&generics_str);
982
983         // FIXME(#2055): rustfmt fails to format when there are comments between trait bounds.
984         if !type_param_bounds.is_empty() {
985             let ident_hi = context
986                 .snippet_provider
987                 .span_after(item.span, &format!("{}", item.ident));
988             let bound_hi = type_param_bounds.last().unwrap().span().hi();
989             let snippet = context.snippet(mk_sp(ident_hi, bound_hi));
990             if contains_comment(snippet) {
991                 return None;
992             }
993         }
994         if !type_param_bounds.is_empty() {
995             result = rewrite_assign_rhs_with(
996                 context,
997                 result + ":",
998                 &TraitTyParamBounds::new(type_param_bounds),
999                 shape,
1000                 RhsTactics::ForceNextLine,
1001             )?;
1002         }
1003
1004         // Rewrite where clause.
1005         if !generics.where_clause.predicates.is_empty() {
1006             let where_density = if context.config.indent_style() == IndentStyle::Block {
1007                 Density::Compressed
1008             } else {
1009                 Density::Tall
1010             };
1011
1012             let where_budget = context.budget(last_line_width(&result));
1013             let pos_before_where = if type_param_bounds.is_empty() {
1014                 generics.where_clause.span.lo()
1015             } else {
1016                 type_param_bounds[type_param_bounds.len() - 1].span().hi()
1017             };
1018             let option = WhereClauseOption::snuggled(&generics_str);
1019             let where_clause_str = rewrite_where_clause(
1020                 context,
1021                 &generics.where_clause,
1022                 context.config.brace_style(),
1023                 Shape::legacy(where_budget, offset.block_only()),
1024                 where_density,
1025                 "{",
1026                 None,
1027                 pos_before_where,
1028                 option,
1029                 false,
1030             )?;
1031             // If the where clause cannot fit on the same line,
1032             // put the where clause on a new line
1033             if !where_clause_str.contains('\n')
1034                 && last_line_width(&result) + where_clause_str.len() + offset.width()
1035                     > context.config.comment_width()
1036             {
1037                 let width = offset.block_indent + context.config.tab_spaces() - 1;
1038                 let where_indent = Indent::new(0, width);
1039                 result.push_str(&where_indent.to_string_with_newline(context.config));
1040             }
1041             result.push_str(&where_clause_str);
1042         } else {
1043             let item_snippet = context.snippet(item.span);
1044             if let Some(lo) = item_snippet.find('/') {
1045                 // 1 = `{`
1046                 let comment_hi = body_lo - BytePos(1);
1047                 let comment_lo = item.span.lo() + BytePos(lo as u32);
1048                 if comment_lo < comment_hi {
1049                     match recover_missing_comment_in_span(
1050                         mk_sp(comment_lo, comment_hi),
1051                         Shape::indented(offset, context.config),
1052                         context,
1053                         last_line_width(&result),
1054                     ) {
1055                         Some(ref missing_comment) if !missing_comment.is_empty() => {
1056                             result.push_str(missing_comment);
1057                         }
1058                         _ => (),
1059                     }
1060                 }
1061             }
1062         }
1063
1064         match context.config.brace_style() {
1065             _ if last_line_contains_single_line_comment(&result)
1066                 || last_line_width(&result) + 2 > context.budget(offset.width()) =>
1067             {
1068                 result.push_str(&offset.to_string_with_newline(context.config));
1069             }
1070             BraceStyle::AlwaysNextLine => {
1071                 result.push_str(&offset.to_string_with_newline(context.config));
1072             }
1073             BraceStyle::PreferSameLine => result.push(' '),
1074             BraceStyle::SameLineWhere => {
1075                 if result.contains('\n')
1076                     || (!generics.where_clause.predicates.is_empty() && !trait_items.is_empty())
1077                 {
1078                     result.push_str(&offset.to_string_with_newline(context.config));
1079                 } else {
1080                     result.push(' ');
1081                 }
1082             }
1083         }
1084         result.push('{');
1085
1086         let snippet = context.snippet(item.span);
1087         let open_pos = snippet.find_uncommented("{")? + 1;
1088
1089         if !trait_items.is_empty() || contains_comment(&snippet[open_pos..]) {
1090             let mut visitor = FmtVisitor::from_context(context);
1091             visitor.block_indent = offset.block_only().block_indent(context.config);
1092             visitor.last_pos = item.span.lo() + BytePos(open_pos as u32);
1093
1094             for item in trait_items {
1095                 visitor.visit_trait_item(item);
1096             }
1097
1098             visitor.format_missing(item.span.hi() - BytePos(1));
1099
1100             let inner_indent_str = visitor.block_indent.to_string_with_newline(context.config);
1101             let outer_indent_str = offset.block_only().to_string_with_newline(context.config);
1102
1103             result.push_str(&inner_indent_str);
1104             result.push_str(visitor.buffer.to_string().trim());
1105             result.push_str(&outer_indent_str);
1106         } else if result.contains('\n') {
1107             result.push('\n');
1108         }
1109
1110         result.push('}');
1111         Some(result)
1112     } else {
1113         unreachable!();
1114     }
1115 }
1116
1117 pub fn format_trait_alias(
1118     context: &RewriteContext,
1119     ident: ast::Ident,
1120     generics: &ast::Generics,
1121     ty_param_bounds: &ast::TyParamBounds,
1122     shape: Shape,
1123 ) -> Option<String> {
1124     let alias = ident.name.as_str();
1125     // 6 = "trait ", 2 = " ="
1126     let g_shape = shape.offset_left(6)?.sub_width(2)?;
1127     let generics_str = rewrite_generics(context, &alias, generics, g_shape, generics.span)?;
1128     let lhs = format!("trait {} =", generics_str);
1129     // 1 = ";"
1130     rewrite_assign_rhs(context, lhs, ty_param_bounds, shape.sub_width(1)?).map(|s| s + ";")
1131 }
1132
1133 fn format_unit_struct(context: &RewriteContext, p: &StructParts, offset: Indent) -> Option<String> {
1134     let header_str = format_header(p.prefix, p.ident, p.vis);
1135     let generics_str = if let Some(generics) = p.generics {
1136         let hi = if generics.where_clause.predicates.is_empty() {
1137             generics.span.hi()
1138         } else {
1139             generics.where_clause.span.hi()
1140         };
1141         format_generics(
1142             context,
1143             generics,
1144             context.config.brace_style(),
1145             BracePos::None,
1146             offset,
1147             mk_sp(generics.span.lo(), hi),
1148             last_line_width(&header_str),
1149         )?
1150     } else {
1151         String::new()
1152     };
1153     Some(format!("{}{};", header_str, generics_str))
1154 }
1155
1156 pub fn format_struct_struct(
1157     context: &RewriteContext,
1158     struct_parts: &StructParts,
1159     fields: &[ast::StructField],
1160     offset: Indent,
1161     one_line_width: Option<usize>,
1162 ) -> Option<String> {
1163     let mut result = String::with_capacity(1024);
1164     let span = struct_parts.span;
1165
1166     let header_str = struct_parts.format_header();
1167     result.push_str(&header_str);
1168
1169     let header_hi = span.lo() + BytePos(header_str.len() as u32);
1170     let body_lo = context.snippet_provider.span_after(span, "{");
1171
1172     let generics_str = match struct_parts.generics {
1173         Some(g) => format_generics(
1174             context,
1175             g,
1176             context.config.brace_style(),
1177             if fields.is_empty() {
1178                 BracePos::ForceSameLine
1179             } else {
1180                 BracePos::Auto
1181             },
1182             offset,
1183             mk_sp(header_hi, body_lo),
1184             last_line_width(&result),
1185         )?,
1186         None => {
1187             // 3 = ` {}`, 2 = ` {`.
1188             let overhead = if fields.is_empty() { 3 } else { 2 };
1189             if (context.config.brace_style() == BraceStyle::AlwaysNextLine && !fields.is_empty())
1190                 || context.config.max_width() < overhead + result.len()
1191             {
1192                 format!("\n{}{{", offset.block_only().to_string(context.config))
1193             } else {
1194                 " {".to_owned()
1195             }
1196         }
1197     };
1198     // 1 = `}`
1199     let overhead = if fields.is_empty() { 1 } else { 0 };
1200     let total_width = result.len() + generics_str.len() + overhead;
1201     if !generics_str.is_empty()
1202         && !generics_str.contains('\n')
1203         && total_width > context.config.max_width()
1204     {
1205         result.push('\n');
1206         result.push_str(&offset.to_string(context.config));
1207         result.push_str(generics_str.trim_left());
1208     } else {
1209         result.push_str(&generics_str);
1210     }
1211
1212     if fields.is_empty() {
1213         let inner_span = mk_sp(body_lo, span.hi() - BytePos(1));
1214         format_empty_struct_or_tuple(context, inner_span, offset, &mut result, "", "}");
1215         return Some(result);
1216     }
1217
1218     // 3 = ` ` and ` }`
1219     let one_line_budget = context.budget(result.len() + 3 + offset.width());
1220     let one_line_budget =
1221         one_line_width.map_or(0, |one_line_width| min(one_line_width, one_line_budget));
1222
1223     let items_str = rewrite_with_alignment(
1224         fields,
1225         context,
1226         Shape::indented(offset, context.config).sub_width(1)?,
1227         mk_sp(body_lo, span.hi()),
1228         one_line_budget,
1229     )?;
1230
1231     if !items_str.contains('\n')
1232         && !result.contains('\n')
1233         && items_str.len() <= one_line_budget
1234         && !last_line_contains_single_line_comment(&items_str)
1235     {
1236         Some(format!("{} {} }}", result, items_str))
1237     } else {
1238         Some(format!(
1239             "{}\n{}{}\n{}}}",
1240             result,
1241             offset
1242                 .block_indent(context.config)
1243                 .to_string(context.config),
1244             items_str,
1245             offset.to_string(context.config)
1246         ))
1247     }
1248 }
1249
1250 fn get_bytepos_after_visibility(vis: &ast::Visibility, default_span: Span) -> BytePos {
1251     match vis.node {
1252         ast::VisibilityKind::Crate(..) | ast::VisibilityKind::Restricted { .. } => vis.span.hi(),
1253         _ => default_span.lo(),
1254     }
1255 }
1256
1257 // Format tuple or struct without any fields. We need to make sure that the comments
1258 // inside the delimiters are preserved.
1259 fn format_empty_struct_or_tuple(
1260     context: &RewriteContext,
1261     span: Span,
1262     offset: Indent,
1263     result: &mut String,
1264     opener: &str,
1265     closer: &str,
1266 ) {
1267     // 3 = " {}" or "();"
1268     let used_width = last_line_used_width(&result, offset.width()) + 3;
1269     if used_width > context.config.max_width() {
1270         result.push_str(&offset.to_string_with_newline(context.config))
1271     }
1272     result.push_str(opener);
1273     match rewrite_missing_comment(span, Shape::indented(offset, context.config), context) {
1274         Some(ref s) if s.is_empty() => (),
1275         Some(ref s) => {
1276             if !is_single_line(s) || first_line_contains_single_line_comment(s) {
1277                 let nested_indent_str = offset
1278                     .block_indent(context.config)
1279                     .to_string_with_newline(context.config);
1280                 result.push_str(&nested_indent_str);
1281             }
1282             result.push_str(s);
1283             if last_line_contains_single_line_comment(s) {
1284                 result.push_str(&offset.to_string_with_newline(context.config));
1285             }
1286         }
1287         None => result.push_str(context.snippet(span)),
1288     }
1289     result.push_str(closer);
1290 }
1291
1292 fn format_tuple_struct(
1293     context: &RewriteContext,
1294     struct_parts: &StructParts,
1295     fields: &[ast::StructField],
1296     offset: Indent,
1297 ) -> Option<String> {
1298     let mut result = String::with_capacity(1024);
1299     let span = struct_parts.span;
1300
1301     let header_str = struct_parts.format_header();
1302     result.push_str(&header_str);
1303
1304     let body_lo = if fields.is_empty() {
1305         let lo = get_bytepos_after_visibility(struct_parts.vis, span);
1306         context
1307             .snippet_provider
1308             .span_after(mk_sp(lo, span.hi()), "(")
1309     } else {
1310         fields[0].span.lo()
1311     };
1312     let body_hi = if fields.is_empty() {
1313         context
1314             .snippet_provider
1315             .span_after(mk_sp(body_lo, span.hi()), ")")
1316     } else {
1317         // This is a dirty hack to work around a missing `)` from the span of the last field.
1318         let last_arg_span = fields[fields.len() - 1].span;
1319         if context.snippet(last_arg_span).ends_with(')') {
1320             last_arg_span.hi()
1321         } else {
1322             context
1323                 .snippet_provider
1324                 .span_after(mk_sp(last_arg_span.hi(), span.hi()), ")")
1325         }
1326     };
1327
1328     let where_clause_str = match struct_parts.generics {
1329         Some(generics) => {
1330             let budget = context.budget(last_line_width(&header_str));
1331             let shape = Shape::legacy(budget, offset);
1332             let g_span = mk_sp(span.lo(), body_lo);
1333             let generics_str = rewrite_generics(context, "", generics, shape, g_span)?;
1334             result.push_str(&generics_str);
1335
1336             let where_budget = context.budget(last_line_width(&result));
1337             let option = WhereClauseOption::new(true, false);
1338             rewrite_where_clause(
1339                 context,
1340                 &generics.where_clause,
1341                 context.config.brace_style(),
1342                 Shape::legacy(where_budget, offset.block_only()),
1343                 Density::Compressed,
1344                 ";",
1345                 None,
1346                 body_hi,
1347                 option,
1348                 false,
1349             )?
1350         }
1351         None => "".to_owned(),
1352     };
1353
1354     if fields.is_empty() {
1355         let body_hi = context
1356             .snippet_provider
1357             .span_before(mk_sp(body_lo, span.hi()), ")");
1358         let inner_span = mk_sp(body_lo, body_hi);
1359         format_empty_struct_or_tuple(context, inner_span, offset, &mut result, "(", ")");
1360     } else {
1361         let shape = Shape::indented(offset, context.config).sub_width(1)?;
1362         let fields = &fields.iter().collect::<Vec<_>>();
1363         result = overflow::rewrite_with_parens(
1364             context,
1365             &result,
1366             fields,
1367             shape,
1368             span,
1369             context.config.width_heuristics().fn_call_width,
1370             None,
1371         )?;
1372     }
1373
1374     if !where_clause_str.is_empty() && !where_clause_str.contains('\n')
1375         && (result.contains('\n')
1376             || offset.block_indent + result.len() + where_clause_str.len() + 1
1377                 > context.config.max_width())
1378     {
1379         // We need to put the where clause on a new line, but we didn't
1380         // know that earlier, so the where clause will not be indented properly.
1381         result.push('\n');
1382         result
1383             .push_str(&(offset.block_only() + (context.config.tab_spaces() - 1))
1384                 .to_string(context.config));
1385     }
1386     result.push_str(&where_clause_str);
1387
1388     Some(result)
1389 }
1390
1391 pub fn rewrite_type_alias(
1392     context: &RewriteContext,
1393     indent: Indent,
1394     ident: ast::Ident,
1395     ty: &ast::Ty,
1396     generics: &ast::Generics,
1397     vis: &ast::Visibility,
1398     span: Span,
1399 ) -> Option<String> {
1400     let mut result = String::with_capacity(128);
1401
1402     result.push_str(&format_visibility(vis));
1403     result.push_str("type ");
1404
1405     // 2 = `= `
1406     let g_shape = Shape::indented(indent, context.config)
1407         .offset_left(result.len())?
1408         .sub_width(2)?;
1409     let g_span = mk_sp(
1410         context.snippet_provider.span_after(span, "type"),
1411         ty.span.lo(),
1412     );
1413     let generics_str = rewrite_generics(context, &ident.to_string(), generics, g_shape, g_span)?;
1414     result.push_str(&generics_str);
1415
1416     let where_budget = context.budget(last_line_width(&result));
1417     let option = WhereClauseOption::snuggled(&result);
1418     let where_clause_str = rewrite_where_clause(
1419         context,
1420         &generics.where_clause,
1421         context.config.brace_style(),
1422         Shape::legacy(where_budget, indent),
1423         Density::Vertical,
1424         "=",
1425         Some(span.hi()),
1426         generics.span.hi(),
1427         option,
1428         false,
1429     )?;
1430     result.push_str(&where_clause_str);
1431     if where_clause_str.is_empty() {
1432         result.push_str(" =");
1433     } else {
1434         result.push_str(&format!(
1435             "{}=",
1436             indent.to_string_with_newline(context.config)
1437         ));
1438     }
1439
1440     // 1 = ";"
1441     let ty_shape = Shape::indented(indent, context.config).sub_width(1)?;
1442     rewrite_assign_rhs(context, result, ty, ty_shape).map(|s| s + ";")
1443 }
1444
1445 fn type_annotation_spacing(config: &Config) -> (&str, &str) {
1446     (
1447         if config.space_before_colon() { " " } else { "" },
1448         if config.space_after_colon() { " " } else { "" },
1449     )
1450 }
1451
1452 pub fn rewrite_struct_field_prefix(
1453     context: &RewriteContext,
1454     field: &ast::StructField,
1455 ) -> Option<String> {
1456     let vis = format_visibility(&field.vis);
1457     let type_annotation_spacing = type_annotation_spacing(context.config);
1458     Some(match field.ident {
1459         Some(name) => format!("{}{}{}:", vis, name, type_annotation_spacing.0),
1460         None => format!("{}", vis),
1461     })
1462 }
1463
1464 impl Rewrite for ast::StructField {
1465     fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option<String> {
1466         rewrite_struct_field(context, self, shape, 0)
1467     }
1468 }
1469
1470 pub fn rewrite_struct_field(
1471     context: &RewriteContext,
1472     field: &ast::StructField,
1473     shape: Shape,
1474     lhs_max_width: usize,
1475 ) -> Option<String> {
1476     if contains_skip(&field.attrs) {
1477         return Some(context.snippet(field.span()).to_owned());
1478     }
1479
1480     let type_annotation_spacing = type_annotation_spacing(context.config);
1481     let prefix = rewrite_struct_field_prefix(context, field)?;
1482
1483     let attrs_str = field.attrs.rewrite(context, shape)?;
1484     let attrs_extendable = field.ident.is_none() && is_attributes_extendable(&attrs_str);
1485     let missing_span = if field.attrs.is_empty() {
1486         mk_sp(field.span.lo(), field.span.lo())
1487     } else {
1488         mk_sp(field.attrs.last().unwrap().span.hi(), field.span.lo())
1489     };
1490     let mut spacing = String::from(if field.ident.is_some() {
1491         type_annotation_spacing.1
1492     } else {
1493         ""
1494     });
1495     // Try to put everything on a single line.
1496     let attr_prefix = combine_strs_with_missing_comments(
1497         context,
1498         &attrs_str,
1499         &prefix,
1500         missing_span,
1501         shape,
1502         attrs_extendable,
1503     )?;
1504     let overhead = last_line_width(&attr_prefix);
1505     let lhs_offset = lhs_max_width.checked_sub(overhead).unwrap_or(0);
1506     for _ in 0..lhs_offset {
1507         spacing.push(' ');
1508     }
1509     // In this extreme case we will be missing a space betweeen an attribute and a field.
1510     if prefix.is_empty() && !attrs_str.is_empty() && attrs_extendable && spacing.is_empty() {
1511         spacing.push(' ');
1512     }
1513     let orig_ty = shape
1514         .offset_left(overhead + spacing.len())
1515         .and_then(|ty_shape| field.ty.rewrite(context, ty_shape));
1516     if let Some(ref ty) = orig_ty {
1517         if !ty.contains('\n') {
1518             return Some(attr_prefix + &spacing + ty);
1519         }
1520     }
1521
1522     let is_prefix_empty = prefix.is_empty();
1523     // We must use multiline. We are going to put attributes and a field on different lines.
1524     let field_str = rewrite_assign_rhs(context, prefix, &*field.ty, shape)?;
1525     // Remove a leading white-space from `rewrite_assign_rhs()` when rewriting a tuple struct.
1526     let field_str = if is_prefix_empty {
1527         field_str.trim_left()
1528     } else {
1529         &field_str
1530     };
1531     combine_strs_with_missing_comments(context, &attrs_str, field_str, missing_span, shape, false)
1532 }
1533
1534 pub struct StaticParts<'a> {
1535     prefix: &'a str,
1536     vis: &'a ast::Visibility,
1537     ident: ast::Ident,
1538     ty: &'a ast::Ty,
1539     mutability: ast::Mutability,
1540     expr_opt: Option<&'a ptr::P<ast::Expr>>,
1541     defaultness: Option<ast::Defaultness>,
1542     span: Span,
1543 }
1544
1545 impl<'a> StaticParts<'a> {
1546     pub fn from_item(item: &'a ast::Item) -> Self {
1547         let (prefix, ty, mutability, expr) = match item.node {
1548             ast::ItemKind::Static(ref ty, mutability, ref expr) => ("static", ty, mutability, expr),
1549             ast::ItemKind::Const(ref ty, ref expr) => {
1550                 ("const", ty, ast::Mutability::Immutable, expr)
1551             }
1552             _ => unreachable!(),
1553         };
1554         StaticParts {
1555             prefix,
1556             vis: &item.vis,
1557             ident: item.ident,
1558             ty,
1559             mutability,
1560             expr_opt: Some(expr),
1561             defaultness: None,
1562             span: item.span,
1563         }
1564     }
1565
1566     pub fn from_trait_item(ti: &'a ast::TraitItem) -> Self {
1567         let (ty, expr_opt) = match ti.node {
1568             ast::TraitItemKind::Const(ref ty, ref expr_opt) => (ty, expr_opt),
1569             _ => unreachable!(),
1570         };
1571         StaticParts {
1572             prefix: "const",
1573             vis: &DEFAULT_VISIBILITY,
1574             ident: ti.ident,
1575             ty,
1576             mutability: ast::Mutability::Immutable,
1577             expr_opt: expr_opt.as_ref(),
1578             defaultness: None,
1579             span: ti.span,
1580         }
1581     }
1582
1583     pub fn from_impl_item(ii: &'a ast::ImplItem) -> Self {
1584         let (ty, expr) = match ii.node {
1585             ast::ImplItemKind::Const(ref ty, ref expr) => (ty, expr),
1586             _ => unreachable!(),
1587         };
1588         StaticParts {
1589             prefix: "const",
1590             vis: &ii.vis,
1591             ident: ii.ident,
1592             ty,
1593             mutability: ast::Mutability::Immutable,
1594             expr_opt: Some(expr),
1595             defaultness: Some(ii.defaultness),
1596             span: ii.span,
1597         }
1598     }
1599 }
1600
1601 fn rewrite_static(
1602     context: &RewriteContext,
1603     static_parts: &StaticParts,
1604     offset: Indent,
1605 ) -> Option<String> {
1606     let colon = colon_spaces(
1607         context.config.space_before_colon(),
1608         context.config.space_after_colon(),
1609     );
1610     let mut prefix = format!(
1611         "{}{}{} {}{}{}",
1612         format_visibility(static_parts.vis),
1613         static_parts.defaultness.map_or("", format_defaultness),
1614         static_parts.prefix,
1615         format_mutability(static_parts.mutability),
1616         static_parts.ident,
1617         colon,
1618     );
1619     // 2 = " =".len()
1620     let ty_shape =
1621         Shape::indented(offset.block_only(), context.config).offset_left(prefix.len() + 2)?;
1622     let ty_str = match static_parts.ty.rewrite(context, ty_shape) {
1623         Some(ty_str) => ty_str,
1624         None => {
1625             if prefix.ends_with(' ') {
1626                 prefix.pop();
1627             }
1628             let nested_indent = offset.block_indent(context.config);
1629             let nested_shape = Shape::indented(nested_indent, context.config);
1630             let ty_str = static_parts.ty.rewrite(context, nested_shape)?;
1631             format!(
1632                 "{}{}",
1633                 nested_indent.to_string_with_newline(context.config),
1634                 ty_str
1635             )
1636         }
1637     };
1638
1639     if let Some(expr) = static_parts.expr_opt {
1640         let lhs = format!("{}{} =", prefix, ty_str);
1641         // 1 = ;
1642         let remaining_width = context.budget(offset.block_indent + 1);
1643         rewrite_assign_rhs(
1644             context,
1645             lhs,
1646             &**expr,
1647             Shape::legacy(remaining_width, offset.block_only()),
1648         ).and_then(|res| recover_comment_removed(res, static_parts.span, context))
1649             .map(|s| if s.ends_with(';') { s } else { s + ";" })
1650     } else {
1651         Some(format!("{}{};", prefix, ty_str))
1652     }
1653 }
1654
1655 pub fn rewrite_associated_type(
1656     ident: ast::Ident,
1657     ty_opt: Option<&ptr::P<ast::Ty>>,
1658     ty_param_bounds_opt: Option<&ast::TyParamBounds>,
1659     context: &RewriteContext,
1660     indent: Indent,
1661 ) -> Option<String> {
1662     let prefix = format!("type {}", ident);
1663
1664     let type_bounds_str = if let Some(bounds) = ty_param_bounds_opt {
1665         if bounds.is_empty() {
1666             String::new()
1667         } else {
1668             // 2 = ": ".len()
1669             let shape = Shape::indented(indent, context.config).offset_left(prefix.len() + 2)?;
1670             bounds.rewrite(context, shape).map(|s| format!(": {}", s))?
1671         }
1672     } else {
1673         String::new()
1674     };
1675
1676     if let Some(ty) = ty_opt {
1677         // 1 = `;`
1678         let shape = Shape::indented(indent, context.config).sub_width(1)?;
1679         let lhs = format!("{}{} =", prefix, type_bounds_str);
1680         rewrite_assign_rhs(context, lhs, &**ty, shape).map(|s| s + ";")
1681     } else {
1682         Some(format!("{}{};", prefix, type_bounds_str))
1683     }
1684 }
1685
1686 pub fn rewrite_associated_impl_type(
1687     ident: ast::Ident,
1688     defaultness: ast::Defaultness,
1689     ty_opt: Option<&ptr::P<ast::Ty>>,
1690     ty_param_bounds_opt: Option<&ast::TyParamBounds>,
1691     context: &RewriteContext,
1692     indent: Indent,
1693 ) -> Option<String> {
1694     let result = rewrite_associated_type(ident, ty_opt, ty_param_bounds_opt, context, indent)?;
1695
1696     match defaultness {
1697         ast::Defaultness::Default => Some(format!("default {}", result)),
1698         _ => Some(result),
1699     }
1700 }
1701
1702 impl Rewrite for ast::FunctionRetTy {
1703     fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option<String> {
1704         match *self {
1705             ast::FunctionRetTy::Default(_) => Some(String::new()),
1706             ast::FunctionRetTy::Ty(ref ty) => {
1707                 let inner_width = shape.width.checked_sub(3)?;
1708                 ty.rewrite(context, Shape::legacy(inner_width, shape.indent + 3))
1709                     .map(|r| format!("-> {}", r))
1710             }
1711         }
1712     }
1713 }
1714
1715 fn is_empty_infer(context: &RewriteContext, ty: &ast::Ty) -> bool {
1716     match ty.node {
1717         ast::TyKind::Infer => {
1718             let original = context.snippet(ty.span);
1719             original != "_"
1720         }
1721         _ => false,
1722     }
1723 }
1724
1725 impl Rewrite for ast::Arg {
1726     fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option<String> {
1727         if is_named_arg(self) {
1728             let mut result = self.pat
1729                 .rewrite(context, Shape::legacy(shape.width, shape.indent))?;
1730
1731             if !is_empty_infer(context, &*self.ty) {
1732                 if context.config.space_before_colon() {
1733                     result.push_str(" ");
1734                 }
1735                 result.push_str(":");
1736                 if context.config.space_after_colon() {
1737                     result.push_str(" ");
1738                 }
1739                 let overhead = last_line_width(&result);
1740                 let max_width = shape.width.checked_sub(overhead)?;
1741                 let ty_str = self.ty
1742                     .rewrite(context, Shape::legacy(max_width, shape.indent))?;
1743                 result.push_str(&ty_str);
1744             }
1745
1746             Some(result)
1747         } else {
1748             self.ty.rewrite(context, shape)
1749         }
1750     }
1751 }
1752
1753 fn rewrite_explicit_self(
1754     explicit_self: &ast::ExplicitSelf,
1755     args: &[ast::Arg],
1756     context: &RewriteContext,
1757 ) -> Option<String> {
1758     match explicit_self.node {
1759         ast::SelfKind::Region(lt, m) => {
1760             let mut_str = format_mutability(m);
1761             match lt {
1762                 Some(ref l) => {
1763                     let lifetime_str = l.rewrite(
1764                         context,
1765                         Shape::legacy(context.config.max_width(), Indent::empty()),
1766                     )?;
1767                     Some(format!("&{} {}self", lifetime_str, mut_str))
1768                 }
1769                 None => Some(format!("&{}self", mut_str)),
1770             }
1771         }
1772         ast::SelfKind::Explicit(ref ty, _) => {
1773             assert!(!args.is_empty(), "&[ast::Arg] shouldn't be empty.");
1774
1775             let mutability = explicit_self_mutability(&args[0]);
1776             let type_str = ty.rewrite(
1777                 context,
1778                 Shape::legacy(context.config.max_width(), Indent::empty()),
1779             )?;
1780
1781             Some(format!(
1782                 "{}self: {}",
1783                 format_mutability(mutability),
1784                 type_str
1785             ))
1786         }
1787         ast::SelfKind::Value(_) => {
1788             assert!(!args.is_empty(), "&[ast::Arg] shouldn't be empty.");
1789
1790             let mutability = explicit_self_mutability(&args[0]);
1791
1792             Some(format!("{}self", format_mutability(mutability)))
1793         }
1794     }
1795 }
1796
1797 // Hacky solution caused by absence of `Mutability` in `SelfValue` and
1798 // `SelfExplicit` variants of `ast::ExplicitSelf_`.
1799 fn explicit_self_mutability(arg: &ast::Arg) -> ast::Mutability {
1800     if let ast::PatKind::Ident(ast::BindingMode::ByValue(mutability), _, _) = arg.pat.node {
1801         mutability
1802     } else {
1803         unreachable!()
1804     }
1805 }
1806
1807 pub fn span_lo_for_arg(arg: &ast::Arg) -> BytePos {
1808     if is_named_arg(arg) {
1809         arg.pat.span.lo()
1810     } else {
1811         arg.ty.span.lo()
1812     }
1813 }
1814
1815 pub fn span_hi_for_arg(context: &RewriteContext, arg: &ast::Arg) -> BytePos {
1816     match arg.ty.node {
1817         ast::TyKind::Infer if context.snippet(arg.ty.span) == "_" => arg.ty.span.hi(),
1818         ast::TyKind::Infer if is_named_arg(arg) => arg.pat.span.hi(),
1819         _ => arg.ty.span.hi(),
1820     }
1821 }
1822
1823 pub fn is_named_arg(arg: &ast::Arg) -> bool {
1824     if let ast::PatKind::Ident(_, ident, _) = arg.pat.node {
1825         ident != symbol::keywords::Invalid.ident()
1826     } else {
1827         true
1828     }
1829 }
1830
1831 // Return type is (result, force_new_line_for_brace)
1832 fn rewrite_fn_base(
1833     context: &RewriteContext,
1834     indent: Indent,
1835     ident: ast::Ident,
1836     fn_sig: &FnSig,
1837     span: Span,
1838     newline_brace: bool,
1839     has_body: bool,
1840 ) -> Option<(String, bool)> {
1841     let mut force_new_line_for_brace = false;
1842
1843     let where_clause = &fn_sig.generics.where_clause;
1844
1845     let mut result = String::with_capacity(1024);
1846     result.push_str(&fn_sig.to_str(context));
1847
1848     // fn foo
1849     result.push_str("fn ");
1850
1851     // Generics.
1852     let overhead = if has_body && !newline_brace {
1853         // 4 = `() {`
1854         4
1855     } else {
1856         // 2 = `()`
1857         2
1858     };
1859     let used_width = last_line_used_width(&result, indent.width());
1860     let one_line_budget = context.budget(used_width + overhead);
1861     let shape = Shape {
1862         width: one_line_budget,
1863         indent,
1864         offset: used_width,
1865     };
1866     let fd = fn_sig.decl;
1867     let g_span = mk_sp(span.lo(), fd.output.span().lo());
1868     let generics_str =
1869         rewrite_generics(context, &ident.to_string(), fn_sig.generics, shape, g_span)?;
1870     result.push_str(&generics_str);
1871
1872     let snuggle_angle_bracket = generics_str
1873         .lines()
1874         .last()
1875         .map_or(false, |l| l.trim_left().len() == 1);
1876
1877     // Note that the width and indent don't really matter, we'll re-layout the
1878     // return type later anyway.
1879     let ret_str = fd.output
1880         .rewrite(context, Shape::indented(indent, context.config))?;
1881
1882     let multi_line_ret_str = ret_str.contains('\n');
1883     let ret_str_len = if multi_line_ret_str { 0 } else { ret_str.len() };
1884
1885     // Args.
1886     let (one_line_budget, multi_line_budget, mut arg_indent) = compute_budgets_for_args(
1887         context,
1888         &result,
1889         indent,
1890         ret_str_len,
1891         newline_brace,
1892         has_body,
1893         multi_line_ret_str,
1894     )?;
1895
1896     debug!(
1897         "rewrite_fn_base: one_line_budget: {}, multi_line_budget: {}, arg_indent: {:?}",
1898         one_line_budget, multi_line_budget, arg_indent
1899     );
1900
1901     // Check if vertical layout was forced.
1902     if one_line_budget == 0 {
1903         if snuggle_angle_bracket {
1904             result.push('(');
1905         } else {
1906             result.push_str("(");
1907             if context.config.indent_style() == IndentStyle::Visual {
1908                 result.push_str(&arg_indent.to_string_with_newline(context.config));
1909             }
1910         }
1911     } else {
1912         result.push('(');
1913     }
1914     if context.config.spaces_within_parens_and_brackets()
1915         && !fd.inputs.is_empty()
1916         && result.ends_with('(')
1917     {
1918         result.push(' ')
1919     }
1920
1921     // Skip `pub(crate)`.
1922     let lo_after_visibility = get_bytepos_after_visibility(&fn_sig.visibility, span);
1923     // A conservative estimation, to goal is to be over all parens in generics
1924     let args_start = fn_sig
1925         .generics
1926         .params
1927         .iter()
1928         .last()
1929         .map_or(lo_after_visibility, |param| param.span().hi());
1930     let args_end = if fd.inputs.is_empty() {
1931         context
1932             .snippet_provider
1933             .span_after(mk_sp(args_start, span.hi()), ")")
1934     } else {
1935         let last_span = mk_sp(fd.inputs[fd.inputs.len() - 1].span().hi(), span.hi());
1936         context.snippet_provider.span_after(last_span, ")")
1937     };
1938     let args_span = mk_sp(
1939         context
1940             .snippet_provider
1941             .span_after(mk_sp(args_start, span.hi()), "("),
1942         args_end,
1943     );
1944     let arg_str = rewrite_args(
1945         context,
1946         &fd.inputs,
1947         fd.get_self().as_ref(),
1948         one_line_budget,
1949         multi_line_budget,
1950         indent,
1951         arg_indent,
1952         args_span,
1953         fd.variadic,
1954         generics_str.contains('\n'),
1955     )?;
1956
1957     let put_args_in_block = match context.config.indent_style() {
1958         IndentStyle::Block => arg_str.contains('\n') || arg_str.len() > one_line_budget,
1959         _ => false,
1960     } && !fd.inputs.is_empty();
1961
1962     let mut args_last_line_contains_comment = false;
1963     if put_args_in_block {
1964         arg_indent = indent.block_indent(context.config);
1965         result.push_str(&arg_indent.to_string_with_newline(context.config));
1966         result.push_str(&arg_str);
1967         result.push_str(&indent.to_string_with_newline(context.config));
1968         result.push(')');
1969     } else {
1970         result.push_str(&arg_str);
1971         let used_width = last_line_used_width(&result, indent.width()) + first_line_width(&ret_str);
1972         // Put the closing brace on the next line if it overflows the max width.
1973         // 1 = `)`
1974         if fd.inputs.is_empty() && used_width + 1 > context.config.max_width() {
1975             result.push('\n');
1976         }
1977         if context.config.spaces_within_parens_and_brackets() && !fd.inputs.is_empty() {
1978             result.push(' ')
1979         }
1980         // If the last line of args contains comment, we cannot put the closing paren
1981         // on the same line.
1982         if arg_str
1983             .lines()
1984             .last()
1985             .map_or(false, |last_line| last_line.contains("//"))
1986         {
1987             args_last_line_contains_comment = true;
1988             result.push_str(&arg_indent.to_string_with_newline(context.config));
1989         }
1990         result.push(')');
1991     }
1992
1993     // Return type.
1994     if let ast::FunctionRetTy::Ty(..) = fd.output {
1995         let ret_should_indent = match context.config.indent_style() {
1996             // If our args are block layout then we surely must have space.
1997             IndentStyle::Block if put_args_in_block || fd.inputs.is_empty() => false,
1998             _ if args_last_line_contains_comment => false,
1999             _ if result.contains('\n') || multi_line_ret_str => true,
2000             _ => {
2001                 // If the return type would push over the max width, then put the return type on
2002                 // a new line. With the +1 for the signature length an additional space between
2003                 // the closing parenthesis of the argument and the arrow '->' is considered.
2004                 let mut sig_length = result.len() + indent.width() + ret_str_len + 1;
2005
2006                 // If there is no where clause, take into account the space after the return type
2007                 // and the brace.
2008                 if where_clause.predicates.is_empty() {
2009                     sig_length += 2;
2010                 }
2011
2012                 sig_length > context.config.max_width()
2013             }
2014         };
2015         let ret_indent = if ret_should_indent {
2016             let indent = if arg_str.is_empty() {
2017                 // Aligning with non-existent args looks silly.
2018                 force_new_line_for_brace = true;
2019                 indent + 4
2020             } else {
2021                 // FIXME: we might want to check that using the arg indent
2022                 // doesn't blow our budget, and if it does, then fallback to
2023                 // the where clause indent.
2024                 arg_indent
2025             };
2026
2027             result.push_str(&indent.to_string_with_newline(context.config));
2028             indent
2029         } else {
2030             result.push(' ');
2031             Indent::new(indent.block_indent, last_line_width(&result))
2032         };
2033
2034         if multi_line_ret_str || ret_should_indent {
2035             // Now that we know the proper indent and width, we need to
2036             // re-layout the return type.
2037             let ret_str = fd.output
2038                 .rewrite(context, Shape::indented(ret_indent, context.config))?;
2039             result.push_str(&ret_str);
2040         } else {
2041             result.push_str(&ret_str);
2042         }
2043
2044         // Comment between return type and the end of the decl.
2045         let snippet_lo = fd.output.span().hi();
2046         if where_clause.predicates.is_empty() {
2047             let snippet_hi = span.hi();
2048             let snippet = context.snippet(mk_sp(snippet_lo, snippet_hi));
2049             // Try to preserve the layout of the original snippet.
2050             let original_starts_with_newline = snippet
2051                 .find(|c| c != ' ')
2052                 .map_or(false, |i| starts_with_newline(&snippet[i..]));
2053             let original_ends_with_newline = snippet
2054                 .rfind(|c| c != ' ')
2055                 .map_or(false, |i| snippet[i..].ends_with('\n'));
2056             let snippet = snippet.trim();
2057             if !snippet.is_empty() {
2058                 result.push(if original_starts_with_newline {
2059                     '\n'
2060                 } else {
2061                     ' '
2062                 });
2063                 result.push_str(snippet);
2064                 if original_ends_with_newline {
2065                     force_new_line_for_brace = true;
2066                 }
2067             }
2068         }
2069     }
2070
2071     let pos_before_where = match fd.output {
2072         ast::FunctionRetTy::Default(..) => args_span.hi(),
2073         ast::FunctionRetTy::Ty(ref ty) => ty.span.hi(),
2074     };
2075
2076     let is_args_multi_lined = arg_str.contains('\n');
2077
2078     let option = WhereClauseOption::new(!has_body, put_args_in_block && ret_str.is_empty());
2079     let where_clause_str = rewrite_where_clause(
2080         context,
2081         where_clause,
2082         context.config.brace_style(),
2083         Shape::indented(indent, context.config),
2084         Density::Tall,
2085         "{",
2086         Some(span.hi()),
2087         pos_before_where,
2088         option,
2089         is_args_multi_lined,
2090     )?;
2091     // If there are neither where clause nor return type, we may be missing comments between
2092     // args and `{`.
2093     if where_clause_str.is_empty() {
2094         if let ast::FunctionRetTy::Default(ret_span) = fd.output {
2095             match recover_missing_comment_in_span(
2096                 mk_sp(args_span.hi(), ret_span.hi()),
2097                 shape,
2098                 context,
2099                 last_line_width(&result),
2100             ) {
2101                 Some(ref missing_comment) if !missing_comment.is_empty() => {
2102                     result.push_str(missing_comment);
2103                     force_new_line_for_brace = true;
2104                 }
2105                 _ => (),
2106             }
2107         }
2108     }
2109
2110     result.push_str(&where_clause_str);
2111
2112     force_new_line_for_brace |= last_line_contains_single_line_comment(&result);
2113     force_new_line_for_brace |= is_args_multi_lined && context.config.where_single_line();
2114     Some((result, force_new_line_for_brace))
2115 }
2116
2117 #[derive(Copy, Clone)]
2118 struct WhereClauseOption {
2119     suppress_comma: bool, // Force no trailing comma
2120     snuggle: bool,        // Do not insert newline before `where`
2121     compress_where: bool, // Try single line where clause instead of vertical layout
2122 }
2123
2124 impl WhereClauseOption {
2125     pub fn new(suppress_comma: bool, snuggle: bool) -> WhereClauseOption {
2126         WhereClauseOption {
2127             suppress_comma,
2128             snuggle,
2129             compress_where: false,
2130         }
2131     }
2132
2133     pub fn snuggled(current: &str) -> WhereClauseOption {
2134         WhereClauseOption {
2135             suppress_comma: false,
2136             snuggle: trimmed_last_line_width(current) == 1,
2137             compress_where: false,
2138         }
2139     }
2140 }
2141
2142 fn rewrite_args(
2143     context: &RewriteContext,
2144     args: &[ast::Arg],
2145     explicit_self: Option<&ast::ExplicitSelf>,
2146     one_line_budget: usize,
2147     multi_line_budget: usize,
2148     indent: Indent,
2149     arg_indent: Indent,
2150     span: Span,
2151     variadic: bool,
2152     generics_str_contains_newline: bool,
2153 ) -> Option<String> {
2154     let mut arg_item_strs = args.iter()
2155         .map(|arg| arg.rewrite(context, Shape::legacy(multi_line_budget, arg_indent)))
2156         .collect::<Option<Vec<_>>>()?;
2157
2158     // Account for sugary self.
2159     // FIXME: the comment for the self argument is dropped. This is blocked
2160     // on rust issue #27522.
2161     let min_args = explicit_self
2162         .and_then(|explicit_self| rewrite_explicit_self(explicit_self, args, context))
2163         .map_or(1, |self_str| {
2164             arg_item_strs[0] = self_str;
2165             2
2166         });
2167
2168     // Comments between args.
2169     let mut arg_items = Vec::new();
2170     if min_args == 2 {
2171         arg_items.push(ListItem::from_str(""));
2172     }
2173
2174     // FIXME(#21): if there are no args, there might still be a comment, but
2175     // without spans for the comment or parens, there is no chance of
2176     // getting it right. You also don't get to put a comment on self, unless
2177     // it is explicit.
2178     if args.len() >= min_args || variadic {
2179         let comment_span_start = if min_args == 2 {
2180             let second_arg_start = if arg_has_pattern(&args[1]) {
2181                 args[1].pat.span.lo()
2182             } else {
2183                 args[1].ty.span.lo()
2184             };
2185             let reduced_span = mk_sp(span.lo(), second_arg_start);
2186
2187             context.snippet_provider.span_after_last(reduced_span, ",")
2188         } else {
2189             span.lo()
2190         };
2191
2192         enum ArgumentKind<'a> {
2193             Regular(&'a ast::Arg),
2194             Variadic(BytePos),
2195         }
2196
2197         let variadic_arg = if variadic {
2198             let variadic_span = mk_sp(args.last().unwrap().ty.span.hi(), span.hi());
2199             let variadic_start =
2200                 context.snippet_provider.span_after(variadic_span, "...") - BytePos(3);
2201             Some(ArgumentKind::Variadic(variadic_start))
2202         } else {
2203             None
2204         };
2205
2206         let more_items = itemize_list(
2207             context.snippet_provider,
2208             args[min_args - 1..]
2209                 .iter()
2210                 .map(ArgumentKind::Regular)
2211                 .chain(variadic_arg),
2212             ")",
2213             ",",
2214             |arg| match *arg {
2215                 ArgumentKind::Regular(arg) => span_lo_for_arg(arg),
2216                 ArgumentKind::Variadic(start) => start,
2217             },
2218             |arg| match *arg {
2219                 ArgumentKind::Regular(arg) => arg.ty.span.hi(),
2220                 ArgumentKind::Variadic(start) => start + BytePos(3),
2221             },
2222             |arg| match *arg {
2223                 ArgumentKind::Regular(..) => None,
2224                 ArgumentKind::Variadic(..) => Some("...".to_owned()),
2225             },
2226             comment_span_start,
2227             span.hi(),
2228             false,
2229         );
2230
2231         arg_items.extend(more_items);
2232     }
2233
2234     let fits_in_one_line = !generics_str_contains_newline
2235         && (arg_items.is_empty()
2236             || arg_items.len() == 1 && arg_item_strs[0].len() <= one_line_budget);
2237
2238     for (item, arg) in arg_items.iter_mut().zip(arg_item_strs) {
2239         item.item = Some(arg);
2240     }
2241
2242     let last_line_ends_with_comment = arg_items
2243         .iter()
2244         .last()
2245         .and_then(|item| item.post_comment.as_ref())
2246         .map_or(false, |s| s.trim().starts_with("//"));
2247
2248     let (indent, trailing_comma) = match context.config.indent_style() {
2249         IndentStyle::Block if fits_in_one_line => {
2250             (indent.block_indent(context.config), SeparatorTactic::Never)
2251         }
2252         IndentStyle::Block => (
2253             indent.block_indent(context.config),
2254             context.config.trailing_comma(),
2255         ),
2256         IndentStyle::Visual if last_line_ends_with_comment => {
2257             (arg_indent, context.config.trailing_comma())
2258         }
2259         IndentStyle::Visual => (arg_indent, SeparatorTactic::Never),
2260     };
2261
2262     let tactic = definitive_tactic(
2263         &arg_items,
2264         context.config.fn_args_density().to_list_tactic(),
2265         Separator::Comma,
2266         one_line_budget,
2267     );
2268     let budget = match tactic {
2269         DefinitiveListTactic::Horizontal => one_line_budget,
2270         _ => multi_line_budget,
2271     };
2272
2273     debug!("rewrite_args: budget: {}, tactic: {:?}", budget, tactic);
2274
2275     let fmt = ListFormatting {
2276         tactic,
2277         separator: ",",
2278         trailing_separator: if variadic {
2279             SeparatorTactic::Never
2280         } else {
2281             trailing_comma
2282         },
2283         separator_place: SeparatorPlace::Back,
2284         shape: Shape::legacy(budget, indent),
2285         ends_with_newline: tactic.ends_with_newline(context.config.indent_style()),
2286         preserve_newline: true,
2287         config: context.config,
2288     };
2289
2290     write_list(&arg_items, &fmt)
2291 }
2292
2293 fn arg_has_pattern(arg: &ast::Arg) -> bool {
2294     if let ast::PatKind::Ident(_, ident, _) = arg.pat.node {
2295         ident != symbol::keywords::Invalid.ident()
2296     } else {
2297         true
2298     }
2299 }
2300
2301 fn compute_budgets_for_args(
2302     context: &RewriteContext,
2303     result: &str,
2304     indent: Indent,
2305     ret_str_len: usize,
2306     newline_brace: bool,
2307     has_braces: bool,
2308     force_vertical_layout: bool,
2309 ) -> Option<((usize, usize, Indent))> {
2310     debug!(
2311         "compute_budgets_for_args {} {:?}, {}, {}",
2312         result.len(),
2313         indent,
2314         ret_str_len,
2315         newline_brace
2316     );
2317     // Try keeping everything on the same line.
2318     if !result.contains('\n') && !force_vertical_layout {
2319         // 2 = `()`, 3 = `() `, space is before ret_string.
2320         let overhead = if ret_str_len == 0 { 2 } else { 3 };
2321         let mut used_space = indent.width() + result.len() + ret_str_len + overhead;
2322         if has_braces {
2323             if !newline_brace {
2324                 // 2 = `{}`
2325                 used_space += 2;
2326             }
2327         } else {
2328             // 1 = `;`
2329             used_space += 1;
2330         }
2331         let one_line_budget = context.budget(used_space);
2332
2333         if one_line_budget > 0 {
2334             // 4 = "() {".len()
2335             let (indent, multi_line_budget) = match context.config.indent_style() {
2336                 IndentStyle::Block => {
2337                     let indent = indent.block_indent(context.config);
2338                     (indent, context.budget(indent.width() + 1))
2339                 }
2340                 IndentStyle::Visual => {
2341                     let indent = indent + result.len() + 1;
2342                     let multi_line_overhead = indent.width() + if newline_brace { 2 } else { 4 };
2343                     (indent, context.budget(multi_line_overhead))
2344                 }
2345             };
2346
2347             return Some((one_line_budget, multi_line_budget, indent));
2348         }
2349     }
2350
2351     // Didn't work. we must force vertical layout and put args on a newline.
2352     let new_indent = indent.block_indent(context.config);
2353     let used_space = match context.config.indent_style() {
2354         // 1 = `,`
2355         IndentStyle::Block => new_indent.width() + 1,
2356         // Account for `)` and possibly ` {`.
2357         IndentStyle::Visual => new_indent.width() + if ret_str_len == 0 { 1 } else { 3 },
2358     };
2359     Some((0, context.budget(used_space), new_indent))
2360 }
2361
2362 fn newline_for_brace(config: &Config, where_clause: &ast::WhereClause) -> bool {
2363     let predicate_count = where_clause.predicates.len();
2364
2365     if config.where_single_line() && predicate_count == 1 {
2366         return false;
2367     }
2368     let brace_style = config.brace_style();
2369
2370     brace_style == BraceStyle::AlwaysNextLine
2371         || (brace_style == BraceStyle::SameLineWhere && predicate_count > 0)
2372 }
2373
2374 fn rewrite_generics(
2375     context: &RewriteContext,
2376     ident: &str,
2377     generics: &ast::Generics,
2378     shape: Shape,
2379     span: Span,
2380 ) -> Option<String> {
2381     // FIXME: convert bounds to where clauses where they get too big or if
2382     // there is a where clause at all.
2383
2384     if generics.params.is_empty() {
2385         return Some(ident.to_owned());
2386     }
2387
2388     let params = &generics.params.iter().map(|e| &*e).collect::<Vec<_>>();
2389     overflow::rewrite_with_angle_brackets(context, ident, params, shape, span)
2390 }
2391
2392 pub fn generics_shape_from_config(config: &Config, shape: Shape, offset: usize) -> Option<Shape> {
2393     match config.indent_style() {
2394         IndentStyle::Visual => shape.visual_indent(1 + offset).sub_width(offset + 2),
2395         IndentStyle::Block => {
2396             // 1 = ","
2397             shape
2398                 .block()
2399                 .block_indent(config.tab_spaces())
2400                 .with_max_width(config)
2401                 .sub_width(1)
2402         }
2403     }
2404 }
2405
2406 fn rewrite_where_clause_rfc_style(
2407     context: &RewriteContext,
2408     where_clause: &ast::WhereClause,
2409     shape: Shape,
2410     terminator: &str,
2411     span_end: Option<BytePos>,
2412     span_end_before_where: BytePos,
2413     where_clause_option: WhereClauseOption,
2414     is_args_multi_line: bool,
2415 ) -> Option<String> {
2416     let block_shape = shape.block().with_max_width(context.config);
2417
2418     let (span_before, span_after) =
2419         missing_span_before_after_where(span_end_before_where, where_clause);
2420     let (comment_before, comment_after) =
2421         rewrite_comments_before_after_where(context, span_before, span_after, shape)?;
2422
2423     let starting_newline = if where_clause_option.snuggle && comment_before.is_empty() {
2424         Cow::from(" ")
2425     } else {
2426         block_shape.indent.to_string_with_newline(context.config)
2427     };
2428
2429     let clause_shape = block_shape.block_left(context.config.tab_spaces())?;
2430     // 1 = `,`
2431     let clause_shape = clause_shape.sub_width(1)?;
2432     // each clause on one line, trailing comma (except if suppress_comma)
2433     let span_start = where_clause.predicates[0].span().lo();
2434     // If we don't have the start of the next span, then use the end of the
2435     // predicates, but that means we miss comments.
2436     let len = where_clause.predicates.len();
2437     let end_of_preds = where_clause.predicates[len - 1].span().hi();
2438     let span_end = span_end.unwrap_or(end_of_preds);
2439     let items = itemize_list(
2440         context.snippet_provider,
2441         where_clause.predicates.iter(),
2442         terminator,
2443         ",",
2444         |pred| pred.span().lo(),
2445         |pred| pred.span().hi(),
2446         |pred| pred.rewrite(context, clause_shape),
2447         span_start,
2448         span_end,
2449         false,
2450     );
2451     let where_single_line = context.config.where_single_line() && len == 1 && !is_args_multi_line;
2452     let comma_tactic = if where_clause_option.suppress_comma || where_single_line {
2453         SeparatorTactic::Never
2454     } else {
2455         context.config.trailing_comma()
2456     };
2457
2458     // shape should be vertical only and only if we have `where_single_line` option enabled
2459     // and the number of items of the where clause is equal to 1
2460     let shape_tactic = if where_single_line {
2461         DefinitiveListTactic::Horizontal
2462     } else {
2463         DefinitiveListTactic::Vertical
2464     };
2465
2466     let fmt = ListFormatting {
2467         tactic: shape_tactic,
2468         separator: ",",
2469         trailing_separator: comma_tactic,
2470         separator_place: SeparatorPlace::Back,
2471         shape: clause_shape,
2472         ends_with_newline: true,
2473         preserve_newline: true,
2474         config: context.config,
2475     };
2476     let preds_str = write_list(&items.collect::<Vec<_>>(), &fmt)?;
2477
2478     let comment_separator = |comment: &str, shape: Shape| {
2479         if comment.is_empty() {
2480             Cow::from("")
2481         } else {
2482             shape.indent.to_string_with_newline(context.config)
2483         }
2484     };
2485     let newline_before_where = comment_separator(&comment_before, shape);
2486     let newline_after_where = comment_separator(&comment_after, clause_shape);
2487
2488     // 6 = `where `
2489     let clause_sep = if where_clause_option.compress_where
2490         && comment_before.is_empty()
2491         && comment_after.is_empty()
2492         && !preds_str.contains('\n')
2493         && 6 + preds_str.len() <= shape.width || where_single_line
2494     {
2495         Cow::from(" ")
2496     } else {
2497         clause_shape.indent.to_string_with_newline(context.config)
2498     };
2499     Some(format!(
2500         "{}{}{}where{}{}{}{}",
2501         starting_newline,
2502         comment_before,
2503         newline_before_where,
2504         newline_after_where,
2505         comment_after,
2506         clause_sep,
2507         preds_str
2508     ))
2509 }
2510
2511 fn rewrite_where_clause(
2512     context: &RewriteContext,
2513     where_clause: &ast::WhereClause,
2514     brace_style: BraceStyle,
2515     shape: Shape,
2516     density: Density,
2517     terminator: &str,
2518     span_end: Option<BytePos>,
2519     span_end_before_where: BytePos,
2520     where_clause_option: WhereClauseOption,
2521     is_args_multi_line: bool,
2522 ) -> Option<String> {
2523     if where_clause.predicates.is_empty() {
2524         return Some(String::new());
2525     }
2526
2527     if context.config.indent_style() == IndentStyle::Block {
2528         return rewrite_where_clause_rfc_style(
2529             context,
2530             where_clause,
2531             shape,
2532             terminator,
2533             span_end,
2534             span_end_before_where,
2535             where_clause_option,
2536             is_args_multi_line,
2537         );
2538     }
2539
2540     let extra_indent = Indent::new(context.config.tab_spaces(), 0);
2541
2542     let offset = match context.config.indent_style() {
2543         IndentStyle::Block => shape.indent + extra_indent.block_indent(context.config),
2544         // 6 = "where ".len()
2545         IndentStyle::Visual => shape.indent + extra_indent + 6,
2546     };
2547     // FIXME: if indent_style != Visual, then the budgets below might
2548     // be out by a char or two.
2549
2550     let budget = context.config.max_width() - offset.width();
2551     let span_start = where_clause.predicates[0].span().lo();
2552     // If we don't have the start of the next span, then use the end of the
2553     // predicates, but that means we miss comments.
2554     let len = where_clause.predicates.len();
2555     let end_of_preds = where_clause.predicates[len - 1].span().hi();
2556     let span_end = span_end.unwrap_or(end_of_preds);
2557     let items = itemize_list(
2558         context.snippet_provider,
2559         where_clause.predicates.iter(),
2560         terminator,
2561         ",",
2562         |pred| pred.span().lo(),
2563         |pred| pred.span().hi(),
2564         |pred| pred.rewrite(context, Shape::legacy(budget, offset)),
2565         span_start,
2566         span_end,
2567         false,
2568     );
2569     let item_vec = items.collect::<Vec<_>>();
2570     // FIXME: we don't need to collect here
2571     let tactic = definitive_tactic(&item_vec, ListTactic::Vertical, Separator::Comma, budget);
2572
2573     let mut comma_tactic = context.config.trailing_comma();
2574     // Kind of a hack because we don't usually have trailing commas in where clauses.
2575     if comma_tactic == SeparatorTactic::Vertical || where_clause_option.suppress_comma {
2576         comma_tactic = SeparatorTactic::Never;
2577     }
2578
2579     let fmt = ListFormatting {
2580         tactic,
2581         separator: ",",
2582         trailing_separator: comma_tactic,
2583         separator_place: SeparatorPlace::Back,
2584         shape: Shape::legacy(budget, offset),
2585         ends_with_newline: tactic.ends_with_newline(context.config.indent_style()),
2586         preserve_newline: true,
2587         config: context.config,
2588     };
2589     let preds_str = write_list(&item_vec, &fmt)?;
2590
2591     let end_length = if terminator == "{" {
2592         // If the brace is on the next line we don't need to count it otherwise it needs two
2593         // characters " {"
2594         match brace_style {
2595             BraceStyle::AlwaysNextLine | BraceStyle::SameLineWhere => 0,
2596             BraceStyle::PreferSameLine => 2,
2597         }
2598     } else if terminator == "=" {
2599         2
2600     } else {
2601         terminator.len()
2602     };
2603     if density == Density::Tall
2604         || preds_str.contains('\n')
2605         || shape.indent.width() + " where ".len() + preds_str.len() + end_length > shape.width
2606     {
2607         Some(format!(
2608             "\n{}where {}",
2609             (shape.indent + extra_indent).to_string(context.config),
2610             preds_str
2611         ))
2612     } else {
2613         Some(format!(" where {}", preds_str))
2614     }
2615 }
2616
2617 fn missing_span_before_after_where(
2618     before_item_span_end: BytePos,
2619     where_clause: &ast::WhereClause,
2620 ) -> (Span, Span) {
2621     let missing_span_before = mk_sp(before_item_span_end, where_clause.span.lo());
2622     // 5 = `where`
2623     let pos_after_where = where_clause.span.lo() + BytePos(5);
2624     let missing_span_after = mk_sp(pos_after_where, where_clause.predicates[0].span().lo());
2625     (missing_span_before, missing_span_after)
2626 }
2627
2628 fn rewrite_comments_before_after_where(
2629     context: &RewriteContext,
2630     span_before_where: Span,
2631     span_after_where: Span,
2632     shape: Shape,
2633 ) -> Option<(String, String)> {
2634     let before_comment = rewrite_missing_comment(span_before_where, shape, context)?;
2635     let after_comment = rewrite_missing_comment(
2636         span_after_where,
2637         shape.block_indent(context.config.tab_spaces()),
2638         context,
2639     )?;
2640     Some((before_comment, after_comment))
2641 }
2642
2643 fn format_header(item_name: &str, ident: ast::Ident, vis: &ast::Visibility) -> String {
2644     format!("{}{}{}", format_visibility(vis), item_name, ident)
2645 }
2646
2647 #[derive(PartialEq, Eq, Clone, Copy)]
2648 enum BracePos {
2649     None,
2650     Auto,
2651     ForceSameLine,
2652 }
2653
2654 fn format_generics(
2655     context: &RewriteContext,
2656     generics: &ast::Generics,
2657     brace_style: BraceStyle,
2658     brace_pos: BracePos,
2659     offset: Indent,
2660     span: Span,
2661     used_width: usize,
2662 ) -> Option<String> {
2663     let shape = Shape::legacy(context.budget(used_width + offset.width()), offset);
2664     let mut result = rewrite_generics(context, "", generics, shape, span)?;
2665
2666     let same_line_brace = if !generics.where_clause.predicates.is_empty() || result.contains('\n') {
2667         let budget = context.budget(last_line_used_width(&result, offset.width()));
2668         let mut option = WhereClauseOption::snuggled(&result);
2669         if brace_pos == BracePos::None {
2670             option.suppress_comma = true;
2671         }
2672         // If the generics are not parameterized then generics.span.hi() == 0,
2673         // so we use span.lo(), which is the position after `struct Foo`.
2674         let span_end_before_where = if generics.is_parameterized() {
2675             generics.span.hi()
2676         } else {
2677             span.lo()
2678         };
2679         let where_clause_str = rewrite_where_clause(
2680             context,
2681             &generics.where_clause,
2682             brace_style,
2683             Shape::legacy(budget, offset.block_only()),
2684             Density::Tall,
2685             "{",
2686             Some(span.hi()),
2687             span_end_before_where,
2688             option,
2689             false,
2690         )?;
2691         result.push_str(&where_clause_str);
2692         brace_pos == BracePos::ForceSameLine || brace_style == BraceStyle::PreferSameLine
2693             || (generics.where_clause.predicates.is_empty()
2694                 && trimmed_last_line_width(&result) == 1)
2695     } else {
2696         brace_pos == BracePos::ForceSameLine
2697             || trimmed_last_line_width(&result) == 1
2698             || brace_style != BraceStyle::AlwaysNextLine
2699     };
2700     if brace_pos == BracePos::None {
2701         return Some(result);
2702     }
2703     let total_used_width = last_line_used_width(&result, used_width);
2704     let remaining_budget = context.budget(total_used_width);
2705     // If the same line brace if forced, it indicates that we are rewriting an item with empty body,
2706     // and hence we take the closer into account as well for one line budget.
2707     // We assume that the closer has the same length as the opener.
2708     let overhead = if brace_pos == BracePos::ForceSameLine {
2709         // 3 = ` {}`
2710         3
2711     } else {
2712         // 2 = ` {`
2713         2
2714     };
2715     let forbid_same_line_brace = overhead > remaining_budget;
2716     if !forbid_same_line_brace && same_line_brace {
2717         result.push(' ');
2718     } else {
2719         result.push('\n');
2720         result.push_str(&offset.block_only().to_string(context.config));
2721     }
2722     result.push('{');
2723
2724     Some(result)
2725 }
2726
2727 impl Rewrite for ast::ForeignItem {
2728     fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option<String> {
2729         let attrs_str = self.attrs.rewrite(context, shape)?;
2730         // Drop semicolon or it will be interpreted as comment.
2731         // FIXME: this may be a faulty span from libsyntax.
2732         let span = mk_sp(self.span.lo(), self.span.hi() - BytePos(1));
2733
2734         let item_str = match self.node {
2735             ast::ForeignItemKind::Fn(ref fn_decl, ref generics) => {
2736                 rewrite_fn_base(
2737                     context,
2738                     shape.indent,
2739                     self.ident,
2740                     &FnSig::new(fn_decl, generics, self.vis.clone()),
2741                     span,
2742                     false,
2743                     false,
2744                 ).map(|(s, _)| format!("{};", s))
2745             }
2746             ast::ForeignItemKind::Static(ref ty, is_mutable) => {
2747                 // FIXME(#21): we're dropping potential comments in between the
2748                 // function keywords here.
2749                 let vis = format_visibility(&self.vis);
2750                 let mut_str = if is_mutable { "mut " } else { "" };
2751                 let prefix = format!("{}static {}{}:", vis, mut_str, self.ident);
2752                 // 1 = ;
2753                 rewrite_assign_rhs(context, prefix, &**ty, shape.sub_width(1)?).map(|s| s + ";")
2754             }
2755             ast::ForeignItemKind::Ty => {
2756                 let vis = format_visibility(&self.vis);
2757                 Some(format!("{}type {};", vis, self.ident))
2758             }
2759             ast::ForeignItemKind::Macro(ref mac) => {
2760                 rewrite_macro(mac, None, context, shape, MacroPosition::Item)
2761             }
2762         }?;
2763
2764         let missing_span = if self.attrs.is_empty() {
2765             mk_sp(self.span.lo(), self.span.lo())
2766         } else {
2767             mk_sp(self.attrs[self.attrs.len() - 1].span.hi(), self.span.lo())
2768         };
2769         combine_strs_with_missing_comments(
2770             context,
2771             &attrs_str,
2772             &item_str,
2773             missing_span,
2774             shape,
2775             false,
2776         )
2777     }
2778 }
2779
2780 impl Rewrite for ast::GenericParam {
2781     fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option<String> {
2782         match *self {
2783             ast::GenericParam::Lifetime(ref lifetime_def) => lifetime_def.rewrite(context, shape),
2784             ast::GenericParam::Type(ref ty) => ty.rewrite(context, shape),
2785         }
2786     }
2787 }
2788
2789 /// Rewrite an inline mod.
2790 pub fn rewrite_mod(item: &ast::Item) -> String {
2791     let mut result = String::with_capacity(32);
2792     result.push_str(&*format_visibility(&item.vis));
2793     result.push_str("mod ");
2794     result.push_str(&item.ident.to_string());
2795     result.push(';');
2796     result
2797 }
2798
2799 /// Rewrite `extern crate foo;` WITHOUT attributes.
2800 pub fn rewrite_extern_crate(context: &RewriteContext, item: &ast::Item) -> Option<String> {
2801     assert!(is_extern_crate(item));
2802     let new_str = context.snippet(item.span);
2803     Some(if contains_comment(new_str) {
2804         new_str.to_owned()
2805     } else {
2806         let no_whitespace = &new_str.split_whitespace().collect::<Vec<&str>>().join(" ");
2807         String::from(&*Regex::new(r"\s;").unwrap().replace(no_whitespace, ";"))
2808     })
2809 }
2810
2811 /// Returns true for `mod foo;`, false for `mod foo { .. }`.
2812 pub fn is_mod_decl(item: &ast::Item) -> bool {
2813     match item.node {
2814         ast::ItemKind::Mod(ref m) => m.inner.hi() != item.span.hi(),
2815         _ => false,
2816     }
2817 }
2818
2819 pub fn is_use_item(item: &ast::Item) -> bool {
2820     match item.node {
2821         ast::ItemKind::Use(_) => true,
2822         _ => false,
2823     }
2824 }
2825
2826 pub fn is_extern_crate(item: &ast::Item) -> bool {
2827     match item.node {
2828         ast::ItemKind::ExternCrate(..) => true,
2829         _ => false,
2830     }
2831 }