1- import { dirname , join , relative } from 'path' ;
1+ import { basename , dirname , join , relative } from 'path' ;
22import { Logger } from '../logger/logger' ;
33import * as Constants from '../util/constants' ;
44import { changeExtension , escapeStringForRegex } from '../util/helpers' ;
@@ -11,17 +11,18 @@ export function calculateUnusedComponents(dependencyMap: Map<string, Set<string>
1111export function calculateUnusedComponentsImpl ( dependencyMap : Map < string , Set < string > > , importee : string ) : any {
1212 const filteredMap = filterMap ( dependencyMap ) ;
1313 processImportTree ( filteredMap , importee ) ;
14+ calculateUnusedIonicProviders ( filteredMap ) ;
1415 return generateResults ( filteredMap ) ;
1516}
1617
1718function generateResults ( dependencyMap : Map < string , Set < string > > ) {
1819 const toPurgeMap = new Map < string , Set < string > > ( ) ;
1920 const updatedMap = new Map < string , Set < string > > ( ) ;
2021 dependencyMap . forEach ( ( importeeSet : Set < string > , modulePath : string ) => {
21- if ( importeeSet . size > 0 ) {
22+ if ( ( importeeSet && importeeSet . size > 0 ) || requiredModule ( modulePath ) ) {
2223 updatedMap . set ( modulePath , importeeSet ) ;
2324 } else {
24- toPurgeMap . set ( modulePath , importeeSet ) ;
25+ toPurgeMap . set ( modulePath , importeeSet ) ;
2526 }
2627 } ) ;
2728 return {
@@ -30,10 +31,17 @@ function generateResults(dependencyMap: Map<string, Set<string>>) {
3031 } ;
3132}
3233
34+ function requiredModule ( modulePath : string ) {
35+ const mainJsFile = changeExtension ( process . env [ Constants . ENV_APP_ENTRY_POINT ] , '.js' ) ;
36+ const appModule = changeExtension ( process . env [ Constants . ENV_APP_NG_MODULE_PATH ] , '.js' ) ;
37+ const appModuleNgFactory = getAppModuleNgFactoryPath ( ) ;
38+ return modulePath === mainJsFile || modulePath === appModule || modulePath === appModuleNgFactory ;
39+ }
40+
3341function filterMap ( dependencyMap : Map < string , Set < string > > ) {
3442 const filteredMap = new Map < string , Set < string > > ( ) ;
3543 dependencyMap . forEach ( ( importeeSet : Set < string > , modulePath : string ) => {
36- if ( isIonicComponent ( modulePath ) ) {
44+ if ( isIonicComponentOrAppSource ( modulePath ) ) {
3745 filteredMap . set ( modulePath , importeeSet ) ;
3846 }
3947 } ) ;
@@ -43,7 +51,7 @@ function filterMap(dependencyMap: Map<string, Set<string>>) {
4351function processImportTree ( dependencyMap : Map < string , Set < string > > , importee : string ) {
4452 const importees : string [ ] = [ ] ;
4553 dependencyMap . forEach ( ( importeeSet : Set < string > , modulePath : string ) => {
46- if ( importeeSet . has ( importee ) ) {
54+ if ( importeeSet && importeeSet . has ( importee ) ) {
4755 importeeSet . delete ( importee ) ;
4856 // if it importer by an `ngfactory` file, we probably aren't going to be able to purge it
4957 let ngFactoryImportee = false ;
@@ -62,10 +70,88 @@ function processImportTree(dependencyMap: Map<string, Set<string>>, importee: st
6270 importees . forEach ( importee => processImportTree ( dependencyMap , importee ) ) ;
6371}
6472
65- export function isIonicComponent ( modulePath : string ) {
73+ function calculateUnusedIonicProviders ( dependencyMap : Map < string , Set < string > > ) {
74+ const ACTION_SHEET_CONTROLLER = join ( process . env [ Constants . ENV_VAR_IONIC_ANGULAR_DIR ] , 'components' , 'action-sheet' , 'action-sheet-controller.js' ) ;
75+ const ACTION_SHEET_COMPONENT_FACTORY = join ( process . env [ Constants . ENV_VAR_IONIC_ANGULAR_DIR ] , 'components' , 'action-sheet' , 'action-sheet-component.ngfactory.js' ) ;
76+
77+ const ALERT_CONTROLLER = join ( process . env [ Constants . ENV_VAR_IONIC_ANGULAR_DIR ] , 'components' , 'alert' , 'alert-controller.js' ) ;
78+ const ALERT_COMPONENT_FACTORY = join ( process . env [ Constants . ENV_VAR_IONIC_ANGULAR_DIR ] , 'components' , 'alert' , 'alert-component.ngfactory.js' ) ;
79+
80+ const LOADING_CONTROLLER = join ( process . env [ Constants . ENV_VAR_IONIC_ANGULAR_DIR ] , 'components' , 'loading' , 'loading-controller.js' ) ;
81+ const LOADING_COMPONENT_FACTORY = join ( process . env [ Constants . ENV_VAR_IONIC_ANGULAR_DIR ] , 'components' , 'loading' , 'loading-component.ngfactory.js' ) ;
82+
83+ const MODAL_CONTROLLER = join ( process . env [ Constants . ENV_VAR_IONIC_ANGULAR_DIR ] , 'components' , 'modal' , 'modal-controller.js' ) ;
84+ const MODAL_COMPONENT_FACTORY = join ( process . env [ Constants . ENV_VAR_IONIC_ANGULAR_DIR ] , 'components' , 'modal' , 'modal-component.ngfactory.js' ) ;
85+
86+ const PICKER_CONTROLLER = join ( process . env [ Constants . ENV_VAR_IONIC_ANGULAR_DIR ] , 'components' , 'picker' , 'picker-controller.js' ) ;
87+ const PICKER_COMPONENT_FACTORY = join ( process . env [ Constants . ENV_VAR_IONIC_ANGULAR_DIR ] , 'components' , 'picker' , 'picker-component.ngfactory.js' ) ;
88+
89+ const POPOVER_CONTROLLER = join ( process . env [ Constants . ENV_VAR_IONIC_ANGULAR_DIR ] , 'components' , 'popover' , 'popover-controller.js' ) ;
90+ const POPOVER_COMPONENT_FACTORY = join ( process . env [ Constants . ENV_VAR_IONIC_ANGULAR_DIR ] , 'components' , 'popover' , 'popover-component.ngfactory.js' ) ;
91+
92+ const TOAST_CONTROLLER = join ( process . env [ Constants . ENV_VAR_IONIC_ANGULAR_DIR ] , 'components' , 'toast' , 'toast-controller.js' ) ;
93+ const TOAST_COMPONENT_FACTORY = join ( process . env [ Constants . ENV_VAR_IONIC_ANGULAR_DIR ] , 'components' , 'toast' , 'toast-component.ngfactory.js' ) ;
94+
95+ processIonicProviders ( dependencyMap , ACTION_SHEET_CONTROLLER ) ;
96+ processIonicProviders ( dependencyMap , ALERT_CONTROLLER ) ;
97+ processIonicProviders ( dependencyMap , LOADING_CONTROLLER ) ;
98+ processIonicProviders ( dependencyMap , MODAL_CONTROLLER ) ;
99+ processIonicProviders ( dependencyMap , PICKER_CONTROLLER ) ;
100+ processIonicProviders ( dependencyMap , POPOVER_CONTROLLER ) ;
101+ processIonicProviders ( dependencyMap , TOAST_CONTROLLER ) ;
102+
103+ // check if the controllers were deleted, if so, purge the component too
104+ processIonicProviderComponents ( dependencyMap , ACTION_SHEET_CONTROLLER , ACTION_SHEET_COMPONENT_FACTORY ) ;
105+ processIonicProviderComponents ( dependencyMap , ALERT_CONTROLLER , ALERT_COMPONENT_FACTORY ) ;
106+ processIonicProviderComponents ( dependencyMap , LOADING_CONTROLLER , LOADING_COMPONENT_FACTORY ) ;
107+ processIonicProviderComponents ( dependencyMap , MODAL_CONTROLLER , MODAL_COMPONENT_FACTORY ) ;
108+ processIonicProviderComponents ( dependencyMap , PICKER_CONTROLLER , PICKER_COMPONENT_FACTORY ) ;
109+ processIonicProviderComponents ( dependencyMap , POPOVER_CONTROLLER , POPOVER_COMPONENT_FACTORY ) ;
110+ processIonicProviderComponents ( dependencyMap , TOAST_CONTROLLER , TOAST_COMPONENT_FACTORY ) ;
111+ }
112+
113+ function processIonicProviderComponents ( dependencyMap : Map < string , Set < string > > , providerPath : string , componentPath : string ) {
114+ const importeeSet = dependencyMap . get ( providerPath ) ;
115+ if ( importeeSet && importeeSet . size === 0 ) {
116+ processIonicProviders ( dependencyMap , componentPath ) ;
117+ }
118+ }
119+
120+ function getAppModuleNgFactoryPath ( ) {
121+ const appNgModulePath = process . env [ Constants . ENV_APP_NG_MODULE_PATH ] ;
122+ const directory = dirname ( appNgModulePath ) ;
123+ const extensionlessFileName = basename ( appNgModulePath , '.js' ) ;
124+ const ngFactoryFileName = extensionlessFileName + '.ngfactory.js' ;
125+ return join ( directory , ngFactoryFileName ) ;
126+ }
127+
128+ function processIonicProviders ( dependencyMap : Map < string , Set < string > > , providerPath : string ) {
129+ const importeeSet = dependencyMap . get ( providerPath ) ;
130+ const appModuleNgFactoryPath = getAppModuleNgFactoryPath ( ) ;
131+ // we can only purge an ionic provider if it is imported from one module, which is the AppModuleNgFactory
132+ if ( importeeSet && importeeSet . size === 1 && importeeSet . has ( appModuleNgFactoryPath ) ) {
133+ importeeSet . delete ( appModuleNgFactoryPath ) ;
134+ // loop over the dependency map and remove this provider from importee sets
135+ processImportTreeForProviders ( dependencyMap , providerPath ) ;
136+ }
137+ }
138+
139+ function processImportTreeForProviders ( dependencyMap : Map < string , Set < string > > , importee : string ) {
140+ const importees : string [ ] = [ ] ;
141+ dependencyMap . forEach ( ( importeeSet : Set < string > , modulePath : string ) => {
142+ if ( importeeSet . has ( importee ) ) {
143+ importeeSet . delete ( importee ) ;
144+ importees . push ( modulePath ) ;
145+ }
146+ } ) ;
147+ importees . forEach ( importee => processImportTreeForProviders ( dependencyMap , importee ) ) ;
148+ }
149+
150+ export function isIonicComponentOrAppSource ( modulePath : string ) {
66151 // for now, just use a simple filter of if a file is in ionic-angular/components
67152 const ionicAngularComponentDir = join ( process . env [ Constants . ENV_VAR_IONIC_ANGULAR_DIR ] , 'components' ) ;
68- return modulePath . indexOf ( ionicAngularComponentDir ) >= 0 ;
153+ const srcDir = process . env [ Constants . ENV_VAR_SRC_DIR ] ;
154+ return modulePath . indexOf ( ionicAngularComponentDir ) >= 0 || modulePath . indexOf ( srcDir ) >= 0 ;
69155}
70156
71157export function isNgFactory ( modulePath : string ) {
0 commit comments