Skip to content

Commit

Permalink
feat(material/schematics): impl mat-mdc ts v15 ng-update (#25447)
Browse files Browse the repository at this point in the history
  • Loading branch information
wagnermaciel committed Aug 15, 2022
1 parent 8027b5b commit 938802f
Show file tree
Hide file tree
Showing 3 changed files with 117 additions and 45 deletions.
Expand Up @@ -37,3 +37,13 @@ export const MIXINS = COMPONENTS.flatMap(component => [
`${component}-density`,
`${component}-typography`,
]);

export const MAT_IMPORT_CHANGE = {
old: '@angular/material/',
new: '@angular/material/legacy-',
};

export const MAT_MDC_IMPORT_CHANGE = {
old: '@angular/material-experimental/mdc-',
new: '@angular/material/',
};
Expand Up @@ -10,7 +10,7 @@ import * as ts from 'typescript';
import * as postcss from 'postcss';
import * as scss from 'postcss-scss';

import {MIXINS} from './constants';
import {MAT_IMPORT_CHANGE, MAT_MDC_IMPORT_CHANGE, MIXINS} from './constants';

import {Migration, ResolvedResource, TargetVersion, WorkspacePath} from '@angular/cdk/schematics';

Expand Down Expand Up @@ -73,7 +73,7 @@ export class LegacyComponentsMigration extends Migration<null> {
this._handleImportDeclaration(node);
return;
}
if (this._isDestructuredAsyncImport(node)) {
if (this._isDestructuredAsyncLegacyImport(node)) {
this._handleDestructuredAsyncImport(node);
return;
}
Expand Down Expand Up @@ -101,23 +101,39 @@ export class LegacyComponentsMigration extends Migration<null> {
}
}

/** Handles updating the module specifier of @angular/material imports. */
/**
* Handles updating the module specifier of
* @angular/material and @angular/material-experimental imports.
*
* Also updates the named import bindings of @angular/material imports.
*/
private _handleImportDeclaration(node: ts.ImportDeclaration): void {
const moduleSpecifier = node.moduleSpecifier as ts.StringLiteral;
if (moduleSpecifier.text.startsWith('@angular/material/')) {
this._tsReplaceAt(node, {old: '@angular/material/', new: '@angular/material/legacy-'});
if (moduleSpecifier.text.startsWith(MAT_IMPORT_CHANGE.old)) {
this._tsReplaceAt(node, MAT_IMPORT_CHANGE);

if (node.importClause?.namedBindings && ts.isNamedImports(node.importClause.namedBindings)) {
this._handleNamedImportBindings(node.importClause.namedBindings);
}
}

if (moduleSpecifier.text.startsWith(MAT_MDC_IMPORT_CHANGE.old)) {
this._tsReplaceAt(node, MAT_MDC_IMPORT_CHANGE);
}
}

/** Handles updating the module specifier of @angular/material import expressions. */
/**
* Handles updating the module specifier of
* @angular/material and @angular/material-experimental import expressions.
*/
private _handleImportExpression(node: ts.CallExpression): void {
const moduleSpecifier = node.arguments[0] as ts.StringLiteral;
if (moduleSpecifier.text.startsWith('@angular/material/')) {
this._tsReplaceAt(node, {old: '@angular/material/', new: '@angular/material/legacy-'});
if (moduleSpecifier.text.startsWith(MAT_IMPORT_CHANGE.old)) {
this._tsReplaceAt(node, MAT_IMPORT_CHANGE);
}

if (moduleSpecifier.text.startsWith(MAT_MDC_IMPORT_CHANGE.old)) {
this._tsReplaceAt(node, MAT_MDC_IMPORT_CHANGE);
}
}

Expand All @@ -136,18 +152,22 @@ export class LegacyComponentsMigration extends Migration<null> {
}

/**
* Returns true if the given node is a variable declaration assigns
* the awaited result of an import expression using an object binding.
* Returns true if the given node is a variable declaration
* assigns the awaited result of an @angular/material import
* expression using an object binding.
*/
private _isDestructuredAsyncImport(
node: ts.Node,
): node is ts.VariableDeclaration & {name: ts.ObjectBindingPattern} {
private _isDestructuredAsyncLegacyImport(node: ts.Node): node is ts.VariableDeclaration & {
name: ts.ObjectBindingPattern;
initializer: ts.AwaitExpression & {expression: ts.CallExpression} & {
arguments: [ts.StringLiteralLike];
};
} {
return (
ts.isVariableDeclaration(node) &&
!!node.initializer &&
ts.isAwaitExpression(node.initializer) &&
ts.isCallExpression(node.initializer.expression) &&
ts.SyntaxKind.ImportKeyword === node.initializer.expression.expression.kind &&
this._isImportCallExpression(node.initializer.expression) &&
node.initializer.expression.arguments[0].text.startsWith(MAT_IMPORT_CHANGE.old) &&
ts.isObjectBindingPattern(node.name)
);
}
Expand Down
Expand Up @@ -43,41 +43,83 @@ describe('v15 legacy components migration', () => {
expect(readLine(TS_FILE_PATH)).withContext(ctx).toEqual(opts.new);
}

it('updates import declarations', async () => {
await runTypeScriptMigrationTest('named binding', {
old: `import {MatButton} from '@angular/material/button';`,
new: `import {MatLegacyButton as MatButton} from '@angular/material/legacy-button';`,
describe('material --> legacy', () => {
it('updates import declarations', async () => {
await runTypeScriptMigrationTest('named binding', {
old: `import {MatButton} from '@angular/material/button';`,
new: `import {MatLegacyButton as MatButton} from '@angular/material/legacy-button';`,
});
await runTypeScriptMigrationTest('named binding w/ alias', {
old: `import {MatButton as Button} from '@angular/material/button';`,
new: `import {MatLegacyButton as Button} from '@angular/material/legacy-button';`,
});
await runTypeScriptMigrationTest('multiple named bindings', {
old: `import {MatButton, MatButtonModule} from '@angular/material/button';`,
new: `import {MatLegacyButton as MatButton, MatLegacyButtonModule as MatButtonModule} from '@angular/material/legacy-button';`,
});
await runTypeScriptMigrationTest('multiple named bindings w/ alias', {
old: `import {MatButton, MatButtonModule as ButtonModule} from '@angular/material/button';`,
new: `import {MatLegacyButton as MatButton, MatLegacyButtonModule as ButtonModule} from '@angular/material/legacy-button';`,
});
});
await runTypeScriptMigrationTest('named binding w/ alias', {
old: `import {MatButton as Button} from '@angular/material/button';`,
new: `import {MatLegacyButton as Button} from '@angular/material/legacy-button';`,
});
await runTypeScriptMigrationTest('multiple named bindings', {
old: `import {MatButton, MatButtonModule} from '@angular/material/button';`,
new: `import {MatLegacyButton as MatButton, MatLegacyButtonModule as MatButtonModule} from '@angular/material/legacy-button';`,
});
await runTypeScriptMigrationTest('multiple named bindings w/ alias', {
old: `import {MatButton, MatButtonModule as ButtonModule} from '@angular/material/button';`,
new: `import {MatLegacyButton as MatButton, MatLegacyButtonModule as ButtonModule} from '@angular/material/legacy-button';`,

it('updates import expressions', async () => {
await runTypeScriptMigrationTest('destructured & awaited', {
old: `const {MatButton} = await import('@angular/material/button');`,
new: `const {MatLegacyButton: MatButton} = await import('@angular/material/legacy-button');`,
});
await runTypeScriptMigrationTest('destructured & awaited w/ alias', {
old: `const {MatButton: Button} = await import('@angular/material/button');`,
new: `const {MatLegacyButton: Button} = await import('@angular/material/legacy-button');`,
});
await runTypeScriptMigrationTest('promise', {
old: `const promise = import('@angular/material/button');`,
new: `const promise = import('@angular/material/legacy-button');`,
});
await runTypeScriptMigrationTest('.then', {
old: `import('@angular/material/button').then(() => {});`,
new: `import('@angular/material/legacy-button').then(() => {});`,
});
});
});

it('updates import expressions', async () => {
await runTypeScriptMigrationTest('destructured & awaited', {
old: `const {MatButton} = await import('@angular/material/button');`,
new: `const {MatLegacyButton: MatButton} = await import('@angular/material/legacy-button');`,
describe('material-experimental --> material', () => {
it('updates import declarations', async () => {
await runTypeScriptMigrationTest('named binding', {
old: `import {MatButton} from '@angular/material-experimental/mdc-button';`,
new: `import {MatButton} from '@angular/material/button';`,
});
await runTypeScriptMigrationTest('named binding w/ alias', {
old: `import {MatButton as Button} from '@angular/material-experimental/mdc-button';`,
new: `import {MatButton as Button} from '@angular/material/button';`,
});
await runTypeScriptMigrationTest('multiple named bindings', {
old: `import {MatButton, MatButtonModule} from '@angular/material-experimental/mdc-button';`,
new: `import {MatButton, MatButtonModule} from '@angular/material/button';`,
});
await runTypeScriptMigrationTest('multiple named bindings w/ alias', {
old: `import {MatButton, MatButtonModule as ButtonModule} from '@angular/material-experimental/mdc-button';`,
new: `import {MatButton, MatButtonModule as ButtonModule} from '@angular/material/button';`,
});
});
await runTypeScriptMigrationTest('destructured & awaited w/ alias', {
old: `const {MatButton: Button} = await import('@angular/material/button');`,
new: `const {MatLegacyButton: Button} = await import('@angular/material/legacy-button');`,
});
await runTypeScriptMigrationTest('promise', {
old: `const promise = import('@angular/material/button');`,
new: `const promise = import('@angular/material/legacy-button');`,
});
await runTypeScriptMigrationTest('.then', {
old: `import('@angular/material/button').then(() => {});`,
new: `import('@angular/material/legacy-button').then(() => {});`,

it('updates import expressions', async () => {
await runTypeScriptMigrationTest('destructured & awaited', {
old: `const {MatButton} = await import('@angular/material-experimental/mdc-button');`,
new: `const {MatButton} = await import('@angular/material/button');`,
});
await runTypeScriptMigrationTest('destructured & awaited w/ alias', {
old: `const {MatButton: Button} = await import('@angular/material-experimental/mdc-button');`,
new: `const {MatButton: Button} = await import('@angular/material/button');`,
});
await runTypeScriptMigrationTest('promise', {
old: `const promise = import('@angular/material-experimental/mdc-button');`,
new: `const promise = import('@angular/material/button');`,
});
await runTypeScriptMigrationTest('.then', {
old: `import('@angular/material-experimental/mdc-button').then(() => {});`,
new: `import('@angular/material/button').then(() => {});`,
});
});
});
});
Expand Down

0 comments on commit 938802f

Please sign in to comment.