Skip to content

Commit

Permalink
feat(compiler): add docs extraction for type aliases (#52118)
Browse files Browse the repository at this point in the history
This commit adds support for extracting type alises. It currently
extracts the raw written type from the source without performing any
resolution, such as for resolving `typeof` queries, as current Angular
public APIs do not rely on this.

PR Close #52118
  • Loading branch information
jelbourn authored and atscott committed Oct 10, 2023
1 parent 75d610d commit 1934524
Show file tree
Hide file tree
Showing 4 changed files with 96 additions and 0 deletions.
3 changes: 3 additions & 0 deletions packages/compiler-cli/src/ngtsc/docs/src/entities.ts
Expand Up @@ -62,6 +62,9 @@ export interface ConstantEntry extends DocEntry {
type: string;
}

/** Documentation entity for a type alias. */
export type TypeAliasEntry = ConstantEntry;

/** Documentation entity for a TypeScript class. */
export interface ClassEntry extends DocEntry {
isAbstract: boolean;
Expand Down
5 changes: 5 additions & 0 deletions packages/compiler-cli/src/ngtsc/docs/src/extractor.ts
Expand Up @@ -17,6 +17,7 @@ import {extractClass, extractInterface} from './class_extractor';
import {extractConstant, isSyntheticAngularConstant} from './constant_extractor';
import {DocEntry} from './entities';
import {isAngularPrivateName} from './filters';
import {extractTypeAlias} from './type_alias_extractor';

type DeclarationWithExportName = readonly[string, ts.Declaration];

Expand Down Expand Up @@ -72,6 +73,10 @@ export class DocsExtractor {
return extractConstant(node, this.typeChecker);
}

if (ts.isTypeAliasDeclaration(node)) {
return extractTypeAlias(node);
}

if (ts.isEnumDeclaration(node)) {
return extractEnum(node, this.typeChecker);
}
Expand Down
27 changes: 27 additions & 0 deletions packages/compiler-cli/src/ngtsc/docs/src/type_alias_extractor.ts
@@ -0,0 +1,27 @@
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import ts from 'typescript';

import {EntryType} from './entities';
import {extractJsDocDescription, extractJsDocTags, extractRawJsDoc} from './jsdoc_extractor';

/** Extract the documentation entry for a type alias. */
export function extractTypeAlias(declaration: ts.TypeAliasDeclaration) {
// TODO: this does not yet resolve type queries (`typeof`). We may want to
// fix this eventually, but for now it does not appear that any type aliases in
// Angular's public API rely on this.

return {
name: declaration.name.getText(),
type: declaration.type.getText(),
entryType: EntryType.TypeAlias,
rawComment: extractRawJsDoc(declaration),
description: extractJsDocDescription(declaration),
jsdocTags: extractJsDocTags(declaration),
};
}
@@ -0,0 +1,61 @@
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/

import {DocEntry} from '@angular/compiler-cli/src/ngtsc/docs';
import {EntryType, TypeAliasEntry} from '@angular/compiler-cli/src/ngtsc/docs/src/entities';
import {runInEachFileSystem} from '@angular/compiler-cli/src/ngtsc/file_system/testing';
import {loadStandardTestFiles} from '@angular/compiler-cli/src/ngtsc/testing';

import {NgtscTestEnvironment} from '../env';

const testFiles = loadStandardTestFiles({fakeCore: true, fakeCommon: true});

runInEachFileSystem(os => {
let env!: NgtscTestEnvironment;

describe('ngtsc type alias docs extraction', () => {
beforeEach(() => {
env = NgtscTestEnvironment.setup(testFiles);
env.tsconfig();
});

it('should extract type aliases based on primitives', () => {
env.write('index.ts', `
export type SuperNumber = number | string;
`);

const docs: DocEntry[] = env.driveDocsExtraction('index.ts');
expect(docs.length).toBe(1);

const typeAliasEntry = docs[0] as TypeAliasEntry;
expect(typeAliasEntry.name).toBe('SuperNumber');
expect(typeAliasEntry.entryType).toBe(EntryType.TypeAlias);
expect(typeAliasEntry.type).toBe('number | string');
});

it('should extract type aliases for objects', () => {
env.write('index.ts', `
export type UserProfile = {
name: string;
age: number;
};
`);

const docs: DocEntry[] = env.driveDocsExtraction('index.ts');
expect(docs.length).toBe(1);

const typeAliasEntry = docs[0] as TypeAliasEntry;
expect(typeAliasEntry.name).toBe('UserProfile');
expect(typeAliasEntry.entryType).toBe(EntryType.TypeAlias);
expect(typeAliasEntry.type).toBe(`{
name: string;
age: number;
}`);
});
});
});

0 comments on commit 1934524

Please sign in to comment.