Skip to content

Commit 2da6f06

Browse files
authored
Merge pull request #1472 from emilio/record-matches-flag
Allow to turn off the matches recording introduced in #1469.
2 parents d7dc508 + 3923851 commit 2da6f06

File tree

3 files changed

+76
-41
lines changed

3 files changed

+76
-41
lines changed

src/lib.rs

+37-14
Original file line numberDiff line numberDiff line change
@@ -509,6 +509,10 @@ impl Builder {
509509
);
510510
}
511511

512+
if !self.options.record_matches {
513+
output_vector.push("--no-record-matches".into());
514+
}
515+
512516
if !self.options.rustfmt_bindings {
513517
output_vector.push("--no-rustfmt-bindings".into());
514518
}
@@ -1137,6 +1141,12 @@ impl Builder {
11371141
self
11381142
}
11391143

1144+
/// Set whether we should record matched items in our regex sets.
1145+
pub fn record_matches(mut self, doit: bool) -> Self {
1146+
self.options.record_matches = doit;
1147+
self
1148+
}
1149+
11401150
/// Set the absolute path to the rustfmt configuration file, if None, the standard rustfmt
11411151
/// options are used.
11421152
pub fn rustfmt_configuration_file(mut self, path: Option<PathBuf>) -> Self {
@@ -1486,6 +1496,12 @@ struct BindgenOptions {
14861496
/// Features to enable, derived from `rust_target`
14871497
rust_features: RustFeatures,
14881498

1499+
/// Whether we should record which items in the regex sets ever matched.
1500+
///
1501+
/// This may be a bit slower, but will enable reporting of unused whitelist
1502+
/// items via the `error!` log.
1503+
record_matches: bool,
1504+
14891505
/// Whether rustfmt should format the generated bindings.
14901506
rustfmt_bindings: bool,
14911507

@@ -1511,20 +1527,26 @@ impl ::std::panic::UnwindSafe for BindgenOptions {}
15111527

15121528
impl BindgenOptions {
15131529
fn build(&mut self) {
1514-
self.whitelisted_vars.build();
1515-
self.whitelisted_types.build();
1516-
self.whitelisted_functions.build();
1517-
self.blacklisted_types.build();
1518-
self.blacklisted_functions.build();
1519-
self.blacklisted_items.build();
1520-
self.opaque_types.build();
1521-
self.bitfield_enums.build();
1522-
self.constified_enums.build();
1523-
self.constified_enum_modules.build();
1524-
self.rustified_enums.build();
1525-
self.no_partialeq_types.build();
1526-
self.no_copy_types.build();
1527-
self.no_hash_types.build();
1530+
let mut regex_sets = [
1531+
&mut self.whitelisted_vars,
1532+
&mut self.whitelisted_types,
1533+
&mut self.whitelisted_functions,
1534+
&mut self.blacklisted_types,
1535+
&mut self.blacklisted_functions,
1536+
&mut self.blacklisted_items,
1537+
&mut self.opaque_types,
1538+
&mut self.bitfield_enums,
1539+
&mut self.constified_enums,
1540+
&mut self.constified_enum_modules,
1541+
&mut self.rustified_enums,
1542+
&mut self.no_partialeq_types,
1543+
&mut self.no_copy_types,
1544+
&mut self.no_hash_types,
1545+
];
1546+
let record_matches = self.record_matches;
1547+
for regex_set in &mut regex_sets {
1548+
regex_set.build(record_matches);
1549+
}
15281550
}
15291551

15301552
/// Update rust target version
@@ -1601,6 +1623,7 @@ impl Default for BindgenOptions {
16011623
enable_mangling: true,
16021624
prepend_enum_name: true,
16031625
time_phases: false,
1626+
record_matches: true,
16041627
rustfmt_bindings: true,
16051628
rustfmt_configuration_file: None,
16061629
no_partialeq_types: Default::default(),

src/options.rs

+8
Original file line numberDiff line numberDiff line change
@@ -277,6 +277,10 @@ where
277277
Useful when debugging bindgen, using C-Reduce, or when \
278278
filing issues. The resulting file will be named \
279279
something like `__bindgen.i` or `__bindgen.ii`."),
280+
Arg::with_name("no-record-matches")
281+
.long("no-record-matches")
282+
.help("Do not record matching items in the regex sets. \
283+
This disables reporting of unused items."),
280284
Arg::with_name("no-rustfmt-bindings")
281285
.long("no-rustfmt-bindings")
282286
.help("Do not format the generated bindings with rustfmt."),
@@ -591,6 +595,10 @@ where
591595
builder.dump_preprocessed_input()?;
592596
}
593597

598+
if matches.is_present("no-record-matches") {
599+
builder = builder.record_matches(false);
600+
}
601+
594602
let no_rustfmt_bindings = matches.is_present("no-rustfmt-bindings");
595603
if no_rustfmt_bindings {
596604
builder = builder.rustfmt_bindings(false);

src/regex_set.rs

+31-27
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,15 @@ use regex::RegexSet as RxSet;
44
use std::cell::Cell;
55

66
/// A dynamic set of regular expressions.
7-
#[derive(Debug)]
7+
#[derive(Debug, Default)]
88
pub struct RegexSet {
99
items: Vec<String>,
10+
/// Whether any of the items in the set was ever matched. The length of this
11+
/// vector is exactly the length of `items`.
1012
matched: Vec<Cell<bool>>,
1113
set: Option<RxSet>,
14+
/// Whether we should record matching items in the `matched` vector or not.
15+
record_matches: bool,
1216
}
1317

1418
impl RegexSet {
@@ -32,23 +36,25 @@ impl RegexSet {
3236
&self.items[..]
3337
}
3438

35-
/// Returns regexes in the set which didn't match any strings yet
36-
pub fn unmatched_items(&self) -> Vec<String> {
37-
let mut items = vec![];
38-
for (i, item) in self.items.iter().enumerate() {
39-
if !self.matched[i].get() {
40-
items.push(item.clone());
39+
/// Returns an iterator over regexes in the set which didn't match any
40+
/// strings yet.
41+
pub fn unmatched_items(&self) -> impl Iterator<Item = &String> {
42+
self.items.iter().enumerate().filter_map(move |(i, item)| {
43+
if !self.record_matches || self.matched[i].get() {
44+
return None;
4145
}
42-
}
43-
items
46+
47+
Some(item)
48+
})
4449
}
4550

4651
/// Construct a RegexSet from the set of entries we've accumulated.
4752
///
4853
/// Must be called before calling `matches()`, or it will always return
4954
/// false.
50-
pub fn build(&mut self) {
55+
pub fn build(&mut self, record_matches: bool) {
5156
let items = self.items.iter().map(|item| format!("^{}$", item));
57+
self.record_matches = record_matches;
5258
self.set = match RxSet::new(items) {
5359
Ok(x) => Some(x),
5460
Err(e) => {
@@ -64,25 +70,23 @@ impl RegexSet {
6470
S: AsRef<str>,
6571
{
6672
let s = string.as_ref();
67-
if let Some(set) = self.set.as_ref() {
68-
let matches = set.matches(s);
69-
if matches.matched_any() {
70-
for i in matches.iter() {
71-
self.matched[i].set(true);
72-
}
73-
return true;
74-
}
73+
let set = match self.set {
74+
Some(ref set) => set,
75+
None => return false,
76+
};
77+
78+
if !self.record_matches {
79+
return set.is_match(s);
7580
}
76-
false
77-
}
78-
}
7981

80-
impl Default for RegexSet {
81-
fn default() -> Self {
82-
RegexSet {
83-
items: vec![],
84-
matched: vec![],
85-
set: None,
82+
let matches = set.matches(s);
83+
if !matches.matched_any() {
84+
return false;
8685
}
86+
for i in matches.iter() {
87+
self.matched[i].set(true);
88+
}
89+
90+
true
8791
}
8892
}

0 commit comments

Comments
 (0)