Skip to content

Commit 676d21c

Browse files
committed
fix(update): support parenthesized directive metadata
* 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 3b50e44 commit 676d21c

File tree

1 file changed

+21
-6
lines changed

1 file changed

+21
-6
lines changed

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

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,13 @@ export class ComponentWalker extends RuleWalker {
4949
}
5050

5151
private _visitDirectiveCallExpression(callExpression: ts.CallExpression) {
52-
const directiveMetadata = callExpression.arguments[0] as ts.ObjectLiteralExpression;
52+
// If the call expressions does not have the correct amount of arguments, we can assume that
53+
// this call expression is not related to Angular and just uses a similar decorator name.
54+
if (callExpression.arguments.length !== 1) {
55+
return;
56+
}
57+
58+
const directiveMetadata = this._findMetadataFromExpression(callExpression.arguments[0]);
5359

5460
if (!directiveMetadata) {
5561
return;
@@ -130,11 +136,20 @@ export class ComponentWalker extends RuleWalker {
130136
this.visitExternalStylesheet(stylesheetFile);
131137
}
132138

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

138-
this.addFailure(ruleFailure);
153+
return null;
139154
}
140155
}

0 commit comments

Comments
 (0)