@@ -16,6 +16,7 @@ import {
16
16
COMPONENT_THEME_MIXINS ,
17
17
CUSTOM_SASS_MIXIN_RENAMINGS ,
18
18
CUSTOM_SASS_FUNCTION_RENAMINGS ,
19
+ MIGRATED_CORE_SYMBOLS ,
19
20
} from './constants' ;
20
21
import { Migration , ResolvedResource , TargetVersion , WorkspacePath } from '@angular/cdk/schematics' ;
21
22
@@ -128,22 +129,107 @@ export class LegacyComponentsMigration extends Migration<null> {
128
129
*/
129
130
private _handleImportDeclaration ( node : ts . ImportDeclaration ) : void {
130
131
const moduleSpecifier = node . moduleSpecifier as ts . StringLiteral ;
131
-
132
132
const matImportChange = this . _findMatImportChange ( moduleSpecifier ) ;
133
- if ( matImportChange ) {
133
+ const mdcImportChange = this . _findMdcImportChange ( moduleSpecifier ) ;
134
+
135
+ if ( this . _isCoreImport ( moduleSpecifier . text ) ) {
136
+ this . _handleCoreImportDeclaration ( node ) ;
137
+ } else if ( matImportChange ) {
134
138
this . _tsReplaceAt ( node , matImportChange ) ;
135
139
136
140
if ( node . importClause ?. namedBindings && ts . isNamedImports ( node . importClause . namedBindings ) ) {
137
141
this . _handleNamedImportBindings ( node . importClause . namedBindings ) ;
138
142
}
143
+ } else if ( mdcImportChange ) {
144
+ this . _tsReplaceAt ( node , mdcImportChange ) ;
139
145
}
146
+ }
140
147
141
- const mdcImportChange = this . _findMdcImportChange ( moduleSpecifier ) ;
142
- if ( mdcImportChange ) {
143
- this . _tsReplaceAt ( node , mdcImportChange ) ;
148
+ private _isCoreImport ( importPath : string ) {
149
+ return [ '@angular/material/core' , '@angular/material/core/testing' ] . includes ( importPath ) ;
150
+ }
151
+
152
+ private _handleCoreImportDeclaration ( node : ts . ImportDeclaration ) {
153
+ const moduleSpecifier = node . moduleSpecifier as ts . StringLiteral ;
154
+
155
+ if ( node . importClause ?. namedBindings && ts . isNamedImports ( node . importClause . namedBindings ) ) {
156
+ this . _splitCoreImport ( node , node . importClause . namedBindings ) ;
157
+ } else {
158
+ this . _tsReplaceAt ( node , {
159
+ old : moduleSpecifier . text ,
160
+ new : moduleSpecifier . text . replace (
161
+ '@angular/material/core' ,
162
+ '@angular/material/legacy-core' ,
163
+ ) ,
164
+ } ) ;
144
165
}
145
166
}
146
167
168
+ private _splitCoreImport (
169
+ node : ts . Node ,
170
+ namedBindings : ts . NamedImports | ts . ObjectBindingPattern ,
171
+ ) {
172
+ const migratedSymbols = [ ] ;
173
+ const unmigratedSymbols = [ ] ;
174
+ for ( const element of namedBindings . elements ) {
175
+ if ( this . _isMigratedCoreSymbol ( element ) ) {
176
+ migratedSymbols . push ( element ) ;
177
+ } else {
178
+ unmigratedSymbols . push ( element ) ;
179
+ }
180
+ }
181
+ const unmigratedImportDeclaration = unmigratedSymbols . length
182
+ ? [ this . _stripImports ( node . getText ( ) , migratedSymbols ) ]
183
+ : [ ] ;
184
+ const migratedImportDeclaration = migratedSymbols . length
185
+ ? [
186
+ this . _updateImportedCoreSymbols (
187
+ this . _stripImports ( node . getText ( ) , unmigratedSymbols ) . replace (
188
+ '@angular/material/core' ,
189
+ '@angular/material/legacy-core' ,
190
+ ) ,
191
+ migratedSymbols ,
192
+ ) ,
193
+ ]
194
+ : [ ] ;
195
+ this . _tsReplaceAt ( node , {
196
+ old : node . getText ( ) ,
197
+ new : [ ...unmigratedImportDeclaration , ...migratedImportDeclaration ] . join ( '\n' ) ,
198
+ } ) ;
199
+ }
200
+
201
+ private _isMigratedCoreSymbol ( node : ts . ImportSpecifier | ts . BindingElement ) : boolean {
202
+ const name = node . propertyName ? node . propertyName : node . name ;
203
+ if ( ! ts . isIdentifier ( name ) ) {
204
+ return false ;
205
+ }
206
+
207
+ return ! ! MIGRATED_CORE_SYMBOLS [ name . escapedText . toString ( ) ] ;
208
+ }
209
+
210
+ private _stripImports ( importString : string , remove : ( ts . ImportSpecifier | ts . BindingElement ) [ ] ) {
211
+ for ( const symbol of remove ) {
212
+ importString = importString
213
+ . replace ( new RegExp ( `,\\s*${ symbol . getText ( ) } ` ) , '' )
214
+ . replace ( new RegExp ( `${ symbol . getText ( ) } ,\\s*` ) , '' )
215
+ . replace ( symbol . getText ( ) , '' ) ;
216
+ }
217
+ return importString ;
218
+ }
219
+
220
+ private _updateImportedCoreSymbols (
221
+ importString : string ,
222
+ rename : ( ts . ImportSpecifier | ts . BindingElement ) [ ] ,
223
+ ) {
224
+ return rename . reduce ( ( result , symbol ) => {
225
+ const oldName = symbol . propertyName ? symbol . propertyName . getText ( ) : symbol . name . getText ( ) ;
226
+ const newName = MIGRATED_CORE_SYMBOLS [ oldName ] ;
227
+ const aliasedName = symbol . propertyName ? symbol . name . getText ( ) : oldName ;
228
+ const separator = ts . isImportSpecifier ( symbol ) ? ' as ' : ': ' ;
229
+ return result . replace ( symbol . getText ( ) , `${ newName } ${ separator } ${ aliasedName } ` ) ;
230
+ } , importString ) ;
231
+ }
232
+
147
233
/**
148
234
* Handles updating the module specifier of
149
235
* @angular /material and @angular /material-experimental import expressions.
@@ -167,8 +253,13 @@ export class LegacyComponentsMigration extends Migration<null> {
167
253
private _handleDestructuredAsyncImport (
168
254
node : ts . VariableDeclaration & { name : ts . ObjectBindingPattern } ,
169
255
) : void {
170
- for ( let i = 0 ; i < node . name . elements . length ; i ++ ) {
171
- this . _handleNamedBindings ( node . name . elements [ i ] ) ;
256
+ const importPath = ( node ! . initializer as any ) . expression . arguments [ 0 ] . text ;
257
+ if ( ts . isVariableStatement ( node . parent . parent ) && this . _isCoreImport ( importPath ) ) {
258
+ this . _splitCoreImport ( node . parent . parent , node . name ) ;
259
+ } else {
260
+ for ( let i = 0 ; i < node . name . elements . length ; i ++ ) {
261
+ this . _handleNamedBindings ( node . name . elements [ i ] ) ;
262
+ }
172
263
}
173
264
}
174
265
0 commit comments