use attr::AttrMetaMethods;
use diagnostic::SpanHandler;
+use feature_gate::GatedCfg;
use fold::Folder;
use {ast, fold, attr};
use codemap::{Spanned, respan};
// Support conditional compilation by transforming the AST, stripping out
// any items that do not belong in the current configuration
-pub fn strip_unconfigured_items(diagnostic: &SpanHandler, krate: ast::Crate) -> ast::Crate {
- let krate = process_cfg_attr(diagnostic, krate);
+pub fn strip_unconfigured_items(diagnostic: &SpanHandler, krate: ast::Crate,
+ feature_gated_cfgs: &mut Vec<GatedCfg>)
+ -> ast::Crate
+{
+ let krate = process_cfg_attr(diagnostic, krate, feature_gated_cfgs);
let config = krate.config.clone();
- strip_items(krate, |attrs| in_cfg(diagnostic, &config, attrs))
+ strip_items(krate, |attrs| in_cfg(diagnostic, &config, attrs, feature_gated_cfgs))
}
impl<F> fold::Folder for Context<F> where F: FnMut(&[ast::Attribute]) -> bool {
let item = match item {
ast::ItemImpl(u, o, a, b, c, impl_items) => {
let impl_items = impl_items.into_iter()
- .filter(|ii| impl_item_in_cfg(cx, ii))
+ .filter(|ii| (cx.in_cfg)(&ii.attrs))
.collect();
ast::ItemImpl(u, o, a, b, c, impl_items)
}
ast::ItemTrait(u, a, b, methods) => {
let methods = methods.into_iter()
- .filter(|m| trait_method_in_cfg(cx, m))
+ .filter(|ti| (cx.in_cfg)(&ti.attrs))
.collect();
ast::ItemTrait(u, a, b, methods)
}
if !(cx.in_cfg)(&v.node.attrs) {
None
} else {
- Some(v.map(|Spanned {node: ast::Variant_ {id, name, attrs, kind,
- disr_expr, vis}, span}| {
+ Some(v.map(|Spanned {node: ast::Variant_ {name, attrs, data,
+ disr_expr}, span}| {
Spanned {
node: ast::Variant_ {
- id: id,
name: name,
attrs: attrs,
- kind: match kind {
- ast::TupleVariantKind(..) => kind,
- ast::StructVariantKind(def) => {
- ast::StructVariantKind(fold_struct(cx, def))
- }
- },
+ data: fold_struct(cx, data),
disr_expr: disr_expr,
- vis: vis
},
span: span
}
fold::noop_fold_item_underscore(item, cx)
}
-fn fold_struct<F>(cx: &mut Context<F>, def: P<ast::StructDef>) -> P<ast::StructDef> where
+fn fold_struct<F>(cx: &mut Context<F>, def: P<ast::VariantData>) -> P<ast::VariantData> where
F: FnMut(&[ast::Attribute]) -> bool
{
- def.map(|ast::StructDef { fields, ctor_id }| {
- ast::StructDef {
- fields: fields.into_iter().filter(|m| {
- (cx.in_cfg)(&m.node.attrs)
- }).collect(),
- ctor_id: ctor_id,
+ def.map(|vdata| {
+ match vdata {
+ ast::VariantData::Struct(fields, id) => {
+ ast::VariantData::Struct(fields.into_iter().filter(|m| {
+ (cx.in_cfg)(&m.node.attrs)
+ }).collect(), id)
+ }
+ ast::VariantData::Tuple(fields, id) => {
+ ast::VariantData::Tuple(fields.into_iter().filter(|m| {
+ (cx.in_cfg)(&m.node.attrs)
+ }).collect(), id)
+ }
+ ast::VariantData::Unit(id) => ast::VariantData::Unit(id)
}
})
}
fold::noop_fold_expr(ast::Expr {
id: id,
node: match node {
- ast::ExprMatch(m, arms, source) => {
+ ast::ExprMatch(m, arms) => {
ast::ExprMatch(m, arms.into_iter()
.filter(|a| (cx.in_cfg)(&a.attrs))
- .collect(), source)
+ .collect())
}
_ => node
},
return (cx.in_cfg)(&item.attrs);
}
-fn trait_method_in_cfg<F>(cx: &mut Context<F>, meth: &ast::TraitItem) -> bool where
- F: FnMut(&[ast::Attribute]) -> bool
-{
- match *meth {
- ast::RequiredMethod(ref meth) => (cx.in_cfg)(&meth.attrs),
- ast::ProvidedMethod(ref meth) => (cx.in_cfg)(&meth.attrs),
- ast::TypeTraitItem(ref typ) => (cx.in_cfg)(&typ.attrs),
- }
-}
-
-fn impl_item_in_cfg<F>(cx: &mut Context<F>, impl_item: &ast::ImplItem) -> bool where
- F: FnMut(&[ast::Attribute]) -> bool
-{
- match *impl_item {
- ast::MethodImplItem(ref meth) => (cx.in_cfg)(&meth.attrs),
- ast::TypeImplItem(ref typ) => (cx.in_cfg)(&typ.attrs),
- }
-}
-
// Determine if an item should be translated in the current crate
// configuration based on the item's attributes
-fn in_cfg(diagnostic: &SpanHandler, cfg: &[P<ast::MetaItem>], attrs: &[ast::Attribute]) -> bool {
+fn in_cfg(diagnostic: &SpanHandler, cfg: &[P<ast::MetaItem>], attrs: &[ast::Attribute],
+ feature_gated_cfgs: &mut Vec<GatedCfg>) -> bool {
attrs.iter().all(|attr| {
let mis = match attr.node.value.node {
ast::MetaList(_, ref mis) if attr.check_name("cfg") => mis,
return true;
}
- attr::cfg_matches(diagnostic, cfg, &*mis[0])
+ attr::cfg_matches(diagnostic, cfg, &*mis[0],
+ feature_gated_cfgs)
})
}
-struct CfgAttrFolder<'a> {
+struct CfgAttrFolder<'a, 'b> {
diag: &'a SpanHandler,
config: ast::CrateConfig,
+ feature_gated_cfgs: &'b mut Vec<GatedCfg>
}
// Process `#[cfg_attr]`.
-fn process_cfg_attr(diagnostic: &SpanHandler, krate: ast::Crate) -> ast::Crate {
+fn process_cfg_attr(diagnostic: &SpanHandler, krate: ast::Crate,
+ feature_gated_cfgs: &mut Vec<GatedCfg>) -> ast::Crate {
let mut fld = CfgAttrFolder {
diag: diagnostic,
config: krate.config.clone(),
+ feature_gated_cfgs: feature_gated_cfgs,
};
fld.fold_crate(krate)
}
-impl<'a> fold::Folder for CfgAttrFolder<'a> {
+impl<'a,'b> fold::Folder for CfgAttrFolder<'a,'b> {
fn fold_attribute(&mut self, attr: ast::Attribute) -> Option<ast::Attribute> {
if !attr.check_name("cfg_attr") {
return fold::noop_fold_attribute(attr, self);
}
- let (cfg, mi) = match attr.meta_item_list() {
- Some([ref cfg, ref mi]) => (cfg, mi),
+ let attr_list = match attr.meta_item_list() {
+ Some(attr_list) => attr_list,
+ None => {
+ self.diag.span_err(attr.span, "expected `#[cfg_attr(<cfg pattern>, <attr>)]`");
+ return None;
+ }
+ };
+ let (cfg, mi) = match (attr_list.len(), attr_list.get(0), attr_list.get(1)) {
+ (2, Some(cfg), Some(mi)) => (cfg, mi),
_ => {
self.diag.span_err(attr.span, "expected `#[cfg_attr(<cfg pattern>, <attr>)]`");
return None;
}
};
- if attr::cfg_matches(self.diag, &self.config[..], &cfg) {
+ if attr::cfg_matches(self.diag, &self.config[..], &cfg,
+ self.feature_gated_cfgs) {
Some(respan(mi.span, ast::Attribute_ {
id: attr::mk_attr_id(),
style: attr.node.style,