chore: JSDoc checker (#4618)

* chore: JSDoc checker

* work

* fix
This commit is contained in:
Asher Gomez 2024-04-22 17:07:34 +10:00 committed by GitHub
parent e1a0275450
commit ac5723de73
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
9 changed files with 127 additions and 4 deletions

View File

@ -8,7 +8,7 @@
* ```
*/
import { doc } from "deno_doc";
import { doc } from "deno_doc/mod.ts";
import { walk } from "../fs/walk.ts";
import { toFileUrl } from "../path/to_file_url.ts";

117
_tools/check_docs.ts Normal file
View File

@ -0,0 +1,117 @@
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
/**
* This script checks that all exported functions have JSDoc comments with
* `@param`, `@return`, and `@example` tags, according to the contributing
* guidelines.
*
* @see {@link https://github.com/denoland/deno_std/blob/main/.github/CONTRIBUTING.md#documentation}
*
* TODO(iuioiua): Add support for classes and methods.
*/
import { doc } from "deno_doc/mod.ts";
import type {
DocNodeBase,
DocNodeFunction,
JsDocTag,
} from "deno_doc/types.d.ts";
const ENTRY_POINTS = [
"../bytes/mod.ts",
"../datetime/mod.ts",
] as const;
class ValidationError extends Error {
constructor(message: string, document: DocNodeBase) {
super(message, {
cause: `${document.location.filename}:${document.location.line}`,
});
this.name = this.constructor.name;
}
}
function assert(
condition: boolean,
message: string,
document: DocNodeBase,
): asserts condition {
if (!condition) {
throw new ValidationError(message, document);
}
}
function isFunctionDoc(document: DocNodeBase): document is DocNodeFunction {
return document.kind === "function";
}
function isExported(document: DocNodeBase) {
return document.declarationKind === "export";
}
function assertHasTag(tags: JsDocTag[], kind: string, document: DocNodeBase) {
const tag = tags.find((tag) => tag.kind === kind);
assert(tag !== undefined, `Symbol must have a @${kind} tag`, document);
assert(
// @ts-ignore doc is defined
tag.doc !== undefined,
`@${kind} tag must have a description`,
document,
);
}
function assertHasParamTag(
tags: JsDocTag[],
param: string,
document: DocNodeBase,
) {
const tag = tags.find((tag) => tag.kind === "param" && tag.name === param);
assert(
tag !== undefined,
`Symbol must have a @param tag for ${param}`,
document,
);
assert(
// @ts-ignore doc is defined
tag.doc !== undefined,
`@param tag for ${param} must have a description`,
document,
);
}
function assertFunctionDocs(document: DocNodeFunction) {
assert(
document.jsDoc !== undefined,
"Symbol must have a JSDoc block",
document,
);
const { tags } = document.jsDoc;
assert(tags !== undefined, "JSDoc block must have tags", document);
for (const param of document.functionDef.params) {
if (param.kind === "identifier") {
assertHasParamTag(tags, param.name, document);
}
if (param.kind === "assign") {
// @ts-ignore Trust me
assertHasParamTag(tags, param.left.name, document);
}
}
assertHasTag(tags, "return", document);
assertHasTag(tags, "example", document);
}
async function checkDocs(specifier: string) {
const docs = await doc(specifier);
docs.filter(isExported)
.forEach((document) => {
if (isFunctionDoc(document)) {
assertFunctionDocs(document);
}
});
}
const promises = [];
for (const entry of ENTRY_POINTS) {
const { href } = new URL(entry, import.meta.url);
promises.push(checkDocs(href));
}
await Promise.all(promises);

View File

@ -5,6 +5,7 @@
* Concatenate an array of byte slices into a single slice.
*
* @param buffers Array of byte slices to concatenate.
* @returns Hello
*
* @example Basic usage
* ```ts

View File

@ -12,6 +12,7 @@
* @param dst Destination array to copy to.
* @param offset Offset in the destination array to start copying to. Defaults
* to 0.
* @returns Number of bytes copied.
*
* @example Basic usage
* ```ts

View File

@ -14,6 +14,8 @@
* @param needle Needle array to check for.
* @param start Start index in the source array to begin the search. Defaults to
* 0.
* @returns Index of the first occurrence of the needle array in the source
* array, or -1 if it is not present.
*
* @example Basic usage
* ```ts

View File

@ -11,6 +11,8 @@
* @param needle Needle array to check for.
* @param start Start index in the source array to begin the search. Defaults to
* the end of the array.
* @returns Index of the last occurrence of the needle array in the source
* array, or -1 if it is not present.
*
* @example Basic usage
* ```ts

View File

@ -10,7 +10,6 @@ import { copy } from "./copy.ts";
* @param count Number of times to repeat the source array.
* @returns A new byte slice composed of `count` repetitions of the `source`
* array.
* @throws {RangeError} If `count` is a negative or not an integer.
*
* @example Basic usage
* ```ts

View File

@ -45,6 +45,7 @@ function calculateMonthsDifference(from: Date, to: Date): number {
* @param from Year to calculate difference from.
* @param to Year to calculate difference to.
* @param options Options such as units to calculate difference in.
* @returns The difference of the 2 given dates in various units.
*
* @example Basic usage
* ```ts

View File

@ -8,7 +8,7 @@
"imports": {
"https://deno.land/std@$STD_VERSION/": "./",
"@deno/graph": "jsr:@deno/graph@^0.70",
"deno_doc": "https://deno.land/x/deno_doc@0.123.1/mod.ts",
"deno_doc/": "https://deno.land/x/deno_doc@0.123.1/",
"npm:/typescript": "npm:typescript@5.4.4",
"automation/": "https://raw.githubusercontent.com/denoland/automation/0.10.0/"
},
@ -22,7 +22,7 @@
"lint:circular": "deno run --allow-env --allow-read --allow-net=deno.land,jsr.io ./_tools/check_circular_package_dependencies.ts",
"lint:mod-exports": "deno run --allow-env --allow-read ./_tools/check_mod_exports.ts",
"lint:tools-types": "deno check _tools/*.ts",
"lint:docs": "deno doc --lint bytes/mod.ts datetime/mod.ts url/mod.ts",
"lint:docs": "deno run -A _tools/check_docs.ts && deno doc --lint bytes/mod.ts datetime/mod.ts url/mod.ts",
"lint": "deno lint && deno task fmt:licence-headers --check && deno task lint:deprecations && deno task lint:doc-imports && deno task lint:circular && deno task lint:tools-types && deno task lint:mod-exports && deno task lint:docs",
"typos": "typos -c ./.github/workflows/typos.toml",
"build:crypto": "deno task --cwd crypto/_wasm wasmbuild",