Format paths
This commit is contained in:
parent
78b38c84c6
commit
41bca58100
32
src/expr.rs
32
src/expr.rs
@ -12,14 +12,14 @@
|
||||
use lists::{write_list, itemize_list, ListFormatting, SeparatorTactic, ListTactic};
|
||||
use string::{StringFormat, rewrite_string};
|
||||
use StructLitStyle;
|
||||
use utils::{span_after, make_indent};
|
||||
use utils::{span_after, make_indent, extra_offset};
|
||||
use visitor::FmtVisitor;
|
||||
use config::BlockIndentStyle;
|
||||
use comment::{FindUncommented, rewrite_comment};
|
||||
use types::rewrite_path;
|
||||
|
||||
use syntax::{ast, ptr};
|
||||
use syntax::codemap::{Pos, Span, BytePos, mk_sp};
|
||||
use syntax::print::pprust;
|
||||
use syntax::visit::Visitor;
|
||||
|
||||
impl Rewrite for ast::Expr {
|
||||
@ -99,6 +99,9 @@ fn rewrite(&self, context: &RewriteContext, width: usize, offset: usize) -> Opti
|
||||
width,
|
||||
offset)
|
||||
}
|
||||
ast::Expr_::ExprPath(ref qself, ref path) => {
|
||||
rewrite_path(context, qself.as_ref(), path, width, offset)
|
||||
}
|
||||
_ => context.codemap.span_to_snippet(self.span).ok()
|
||||
}
|
||||
}
|
||||
@ -320,11 +323,7 @@ fn rewrite_pat_expr(context: &RewriteContext,
|
||||
};
|
||||
|
||||
// Consider only the last line of the pat string.
|
||||
let extra_offset = match result.rfind('\n') {
|
||||
// 1 for newline character
|
||||
Some(idx) => result.len() - idx - 1 - offset,
|
||||
None => result.len()
|
||||
};
|
||||
let extra_offset = extra_offset(&result, offset);
|
||||
|
||||
// The expression may (partionally) fit on the current line.
|
||||
if width > extra_offset + 1 {
|
||||
@ -391,16 +390,19 @@ fn rewrite_call(context: &RewriteContext,
|
||||
debug!("rewrite_call, width: {}, offset: {}", width, offset);
|
||||
|
||||
// TODO using byte lens instead of char lens (and probably all over the place too)
|
||||
let callee_str = try_opt!(callee.rewrite(context, width, offset));
|
||||
// 2 is for parens
|
||||
let max_callee_width = try_opt!(width.checked_sub(2));
|
||||
let callee_str = try_opt!(callee.rewrite(context, max_callee_width, offset));
|
||||
debug!("rewrite_call, callee_str: `{}`", callee_str);
|
||||
|
||||
if args.len() == 0 {
|
||||
return Some(format!("{}()", callee_str));
|
||||
}
|
||||
|
||||
let extra_offset = extra_offset(&callee_str, offset);
|
||||
// 2 is for parens.
|
||||
let remaining_width = try_opt!(width.checked_sub(callee_str.len() + 2));
|
||||
let offset = callee_str.len() + 1 + offset;
|
||||
let remaining_width = try_opt!(width.checked_sub(extra_offset + 2));
|
||||
let offset = offset + extra_offset + 1;
|
||||
let block_indent = expr_block_indent(context, offset);
|
||||
let inner_context = &RewriteContext { block_indent: block_indent, ..*context };
|
||||
|
||||
@ -425,7 +427,7 @@ fn rewrite_call(context: &RewriteContext,
|
||||
indent: offset,
|
||||
h_width: remaining_width,
|
||||
v_width: remaining_width,
|
||||
ends_with_newline: true,
|
||||
ends_with_newline: false,
|
||||
};
|
||||
|
||||
Some(format!("{}({})", callee_str, write_list(&items, &fmt)))
|
||||
@ -468,7 +470,9 @@ enum StructLitField<'a> {
|
||||
Base(&'a ast::Expr),
|
||||
}
|
||||
|
||||
let path_str = pprust::path_to_string(path);
|
||||
// 2 = " {".len()
|
||||
let path_str = try_opt!(path.rewrite(context, width - 2, offset));
|
||||
|
||||
// Foo { a: Foo } - indent is +3, width is -5.
|
||||
let h_budget = width.checked_sub(path_str.len() + 5).unwrap_or(0);
|
||||
let (indent, v_budget) = match context.config.struct_lit_style {
|
||||
@ -537,7 +541,7 @@ enum StructLitField<'a> {
|
||||
indent: indent,
|
||||
h_width: h_budget,
|
||||
v_width: v_budget,
|
||||
ends_with_newline: true,
|
||||
ends_with_newline: false,
|
||||
};
|
||||
let fields_str = write_list(&items, &fmt);
|
||||
|
||||
@ -601,7 +605,7 @@ fn rewrite_tuple_lit(context: &RewriteContext,
|
||||
indent: indent,
|
||||
h_width: width - 2,
|
||||
v_width: width - 2,
|
||||
ends_with_newline: true,
|
||||
ends_with_newline: false,
|
||||
};
|
||||
|
||||
Some(format!("({})", write_list(&items, &fmt)))
|
||||
|
@ -11,11 +11,9 @@
|
||||
use lists::{write_list, itemize_list, ListItem, ListFormatting, SeparatorTactic, ListTactic};
|
||||
use utils::span_after;
|
||||
use rewrite::{Rewrite, RewriteContext};
|
||||
use config::Config;
|
||||
|
||||
use syntax::ast;
|
||||
use syntax::print::pprust;
|
||||
use syntax::codemap::{CodeMap, Span};
|
||||
use syntax::codemap::Span;
|
||||
|
||||
// TODO (some day) remove unused imports, expand globs, compress many single imports into a list import
|
||||
|
||||
@ -29,20 +27,21 @@ fn rewrite(&self, context: &RewriteContext, width: usize, offset: usize) -> Opti
|
||||
path,
|
||||
path_list,
|
||||
self.span,
|
||||
context.codemap,
|
||||
context.config).unwrap_or("".to_owned()))
|
||||
context).unwrap_or("".to_owned()))
|
||||
}
|
||||
ast::ViewPath_::ViewPathGlob(_) => {
|
||||
// FIXME convert to list?
|
||||
None
|
||||
}
|
||||
ast::ViewPath_::ViewPathSimple(ident, ref path) => {
|
||||
let path_str = pprust::path_to_string(path);
|
||||
let ident_str = ident.to_string();
|
||||
// 4 = " as ".len()
|
||||
let path_str = try_opt!(path.rewrite(context, width - ident_str.len() - 4, offset));
|
||||
|
||||
Some(if path.segments.last().unwrap().identifier == ident {
|
||||
path_str
|
||||
} else {
|
||||
format!("{} as {}", path_str, ident)
|
||||
format!("{} as {}", path_str, ident_str)
|
||||
})
|
||||
}
|
||||
}
|
||||
@ -74,10 +73,10 @@ pub fn rewrite_use_list(width: usize,
|
||||
path: &ast::Path,
|
||||
path_list: &[ast::PathListItem],
|
||||
span: Span,
|
||||
codemap: &CodeMap,
|
||||
config: &Config)
|
||||
context: &RewriteContext)
|
||||
-> Option<String> {
|
||||
let path_str = pprust::path_to_string(path);
|
||||
// 1 = {}
|
||||
let path_str = try_opt!(path.rewrite(context, width - 1, offset));
|
||||
|
||||
match path_list.len() {
|
||||
0 => return None,
|
||||
@ -106,10 +105,10 @@ pub fn rewrite_use_list(width: usize,
|
||||
// available
|
||||
// (loose 1 column (";"))
|
||||
v_width: remaining_width,
|
||||
ends_with_newline: true,
|
||||
ends_with_newline: false,
|
||||
};
|
||||
|
||||
let mut items = itemize_list(codemap,
|
||||
let mut items = itemize_list(context.codemap,
|
||||
vec![ListItem::from_str("")], /* Dummy value, explanation
|
||||
* below */
|
||||
path_list.iter(),
|
||||
@ -125,7 +124,7 @@ pub fn rewrite_use_list(width: usize,
|
||||
"self".to_owned()
|
||||
}
|
||||
},
|
||||
span_after(span, "{", codemap),
|
||||
span_after(span, "{", context.codemap),
|
||||
span.hi);
|
||||
|
||||
// We prefixed the item list with a dummy value so that we can
|
||||
@ -140,7 +139,7 @@ pub fn rewrite_use_list(width: usize,
|
||||
1
|
||||
};
|
||||
|
||||
if config.reorder_imports {
|
||||
if context.config.reorder_imports {
|
||||
items[1..].sort_by(|a, b| a.item.cmp(&b.item));
|
||||
}
|
||||
|
||||
|
40
src/items.rs
40
src/items.rs
@ -16,6 +16,8 @@
|
||||
use lists::{write_list, itemize_list, ListItem, ListFormatting, SeparatorTactic, ListTactic};
|
||||
use comment::FindUncommented;
|
||||
use visitor::FmtVisitor;
|
||||
use rewrite::Rewrite;
|
||||
use config::Config;
|
||||
|
||||
use syntax::{ast, abi};
|
||||
use syntax::codemap::{self, Span, BytePos};
|
||||
@ -215,6 +217,7 @@ fn rewrite_fn_base(&mut self,
|
||||
|
||||
// Where clause.
|
||||
result.push_str(&self.rewrite_where_clause(where_clause,
|
||||
self.config,
|
||||
indent,
|
||||
span.hi));
|
||||
|
||||
@ -281,7 +284,7 @@ fn rewrite_args(&self,
|
||||
indent: arg_indent,
|
||||
h_width: one_line_budget,
|
||||
v_width: multi_line_budget,
|
||||
ends_with_newline: true,
|
||||
ends_with_newline: false,
|
||||
};
|
||||
|
||||
write_list(&arg_items, &fmt)
|
||||
@ -429,7 +432,7 @@ fn visit_variant(&mut self, field: &ast::Variant, last_field: bool, next_span_st
|
||||
indent: indent,
|
||||
h_width: budget,
|
||||
v_width: budget,
|
||||
ends_with_newline: false,
|
||||
ends_with_newline: true,
|
||||
};
|
||||
result.push_str(&write_list(&items, &fmt));
|
||||
result.push(')');
|
||||
@ -557,7 +560,7 @@ fn format_struct(&self,
|
||||
indent: offset + self.config.tab_spaces,
|
||||
h_width: self.config.max_width,
|
||||
v_width: budget,
|
||||
ends_with_newline: false,
|
||||
ends_with_newline: true,
|
||||
};
|
||||
|
||||
result.push_str(&write_list(&items, &fmt));
|
||||
@ -608,6 +611,7 @@ fn format_generics(&self,
|
||||
|
||||
if generics.where_clause.predicates.len() > 0 || result.contains('\n') {
|
||||
result.push_str(&self.rewrite_where_clause(&generics.where_clause,
|
||||
self.config,
|
||||
self.block_indent,
|
||||
span.hi));
|
||||
result.push_str(&make_indent(self.block_indent));
|
||||
@ -664,8 +668,15 @@ fn rewrite_generics(&self, generics: &ast::Generics, offset: usize, span: Span)
|
||||
result.push('<');
|
||||
|
||||
// Strings for the generics.
|
||||
let lt_strs = lifetimes.iter().map(|l| self.rewrite_lifetime_def(l));
|
||||
let ty_strs = tys.iter().map(|ty| self.rewrite_ty_param(ty));
|
||||
// 1 = <
|
||||
let context = self.get_context();
|
||||
// FIXME: don't unwrap
|
||||
let lt_strs = lifetimes.iter().map(|lt| {
|
||||
lt.rewrite(&context, budget, offset + 1).unwrap()
|
||||
});
|
||||
let ty_strs = tys.iter().map(|ty_param| {
|
||||
ty_param.rewrite(&context, budget, offset + 1).unwrap()
|
||||
});
|
||||
|
||||
// Extract comments between generics.
|
||||
let lt_spans = lifetimes.iter().map(|l| {
|
||||
@ -700,7 +711,7 @@ fn rewrite_generics(&self, generics: &ast::Generics, offset: usize, span: Span)
|
||||
indent: offset + 1,
|
||||
h_width: budget,
|
||||
v_width: budget,
|
||||
ends_with_newline: true,
|
||||
ends_with_newline: false,
|
||||
};
|
||||
result.push_str(&write_list(&items, &fmt));
|
||||
|
||||
@ -711,6 +722,7 @@ fn rewrite_generics(&self, generics: &ast::Generics, offset: usize, span: Span)
|
||||
|
||||
fn rewrite_where_clause(&self,
|
||||
where_clause: &ast::WhereClause,
|
||||
config: &Config,
|
||||
indent: usize,
|
||||
span_end: BytePos)
|
||||
-> String {
|
||||
@ -720,9 +732,13 @@ fn rewrite_where_clause(&self,
|
||||
}
|
||||
|
||||
result.push('\n');
|
||||
result.push_str(&make_indent(indent + 4));
|
||||
result.push_str(&make_indent(indent + config.tab_spaces));
|
||||
result.push_str("where ");
|
||||
|
||||
let context = self.get_context();
|
||||
// 6 = "where ".len()
|
||||
let offset = indent + config.tab_spaces + 6;
|
||||
let budget = self.config.ideal_width + self.config.leeway - offset;
|
||||
let span_start = span_for_where_pred(&where_clause.predicates[0]).lo;
|
||||
let items = itemize_list(self.codemap,
|
||||
Vec::new(),
|
||||
@ -731,19 +747,21 @@ fn rewrite_where_clause(&self,
|
||||
"{",
|
||||
|pred| span_for_where_pred(pred).lo,
|
||||
|pred| span_for_where_pred(pred).hi,
|
||||
|pred| self.rewrite_pred(pred),
|
||||
// FIXME: we should handle failure better
|
||||
// this will be taken care of when write_list
|
||||
// takes Rewrite object: see issue #133
|
||||
|pred| pred.rewrite(&context, budget, offset).unwrap(),
|
||||
span_start,
|
||||
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,
|
||||
indent: offset,
|
||||
h_width: budget,
|
||||
v_width: budget,
|
||||
ends_with_newline: true,
|
||||
ends_with_newline: false,
|
||||
};
|
||||
result.push_str(&write_list(&items, &fmt));
|
||||
|
||||
|
@ -211,7 +211,7 @@ pub fn write_list<'b>(items: &[ListItem], formatting: &ListFormatting<'b>) -> St
|
||||
let offset = formatting.indent + item_width + 1;
|
||||
let comment = item.post_comment.as_ref().unwrap();
|
||||
// Use block-style only for the last item or multiline comments.
|
||||
let block_style = formatting.ends_with_newline && last ||
|
||||
let block_style = !formatting.ends_with_newline && last ||
|
||||
comment.trim().contains('\n') || comment.trim().len() > width;
|
||||
|
||||
let formatted_comment = rewrite_comment(comment, block_style, width, offset);
|
||||
|
400
src/types.rs
400
src/types.rs
@ -8,33 +8,311 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use visitor::FmtVisitor;
|
||||
use std::fmt;
|
||||
|
||||
use syntax::ast;
|
||||
use syntax::print::pprust;
|
||||
use syntax::codemap::{self, Span, BytePos, CodeMap};
|
||||
|
||||
impl<'a> FmtVisitor<'a> {
|
||||
pub fn rewrite_pred(&self, predicate: &ast::WherePredicate) -> String {
|
||||
// TODO dead spans
|
||||
use lists::{itemize_list, write_list, ListTactic, SeparatorTactic, ListFormatting};
|
||||
use rewrite::{Rewrite, RewriteContext};
|
||||
use utils::{extra_offset, span_after};
|
||||
|
||||
impl Rewrite for ast::Path {
|
||||
fn rewrite(&self, context: &RewriteContext, width: usize, offset: usize) -> Option<String> {
|
||||
rewrite_path(context, None, self, width, offset)
|
||||
}
|
||||
}
|
||||
|
||||
// Does not wrap on simple segments.
|
||||
pub fn rewrite_path(context: &RewriteContext,
|
||||
qself: Option<&ast::QSelf>,
|
||||
path: &ast::Path,
|
||||
width: usize,
|
||||
offset: usize)
|
||||
-> Option<String> {
|
||||
let skip_count = qself.map(|x| x.position).unwrap_or(0);
|
||||
|
||||
let mut result = if path.global {
|
||||
"::".to_owned()
|
||||
} else {
|
||||
String::new()
|
||||
};
|
||||
|
||||
let mut span_lo = path.span.lo;
|
||||
|
||||
if let Some(ref qself) = qself {
|
||||
result.push('<');
|
||||
result.push_str(&pprust::ty_to_string(&qself.ty));
|
||||
result.push_str(" as ");
|
||||
|
||||
let extra_offset = extra_offset(&result, offset);
|
||||
// 3 = ">::".len()
|
||||
let budget = try_opt!(width.checked_sub(extra_offset)) - 3;
|
||||
|
||||
result = try_opt!(rewrite_path_segments(result,
|
||||
path.segments.iter().take(skip_count),
|
||||
span_lo,
|
||||
path.span.hi,
|
||||
context,
|
||||
budget,
|
||||
offset + extra_offset));
|
||||
|
||||
result.push_str(">::");
|
||||
span_lo = qself.ty.span.hi + BytePos(1);
|
||||
}
|
||||
|
||||
let extra_offset = extra_offset(&result, offset);
|
||||
let budget = try_opt!(width.checked_sub(extra_offset));
|
||||
rewrite_path_segments(result,
|
||||
path.segments.iter().skip(skip_count),
|
||||
span_lo,
|
||||
path.span.hi,
|
||||
context,
|
||||
budget,
|
||||
offset + extra_offset)
|
||||
}
|
||||
|
||||
fn rewrite_path_segments<'a, I>(mut buffer: String,
|
||||
iter: I,
|
||||
mut span_lo: BytePos,
|
||||
span_hi: BytePos,
|
||||
context: &RewriteContext,
|
||||
width: usize,
|
||||
offset: usize)
|
||||
-> Option<String>
|
||||
where I: Iterator<Item = &'a ast::PathSegment>
|
||||
{
|
||||
let mut first = true;
|
||||
|
||||
for segment in iter {
|
||||
let extra_offset = extra_offset(&buffer, offset);
|
||||
let remaining_width = try_opt!(width.checked_sub(extra_offset));
|
||||
let new_offset = offset + extra_offset;
|
||||
let segment_string = try_opt!(rewrite_segment(segment,
|
||||
&mut span_lo,
|
||||
span_hi,
|
||||
context,
|
||||
remaining_width,
|
||||
new_offset));
|
||||
|
||||
if first {
|
||||
first = false;
|
||||
} else {
|
||||
buffer.push_str("::");
|
||||
}
|
||||
|
||||
buffer.push_str(&segment_string);
|
||||
}
|
||||
|
||||
Some(buffer)
|
||||
}
|
||||
|
||||
enum SegmentParam<'a> {
|
||||
LifeTime(&'a ast::Lifetime),
|
||||
Type(&'a ast::Ty),
|
||||
Binding(&'a ast::TypeBinding),
|
||||
}
|
||||
|
||||
impl<'a> SegmentParam<'a> {
|
||||
fn get_span(&self) -> Span {
|
||||
match *self {
|
||||
SegmentParam::LifeTime(ref lt) => lt.span,
|
||||
SegmentParam::Type(ref ty) => ty.span,
|
||||
SegmentParam::Binding(ref binding) => binding.span,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> fmt::Display for SegmentParam<'a> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match *self {
|
||||
SegmentParam::LifeTime(ref lt) => {
|
||||
write!(f, "{}", pprust::lifetime_to_string(lt))
|
||||
}
|
||||
SegmentParam::Type(ref ty) => {
|
||||
write!(f, "{}", pprust::ty_to_string(ty))
|
||||
}
|
||||
SegmentParam::Binding(ref binding) => {
|
||||
write!(f, "{} = {}", binding.ident, pprust::ty_to_string(&*binding.ty))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// This is a dirty hack to determine if we're in an expression or not. Generic
|
||||
// parameters are passed differently in expressions and items. We'd declare
|
||||
// a struct with Foo<A, B>, but call its functions with Foo::<A, B>::f().
|
||||
// We'd really rather not do this, but there doesn't seem to be an alternative
|
||||
// at this point.
|
||||
// FIXME: fails with spans containing comments with the characters < or :
|
||||
fn get_path_separator(codemap: &CodeMap,
|
||||
path_start: BytePos,
|
||||
segment_start: BytePos)
|
||||
-> &'static str {
|
||||
let span = codemap::mk_sp(path_start, segment_start);
|
||||
let snippet = codemap.span_to_snippet(span).unwrap();
|
||||
|
||||
for c in snippet.chars().rev() {
|
||||
if c == ':' {
|
||||
return "::"
|
||||
} else if c.is_whitespace() || c == '<' {
|
||||
continue;
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
unreachable!();
|
||||
}
|
||||
|
||||
// Formats a path segment. There are some hacks involved to correctly determine
|
||||
// the segment's associated span since it's not part of the AST.
|
||||
//
|
||||
// The span_lo is assumed to be greater than the end of any previous segment's
|
||||
// parameters and lesser or equal than the start of current segment.
|
||||
//
|
||||
// span_hi is assumed equal to the end of the entire path.
|
||||
//
|
||||
// When the segment contains a positive number of parameters, we update span_lo
|
||||
// so that invariants described above will hold for the next segment.
|
||||
fn rewrite_segment(segment: &ast::PathSegment,
|
||||
span_lo: &mut BytePos,
|
||||
span_hi: BytePos,
|
||||
context: &RewriteContext,
|
||||
width: usize,
|
||||
offset: usize)
|
||||
-> Option<String> {
|
||||
let ident_len = segment.identifier.to_string().len();
|
||||
let width = try_opt!(width.checked_sub(ident_len));
|
||||
let offset = offset + ident_len;
|
||||
|
||||
let params = match segment.parameters {
|
||||
ast::PathParameters::AngleBracketedParameters(ref data) if data.lifetimes.len() > 0 ||
|
||||
data.types.len() > 0 ||
|
||||
data.bindings.len() > 0 => {
|
||||
let param_list = data.lifetimes.iter()
|
||||
.map(SegmentParam::LifeTime)
|
||||
.chain(data.types.iter()
|
||||
.map(|x| SegmentParam::Type(&*x)))
|
||||
.chain(data.bindings.iter()
|
||||
.map(|x| SegmentParam::Binding(&*x)))
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let next_span_lo = param_list.last().unwrap().get_span().hi + BytePos(1);
|
||||
let list_lo = span_after(codemap::mk_sp(*span_lo, span_hi), "<", context.codemap);
|
||||
let separator = get_path_separator(context.codemap, *span_lo, list_lo);
|
||||
|
||||
let items = itemize_list(context.codemap,
|
||||
Vec::new(),
|
||||
param_list.into_iter(),
|
||||
",",
|
||||
">",
|
||||
|param| param.get_span().lo,
|
||||
|param| param.get_span().hi,
|
||||
ToString::to_string,
|
||||
list_lo,
|
||||
span_hi);
|
||||
|
||||
// 1 for <
|
||||
let extra_offset = 1 + separator.len();
|
||||
// 1 for >
|
||||
let list_width = try_opt!(width.checked_sub(extra_offset + 1));
|
||||
|
||||
let fmt = ListFormatting {
|
||||
tactic: ListTactic::HorizontalVertical,
|
||||
separator: ",",
|
||||
trailing_separator: SeparatorTactic::Never,
|
||||
indent: offset + extra_offset,
|
||||
h_width: list_width,
|
||||
v_width: list_width,
|
||||
ends_with_newline: false,
|
||||
};
|
||||
|
||||
// update pos
|
||||
*span_lo = next_span_lo;
|
||||
|
||||
format!("{}<{}>", separator, write_list(&items, &fmt))
|
||||
}
|
||||
ast::PathParameters::ParenthesizedParameters(ref data) => {
|
||||
let output = match data.output {
|
||||
Some(ref ty) => format!(" -> {}", pprust::ty_to_string(&*ty)),
|
||||
None => String::new()
|
||||
};
|
||||
|
||||
let list_lo = span_after(codemap::mk_sp(*span_lo, span_hi), "(", context.codemap);
|
||||
let items = itemize_list(context.codemap,
|
||||
Vec::new(),
|
||||
data.inputs.iter(),
|
||||
",",
|
||||
")",
|
||||
|ty| ty.span.lo,
|
||||
|ty| ty.span.hi,
|
||||
|ty| pprust::ty_to_string(ty),
|
||||
list_lo,
|
||||
span_hi);
|
||||
|
||||
// 2 for ()
|
||||
let budget = try_opt!(width.checked_sub(output.len() + 2));
|
||||
|
||||
let fmt = ListFormatting {
|
||||
tactic: ListTactic::HorizontalVertical,
|
||||
separator: ",",
|
||||
trailing_separator: SeparatorTactic::Never,
|
||||
// 1 for (
|
||||
indent: offset + 1,
|
||||
h_width: budget,
|
||||
v_width: budget,
|
||||
ends_with_newline: false,
|
||||
};
|
||||
|
||||
// update pos
|
||||
*span_lo = data.inputs.last().unwrap().span.hi + BytePos(1);
|
||||
|
||||
format!("({}){}", write_list(&items, &fmt), output)
|
||||
}
|
||||
_ => String::new()
|
||||
};
|
||||
|
||||
Some(format!("{}{}", segment.identifier, params))
|
||||
}
|
||||
|
||||
impl Rewrite for ast::WherePredicate {
|
||||
fn rewrite(&self, context: &RewriteContext, width: usize, offset: usize) -> Option<String> {
|
||||
// TODO dead spans?
|
||||
// TODO assumes we'll always fit on one line...
|
||||
match predicate {
|
||||
Some(match self {
|
||||
&ast::WherePredicate::BoundPredicate(ast::WhereBoundPredicate{ref bound_lifetimes,
|
||||
ref bounded_ty,
|
||||
ref bounds,
|
||||
..}) => {
|
||||
if bound_lifetimes.len() > 0 {
|
||||
format!("for<{}> {}: {}",
|
||||
bound_lifetimes.iter().map(|l| self.rewrite_lifetime_def(l))
|
||||
.collect::<Vec<_>>().join(", "),
|
||||
pprust::ty_to_string(bounded_ty),
|
||||
bounds.iter().map(|b| self.rewrite_ty_bound(b))
|
||||
.collect::<Vec<_>>().join(" + "))
|
||||
let lifetime_str = bound_lifetimes.iter().map(|lt| {
|
||||
lt.rewrite(context, width, offset).unwrap()
|
||||
}).collect::<Vec<_>>().join(", ");
|
||||
let type_str = pprust::ty_to_string(bounded_ty);
|
||||
// 8 = "for<> : ".len()
|
||||
let used_width = lifetime_str.len() + type_str.len() + 8;
|
||||
let bounds_str = bounds.iter().map(|ty_bound| {
|
||||
ty_bound.rewrite(context,
|
||||
width - used_width,
|
||||
offset + used_width)
|
||||
.unwrap()
|
||||
}).collect::<Vec<_>>().join(" + ");
|
||||
|
||||
format!("for<{}> {}: {}", lifetime_str, type_str, bounds_str)
|
||||
} else {
|
||||
format!("{}: {}",
|
||||
pprust::ty_to_string(bounded_ty),
|
||||
bounds.iter().map(|b| self.rewrite_ty_bound(b))
|
||||
.collect::<Vec<_>>().join(" + "))
|
||||
let type_str = pprust::ty_to_string(bounded_ty);
|
||||
// 2 = ": ".len()
|
||||
let used_width = type_str.len() + 2;
|
||||
let bounds_str = bounds.iter().map(|ty_bound| {
|
||||
ty_bound.rewrite(context,
|
||||
width - used_width,
|
||||
offset + used_width)
|
||||
.unwrap()
|
||||
}).collect::<Vec<_>>().join(" + ");
|
||||
|
||||
format!("{}: {}", type_str, bounds_str)
|
||||
}
|
||||
}
|
||||
&ast::WherePredicate::RegionPredicate(ast::WhereRegionPredicate{ref lifetime,
|
||||
@ -42,65 +320,91 @@ pub fn rewrite_pred(&self, predicate: &ast::WherePredicate) -> String {
|
||||
..}) => {
|
||||
format!("{}: {}",
|
||||
pprust::lifetime_to_string(lifetime),
|
||||
bounds.iter().map(|l| pprust::lifetime_to_string(l))
|
||||
.collect::<Vec<_>>().join(" + "))
|
||||
bounds.iter().map(pprust::lifetime_to_string)
|
||||
.collect::<Vec<_>>().join(" + "))
|
||||
}
|
||||
&ast::WherePredicate::EqPredicate(ast::WhereEqPredicate{ref path, ref ty, ..}) => {
|
||||
format!("{} = {}", pprust::path_to_string(path), pprust::ty_to_string(ty))
|
||||
let ty_str = pprust::ty_to_string(ty);
|
||||
// 3 = " = ".len()
|
||||
let used_width = 3 + ty_str.len();
|
||||
let path_str = try_opt!(path.rewrite(context,
|
||||
width - used_width,
|
||||
offset + used_width));
|
||||
format!("{} = {}", path_str, ty_str)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl Rewrite for ast::LifetimeDef {
|
||||
fn rewrite(&self, _: &RewriteContext, _: usize, _: usize) -> Option<String> {
|
||||
if self.bounds.len() == 0 {
|
||||
Some(pprust::lifetime_to_string(&self.lifetime))
|
||||
} else {
|
||||
Some(format!("{}: {}",
|
||||
pprust::lifetime_to_string(&self.lifetime),
|
||||
self.bounds.iter().map(pprust::lifetime_to_string)
|
||||
.collect::<Vec<_>>().join(" + ")))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn rewrite_lifetime_def(&self, lifetime: &ast::LifetimeDef) -> String {
|
||||
if lifetime.bounds.len() == 0 {
|
||||
return pprust::lifetime_to_string(&lifetime.lifetime);
|
||||
}
|
||||
|
||||
format!("{}: {}",
|
||||
pprust::lifetime_to_string(&lifetime.lifetime),
|
||||
lifetime.bounds.iter().map(|l| pprust::lifetime_to_string(l))
|
||||
.collect::<Vec<_>>().join(" + "))
|
||||
}
|
||||
|
||||
pub fn rewrite_ty_bound(&self, bound: &ast::TyParamBound) -> String {
|
||||
match *bound {
|
||||
impl Rewrite for ast::TyParamBound {
|
||||
fn rewrite(&self, context: &RewriteContext, width: usize, offset: usize) -> Option<String> {
|
||||
match *self {
|
||||
ast::TyParamBound::TraitTyParamBound(ref tref, ast::TraitBoundModifier::None) => {
|
||||
self.rewrite_poly_trait_ref(tref)
|
||||
tref.rewrite(context, width, offset)
|
||||
}
|
||||
ast::TyParamBound::TraitTyParamBound(ref tref, ast::TraitBoundModifier::Maybe) => {
|
||||
format!("?{}", self.rewrite_poly_trait_ref(tref))
|
||||
Some(format!("?{}", try_opt!(tref.rewrite(context, width - 1, offset + 1))))
|
||||
}
|
||||
ast::TyParamBound::RegionTyParamBound(ref l) => {
|
||||
pprust::lifetime_to_string(l)
|
||||
Some(pprust::lifetime_to_string(l))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn rewrite_ty_param(&self, ty_param: &ast::TyParam) -> String {
|
||||
// FIXME: this assumes everything will fit on one line
|
||||
impl Rewrite for ast::TyParam {
|
||||
fn rewrite(&self, context: &RewriteContext, width: usize, offset: usize) -> Option<String> {
|
||||
let mut result = String::with_capacity(128);
|
||||
result.push_str(&ty_param.ident.to_string());
|
||||
if ty_param.bounds.len() > 0 {
|
||||
result.push_str(&self.ident.to_string());
|
||||
if self.bounds.len() > 0 {
|
||||
result.push_str(": ");
|
||||
result.push_str(&ty_param.bounds.iter().map(|b| self.rewrite_ty_bound(b))
|
||||
.collect::<Vec<_>>().join(" + "));
|
||||
|
||||
let bounds = self.bounds.iter().map(|ty_bound| {
|
||||
ty_bound.rewrite(context, width, offset).unwrap()
|
||||
}).collect::<Vec<_>>().join(" + ");
|
||||
|
||||
result.push_str(&bounds);
|
||||
}
|
||||
if let Some(ref def) = ty_param.default {
|
||||
if let Some(ref def) = self.default {
|
||||
result.push_str(" = ");
|
||||
result.push_str(&pprust::ty_to_string(&def));
|
||||
}
|
||||
|
||||
result
|
||||
Some(result)
|
||||
}
|
||||
}
|
||||
|
||||
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<_>>().join(", "),
|
||||
pprust::path_to_string(&t.trait_ref.path))
|
||||
// FIXME: this assumes everything will fit on one line
|
||||
impl Rewrite for ast::PolyTraitRef {
|
||||
fn rewrite(&self, context: &RewriteContext, width: usize, offset: usize) -> Option<String> {
|
||||
if self.bound_lifetimes.len() > 0 {
|
||||
let lifetime_str = self.bound_lifetimes.iter().map(|lt| {
|
||||
lt.rewrite(context, width, offset).unwrap()
|
||||
}).collect::<Vec<_>>().join(", ");
|
||||
// 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!(self.trait_ref.path.rewrite(context,
|
||||
max_path_width,
|
||||
offset + extra_offset));
|
||||
|
||||
Some(format!("for<{}> {}", lifetime_str, path_str))
|
||||
} else {
|
||||
pprust::path_to_string(&t.trait_ref.path)
|
||||
self.trait_ref.path.rewrite(context, width, offset)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
10
src/utils.rs
10
src/utils.rs
@ -15,6 +15,16 @@
|
||||
|
||||
use SKIP_ANNOTATION;
|
||||
|
||||
// Computes the length of a string's last line, minus offset.
|
||||
#[inline]
|
||||
pub fn extra_offset(text: &str, offset: usize) -> usize {
|
||||
match text.rfind('\n') {
|
||||
// 1 for newline character
|
||||
Some(idx) => text.len() - idx - 1 - offset,
|
||||
None => text.len()
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn span_after(original: Span, needle: &str, codemap: &CodeMap) -> BytePos {
|
||||
let snippet = codemap.span_to_snippet(original).unwrap();
|
||||
|
@ -33,13 +33,9 @@ fn visit_expr(&mut self, ex: &'v ast::Expr) {
|
||||
self.codemap.lookup_char_pos(ex.span.lo),
|
||||
self.codemap.lookup_char_pos(ex.span.hi));
|
||||
self.format_missing(ex.span.lo);
|
||||
|
||||
let offset = self.buffer.cur_offset();
|
||||
let context = RewriteContext {
|
||||
codemap: self.codemap,
|
||||
config: self.config,
|
||||
block_indent: self.block_indent,
|
||||
};
|
||||
let rewrite = ex.rewrite(&context, self.config.max_width - offset, offset);
|
||||
let rewrite = ex.rewrite(&self.get_context(), self.config.max_width - offset, offset);
|
||||
|
||||
if let Some(new_str) = rewrite {
|
||||
self.buffer.push_str(&new_str);
|
||||
@ -372,4 +368,12 @@ fn format_import(&mut self, vis: ast::Visibility, vp: &ast::ViewPath, span: Span
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_context(&self) -> RewriteContext {
|
||||
RewriteContext {
|
||||
codemap: self.codemap,
|
||||
config: self.config,
|
||||
block_indent: self.block_indent,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -9,3 +9,11 @@ fn weird_comment(/* /*/ double level */ comment */ x: Hello /*/*/* tripple, even
|
||||
) {
|
||||
simple(/* does this preserve comments now? */ 42, NoWay)
|
||||
}
|
||||
|
||||
fn generic<T>(arg: T) -> &SomeType
|
||||
where T: Fn(// First arg
|
||||
A,
|
||||
// Second argument
|
||||
B, C, D, /* pre comment */ E /* last comment */) -> &SomeType {
|
||||
arg(a, b, c, d, e)
|
||||
}
|
||||
|
22
tests/source/paths.rs
Normal file
22
tests/source/paths.rs
Normal file
@ -0,0 +1,22 @@
|
||||
|
||||
fn main() {
|
||||
// FIXME(#133): the list rewrite should fail and force a different format
|
||||
let constellation_chan = Constellation::<layout::layout_task::LayoutTask, script::script_task::ScriptTask> ::start(
|
||||
compositor_proxy,
|
||||
resource_task,
|
||||
image_cache_task,font_cache_task,
|
||||
time_profiler_chan,
|
||||
mem_profiler_chan,
|
||||
devtools_chan,
|
||||
storage_task,
|
||||
supports_clipboard
|
||||
);
|
||||
|
||||
Quux::<ParamOne, // Comment 1
|
||||
ParamTwo, // Comment 2
|
||||
>::some_func();
|
||||
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA::BBBBBBBBBBBBBBBBBBBBBBBBBBBB::CCCCCCCCCCCCCCCCCCCCCC::quux();
|
||||
}
|
||||
|
||||
fn op(foo: Bar, key : &[u8], upd : Fn(Option<&memcache::Item> , Baz ) -> Result) -> MapResult {}
|
@ -48,3 +48,8 @@ fn matcher() {
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
fn issue177() {
|
||||
struct Foo<T> { memb: T }
|
||||
let foo = Foo::<i64> { memb: 10 };
|
||||
}
|
||||
|
@ -14,3 +14,16 @@ fn weird_comment(// /*/ double level */ comment
|
||||
42,
|
||||
NoWay)
|
||||
}
|
||||
|
||||
fn generic<T>(arg: T) -> &SomeType
|
||||
where T: Fn(// First arg
|
||||
A,
|
||||
// Second argument
|
||||
B,
|
||||
C,
|
||||
D,
|
||||
// pre comment
|
||||
E /* last comment */) -> &SomeType
|
||||
{
|
||||
arg(a, b, c, d, e)
|
||||
}
|
||||
|
@ -79,17 +79,3 @@ fn main() {
|
||||
let _ = function(move || 5);
|
||||
let _ = move || 42;
|
||||
}
|
||||
|
||||
fn servo() {
|
||||
let constellation_chan = Constellation::<layout::layout_task::LayoutTask,
|
||||
script::script_task::ScriptTask>::start(
|
||||
compositor_proxy,
|
||||
resource_task,
|
||||
image_cache_task,
|
||||
font_cache_task,
|
||||
time_profiler_chan,
|
||||
mem_profiler_chan,
|
||||
devtools_chan,
|
||||
storage_task,
|
||||
supports_clipboard);
|
||||
}
|
||||
|
21
tests/target/paths.rs
Normal file
21
tests/target/paths.rs
Normal file
@ -0,0 +1,21 @@
|
||||
|
||||
fn main() {
|
||||
// FIXME(#133): the list rewrite should fail and force a different format
|
||||
let constellation_chan = Constellation::<layout::layout_task::LayoutTask,
|
||||
script::script_task::ScriptTask>::start(compositor_proxy,
|
||||
resource_task,
|
||||
image_cache_task,
|
||||
font_cache_task,
|
||||
time_profiler_chan,
|
||||
mem_profiler_chan,
|
||||
devtools_chan,
|
||||
storage_task,
|
||||
supports_clipboard);
|
||||
|
||||
Quux::<ParamOne /* Comment 1 */, ParamTwo /* Comment 2 */>::some_func();
|
||||
|
||||
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA::BBBBBBBBBBBBBBBBBBBBBBBBBBBB::CCCCCCCCCCCCCCCCCCCCCC::quux();
|
||||
}
|
||||
|
||||
fn op(foo: Bar, key: &[u8], upd: Fn(Option<&memcache::Item>, Baz) -> Result) -> MapResult {
|
||||
}
|
@ -64,3 +64,10 @@ fn matcher() {
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
fn issue177() {
|
||||
struct Foo<T> {
|
||||
memb: T,
|
||||
}
|
||||
let foo = Foo::<i64> { memb: 10 };
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user