From d127d05dc37e5d98680464b5069ca38310405acd Mon Sep 17 00:00:00 2001 From: Alex Rickabaugh Date: Fri, 22 Feb 2019 14:11:38 -0800 Subject: [PATCH] fix(ivy): correctly resolve shorthand property declarations (#28936) The partial evaluator in ngtsc can handle a shorthand property declaration in the middle evaluation, but fails if evaluation starts at the shorthand property itself. This is because evaluation starts at the ts.Identifier of the property (the ts.Expression representing it), not the ts.Declaration for the property. The fix for this is to detect in TypeScriptReflectionHost when a ts.Symbol refers to a shorthand property, and to use the ts.TypeChecker method getShorthandAssignmentValueSymbol() to resolve the value of the assignment instead. FW-1089 #resolve PR Close #28936 --- .../ngtsc/partial_evaluator/test/evaluator_spec.ts | 14 ++++++++++++++ .../src/ngtsc/reflection/src/typescript.ts | 10 ++++++++++ 2 files changed, 24 insertions(+) diff --git a/packages/compiler-cli/src/ngtsc/partial_evaluator/test/evaluator_spec.ts b/packages/compiler-cli/src/ngtsc/partial_evaluator/test/evaluator_spec.ts index 640c332b31..ee3b2c83c4 100644 --- a/packages/compiler-cli/src/ngtsc/partial_evaluator/test/evaluator_spec.ts +++ b/packages/compiler-cli/src/ngtsc/partial_evaluator/test/evaluator_spec.ts @@ -267,6 +267,20 @@ describe('ngtsc metadata', () => { ]); expect(value instanceof Reference).toBe(true); }); + + it('should resolve shorthand properties to values', () => { + const {program} = makeProgram([ + {name: 'entry.ts', contents: `const prop = 42; const target$ = {prop};`}, + ]); + const checker = program.getTypeChecker(); + const reflectionHost = new TypeScriptReflectionHost(checker); + const result = getDeclaration(program, 'entry.ts', 'target$', ts.isVariableDeclaration); + const expr = result.initializer !as ts.ObjectLiteralExpression; + const prop = expr.properties[0] as ts.ShorthandPropertyAssignment; + const evaluator = new PartialEvaluator(reflectionHost, checker); + const resolved = evaluator.evaluate(prop.name); + expect(resolved).toBe(42); + }); }); function owningModuleOf(ref: Reference): string|null { diff --git a/packages/compiler-cli/src/ngtsc/reflection/src/typescript.ts b/packages/compiler-cli/src/ngtsc/reflection/src/typescript.ts index 460a1e3eea..519e767138 100644 --- a/packages/compiler-cli/src/ngtsc/reflection/src/typescript.ts +++ b/packages/compiler-cli/src/ngtsc/reflection/src/typescript.ts @@ -196,6 +196,16 @@ export class TypeScriptReflectionHost implements ReflectionHost { * @internal */ protected getDeclarationOfSymbol(symbol: ts.Symbol): Declaration|null { + // If the symbol points to a ShorthandPropertyAssignment, resolve it. + if (symbol.valueDeclaration !== undefined && + ts.isShorthandPropertyAssignment(symbol.valueDeclaration)) { + const shorthandSymbol = + this.checker.getShorthandAssignmentValueSymbol(symbol.valueDeclaration); + if (shorthandSymbol === undefined) { + return null; + } + return this.getDeclarationOfSymbol(shorthandSymbol); + } let viaModule: string|null = null; // Look through the Symbol's immediate declarations, and see if any of them are import-type // statements.