Merge pull request #646 from rust-lang-nursery/mulit-file

Handle multiply-referenced files
This commit is contained in:
Marcus Klaas de Vries 2015-11-23 21:35:09 +01:00
commit 5a3f5bc1f6
11 changed files with 228 additions and 35 deletions

View File

@ -219,7 +219,10 @@ pub enum CodeCharKind {
Comment,
}
impl<T> CharClasses<T> where T: Iterator, T::Item: RichChar {
impl<T> CharClasses<T>
where T: Iterator,
T::Item: RichChar
{
fn new(base: T) -> CharClasses<T> {
CharClasses {
base: base.peekable(),
@ -228,7 +231,10 @@ impl<T> CharClasses<T> where T: Iterator, T::Item: RichChar {
}
}
impl<T> Iterator for CharClasses<T> where T: Iterator, T::Item: RichChar {
impl<T> Iterator for CharClasses<T>
where T: Iterator,
T::Item: RichChar
{
type Item = (CodeCharKind, T::Item);
fn next(&mut self) -> Option<(CodeCharKind, T::Item)> {

View File

@ -12,7 +12,7 @@
use Indent;
use utils::{format_mutability, format_visibility, contains_skip, span_after, end_typaram,
wrap_str, last_line_width, semicolon_for_expr};
wrap_str, last_line_width, semicolon_for_expr, format_unsafety, trim_newlines};
use lists::{write_list, itemize_list, ListItem, ListFormatting, SeparatorTactic,
DefinitiveListTactic, definitive_tactic, format_item_list};
use expr::{is_empty_block, is_simple_block_stmt, rewrite_assign_rhs};
@ -435,6 +435,104 @@ impl<'a> FmtVisitor<'a> {
}
}
pub fn format_impl(context: &RewriteContext, item: &ast::Item, offset: Indent) -> Option<String> {
if let ast::Item_::ItemImpl(unsafety,
polarity,
ref generics,
ref trait_ref,
ref self_ty,
ref items) = item.node {
let mut result = String::new();
result.push_str(format_visibility(item.vis));
result.push_str(format_unsafety(unsafety));
result.push_str("impl");
let lo = span_after(item.span, "impl", context.codemap);
let hi = match *trait_ref {
Some(ref tr) => tr.path.span.lo,
None => self_ty.span.lo,
};
let generics_str = try_opt!(rewrite_generics(context,
generics,
offset,
offset + result.len(),
mk_sp(lo, hi)));
result.push_str(&generics_str);
// FIXME might need to linebreak in the impl header, here would be a
// good place.
result.push(' ');
if polarity == ast::ImplPolarity::Negative {
result.push_str("!");
}
if let &Some(ref trait_ref) = trait_ref {
let budget = try_opt!(context.config.max_width.checked_sub(result.len()));
let indent = offset + result.len();
result.push_str(&*try_opt!(trait_ref.rewrite(context, budget, indent)));
result.push_str(" for ");
}
let budget = try_opt!(context.config.max_width.checked_sub(result.len()));
let indent = offset + result.len();
result.push_str(&*try_opt!(self_ty.rewrite(context, budget, indent)));
let where_clause_str = try_opt!(rewrite_where_clause(context,
&generics.where_clause,
context.config,
context.block_indent,
context.config.where_density,
"{",
None));
if !where_clause_str.contains('\n') &&
result.len() + where_clause_str.len() + offset.width() > context.config.max_width {
result.push('\n');
let width = context.block_indent.width() + context.config.tab_spaces - 1;
let where_indent = Indent::new(0, width);
result.push_str(&where_indent.to_string(context.config));
}
result.push_str(&where_clause_str);
match context.config.item_brace_style {
BraceStyle::AlwaysNextLine => result.push('\n'),
BraceStyle::PreferSameLine => result.push(' '),
BraceStyle::SameLineWhere => {
if where_clause_str.len() > 0 {
result.push('\n')
} else {
result.push(' ')
}
}
}
result.push('{');
if !items.is_empty() {
result.push('\n');
let indent_str = context.block_indent.to_string(context.config);
result.push_str(&indent_str);
let mut visitor = FmtVisitor::from_codemap(context.parse_session, context.config, None);
visitor.block_indent = context.block_indent.block_indent(context.config);
let snippet = context.snippet(item.span);
let open_pos = try_opt!(snippet.find_uncommented("{")) + 1;
visitor.last_pos = item.span.lo + BytePos(open_pos as u32);
for item in items {
visitor.visit_impl_item(&item);
}
result.push_str(trim_newlines(&visitor.buffer.to_string()));
result.push('\n');
result.push_str(&indent_str);
}
result.push('}');
Some(result)
} else {
unreachable!();
}
}
pub fn format_struct(context: &RewriteContext,
item_name: &str,
ident: ast::Ident,

View File

@ -298,7 +298,7 @@ fn fmt_ast(krate: &ast::Crate,
println!("Formatting {}", path);
}
let mut visitor = FmtVisitor::from_codemap(parse_session, config, Some(mode));
visitor.format_separate_mod(module, path);
visitor.format_separate_mod(module);
file_map.insert(path.to_owned(), visitor.buffer);
}
file_map
@ -404,7 +404,7 @@ pub fn format_string(input: String, config: &Config, mode: WriteMode) -> FileMap
// do the actual formatting
let mut visitor = FmtVisitor::from_codemap(&parse_session, config, Some(mode));
visitor.format_separate_mod(&krate.module, path);
visitor.format_separate_mod(&krate.module);
// append final newline
visitor.buffer.push_str("\n");

View File

@ -215,8 +215,12 @@ fn rewrite_segment(expr_context: bool,
format!("{}<{}>", separator, list_str)
}
ast::PathParameters::ParenthesizedParameters(ref data) => {
let output = match data.output {
Some(ref ty) => FunctionRetTy::Return(ty.clone()),
None => FunctionRetTy::DefaultReturn(codemap::DUMMY_SP),
};
try_opt!(format_function_type(data.inputs.iter().map(|x| &**x),
data.output.as_ref().map(|x| &**x),
&output,
data.span,
context,
width,
@ -229,7 +233,7 @@ fn rewrite_segment(expr_context: bool,
}
fn format_function_type<'a, I>(inputs: I,
output: Option<&ast::Ty>,
output: &FunctionRetTy,
span: Span,
context: &RewriteContext,
width: usize,
@ -253,13 +257,14 @@ fn format_function_type<'a, I>(inputs: I,
let list_str = try_opt!(format_fn_args(items, budget, offset, context.config));
let output = match output {
Some(ref ty) => {
let output = match *output {
FunctionRetTy::Return(ref ty) => {
let budget = try_opt!(width.checked_sub(4));
let type_str = try_opt!(ty.rewrite(context, budget, offset + 4));
format!(" -> {}", type_str)
}
None => String::new(),
FunctionRetTy::NoReturn(..) => " -> !".to_owned(),
FunctionRetTy::DefaultReturn(..) => String::new(),
};
let infix = if output.len() + list_str.len() > width {
@ -432,20 +437,22 @@ impl Rewrite for ast::PolyTraitRef {
// 6 is "for<> ".len()
let extra_offset = lifetime_str.len() + 6;
let max_path_width = try_opt!(width.checked_sub(extra_offset));
let path_str = try_opt!(rewrite_path(context,
false,
None,
&self.trait_ref.path,
max_path_width,
offset + extra_offset));
let path_str = try_opt!(self.trait_ref
.rewrite(context, max_path_width, offset + extra_offset));
Some(format!("for<{}> {}", lifetime_str, path_str))
} else {
rewrite_path(context, false, None, &self.trait_ref.path, width, offset)
self.trait_ref.rewrite(context, width, offset)
}
}
}
impl Rewrite for ast::TraitRef {
fn rewrite(&self, context: &RewriteContext, width: usize, offset: Indent) -> Option<String> {
rewrite_path(context, false, None, &self.path, width, offset)
}
}
impl Rewrite for ast::Ty {
fn rewrite(&self, context: &RewriteContext, width: usize, offset: Indent) -> Option<String> {
match self.node {
@ -538,17 +545,11 @@ fn rewrite_bare_fn(bare_fn: &ast::BareFnTy,
result.push_str("fn");
let output = match bare_fn.decl.output {
FunctionRetTy::Return(ref ty) => Some(&**ty),
FunctionRetTy::NoReturn(..) => None,
FunctionRetTy::DefaultReturn(..) => unreachable!(),
};
let budget = try_opt!(width.checked_sub(result.len()));
let indent = offset + result.len();
let rewrite = try_opt!(format_function_type(bare_fn.decl.inputs.iter().map(|x| &*(x.ty)),
output,
&bare_fn.decl.output,
span,
context,
budget,

View File

@ -142,6 +142,13 @@ pub fn semicolon_for_stmt(stmt: &ast::Stmt) -> bool {
}
}
#[inline]
pub fn trim_newlines(input: &str) -> &str {
let start = input.find(|c| c != '\n' && c != '\r').unwrap_or(0);
let end = input.rfind(|c| c != '\n' && c != '\r').unwrap_or(0) + 1;
&input[start..end]
}
#[inline]
#[cfg(target_pointer_width="64")]
// Based on the trick layed out at

View File

@ -21,7 +21,7 @@ use config::Config;
use rewrite::{Rewrite, RewriteContext};
use comment::rewrite_comment;
use macros::rewrite_macro;
use items::rewrite_static;
use items::{rewrite_static, format_impl};
pub struct FmtVisitor<'a> {
pub parse_session: &'a ParseSess,
@ -200,14 +200,12 @@ impl<'a> FmtVisitor<'a> {
ast::Item_::ItemUse(ref vp) => {
self.format_import(item.vis, vp, item.span);
}
// FIXME(#78): format impl definitions.
ast::Item_::ItemImpl(_, _, _, _, _, ref impl_items) => {
ast::Item_::ItemImpl(..) => {
self.format_missing_with_indent(item.span.lo);
self.block_indent = self.block_indent.block_indent(self.config);
for item in impl_items {
self.visit_impl_item(&item);
if let Some(impl_str) = format_impl(&self.get_context(), item, self.block_indent) {
self.buffer.push_str(&impl_str);
self.last_pos = item.span.hi;
}
self.block_indent = self.block_indent.block_unindent(self.config);
}
// FIXME(#78): format traits.
ast::Item_::ItemTrait(_, _, _, ref trait_items) => {
@ -334,7 +332,7 @@ impl<'a> FmtVisitor<'a> {
}
}
fn visit_impl_item(&mut self, ii: &ast::ImplItem) {
pub fn visit_impl_item(&mut self, ii: &ast::ImplItem) {
if self.visit_attrs(&ii.attrs) {
return;
}
@ -465,8 +463,8 @@ impl<'a> FmtVisitor<'a> {
}
}
pub fn format_separate_mod(&mut self, m: &ast::Mod, filename: &str) {
let filemap = self.codemap.get_filemap(filename);
pub fn format_separate_mod(&mut self, m: &ast::Mod) {
let filemap = self.codemap.lookup_char_pos(m.inner.lo).file;
self.last_pos = filemap.start_pos;
self.block_indent = Indent::empty();
self.walk_mod_items(m);

23
tests/source/impls.rs Normal file
View File

@ -0,0 +1,23 @@
impl Foo for Bar { fn foo() { "hi" } }
pub impl Foo for Bar {
// Comment 1
fn foo() { "hi" }
// Comment 2
fn foo() { "hi" }
// Comment 3
}
pub unsafe impl<'a, 'b, X, Y: Foo<Bar>> !Foo<'a, X> for Bar<'b, Y> where X: Foo<'a, Z> {
fn foo() { "hi" }
}
impl<'a, 'b, X, Y: Foo<Bar>> Foo<'a, X> for Bar<'b, Y> where X: Fooooooooooooooooooooooooooooo<'a, Z>
{
fn foo() { "hi" }
}
impl<'a, 'b, X, Y: Foo<Bar>> Foo<'a, X> for Bar<'b, Y> where X: Foooooooooooooooooooooooooooo<'a, Z>
{
fn foo() { "hi" }
}

12
tests/target/fn-ty.rs Normal file
View File

@ -0,0 +1,12 @@
fn f(xxxxxxxxxxxxxxxxxx: fn(a, b, b) -> a,
xxxxxxxxxxxxxxxxxx: fn() -> a,
xxxxxxxxxxxxxxxxxx: fn(a, b, b),
xxxxxxxxxxxxxxxxxx: fn(),
xxxxxxxxxxxxxxxxxx: fn(a, b, b) -> !,
xxxxxxxxxxxxxxxxxx: fn() -> !)
where F1: Fn(a, b, b) -> a,
F2: Fn(a, b, b),
F3: Fn(),
F4: Fn() -> u32
{
}

38
tests/target/impls.rs Normal file
View File

@ -0,0 +1,38 @@
impl Foo for Bar {
fn foo() {
"hi"
}
}
pub impl Foo for Bar {
// Comment 1
fn foo() {
"hi"
}
// Comment 2
fn foo() {
"hi"
}
}
pub unsafe impl<'a, 'b, X, Y: Foo<Bar>> !Foo<'a, X> for Bar<'b, Y> where X: Foo<'a, Z>
{
fn foo() {
"hi"
}
}
impl<'a, 'b, X, Y: Foo<Bar>> Foo<'a, X> for Bar<'b, Y>
where X: Fooooooooooooooooooooooooooooo<'a, Z>
{
fn foo() {
"hi"
}
}
impl<'a, 'b, X, Y: Foo<Bar>> Foo<'a, X> for Bar<'b, Y> where X: Foooooooooooooooooooooooooooo<'a, Z>
{
fn foo() {
"hi"
}
}

View File

@ -0,0 +1,10 @@
// Tests that where a single file is referred to in multiple places, we don't
// crash.
#[cfg(all(foo))]
#[path = "closure.rs"]
pub mod imp;
#[cfg(all(bar))]
#[path = "closure.rs"]
pub mod imp;

View File

@ -15,7 +15,7 @@ fn main() {
}
}
impl<'a,'b> ResolveGeneratedContentFragmentMutator<'a,'b> {
impl<'a, 'b> ResolveGeneratedContentFragmentMutator<'a, 'b> {
fn mutate_fragment(&mut self, fragment: &mut Fragment) {
match **info {
GeneratedContentInfo::ContentItem(ContentItem::Counter(ref counter_name,