From c60ade442e363d3ec0af71b1c40d3e13a9f34247 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Fri, 7 Jun 2019 00:27:49 +0900 Subject: [PATCH 1/7] Format modules defined in cfg_attr --- src/attr.rs | 33 ++++ src/formatting.rs | 2 +- src/modules.rs | 338 +++++++++++++++++++++++++++++++++-------- src/modules/visitor.rs | 43 ++++++ 4 files changed, 350 insertions(+), 66 deletions(-) diff --git a/src/attr.rs b/src/attr.rs index 78d88958ac7..8497917ab06 100644 --- a/src/attr.rs +++ b/src/attr.rs @@ -488,3 +488,36 @@ fn attr_prefix(attr: &ast::Attribute) -> &'static str { ast::AttrStyle::Outer => "#", } } + +pub(crate) trait MetaVisitor<'ast> { + fn visit_meta_item(&mut self, meta_item: &'ast ast::MetaItem) { + match meta_item.node { + 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) {} +} diff --git a/src/formatting.rs b/src/formatting.rs index 0e98bca9896..d431dd2679c 100644 --- a/src/formatting.rs +++ b/src/formatting.rs @@ -105,7 +105,7 @@ fn format_project( ) .visit_crate(&krate) .map_err(|e| io::Error::new(io::ErrorKind::Other, e))?; - for (path, (module, _)) in files { + for (path, module) in files { let should_ignore = !input_is_stdin && ignore_path_set.is_match(&path); if (config.skip_children() && path != main_file) || should_ignore { continue; diff --git a/src/modules.rs b/src/modules.rs index e54bdb87570..a0e9df9d7bf 100644 --- a/src/modules.rs +++ b/src/modules.rs @@ -3,19 +3,23 @@ use std::collections::BTreeMap; use std::path::{Path, PathBuf}; use syntax::ast; -use syntax::parse::{parser, DirectoryOwnership, ParseSess}; -use syntax::source_map; +use syntax::attr; +use syntax::parse::{ + new_sub_parser_from_file, parser, token, DirectoryOwnership, PResult, ParseSess, +}; +use syntax::source_map::{self, Span}; use syntax::symbol::sym; use syntax::visit::Visitor; -use syntax_pos::symbol::Symbol; +use syntax_pos::{self, symbol::Symbol, DUMMY_SP}; +use crate::attr::MetaVisitor; use crate::config::FileName; use crate::items::is_mod_decl; use crate::utils::contains_skip; mod visitor; -type FileModMap<'ast> = BTreeMap, String)>; +type FileModMap<'ast> = BTreeMap>; /// Maps each module to the corresponding file. pub(crate) struct ModResolver<'ast, 'sess> { @@ -40,13 +44,16 @@ impl<'a> Directory { } } -enum SubModKind { +#[derive(Clone)] +enum SubModKind<'a, 'ast> { /// `mod foo;` External(PathBuf, DirectoryOwnership), + /// `mod foo;` with multiple sources. + MultiExternal(Vec<(PathBuf, DirectoryOwnership, Cow<'ast, ast::Mod>)>), /// `#[path = "..."] mod foo {}` InternalWithPath(PathBuf), /// `mod foo {}` - Internal, + Internal(&'a ast::Item), } impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> { @@ -86,64 +93,48 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> { self.visit_mod_from_ast(&krate.module)?; } - self.file_map.insert( - root_filename.into(), - (Cow::Borrowed(&krate.module), String::new()), - ); + self.file_map + .insert(root_filename.into(), Cow::Borrowed(&krate.module)); Ok(self.file_map) } - /// Visit macro calls and look for module declarations. Currently only supports `cfg_if` macro. - fn visit_mac(&mut self, item: Cow<'ast, ast::Item>) -> Result<(), String> { + /// Visit `cfg_if` macro and look for module declarations. + fn visit_cfg_if(&mut self, item: Cow<'ast, ast::Item>) -> Result<(), String> { let mut visitor = visitor::CfgIfVisitor::new(self.parse_sess, self.directory.to_syntax_directory()); visitor.visit_item(&item); for module_item in visitor.mods() { if let ast::ItemKind::Mod(ref sub_mod) = module_item.item.node { - self.visit_mod_from_mac_inner(&item, Cow::Owned(sub_mod.clone()))?; + self.visit_sub_mod(&item, Cow::Owned(sub_mod.clone()))?; } } Ok(()) } /// Visit modules defined inside macro calls. - fn visit_mod_from_macro(&mut self, module: Cow<'ast, ast::Mod>) -> Result<(), String> { - for item in &module.items { - if let ast::ItemKind::Mac(..) = item.node { - self.visit_mac(Cow::Owned(item.clone().into_inner()))?; + fn visit_mod_outside_ast(&mut self, module: ast::Mod) -> Result<(), String> { + for item in module.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.node { - self.visit_mod_from_mac_inner(item, Cow::Owned(sub_mod.clone()))?; + self.visit_sub_mod(&item, Cow::Owned(sub_mod.clone()))?; } } Ok(()) } - fn visit_mod_from_mac_inner( - &mut self, - item: &'c ast::Item, - sub_mod: Cow<'ast, ast::Mod>, - ) -> Result<(), String> { - let old_directory = self.directory.clone(); - self.visit_sub_mod(item, &sub_mod)?; - self.visit_mod_from_macro(sub_mod)?; - self.directory = old_directory; - Ok(()) - } - /// Visit modules from AST. fn visit_mod_from_ast(&mut self, module: &'ast ast::Mod) -> Result<(), String> { for item in &module.items { - if let ast::ItemKind::Mac(..) = item.node { - self.visit_mac(Cow::Borrowed(item))?; + if is_cfg_if(item) { + self.visit_cfg_if(Cow::Borrowed(item))?; } if let ast::ItemKind::Mod(ref sub_mod) = item.node { - let old_directory = self.directory.clone(); - self.visit_sub_mod(item, &Cow::Borrowed(sub_mod))?; - self.visit_mod_from_ast(sub_mod)?; - self.directory = old_directory; + self.visit_sub_mod(item, Cow::Borrowed(sub_mod))?; } } Ok(()) @@ -152,34 +143,24 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> { fn visit_sub_mod( &mut self, item: &'c ast::Item, - sub_mod: &Cow<'ast, ast::Mod>, + sub_mod: Cow<'ast, ast::Mod>, ) -> Result<(), String> { - match self.peek_sub_mod(item)? { - Some(SubModKind::External(mod_path, directory_ownership)) => { - self.file_map.insert( - FileName::Real(mod_path.clone()), - (sub_mod.clone(), item.ident.name.as_str().get().to_owned()), - ); - self.directory = Directory { - path: mod_path.parent().unwrap().to_path_buf(), - ownership: directory_ownership, - }; - } - Some(SubModKind::InternalWithPath(mod_path)) => { - // All `#[path]` files are treated as though they are a `mod.rs` file. - self.directory = Directory { - path: mod_path, - ownership: DirectoryOwnership::Owned { relative: None }, - }; - } - Some(SubModKind::Internal) => self.push_inline_mod_directory(item.ident, &item.attrs), - None => (), // rustfmt::skip + let old_directory = self.directory.clone(); + let sub_mod_kind = self.peek_sub_mod(item, &sub_mod)?; + if let Some(sub_mod_kind) = sub_mod_kind { + self.insert_sub_mod(sub_mod_kind.clone(), sub_mod.clone())?; + self.visit_sub_mod_inner(sub_mod, sub_mod_kind)?; } + self.directory = old_directory; Ok(()) } /// Inspect the given sub-module which we are about to visit and returns its kind. - fn peek_sub_mod(&self, item: &'c ast::Item) -> Result, String> { + fn peek_sub_mod( + &self, + item: &'c ast::Item, + sub_mod: &Cow<'ast, ast::Mod>, + ) -> Result>, String> { if contains_skip(&item.attrs) { return Ok(None); } @@ -187,28 +168,112 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> { if is_mod_decl(item) { // mod foo; // Look for an extern file. - let (mod_path, directory_ownership) = - self.find_external_module(item.ident, &item.attrs)?; - Ok(Some(SubModKind::External(mod_path, directory_ownership))) + self.find_external_module(item.ident, &item.attrs, sub_mod) + .map(Some) } else { // An internal module (`mod foo { /* ... */ }`); if let Some(path) = find_path_value(&item.attrs) { let path = Path::new(&path.as_str()).to_path_buf(); Ok(Some(SubModKind::InternalWithPath(path))) } else { - Ok(Some(SubModKind::Internal)) + Ok(Some(SubModKind::Internal(item))) } } } + fn insert_sub_mod( + &mut self, + sub_mod_kind: SubModKind<'c, 'ast>, + sub_mod: Cow<'ast, ast::Mod>, + ) -> Result<(), String> { + match sub_mod_kind { + SubModKind::External(mod_path, _) => { + self.file_map.insert(FileName::Real(mod_path), sub_mod); + } + SubModKind::MultiExternal(mods) => { + for (mod_path, _, sub_mod) in mods { + self.file_map.insert(FileName::Real(mod_path), sub_mod); + } + } + _ => (), + } + Ok(()) + } + + fn visit_sub_mod_inner( + &mut self, + sub_mod: Cow<'ast, ast::Mod>, + sub_mod_kind: SubModKind<'c, 'ast>, + ) -> Result<(), String> { + match sub_mod_kind { + SubModKind::External(mod_path, directory_ownership) => { + let directory = Directory { + path: mod_path.parent().unwrap().to_path_buf(), + ownership: directory_ownership, + }; + self.visit_sub_mod_after_directory_update(sub_mod, Some(directory)) + } + SubModKind::InternalWithPath(mod_path) => { + // All `#[path]` files are treated as though they are a `mod.rs` file. + let directory = Directory { + path: mod_path, + ownership: DirectoryOwnership::Owned { relative: None }, + }; + self.visit_sub_mod_after_directory_update(sub_mod, Some(directory)) + } + SubModKind::Internal(ref item) => { + self.push_inline_mod_directory(item.ident, &item.attrs); + self.visit_sub_mod_after_directory_update(sub_mod, None) + } + SubModKind::MultiExternal(mods) => { + for (mod_path, directory_ownership, sub_mod) in mods { + let directory = Directory { + path: mod_path.parent().unwrap().to_path_buf(), + ownership: directory_ownership, + }; + self.visit_sub_mod_after_directory_update(sub_mod, Some(directory))?; + } + Ok(()) + } + } + } + + fn visit_sub_mod_after_directory_update( + &mut self, + sub_mod: Cow<'ast, ast::Mod>, + directory: Option, + ) -> Result<(), String> { + if let Some(directory) = directory { + self.directory = directory; + } + match sub_mod { + Cow::Borrowed(sub_mod) => self.visit_mod_from_ast(sub_mod), + Cow::Owned(sub_mod) => self.visit_mod_outside_ast(sub_mod), + } + } + /// Find a file path in the filesystem which corresponds to the given module. fn find_external_module( &self, mod_name: ast::Ident, attrs: &[ast::Attribute], - ) -> Result<(PathBuf, DirectoryOwnership), String> { + sub_mod: &Cow<'ast, ast::Mod>, + ) -> Result, String> { if let Some(path) = parser::Parser::submod_path_from_attr(attrs, &self.directory.path) { - return Ok((path, DirectoryOwnership::Owned { relative: None })); + return Ok(SubModKind::External( + path, + DirectoryOwnership::Owned { relative: None }, + )); + } + + // Look for nested path, like `#[cfg_attr(feature = "foo", path = "bar.rs")]`. + match self.find_mods_ouside_of_ast(attrs, sub_mod) { + Some(mods) => { + if !mods.is_empty() { + return Ok(SubModKind::MultiExternal(mods)); + } + } + _ => (), } let relative = match self.directory.ownership { @@ -227,7 +292,7 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> { path, directory_ownership, .. - }) => Ok((path, directory_ownership)), + }) => Ok(SubModKind::External(path, directory_ownership)), Err(_) => Err(format!( "Failed to find module {} in {:?} {:?}", mod_name, self.directory.path, relative, @@ -255,6 +320,90 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> { self.directory.path.push(&id.as_str()); } } + + fn find_mods_ouside_of_ast( + &self, + attrs: &[ast::Attribute], + sub_mod: &Cow<'ast, ast::Mod>, + ) -> Option)>> { + use std::panic::{catch_unwind, AssertUnwindSafe}; + Some( + catch_unwind(AssertUnwindSafe(|| { + self.find_mods_ouside_of_ast_inner(attrs, sub_mod) + })) + .ok()?, + ) + } + + fn find_mods_ouside_of_ast_inner( + &self, + attrs: &[ast::Attribute], + sub_mod: &Cow<'ast, ast::Mod>, + ) -> Vec<(PathBuf, DirectoryOwnership, Cow<'ast, ast::Mod>)> { + // Filter nested path, like `#[cfg_attr(feature = "foo", path = "bar.rs")]`. + let mut path_visitor = visitor::PathVisitor::default(); + for attr in attrs.iter() { + if let Some(meta) = attr.meta() { + path_visitor.visit_meta_item(&meta) + } + } + let mut result = vec![]; + for path in path_visitor.paths() { + let mut actual_path = self.directory.path.clone(); + actual_path.push(&path); + let file_name = syntax_pos::FileName::Real(actual_path.clone()); + if self + .parse_sess + .source_map() + .get_source_file(&file_name) + .is_some() + { + // If the specfied file is already parsed, then we just use that. + println!("{:?} already parsed", actual_path); + result.push(( + actual_path, + DirectoryOwnership::Owned { relative: None }, + sub_mod.clone(), + )); + continue; + } + println!("Trying to parse {:?}", actual_path); + let mut parser = new_sub_parser_from_file( + self.parse_sess, + &actual_path, + self.directory.ownership, + None, + DUMMY_SP, + ); + println!("Created a parser"); + parser.cfg_mods = false; + let lo = parser.span; + let mod_attrs = match parse_inner_attributes(&mut parser) { + Ok(attrs) => attrs, + Err(mut e) => { + e.cancel(); + parser.sess.span_diagnostic.reset_err_count(); + continue; + } + }; + println!("Parsed mod_attrs: {:?}", mod_attrs); + let m = match parse_mod_items(&mut parser, lo) { + Ok(m) => m, + Err(mut e) => { + e.cancel(); + parser.sess.span_diagnostic.reset_err_count(); + continue; + } + }; + println!("path: {:?}, m: {:?}", path, m.inner); + result.push(( + actual_path, + DirectoryOwnership::Owned { relative: None }, + Cow::Owned(m), + )) + } + result + } } fn path_value(attr: &ast::Attribute) -> Option { @@ -271,3 +420,62 @@ fn path_value(attr: &ast::Attribute) -> Option { fn find_path_value(attrs: &[ast::Attribute]) -> Option { attrs.iter().flat_map(path_value).next() } + +// FIXME(topecongiro) Use the method from libsyntax[1] once it become public. +// +// [1] https://github.com/rust-lang/rust/blob/master/src/libsyntax/parse/attr.rs +fn parse_inner_attributes<'a>(parser: &mut parser::Parser<'a>) -> PResult<'a, Vec> { + let mut attrs: Vec = vec![]; + loop { + match parser.token { + token::Pound => { + // Don't even try to parse if it's not an inner attribute. + if !parser.look_ahead(1, |t| t == &token::Not) { + break; + } + + let attr = parser.parse_attribute(true)?; + assert_eq!(attr.style, ast::AttrStyle::Inner); + attrs.push(attr); + } + token::DocComment(s) => { + // we need to get the position of this token before we bump. + let attr = attr::mk_sugared_doc_attr(attr::mk_attr_id(), s, parser.span); + if attr.style == ast::AttrStyle::Inner { + attrs.push(attr); + parser.bump(); + } else { + break; + } + } + _ => break, + } + } + Ok(attrs) +} + +fn parse_mod_items<'a>(parser: &mut parser::Parser<'a>, inner_lo: Span) -> PResult<'a, ast::Mod> { + let mut items = vec![]; + while let Some(item) = parser.parse_item()? { + items.push(item); + } + + let hi = if parser.span.is_dummy() { + inner_lo + } else { + parser.prev_span + }; + + Ok(ast::Mod { + inner: inner_lo.to(hi), + items, + inline: false, + }) +} + +fn is_cfg_if(item: &ast::Item) -> bool { + match item.node { + ast::ItemKind::Mac(..) if item.ident.name == Symbol::intern("cfg_if") => true, + _ => false, + } +} diff --git a/src/modules/visitor.rs b/src/modules/visitor.rs index 1086a1a026c..60ceec6efcd 100644 --- a/src/modules/visitor.rs +++ b/src/modules/visitor.rs @@ -5,6 +5,8 @@ use syntax::symbol::kw; use syntax::visit::Visitor; use syntax_pos::Symbol; +use crate::attr::MetaVisitor; + pub(crate) struct ModItem { pub(crate) item: ast::Item, } @@ -103,3 +105,44 @@ impl<'a, 'ast: 'a> CfgIfVisitor<'a> { Ok(()) } } + +/// Extracts `path = "foo.rs"` from attributes. +#[derive(Default)] +pub(crate) struct PathVisitor { + /// A list of path defined in attributes. + paths: Vec, +} + +impl PathVisitor { + pub(crate) fn paths(self) -> Vec { + self.paths + } +} + +impl<'ast> MetaVisitor<'ast> for PathVisitor { + fn visit_meta_name_value(&mut self, meta_item: &'ast ast::MetaItem, lit: &'ast ast::Lit) { + if meta_item.check_name(Symbol::intern("path")) && lit.node.is_str() { + self.paths.push(lit_to_str(lit)); + } + } +} + +#[cfg(not(windows))] +fn lit_to_str(lit: &ast::Lit) -> String { + match lit.node { + ast::LitKind::Str(symbol, ..) => symbol.to_string(), + _ => unreachable!(), + } +} + +#[cfg(windows)] +fn lit_to_str(lit: &ast::Lit) -> String { + match lit.node { + ast::LitKind::Str(symbol, ..) => { + let mut s = symbol.as_str(); + s.replace("/", "\\"); + s.to_owned() + } + _ => unreachable!(), + } +} From 9319da7248d701b7ebd888fc72b9bef82ea01e82 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Fri, 7 Jun 2019 00:38:36 +0900 Subject: [PATCH 2/7] Sayonara println --- src/modules.rs | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/modules.rs b/src/modules.rs index a0e9df9d7bf..540fe69dfb7 100644 --- a/src/modules.rs +++ b/src/modules.rs @@ -359,7 +359,6 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> { .is_some() { // If the specfied file is already parsed, then we just use that. - println!("{:?} already parsed", actual_path); result.push(( actual_path, DirectoryOwnership::Owned { relative: None }, @@ -367,7 +366,6 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> { )); continue; } - println!("Trying to parse {:?}", actual_path); let mut parser = new_sub_parser_from_file( self.parse_sess, &actual_path, @@ -375,7 +373,6 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> { None, DUMMY_SP, ); - println!("Created a parser"); parser.cfg_mods = false; let lo = parser.span; let mod_attrs = match parse_inner_attributes(&mut parser) { @@ -386,7 +383,6 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> { continue; } }; - println!("Parsed mod_attrs: {:?}", mod_attrs); let m = match parse_mod_items(&mut parser, lo) { Ok(m) => m, Err(mut e) => { @@ -395,7 +391,6 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> { continue; } }; - println!("path: {:?}, m: {:?}", path, m.inner); result.push(( actual_path, DirectoryOwnership::Owned { relative: None }, From 3c5c3d440764db2a5fcd56f8a64457f3f6f5da43 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Fri, 7 Jun 2019 11:36:17 +0900 Subject: [PATCH 3/7] Handle mod declaration with a partial cfg --- src/modules.rs | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/src/modules.rs b/src/modules.rs index 540fe69dfb7..107a2a49aa5 100644 --- a/src/modules.rs +++ b/src/modules.rs @@ -267,14 +267,9 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> { } // Look for nested path, like `#[cfg_attr(feature = "foo", path = "bar.rs")]`. - match self.find_mods_ouside_of_ast(attrs, sub_mod) { - Some(mods) => { - if !mods.is_empty() { - return Ok(SubModKind::MultiExternal(mods)); - } - } - _ => (), - } + let mut mods_outside_ast = self + .find_mods_ouside_of_ast(attrs, sub_mod) + .unwrap_or(vec![]); let relative = match self.directory.ownership { DirectoryOwnership::Owned { relative } => relative, @@ -292,7 +287,15 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> { path, directory_ownership, .. - }) => Ok(SubModKind::External(path, directory_ownership)), + }) => Ok(if mods_outside_ast.is_empty() { + SubModKind::External(path, directory_ownership) + } else { + mods_outside_ast.push((path, directory_ownership, sub_mod.clone())); + SubModKind::MultiExternal(mods_outside_ast) + }), + Err(_) if !mods_outside_ast.is_empty() => { + Ok(SubModKind::MultiExternal(mods_outside_ast)) + } Err(_) => Err(format!( "Failed to find module {} in {:?} {:?}", mod_name, self.directory.path, relative, @@ -375,7 +378,8 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> { ); parser.cfg_mods = false; let lo = parser.span; - let mod_attrs = match parse_inner_attributes(&mut parser) { + // FIXME(topecongiro) Format inner attributes (#3606). + let _mod_attrs = match parse_inner_attributes(&mut parser) { Ok(attrs) => attrs, Err(mut e) => { e.cancel(); From aae5f00a258ee518f7e0fdccb3d23eb2be7901a1 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Fri, 7 Jun 2019 12:09:09 +0900 Subject: [PATCH 4/7] Ignore path attributes that point to invalid path --- src/modules.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/modules.rs b/src/modules.rs index 107a2a49aa5..18b91add17b 100644 --- a/src/modules.rs +++ b/src/modules.rs @@ -354,6 +354,9 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> { for path in path_visitor.paths() { let mut actual_path = self.directory.path.clone(); actual_path.push(&path); + if !actual_path.exists() { + continue; + } let file_name = syntax_pos::FileName::Real(actual_path.clone()); if self .parse_sess From 2c9187755116e6fd98758cc37d77f6e878b82492 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Sat, 8 Jun 2019 18:28:32 +0900 Subject: [PATCH 5/7] Fix test on Windows --- src/modules/visitor.rs | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/modules/visitor.rs b/src/modules/visitor.rs index 60ceec6efcd..77bbb1535fe 100644 --- a/src/modules/visitor.rs +++ b/src/modules/visitor.rs @@ -138,11 +138,7 @@ fn lit_to_str(lit: &ast::Lit) -> String { #[cfg(windows)] fn lit_to_str(lit: &ast::Lit) -> String { match lit.node { - ast::LitKind::Str(symbol, ..) => { - let mut s = symbol.as_str(); - s.replace("/", "\\"); - s.to_owned() - } + ast::LitKind::Str(symbol, ..) => symtol.as_str().replace("/", "\\"), _ => unreachable!(), } } From 949bbfdbddb38c38f61b348b46eeace34a2ae535 Mon Sep 17 00:00:00 2001 From: topecongiro Date: Sat, 8 Jun 2019 18:38:23 +0900 Subject: [PATCH 6/7] Add tests --- src/test/mod.rs | 5 +++++ tests/source/cfg_mod/bar.rs | 3 +++ tests/source/cfg_mod/dir/dir1/dir2/wasm32.rs | 6 ++++++ tests/source/cfg_mod/dir/dir1/dir3/wasm32.rs | 6 ++++++ tests/source/cfg_mod/foo.rs | 4 ++++ tests/source/cfg_mod/mod.rs | 10 ++++++++++ tests/source/cfg_mod/other.rs | 1 + tests/source/cfg_mod/wasm32.rs | 4 ++++ tests/target/cfg_mod/bar.rs | 3 +++ tests/target/cfg_mod/dir/dir1/dir2/wasm32.rs | 3 +++ tests/target/cfg_mod/dir/dir1/dir3/wasm32.rs | 3 +++ tests/target/cfg_mod/foo.rs | 3 +++ tests/target/cfg_mod/mod.rs | 10 ++++++++++ tests/target/cfg_mod/other.rs | 3 +++ tests/target/cfg_mod/wasm32.rs | 3 +++ 15 files changed, 67 insertions(+) create mode 100644 tests/source/cfg_mod/bar.rs create mode 100644 tests/source/cfg_mod/dir/dir1/dir2/wasm32.rs create mode 100644 tests/source/cfg_mod/dir/dir1/dir3/wasm32.rs create mode 100644 tests/source/cfg_mod/foo.rs create mode 100644 tests/source/cfg_mod/mod.rs create mode 100644 tests/source/cfg_mod/other.rs create mode 100644 tests/source/cfg_mod/wasm32.rs create mode 100644 tests/target/cfg_mod/bar.rs create mode 100644 tests/target/cfg_mod/dir/dir1/dir2/wasm32.rs create mode 100644 tests/target/cfg_mod/dir/dir1/dir3/wasm32.rs create mode 100644 tests/target/cfg_mod/foo.rs create mode 100644 tests/target/cfg_mod/mod.rs create mode 100644 tests/target/cfg_mod/other.rs create mode 100644 tests/target/cfg_mod/wasm32.rs diff --git a/src/test/mod.rs b/src/test/mod.rs index c68b33b844f..96f6f2ce9ba 100644 --- a/src/test/mod.rs +++ b/src/test/mod.rs @@ -28,6 +28,11 @@ const SKIP_FILE_WHITE_LIST: &[&str] = &[ // These files and directory are a part of modules defined inside `cfg_if!`. "cfg_if/mod.rs", "cfg_if/detect", + // These files and directory are a part of modules defined inside `cfg_attr(..)`. + "cfg_mod/dir", + "cfg_mod/bar.rs", + "cfg_mod/foo.rs", + "cfg_mod/wasm32.rs", ]; struct TestSetting { diff --git a/tests/source/cfg_mod/bar.rs b/tests/source/cfg_mod/bar.rs new file mode 100644 index 00000000000..5b6b5f43837 --- /dev/null +++ b/tests/source/cfg_mod/bar.rs @@ -0,0 +1,3 @@ +fn bar( ) -> &str { +"bar" +} diff --git a/tests/source/cfg_mod/dir/dir1/dir2/wasm32.rs b/tests/source/cfg_mod/dir/dir1/dir2/wasm32.rs new file mode 100644 index 00000000000..0f8c0a3a7ac --- /dev/null +++ b/tests/source/cfg_mod/dir/dir1/dir2/wasm32.rs @@ -0,0 +1,6 @@ +fn + wasm32 + () -> &str +{ + "wasm32" +} diff --git a/tests/source/cfg_mod/dir/dir1/dir3/wasm32.rs b/tests/source/cfg_mod/dir/dir1/dir3/wasm32.rs new file mode 100644 index 00000000000..0f8c0a3a7ac --- /dev/null +++ b/tests/source/cfg_mod/dir/dir1/dir3/wasm32.rs @@ -0,0 +1,6 @@ +fn + wasm32 + () -> &str +{ + "wasm32" +} diff --git a/tests/source/cfg_mod/foo.rs b/tests/source/cfg_mod/foo.rs new file mode 100644 index 00000000000..de4ce55ef6f --- /dev/null +++ b/tests/source/cfg_mod/foo.rs @@ -0,0 +1,4 @@ +fn foo( ) + -> &str { + "foo" +} diff --git a/tests/source/cfg_mod/mod.rs b/tests/source/cfg_mod/mod.rs new file mode 100644 index 00000000000..45ba86f11b3 --- /dev/null +++ b/tests/source/cfg_mod/mod.rs @@ -0,0 +1,10 @@ +#[cfg_attr(feature = "foo", path = "foo.rs")] +#[cfg_attr(not(feture = "foo"), path = "bar.rs")] +mod sub_mod; + +#[cfg_attr(target_arch = "wasm32", path = "dir/dir1/dir2/wasm32.rs")] +#[cfg_attr(not(target_arch = "wasm32"), path = "dir/dir1/dir3/wasm32.rs")] +mod wasm32; + +#[some_attr(path = "somewhere.rs")] +mod other; diff --git a/tests/source/cfg_mod/other.rs b/tests/source/cfg_mod/other.rs new file mode 100644 index 00000000000..0b5c04d2192 --- /dev/null +++ b/tests/source/cfg_mod/other.rs @@ -0,0 +1 @@ +fn other() -> &str { "other"} diff --git a/tests/source/cfg_mod/wasm32.rs b/tests/source/cfg_mod/wasm32.rs new file mode 100644 index 00000000000..3741e53fd4e --- /dev/null +++ b/tests/source/cfg_mod/wasm32.rs @@ -0,0 +1,4 @@ +fn + wasm32() -> &str { + "wasm32" + } diff --git a/tests/target/cfg_mod/bar.rs b/tests/target/cfg_mod/bar.rs new file mode 100644 index 00000000000..20dc5b4a080 --- /dev/null +++ b/tests/target/cfg_mod/bar.rs @@ -0,0 +1,3 @@ +fn bar() -> &str { + "bar" +} diff --git a/tests/target/cfg_mod/dir/dir1/dir2/wasm32.rs b/tests/target/cfg_mod/dir/dir1/dir2/wasm32.rs new file mode 100644 index 00000000000..ac437e4225a --- /dev/null +++ b/tests/target/cfg_mod/dir/dir1/dir2/wasm32.rs @@ -0,0 +1,3 @@ +fn wasm32() -> &str { + "wasm32" +} diff --git a/tests/target/cfg_mod/dir/dir1/dir3/wasm32.rs b/tests/target/cfg_mod/dir/dir1/dir3/wasm32.rs new file mode 100644 index 00000000000..ac437e4225a --- /dev/null +++ b/tests/target/cfg_mod/dir/dir1/dir3/wasm32.rs @@ -0,0 +1,3 @@ +fn wasm32() -> &str { + "wasm32" +} diff --git a/tests/target/cfg_mod/foo.rs b/tests/target/cfg_mod/foo.rs new file mode 100644 index 00000000000..053c8e6f3ed --- /dev/null +++ b/tests/target/cfg_mod/foo.rs @@ -0,0 +1,3 @@ +fn foo() -> &str { + "foo" +} diff --git a/tests/target/cfg_mod/mod.rs b/tests/target/cfg_mod/mod.rs new file mode 100644 index 00000000000..45ba86f11b3 --- /dev/null +++ b/tests/target/cfg_mod/mod.rs @@ -0,0 +1,10 @@ +#[cfg_attr(feature = "foo", path = "foo.rs")] +#[cfg_attr(not(feture = "foo"), path = "bar.rs")] +mod sub_mod; + +#[cfg_attr(target_arch = "wasm32", path = "dir/dir1/dir2/wasm32.rs")] +#[cfg_attr(not(target_arch = "wasm32"), path = "dir/dir1/dir3/wasm32.rs")] +mod wasm32; + +#[some_attr(path = "somewhere.rs")] +mod other; diff --git a/tests/target/cfg_mod/other.rs b/tests/target/cfg_mod/other.rs new file mode 100644 index 00000000000..5929b8dcf53 --- /dev/null +++ b/tests/target/cfg_mod/other.rs @@ -0,0 +1,3 @@ +fn other() -> &str { + "other" +} diff --git a/tests/target/cfg_mod/wasm32.rs b/tests/target/cfg_mod/wasm32.rs new file mode 100644 index 00000000000..ac437e4225a --- /dev/null +++ b/tests/target/cfg_mod/wasm32.rs @@ -0,0 +1,3 @@ +fn wasm32() -> &str { + "wasm32" +} From 052a5775825bd30316d4e6d10770b5ac3052a23b Mon Sep 17 00:00:00 2001 From: topecongiro Date: Sat, 8 Jun 2019 20:42:55 +0900 Subject: [PATCH 7/7] Fix a typo --- src/modules/visitor.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/modules/visitor.rs b/src/modules/visitor.rs index 77bbb1535fe..4b4b2acd913 100644 --- a/src/modules/visitor.rs +++ b/src/modules/visitor.rs @@ -138,7 +138,7 @@ fn lit_to_str(lit: &ast::Lit) -> String { #[cfg(windows)] fn lit_to_str(lit: &ast::Lit) -> String { match lit.node { - ast::LitKind::Str(symbol, ..) => symtol.as_str().replace("/", "\\"), + ast::LitKind::Str(symbol, ..) => symbol.as_str().replace("/", "\\"), _ => unreachable!(), } }