6
6
ClassDeclaration ,
7
7
createClassDeclaration ,
8
8
createIdentifier ,
9
+ createNamedImports ,
9
10
Decorator ,
10
11
Expression ,
11
12
Identifier ,
@@ -24,6 +25,8 @@ import {
24
25
TransformerFactory ,
25
26
updateCall ,
26
27
updateClassDeclaration ,
28
+ updateImportClause ,
29
+ updateImportDeclaration ,
27
30
updateSourceFile ,
28
31
visitEachChild ,
29
32
VisitResult
@@ -378,51 +381,87 @@ export class ${className}Module {}
378
381
}
379
382
380
383
export function purgeDeepLinkDecoratorTSTransform ( ) : TransformerFactory < SourceFile > {
381
- return ( transformContext : TransformationContext ) => {
384
+ return purgeDeepLinkDecoratorTSTransformImpl ;
385
+ }
382
386
383
- function visitClassDeclaration ( classDeclaration : ClassDeclaration ) {
384
- let hasDeepLinkDecorator = false ;
385
- const diffDecorators : Decorator [ ] = [ ] ;
386
- for ( const decorator of classDeclaration . decorators || [ ] ) {
387
- if ( decorator . expression && ( decorator . expression as CallExpression ) . expression
388
- && ( ( decorator . expression as CallExpression ) . expression as Identifier ) . escapedText === DEEPLINK_DECORATOR_TEXT ) {
389
- hasDeepLinkDecorator = true ;
390
- } else {
391
- diffDecorators . push ( decorator ) ;
392
- }
387
+ export function purgeDeepLinkDecoratorTSTransformImpl ( transformContext : TransformationContext ) {
388
+ function visitClassDeclaration ( classDeclaration : ClassDeclaration ) {
389
+ let hasDeepLinkDecorator = false ;
390
+ const diffDecorators : Decorator [ ] = [ ] ;
391
+ for ( const decorator of classDeclaration . decorators || [ ] ) {
392
+ if ( decorator . expression && ( decorator . expression as CallExpression ) . expression
393
+ && ( ( decorator . expression as CallExpression ) . expression as Identifier ) . escapedText === DEEPLINK_DECORATOR_TEXT ) {
394
+ hasDeepLinkDecorator = true ;
395
+ } else {
396
+ diffDecorators . push ( decorator ) ;
393
397
}
398
+ }
394
399
395
- if ( hasDeepLinkDecorator ) {
396
- return updateClassDeclaration (
397
- classDeclaration ,
398
- diffDecorators ,
399
- classDeclaration . modifiers ,
400
- classDeclaration . name ,
401
- classDeclaration . typeParameters ,
402
- classDeclaration . heritageClauses ,
403
- classDeclaration . members
404
- ) ;
405
- }
400
+ if ( hasDeepLinkDecorator ) {
401
+ return updateClassDeclaration (
402
+ classDeclaration ,
403
+ diffDecorators ,
404
+ classDeclaration . modifiers ,
405
+ classDeclaration . name ,
406
+ classDeclaration . typeParameters ,
407
+ classDeclaration . heritageClauses ,
408
+ classDeclaration . members
409
+ ) ;
406
410
407
- return classDeclaration ;
408
411
}
409
412
410
- function visit ( node : Node ) : VisitResult < Node > {
411
- switch ( node . kind ) {
413
+ return classDeclaration ;
414
+ }
412
415
413
- case SyntaxKind . ClassDeclaration :
414
- return visitClassDeclaration ( node as ClassDeclaration ) ;
416
+ function visitImportDeclaration ( importDeclaration : ImportDeclaration , sourceFile : SourceFile ) : ImportDeclaration {
415
417
416
- default :
417
- return visitEachChild ( node , ( node ) => {
418
- return visit ( node ) ;
419
- } , transformContext ) ;
420
- }
418
+ if ( importDeclaration . moduleSpecifier
419
+ && ( importDeclaration . moduleSpecifier as StringLiteral ) . text === 'ionic-angular'
420
+ && importDeclaration . importClause
421
+ && importDeclaration . importClause . namedBindings
422
+ && ( importDeclaration . importClause . namedBindings as NamedImports ) . elements
423
+ ) {
424
+ // loop over each import and store it
425
+ const importSpecifiers : ImportSpecifier [ ] = [ ] ;
426
+ ( importDeclaration . importClause . namedBindings as NamedImports ) . elements . forEach ( ( importSpecifier : ImportSpecifier ) => {
427
+
428
+ if ( importSpecifier . name . escapedText !== DEEPLINK_DECORATOR_TEXT ) {
429
+ importSpecifiers . push ( importSpecifier ) ;
430
+ }
431
+ } ) ;
432
+ const emptyNamedImports = createNamedImports ( importSpecifiers ) ;
433
+ const newImportClause = updateImportClause ( importDeclaration . importClause , importDeclaration . importClause . name , emptyNamedImports ) ;
434
+
435
+ return updateImportDeclaration (
436
+ importDeclaration ,
437
+ importDeclaration . decorators ,
438
+ importDeclaration . modifiers ,
439
+ newImportClause ,
440
+ importDeclaration . moduleSpecifier
441
+ ) ;
421
442
}
422
443
423
- return ( sourceFile : SourceFile ) => {
424
- return visit ( sourceFile ) as SourceFile ;
425
- } ;
444
+
445
+ return importDeclaration ;
446
+ }
447
+
448
+ function visit ( node : Node , sourceFile : SourceFile ) : VisitResult < Node > {
449
+ switch ( node . kind ) {
450
+
451
+ case SyntaxKind . ClassDeclaration :
452
+ return visitClassDeclaration ( node as ClassDeclaration ) ;
453
+
454
+ case SyntaxKind . ImportDeclaration :
455
+ return visitImportDeclaration ( node as ImportDeclaration , sourceFile ) ;
456
+ default :
457
+ return visitEachChild ( node , ( node ) => {
458
+ return visit ( node , sourceFile ) ;
459
+ } , transformContext ) ;
460
+ }
461
+ }
462
+
463
+ return ( sourceFile : SourceFile ) => {
464
+ return visit ( sourceFile , sourceFile ) as SourceFile ;
426
465
} ;
427
466
}
428
467
@@ -442,9 +481,53 @@ export function purgeDeepLinkDecorator(inputText: string): string {
442
481
toRemove . forEach ( node => {
443
482
toReturn = replaceNode ( '' , inputText , node , '' ) ;
444
483
} ) ;
484
+
485
+ toReturn = purgeDeepLinkImport ( toReturn ) ;
445
486
return toReturn ;
446
487
}
447
488
489
+ export function purgeDeepLinkImport ( inputText : string ) : string {
490
+ const sourceFile = getTypescriptSourceFile ( '' , inputText ) ;
491
+ const importDeclarations = findNodes ( sourceFile , sourceFile , SyntaxKind . ImportDeclaration ) as ImportDeclaration [ ] ;
492
+
493
+ importDeclarations . forEach ( importDeclaration => {
494
+ if ( importDeclaration . moduleSpecifier
495
+ && ( importDeclaration . moduleSpecifier as StringLiteral ) . text === 'ionic-angular'
496
+ && importDeclaration . importClause
497
+ && importDeclaration . importClause . namedBindings
498
+ && ( importDeclaration . importClause . namedBindings as NamedImports ) . elements
499
+ ) {
500
+ // loop over each import and store it
501
+ let decoratorIsImported = false ;
502
+ const namedImportStrings : string [ ] = [ ] ;
503
+ ( importDeclaration . importClause . namedBindings as NamedImports ) . elements . forEach ( ( importSpecifier : ImportSpecifier ) => {
504
+
505
+ if ( importSpecifier . name . escapedText === DEEPLINK_DECORATOR_TEXT ) {
506
+ decoratorIsImported = true ;
507
+ } else {
508
+ namedImportStrings . push ( importSpecifier . name . escapedText as string ) ;
509
+ }
510
+ } ) ;
511
+
512
+ // okay, cool. If namedImportStrings is empty, then just remove the entire import statement
513
+ // otherwise, just replace the named imports with the namedImportStrings separated by a comma
514
+ if ( decoratorIsImported ) {
515
+ if ( namedImportStrings . length ) {
516
+ // okay cool, we only want to remove some of these homies
517
+ const stringRepresentation = namedImportStrings . join ( ', ' ) ;
518
+ const namedImportString = `{ ${ stringRepresentation } }` ;
519
+ inputText = replaceNode ( '' , inputText , importDeclaration . importClause . namedBindings , namedImportString ) ;
520
+ } else {
521
+ // remove the entire import statement
522
+ inputText = replaceNode ( '' , inputText , importDeclaration , '' ) ;
523
+ }
524
+ }
525
+ }
526
+ } ) ;
527
+
528
+ return inputText ;
529
+ }
530
+
448
531
export function getInjectDeepLinkConfigTypescriptTransform ( ) {
449
532
const deepLinkString = convertDeepLinkConfigEntriesToString ( getParsedDeepLinkConfig ( ) ) ;
450
533
const appNgModulePath = getStringPropertyValue ( Constants . ENV_APP_NG_MODULE_PATH ) ;
0 commit comments