Skip to content

Commit

Permalink
docs: check and improve handling of duplicate tags (#2444)
Browse files Browse the repository at this point in the history
  • Loading branch information
ST-DDT committed Dec 3, 2023
1 parent 9dd57d7 commit 505f659
Show file tree
Hide file tree
Showing 5 changed files with 99 additions and 37 deletions.
44 changes: 38 additions & 6 deletions scripts/apidoc/typedoc.ts
Expand Up @@ -219,7 +219,40 @@ export function extractTagContent(
reflection?: CommentHolder,
tagProcessor: (tag: CommentTag) => string[] = joinTagContent
): string[] {
return reflection?.comment?.getTags(tag).flatMap(tagProcessor) ?? [];
const tags =
reflection?.comment
?.getTags(tag)
.flatMap(tagProcessor)
.map((tag) => tag.trim()) ?? [];
if (tags.some((tag) => tag.length === 0)) {
throw new Error(`Expected non-empty ${tag} tag.`);
}

return tags;
}

/**
* Extracts the text (md) from a single jsdoc tag.
*
* @param tag The tag to extract the text from.
* @param reflection The reflection to extract the text from.
* @param tagProcessor The function used to extract the text from the tag.
*
* @throws If there are multiple tags of that type.
*/
function extractSingleTagContent(
tag: `@${string}`,
reflection?: CommentHolder,
tagProcessor: (tag: CommentTag) => string[] = joinTagContent
): string | undefined {
const tags = extractTagContent(tag, reflection, tagProcessor);
if (tags.length === 0) {
return undefined;
} else if (tags.length === 1) {
return tags[0];
}

throw new Error(`Expected 1 ${tag} tag, but got ${tags.length}.`);
}

/**
Expand Down Expand Up @@ -358,8 +391,7 @@ export function joinTagParts(parts?: CommentDisplayPart[]): string | undefined {
export function extractDeprecated(
reflection?: CommentHolder
): string | undefined {
const deprecated = extractTagContent('@deprecated', reflection).join().trim();
return deprecated.length === 0 ? undefined : deprecated;
return extractSingleTagContent('@deprecated', reflection);
}

/**
Expand All @@ -370,8 +402,8 @@ export function extractDeprecated(
* @returns The message explaining the conditions when this method throws. Or `undefined` if it does not throw.
*/
export function extractThrows(reflection?: CommentHolder): string | undefined {
const throws = extractTagContent('@throws', reflection).join().trim();
return throws.length === 0 ? undefined : throws;
const content = extractTagContent('@throws', reflection).join('\n');
return content.length === 0 ? undefined : content;
}

/**
Expand All @@ -382,5 +414,5 @@ export function extractThrows(reflection?: CommentHolder): string | undefined {
* @returns The contents of the `@since` tag.
*/
export function extractSince(reflection: CommentHolder): string {
return extractTagContent('@since', reflection).join().trim();
return extractSingleTagContent('@since', reflection) || MISSING_DESCRIPTION;
}
4 changes: 2 additions & 2 deletions src/modules/helpers/index.ts
Expand Up @@ -417,8 +417,8 @@ export class SimpleHelpersModule extends SimpleModuleBase {
*
* @param pattern The template string/RegExp to generate a matching string for.
*
* @throws If min value is more than max value in quantifier. e.g. `#{10,5}`
* @throws If invalid quantifier symbol is passed in.
* @throws If min value is more than max value in quantifier, e.g. `#{10,5}`.
* @throws If an invalid quantifier symbol is passed in.
*
* @example
* faker.helpers.fromRegExp('#{5}') // '#####'
Expand Down
73 changes: 46 additions & 27 deletions test/scripts/apidoc/__snapshots__/signature.spec.ts.snap
Expand Up @@ -42,8 +42,8 @@ exports[`signature > analyzeSignature() > complexArrayParameter 1`] = `
],
"returns": "T",
"seeAlsos": [],
"since": "",
"sourcePath": "test/scripts/apidoc/signature.example.ts#L367",
"since": "Missing",
"sourcePath": "test/scripts/apidoc/signature.example.ts#L377",
"throws": undefined,
}
`;
Expand All @@ -67,7 +67,7 @@ exports[`signature > analyzeSignature() > defaultBooleanParamMethod 1`] = `
],
"returns": "number",
"seeAlsos": [],
"since": "",
"since": "Missing",
"sourcePath": "test/scripts/apidoc/signature.example.ts#L105",
"throws": undefined,
}
Expand All @@ -84,6 +84,7 @@ exports[`signature > analyzeSignature() > expected and actual methods are equal
"methodWithExample",
"methodWithMultipleSeeMarkers",
"methodWithMultipleSeeMarkersAndBackticks",
"methodWithMultipleThrows",
"methodWithSinceMarker",
"methodWithThrows",
"multiParamMethod",
Expand Down Expand Up @@ -118,7 +119,7 @@ exports[`signature > analyzeSignature() > functionParamMethod 1`] = `
],
"returns": "number",
"seeAlsos": [],
"since": "",
"since": "Missing",
"sourcePath": "test/scripts/apidoc/signature.example.ts#L125",
"throws": undefined,
}
Expand Down Expand Up @@ -178,7 +179,7 @@ exports[`signature > analyzeSignature() > literalUnionParamMethod 1`] = `
],
"returns": "string",
"seeAlsos": [],
"since": "",
"since": "Missing",
"sourcePath": "test/scripts/apidoc/signature.example.ts#L159",
"throws": undefined,
}
Expand All @@ -198,7 +199,7 @@ exports[`signature > analyzeSignature() > methodWithDeprecated 1`] = `
"seeAlsos": [
"test.apidoc.methodWithExample()",
],
"since": "",
"since": "Missing",
"sourcePath": "test/scripts/apidoc/signature.example.ts#L287",
"throws": undefined,
}
Expand Down Expand Up @@ -250,8 +251,8 @@ exports[`signature > analyzeSignature() > methodWithDeprecatedOption 1`] = `
],
"returns": "number",
"seeAlsos": [],
"since": "",
"sourcePath": "test/scripts/apidoc/signature.example.ts#L308",
"since": "Missing",
"sourcePath": "test/scripts/apidoc/signature.example.ts#L318",
"throws": undefined,
}
`;
Expand All @@ -268,7 +269,7 @@ exports[`signature > analyzeSignature() > methodWithExample 1`] = `
"parameters": [],
"returns": "number",
"seeAlsos": [],
"since": "",
"since": "Missing",
"sourcePath": "test/scripts/apidoc/signature.example.ts#L276",
"throws": undefined,
}
Expand All @@ -288,8 +289,8 @@ exports[`signature > analyzeSignature() > methodWithMultipleSeeMarkers 1`] = `
"test.apidoc.methodWithExample()",
"test.apidoc.methodWithDeprecated()",
],
"since": "",
"sourcePath": "test/scripts/apidoc/signature.example.ts#L335",
"since": "Missing",
"sourcePath": "test/scripts/apidoc/signature.example.ts#L345",
"throws": undefined,
}
`;
Expand All @@ -308,12 +309,30 @@ exports[`signature > analyzeSignature() > methodWithMultipleSeeMarkersAndBacktic
"test.apidoc.methodWithExample() with parameter <code>foo</code>.",
"test.apidoc.methodWithDeprecated() with parameter <code>bar</code> and <code>baz</code>.",
],
"since": "",
"sourcePath": "test/scripts/apidoc/signature.example.ts#L345",
"since": "Missing",
"sourcePath": "test/scripts/apidoc/signature.example.ts#L355",
"throws": undefined,
}
`;
exports[`signature > analyzeSignature() > methodWithMultipleThrows 1`] = `
{
"deprecated": undefined,
"description": "<p>Test with multiple throws.</p>
",
"examples": "<div class=\\"language-ts\\"><button title=\\"Copy Code\\" class=\\"copy\\"></button><span class=\\"lang\\">ts</span><pre v-pre class=\\"shiki material-theme-palenight\\"><code><span class=\\"line\\"><span style=\\"color:#82AAFF\\">methodWithMultipleThrows</span><span style=\\"color:#BABED8\\">(): number</span></span></code></pre>
</div>",
"name": "methodWithMultipleThrows",
"parameters": [],
"returns": "number",
"seeAlsos": [],
"since": "Missing",
"sourcePath": "test/scripts/apidoc/signature.example.ts#L306",
"throws": "First error case.
Another error case.",
}
`;
exports[`signature > analyzeSignature() > methodWithSinceMarker 1`] = `
{
"deprecated": undefined,
Expand All @@ -326,25 +345,25 @@ exports[`signature > analyzeSignature() > methodWithSinceMarker 1`] = `
"returns": "number",
"seeAlsos": [],
"since": "1.0.0",
"sourcePath": "test/scripts/apidoc/signature.example.ts#L354",
"sourcePath": "test/scripts/apidoc/signature.example.ts#L364",
"throws": undefined,
}
`;
exports[`signature > analyzeSignature() > methodWithThrows 1`] = `
{
"deprecated": undefined,
"description": "<p>Test with throws</p>
"description": "<p>Test with throws.</p>
",
"examples": "<div class=\\"language-ts\\"><button title=\\"Copy Code\\" class=\\"copy\\"></button><span class=\\"lang\\">ts</span><pre v-pre class=\\"shiki material-theme-palenight\\"><code><span class=\\"line\\"><span style=\\"color:#82AAFF\\">methodWithThrows</span><span style=\\"color:#BABED8\\">(): number</span></span></code></pre>
</div>",
"name": "methodWithThrows",
"parameters": [],
"returns": "number",
"seeAlsos": [],
"since": "",
"since": "Missing",
"sourcePath": "test/scripts/apidoc/signature.example.ts#L296",
"throws": "a Faker error",
"throws": "Everytime.",
}
`;
Expand Down Expand Up @@ -381,7 +400,7 @@ exports[`signature > analyzeSignature() > multiParamMethod 1`] = `
],
"returns": "number",
"seeAlsos": [],
"since": "",
"since": "Missing",
"sourcePath": "test/scripts/apidoc/signature.example.ts#L116",
"throws": undefined,
}
Expand All @@ -398,7 +417,7 @@ exports[`signature > analyzeSignature() > noParamMethod 1`] = `
"parameters": [],
"returns": "number",
"seeAlsos": [],
"since": "",
"since": "Missing",
"sourcePath": "test/scripts/apidoc/signature.example.ts#L78",
"throws": undefined,
}
Expand All @@ -423,7 +442,7 @@ exports[`signature > analyzeSignature() > optionalStringParamMethod 1`] = `
],
"returns": "number",
"seeAlsos": [],
"since": "",
"since": "Missing",
"sourcePath": "test/scripts/apidoc/signature.example.ts#L96",
"throws": undefined,
}
Expand Down Expand Up @@ -491,7 +510,7 @@ It also has a more complex description.</p>
],
"returns": "number",
"seeAlsos": [],
"since": "",
"since": "Missing",
"sourcePath": "test/scripts/apidoc/signature.example.ts#L226",
"throws": undefined,
}
Expand Down Expand Up @@ -530,7 +549,7 @@ exports[`signature > analyzeSignature() > optionsInterfaceParamMethodWithDefault
],
"returns": "number",
"seeAlsos": [],
"since": "",
"since": "Missing",
"sourcePath": "test/scripts/apidoc/signature.example.ts#L262",
"throws": undefined,
}
Expand Down Expand Up @@ -596,7 +615,7 @@ exports[`signature > analyzeSignature() > optionsParamMethod 1`] = `
],
"returns": "number",
"seeAlsos": [],
"since": "",
"since": "Missing",
"sourcePath": "test/scripts/apidoc/signature.example.ts#L196",
"throws": undefined,
}
Expand Down Expand Up @@ -635,7 +654,7 @@ exports[`signature > analyzeSignature() > optionsTypeParamMethodWithDefaults 1`]
],
"returns": "number",
"seeAlsos": [],
"since": "",
"since": "Missing",
"sourcePath": "test/scripts/apidoc/signature.example.ts#L244",
"throws": undefined,
}
Expand All @@ -660,7 +679,7 @@ exports[`signature > analyzeSignature() > recordParamMethod 1`] = `
],
"returns": "number",
"seeAlsos": [],
"since": "",
"since": "Missing",
"sourcePath": "test/scripts/apidoc/signature.example.ts#L182",
"throws": undefined,
}
Expand All @@ -685,7 +704,7 @@ exports[`signature > analyzeSignature() > requiredNumberParamMethod 1`] = `
],
"returns": "number",
"seeAlsos": [],
"since": "",
"since": "Missing",
"sourcePath": "test/scripts/apidoc/signature.example.ts#L87",
"throws": undefined,
}
Expand Down Expand Up @@ -742,7 +761,7 @@ exports[`signature > analyzeSignature() > stringUnionParamMethod 1`] = `
],
"returns": "string",
"seeAlsos": [],
"since": "",
"since": "Missing",
"sourcePath": "test/scripts/apidoc/signature.example.ts#L138",
"throws": undefined,
}
Expand Down
14 changes: 12 additions & 2 deletions test/scripts/apidoc/signature.example.ts
Expand Up @@ -289,14 +289,24 @@ export class SignatureTest {
}

/**
* Test with throws
* Test with throws.
*
* @throws a Faker error
* @throws Everytime.
*/
methodWithThrows(): number {
throw new FakerError('Test error');
}

/**
* Test with multiple throws.
*
* @throws First error case.
* @throws Another error case.
*/
methodWithMultipleThrows(): number {
throw new FakerError('Another test error');
}

/**
* Test with deprecated option.
*
Expand Down
1 change: 1 addition & 0 deletions test/scripts/apidoc/verify-jsdoc-tags.spec.ts
Expand Up @@ -300,6 +300,7 @@ describe('verify JSDoc tags', () => {
it('verify @since tag', () => {
const since = extractSince(signature);
expect(since, '@since to be present').toBeTruthy();
expect(since).not.toBe(MISSING_DESCRIPTION);
expect(since, '@since to be a valid semver').toSatisfy(
validator.isSemVer
);
Expand Down

0 comments on commit 505f659

Please sign in to comment.