-// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
//! Format attributes and meta items.
-use comment::{contains_comment, rewrite_doc_comment, CommentStyle};
-use config::lists::*;
-use config::IndentStyle;
-use expr::rewrite_literal;
-use lists::{definitive_tactic, itemize_list, write_list, ListFormatting, Separator};
-use overflow;
-use rewrite::{Rewrite, RewriteContext};
-use shape::Shape;
-use types::{rewrite_path, PathContext};
-use utils::{count_newlines, mk_sp};
-
use syntax::ast;
use syntax::source_map::{BytePos, Span, DUMMY_SP};
+use syntax::symbol::sym;
+
+use self::doc_comment::DocCommentFormatter;
+use crate::comment::{contains_comment, rewrite_doc_comment, CommentStyle};
+use crate::config::lists::*;
+use crate::config::IndentStyle;
+use crate::expr::rewrite_literal;
+use crate::lists::{definitive_tactic, itemize_list, write_list, ListFormatting, Separator};
+use crate::overflow;
+use crate::rewrite::{Rewrite, RewriteContext};
+use crate::shape::Shape;
+use crate::types::{rewrite_path, PathContext};
+use crate::utils::{count_newlines, mk_sp};
+
+mod doc_comment;
/// Returns attributes on the given statement.
-pub fn get_attrs_from_stmt(stmt: &ast::Stmt) -> &[ast::Attribute] {
- match stmt.node {
+pub(crate) fn get_attrs_from_stmt(stmt: &ast::Stmt) -> &[ast::Attribute] {
+ match stmt.kind {
ast::StmtKind::Local(ref local) => &local.attrs,
ast::StmtKind::Item(ref item) => &item.attrs,
ast::StmtKind::Expr(ref expr) | ast::StmtKind::Semi(ref expr) => &expr.attrs,
}
}
+pub(crate) fn get_span_without_attrs(stmt: &ast::Stmt) -> Span {
+ match stmt.kind {
+ ast::StmtKind::Local(ref local) => local.span,
+ ast::StmtKind::Item(ref item) => item.span,
+ ast::StmtKind::Expr(ref expr) | ast::StmtKind::Semi(ref expr) => expr.span,
+ ast::StmtKind::Mac(ref mac) => {
+ let (ref mac, _, _) = **mac;
+ mac.span
+ }
+ }
+}
+
/// Returns attributes that are within `outer_span`.
-pub fn filter_inline_attrs(attrs: &[ast::Attribute], outer_span: Span) -> Vec<ast::Attribute> {
+pub(crate) fn filter_inline_attrs(
+ attrs: &[ast::Attribute],
+ outer_span: Span,
+) -> Vec<ast::Attribute> {
attrs
.iter()
.filter(|a| outer_span.lo() <= a.span.lo() && a.span.hi() <= outer_span.hi())
}
fn is_derive(attr: &ast::Attribute) -> bool {
- attr.check_name("derive")
+ attr.check_name(sym::derive)
}
/// Returns the arguments of `#[derive(...)]`.
-fn get_derive_spans(attr: &ast::Attribute) -> Option<Vec<Span>> {
+fn get_derive_spans<'a>(attr: &'a ast::Attribute) -> Option<impl Iterator<Item = Span> + 'a> {
attr.meta_item_list().map(|meta_item_list| {
meta_item_list
- .iter()
- .map(|nested_meta_item| nested_meta_item.span)
- .collect()
+ .into_iter()
+ .map(|nested_meta_item| nested_meta_item.span())
})
}
right: usize,
combine: bool,
shape: Shape,
- context: &RewriteContext,
+ context: &RewriteContext<'_>,
) -> Option<Shape> {
match context.config.indent_style() {
IndentStyle::Block => {
derive_args: &[Span],
prefix: &str,
shape: Shape,
- context: &RewriteContext,
+ context: &RewriteContext<'_>,
) -> Option<String> {
let mut result = String::with_capacity(128);
result.push_str(prefix);
/// Returns the first group of attributes that fills the given predicate.
/// We consider two doc comments are in different group if they are separated by normal comments.
fn take_while_with_pred<'a, P>(
- context: &RewriteContext,
+ context: &RewriteContext<'_>,
attrs: &'a [ast::Attribute],
pred: P,
) -> &'a [ast::Attribute]
/// Rewrite the any doc comments which come before any other attributes.
fn rewrite_initial_doc_comments(
- context: &RewriteContext,
+ context: &RewriteContext<'_>,
attrs: &[ast::Attribute],
shape: Shape,
) -> Option<(usize, Option<String>)> {
}
impl Rewrite for ast::NestedMetaItem {
- fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option<String> {
- match self.node {
- ast::NestedMetaItemKind::MetaItem(ref meta_item) => meta_item.rewrite(context, shape),
- ast::NestedMetaItemKind::Literal(ref l) => rewrite_literal(context, l, shape),
+ fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option<String> {
+ match self {
+ ast::NestedMetaItem::MetaItem(ref meta_item) => meta_item.rewrite(context, shape),
+ ast::NestedMetaItem::Literal(ref l) => rewrite_literal(context, l, shape),
}
}
}
}
impl Rewrite for ast::MetaItem {
- fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option<String> {
- Some(match self.node {
+ fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option<String> {
+ Some(match self.kind {
ast::MetaItemKind::Word => {
- rewrite_path(context, PathContext::Type, None, &self.ident, shape)?
+ rewrite_path(context, PathContext::Type, None, &self.path, shape)?
}
ast::MetaItemKind::List(ref list) => {
- let path = rewrite_path(context, PathContext::Type, None, &self.ident, shape)?;
- let has_trailing_comma = ::expr::span_ends_with_comma(context, self.span);
+ let path = rewrite_path(context, PathContext::Type, None, &self.path, shape)?;
+ let has_trailing_comma = crate::expr::span_ends_with_comma(context, self.span);
overflow::rewrite_with_parens(
context,
&path,
)?
}
ast::MetaItemKind::NameValue(ref literal) => {
- let path = rewrite_path(context, PathContext::Type, None, &self.ident, shape)?;
+ let path = rewrite_path(context, PathContext::Type, None, &self.path, shape)?;
// 3 = ` = `
let lit_shape = shape.shrink_left(path.len() + 3)?;
// `rewrite_literal` returns `None` when `literal` exceeds max
get_hi: F2,
get_item_string: F3,
span: Span,
- context: &RewriteContext,
+ context: &RewriteContext<'_>,
shape: Shape,
one_line_shape: Shape,
one_line_limit: Option<usize>,
}
impl Rewrite for ast::Attribute {
- fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option<String> {
+ fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option<String> {
let snippet = context.snippet(self.span);
if self.is_sugared_doc {
rewrite_doc_comment(snippet, shape.comment(context.config), context.config)
} else {
+ let should_skip = self
+ .ident()
+ .map(|s| context.skip_context.skip_attribute(&s.name.as_str()))
+ .unwrap_or(false);
let prefix = attr_prefix(self);
- if contains_comment(snippet) {
+ if should_skip || contains_comment(snippet) {
return Some(snippet.to_owned());
}
if let Some(ref meta) = self.meta() {
// This attribute is possibly a doc attribute needing normalization to a doc comment
- if context.config.normalize_doc_attributes() && meta.check_name("doc") {
+ if context.config.normalize_doc_attributes() && meta.check_name(sym::doc) {
if let Some(ref literal) = meta.value_str() {
let comment_style = match self.style {
ast::AttrStyle::Inner => CommentStyle::Doc,
ast::AttrStyle::Outer => CommentStyle::TripleSlash,
};
- // Remove possible whitespace from the `CommentStyle::opener()` so that
- // the literal itself has control over the comment's leading spaces.
- let opener = comment_style.opener().trim_end();
-
- let doc_comment = format!("{}{}", opener, literal);
+ let literal_str = literal.as_str();
+ let doc_comment_formatter =
+ DocCommentFormatter::new(&*literal_str, comment_style);
+ let doc_comment = format!("{}", doc_comment_formatter);
return rewrite_doc_comment(
&doc_comment,
shape.comment(context.config),
}
impl<'a> Rewrite for [ast::Attribute] {
- fn rewrite(&self, context: &RewriteContext, shape: Shape) -> Option<String> {
+ fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option<String> {
if self.is_empty() {
return Some(String::new());
}
if let Some(missing_span) = missing_span {
let snippet = context.snippet(missing_span);
let (mla, mlb) = has_newlines_before_after_comment(snippet);
- let comment = ::comment::recover_missing_comment_in_span(
+ let comment = crate::comment::recover_missing_comment_in_span(
missing_span,
shape.with_max_width(context.config),
context,
// Handle derives if we will merge them.
if context.config.merge_derives() && is_derive(&attrs[0]) {
let derives = take_while_with_pred(context, attrs, is_derive);
- let mut derive_spans = vec![];
- for derive in derives {
- derive_spans.append(&mut get_derive_spans(derive)?);
- }
+ let derive_spans: Vec<_> = derives
+ .iter()
+ .filter_map(get_derive_spans)
+ .flatten()
+ .collect();
let derive_str =
format_derive(&derive_spans, attr_prefix(&attrs[0]), shape, context)?;
result.push_str(&derive_str);
.get(derives.len())
.map(|next| mk_sp(attrs[derives.len() - 1].span.hi(), next.span.lo()));
if let Some(missing_span) = missing_span {
- let comment = ::comment::recover_missing_comment_in_span(
+ let comment = crate::comment::recover_missing_comment_in_span(
missing_span,
shape.with_max_width(context.config),
context,
.get(1)
.map(|next| mk_sp(attrs[0].span.hi(), next.span.lo()));
if let Some(missing_span) = missing_span {
- let comment = ::comment::recover_missing_comment_in_span(
+ let comment = crate::comment::recover_missing_comment_in_span(
missing_span,
shape.with_max_width(context.config),
context,
ast::AttrStyle::Outer => "#",
}
}
+
+pub(crate) trait MetaVisitor<'ast> {
+ fn visit_meta_item(&mut self, meta_item: &'ast ast::MetaItem) {
+ match meta_item.kind {
+ ast::MetaItemKind::Word => self.visit_meta_word(meta_item),
+ ast::MetaItemKind::List(ref list) => self.visit_meta_list(meta_item, list),
+ ast::MetaItemKind::NameValue(ref lit) => self.visit_meta_name_value(meta_item, lit),
+ }
+ }
+
+ fn visit_meta_list(
+ &mut self,
+ _meta_item: &'ast ast::MetaItem,
+ list: &'ast [ast::NestedMetaItem],
+ ) {
+ for nm in list {
+ self.visit_nested_meta_item(nm);
+ }
+ }
+
+ fn visit_meta_word(&mut self, _meta_item: &'ast ast::MetaItem) {}
+
+ fn visit_meta_name_value(&mut self, _meta_item: &'ast ast::MetaItem, _lit: &'ast ast::Lit) {}
+
+ fn visit_nested_meta_item(&mut self, nm: &'ast ast::NestedMetaItem) {
+ match nm {
+ ast::NestedMetaItem::MetaItem(ref meta_item) => self.visit_meta_item(meta_item),
+ ast::NestedMetaItem::Literal(ref lit) => self.visit_literal(lit),
+ }
+ }
+
+ fn visit_literal(&mut self, _lit: &'ast ast::Lit) {}
+}