@@ -25,17 +25,18 @@ use crate::generator::{
25
25
use crate :: idl_type:: ToIdlType ;
26
26
use crate :: traverse:: TraverseType ;
27
27
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 ,
31
32
} ;
32
33
use anyhow:: Context ;
33
34
use anyhow:: Result ;
34
35
use idl_type:: IdlType ;
35
36
use proc_macro2:: { Ident , TokenStream } ;
36
37
use quote:: ToTokens ;
37
38
use sourcefile:: SourceFile ;
38
- use std:: collections:: { BTreeMap , BTreeSet , HashSet } ;
39
+ use std:: collections:: { BTreeMap , BTreeSet , HashMap , HashSet } ;
39
40
use std:: ffi:: OsStr ;
40
41
use std:: fs;
41
42
use std:: path:: { Path , PathBuf } ;
@@ -46,7 +47,7 @@ use weedle::attribute::ExtendedAttributeList;
46
47
use weedle:: common:: Identifier ;
47
48
use weedle:: dictionary:: DictionaryMember ;
48
49
use weedle:: interface:: InterfaceMember ;
49
- use weedle:: Parse ;
50
+ use weedle:: { Definition , Parse } ;
50
51
51
52
/// Options to configure the conversion process
52
53
#[ derive( Debug ) ]
@@ -130,18 +131,17 @@ fn parse(
130
131
131
132
let unstable_definitions = parse_source ( unstable_source) ?;
132
133
134
+ test ( & definitions, & unstable_definitions) ;
135
+
133
136
// Gather unstable type Identifiers so that stable APIs can be downgraded
134
137
// to unstable if they accept one of these types
135
138
let unstable_types: HashSet < Identifier > = unstable_definitions
136
139
. 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 ,
145
145
} )
146
146
. collect ( ) ;
147
147
@@ -198,6 +198,252 @@ fn parse(
198
198
Ok ( types)
199
199
}
200
200
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
+
201
447
/// Data for a single feature
202
448
#[ derive( Debug ) ]
203
449
pub struct Feature {
0 commit comments