Skip to content

Commit 0d4bd7e

Browse files
committed
test
1 parent 0c4e8dc commit 0d4bd7e

File tree

2 files changed

+302
-13
lines changed

2 files changed

+302
-13
lines changed

crates/webidl/src/lib.rs

Lines changed: 259 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -25,17 +25,18 @@ use crate::generator::{
2525
use crate::idl_type::ToIdlType;
2626
use crate::traverse::TraverseType;
2727
use crate::util::{
28-
camel_case_ident, getter_throws, is_rust_returned_dictionary, is_structural, is_type_unstable,
29-
optional_return_ty, read_dir, setter_throws, shouty_snake_case_ident, snake_case_ident, throws,
30-
webidl_const_v_to_backend_const_v, TypePosition,
28+
camel_case_ident, find_in_arguments, find_in_type, getter_throws, is_rust_returned_dictionary,
29+
is_structural, is_type_unstable, optional_return_ty, read_dir, setter_throws,
30+
shouty_snake_case_ident, snake_case_ident, throws, webidl_const_v_to_backend_const_v,
31+
TypePosition,
3132
};
3233
use anyhow::Context;
3334
use anyhow::Result;
3435
use idl_type::IdlType;
3536
use proc_macro2::{Ident, TokenStream};
3637
use quote::ToTokens;
3738
use sourcefile::SourceFile;
38-
use std::collections::{BTreeMap, BTreeSet, HashSet};
39+
use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet};
3940
use std::ffi::OsStr;
4041
use std::fs;
4142
use std::path::{Path, PathBuf};
@@ -46,7 +47,7 @@ use weedle::attribute::ExtendedAttributeList;
4647
use weedle::common::Identifier;
4748
use weedle::dictionary::DictionaryMember;
4849
use weedle::interface::InterfaceMember;
49-
use weedle::Parse;
50+
use weedle::{Definition, Parse};
5051

