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;
|
name: string;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* TypeScript `ts.Identifier` representing the name of the member, or `null` if no such node
|
* TypeScript `ts.Identifier` or `ts.StringLiteral` representing the name of the member, or `null`
|
||||||
* is present.
|
* if no such node is present.
|
||||||
*
|
*
|
||||||
* The `nameNode` is useful in writing references to this member that will be correctly source-
|
* The `nameNode` is useful in writing references to this member that will be correctly source-
|
||||||
* mapped back to the original file.
|
* 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.
|
* 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 kind: ClassMemberKind|null = null;
|
||||||
let value: ts.Expression|null = null;
|
let value: ts.Expression|null = null;
|
||||||
let name: string|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)) {
|
if (ts.isPropertyDeclaration(node)) {
|
||||||
kind = ClassMemberKind.Property;
|
kind = ClassMemberKind.Property;
|
||||||
|
@ -385,6 +385,9 @@ export class TypeScriptReflectionHost implements ReflectionHost {
|
||||||
} else if (ts.isIdentifier(node.name)) {
|
} else if (ts.isIdentifier(node.name)) {
|
||||||
name = node.name.text;
|
name = node.name.text;
|
||||||
nameNode = node.name;
|
nameNode = node.name;
|
||||||
|
} else if (ts.isStringLiteral(node.name)) {
|
||||||
|
name = node.name.text;
|
||||||
|
nameNode = node.name;
|
||||||
} else {
|
} else {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,7 +9,7 @@ import * as ts from 'typescript';
|
||||||
import {absoluteFrom, getSourceFileOrError} from '../../file_system';
|
import {absoluteFrom, getSourceFileOrError} from '../../file_system';
|
||||||
import {runInEachFileSystem} from '../../file_system/testing';
|
import {runInEachFileSystem} from '../../file_system/testing';
|
||||||
import {getDeclaration, makeProgram} from '../../testing';
|
import {getDeclaration, makeProgram} from '../../testing';
|
||||||
import {CtorParameter} from '../src/host';
|
import {ClassMember, ClassMemberKind, CtorParameter} from '../src/host';
|
||||||
import {TypeScriptReflectionHost} from '../src/typescript';
|
import {TypeScriptReflectionHost} from '../src/typescript';
|
||||||
import {isNamedClassDeclaration} from '../src/util';
|
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(
|
function expectParameter(
|
||||||
|
|
Loading…
Reference in New Issue