@@ -21,6 +21,9 @@ export function* generateStatement(node: Parser.SyntaxNode): Generator<Code> {
21
21
yield * generateExpression ( node . namedChildren [ 0 ] ) ;
22
22
yield ";" ;
23
23
break ;
24
+ case "use_declaration" :
25
+ yield * generateUse ( node ) ;
26
+ break ;
24
27
default :
25
28
yield * generateExpression ( node ) ;
26
29
}
@@ -271,3 +274,193 @@ function* generateSelf(node: Parser.SyntaxNode): Generator<Code> {
271
274
`this` ,
272
275
) ;
273
276
}
277
+
278
+ function * generateUse ( node : Parser . SyntaxNode ) : Generator < Code > {
279
+ const reexportsNamed : Code [ ] = [ ] ;
280
+ const reexportsAll : string [ ] = [ ] ;
281
+ yield * generateUseItem ( node . childForFieldName ( "argument" ) ! ) ;
282
+ if ( node . namedChildren [ 0 ] ?. type === "visibility_modifier" ) {
283
+ if ( reexportsNamed . length ) {
284
+ yield "export {" ;
285
+ yield * reexportsNamed ;
286
+ yield "};\n" ;
287
+ }
288
+ if ( reexportsAll . length ) {
289
+ for ( const path of reexportsAll ) {
290
+ yield `export * from "` ;
291
+ yield path ;
292
+ yield `";\n` ;
293
+ }
294
+ }
295
+ }
296
+ else {
297
+ if ( reexportsAll . length ) {
298
+ throw new Error ( "Wildcard import is not supported" ) ;
299
+ }
300
+ }
301
+
302
+ function * generateUseItem ( node : Parser . SyntaxNode , base = "" , alias ?: Code ) : Generator < Code > {
303
+ switch ( node . type ) {
304
+ case "scoped_use_list" : {
305
+ const path = getPath ( node . namedChildren [ 0 ] ) ;
306
+ let wildcard : Code [ ] | undefined ;
307
+ const named : [ original : Code , alias ?: Code ] [ ] = [ ] ;
308
+ for ( const child of node . namedChildren [ 1 ] . namedChildren ) {
309
+ if ( child . type === "self" ) {
310
+ wildcard = [ ...wrapWith (
311
+ child . startIndex ,
312
+ child . endIndex ,
313
+ codeFeatures . verification ,
314
+ getSelfName ( node . namedChildren [ 0 ] ) ,
315
+ ) ] ;
316
+ }
317
+ else if ( child . type === "identifier" ) {
318
+ named . push ( [ [ child . text , child . startIndex ] ] ) ;
319
+ }
320
+ else if ( child . type === "use_as_clause" ) {
321
+ const original = child . namedChildren [ 0 ] ;
322
+ const alias = child . namedChildren [ 1 ] ;
323
+ if ( original . type === "self" ) {
324
+ wildcard = [ [ alias . text , alias . startIndex ] ] ;
325
+ }
326
+ else if ( original . type === "identifier" ) {
327
+ named . push ( [ [ original . text , original . startIndex ] , [ alias . text , alias . startIndex ] ] ) ;
328
+ }
329
+ else {
330
+ yield * generateUseItem ( original , path , [ alias . text , alias . startIndex ] ) ;
331
+ }
332
+ }
333
+ else {
334
+ yield * generateUseItem ( child , path ) ;
335
+ }
336
+ }
337
+ if ( wildcard ) {
338
+ reexportsNamed . push ( ...wildcard , ", " ) ;
339
+ yield `import * as ` ;
340
+ yield * wildcard ;
341
+ yield ` from ` ;
342
+ yield * generatePath ( node , path ) ;
343
+ yield `;\n` ;
344
+ }
345
+ if ( named . length > 0 ) {
346
+ yield "import { " ;
347
+ let isFirst = true ;
348
+ for ( const [ name , alias ] of named ) {
349
+ if ( ! isFirst )
350
+ yield `, ` ;
351
+ isFirst = false ;
352
+
353
+ reexportsNamed . push ( alias || name , ", " ) ;
354
+ yield name ;
355
+ if ( alias ) {
356
+ yield ` as ` ;
357
+ yield alias ;
358
+ }
359
+ }
360
+ yield ` } from ` ;
361
+ yield * generatePath ( node , path ) ;
362
+ yield `;\n` ;
363
+ }
364
+ break ;
365
+ }
366
+ case "scoped_identifier" : {
367
+ const path = getPath ( node . namedChildren [ 0 ] ) ;
368
+ const name = node . namedChildren [ 1 ] ;
369
+ if ( name . text === "self" ) {
370
+ const nameCode = alias
371
+ ? [ alias ]
372
+ : [ ...wrapWith (
373
+ name . startIndex ,
374
+ name . endIndex ,
375
+ codeFeatures . verification ,
376
+ getSelfName ( node . namedChildren [ 0 ] ) ,
377
+ ) ] ;
378
+ reexportsNamed . push ( ...nameCode , ", " ) ;
379
+ yield `import * as ` ;
380
+ yield * nameCode ;
381
+ yield ` from ` ;
382
+ yield * generatePath ( node , path ) ;
383
+ yield `;\n` ;
384
+ }
385
+ else {
386
+ reexportsNamed . push ( alias || [ name . text , name . startIndex ] , ", " ) ;
387
+ yield `import { ` ;
388
+ yield [ name . text , name . startIndex ] ;
389
+ if ( alias ) {
390
+ yield ` as ` ;
391
+ yield alias ;
392
+ }
393
+ yield ` } from ` ;
394
+ yield * generatePath ( node , path ) ;
395
+ yield `;\n` ;
396
+ }
397
+ break ;
398
+ }
399
+ case "identifier" : {
400
+ yield `import * as ` ;
401
+ yield [ node . text , node . startIndex ] ;
402
+ yield ` from ` ;
403
+ yield * generatePath ( node , node . text ) ;
404
+ yield `;\n` ;
405
+ break ;
406
+ }
407
+ case "use_as_clause" : {
408
+ const original = node . namedChildren [ 0 ] ;
409
+ yield * generateUseItem ( original , base , alias ) ;
410
+ break ;
411
+ }
412
+ case "use_wildcard" : {
413
+ const path = getPath ( node . namedChildren [ 0 ] ) ;
414
+ reexportsAll . push ( path ) ;
415
+ break ;
416
+ }
417
+ default :
418
+ throw new Error ( `Not implemented: ${ node . type } ` ) ;
419
+ }
420
+
421
+ function getPath ( path : Parser . SyntaxNode ) : string {
422
+ return base ? `${ base } /${ getPathImpl ( path ) } ` : getPathImpl ( path ) ;
423
+ }
424
+
425
+ function getPathImpl ( path : Parser . SyntaxNode ) : string {
426
+ if ( path . type === "identifier" ) {
427
+ return `${ path . text } ` ;
428
+ }
429
+ else if ( path . type === "scoped_identifier" ) {
430
+ return `${ getPathImpl ( path . namedChildren [ 0 ] ) } /${ path . namedChildren [ 1 ] . text } ` ;
431
+ }
432
+ else if ( path . type === "crate" ) {
433
+ return `@` ;
434
+ }
435
+ else {
436
+ throw new Error ( `Not implemented: ${ path . type } ` ) ;
437
+ }
438
+ }
439
+
440
+ function getSelfName ( path : Parser . SyntaxNode ) : string {
441
+ if ( path . type === "identifier" ) {
442
+ return path . text ;
443
+ }
444
+ else if ( path . type === "scoped_identifier" ) {
445
+ return getSelfName ( path . namedChildren [ 1 ] ) ;
446
+ }
447
+ else if ( path . type === "crate" ) {
448
+ return "crate" ;
449
+ }
450
+ else {
451
+ throw new Error ( `Not implemented: ${ path . type } ` ) ;
452
+ }
453
+ }
454
+ }
455
+
456
+ function generatePath ( node : Parser . SyntaxNode , path : string ) : Generator < Code > {
457
+ return wrapWith (
458
+ node . startIndex ,
459
+ node . endIndex ,
460
+ codeFeatures . verification ,
461
+ `"` ,
462
+ path ,
463
+ `"` ,
464
+ ) ;
465
+ }
466
+ }
0 commit comments