2 use rustc_ast::visit::Visitor;
3 use rustc_span::Symbol;
5 use crate::attr::MetaVisitor;
6 use crate::parse::macros::cfg_if::parse_cfg_if;
7 use crate::parse::session::ParseSess;
9 pub(crate) struct ModItem {
10 pub(crate) item: ast::Item,
13 /// Traverse `cfg_if!` macro and fetch modules.
14 pub(crate) struct CfgIfVisitor<'a> {
15 parse_sess: &'a ParseSess,
19 impl<'a> CfgIfVisitor<'a> {
20 pub(crate) fn new(parse_sess: &'a ParseSess) -> CfgIfVisitor<'a> {
27 pub(crate) fn mods(self) -> Vec<ModItem> {
32 impl<'a, 'ast: 'a> Visitor<'ast> for CfgIfVisitor<'a> {
33 fn visit_mac_call(&mut self, mac: &'ast ast::MacCall) {
34 match self.visit_mac_inner(mac) {
36 Err(e) => debug!("{}", e),
41 impl<'a, 'ast: 'a> CfgIfVisitor<'a> {
42 fn visit_mac_inner(&mut self, mac: &'ast ast::MacCall) -> Result<(), &'static str> {
45 // extern crate cfg_if;
46 // cfg_if::cfg_if! {..}
51 // extern crate cfg_if;
54 match mac.path.segments.first() {
55 Some(first_segment) => {
56 if first_segment.ident.name != Symbol::intern("cfg_if") {
57 return Err("Expected cfg_if");
61 return Err("Expected cfg_if");
65 let items = parse_cfg_if(self.parse_sess, mac)?;
67 .append(&mut items.into_iter().map(|item| ModItem { item }).collect());
73 /// Extracts `path = "foo.rs"` from attributes.
75 pub(crate) struct PathVisitor {
76 /// A list of path defined in attributes.
81 pub(crate) fn paths(self) -> Vec<String> {
86 impl<'ast> MetaVisitor<'ast> for PathVisitor {
87 fn visit_meta_name_value(
89 meta_item: &'ast ast::MetaItem,
90 lit: &'ast ast::MetaItemLit,
92 if meta_item.has_name(Symbol::intern("path")) && lit.kind.is_str() {
93 self.paths.push(meta_item_lit_to_str(lit));
99 fn meta_item_lit_to_str(lit: &ast::MetaItemLit) -> String {
101 ast::LitKind::Str(symbol, ..) => symbol.to_string(),
107 fn meta_item_lit_to_str(lit: &ast::MetaItemLit) -> String {
109 ast::LitKind::Str(symbol, ..) => symbol.as_str().replace("/", "\\"),