refactor(compiler-cli): Add support for inheritance in API extraction (#57588)

This commit adds the `extends` and `implements` properties to the `ClassEntry` & `InterfaceEntry`

PR Close #57588
This commit is contained in:
Matthieu Riegler
2024-08-21 01:05:01 +02:00
committed by Andrew Kushnir
parent 5256016695
commit 582aac49a7
3 changed files with 55 additions and 0 deletions
@@ -85,6 +85,8 @@ class ClassExtractor {
description: extractJsDocDescription(this.declaration),
jsdocTags: extractJsDocTags(this.declaration),
rawComment: extractRawJsDoc(this.declaration),
extends: this.extractInheritance(this.declaration),
implements: this.extractInterfaceConformance(this.declaration),
};
}
@@ -175,6 +177,36 @@ class ClassExtractor {
};
}
protected extractInheritance(
declaration: ClassDeclaration & ClassDeclarationLike,
): string | undefined {
if (!declaration.heritageClauses) {
return undefined;
}
for (const clause of declaration.heritageClauses) {
if (clause.token === ts.SyntaxKind.ExtendsKeyword) {
// We are assuming a single class can only extend one class.
const types = clause.types;
if (types.length > 0) {
const baseClass: ts.ExpressionWithTypeArguments = types[0];
return baseClass.getText();
}
}
}
return undefined;
}
protected extractInterfaceConformance(
declaration: ClassDeclaration & ClassDeclarationLike,
): string[] {
const implementClause = declaration.heritageClauses?.find(
(clause) => clause.token === ts.SyntaxKind.ImplementsKeyword,
);
return implementClause?.types.map((m) => m.getText()) ?? [];
}
/** Gets the tags for a member (protected, readonly, static, etc.) */
protected getMemberTags(member: MethodLike | PropertyLike): MemberTags[] {
const tags: MemberTags[] = this.getMemberTagsFromModifiers(member.modifiers ?? []);
@@ -107,6 +107,8 @@ export interface ClassEntry extends DocEntry {
isAbstract: boolean;
members: MemberEntry[];
generics: GenericEntry[];
extends?: string;
implements: string[];
}
// From an API doc perspective, class and interfaces are identical.
@@ -461,6 +461,27 @@ runInEachFileSystem(() => {
expect(genericEntry.default).toBeUndefined();
});
it('should extract inheritence/interface conformance', () => {
env.write(
'index.ts',
`
interface Foo {}
interface Bar {}
class Parent extends Ancestor {}
export class Child extends Parent implements Foo, Bar {}
`,
);
const docs: DocEntry[] = env.driveDocsExtraction('index.ts');
expect(docs.length).toBe(1);
const classEntry = docs[0] as ClassEntry;
expect(classEntry.extends).toBe('Parent');
expect(classEntry.implements).toEqual(['Foo', 'Bar']);
});
it('should extract inherited members', () => {
env.write(
'index.ts',