aboutsummaryrefslogtreecommitdiff
path: root/gen/src/cfg.rs
diff options
context:
space:
mode:
Diffstat (limited to 'gen/src/cfg.rs')
-rw-r--r--gen/src/cfg.rs68
1 files changed, 68 insertions, 0 deletions
diff --git a/gen/src/cfg.rs b/gen/src/cfg.rs
index 2595e310..bd62a930 100644
--- a/gen/src/cfg.rs
+++ b/gen/src/cfg.rs
@@ -1,4 +1,9 @@
use crate::gen::{CfgEvaluator, CfgResult};
+use crate::syntax::cfg::CfgExpr;
+use crate::syntax::report::Errors;
+use crate::syntax::Api;
+use quote::quote;
+use std::collections::BTreeSet as Set;
pub(super) struct UnsupportedCfgEvaluator;
@@ -10,3 +15,66 @@ impl CfgEvaluator for UnsupportedCfgEvaluator {
CfgResult::Undetermined { msg }
}
}
+
+pub(super) fn strip(cx: &mut Errors, cfg_evaluator: &dyn CfgEvaluator, apis: &mut Vec<Api>) {
+ let mut already_errors = Set::new();
+ apis.retain(|api| eval(cx, &mut already_errors, cfg_evaluator, api.cfg()));
+ for api in apis {
+ match api {
+ Api::Struct(strct) => strct
+ .fields
+ .retain(|field| eval(cx, &mut already_errors, cfg_evaluator, &field.cfg)),
+ Api::Enum(enm) => enm
+ .variants
+ .retain(|variant| eval(cx, &mut already_errors, cfg_evaluator, &variant.cfg)),
+ _ => {}
+ }
+ }
+}
+
+fn eval(
+ cx: &mut Errors,
+ already_errors: &mut Set<String>,
+ cfg_evaluator: &dyn CfgEvaluator,
+ expr: &CfgExpr,
+) -> bool {
+ match expr {
+ CfgExpr::Unconditional => true,
+ CfgExpr::Eq(ident, string) => {
+ let key = ident.to_string();
+ let value = string.as_ref().map(|string| string.value());
+ match cfg_evaluator.eval(&key, value.as_deref()) {
+ CfgResult::True => true,
+ CfgResult::False => false,
+ CfgResult::Undetermined { msg } => {
+ if already_errors.insert(msg.clone()) {
+ let span = quote!(#ident #string);
+ cx.error(span, msg);
+ }
+ false
+ }
+ }
+ }
+ CfgExpr::All(list) => list
+ .iter()
+ .all(|expr| eval(cx, already_errors, cfg_evaluator, expr)),
+ CfgExpr::Any(list) => list
+ .iter()
+ .any(|expr| eval(cx, already_errors, cfg_evaluator, expr)),
+ CfgExpr::Not(expr) => !eval(cx, already_errors, cfg_evaluator, expr),
+ }
+}
+
+impl Api {
+ fn cfg(&self) -> &CfgExpr {
+ match self {
+ Api::Include(include) => &include.cfg,
+ Api::Struct(strct) => &strct.cfg,
+ Api::Enum(enm) => &enm.cfg,
+ Api::CxxType(ety) | Api::RustType(ety) => &ety.cfg,
+ Api::CxxFunction(efn) | Api::RustFunction(efn) => &efn.cfg,
+ Api::TypeAlias(alias) => &alias.cfg,
+ Api::Impl(imp) => &imp.cfg,
+ }
+ }
+}