@@ -114,33 +114,32 @@ export function migrateFileContent(content: string,
114
114
oldCdkPrefix : string ,
115
115
newMaterialImportPath : string ,
116
116
newCdkImportPath : string ) : string {
117
- // Drop the CDK imports and detect their namespaces.
118
- const cdkResults = detectAndDropImports ( content , oldCdkPrefix ) ;
119
- content = cdkResults . content ;
120
-
121
- // Drop the Material imports and detect their namespaces.
122
- const materialResults = detectAndDropImports ( content , oldMaterialPrefix ) ;
123
- content = materialResults . content ;
124
-
125
- // If nothing has changed, then the file doesn't import the Material theming API.
126
- if ( materialResults . hasChanged || cdkResults . hasChanged ) {
127
- // Replacing the imports may have resulted in leading whitespace.
128
- content = content . replace ( / ^ \s + / , '' ) ;
129
- content = migrateCdkSymbols ( content , newCdkImportPath , cdkResults . namespaces ) ;
117
+ const materialResults = detectImports ( content , oldMaterialPrefix ) ;
118
+ const cdkResults = detectImports ( content , oldCdkPrefix ) ;
119
+
120
+ // If there are no imports, we don't need to go further.
121
+ if ( materialResults . imports . length > 0 || cdkResults . imports . length > 0 ) {
122
+ const initialContent = content ;
130
123
content = migrateMaterialSymbols ( content , newMaterialImportPath , materialResults . namespaces ) ;
124
+ content = migrateCdkSymbols ( content , newCdkImportPath , cdkResults . namespaces ) ;
125
+
126
+ // Only drop the imports if any of the symbols were used within the file.
127
+ if ( content !== initialContent ) {
128
+ content = removeStrings ( content , materialResults . imports ) ;
129
+ content = removeStrings ( content , cdkResults . imports ) ;
130
+ content = content . replace ( / ^ \s + / , '' ) ;
131
+ }
131
132
}
132
133
133
134
return content ;
134
135
}
135
136
136
137
/**
137
- * Finds all of the imports matching a prefix, removes them from
138
- * the content string and returns some information about them.
139
- * @param content Content from which to remove the imports.
138
+ * Counts the number of imports with a specific prefix and extracts their namespaces.
139
+ * @param content File content in which to look for imports.
140
140
* @param prefix Prefix that the imports should start with.
141
141
*/
142
- function detectAndDropImports ( content : string , prefix : string ) :
143
- { content : string , hasChanged : boolean , namespaces : string [ ] } {
142
+ function detectImports ( content : string , prefix : string ) : { imports : string [ ] , namespaces : string [ ] } {
144
143
if ( prefix [ prefix . length - 1 ] !== '/' ) {
145
144
// Some of the logic further down makes assumptions about the import depth.
146
145
throw Error ( `Prefix "${ prefix } " has to end in a slash.` ) ;
@@ -150,10 +149,13 @@ function detectAndDropImports(content: string, prefix: string):
150
149
// Since we know that the library doesn't have any name collisions, we can treat all of these
151
150
// namespaces as equivalent.
152
151
const namespaces : string [ ] = [ ] ;
152
+ const imports : string [ ] = [ ] ;
153
153
const pattern = new RegExp ( `@(import|use) +['"]${ escapeRegExp ( prefix ) } .*['"].*;?\n` , 'g' ) ;
154
- let hasChanged = false ;
154
+ let match : RegExpExecArray | null = null ;
155
+
156
+ while ( match = pattern . exec ( content ) ) {
157
+ const [ fullImport , type ] = match ;
155
158
156
- content = content . replace ( pattern , ( fullImport , type : 'import' | 'use' ) => {
157
159
if ( type === 'use' ) {
158
160
const namespace = extractNamespaceFromUseStatement ( fullImport ) ;
159
161
@@ -162,11 +164,10 @@ function detectAndDropImports(content: string, prefix: string):
162
164
}
163
165
}
164
166
165
- hasChanged = true ;
166
- return '' ;
167
- } ) ;
167
+ imports . push ( fullImport ) ;
168
+ }
168
169
169
- return { content , hasChanged , namespaces} ;
170
+ return { imports , namespaces} ;
170
171
}
171
172
172
173
/** Migrates the Material symbls in a file. */
@@ -303,6 +304,11 @@ function sortLengthDescending(a: string, b: string) {
303
304
return b . length - a . length ;
304
305
}
305
306
307
+ /** Removes all strings from another string. */
308
+ function removeStrings ( content : string , toRemove : string [ ] ) : string {
309
+ return toRemove . reduce ( ( accumulator , current ) => accumulator . replace ( current , '' ) , content ) ;
310
+ }
311
+
306
312
/** Parses out the namespace from a Sass `@use` statement. */
307
313
function extractNamespaceFromUseStatement ( fullImport : string ) : string {
308
314
const closeQuoteIndex = Math . max ( fullImport . lastIndexOf ( `"` ) , fullImport . lastIndexOf ( `'` ) ) ;
0 commit comments