fix(compiler-cli): Add support for string literal class members (#38226)
The current implementation of the TypeScriptReflectionHost does not account for members that are string literals, i.e. `class A { 'string-literal-prop': string; }` PR Close #38226
This commit is contained in:
parent
03a6252123
commit
65cc0c8bd6
|
@ -152,13 +152,13 @@ export interface ClassMember {
|
|||
name: string;
|
||||
|
||||
/**
|
||||
* TypeScript `ts.Identifier` representing the name of the member, or `null` if no such node
|
||||
* is present.
|
||||
* TypeScript `ts.Identifier` or `ts.StringLiteral` representing the name of the member, or `null`
|
||||
* if no such node is present.
|
||||
*
|
||||
* The `nameNode` is useful in writing references to this member that will be correctly source-
|
||||
* mapped back to the original file.
|
||||
*/
|
||||
nameNode: ts.Identifier|null;
|
||||
nameNode: ts.Identifier|ts.StringLiteral|null;
|
||||
|
||||
/**
|
||||
* TypeScript `ts.Expression` which represents the value of the member.
|
||||
|
|
|
@ -363,7 +363,7 @@ export class TypeScriptReflectionHost implements ReflectionHost {
|
|||
let kind: ClassMemberKind|null = null;
|
||||
let value: ts.Expression|null = null;
|
||||
let name: string|null = null;
|
||||
let nameNode: ts.Identifier|null = null;
|
||||
let nameNode: ts.Identifier|ts.StringLiteral|null = null;
|
||||
|
||||
if (ts.isPropertyDeclaration(node)) {
|
||||
kind = ClassMemberKind.Property;
|
||||
|
@ -385,6 +385,9 @@ export class TypeScriptReflectionHost implements ReflectionHost {
|
|||
} else if (ts.isIdentifier(node.name)) {
|
||||
name = node.name.text;
|
||||
nameNode = node.name;
|
||||
} else if (ts.isStringLiteral(node.name)) {
|
||||
name = node.name.text;
|
||||
nameNode = node.name;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
|
|
|
@ -9,7 +9,7 @@ import * as ts from 'typescript';
|
|||
import {absoluteFrom, getSourceFileOrError} from '../../file_system';
|
||||
import {runInEachFileSystem} from '../../file_system/testing';
|
||||
import {getDeclaration, makeProgram} from '../../testing';
|
||||
import {CtorParameter} from '../src/host';
|
||||
import {ClassMember, ClassMemberKind, CtorParameter} from '../src/host';
|
||||
import {TypeScriptReflectionHost} from '../src/typescript';
|
||||
import {isNamedClassDeclaration} from '../src/util';
|
||||
|
||||
|
@ -450,6 +450,95 @@ runInEachFileSystem(() => {
|
|||
]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('getMembersOfClass()', () => {
|
||||
it('should get string literal members of class', () => {
|
||||
const {program} = makeProgram([{
|
||||
name: _('/entry.ts'),
|
||||
contents: `
|
||||
class Foo {
|
||||
'string-literal-property-member' = 'my value';
|
||||
}
|
||||
`
|
||||
}]);
|
||||
const members = getMembers(program);
|
||||
expect(members.length).toBe(1);
|
||||
expectMember(members[0], 'string-literal-property-member', ClassMemberKind.Property);
|
||||
});
|
||||
|
||||
it('should retrieve method members', () => {
|
||||
const {program} = makeProgram([{
|
||||
name: _('/entry.ts'),
|
||||
contents: `
|
||||
class Foo {
|
||||
myMethod(): void {
|
||||
}
|
||||
}
|
||||
`
|
||||
}]);
|
||||
const members = getMembers(program);
|
||||
expect(members.length).toBe(1);
|
||||
expectMember(members[0], 'myMethod', ClassMemberKind.Method);
|
||||
});
|
||||
|
||||
it('should retrieve constructor as member', () => {
|
||||
const {program} = makeProgram([{
|
||||
name: _('/entry.ts'),
|
||||
contents: `
|
||||
class Foo {
|
||||
constructor() {}
|
||||
}
|
||||
`
|
||||
}]);
|
||||
const members = getMembers(program);
|
||||
expect(members.length).toBe(1);
|
||||
expectMember(members[0], 'constructor', ClassMemberKind.Constructor);
|
||||
});
|
||||
|
||||
it('should retrieve decorators of member', () => {
|
||||
const {program} = makeProgram([{
|
||||
name: _('/entry.ts'),
|
||||
contents: `
|
||||
declare var Input;
|
||||
|
||||
class Foo {
|
||||
@Input()
|
||||
prop: string;
|
||||
}
|
||||
`
|
||||
}]);
|
||||
const members = getMembers(program);
|
||||
expect(members.length).toBe(1);
|
||||
expect(members[0].decorators).not.toBeNull();
|
||||
expect(members[0].decorators![0].name).toBe('Input');
|
||||
});
|
||||
|
||||
it('identifies static members', () => {
|
||||
const {program} = makeProgram([{
|
||||
name: _('/entry.ts'),
|
||||
contents: `
|
||||
class Foo {
|
||||
static staticMember = '';
|
||||
}
|
||||
`
|
||||
}]);
|
||||
const members = getMembers(program);
|
||||
expect(members.length).toBe(1);
|
||||
expect(members[0].isStatic).toBeTrue();
|
||||
});
|
||||
|
||||
function getMembers(program: ts.Program) {
|
||||
const clazz = getDeclaration(program, _('/entry.ts'), 'Foo', isNamedClassDeclaration);
|
||||
const checker = program.getTypeChecker();
|
||||
const host = new TypeScriptReflectionHost(checker);
|
||||
return host.getMembersOfClass(clazz);
|
||||
}
|
||||
|
||||
function expectMember(member: ClassMember, name: string, kind: ClassMemberKind) {
|
||||
expect(member.name).toEqual(name);
|
||||
expect(member.kind).toEqual(kind);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
function expectParameter(
|
||||
|
|
Loading…
Reference in New Issue