Merge pull request #122 from cassiersg/fix-mod

Reformat modules in external files
This commit is contained in:
Nick Cameron 2015-07-06 07:07:08 +12:00
commit 04cf309f32
28 changed files with 352 additions and 234 deletions

View File

@ -35,11 +35,9 @@ pub struct ChangeSet<'a> {
impl<'a> ChangeSet<'a> {
// Create a new ChangeSet for a given libsyntax CodeMap.
pub fn from_codemap(codemap: &'a CodeMap) -> ChangeSet<'a> {
let mut result = ChangeSet {
file_map: HashMap::new(),
codemap: codemap,
file_spans: Vec::with_capacity(codemap.files.borrow().len()),
};
let mut result = ChangeSet { file_map: HashMap::new(),
codemap: codemap,
file_spans: Vec::with_capacity(codemap.files.borrow().len()), };
for f in codemap.files.borrow().iter() {
// Use the length of the file as a heuristic for how much space we
@ -116,11 +114,7 @@ impl<'a> ChangeSet<'a> {
// Return an iterator over the entire changed text.
pub fn text<'c>(&'c self) -> FileIterator<'c, 'a> {
FileIterator {
change_set: self,
keys: self.file_map.keys().collect(),
cur_key: 0,
}
FileIterator { change_set: self, keys: self.file_map.keys().collect(), cur_key: 0 }
}
// Append a newline to the end of each file.
@ -153,12 +147,11 @@ impl<'a> ChangeSet<'a> {
let text = &self.file_map[filename];
// prints all newlines either as `\n` or as `\r\n`
fn write_system_newlines<T>(
mut writer: T,
text: &StringBuffer,
config: &Config)
-> Result<(), ::std::io::Error>
where T: Write,
fn write_system_newlines<T>(mut writer: T,
text: &StringBuffer,
config: &Config)
-> Result<(), ::std::io::Error>
where T: Write
{
match config.newline_style {
NewlineStyle::Unix => write!(writer, "{}", text),
@ -213,6 +206,10 @@ impl<'a> ChangeSet<'a> {
Ok(None)
}
pub fn is_changed(&self, filename: &str) -> bool {
self.file_map.get(filename).expect("Unknown filename").len != 0
}
}
// Iterates over each file in the ChangSet. Yields the filename and the changed

View File

@ -24,15 +24,13 @@ pub fn rewrite_comment(orig: &str, block_style: bool, width: usize, offset: usiz
let max_chars = width.checked_sub(closer.len()).unwrap_or(1)
.checked_sub(opener.len()).unwrap_or(1);
let fmt = StringFormat {
opener: "",
closer: "",
line_start: line_start,
line_end: "",
width: max_chars,
offset: offset + opener.len() - line_start.len(),
trim_end: true
};
let fmt = StringFormat { opener: "",
closer: "",
line_start: line_start,
line_end: "",
width: max_chars,
offset: offset + opener.len() - line_start.len(),
trim_end: true, };
let indent_str = make_indent(offset);
let line_breaks = s.chars().filter(|&c| c == '\n').count();
@ -102,8 +100,8 @@ fn format_comments() {
let input = "// comment";
let expected_output = "/* com\n \
* men\n \
* t */";
* men\n \
* t */";
assert_eq!(expected_output, rewrite_comment(input, true, 9, 69));
assert_eq!("/* trimmed */", rewrite_comment("/* trimmed */", true, 100, 100));

View File

@ -63,7 +63,7 @@ fn rewrite_string_lit(context: &RewriteContext,
span: Span,
width: usize,
offset: usize)
-> Option<String> {
-> Option<String> {
// Check if there is anything to fix: we always try to fixup multi-line
// strings, or if the string is too long for the line.
let l_loc = context.codemap.lookup_char_pos(span.lo);
@ -71,15 +71,13 @@ fn rewrite_string_lit(context: &RewriteContext,
if l_loc.line == r_loc.line && r_loc.col.to_usize() <= context.config.max_width {
return context.codemap.span_to_snippet(span).ok();
}
let fmt = StringFormat {
opener: "\"",
closer: "\"",
line_start: " ",
line_end: "\\",
width: width,
offset: offset,
trim_end: false
};
let fmt = StringFormat { opener: "\"",
closer: "\"",
line_start: " ",
line_end: "\\",
width: width,
offset: offset,
trim_end: false, };
Some(rewrite_string(&s.escape_default(), &fmt))
}
@ -90,7 +88,7 @@ fn rewrite_call(context: &RewriteContext,
span: Span,
width: usize,
offset: usize)
-> Option<String> {
-> Option<String> {
debug!("rewrite_call, width: {}, offset: {}", width, offset);
// TODO using byte lens instead of char lens (and probably all over the place too)
@ -119,20 +117,22 @@ fn rewrite_call(context: &RewriteContext,
callee.span.hi + BytePos(1),
span.hi);
let fmt = ListFormatting {
tactic: ListTactic::HorizontalVertical,
separator: ",",
trailing_separator: SeparatorTactic::Never,
indent: offset,
h_width: remaining_width,
v_width: remaining_width,
ends_with_newline: true,
};
let fmt = ListFormatting { tactic: ListTactic::HorizontalVertical,
separator: ",",
trailing_separator: SeparatorTactic::Never,
indent: offset,
h_width: remaining_width,
v_width: remaining_width,
ends_with_newline: true, };
Some(format!("{}({})", callee_str, write_list(&items, &fmt)))
}
fn rewrite_paren(context: &RewriteContext, subexpr: &ast::Expr, width: usize, offset: usize) -> Option<String> {
fn rewrite_paren(context: &RewriteContext,
subexpr: &ast::Expr,
width: usize,
offset: usize)
-> Option<String> {
debug!("rewrite_paren, width: {}, offset: {}", width, offset);
// 1 is for opening paren, 2 is for opening+closing, we want to keep the closing
// paren on the same line as the subexpr
@ -148,14 +148,13 @@ fn rewrite_struct_lit<'a>(context: &RewriteContext,
span: Span,
width: usize,
offset: usize)
-> Option<String>
{
-> Option<String> {
debug!("rewrite_struct_lit: width {}, offset {}", width, offset);
assert!(fields.len() > 0 || base.is_some());
enum StructLitField<'a> {
Regular(&'a ast::Field),
Base(&'a ast::Expr)
Base(&'a ast::Expr),
}
let path_str = pprust::path_to_string(path);
@ -203,19 +202,17 @@ fn rewrite_struct_lit<'a>(context: &RewriteContext,
span_after(span, "{", context.codemap),
span.hi);
let fmt = ListFormatting {
tactic: ListTactic::HorizontalVertical,
separator: ",",
trailing_separator: if base.is_some() {
let fmt = ListFormatting { tactic: ListTactic::HorizontalVertical,
separator: ",",
trailing_separator: if base.is_some() {
SeparatorTactic::Never
} else {
context.config.struct_lit_trailing_comma
},
indent: indent,
h_width: budget,
v_width: budget,
ends_with_newline: true,
};
indent: indent,
h_width: budget,
v_width: budget,
ends_with_newline: true, };
let fields_str = write_list(&items, &fmt);
Some(format!("{} {{ {} }}", path_str, fields_str))
@ -225,7 +222,11 @@ fn rewrite_struct_lit<'a>(context: &RewriteContext,
// }
}
fn rewrite_field(context: &RewriteContext, field: &ast::Field, width: usize, offset: usize) -> Option<String> {
fn rewrite_field(context: &RewriteContext,
field: &ast::Field,
width: usize,
offset: usize)
-> Option<String> {
let name = &token::get_ident(field.ident.node);
let overhead = name.len() + 2;
let expr = field.expr.rewrite(context, width - overhead, offset + overhead);
@ -262,15 +263,13 @@ fn rewrite_tuple_lit(context: &RewriteContext,
SeparatorTactic::Never
};
let fmt = ListFormatting {
tactic: ListTactic::HorizontalVertical,
separator: ",",
trailing_separator: trailing_separator_tactic,
indent: indent,
h_width: width - 2,
v_width: width - 2,
ends_with_newline: true,
};
let fmt = ListFormatting { tactic: ListTactic::HorizontalVertical,
separator: ",",
trailing_separator: trailing_separator_tactic,
indent: indent,
h_width: width - 2,
v_width: width - 2,
ends_with_newline: true, };
Some(format!("({})", write_list(&items, &fmt)))
}

View File

@ -48,7 +48,8 @@ impl<'a> FmtVisitor<'a> {
path: &ast::Path,
path_list: &[ast::PathListItem],
visibility: ast::Visibility,
span: Span) -> Option<String> {
span: Span)
-> Option<String> {
let path_str = pprust::path_to_string(path);
let vis = format_visibility(visibility);
@ -70,18 +71,17 @@ impl<'a> FmtVisitor<'a> {
let remaining_line_budget = one_line_budget.checked_sub(used_width).unwrap_or(0);
let remaining_multi_budget = multi_line_budget.checked_sub(used_width).unwrap_or(0);
let fmt = ListFormatting {
tactic: ListTactic::Mixed,
separator: ",",
trailing_separator: SeparatorTactic::Never,
indent: block_indent + indent,
h_width: remaining_line_budget,
v_width: remaining_multi_budget,
ends_with_newline: true,
};
let fmt = ListFormatting { tactic: ListTactic::Mixed,
separator: ",",
trailing_separator: SeparatorTactic::Never,
indent: block_indent + indent,
h_width: remaining_line_budget,
v_width: remaining_multi_budget,
ends_with_newline: true, };
let mut items = itemize_list(self.codemap,
vec![ListItem::from_str("")], // Dummy value, explanation below
vec![ListItem::from_str("")], /* Dummy value, explanation
* below */
path_list.iter(),
",",
"}",

View File

@ -21,7 +21,7 @@ static FIX_ME_CHARS: &'static [char] = &['F', 'I', 'X', 'M', 'E'];
pub enum ReportTactic {
Always,
Unnumbered,
Never
Never,
}
impl ReportTactic {
@ -40,12 +40,12 @@ impl_enum_decodable!(ReportTactic, Always, Unnumbered, Never);
enum Seeking {
Issue {
todo_idx: usize,
fixme_idx: usize
fixme_idx: usize,
},
Number {
issue: Issue,
part: NumberPart
}
part: NumberPart,
},
}
#[derive(Clone, Copy)]
@ -53,7 +53,7 @@ enum NumberPart {
OpenParen,
Pound,
Number,
CloseParen
CloseParen,
}
#[derive(PartialEq, Eq, Debug, Clone, Copy)]
@ -79,13 +79,13 @@ impl fmt::Display for Issue {
#[derive(PartialEq, Eq, Debug, Clone, Copy)]
enum IssueType {
Todo,
Fixme
Fixme,
}
enum IssueClassification {
Good,
Bad(Issue),
None
None,
}
pub struct BadIssueSeeker {
@ -96,11 +96,9 @@ pub struct BadIssueSeeker {
impl BadIssueSeeker {
pub fn new(report_todo: ReportTactic, report_fixme: ReportTactic) -> BadIssueSeeker {
BadIssueSeeker {
state: Seeking::Issue { todo_idx: 0, fixme_idx: 0 },
report_todo: report_todo,
report_fixme: report_fixme,
}
BadIssueSeeker { state: Seeking::Issue { todo_idx: 0, fixme_idx: 0 },
report_todo: report_todo,
report_fixme: report_fixme, }
}
// Check whether or not the current char is conclusive evidence for an
@ -176,8 +174,7 @@ impl BadIssueSeeker {
c: char,
issue: Issue,
mut part: NumberPart)
-> IssueClassification
{
-> IssueClassification {
if ! issue.missing_number || c == '\n' {
return IssueClassification::Bad(issue);
} else if c == ')' {
@ -272,10 +269,7 @@ fn find_issue() {
#[test]
fn issue_type() {
let mut seeker = BadIssueSeeker::new(ReportTactic::Always, ReportTactic::Never);
let expected = Some(Issue {
issue_type: IssueType::Todo,
missing_number: false
});
let expected = Some(Issue { issue_type: IssueType::Todo, missing_number: false });
assert_eq!(expected,
"TODO(#100): more awesomeness".chars()
@ -284,10 +278,7 @@ fn issue_type() {
.unwrap());
let mut seeker = BadIssueSeeker::new(ReportTactic::Never, ReportTactic::Unnumbered);
let expected = Some(Issue {
issue_type: IssueType::Fixme,
missing_number: true
});
let expected = Some(Issue { issue_type: IssueType::Fixme, missing_number: true });
assert_eq!(expected,
"Test. FIXME: bad, bad, not good".chars()

View File

@ -11,7 +11,7 @@
// Formatting top-level items - functions, structs, enums, traits, impls.
use {ReturnIndent, BraceStyle};
use utils::{format_visibility, make_indent, contains_skip, span_after};
use utils::{format_visibility, make_indent, contains_skip, span_after, end_typaram};
use lists::{write_list, itemize_list, ListItem, ListFormatting, SeparatorTactic, ListTactic};
use comment::FindUncommented;
use visitor::FmtVisitor;
@ -33,8 +33,7 @@ impl<'a> FmtVisitor<'a> {
abi: &abi::Abi,
vis: ast::Visibility,
span: Span)
-> String
{
-> String {
let newline_brace = self.newline_for_brace(&generics.where_clause);
let mut result = self.rewrite_fn_base(indent,
@ -67,8 +66,7 @@ impl<'a> FmtVisitor<'a> {
ident: ast::Ident,
sig: &ast::MethodSig,
span: Span)
-> String
{
-> String {
// Drop semicolon or it will be interpreted as comment
let span = codemap::mk_sp(span.lo, span.hi - BytePos(1));
@ -102,8 +100,7 @@ impl<'a> FmtVisitor<'a> {
vis: ast::Visibility,
span: Span,
newline_brace: bool)
-> String
{
-> String {
// FIXME we'll lose any comments in between parts of the function decl, but anyone
// who comments there probably deserves what they get.
@ -160,13 +157,21 @@ impl<'a> FmtVisitor<'a> {
result.push('(');
}
// A conservative estimation, to goal is to be over all parens in generics
let args_start = generics.ty_params
.last()
.map(|tp| end_typaram(tp))
.unwrap_or(span.lo);
let args_span = codemap::mk_sp(span_after(codemap::mk_sp(args_start, span.hi),
"(",
self.codemap),
span_for_return(&fd.output).lo);
result.push_str(&self.rewrite_args(&fd.inputs,
explicit_self,
one_line_budget,
multi_line_budget,
arg_indent,
codemap::mk_sp(span_after(span, "(", self.codemap),
span_for_return(&fd.output).lo)));
args_span));
result.push(')');
// Return type.
@ -222,8 +227,7 @@ impl<'a> FmtVisitor<'a> {
multi_line_budget: usize,
arg_indent: usize,
span: Span)
-> String
{
-> String {
let mut arg_item_strs: Vec<_> = args.iter().map(|a| self.rewrite_fn_input(a)).collect();
// Account for sugary self.
let mut min_args = 1;
@ -301,15 +305,13 @@ impl<'a> FmtVisitor<'a> {
item.item = arg;
}
let fmt = ListFormatting {
tactic: ListTactic::HorizontalVertical,
separator: ",",
trailing_separator: SeparatorTactic::Never,
indent: arg_indent,
h_width: one_line_budget,
v_width: multi_line_budget,
ends_with_newline: true,
};
let fmt = ListFormatting { tactic: ListTactic::HorizontalVertical,
separator: ",",
trailing_separator: SeparatorTactic::Never,
indent: arg_indent,
h_width: one_line_budget,
v_width: multi_line_budget,
ends_with_newline: true, };
write_list(&arg_items, &fmt)
}
@ -319,8 +321,7 @@ impl<'a> FmtVisitor<'a> {
indent: usize,
ret_str_len: usize,
newline_brace: bool)
-> (usize, usize, usize)
{
-> (usize, usize, usize) {
let mut budgets = None;
// Try keeping everything on the same line
@ -377,8 +378,7 @@ impl<'a> FmtVisitor<'a> {
vis: ast::Visibility,
enum_def: &ast::EnumDef,
generics: &ast::Generics,
span: Span)
{
span: Span) {
let header_str = self.format_header("enum ", ident, vis);
self.changes.push_str_span(span, &header_str);
@ -409,18 +409,14 @@ impl<'a> FmtVisitor<'a> {
}
// Variant of an enum
fn visit_variant(&mut self,
field: &ast::Variant,
last_field: bool,
next_span_start: BytePos)
{
fn visit_variant(&mut self, field: &ast::Variant, last_field: bool, next_span_start: BytePos) {
if self.visit_attrs(&field.node.attrs) {
return;
}
self.format_missing_with_indent(field.span.lo);
match field.node.kind {
let result = match field.node.kind {
ast::VariantKind::TupleVariantKind(ref types) => {
let vis = format_visibility(field.node.vis);
self.changes.push_str_span(field.span, vis);
@ -475,23 +471,23 @@ impl<'a> FmtVisitor<'a> {
"Enum variant exceeded column limit");
}
self.changes.push_str_span(field.span, &result);
if !last_field || self.config.enum_trailing_comma {
self.changes.push_str_span(field.span, ",");
}
result
},
ast::VariantKind::StructVariantKind(ref struct_def) => {
let result = self.format_struct("",
field.node.name,
field.node.vis,
struct_def,
None,
field.span,
self.block_indent);
self.changes.push_str_span(field.span, &result)
// TODO Should limit the width, as we have a trailing comma
self.format_struct("",
field.node.name,
field.node.vis,
struct_def,
None,
field.span,
self.block_indent)
}
};
self.changes.push_str_span(field.span, &result);
if !last_field || self.config.enum_trailing_comma {
self.changes.push_str_span(field.span, ",");
}
self.last_pos = field.span.hi + BytePos(1);
@ -504,8 +500,8 @@ impl<'a> FmtVisitor<'a> {
struct_def: &ast::StructDef,
generics: Option<&ast::Generics>,
span: Span,
offset: usize) -> String
{
offset: usize)
-> String {
let mut result = String::with_capacity(1024);
let header_str = self.format_header(item_name, ident, vis);
@ -557,8 +553,7 @@ impl<'a> FmtVisitor<'a> {
// Conservative approximation
let single_line_cost = (span.hi - struct_def.fields[0].span.lo).0;
let break_line = !is_tuple ||
generics_str.contains('\n') ||
let break_line = !is_tuple || generics_str.contains('\n') ||
single_line_cost as usize + used_budget > self.config.max_width;
if break_line {
@ -571,15 +566,13 @@ impl<'a> FmtVisitor<'a> {
// 1 = ,
let budget = self.config.ideal_width - offset + self.config.tab_spaces - 1;
let fmt = ListFormatting {
tactic: tactic,
separator: ",",
trailing_separator: self.config.struct_trailing_comma,
indent: offset + self.config.tab_spaces,
h_width: self.config.max_width,
v_width: budget,
ends_with_newline: false,
};
let fmt = ListFormatting { tactic: tactic,
separator: ",",
trailing_separator: self.config.struct_trailing_comma,
indent: offset + self.config.tab_spaces,
h_width: self.config.max_width,
v_width: budget,
ends_with_newline: false, };
result.push_str(&write_list(&items, &fmt));
@ -602,8 +595,7 @@ impl<'a> FmtVisitor<'a> {
vis: ast::Visibility,
struct_def: &ast::StructDef,
generics: &ast::Generics,
span: Span)
{
span: Span) {
let indent = self.block_indent;
let result = self.format_struct("struct ",
ident,
@ -616,12 +608,7 @@ impl<'a> FmtVisitor<'a> {
self.last_pos = span.hi;
}
fn format_header(&self,
item_name: &str,
ident: ast::Ident,
vis: ast::Visibility)
-> String
{
fn format_header(&self, item_name: &str, ident: ast::Ident, vis: ast::Visibility) -> String {
format!("{}{}{}", format_visibility(vis), item_name, &token::get_ident(ident))
}
@ -630,8 +617,7 @@ impl<'a> FmtVisitor<'a> {
opener: &str,
offset: usize,
span: Span)
-> String
{
-> String {
let mut result = self.rewrite_generics(generics, offset, span);
if generics.where_clause.predicates.len() > 0 || result.contains('\n') {
@ -721,15 +707,13 @@ impl<'a> FmtVisitor<'a> {
item.item = ty;
}
let fmt = ListFormatting {
tactic: ListTactic::HorizontalVertical,
separator: ",",
trailing_separator: SeparatorTactic::Never,
indent: offset + 1,
h_width: budget,
v_width: budget,
ends_with_newline: true,
};
let fmt = ListFormatting { tactic: ListTactic::HorizontalVertical,
separator: ",",
trailing_separator: SeparatorTactic::Never,
indent: offset + 1,
h_width: budget,
v_width: budget,
ends_with_newline: true, };
result.push_str(&write_list(&items, &fmt));
result.push('>');
@ -741,8 +725,7 @@ impl<'a> FmtVisitor<'a> {
where_clause: &ast::WhereClause,
indent: usize,
span_end: BytePos)
-> String
{
-> String {
let mut result = String::new();
if where_clause.predicates.len() == 0 {
return result;
@ -765,15 +748,13 @@ impl<'a> FmtVisitor<'a> {
span_end);
let budget = self.config.ideal_width + self.config.leeway - indent - 10;
let fmt = ListFormatting {
tactic: ListTactic::Vertical,
separator: ",",
trailing_separator: SeparatorTactic::Never,
indent: indent + 10,
h_width: budget,
v_width: budget,
ends_with_newline: true,
};
let fmt = ListFormatting { tactic: ListTactic::Vertical,
separator: ",",
trailing_separator: SeparatorTactic::Never,
indent: indent + 10,
h_width: budget,
v_width: budget,
ends_with_newline: true, };
result.push_str(&write_list(&items, &fmt));
result

View File

@ -167,11 +167,6 @@ impl fmt::Display for FormatReport {
fn fmt_ast<'a>(krate: &ast::Crate, codemap: &'a CodeMap, config: &'a Config) -> ChangeSet<'a> {
let mut visitor = FmtVisitor::from_codemap(codemap, config);
visit::walk_crate(&mut visitor, krate);
let files = codemap.files.borrow();
if let Some(last) = files.last() {
visitor.format_missing(last.end_pos);
}
visitor.changes
}

View File

@ -48,20 +48,19 @@ pub struct ListFormatting<'a> {
pub v_width: usize,
// Non-expressions, e.g. items, will have a new line at the end of the list.
// Important for comment styles.
pub ends_with_newline: bool
pub ends_with_newline: bool,
}
pub struct ListItem {
pub pre_comment: Option<String>,
// Item should include attributes and doc comments
pub item: String,
pub post_comment: Option<String>
pub post_comment: Option<String>,
}
impl ListItem {
pub fn is_multiline(&self) -> bool {
self.item.contains('\n') ||
self.pre_comment.is_some() ||
self.item.contains('\n') || self.pre_comment.is_some() ||
self.post_comment.as_ref().map(|s| s.contains('\n')).unwrap_or(false)
}
@ -70,11 +69,7 @@ impl ListItem {
}
pub fn from_str<S: Into<String>>(s: S) -> ListItem {
ListItem {
pre_comment: None,
item: s.into(),
post_comment: None
}
ListItem { pre_comment: None, item: s.into(), post_comment: None }
}
}
@ -239,8 +234,8 @@ pub fn itemize_list<T, I, F1, F2, F3>(codemap: &CodeMap,
get_item_string: F3,
mut prev_span_end: BytePos,
next_span_start: BytePos)
-> Vec<ListItem>
where I: Iterator<Item=T>,
-> Vec<ListItem>
where I: Iterator<Item = T>,
F1: Fn(&T) -> BytePos,
F2: Fn(&T) -> BytePos,
F3: Fn(&T) -> String

View File

@ -36,8 +36,7 @@ impl<'a> FmtVisitor<'a> {
fn format_missing_inner<F: Fn(&mut FmtVisitor, &str, &str, &str)>(&mut self,
end: BytePos,
process_last_snippet: F)
{
process_last_snippet: F) {
let start = self.last_pos;
debug!("format_missing_inner: {:?} to {:?}",
self.codemap.lookup_char_pos(start),

View File

@ -15,8 +15,7 @@ use syntax::parse::token;
use syntax::print::pprust;
impl<'a> FmtVisitor<'a> {
pub fn rewrite_pred(&self, predicate: &ast::WherePredicate) -> String
{
pub fn rewrite_pred(&self, predicate: &ast::WherePredicate) -> String {
// TODO dead spans
// TODO assumes we'll always fit on one line...
match predicate {
@ -49,8 +48,7 @@ impl<'a> FmtVisitor<'a> {
}
}
pub fn rewrite_lifetime_def(&self, lifetime: &ast::LifetimeDef) -> String
{
pub fn rewrite_lifetime_def(&self, lifetime: &ast::LifetimeDef) -> String {
if lifetime.bounds.len() == 0 {
return pprust::lifetime_to_string(&lifetime.lifetime);
}
@ -60,8 +58,7 @@ impl<'a> FmtVisitor<'a> {
lifetime.bounds.iter().map(|l| pprust::lifetime_to_string(l)).collect::<Vec<_>>().connect(" + "))
}
pub fn rewrite_ty_bound(&self, bound: &ast::TyParamBound) -> String
{
pub fn rewrite_ty_bound(&self, bound: &ast::TyParamBound) -> String {
match *bound {
ast::TyParamBound::TraitTyParamBound(ref tref, ast::TraitBoundModifier::None) => {
self.rewrite_poly_trait_ref(tref)
@ -75,8 +72,7 @@ impl<'a> FmtVisitor<'a> {
}
}
pub fn rewrite_ty_param(&self, ty_param: &ast::TyParam) -> String
{
pub fn rewrite_ty_param(&self, ty_param: &ast::TyParam) -> String {
let mut result = String::with_capacity(128);
result.push_str(&token::get_ident(ty_param.ident));
if ty_param.bounds.len() > 0 {
@ -91,8 +87,7 @@ impl<'a> FmtVisitor<'a> {
result
}
fn rewrite_poly_trait_ref(&self, t: &ast::PolyTraitRef) -> String
{
fn rewrite_poly_trait_ref(&self, t: &ast::PolyTraitRef) -> String {
if t.bound_lifetimes.len() > 0 {
format!("for<{}> {}",
t.bound_lifetimes.iter().map(|l| self.rewrite_lifetime_def(l)).collect::<Vec<_>>().connect(", "),

View File

@ -8,7 +8,7 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use syntax::ast::{Visibility, Attribute, MetaItem, MetaItem_};
use syntax::ast::{self, Visibility, Attribute, MetaItem, MetaItem_};
use syntax::codemap::{CodeMap, Span, BytePos};
use comment::FindUncommented;
@ -72,6 +72,14 @@ pub fn contains_skip(attrs: &[Attribute]) -> bool {
attrs.iter().any(|a| is_skip(&a.node.value))
}
// Find the end of a TyParam
pub fn end_typaram(typaram: &ast::TyParam) -> BytePos {
typaram.bounds.last().map(|bound| match *bound {
ast::RegionTyParamBound(ref lt) => lt.span,
ast::TraitTyParamBound(ref prt, _) => prt.span,
}).unwrap_or(typaram.span).hi
}
#[inline]
#[cfg(target_pointer_width="64")]
// Based on the trick layed out at

View File

@ -11,9 +11,13 @@
use syntax::ast;
use syntax::codemap::{self, CodeMap, Span, BytePos};
use syntax::visit;
use syntax::parse::token;
use syntax::attr;
use std::path::PathBuf;
use utils;
use config::Config;
use comment::FindUncommented;
use changes::ChangeSet;
use rewrite::{Rewrite, RewriteContext};
@ -197,7 +201,6 @@ impl<'a, 'v> visit::Visitor<'v> for FmtVisitor<'a> {
visit::walk_item(self, item);
}
ast::Item_::ItemImpl(..) |
ast::Item_::ItemMod(_) |
ast::Item_::ItemTrait(..) => {
self.block_indent += self.config.tab_spaces;
visit::walk_item(self, item);
@ -227,6 +230,10 @@ impl<'a, 'v> visit::Visitor<'v> for FmtVisitor<'a> {
item.span);
self.last_pos = item.span.hi;
}
ast::Item_::ItemMod(ref module) => {
self.format_missing_with_indent(item.span.lo);
self.format_mod(module, item.span, item.ident, &item.attrs);
}
_ => {
visit::walk_item(self, item);
}
@ -267,24 +274,19 @@ impl<'a, 'v> visit::Visitor<'v> for FmtVisitor<'a> {
}
fn visit_mod(&mut self, m: &'v ast::Mod, s: Span, _: ast::NodeId) {
// Only visit inline mods here.
if self.codemap.lookup_char_pos(s.lo).file.name !=
self.codemap.lookup_char_pos(m.inner.lo).file.name {
return;
}
visit::walk_mod(self, m);
// This is only called for the root module
let filename = self.codemap.span_to_filename(s);
self.format_separate_mod(m, &filename);
}
}
impl<'a> FmtVisitor<'a> {
pub fn from_codemap<'b>(codemap: &'b CodeMap, config: &'b Config) -> FmtVisitor<'b> {
FmtVisitor {
codemap: codemap,
changes: ChangeSet::from_codemap(codemap),
last_pos: BytePos(0),
block_indent: 0,
config: config
}
FmtVisitor { codemap: codemap,
changes: ChangeSet::from_codemap(codemap),
last_pos: BytePos(0),
block_indent: 0,
config: config, }
}
pub fn snippet(&self, span: Span) -> String {
@ -352,4 +354,82 @@ impl<'a> FmtVisitor<'a> {
result
}
fn format_mod(&mut self, m: &ast::Mod, s: Span, ident: ast::Ident, attrs: &[ast::Attribute]) {
debug!("FmtVisitor::format_mod: ident: {:?}, span: {:?}", ident, s);
// Decide whether this is an inline mod or an external mod.
// There isn't any difference between inline and external mod in AST,
// so we use the trick of searching for an opening brace.
// We can't use the inner span of the mod since it is weird when it
// is empty (no items).
// FIXME Use the inner span once rust-lang/rust#26755 is fixed.
let open_brace = self.codemap.span_to_snippet(s).unwrap().find_uncommented("{");
match open_brace {
None => {
debug!("FmtVisitor::format_mod: external mod");
let file_path = self.module_file(ident, attrs, s);
let filename = file_path.to_str().unwrap();
if self.changes.is_changed(filename) {
// The file has already been reformatted, do nothing
} else {
self.format_separate_mod(m, filename);
}
// TODO Should rewrite properly `mod X;`
}
Some(open_brace) => {
debug!("FmtVisitor::format_mod: internal mod");
debug!("... open_brace: {}, str: {:?}", open_brace, self.codemap.span_to_snippet(s));
// Format everything until opening brace
// TODO Shoud rewrite properly
self.format_missing(s.lo + BytePos(open_brace as u32));
self.block_indent += self.config.tab_spaces;
visit::walk_mod(self, m);
debug!("... last_pos after: {:?}", self.last_pos);
self.block_indent -= self.config.tab_spaces;
}
}
self.format_missing(s.hi);
debug!("FmtVisitor::format_mod: exit");
}
/// Find the file corresponding to an external mod
/// Same algorithm as syntax::parse::eval_src_mod
fn module_file(&self, id: ast::Ident, outer_attrs: &[ast::Attribute], id_sp: Span) -> PathBuf {
// FIXME use libsyntax once rust-lang/rust#26750 is merged
let mut prefix = PathBuf::from(&self.codemap.span_to_filename(id_sp));
prefix.pop();
let mod_string = token::get_ident(id);
match attr::first_attr_value_str_by_name(outer_attrs, "path") {
Some(d) => prefix.join(&*d),
None => {
let default_path_str = format!("{}.rs", mod_string);
let secondary_path_str = format!("{}/mod.rs", mod_string);
let default_path = prefix.join(&default_path_str);
let secondary_path = prefix.join(&secondary_path_str);
let default_exists = self.codemap.file_exists(&default_path);
let secondary_exists = self.codemap.file_exists(&secondary_path);
if default_exists {
default_path
} else if secondary_exists {
secondary_path
} else {
// Should never appens since rustc parsed everything sucessfully
panic!("Didn't found module {}", mod_string);
}
}
}
}
/// Format the content of a module into a separate file
fn format_separate_mod(&mut self, m: &ast::Mod, filename: &str) {
let last_pos = self.last_pos;
let block_indent = self.block_indent;
let filemap = self.codemap.get_filemap(filename);
self.last_pos = filemap.start_pos;
self.block_indent = 0;
visit::walk_mod(self, m);
self.format_missing(filemap.end_pos);
self.last_pos = last_pos;
self.block_indent = block_indent;
}
}

3
tests/source/mod-2.rs Normal file
View File

@ -0,0 +1,3 @@
// Some nested mods
mod nestedmod;

View File

@ -0,0 +1,12 @@
mod mod2a;
mod mod2b;
mod mymod1 {
use mod2a::{Foo,Bar};
}
#[path="mod2c.rs"]
mod mymod2;
mod submod2;

View File

@ -0,0 +1,4 @@
// This is an empty file containing only
// comments
// ...................

View File

@ -0,0 +1,3 @@
#[path="mod2a.rs"]
mod c;

View File

@ -0,0 +1,3 @@
// A standard mod
fn a( ) {}

View File

@ -0,0 +1,6 @@
// Yet Another mod
// Nested
use c::a;
fn foo( ) { }

View File

@ -0,0 +1,5 @@
// Another mod
mod a;
use a::a;

View File

@ -40,5 +40,8 @@ enum StructLikeVariants {
// Pre-comment
#[Attr50]
y: SomeType, // Aanother Comment
}
},
SL {
a: A,
},
}

View File

@ -34,6 +34,9 @@ fn foo<U, T>(a: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA,
}
fn foo<U: Fn(A) -> B /* paren inside generics */>() {
}
impl Foo {
fn with_no_errors<T, F>(&mut self, f: F) -> T
where F: FnOnce(&mut Resolver) -> T

3
tests/target/mod-2.rs Normal file
View File

@ -0,0 +1,3 @@
// Some nested mods
mod nestedmod;

View File

@ -0,0 +1,12 @@
mod mod2a;
mod mod2b;
mod mymod1 {
use mod2a::{Foo, Bar};
}
#[path="mod2c.rs"]
mod mymod2;
mod submod2;

View File

@ -0,0 +1,4 @@
// This is an empty file containing only
// comments
// ...................

View File

@ -0,0 +1,3 @@
#[path="mod2a.rs"]
mod c;

View File

@ -0,0 +1,4 @@
// A standard mod
fn a() {
}

View File

@ -0,0 +1,7 @@
// Yet Another mod
// Nested
use c::a;
fn foo() {
}

View File

@ -0,0 +1,5 @@
// Another mod
mod a;
use a::a;