Skip to content

Commit 66416f5

Browse files
devversionmmalerba
authored andcommitted
fix(update): support parenthesized directive metadata (#12314)
* Currently if the directive metadata is parenthesized, the upgrade tool will fail due to a runtime exception. We should properly handle that edge-case since the `ComponentWalker` is one of major parts for the upgrade tool and will persist in future releases. * No longer fails if a `@Component` is being created without any metadata or a wrong number of arguments (rel: angular/angular@9a6f27c)
1 parent 25d0bf4 commit 66416f5

File tree

1 file changed

+22
-7
lines changed

1 file changed

+22
-7
lines changed

src/lib/schematics/update/tslint/component-walker.ts

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
*/
44
import {existsSync, readFileSync} from 'fs'
55
import {dirname, join, resolve} from 'path';
6-
import {Fix, IOptions, RuleFailure, RuleWalker} from 'tslint';
6+
import {IOptions, RuleWalker} from 'tslint';
77
import * as ts from 'typescript';
88
import {getLiteralTextWithoutQuotes} from '../typescript/literal';
99
import {createComponentFile, ExternalResource} from "./component-file";
@@ -41,7 +41,13 @@ export class ComponentWalker extends RuleWalker {
4141
}
4242

4343
private _visitDirectiveCallExpression(callExpression: ts.CallExpression) {
44-
const directiveMetadata = callExpression.arguments[0] as ts.ObjectLiteralExpression;
44+
// If the call expressions does not have the correct amount of arguments, we can assume that
45+
// this call expression is not related to Angular and just uses a similar decorator name.
46+
if (callExpression.arguments.length !== 1) {
47+
return;
48+
}
49+
50+
const directiveMetadata = this._findMetadataFromExpression(callExpression.arguments[0]);
4551

4652
if (!directiveMetadata) {
4753
return;
@@ -121,11 +127,20 @@ export class ComponentWalker extends RuleWalker {
121127
this.visitExternalStylesheet(stylesheetFile);
122128
}
123129

124-
/** Creates a TSLint rule failure for the given external resource. */
125-
protected addExternalResourceFailure(file: ExternalResource, message: string, fix?: Fix) {
126-
const ruleFailure = new RuleFailure(file, file.getStart(), file.getEnd(),
127-
message, this.getRuleName(), fix);
130+
/**
131+
* Recursively searches for the metadata object literal expression inside of a directive call
132+
* expression. Since expression calls can be nested through *parenthesized* expressions, we
133+
* need to recursively visit and check every expression inside of a parenthesized expression.
134+
*
135+
* e.g. @Component((({myMetadataExpression}))) will return `myMetadataExpression`.
136+
*/
137+
private _findMetadataFromExpression(node: ts.Expression): ts.ObjectLiteralExpression | null {
138+
if (node.kind === ts.SyntaxKind.ObjectLiteralExpression) {
139+
return node as ts.ObjectLiteralExpression;
140+
} else if (node.kind === ts.SyntaxKind.ParenthesizedExpression) {
141+
return this._findMetadataFromExpression((node as ts.ParenthesizedExpression).expression);
142+
}
128143

129-
this.addFailure(ruleFailure);
144+
return null;
130145
}
131146
}

0 commit comments

Comments
 (0)