Skip to content
Permalink
Browse files

fix(core): static-query migration fails with default parameter values (

…#30269)

Currently when someone has a call expression within the `ngOnInit` call
and we try to peek into that function with respect to the current function
context, the schematic errors because a call expression argument is
undefined. This is valid because the target function declaration defines
that parameter with a default value. In order to fix this, we need to
respect parameter default values.

PR Close #30269
  • Loading branch information...
devversion authored and alxhub committed May 5, 2019
1 parent 29786e8 commit 6357d4a0d3f211d27763e2faa24379507964b438
@@ -68,7 +68,8 @@ function getInputNamesFromMetadata(
// where inputs could be declared. This is an edge case because there // where inputs could be declared. This is an edge case because there
// always needs to be an object literal, but in case there isn't we just // always needs to be an object literal, but in case there isn't we just
// want to skip the invalid decorator and return null. // want to skip the invalid decorator and return null.
if (!ts.isObjectLiteralExpression(decoratorCall.arguments[0])) { if (decoratorCall.arguments.length !== 1 ||
!ts.isObjectLiteralExpression(decoratorCall.arguments[0])) {
return null; return null;
} }


@@ -240,6 +240,17 @@ export class DeclarationUsageVisitor {
callArgs: ts.NodeArray<ts.Expression>, parameters: ts.NodeArray<ts.ParameterDeclaration>) { callArgs: ts.NodeArray<ts.Expression>, parameters: ts.NodeArray<ts.ParameterDeclaration>) {
parameters.forEach((parameter, index) => { parameters.forEach((parameter, index) => {
let argumentNode: ts.Node = callArgs[index]; let argumentNode: ts.Node = callArgs[index];

if (!argumentNode) {
if (!parameter.initializer) {
return;
}

// Argument can be undefined in case the function parameter has a default
// value. In that case we want to store the parameter default value in the context.
argumentNode = parameter.initializer;
}

if (ts.isIdentifier(argumentNode)) { if (ts.isIdentifier(argumentNode)) {
this.context.set(parameter, this._resolveIdentifier(argumentNode)); this.context.set(parameter, this._resolveIdentifier(argumentNode));
} else { } else {
@@ -285,7 +296,7 @@ export class DeclarationUsageVisitor {
private _getPropertyAccessSymbol(node: ts.PropertyAccessExpression): ts.Symbol|null { private _getPropertyAccessSymbol(node: ts.PropertyAccessExpression): ts.Symbol|null {
let propertySymbol = this._getDeclarationSymbolOfNode(node.name); let propertySymbol = this._getDeclarationSymbolOfNode(node.name);


if (!propertySymbol) { if (!propertySymbol || !propertySymbol.valueDeclaration) {
return null; return null;
} }


@@ -1384,5 +1384,29 @@ describe('static-queries migration with usage strategy', () => {


expect(testModule.promptForMigrationStrategy).toHaveBeenCalledTimes(0); expect(testModule.promptForMigrationStrategy).toHaveBeenCalledTimes(0);
}); });

it('should support function call with default parameter value', async() => {
writeFile('/index.ts', `
import {Component, ${queryType}} from '@angular/core';
@Component({template: '<span>Test</span>'})
export class MyComponent {
@${queryType}('test') query: any;
ngOnInit() {
this.myFunction();
}
myFunction(unused?: string, cb = () => this.query.doSomething) {
cb();
}
}
`);

await runMigration();

expect(tree.readContent('/index.ts'))
.toContain(`@${queryType}('test', { static: true }) query: any;`);
});
} }
}); });

0 comments on commit 6357d4a

Please sign in to comment.
You can’t perform that action at this time.