1
Fork 0

Use SnippetProvider to implement SpanUtils over CodeMap

`SnippetProvider::span_to_snippet` avoids allocating a `String` so it is more
efficient than `CodeMap::span_to_snippet`.
This commit is contained in:
topecongiro 2018-02-19 12:41:43 +09:00
parent f0519c8001
commit 9d47e7370e
12 changed files with 86 additions and 65 deletions

View file

@ -225,14 +225,14 @@ fn rewrite_closure_fn_decl(
let ret_str = fn_decl.output.rewrite(context, arg_shape)?;
let arg_items = itemize_list(
context.codemap,
context.snippet_provider,
fn_decl.inputs.iter(),
"|",
",",
|arg| span_lo_for_arg(arg),
|arg| span_hi_for_arg(context, arg),
|arg| arg.rewrite(context, arg_shape),
context.codemap.span_after(span, "|"),
context.snippet_provider.span_after(span, "|"),
body.span.lo(),
false,
);

View file

@ -12,6 +12,7 @@
//! This includes extension traits and methods for looking up spans and line ranges for AST nodes.
use config::file_lines::LineRange;
use visitor::SnippetProvider;
use syntax::codemap::{BytePos, CodeMap, Span};
use comment::FindUncommented;
@ -32,7 +33,7 @@ pub trait LineRangeUtils {
fn lookup_line_range(&self, span: Span) -> LineRange;
}
impl SpanUtils for CodeMap {
impl<'a> SpanUtils for SnippetProvider<'a> {
fn span_after(&self, original: Span, needle: &str) -> BytePos {
let snippet = self.span_to_snippet(original).expect("Bad snippet");
let offset = snippet.find_uncommented(needle).expect("Bad offset") + needle.len();
@ -59,7 +60,7 @@ impl SpanUtils for CodeMap {
}
fn opt_span_after(&self, original: Span, needle: &str) -> Option<BytePos> {
let snippet = self.span_to_snippet(original).ok()?;
let snippet = self.span_to_snippet(original)?;
let offset = snippet.find_uncommented(needle)? + needle.len();
Some(original.lo() + BytePos(offset as u32))

View file

@ -65,7 +65,10 @@ pub fn format_expr(
let expr_rw = match expr.node {
ast::ExprKind::Array(ref expr_vec) => rewrite_array(
&ptr_vec_to_ref_vec(expr_vec),
mk_sp(context.codemap.span_after(expr.span, "["), expr.span.hi()),
mk_sp(
context.snippet_provider.span_after(expr.span, "["),
expr.span.hi(),
),
context,
shape,
false,
@ -425,7 +428,7 @@ pub fn rewrite_array<T: Rewrite + Spanned + ToExpr>(
};
let items = itemize_list(
context.codemap,
context.snippet_provider,
exprs.iter(),
"]",
",",
@ -1002,13 +1005,15 @@ impl<'a> ControlFlow<'a> {
let lo = self.label.map_or(self.span.lo(), |label| label.span.hi());
let between_kwd_cond = mk_sp(
context
.codemap
.snippet_provider
.span_after(mk_sp(lo, self.span.hi()), self.keyword.trim()),
self.pat.map_or(cond_span.lo(), |p| {
if self.matcher.is_empty() {
p.span.lo()
} else {
context.codemap.span_before(self.span, self.matcher.trim())
context
.snippet_provider
.span_before(self.span, self.matcher.trim())
}
}),
);
@ -1131,7 +1136,7 @@ impl<'a> Rewrite for ControlFlow<'a> {
let between_kwd_else_block = mk_sp(
self.block.span.hi(),
context
.codemap
.snippet_provider
.span_before(mk_sp(self.block.span.hi(), else_block.span.lo()), "else"),
);
let between_kwd_else_block_comment =
@ -1139,7 +1144,7 @@ impl<'a> Rewrite for ControlFlow<'a> {
let after_else = mk_sp(
context
.codemap
.snippet_provider
.span_after(mk_sp(self.block.span.hi(), else_block.span.lo()), "else"),
else_block.span.lo(),
);
@ -1295,7 +1300,9 @@ fn rewrite_match(
} else {
arms[0].span().lo()
};
context.codemap.span_after(mk_sp(cond.span.hi(), hi), "{")
context
.snippet_provider
.span_after(mk_sp(cond.span.hi(), hi), "{")
} else {
inner_attrs[inner_attrs.len() - 1].span().hi()
};
@ -1353,7 +1360,7 @@ fn rewrite_match_arms(
.take(arm_len.checked_sub(1).unwrap_or(0))
.chain(repeat(true));
let items = itemize_list(
context.codemap,
context.snippet_provider,
arms.iter()
.zip(is_last_iter)
.map(|(arm, is_last)| ArmWrapper::new(arm, is_last)),
@ -1915,7 +1922,7 @@ where
used_width + paren_overhead,
)?;
let span_lo = context.codemap.span_after(span, "(");
let span_lo = context.snippet_provider.span_after(span, "(");
let args_span = mk_sp(span_lo, span.hi());
let (extendable, list_str) = rewrite_call_args(
@ -1974,7 +1981,7 @@ where
T: Rewrite + Spanned + ToExpr + 'a,
{
let items = itemize_list(
context.codemap,
context.snippet_provider,
args.iter(),
")",
",",
@ -2473,7 +2480,7 @@ fn rewrite_struct_lit<'a>(
let (h_shape, v_shape) = struct_lit_shape(shape, context, path_str.len() + 3, 2)?;
let one_line_width = h_shape.map_or(0, |shape| shape.width);
let body_lo = context.codemap.span_after(span, "{");
let body_lo = context.snippet_provider.span_after(span, "{");
let fields_str = if struct_lit_can_be_aligned(fields, &base)
&& context.config.struct_field_align_threshold() > 0
{
@ -2516,7 +2523,7 @@ fn rewrite_struct_lit<'a>(
};
let items = itemize_list(
context.codemap,
context.snippet_provider,
field_iter,
"}",
",",
@ -2665,10 +2672,10 @@ where
});
}
let list_lo = context.codemap.span_after(span, "(");
let list_lo = context.snippet_provider.span_after(span, "(");
let nested_shape = shape.sub_width(2)?.visual_indent(1);
let items = itemize_list(
context.codemap,
context.snippet_provider,
items,
")",
",",

View file

@ -314,14 +314,14 @@ fn rewrite_nested_use_tree(
// Dummy value, see explanation below.
let mut items = vec![ListItem::from_str("")];
let iter = itemize_list(
context.codemap,
context.snippet_provider,
trees.iter().map(|tree| &tree.0),
"}",
",",
|tree| tree.span.lo(),
|tree| tree.span.hi(),
|tree| tree.rewrite(context, nested_shape),
context.codemap.span_after(span, "{"),
context.snippet_provider.span_after(span, "{"),
span.hi(),
false,
);

View file

@ -477,7 +477,7 @@ impl<'a> FmtVisitor<'a> {
let itemize_list_with = |one_line_width: usize| {
itemize_list(
self.codemap,
self.snippet_provider,
enum_def.variants.iter(),
"}",
",",
@ -722,7 +722,7 @@ fn format_impl_ref_and_type(
result.push_str(format_unsafety(unsafety));
result.push_str("impl");
let lo = context.codemap.span_after(item.span, "impl");
let lo = context.snippet_provider.span_after(item.span, "impl");
let hi = match *trait_ref {
Some(ref tr) => tr.path.span.lo(),
None => self_ty.span.lo(),
@ -929,7 +929,7 @@ pub fn format_trait(context: &RewriteContext, item: &ast::Item, offset: Indent)
result.push_str(&header);
let body_lo = context.codemap.span_after(item.span, "{");
let body_lo = context.snippet_provider.span_after(item.span, "{");
let shape = Shape::indented(offset, context.config).offset_left(result.len())?;
let generics_str =
@ -939,7 +939,7 @@ pub fn format_trait(context: &RewriteContext, item: &ast::Item, offset: Indent)
// FIXME(#2055): rustfmt fails to format when there are comments between trait bounds.
if !type_param_bounds.is_empty() {
let ident_hi = context
.codemap
.snippet_provider
.span_after(item.span, &format!("{}", item.ident));
let bound_hi = type_param_bounds.last().unwrap().span().hi();
let snippet = context.snippet(mk_sp(ident_hi, bound_hi));
@ -1133,7 +1133,7 @@ pub fn format_struct_struct(
result.push_str(&header_str);
let header_hi = span.lo() + BytePos(header_str.len() as u32);
let body_lo = context.codemap.span_after(span, "{");
let body_lo = context.snippet_provider.span_after(span, "{");
let generics_str = match struct_parts.generics {
Some(g) => format_generics(
@ -1231,7 +1231,7 @@ fn get_bytepos_after_visibility(
) -> BytePos {
match *vis {
ast::Visibility::Crate(s, CrateSugar::PubCrate) => context
.codemap
.snippet_provider
.span_after(mk_sp(s.hi(), default_span.hi()), terminator),
ast::Visibility::Crate(s, CrateSugar::JustCrate) => s.hi(),
ast::Visibility::Restricted { ref path, .. } => path.span.hi(),
@ -1253,12 +1253,16 @@ fn format_tuple_struct(
let body_lo = if fields.is_empty() {
let lo = get_bytepos_after_visibility(context, struct_parts.vis, span, ")");
context.codemap.span_after(mk_sp(lo, span.hi()), "(")
context
.snippet_provider
.span_after(mk_sp(lo, span.hi()), "(")
} else {
fields[0].span.lo()
};
let body_hi = if fields.is_empty() {
context.codemap.span_after(mk_sp(body_lo, span.hi()), ")")
context
.snippet_provider
.span_after(mk_sp(body_lo, span.hi()), ")")
} else {
// This is a dirty hack to work around a missing `)` from the span of the last field.
let last_arg_span = fields[fields.len() - 1].span;
@ -1266,7 +1270,7 @@ fn format_tuple_struct(
last_arg_span.hi()
} else {
context
.codemap
.snippet_provider
.span_after(mk_sp(last_arg_span.hi(), span.hi()), ")")
}
};
@ -1309,7 +1313,9 @@ fn format_tuple_struct(
result.push('(');
let snippet = context.snippet(mk_sp(
body_lo,
context.codemap.span_before(mk_sp(body_lo, span.hi()), ")"),
context
.snippet_provider
.span_before(mk_sp(body_lo, span.hi()), ")"),
));
if snippet.is_empty() {
// `struct S ()`
@ -1364,7 +1370,10 @@ pub fn rewrite_type_alias(
let g_shape = Shape::indented(indent, context.config)
.offset_left(result.len())?
.sub_width(2)?;
let g_span = mk_sp(context.codemap.span_after(span, "type"), ty.span.lo());
let g_span = mk_sp(
context.snippet_provider.span_after(span, "type"),
ty.span.lo(),
);
let generics_str = rewrite_generics(context, generics, g_shape, g_span)?;
result.push_str(&generics_str);
@ -1881,15 +1890,15 @@ fn rewrite_fn_base(
.map_or(lo_after_visibility, |param| param.span().hi());
let args_end = if fd.inputs.is_empty() {
context
.codemap
.snippet_provider
.span_after(mk_sp(args_start, span.hi()), ")")
} else {
let last_span = mk_sp(fd.inputs[fd.inputs.len() - 1].span().hi(), span.hi());
context.codemap.span_after(last_span, ")")
context.snippet_provider.span_after(last_span, ")")
};
let args_span = mk_sp(
context
.codemap
.snippet_provider
.span_after(mk_sp(args_start, span.hi()), "("),
args_end,
);
@ -2140,7 +2149,7 @@ fn rewrite_args(
};
let reduced_span = mk_sp(span.lo(), second_arg_start);
context.codemap.span_after_last(reduced_span, ",")
context.snippet_provider.span_after_last(reduced_span, ",")
} else {
span.lo()
};
@ -2152,14 +2161,15 @@ fn rewrite_args(
let variadic_arg = if variadic {
let variadic_span = mk_sp(args.last().unwrap().ty.span.hi(), span.hi());
let variadic_start = context.codemap.span_after(variadic_span, "...") - BytePos(3);
let variadic_start =
context.snippet_provider.span_after(variadic_span, "...") - BytePos(3);
Some(ArgumentKind::Variadic(variadic_start))
} else {
None
};
let more_items = itemize_list(
context.codemap,
context.snippet_provider,
args[min_args - 1..]
.iter()
.map(ArgumentKind::Regular)
@ -2353,14 +2363,14 @@ fn rewrite_generics_inner(
}
let items = itemize_list(
context.codemap,
context.snippet_provider,
generics.params.iter(),
">",
",",
|arg| arg.span().lo(),
|arg| arg.span().hi(),
|arg| arg.rewrite(context, shape),
context.codemap.span_after(span, "<"),
context.snippet_provider.span_after(span, "<"),
span.hi(),
false,
);
@ -2494,7 +2504,7 @@ fn rewrite_where_clause_rfc_style(
let end_of_preds = where_clause.predicates[len - 1].span().hi();
let span_end = span_end.unwrap_or(end_of_preds);
let items = itemize_list(
context.codemap,
context.snippet_provider,
where_clause.predicates.iter(),
terminator,
",",
@ -2610,7 +2620,7 @@ fn rewrite_where_clause(
let end_of_preds = where_clause.predicates[len - 1].span().hi();
let span_end = span_end.unwrap_or(end_of_preds);
let items = itemize_list(
context.codemap,
context.snippet_provider,
where_clause.predicates.iter(),
terminator,
",",

View file

@ -14,13 +14,14 @@ use std::cmp;
use std::iter::Peekable;
use config::lists::*;
use syntax::codemap::{BytePos, CodeMap};
use syntax::codemap::BytePos;
use comment::{find_comment_end, rewrite_comment, FindUncommented};
use config::{Config, IndentStyle};
use rewrite::RewriteContext;
use shape::{Indent, Shape};
use utils::{count_newlines, first_line_width, last_line_width, mk_sp, starts_with_newline};
use visitor::SnippetProvider;
pub struct ListFormatting<'a> {
pub tactic: DefinitiveListTactic,
@ -446,7 +447,7 @@ pub struct ListItems<'a, I, F1, F2, F3>
where
I: Iterator,
{
codemap: &'a CodeMap,
snippet_provider: &'a SnippetProvider<'a>,
inner: Peekable<I>,
get_lo: F1,
get_hi: F2,
@ -473,7 +474,7 @@ where
self.inner.next().map(|item| {
let mut new_lines = false;
// Pre-comment
let pre_snippet = self.codemap
let pre_snippet = self.snippet_provider
.span_to_snippet(mk_sp(self.prev_span_end, (self.get_lo)(&item)))
.unwrap();
let trimmed_pre_snippet = pre_snippet.trim();
@ -511,7 +512,7 @@ where
Some(next_item) => (self.get_lo)(next_item),
None => self.next_span_start,
};
let post_snippet = self.codemap
let post_snippet = self.snippet_provider
.span_to_snippet(mk_sp((self.get_hi)(&item), next_start))
.unwrap();
@ -619,7 +620,7 @@ where
#[cfg_attr(feature = "cargo-clippy", allow(too_many_arguments))]
// Creates an iterator over a list's items with associated comments.
pub fn itemize_list<'a, T, I, F1, F2, F3>(
codemap: &'a CodeMap,
snippet_provider: &'a SnippetProvider,
inner: I,
terminator: &'a str,
separator: &'a str,
@ -637,7 +638,7 @@ where
F3: Fn(&T) -> Option<String>,
{
ListItems {
codemap,
snippet_provider,
inner: inner.peekable(),
get_lo,
get_hi,

View file

@ -272,7 +272,7 @@ pub fn rewrite_macro(
// Convert `MacroArg` into `ast::Expr`, as `rewrite_array` only accepts the latter.
let sp = mk_sp(
context
.codemap
.snippet_provider
.span_after(mac.span, original_style.opener()),
mac.span.hi() - BytePos(1),
);
@ -326,14 +326,14 @@ pub fn rewrite_macro_def(
};
let branch_items = itemize_list(
context.codemap,
context.snippet_provider,
parsed_def.branches.iter(),
"}",
";",
|branch| branch.span.lo(),
|branch| branch.span.hi(),
|branch| branch.rewrite(context, arm_shape, multi_branch_style),
context.codemap.span_after(span, "{"),
context.snippet_provider.span_after(span, "{"),
span.hi(),
false,
).collect::<Vec<_>>();

View file

@ -156,14 +156,14 @@ fn rewrite_struct_pat(
struct_lit_shape(shape, context, path_str.len() + 3, ellipsis_str.len() + 2)?;
let items = itemize_list(
context.codemap,
context.snippet_provider,
fields.iter(),
terminator,
",",
|f| f.span.lo(),
|f| f.span.hi(),
|f| f.node.rewrite(context, v_shape),
context.codemap.span_after(span, "{"),
context.snippet_provider.span_after(span, "{"),
span.hi(),
false,
);
@ -353,14 +353,14 @@ fn count_wildcard_suffix_len(
let mut suffix_len = 0;
let items: Vec<_> = itemize_list(
context.codemap,
context.snippet_provider,
patterns.iter(),
")",
",",
|item| item.span().lo(),
|item| item.span().hi(),
|item| item.rewrite(context, shape),
context.codemap.span_after(span, "("),
context.snippet_provider.span_after(span, "("),
span.hi() - BytePos(1),
false,
).collect();

View file

@ -157,7 +157,7 @@ fn rewrite_reorderable_items(
span: Span,
) -> Option<String> {
let items = itemize_list(
context.codemap,
context.snippet_provider,
reorderable_items.iter(),
"",
";",

View file

@ -217,7 +217,9 @@ fn rewrite_segment(
.collect::<Vec<_>>();
let next_span_lo = param_list.last().unwrap().get_span().hi() + BytePos(1);
let list_lo = context.codemap.span_after(mk_sp(*span_lo, span_hi), "<");
let list_lo = context
.snippet_provider
.span_after(mk_sp(*span_lo, span_hi), "<");
let separator = if path_context == PathContext::Expr {
"::"
} else {
@ -228,7 +230,7 @@ fn rewrite_segment(
generics_shape_from_config(context.config, shape, separator.len())?;
let one_line_width = shape.width.checked_sub(separator.len() + 2)?;
let items = itemize_list(
context.codemap,
context.snippet_provider,
param_list.into_iter(),
">",
",",
@ -295,7 +297,7 @@ where
}
let variadic_arg = if variadic {
let variadic_start = context.codemap.span_before(span, "...");
let variadic_start = context.snippet_provider.span_before(span, "...");
Some(ArgumentKind::Variadic(variadic_start))
} else {
None
@ -314,9 +316,9 @@ where
IndentStyle::Visual => shape.indent + 1,
};
let list_shape = Shape::legacy(budget, offset);
let list_lo = context.codemap.span_after(span, "(");
let list_lo = context.snippet_provider.span_after(span, "(");
let items = itemize_list(
context.codemap,
context.snippet_provider,
// FIXME Would be nice to avoid this allocation,
// but I couldn't get the types to work out.
inputs

View file

@ -136,7 +136,7 @@ pub fn rewrite_with_alignment<T: AlignedItem>(
let rest_lo = rest[0].get_span().lo();
let missing_span = mk_sp(init_hi, rest_lo);
let missing_span = mk_sp(
context.codemap.span_after(missing_span, ","),
context.snippet_provider.span_after(missing_span, ","),
missing_span.hi(),
);
@ -227,7 +227,7 @@ fn rewrite_aligned_items_inner<T: AlignedItem>(
}
let items = itemize_list(
context.codemap,
context.snippet_provider,
fields.iter(),
"}",
",",

View file

@ -680,7 +680,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> {
_ => self.push_str(" {"),
}
// Hackery to account for the closing }.
let mod_lo = self.codemap.span_after(source!(self, s), "{");
let mod_lo = self.snippet_provider.span_after(source!(self, s), "{");
let body_snippet =
self.snippet(mk_sp(mod_lo, source!(self, m.inner).hi() - BytePos(1)));
let body_snippet = body_snippet.trim();
@ -708,7 +708,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> {
}
pub fn skip_empty_lines(&mut self, end_pos: BytePos) {
while let Some(pos) = self.codemap
while let Some(pos) = self.snippet_provider
.opt_span_after(mk_sp(self.last_pos, end_pos), "\n")
{
if let Some(snippet) = self.opt_snippet(mk_sp(self.last_pos, pos)) {
@ -756,7 +756,7 @@ impl Rewrite for ast::MetaItem {
.shrink_left(name.len() + 1)
.and_then(|s| s.sub_width(2))?;
let items = itemize_list(
context.codemap,
context.snippet_provider,
list.iter(),
")",
",",