5152
/// Options to configure the conversion process
5253
#[derive(Debug)]
@@ -130,18 +131,17 @@ fn parse(
130131

131132
let unstable_definitions = parse_source(unstable_source)?;
132133

134+
test(&definitions, &unstable_definitions);
135+
133136
// Gather unstable type Identifiers so that stable APIs can be downgraded
134137
// to unstable if they accept one of these types
135138
let unstable_types: HashSet<Identifier> = unstable_definitions
136139
.iter()
137-
.flat_map(|definition| {
138-
use weedle::Definition::*;
139-
match definition {
140-
Dictionary(v) => Some(v.identifier),
141-
Enum(v) => Some(v.identifier),
142-
Interface(v) => Some(v.identifier),
143-
_ => None,
144-
}
140+
.flat_map(|definition| match definition {
141+
Definition::Dictionary(v) => Some(v.identifier),
142+
Definition::Enum(v) => Some(v.identifier),
143+
Definition::Interface(v) => Some(v.identifier),
144+
_ => None,
145145
})
146146
.collect();
147147

@@ -198,6 +198,252 @@ fn parse(
198198
Ok(types)
199199
}
200200

201+
fn test(definitions: &[Definition], unstable_definitions: &[Definition]) {
202+
use weedle::attribute::ExtendedAttribute;
203+
use weedle::interface::{
204+
AsyncIterableInterfaceMember, ConstructorInterfaceMember, DoubleTypedAsyncIterable,
205+
IterableInterfaceMember, OperationInterfaceMember, SingleTypedAsyncIterable,
206+
StringifierOrInheritOrStatic,
207+
};
208+
use weedle::mixin::MixinMember;
209+
use weedle::namespace::NamespaceMember;
210+
use weedle::types::ReturnType;
211+
use weedle::{
212+
InterfaceDefinition, InterfaceMixinDefinition, NamespaceDefinition,
213+
PartialInterfaceDefinition, PartialInterfaceMixinDefinition, PartialNamespaceDefinition,
214+
};
215+
216+
#[derive(Clone, Copy, Eq, Hash, PartialEq)]
217+
enum Type<'a> {
218+
Dictionary(Identifier<'a>),
219+
Typedef(Identifier<'a>),
220+
}
221+
222+
impl<'a> Type<'a> {
223+
fn identifier(self) -> Identifier<'a> {
224+
match self {
225+
Type::Dictionary(identifier) | Type::Typedef(identifier) => identifier,
226+
}
227+
}
228+
}
229+
230+
let mut types = HashMap::new();
231+
232+
for type_ in definitions
233+
.iter()
234+
.chain(unstable_definitions)
235+
.filter_map(|definition| match definition {
236+
Definition::Dictionary(dictionary) => Some(Type::Dictionary(dictionary.identifier)),
237+
Definition::Typedef(typedef) => Some(Type::Typedef(typedef.identifier)),
238+
_ => None,
239+
})
240+
{
241+
let mut list = Vec::new();
242+
243+
if !definitions
244+
.iter()
245+
.chain(unstable_definitions)
246+
.any(|definition| match definition {
247+
Definition::Callback(callback) => {
248+
if let ReturnType::Type(return_type) = &callback.return_type {
249+
find_in_type(return_type, type_.identifier())
250+
} else {
251+
false
252+
}
253+
}
254+
Definition::Interface(InterfaceDefinition {
255+
attributes,
256+
members,
257+
..
258+
})
259+
| Definition::PartialInterface(PartialInterfaceDefinition {
260+
attributes,
261+
members,
262+
..
263+
}) => {
264+
attributes
265+
.as_ref()
266+
.map(|attributes| {
267+
attributes
268+
.body
269+
.list
270+
.iter()
271+
.any(|attribute| match attribute {
272+
ExtendedAttribute::ArgList(list) => {
273+
find_in_arguments(&list.args, type_.identifier())
274+
}
275+
ExtendedAttribute::NamedArgList(list) => {
276+
find_in_arguments(&list.args, type_.identifier())
277+
}
278+
_ => false,
279+
})
280+
})
281+
.unwrap_or(false)
282+
|| members.body.iter().any(|member| match member {
283+
InterfaceMember::Attribute(attribute)
284+
if attribute.readonly.is_none()
285+
&& !matches!(
286+
attribute.modifier,
287+
Some(StringifierOrInheritOrStatic::Static(_))
288+
) =>
289+
{
290+
find_in_type(&attribute.type_.type_, type_.identifier())
291+
}
292+
InterfaceMember::Constructor(ConstructorInterfaceMember {
293+
args,
294+
..
295+
})
296+
| InterfaceMember::Operation(OperationInterfaceMember {
297+
args, ..
298+
}) => find_in_arguments(args, type_.identifier()),
299+
InterfaceMember::Iterable(iterable) => match iterable {
300+
IterableInterfaceMember::Single(iterable) => {
301+
find_in_type(&iterable.generics.body.type_, type_.identifier())
302+
}
303+
IterableInterfaceMember::Double(iterable) => {
304+
find_in_type(
305+
&iterable.generics.body.0.type_,
306+
type_.identifier(),
307+
) | find_in_type(
308+
&iterable.generics.body.2.type_,
309+
type_.identifier(),
310+
)
311+
}
312+
},
313+
InterfaceMember::AsyncIterable(iterable) => {
314+
(match iterable {
315+
AsyncIterableInterfaceMember::Single(iterable) => find_in_type(
316+
&iterable.generics.body.type_,
317+
type_.identifier(),
318+
),
319+
AsyncIterableInterfaceMember::Double(iterable) => {
320+
find_in_type(
321+
&iterable.generics.body.0.type_,
322+
type_.identifier(),
323+
) || find_in_type(
324+
&iterable.generics.body.2.type_,
325+
type_.identifier(),
326+
)
327+
}
328+
}) || match iterable {
329+
AsyncIterableInterfaceMember::Single(
330+
SingleTypedAsyncIterable {
331+
args: Some(args), ..
332+
},
333+
)
334+
| AsyncIterableInterfaceMember::Double(
335+
DoubleTypedAsyncIterable {
336+
args: Some(args), ..
337+
},
338+
) => find_in_arguments(args, type_.identifier()),
339+
_ => false,
340+
}
341+
}
342+
InterfaceMember::Maplike(map) if map.readonly.is_none() => {
343+
find_in_type(&map.generics.body.0.type_, type_.identifier())
344+
|| find_in_type(&map.generics.body.2.type_, type_.identifier())
345+
}
346+
InterfaceMember::Setlike(set) if set.readonly.is_none() => {
347+
find_in_type(&set.generics.body.type_, type_.identifier())
348+
}
349+
_ => false,
350+
})
351+
}
352+
Definition::InterfaceMixin(InterfaceMixinDefinition { members, .. })
353+
| Definition::PartialInterfaceMixin(PartialInterfaceMixinDefinition {
354+
members,
355+
..
356+
}) => members.body.iter().any(|member| match member {
357+
MixinMember::Operation(operation) => {
358+
find_in_arguments(&operation.args, type_.identifier())
359+
}
360+
MixinMember::Attribute(attribute) if attribute.readonly.is_none() => {
361+
find_in_type(&attribute.type_.type_, type_.identifier())
362+
}
363+
_ => false,
364+
}),
365+
Definition::Namespace(NamespaceDefinition { members, .. })
366+
| Definition::PartialNamespace(PartialNamespaceDefinition { members, .. }) => {
367+
members.body.iter().any(|member| {
368+
if let NamespaceMember::Operation(operation) = member {
369+
find_in_arguments(&operation.args, type_.identifier())
370+
} else {
371+
false
372+
}
373+
})
374+
}
375+
Definition::Dictionary(dictionary) => {
376+
if let Some(inheritance) = dictionary.inheritance {
377+
if inheritance.identifier == type_.identifier() {
378+
list.push(dictionary.identifier);
379+
}
380+
}
381+
382+
for member in &dictionary.members.body {
383+
if find_in_type(&member.type_, type_.identifier()) {
384+
list.push(dictionary.identifier);
385+
}
386+
}
387+
388+
false
389+
}
390+
Definition::PartialDictionary(dictionary) => {
391+
for member in &dictionary.members.body {
392+
if find_in_type(&member.type_, type_.identifier()) {
393+
list.push(dictionary.identifier);
394+
}
395+
}
396+
397+
false
398+
}
399+
Definition::Typedef(typedef) => {
400+
if find_in_type(&typedef.type_.type_, type_.identifier()) {
401+
list.push(typedef.identifier);
402+
}
403+
404+
false
405+
}
406+
_ => false,
407+
})
408+
{
409+
types.insert(type_, list);
410+
}
411+
}
412+
413+
let mut surviving_types: HashSet<_> = types.keys().map(|type_| type_.identifier()).collect();
414+
let mut size = types.len() + 1;
415+
416+
while size != types.len() {
417+
size = types.len();
418+
419+
types.retain(|type_, points| {
420+
for point in points {
421+
if !surviving_types.contains(point) {
422+
surviving_types.remove(&type_.identifier());
423+
return false;
424+
}
425+
}
426+
427+
true
428+
});
429+
}
430+
431+
let dictionaries: Vec<_> = types
432+
.into_iter()
433+
.filter_map(|(type_, _)| {
434+
if let Type::Dictionary(dictionary) = type_ {
435+
Some(dictionary)
436+
} else {
437+
None
438+
}
439+
})
440+
.collect();
441+
442+
for dictionary in dictionaries {
443+
println!("{}", dictionary.0);
444+
}
445+
}
446+
201447
/// Data for a single feature
202448
#[derive(Debug)]
203449
pub struct Feature {

crates/webidl/src/util.rs

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -792,3 +792,46 @@ pub fn nullable(mut ty: weedle::types::Type) -> weedle::types::Type {
792792

793793
ty
794794
}
795+
796+
pub fn find_in_arguments(
797+
in_: &weedle::common::Parenthesized<weedle::argument::ArgumentList>,
798+
to_find: Identifier,
799+
) -> bool {
800+
use weedle::argument::Argument;
801+
802+
in_.body.list.iter().any(|argument| match argument {
803+
Argument::Single(argument) => find_in_type(&argument.type_.type_, to_find),
804+
Argument::Variadic(argument) => find_in_type(&argument.type_, to_find),
805+
})
806+
}
807+
808+
pub fn find_in_type(in_: &weedle::types::Type, to_find: Identifier) -> bool {
809+
use weedle::types::{NonAnyType, ReturnType, SingleType, Type, UnionMemberType, UnionType};
810+
811+
fn internal(in_: &NonAnyType, to_find: Identifier) -> bool {
812+
match in_ {
813+
NonAnyType::Promise(promise) => match &*promise.generics.body {
814+
ReturnType::Undefined(_) => false,
815+
ReturnType::Type(type_) => find_in_type(type_, to_find),
816+
},
817+
NonAnyType::Sequence(sequence) => find_in_type(&sequence.type_.generics.body, to_find),
818+
NonAnyType::FrozenArrayType(array) => find_in_type(&array.type_.generics.body, to_find),
819+
NonAnyType::RecordType(record) => find_in_type(&record.type_.generics.body.2, to_find),
820+
NonAnyType::Identifier(identifier) => identifier.type_ == to_find,
821+
_ => false,
822+
}
823+
}
824+
825+
fn find_in_union(union: &UnionType, to_find: Identifier) -> bool {
826+
union.body.list.iter().any(|member| match member {
827+
UnionMemberType::Single(non_any) => internal(&non_any.type_, to_find),
828+
UnionMemberType::Union(union) => find_in_union(&union.type_, to_find),
829+
})
830+
}
831+
832+
match in_ {
833+
Type::Single(SingleType::NonAny(non_any)) => internal(non_any, to_find),
834+
Type::Union(union) => find_in_union(&union.type_, to_find),
835+
_ => false,
836+
}
837+
}

0 commit comments

Comments
 (0)