mirror of
https://github.com/angular/angular
synced 2026-05-24 09:28:37 +00:00
docs(docs-infra): improve api docs extraction
This allows us to show the API docs when the jsdoc block is at the top of a overloaded function (and not on the implementation signature).
eg: `injectAsync`
(cherry picked from commit 7360c1da68)
This commit is contained in:
parent
0601dc579a
commit
78ec99d146
2 changed files with 88 additions and 9 deletions
|
|
@ -42,8 +42,18 @@ export class FunctionExtractor {
|
|||
const overloads = ts.isConstructorDeclaration(this.exportDeclaration)
|
||||
? constructorOverloads(this.exportDeclaration, this.typeChecker)
|
||||
: extractCallSignatures(this.name, this.typeChecker, type);
|
||||
const jsdocsTags = extractJsDocTags(implementation);
|
||||
const description = extractJsDocDescription(implementation);
|
||||
const implementationJsDocTags = extractJsDocTags(implementation);
|
||||
const implementationDescription = extractJsDocDescription(implementation);
|
||||
const implementationRawComment = extractRawJsDoc(implementation);
|
||||
const docsForFunctionEntry = extractFunctionEntryDocs(overloads, {
|
||||
description: implementationDescription,
|
||||
jsdocTags: implementationJsDocTags,
|
||||
rawComment: implementationRawComment,
|
||||
}) ?? {
|
||||
description: implementationDescription,
|
||||
jsdocTags: implementationJsDocTags,
|
||||
rawComment: implementationRawComment,
|
||||
};
|
||||
|
||||
return {
|
||||
name: this.name,
|
||||
|
|
@ -52,22 +62,41 @@ export class FunctionExtractor {
|
|||
params: extractAllParams(implementation.parameters, this.typeChecker),
|
||||
isNewType: ts.isConstructSignatureDeclaration(implementation),
|
||||
returnType,
|
||||
returnDescription: jsdocsTags.find((tag) => tag.name === 'returns')?.comment,
|
||||
returnDescription: implementationJsDocTags.find((tag) => tag.name === 'returns')?.comment,
|
||||
generics: extractGenerics(implementation),
|
||||
name: this.name,
|
||||
description,
|
||||
description: implementationDescription,
|
||||
entryType: EntryType.Function,
|
||||
jsdocTags: jsdocsTags,
|
||||
rawComment: extractRawJsDoc(implementation),
|
||||
jsdocTags: implementationJsDocTags,
|
||||
rawComment: implementationRawComment,
|
||||
},
|
||||
entryType: EntryType.Function,
|
||||
description,
|
||||
jsdocTags: jsdocsTags,
|
||||
rawComment: extractRawJsDoc(implementation),
|
||||
description: docsForFunctionEntry.description,
|
||||
jsdocTags: docsForFunctionEntry.jsdocTags,
|
||||
rawComment: docsForFunctionEntry.rawComment,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
function extractFunctionEntryDocs(
|
||||
overloads: FunctionSignatureMetadata[],
|
||||
implementationDocs: Pick<FunctionSignatureMetadata, 'description' | 'jsdocTags' | 'rawComment'>,
|
||||
): Pick<FunctionSignatureMetadata, 'description' | 'jsdocTags' | 'rawComment'> | null {
|
||||
if (hasJSDocContent(implementationDocs)) {
|
||||
return implementationDocs;
|
||||
}
|
||||
|
||||
return overloads.find((overload) => hasJSDocContent(overload)) ?? null;
|
||||
}
|
||||
|
||||
function hasJSDocContent(
|
||||
docs: Pick<FunctionSignatureMetadata, 'description' | 'jsdocTags' | 'rawComment'>,
|
||||
): boolean {
|
||||
return (
|
||||
docs.description.trim() !== '' || docs.rawComment.trim() !== '' || docs.jsdocTags.length > 0
|
||||
);
|
||||
}
|
||||
|
||||
function constructorOverloads(
|
||||
constructorDeclaration: ts.ConstructorDeclaration,
|
||||
typeChecker: ts.TypeChecker,
|
||||
|
|
|
|||
|
|
@ -126,6 +126,56 @@ runInEachFileSystem(() => {
|
|||
expect(numberOverloadEntry.returnType).toBe('number');
|
||||
});
|
||||
|
||||
it('should use overload docs when implementation has no docs', () => {
|
||||
env.write(
|
||||
'index.ts',
|
||||
`
|
||||
/**
|
||||
* Overload docs.
|
||||
*
|
||||
* @publicApi
|
||||
*/
|
||||
export function ident(value: boolean): boolean
|
||||
export function ident(value: boolean|number): boolean|number {
|
||||
return value;
|
||||
}
|
||||
`,
|
||||
);
|
||||
|
||||
const docs = env.driveDocsExtraction('index.ts') as FunctionEntry[];
|
||||
const [functionEntry] = docs;
|
||||
|
||||
expect(functionEntry.description).toContain('Overload docs.');
|
||||
expect(functionEntry.rawComment).toContain('Overload docs.');
|
||||
expect(functionEntry.jsdocTags.some((tag) => tag.name === 'publicApi')).toBeTrue();
|
||||
expect(functionEntry.implementation.description).toBe('');
|
||||
});
|
||||
|
||||
it('should prefer implementation docs over overload docs', () => {
|
||||
env.write(
|
||||
'index.ts',
|
||||
`
|
||||
/** Overload docs. */
|
||||
export function ident(value: boolean): boolean
|
||||
/**
|
||||
* Implementation docs.
|
||||
*
|
||||
* @publicApi
|
||||
*/
|
||||
export function ident(value: boolean|number): boolean|number {
|
||||
return value;
|
||||
}
|
||||
`,
|
||||
);
|
||||
|
||||
const docs = env.driveDocsExtraction('index.ts') as FunctionEntry[];
|
||||
const [functionEntry] = docs;
|
||||
|
||||
expect(functionEntry.description).toContain('Implementation docs.');
|
||||
expect(functionEntry.rawComment).toContain('Implementation docs.');
|
||||
expect(functionEntry.jsdocTags.some((tag) => tag.name === 'publicApi')).toBeTrue();
|
||||
});
|
||||
|
||||
it('should extract function generics', () => {
|
||||
env.write(
|
||||
'index.ts',
|
||||
|
|
|
|||
Loading…
Reference in a new issue