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
This commit is contained in:
crisbeto 2020-08-09 10:10:35 +02:00 committed by Andrew Kushnir
parent 250e299dc3
commit 6da9e5851a
2 changed files with 16 additions and 3 deletions

View File

@ -70,8 +70,8 @@ export function generateSetClassMetadataCall(
`Duplicate decorated properties found on class '${clazz.name.text}': ` + `Duplicate decorated properties found on class '${clazz.name.text}': ` +
duplicateDecoratedMemberNames.join(', ')); duplicateDecoratedMemberNames.join(', '));
} }
const decoratedMembers = const decoratedMembers = classMembers.map(
classMembers.map(member => classMemberToMetadata(member.name, member.decorators!, isCore)); member => classMemberToMetadata(member.nameNode ?? member.name, member.decorators!, isCore));
if (decoratedMembers.length > 0) { if (decoratedMembers.length > 0) {
metaPropDecorators = ts.createObjectLiteral(decoratedMembers); metaPropDecorators = ts.createObjectLiteral(decoratedMembers);
} }
@ -127,7 +127,7 @@ function ctorParameterToMetadata(
* Convert a reflected class member to metadata. * Convert a reflected class member to metadata.
*/ */
function classMemberToMetadata( 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)) const ngDecorators = decorators.filter(dec => isAngularDecorator(dec, isCore))
.map((decorator: Decorator) => decoratorToMetadata(decorator)); .map((decorator: Decorator) => decoratorToMetadata(decorator));
const decoratorMeta = ts.createArrayLiteral(ngDecorators); const decoratorMeta = ts.createArrayLiteral(ngDecorators);

View File

@ -90,6 +90,19 @@ runInEachFileSystem(() => {
`); `);
expect(res).toBe(''); 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 { function compileAndPrint(contents: string): string {