X-Git-Url: https://git.lizzy.rs/?a=blobdiff_plain;f=src%2Fvisitor.rs;h=fefeffac95c8fc416a510e215e7f6a2ff8664f65;hb=b7c38c9d50fcf48e40cf245b48ab9f36054f40d3;hp=27e4f6543b09c04efe8cc072ed35cb4998fa4e9a;hpb=b173b42354ec8d77d1613de383c9a0ea801f9a9d;p=rust.git diff --git a/src/visitor.rs b/src/visitor.rs index 27e4f6543b0..fefeffac95c 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -1,22 +1,21 @@ use std::cell::{Cell, RefCell}; use std::rc::Rc; -use rustc_ast::token::DelimToken; -use rustc_ast::{ast, visit}; -use rustc_span::{BytePos, Pos, Span}; +use rustc_ast::{ast, attr::HasAttrs, token::DelimToken, visit}; +use rustc_span::{symbol, BytePos, Pos, Span, DUMMY_SP}; use crate::attr::*; -use crate::comment::{rewrite_comment, CodeCharKind, CommentCodeSlices}; +use crate::comment::{contains_comment, rewrite_comment, CodeCharKind, CommentCodeSlices}; use crate::config::Version; use crate::config::{BraceStyle, Config}; use crate::coverage::transform_missing_snippet; use crate::items::{ format_impl, format_trait, format_trait_alias, is_mod_decl, is_use_item, - rewrite_associated_impl_type, rewrite_associated_type, rewrite_extern_crate, - rewrite_opaque_impl_type, rewrite_opaque_type, rewrite_type_alias, FnBraceStyle, FnSig, - StaticParts, StructParts, + rewrite_associated_impl_type, rewrite_extern_crate, rewrite_opaque_impl_type, + rewrite_opaque_type, rewrite_type_alias, FnBraceStyle, FnSig, StaticParts, StructParts, }; use crate::macros::{macro_style, rewrite_macro, rewrite_macro_def, MacroPosition}; +use crate::modules::Module; use crate::rewrite::{Rewrite, RewriteContext}; use crate::shape::{Indent, Shape}; use crate::skip::{is_skip_attr, SkipContext}; @@ -25,8 +24,8 @@ use crate::stmt::Stmt; use crate::syntux::session::ParseSess; use crate::utils::{ - self, contains_skip, count_newlines, depr_skip_annotation, inner_attributes, last_line_width, - mk_sp, ptr_vec_to_ref_vec, rewrite_ident, stmt_expr, + self, contains_skip, count_newlines, depr_skip_annotation, format_unsafety, inner_attributes, + last_line_width, mk_sp, ptr_vec_to_ref_vec, rewrite_ident, starts_with_newline, stmt_expr, }; use crate::{ErrorKind, FormatReport, FormattingError}; @@ -87,6 +86,7 @@ pub(crate) struct FmtVisitor<'a> { pub(crate) macro_rewrite_failure: bool, pub(crate) report: FormatReport, pub(crate) skip_context: SkipContext, + pub(crate) is_macro_def: bool, } impl<'a> Drop for FmtVisitor<'a> { @@ -118,10 +118,22 @@ fn visit_stmt(&mut self, stmt: &Stmt<'_>) { self.parse_sess.span_to_debug_info(stmt.span()) ); - // https://github.com/rust-lang/rust/issues/63679. - let is_all_semicolons = - |snippet: &str| snippet.chars().all(|c| c.is_whitespace() || c == ';'); - if is_all_semicolons(&self.snippet(stmt.span())) { + if stmt.is_empty() { + // If the statement is empty, just skip over it. Before that, make sure any comment + // snippet preceding the semicolon is picked up. + let snippet = self.snippet(mk_sp(self.last_pos, stmt.span().lo())); + let original_starts_with_newline = snippet + .find(|c| c != ' ') + .map_or(false, |i| starts_with_newline(&snippet[i..])); + let snippet = snippet.trim(); + if !snippet.is_empty() { + if original_starts_with_newline { + self.push_str("\n"); + } + self.push_str(&self.block_indent.to_string(self.config)); + self.push_str(snippet); + } + self.last_pos = stmt.span().hi(); return; } @@ -133,34 +145,28 @@ fn visit_stmt(&mut self, stmt: &Stmt<'_>) { self.format_missing(stmt.span().hi()); } ast::StmtKind::Local(..) | ast::StmtKind::Expr(..) | ast::StmtKind::Semi(..) => { - if let Some(attrs) = get_attrs_from_stmt(stmt.as_ast_node()) { - if contains_skip(attrs) { - self.push_skipped_with_span( - attrs, - stmt.span(), - get_span_without_attrs(stmt.as_ast_node()), - ); - } else { - let shape = self.shape(); - let rewrite = self.with_context(|ctx| stmt.rewrite(&ctx, shape)); - self.push_rewrite(stmt.span(), rewrite) - } + let attrs = get_attrs_from_stmt(stmt.as_ast_node()); + if contains_skip(attrs) { + self.push_skipped_with_span( + attrs, + stmt.span(), + get_span_without_attrs(stmt.as_ast_node()), + ); } else { let shape = self.shape(); let rewrite = self.with_context(|ctx| stmt.rewrite(&ctx, shape)); self.push_rewrite(stmt.span(), rewrite) } } - ast::StmtKind::MacCall(ref mac) => { - let (ref mac, _macro_style, ref attrs) = **mac; - if self.visit_attrs(attrs, ast::AttrStyle::Outer) { + ast::StmtKind::MacCall(ref mac_stmt) => { + if self.visit_attrs(&mac_stmt.attrs, ast::AttrStyle::Outer) { self.push_skipped_with_span( - attrs, + &mac_stmt.attrs, stmt.span(), get_span_without_attrs(stmt.as_ast_node()), ); } else { - self.visit_mac(mac, None, MacroPosition::Statement); + self.visit_mac(&mac_stmt.mac, None, MacroPosition::Statement); } self.format_missing(stmt.span().hi()); } @@ -255,14 +261,23 @@ fn close_block(&mut self, span: Span, unindent_comment: bool) { trimmed.is_empty() || trimmed.chars().all(|c| c == ';') }; - for (kind, offset, sub_slice) in CommentCodeSlices::new(self.snippet(span)) { + let comment_snippet = self.snippet(span); + + let align_to_right = if unindent_comment && contains_comment(&comment_snippet) { + let first_lines = comment_snippet.splitn(2, '/').next().unwrap_or(""); + last_line_width(first_lines) > last_line_width(&comment_snippet) + } else { + false + }; + + for (kind, offset, sub_slice) in CommentCodeSlices::new(comment_snippet) { let sub_slice = transform_missing_snippet(config, sub_slice); debug!("close_block: {:?} {:?} {:?}", kind, offset, sub_slice); match kind { CodeCharKind::Comment => { - if !unindented && unindent_comment { + if !unindented && unindent_comment && !align_to_right { unindented = true; self.block_indent = self.block_indent.block_unindent(config); } @@ -355,7 +370,7 @@ fn unindent_comment_on_closing_brace(&self, b: &ast::Block) -> bool { // Note that this only gets called for function definitions. Required methods // on traits do not get handled here. - fn visit_fn( + pub(crate) fn visit_fn( &mut self, fk: visit::FnKind<'_>, generics: &ast::Generics, @@ -550,12 +565,14 @@ pub(crate) fn visit_item(&mut self, item: &ast::Item) { ast::ItemKind::TyAlias(_, ref generics, ref generic_bounds, ref ty) => match ty { Some(ty) => { let rewrite = rewrite_type_alias( - &self.get_context(), - self.block_indent, item.ident, - &*ty, + Some(&*ty), generics, + Some(generic_bounds), + &self.get_context(), + self.block_indent, &item.vis, + item.span, ); self.push_rewrite(item.span, rewrite); } @@ -567,6 +584,7 @@ pub(crate) fn visit_item(&mut self, item: &ast::Item) { generic_bounds, generics, &item.vis, + item.span, ); self.push_rewrite(item.span, rewrite); } @@ -609,7 +627,11 @@ pub(crate) fn visit_trait_item(&mut self, ti: &ast::AssocItem) { } ast::AssocItemKind::Fn(defaultness, ref sig, ref generics, Some(ref body)) => { let inner_attrs = inner_attributes(&ti.attrs); - let vis = rustc_span::source_map::dummy_spanned(ast::VisibilityKind::Inherited); + let vis = ast::Visibility { + kind: ast::VisibilityKind::Inherited, + span: DUMMY_SP, + tokens: None, + }; let fn_ctxt = visit::FnCtxt::Assoc(visit::AssocCtxt::Trait); self.visit_fn( visit::FnKind::Fn(fn_ctxt, ti.ident, sig, &vis, Some(body)), @@ -621,13 +643,15 @@ pub(crate) fn visit_trait_item(&mut self, ti: &ast::AssocItem) { ); } ast::AssocItemKind::TyAlias(_, ref generics, ref generic_bounds, ref type_default) => { - let rewrite = rewrite_associated_type( + let rewrite = rewrite_type_alias( ti.ident, type_default.as_ref(), generics, Some(generic_bounds), &self.get_context(), self.block_indent, + &ti.vis, + ti.span, ); self.push_rewrite(ti.span, rewrite); } @@ -668,24 +692,26 @@ pub(crate) fn visit_impl_item(&mut self, ii: &ast::AssocItem) { let rewrite_associated = || { rewrite_associated_impl_type( ii.ident, + &ii.vis, defaultness, ty.as_ref(), &generics, &self.get_context(), self.block_indent, + ii.span, ) }; let rewrite = match ty { None => rewrite_associated(), - Some(ty) => match ty.kind.opaque_top_hack() { - Some(generic_bounds) => rewrite_opaque_impl_type( + Some(ty) => match ty.kind { + ast::TyKind::ImplTrait(_, ref bounds) => rewrite_opaque_impl_type( &self.get_context(), ii.ident, generics, - generic_bounds, + bounds, self.block_indent, ), - None => rewrite_associated(), + _ => rewrite_associated(), }, }; self.push_rewrite(ii.span, rewrite); @@ -696,7 +722,7 @@ pub(crate) fn visit_impl_item(&mut self, ii: &ast::AssocItem) { } } - fn visit_mac(&mut self, mac: &ast::MacCall, ident: Option, pos: MacroPosition) { + fn visit_mac(&mut self, mac: &ast::MacCall, ident: Option, pos: MacroPosition) { skip_out_of_file_lines_range_visitor!(self, mac.span()); // 1 = ; @@ -799,6 +825,7 @@ pub(crate) fn from_parse_sess( snippet_provider, line_number: 0, skipped_range: Rc::new(RefCell::new(vec![])), + is_macro_def: false, macro_rewrite_failure: false, report, skip_context: Default::default(), @@ -816,7 +843,7 @@ pub(crate) fn snippet(&'b self, span: Span) -> &'a str { // Returns true if we should skip the following item. pub(crate) fn visit_attrs(&mut self, attrs: &[ast::Attribute], style: ast::AttrStyle) -> bool { for attr in attrs { - if attr.check_name(depr_skip_annotation()) { + if attr.has_name(depr_skip_annotation()) { let file_name = self.parse_sess.span_to_filename(attr.span); self.report.append( file_name, @@ -828,7 +855,7 @@ pub(crate) fn visit_attrs(&mut self, attrs: &[ast::Attribute], style: ast::AttrS ); } else { match &attr.kind { - ast::AttrKind::Normal(ref attribute_item) + ast::AttrKind::Normal(ref attribute_item, _) if self.is_unknown_rustfmt_attr(&attribute_item.path.segments) => { let file_name = self.parse_sess.span_to_filename(attr.span); @@ -902,12 +929,13 @@ fn format_mod( m: &ast::Mod, vis: &ast::Visibility, s: Span, - ident: ast::Ident, + ident: symbol::Ident, attrs: &[ast::Attribute], is_internal: bool, ) { let vis_str = utils::format_visibility(&self.get_context(), vis); self.push_str(&*vis_str); + self.push_str(format_unsafety(m.unsafety)); self.push_str("mod "); // Calling `to_owned()` to work around borrow checker. let ident_str = rewrite_ident(&self.get_context(), ident).to_owned(); @@ -944,10 +972,14 @@ fn format_mod( } } - pub(crate) fn format_separate_mod(&mut self, m: &ast::Mod, end_pos: BytePos) { + pub(crate) fn format_separate_mod(&mut self, m: &Module<'_>, end_pos: BytePos) { self.block_indent = Indent::empty(); - self.walk_mod_items(m); - self.format_missing_with_indent(end_pos); + if self.visit_attrs(m.attrs(), ast::AttrStyle::Inner) { + self.push_skipped_with_span(m.attrs(), m.as_ref().inner, m.as_ref().inner); + } else { + self.walk_mod_items(m.as_ref()); + self.format_missing_with_indent(end_pos); + } } pub(crate) fn skip_empty_lines(&mut self, end_pos: BytePos) { @@ -986,6 +1018,7 @@ pub(crate) fn get_context(&self) -> RewriteContext<'_> { force_one_line_chain: Cell::new(false), snippet_provider: self.snippet_provider, macro_rewrite_failure: Cell::new(false), + is_macro_def: self.is_macro_def, report: self.report.clone(), skip_context: self.skip_context.clone(), skipped_range: self.skipped_range.clone(),