diff --git a/src/formatting.rs b/src/formatting.rs index e42864a5055..2c38de04797 100644 --- a/src/formatting.rs +++ b/src/formatting.rs @@ -145,7 +145,7 @@ fn format_file( module: &Module<'_>, is_macro_def: bool, ) -> Result<(), ErrorKind> { - let snippet_provider = self.parse_session.snippet_provider(module.as_ref().inner); + let snippet_provider = self.parse_session.snippet_provider(module.span); let mut visitor = FmtVisitor::from_parse_sess( &self.parse_session, &self.config, diff --git a/src/items.rs b/src/items.rs index 6cdbb686ad8..00757210ce5 100644 --- a/src/items.rs +++ b/src/items.rs @@ -3271,8 +3271,8 @@ pub(crate) fn rewrite_extern_crate( /// Returns `true` for `mod foo;`, false for `mod foo { .. }`. pub(crate) fn is_mod_decl(item: &ast::Item) -> bool { match item.kind { - ast::ItemKind::Mod(ref m) => m.inner.hi() != item.span.hi(), - _ => false, + ast::ItemKind::Mod(_, ast::ModKind::Loaded(_, ast::Inline::Yes, _)) => false, + _ => true, } } diff --git a/src/modules.rs b/src/modules.rs index eaa889bcb3f..2ee3639ffb1 100644 --- a/src/modules.rs +++ b/src/modules.rs @@ -6,6 +6,7 @@ use rustc_ast::attr::HasAttrs; use rustc_ast::visit::Visitor; use rustc_span::symbol::{self, sym, Symbol}; +use rustc_span::Span; use thiserror::Error; use crate::attr::MetaVisitor; @@ -24,20 +25,31 @@ /// Represents module with its inner attributes. #[derive(Debug, Clone)] pub(crate) struct Module<'a> { - ast_mod: Cow<'a, ast::Mod>, + ast_mod_kind: Option>, + pub(crate) items: Cow<'a, Vec>>, + attrs: Cow<'a, Vec>, inner_attr: Vec, + pub(crate) span: Span, } impl<'a> Module<'a> { - pub(crate) fn new(ast_mod: Cow<'a, ast::Mod>, attrs: &[ast::Attribute]) -> Self { - let inner_attr = attrs + pub(crate) fn new( + mod_span: Span, + ast_mod_kind: Option>, + mod_items: Cow<'a, Vec>>, + mod_attrs: Cow<'a, Vec>, + ) -> Self { + let inner_attr = mod_attrs .iter() .filter(|attr| attr.style == ast::AttrStyle::Inner) .cloned() .collect(); Module { - ast_mod, + items: mod_items, + attrs: mod_attrs, inner_attr, + span: mod_span, + ast_mod_kind, } } } @@ -51,12 +63,6 @@ fn visit_attrs(&mut self, f: impl FnOnce(&mut Vec)) { } } -impl<'a> AsRef for Module<'a> { - fn as_ref(&self) -> &ast::Mod { - &self.ast_mod - } -} - /// Maps each module to the corresponding file. pub(crate) struct ModResolver<'ast, 'sess> { parse_sess: &'sess ParseSess, @@ -124,12 +130,17 @@ pub(crate) fn visit_crate( // Skip visiting sub modules when the input is from stdin. if self.recursive { - self.visit_mod_from_ast(&krate.module)?; + self.visit_mod_from_ast(&krate.items)?; } self.file_map.insert( root_filename, - Module::new(Cow::Borrowed(&krate.module), &krate.attrs), + Module::new( + krate.span, + None, + Cow::Borrowed(&krate.items), + Cow::Borrowed(&krate.attrs), + ), ); Ok(self.file_map) } @@ -139,10 +150,15 @@ fn visit_cfg_if(&mut self, item: Cow<'ast, ast::Item>) -> Result<(), ModuleResol let mut visitor = visitor::CfgIfVisitor::new(self.parse_sess); visitor.visit_item(&item); for module_item in visitor.mods() { - if let ast::ItemKind::Mod(ref sub_mod) = module_item.item.kind { + if let ast::ItemKind::Mod(_, ref sub_mod_kind) = module_item.item.kind { self.visit_sub_mod( &module_item.item, - Module::new(Cow::Owned(sub_mod.clone()), &module_item.item.attrs), + Module::new( + module_item.item.span, + Some(Cow::Owned(sub_mod_kind.clone())), + Cow::Owned(vec![]), + Cow::Owned(vec![]), + ), )?; } } @@ -150,29 +166,53 @@ fn visit_cfg_if(&mut self, item: Cow<'ast, ast::Item>) -> Result<(), ModuleResol } /// Visit modules defined inside macro calls. - fn visit_mod_outside_ast(&mut self, module: ast::Mod) -> Result<(), ModuleResolutionError> { - for item in module.items { + fn visit_mod_outside_ast( + &mut self, + items: Vec>, + ) -> Result<(), ModuleResolutionError> { + for item in items { if is_cfg_if(&item) { self.visit_cfg_if(Cow::Owned(item.into_inner()))?; continue; } - if let ast::ItemKind::Mod(ref sub_mod) = item.kind { - self.visit_sub_mod(&item, Module::new(Cow::Owned(sub_mod.clone()), &item.attrs))?; + if let ast::ItemKind::Mod(_, ref sub_mod_kind) = item.kind { + let span = item.span; + self.visit_sub_mod( + &item, + Module::new( + span, + Some(Cow::Owned(sub_mod_kind.clone())), + Cow::Owned(vec![]), + Cow::Owned(vec![]), + ), + )?; } } Ok(()) } /// Visit modules from AST. - fn visit_mod_from_ast(&mut self, module: &'ast ast::Mod) -> Result<(), ModuleResolutionError> { - for item in &module.items { + fn visit_mod_from_ast( + &mut self, + items: &'ast Vec>, + ) -> Result<(), ModuleResolutionError> { + for item in items { if is_cfg_if(item) { self.visit_cfg_if(Cow::Borrowed(item))?; } - if let ast::ItemKind::Mod(ref sub_mod) = item.kind { - self.visit_sub_mod(item, Module::new(Cow::Borrowed(sub_mod), &item.attrs))?; + if let ast::ItemKind::Mod(_, ref sub_mod_kind) = item.kind { + let span = item.span; + self.visit_sub_mod( + item, + Module::new( + span, + Some(Cow::Borrowed(sub_mod_kind)), + Cow::Owned(vec![]), + Cow::Borrowed(&item.attrs), + ), + )?; } } Ok(()) @@ -273,9 +313,12 @@ fn visit_sub_mod_after_directory_update( if let Some(directory) = directory { self.directory = directory; } - match sub_mod.ast_mod { - Cow::Borrowed(sub_mod) => self.visit_mod_from_ast(sub_mod), - Cow::Owned(sub_mod) => self.visit_mod_outside_ast(sub_mod), + match (sub_mod.ast_mod_kind, sub_mod.items) { + (Some(Cow::Borrowed(ast::ModKind::Loaded(items, ast::Inline::No, _))), _) => { + self.visit_mod_from_ast(&items) + } + (Some(Cow::Owned(..)), Cow::Owned(items)) => self.visit_mod_outside_ast(items), + (_, _) => Ok(()), } } @@ -294,13 +337,17 @@ fn find_external_module( if self.parse_sess.is_file_parsed(&path) { return Ok(None); } - return match Parser::parse_file_as_module(self.parse_sess, &path, sub_mod.ast_mod.inner) - { - Ok((_, ref attrs)) if contains_skip(attrs) => Ok(None), - Ok(m) => Ok(Some(SubModKind::External( + return match Parser::parse_file_as_module(self.parse_sess, &path, sub_mod.span) { + Ok((ref attrs, _, _)) if contains_skip(attrs) => Ok(None), + Ok((attrs, items, span)) => Ok(Some(SubModKind::External( path, DirectoryOwnership::Owned { relative: None }, - Module::new(Cow::Owned(m.0), &m.1), + Module::new( + span, + Some(Cow::Owned(ast::ModKind::Unloaded)), + Cow::Owned(items), + Cow::Owned(attrs), + ), ))), Err(ParserError::ParseError) => Err(ModuleResolutionError { module: mod_name.to_string(), @@ -338,18 +385,30 @@ fn find_external_module( return Ok(Some(SubModKind::MultiExternal(mods_outside_ast))); } } - match Parser::parse_file_as_module(self.parse_sess, &path, sub_mod.ast_mod.inner) { - Ok((_, ref attrs)) if contains_skip(attrs) => Ok(None), - Ok(m) if outside_mods_empty => Ok(Some(SubModKind::External( - path, - ownership, - Module::new(Cow::Owned(m.0), &m.1), - ))), - Ok(m) => { + match Parser::parse_file_as_module(self.parse_sess, &path, sub_mod.span) { + Ok((ref attrs, _, _)) if contains_skip(attrs) => Ok(None), + Ok((attrs, items, span)) if outside_mods_empty => { + Ok(Some(SubModKind::External( + path, + ownership, + Module::new( + span, + Some(Cow::Owned(ast::ModKind::Unloaded)), + Cow::Owned(items), + Cow::Owned(attrs), + ), + ))) + } + Ok((attrs, items, span)) => { mods_outside_ast.push(( path.clone(), ownership, - Module::new(Cow::Owned(m.0), &m.1), + Module::new( + span, + Some(Cow::Owned(ast::ModKind::Unloaded)), + Cow::Owned(items), + Cow::Owned(attrs), + ), )); if should_insert { mods_outside_ast.push((path, ownership, sub_mod.clone())); @@ -437,20 +496,22 @@ fn find_mods_outside_of_ast( )); continue; } - let m = match Parser::parse_file_as_module( - self.parse_sess, - &actual_path, - sub_mod.ast_mod.inner, - ) { - Ok((_, ref attrs)) if contains_skip(attrs) => continue, - Ok(m) => m, - Err(..) => continue, - }; + let (attrs, items, span) = + match Parser::parse_file_as_module(self.parse_sess, &actual_path, sub_mod.span) { + Ok((ref attrs, _, _)) if contains_skip(attrs) => continue, + Ok(m) => m, + Err(..) => continue, + }; result.push(( actual_path, DirectoryOwnership::Owned { relative: None }, - Module::new(Cow::Owned(m.0), &m.1), + Module::new( + span, + Some(Cow::Owned(ast::ModKind::Unloaded)), + Cow::Owned(items), + Cow::Owned(attrs), + ), )) } result diff --git a/src/syntux/parser.rs b/src/syntux/parser.rs index 5c555e06a80..29248ced2ff 100644 --- a/src/syntux/parser.rs +++ b/src/syntux/parser.rs @@ -1,8 +1,8 @@ use std::panic::{catch_unwind, AssertUnwindSafe}; use std::path::{Path, PathBuf}; -use rustc_ast::ast; use rustc_ast::token::{DelimToken, TokenKind}; +use rustc_ast::{ast, ptr}; use rustc_errors::Diagnostic; use rustc_parse::{ new_parser_from_file, @@ -109,10 +109,10 @@ pub(crate) fn parse_file_as_module( sess: &'a ParseSess, path: &Path, span: Span, - ) -> Result<(ast::Mod, Vec), ParserError> { + ) -> Result<(Vec, Vec>, Span), ParserError> { let result = catch_unwind(AssertUnwindSafe(|| { let mut parser = new_parser_from_file(sess.inner(), &path, Some(span)); - match parser.parse_mod(&TokenKind::Eof, ast::Unsafe::No) { + match parser.parse_mod(&TokenKind::Eof) { Ok(result) => Some(result), Err(mut e) => { sess.emit_or_cancel_diagnostic(&mut e); diff --git a/src/visitor.rs b/src/visitor.rs index 34e8536b7ee..4cd6b8d56d1 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -524,10 +524,9 @@ pub(crate) fn visit_item(&mut self, item: &ast::Item) { self.visit_enum(item.ident, &item.vis, def, generics, item.span); self.last_pos = source!(self, item.span).hi(); } - ast::ItemKind::Mod(ref module) => { - let is_inline = !is_mod_decl(item); + ast::ItemKind::Mod(unsafety, ref mod_kind) => { self.format_missing_with_indent(source!(self, item.span).lo()); - self.format_mod(module, &item.vis, item.span, item.ident, attrs, is_inline); + self.format_mod(mod_kind, unsafety, &item.vis, item.span, item.ident, attrs); } ast::ItemKind::MacCall(ref mac) => { self.visit_mac(mac, Some(item.ident), MacroPosition::Item); @@ -921,8 +920,8 @@ fn is_unknown_rustfmt_attr(&self, segments: &[ast::PathSegment]) -> bool { !is_skip_attr(segments) } - fn walk_mod_items(&mut self, m: &ast::Mod) { - self.visit_items_with_reordering(&ptr_vec_to_ref_vec(&m.items)); + fn walk_mod_items(&mut self, items: &Vec>) { + self.visit_items_with_reordering(&ptr_vec_to_ref_vec(&items)); } fn walk_stmts(&mut self, stmts: &[Stmt<'_>], include_current_empty_semi: bool) { @@ -974,22 +973,22 @@ fn walk_block_stmts(&mut self, b: &ast::Block) { fn format_mod( &mut self, - m: &ast::Mod, + mod_kind: &ast::ModKind, + unsafety: ast::Unsafe, vis: &ast::Visibility, s: Span, 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(format_unsafety(unsafety)); self.push_str("mod "); // Calling `to_owned()` to work around borrow checker. let ident_str = rewrite_ident(&self.get_context(), ident).to_owned(); self.push_str(&ident_str); - if is_internal { + if let ast::ModKind::Loaded(ref items, ast::Inline::Yes, inner_span) = mod_kind { match self.config.brace_style() { BraceStyle::AlwaysNextLine => { let indent_str = self.block_indent.to_string_with_newline(self.config); @@ -1001,7 +1000,7 @@ fn format_mod( // Hackery to account for the closing }. 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))); + self.snippet(mk_sp(mod_lo, source!(self, inner_span).hi() - BytePos(1))); let body_snippet = body_snippet.trim(); if body_snippet.is_empty() { self.push_str("}"); @@ -1009,11 +1008,11 @@ fn format_mod( self.last_pos = mod_lo; self.block_indent = self.block_indent.block_indent(self.config); self.visit_attrs(attrs, ast::AttrStyle::Inner); - self.walk_mod_items(m); - let missing_span = self.next_span(m.inner.hi() - BytePos(1)); + self.walk_mod_items(items); + let missing_span = self.next_span(inner_span.hi() - BytePos(1)); self.close_block(missing_span, false); } - self.last_pos = source!(self, m.inner).hi(); + self.last_pos = source!(self, inner_span).hi(); } else { self.push_str(";"); self.last_pos = source!(self, s).hi(); @@ -1023,9 +1022,9 @@ fn format_mod( pub(crate) fn format_separate_mod(&mut self, m: &Module<'_>, end_pos: BytePos) { self.block_indent = Indent::empty(); if self.visit_attrs(m.attrs(), ast::AttrStyle::Inner) { - self.push_skipped_with_span(m.attrs(), m.as_ref().inner, m.as_ref().inner); + self.push_skipped_with_span(m.attrs(), m.span, m.span); } else { - self.walk_mod_items(m.as_ref()); + self.walk_mod_items(&m.items); self.format_missing_with_indent(end_pos); } }