mirror of
https://github.com/angular/angular.git
synced 2026-09-14 13:54:52 +08:00
Currently if someone uses a namespace import or an import without named bindings in an Angular application, the `ng-update` schematics from Angular Material will fail due to missing safety checks before casting. Fixes #11571
This commit is contained in:
committed by
Jeremy Elbourn
parent
4ddbde93ea
commit
fe642115de
@@ -27,6 +27,10 @@ export function isMaterialExportDeclaration(node: ts.Node) {
|
||||
|
||||
/** Whether the declaration is part of Angular Material. */
|
||||
function isMaterialDeclaration(declaration: ts.ImportDeclaration | ts.ExportDeclaration) {
|
||||
if (!declaration.moduleSpecifier) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const moduleSpecifier = declaration.moduleSpecifier.getText();
|
||||
return moduleSpecifier.indexOf(materialModuleSpecifier) !== -1 ||
|
||||
moduleSpecifier.indexOf(cdkModuleSpecifier) !== -1;
|
||||
|
||||
@@ -12,26 +12,43 @@ import * as ts from 'typescript';
|
||||
import {isMaterialImportDeclaration} from '../material/typescript-specifiers';
|
||||
|
||||
/**
|
||||
* Rule that walks through every identifier that is part of Angular Material and replaces the
|
||||
* outdated name with the new one.
|
||||
* Rule that detects import declarations that refer to outdated identifiers from Angular Material
|
||||
* or the CDK which cannot be updated automatically.
|
||||
*/
|
||||
export class Rule extends Rules.TypedRule {
|
||||
applyWithProgram(sourceFile: ts.SourceFile, program: ts.Program): RuleFailure[] {
|
||||
return this.applyWithWalker(new CheckImportMiscWalker(sourceFile, this.getOptions(), program));
|
||||
return this.applyWithWalker(new Walker(sourceFile, this.getOptions(), program));
|
||||
}
|
||||
}
|
||||
|
||||
export class CheckImportMiscWalker extends ProgramAwareRuleWalker {
|
||||
visitImportDeclaration(declaration: ts.ImportDeclaration) {
|
||||
if (isMaterialImportDeclaration(declaration)) {
|
||||
declaration.importClause.namedBindings.forEachChild(n => {
|
||||
let importName = n.getFirstToken() && n.getFirstToken().getText();
|
||||
if (importName === 'SHOW_ANIMATION' || importName === 'HIDE_ANIMATION') {
|
||||
this.addFailureAtNode(
|
||||
n,
|
||||
`Found deprecated symbol "${red(importName)}" which has been removed`);
|
||||
}
|
||||
});
|
||||
export class Walker extends ProgramAwareRuleWalker {
|
||||
|
||||
visitImportDeclaration(node: ts.ImportDeclaration) {
|
||||
if (!isMaterialImportDeclaration(node) ||
|
||||
!node.importClause ||
|
||||
!node.importClause.namedBindings) {
|
||||
return;
|
||||
}
|
||||
|
||||
const namedBindings = node.importClause.namedBindings;
|
||||
|
||||
if (ts.isNamedImports(namedBindings)) {
|
||||
this._checkAnimationConstants(namedBindings);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks for named imports that refer to the deleted animation constants.
|
||||
* https://github.com/angular/material2/commit/9f3bf274c4f15f0b0fbd8ab7dbf1a453076e66d9
|
||||
*/
|
||||
private _checkAnimationConstants(namedImports: ts.NamedImports) {
|
||||
namedImports.elements.filter(element => ts.isIdentifier(element.name)).forEach(element => {
|
||||
const importName = element.name.text;
|
||||
|
||||
if (importName === 'SHOW_ANIMATION' || importName === 'HIDE_ANIMATION') {
|
||||
this.addFailureAtNode(element,
|
||||
`Found deprecated symbol "${red(importName)}" which has been removed`);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user