From 6da9e5851a8dea2bcffc9be690e349ce52465393 Mon Sep 17 00:00:00 2001 From: crisbeto Date: Sun, 9 Aug 2020 10:10:35 +0200 Subject: [PATCH] fix(compiler-cli): preserve quotes in class member names (#38387) When we were outputting class members for `setClassMetadata` calls, we were using the string representation of the member name. This can lead to us generating invalid code when the name contains dashes and is quoted (e.g. `@Output() 'has-dashes' = new EventEmitter()`), because the quotes will be stripped for the string representation. These changes fix the issue by using the original name AST node that was used for the declaration and which knows whether it's supposed to be quoted or not. Fixes #38311. PR Close #38387 --- .../src/ngtsc/annotations/src/metadata.ts | 6 +++--- .../src/ngtsc/annotations/test/metadata_spec.ts | 13 +++++++++++++ 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/packages/compiler-cli/src/ngtsc/annotations/src/metadata.ts b/packages/compiler-cli/src/ngtsc/annotations/src/metadata.ts index 56676ac84d..3ac72e8d10 100644 --- a/packages/compiler-cli/src/ngtsc/annotations/src/metadata.ts +++ b/packages/compiler-cli/src/ngtsc/annotations/src/metadata.ts @@ -70,8 +70,8 @@ export function generateSetClassMetadataCall( `Duplicate decorated properties found on class '${clazz.name.text}': ` + duplicateDecoratedMemberNames.join(', ')); } - const decoratedMembers = - classMembers.map(member => classMemberToMetadata(member.name, member.decorators!, isCore)); + const decoratedMembers = classMembers.map( + member => classMemberToMetadata(member.nameNode ?? member.name, member.decorators!, isCore)); if (decoratedMembers.length > 0) { metaPropDecorators = ts.createObjectLiteral(decoratedMembers); } @@ -127,7 +127,7 @@ function ctorParameterToMetadata( * Convert a reflected class member to metadata. */ function classMemberToMetadata( - name: string, decorators: Decorator[], isCore: boolean): ts.PropertyAssignment { + name: ts.PropertyName|string, decorators: Decorator[], isCore: boolean): ts.PropertyAssignment { const ngDecorators = decorators.filter(dec => isAngularDecorator(dec, isCore)) .map((decorator: Decorator) => decoratorToMetadata(decorator)); const decoratorMeta = ts.createArrayLiteral(ngDecorators); diff --git a/packages/compiler-cli/src/ngtsc/annotations/test/metadata_spec.ts b/packages/compiler-cli/src/ngtsc/annotations/test/metadata_spec.ts index b830a43326..1745af51a7 100644 --- a/packages/compiler-cli/src/ngtsc/annotations/test/metadata_spec.ts +++ b/packages/compiler-cli/src/ngtsc/annotations/test/metadata_spec.ts @@ -90,6 +90,19 @@ runInEachFileSystem(() => { `); expect(res).toBe(''); }); + + it('should preserve quotes around class member names', () => { + const res = compileAndPrint(` + import {Component, Input} from '@angular/core'; + + @Component('metadata') class Target { + @Input() 'has-dashes-in-name' = 123; + @Input() noDashesInName = 456; + } + `); + expect(res).toContain( + `{ 'has-dashes-in-name': [{ type: Input }], noDashesInName: [{ type: Input }] })`); + }); }); function compileAndPrint(contents: string): string {