• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 use crate::gen::{CfgEvaluator, CfgResult};
2 use crate::syntax::cfg::CfgExpr;
3 use crate::syntax::report::Errors;
4 use crate::syntax::Api;
5 use quote::quote;
6 use std::collections::BTreeSet as Set;
7 use syn::Error;
8 
9 pub(super) struct UnsupportedCfgEvaluator;
10 
11 impl CfgEvaluator for UnsupportedCfgEvaluator {
eval(&self, name: &str, value: Option<&str>) -> CfgResult12     fn eval(&self, name: &str, value: Option<&str>) -> CfgResult {
13         let _ = name;
14         let _ = value;
15         let msg = "cfg attribute is not supported".to_owned();
16         CfgResult::Undetermined { msg }
17     }
18 }
19 
strip( cx: &mut Errors, cfg_errors: &mut Set<String>, cfg_evaluator: &dyn CfgEvaluator, apis: &mut Vec<Api>, )20 pub(super) fn strip(
21     cx: &mut Errors,
22     cfg_errors: &mut Set<String>,
23     cfg_evaluator: &dyn CfgEvaluator,
24     apis: &mut Vec<Api>,
25 ) {
26     apis.retain(|api| eval(cx, cfg_errors, cfg_evaluator, api.cfg()));
27     for api in apis {
28         match api {
29             Api::Struct(strct) => strct
30                 .fields
31                 .retain(|field| eval(cx, cfg_errors, cfg_evaluator, &field.cfg)),
32             Api::Enum(enm) => enm
33                 .variants
34                 .retain(|variant| eval(cx, cfg_errors, cfg_evaluator, &variant.cfg)),
35             _ => {}
36         }
37     }
38 }
39 
eval( cx: &mut Errors, cfg_errors: &mut Set<String>, cfg_evaluator: &dyn CfgEvaluator, expr: &CfgExpr, ) -> bool40 pub(super) fn eval(
41     cx: &mut Errors,
42     cfg_errors: &mut Set<String>,
43     cfg_evaluator: &dyn CfgEvaluator,
44     expr: &CfgExpr,
45 ) -> bool {
46     match try_eval(cfg_evaluator, expr) {
47         Ok(value) => value,
48         Err(errors) => {
49             for error in errors {
50                 if cfg_errors.insert(error.to_string()) {
51                     cx.push(error);
52                 }
53             }
54             false
55         }
56     }
57 }
58 
try_eval(cfg_evaluator: &dyn CfgEvaluator, expr: &CfgExpr) -> Result<bool, Vec<Error>>59 fn try_eval(cfg_evaluator: &dyn CfgEvaluator, expr: &CfgExpr) -> Result<bool, Vec<Error>> {
60     match expr {
61         CfgExpr::Unconditional => Ok(true),
62         CfgExpr::Eq(ident, string) => {
63             let key = ident.to_string();
64             let value = string.as_ref().map(|string| string.value());
65             match cfg_evaluator.eval(&key, value.as_deref()) {
66                 CfgResult::True => Ok(true),
67                 CfgResult::False => Ok(false),
68                 CfgResult::Undetermined { msg } => {
69                     let span = quote!(#ident #string);
70                     Err(vec![Error::new_spanned(span, msg)])
71                 }
72             }
73         }
74         CfgExpr::All(list) => {
75             let mut all_errors = Vec::new();
76             for subexpr in list {
77                 match try_eval(cfg_evaluator, subexpr) {
78                     Ok(true) => {}
79                     Ok(false) => return Ok(false),
80                     Err(errors) => all_errors.extend(errors),
81                 }
82             }
83             if all_errors.is_empty() {
84                 Ok(true)
85             } else {
86                 Err(all_errors)
87             }
88         }
89         CfgExpr::Any(list) => {
90             let mut all_errors = Vec::new();
91             for subexpr in list {
92                 match try_eval(cfg_evaluator, subexpr) {
93                     Ok(true) => return Ok(true),
94                     Ok(false) => {}
95                     Err(errors) => all_errors.extend(errors),
96                 }
97             }
98             if all_errors.is_empty() {
99                 Ok(false)
100             } else {
101                 Err(all_errors)
102             }
103         }
104         CfgExpr::Not(subexpr) => match try_eval(cfg_evaluator, subexpr) {
105             Ok(value) => Ok(!value),
106             Err(errors) => Err(errors),
107         },
108     }
109 }
110 
111 impl Api {
cfg(&self) -> &CfgExpr112     fn cfg(&self) -> &CfgExpr {
113         match self {
114             Api::Include(include) => &include.cfg,
115             Api::Struct(strct) => &strct.cfg,
116             Api::Enum(enm) => &enm.cfg,
117             Api::CxxType(ety) | Api::RustType(ety) => &ety.cfg,
118             Api::CxxFunction(efn) | Api::RustFunction(efn) => &efn.cfg,
119             Api::TypeAlias(alias) => &alias.cfg,
120             Api::Impl(imp) => &imp.cfg,
121         }
122     }
123 }
124 
125 impl From<bool> for CfgResult {
from(value: bool) -> Self126     fn from(value: bool) -> Self {
127         if value {
128             CfgResult::True
129         } else {
130             CfgResult::False
131         }
132     }
133 }
134