//! and constatns comes before methods).
use config::lists::*;
-use syntax::{ast, codemap::Span};
+use syntax::{ast, attr, codemap::Span};
+use codemap::LineRangeUtils;
use comment::combine_strs_with_missing_comments;
use imports::{path_to_imported_ident, rewrite_import};
use items::rewrite_mod;
use shape::Shape;
use spanned::Spanned;
use utils::mk_sp;
-use visitor::{filter_inline_attrs, rewrite_extern_crate};
+use visitor::{filter_inline_attrs, is_extern_crate, is_mod_decl, is_use_item,
+ rewrite_extern_crate, FmtVisitor};
use std::cmp::Ordering;
write_list(&item_vec, &fmt)
}
+
+fn contains_macro_use_attr(attrs: &[ast::Attribute], span: Span) -> bool {
+ attr::contains_name(&filter_inline_attrs(attrs, span), "macro_use")
+}
+
+/// Returns true for `mod foo;` without any inline attributes.
+/// We cannot reorder modules with attributes because doing so can break the code.
+/// e.g. `#[macro_use]`.
+fn is_mod_decl_without_attr(item: &ast::Item) -> bool {
+ is_mod_decl(item) && !contains_macro_use_attr(&item.attrs, item.span())
+}
+
+fn is_use_item_without_attr(item: &ast::Item) -> bool {
+ is_use_item(item) && !contains_macro_use_attr(&item.attrs, item.span())
+}
+
+fn is_extern_crate_without_attr(item: &ast::Item) -> bool {
+ is_extern_crate(item) && !contains_macro_use_attr(&item.attrs, item.span())
+}
+
+impl<'b, 'a: 'b> FmtVisitor<'a> {
+ pub fn reorder_items<F>(
+ &mut self,
+ items_left: &[&ast::Item],
+ is_item: &F,
+ in_group: bool,
+ ) -> usize
+ where
+ F: Fn(&ast::Item) -> bool,
+ {
+ let mut last = self.codemap.lookup_line_range(items_left[0].span());
+ let item_length = items_left
+ .iter()
+ .take_while(|ppi| {
+ is_item(&***ppi) && (!in_group || {
+ let current = self.codemap.lookup_line_range(ppi.span());
+ let in_same_group = current.lo < last.hi + 2;
+ last = current;
+ in_same_group
+ })
+ })
+ .count();
+ let items = &items_left[..item_length];
+
+ let at_least_one_in_file_lines = items
+ .iter()
+ .any(|item| !out_of_file_lines_range!(self, item.span));
+
+ if at_least_one_in_file_lines {
+ self.format_imports(items);
+ } else {
+ for item in items {
+ self.push_rewrite(item.span, None);
+ }
+ }
+
+ item_length
+ }
+
+ pub fn walk_items(&mut self, mut items_left: &[&ast::Item]) {
+ macro try_reorder_items_with($reorder: ident, $in_group: ident, $pred: ident) {
+ if self.config.$reorder() && $pred(&*items_left[0]) {
+ let used_items_len =
+ self.reorder_items(items_left, &$pred, self.config.$in_group());
+ let (_, rest) = items_left.split_at(used_items_len);
+ items_left = rest;
+ continue;
+ }
+ }
+
+ while !items_left.is_empty() {
+ // If the next item is a `use`, `extern crate` or `mod`, then extract it and any
+ // subsequent items that have the same item kind to be reordered within
+ // `format_imports`. Otherwise, just format the next item for output.
+ {
+ try_reorder_items_with!(
+ reorder_imports,
+ reorder_imports_in_group,
+ is_use_item_without_attr
+ );
+ try_reorder_items_with!(
+ reorder_extern_crates,
+ reorder_extern_crates_in_group,
+ is_extern_crate_without_attr
+ );
+ try_reorder_items_with!(reorder_modules, reorder_modules, is_mod_decl_without_attr);
+ }
+ // Reaching here means items were not reordered. There must be at least
+ // one item left in `items_left`, so calling `unwrap()` here is safe.
+ let (item, rest) = items_left.split_first().unwrap();
+ self.visit_item(item);
+ items_left = rest;
+ }
+ }
+}
use config::lists::*;
use syntax::{ast, visit};
-use syntax::attr::{self, HasAttrs};
+use syntax::attr::HasAttrs;
use syntax::codemap::{self, BytePos, CodeMap, Pos, Span};
use syntax::parse::ParseSess;
}
/// Returns true for `mod foo;`, false for `mod foo { .. }`.
-fn is_mod_decl(item: &ast::Item) -> bool {
+pub fn is_mod_decl(item: &ast::Item) -> bool {
match item.node {
ast::ItemKind::Mod(ref m) => m.inner.hi() != item.span.hi(),
_ => false,
}
}
-fn contains_macro_use_attr(attrs: &[ast::Attribute], span: Span) -> bool {
- attr::contains_name(&filter_inline_attrs(attrs, span), "macro_use")
-}
-
-/// Returns true for `mod foo;` without any inline attributes.
-/// We cannot reorder modules with attributes because doing so can break the code.
-/// e.g. `#[macro_use]`.
-fn is_mod_decl_without_attr(item: &ast::Item) -> bool {
- is_mod_decl(item) && !contains_macro_use_attr(&item.attrs, item.span())
-}
-
-fn is_use_item(item: &ast::Item) -> bool {
+pub fn is_use_item(item: &ast::Item) -> bool {
match item.node {
ast::ItemKind::Use(_) => true,
_ => false,
}
}
-fn is_use_item_without_attr(item: &ast::Item) -> bool {
- is_use_item(item) && !contains_macro_use_attr(&item.attrs, item.span())
-}
-
-fn is_extern_crate(item: &ast::Item) -> bool {
+pub fn is_extern_crate(item: &ast::Item) -> bool {
match item.node {
ast::ItemKind::ExternCrate(..) => true,
_ => false,
}
}
-fn is_extern_crate_without_attr(item: &ast::Item) -> bool {
- is_extern_crate(item) && !contains_macro_use_attr(&item.attrs, item.span())
-}
-
/// Creates a string slice corresponding to the specified span.
pub struct SnippetProvider<'a> {
/// A pointer to the content of the file we are formatting.
false
}
- fn reorder_items<F>(&mut self, items_left: &[&ast::Item], is_item: &F, in_group: bool) -> usize
- where
- F: Fn(&ast::Item) -> bool,
- {
- let mut last = self.codemap.lookup_line_range(items_left[0].span());
- let item_length = items_left
- .iter()
- .take_while(|ppi| {
- is_item(&***ppi) && (!in_group || {
- let current = self.codemap.lookup_line_range(ppi.span());
- let in_same_group = current.lo < last.hi + 2;
- last = current;
- in_same_group
- })
- })
- .count();
- let items = &items_left[..item_length];
-
- let at_least_one_in_file_lines = items
- .iter()
- .any(|item| !out_of_file_lines_range!(self, item.span));
-
- if at_least_one_in_file_lines {
- self.format_imports(items);
- } else {
- for item in items {
- self.push_rewrite(item.span, None);
- }
- }
-
- item_length
- }
-
- fn walk_items(&mut self, mut items_left: &[&ast::Item]) {
- macro try_reorder_items_with($reorder: ident, $in_group: ident, $pred: ident) {
- if self.config.$reorder() && $pred(&*items_left[0]) {
- let used_items_len =
- self.reorder_items(items_left, &$pred, self.config.$in_group());
- let (_, rest) = items_left.split_at(used_items_len);
- items_left = rest;
- continue;
- }
- }
-
- while !items_left.is_empty() {
- // If the next item is a `use`, `extern crate` or `mod`, then extract it and any
- // subsequent items that have the same item kind to be reordered within
- // `format_imports`. Otherwise, just format the next item for output.
- {
- try_reorder_items_with!(
- reorder_imports,
- reorder_imports_in_group,
- is_use_item_without_attr
- );
- try_reorder_items_with!(
- reorder_extern_crates,
- reorder_extern_crates_in_group,
- is_extern_crate_without_attr
- );
- try_reorder_items_with!(reorder_modules, reorder_modules, is_mod_decl_without_attr);
- }
- // Reaching here means items were not reordered. There must be at least
- // one item left in `items_left`, so calling `unwrap()` here is safe.
- let (item, rest) = items_left.split_first().unwrap();
- self.visit_item(item);
- items_left = rest;
- }
- }
-
fn walk_mod_items(&mut self, m: &ast::Mod) {
self.walk_items(&ptr_vec_to_ref_vec(&m.items));
}