feat(ivy): add getBaseClassIdentifier() to ReflectionHost (#31544)

This method will be useful for writing ngcc `Migrations` that
need to be able to find base classes.

PR Close #31544
This commit is contained in:
Pete Bacon Darwin
2019-07-18 21:05:31 +01:00
committed by Misko Hevery
parent 399935c32b
commit 8a470b9af9
8 changed files with 408 additions and 4 deletions

View File

@ -1680,6 +1680,77 @@ runInEachFileSystem(() => {
});
});
describe('getBaseClassExpression()', () => {
it('should not consider a class without extends clause as having a base class', () => {
const file = {
name: _('/base_class.js'),
contents: `class TestClass {}`,
};
loadTestFiles([file]);
const {program} = makeTestBundleProgram(file.name);
const host = new Esm2015ReflectionHost(new MockLogger(), false, program.getTypeChecker());
const classNode = getDeclaration(program, file.name, 'TestClass', isNamedClassDeclaration);
expect(host.getBaseClassExpression(classNode)).toBe(null);
});
it('should find the base class of a class with an `extends` clause', () => {
const file = {
name: _('/base_class.js'),
contents: `
class BaseClass {}
class TestClass extends BaseClass {}`,
};
loadTestFiles([file]);
const {program} = makeTestBundleProgram(file.name);
const host = new Esm2015ReflectionHost(new MockLogger(), false, program.getTypeChecker());
const classNode = getDeclaration(program, file.name, 'TestClass', isNamedClassDeclaration);
const baseIdentifier = host.getBaseClassExpression(classNode) !;
if (!ts.isIdentifier(baseIdentifier)) {
throw new Error(`Expected ${baseIdentifier.getText()} to be an identifier.`);
}
expect(baseIdentifier.text).toEqual('BaseClass');
});
it('should find the base class of an aliased class with an `extends` clause', () => {
const file = {
name: _('/base_class.js'),
contents: `
let TestClass_1;
class BaseClass {}
let TestClass = TestClass_1 = class TestClass extends BaseClass {}`,
};
loadTestFiles([file]);
const {program} = makeTestBundleProgram(file.name);
const host = new Esm2015ReflectionHost(new MockLogger(), false, program.getTypeChecker());
const classNode =
getDeclaration(program, file.name, 'TestClass', isNamedVariableDeclaration);
const baseIdentifier = host.getBaseClassExpression(classNode) !;
if (!ts.isIdentifier(baseIdentifier)) {
throw new Error(`Expected ${baseIdentifier.getText()} to be an identifier.`);
}
expect(baseIdentifier.text).toEqual('BaseClass');
});
it('should find the base class expression of a class with a dynamic `extends` expression',
() => {
const file = {
name: _('/base_class.js'),
contents: `
class BaseClass {}
function foo() { return BaseClass; }
class TestClass extends foo() {}`,
};
loadTestFiles([file]);
const {program} = makeTestBundleProgram(file.name);
const host =
new Esm2015ReflectionHost(new MockLogger(), false, program.getTypeChecker());
const classNode =
getDeclaration(program, file.name, 'TestClass', isNamedClassDeclaration);
const baseExpression = host.getBaseClassExpression(classNode) !;
expect(baseExpression.getText()).toEqual('foo()');
});
});
describe('getGenericArityOfClass()', () => {
it('should properly count type parameters', () => {
loadTestFiles(ARITY_CLASSES);