Change how filtering is done in WebIDL

Instead of actually modifying the `FirstPassRecord` let's instead just skip
relevant entries when we come across them. This should help us retain knowledge
that `optional SomeImportedType arg` can be bound even though `SomeImportedType`
may not exist.

One small tweak was needed to modify the AST afterwards to remove `extends`
annotations which aren't actually defined, but other than that this should...

Closes #802
This commit is contained in:
Alex Crichton
2018-09-10 09:52:35 -07:00
parent be4ead7c8a
commit 116a19962f
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
}
}