Merge pull request #803 from alexcrichton/fix-required

Change how filtering is done in WebIDL
This commit is contained in:
Alex Crichton 2018-09-10 11:59:36 -07:00 committed by GitHub
commit 2cf82bc0b3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 54 additions and 36 deletions

View File

@ -289,6 +289,9 @@ impl ImportedTypes for ast::ImportType {
F: FnMut(&Ident, ImportedTypeKind),
{
f(&self.rust_name, ImportedTypeKind::Definition);
for class in self.extends.iter() {
f(class, ImportedTypeKind::Reference);
}
}
}
@ -344,10 +347,27 @@ impl RemoveUndefinedImports for ast::Program {
where
F: Fn(&Ident) -> bool,
{
let a = self.imports.remove_undefined_imports(is_defined);
let b = self.consts.remove_undefined_imports(is_defined);
let c = self.dictionaries.remove_undefined_imports(is_defined);
a || b || c
let mut changed = self.imports.remove_undefined_imports(is_defined);
changed = self.consts.remove_undefined_imports(is_defined) || changed;
let mut dictionaries_to_remove = Vec::new();
for (i, dictionary) in self.dictionaries.iter_mut().enumerate() {
let num_required = |dict: &ast::Dictionary| {
dict.fields.iter().filter(|f| f.required).count()
};
let before = num_required(dictionary);
changed = dictionary.fields.remove_undefined_imports(is_defined) || changed;
if before != num_required(dictionary) {
warn!("removing {} due to a required field being removed",
dictionary.name);
dictionaries_to_remove.push(i);
}
}
for i in dictionaries_to_remove.iter().rev() {
self.dictionaries.swap_remove(*i);
}
changed || dictionaries_to_remove.len() > 0
}
}

View File

@ -29,7 +29,7 @@ mod idl_type;
mod util;
mod error;
use std::collections::{BTreeSet, HashSet, BTreeMap};
use std::collections::{BTreeSet, HashSet};
use std::env;
use std::fs;
use std::iter::FromIterator;
@ -80,49 +80,47 @@ fn parse(webidl_source: &str, allowed_types: Option<&[&str]>)
definitions.first_pass(&mut first_pass_record, ())?;
let mut program = Default::default();
// Prune out everything in the `first_pass_record` which isn't allowed, or
// is otherwise gated from not actually being generated.
if let Some(allowed_types) = allowed_types {
let allowed = allowed_types.iter().cloned().collect::<HashSet<_>>();
let filter = |name: &&str| {
allowed.contains(&camel_case_ident(name)[..])
};
retain(&mut first_pass_record.enums, &filter);
retain(&mut first_pass_record.dictionaries, &filter);
retain(&mut first_pass_record.interfaces, &filter);
let allowed_types = allowed_types.map(|list| {
list.iter().cloned().collect::<HashSet<_>>()
});
let filter = |name: &str| {
match &allowed_types {
Some(set) => set.contains(&camel_case_ident(name)[..]),
None => true,
}
};
for e in first_pass_record.enums.values() {
for (name, e) in first_pass_record.enums.iter() {
if filter(name) {
first_pass_record.append_enum(&mut program, e);
}
for d in first_pass_record.dictionaries.values() {
}
for (name, d) in first_pass_record.dictionaries.iter() {
if filter(name) {
first_pass_record.append_dictionary(&mut program, d);
}
}
for (name, n) in first_pass_record.namespaces.iter() {
first_pass_record.append_ns(&mut program, name, n);
}
for (name, d) in first_pass_record.interfaces.iter() {
if filter(name) {
first_pass_record.append_interface(&mut program, name, d);
}
}
// Prune out `extends` annotations that aren't defined as these shouldn't
// prevent the type from being usable entirely. They're just there for
// `AsRef` and such implementations.
for import in program.imports.iter_mut() {
if let backend::ast::ImportKind::Type(t) = &mut import.kind {
t.extends.retain(|n| filter(&n.to_string()));
}
}
Ok(program)
}
fn retain<K: Copy + Ord, V>(
map: &mut BTreeMap<K, V>,
mut filter: impl FnMut(&K) -> bool,
) {
let mut to_remove = Vec::new();
for k in map.keys() {
if !filter(k) {
to_remove.push(*k);
}
}
for k in to_remove {
map.remove(&k);
}
}
/// Compile the given WebIDL source text into Rust source text containing
/// `wasm-bindgen` bindings to the things described in the WebIDL.
pub fn compile(