summaryrefslogtreecommitdiff
path: root/tools/jsdoc_checker.js
diff options
context:
space:
mode:
authorLeo Kettmeir <crowlkats@toaxl.com>2024-04-26 09:04:29 -0700
committerGitHub <noreply@github.com>2024-04-26 09:04:29 -0700
commitc5193556242117737fc3ba95ee3692b7831ca04a (patch)
tree914870befca84cc3bd928f5a0c3f6c39ed281fbd /tools/jsdoc_checker.js
parent0b0af5c635872132d1c727f13ca05aa9be3d1c3a (diff)
feat(ci): category & unstable tags checker (#23568)
Diffstat (limited to 'tools/jsdoc_checker.js')
-rw-r--r--tools/jsdoc_checker.js92
1 files changed, 92 insertions, 0 deletions
diff --git a/tools/jsdoc_checker.js b/tools/jsdoc_checker.js
new file mode 100644
index 000000000..733790c4e
--- /dev/null
+++ b/tools/jsdoc_checker.js
@@ -0,0 +1,92 @@
+#!/usr/bin/env -S deno run --allow-read --allow-env --allow-sys
+// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
+import { Node, Project, ts } from "npm:ts-morph@22.0.0";
+import { join, ROOT_PATH } from "./util.js";
+
+const libs = [
+ join(ROOT_PATH, "ext/cache/lib.deno_cache.d.ts"),
+ join(ROOT_PATH, "ext/console/lib.deno_console.d.ts"),
+ join(ROOT_PATH, "ext/url/lib.deno_url.d.ts"),
+ join(ROOT_PATH, "ext/web/lib.deno_web.d.ts"),
+ join(ROOT_PATH, "ext/fetch/lib.deno_fetch.d.ts"),
+ join(ROOT_PATH, "ext/websocket/lib.deno_websocket.d.ts"),
+ join(ROOT_PATH, "ext/webstorage/lib.deno_webstorage.d.ts"),
+ join(ROOT_PATH, "ext/canvas/lib.deno_canvas.d.ts"),
+ join(ROOT_PATH, "ext/crypto/lib.deno_crypto.d.ts"),
+ join(ROOT_PATH, "ext/net/lib.deno_net.d.ts"),
+ join(ROOT_PATH, "cli/tsc/dts/lib.deno.ns.d.ts"),
+ join(ROOT_PATH, "cli/tsc/dts/lib.deno.shared_globals.d.ts"),
+ join(ROOT_PATH, "cli/tsc/dts/lib.deno.window.d.ts"),
+];
+
+const unstableLibs = [
+ join(ROOT_PATH, "ext/broadcast_channel/lib.deno_broadcast_channel.d.ts"),
+ join(ROOT_PATH, "cli/tsc/dts/lib.deno_webgpu.d.ts"),
+ join(ROOT_PATH, "cli/tsc/dts/lib.deno.unstable.d.ts"),
+];
+
+const errors = [];
+
+const project = new Project();
+project.addSourceFilesAtPaths(libs);
+const unstableFiles = project.addSourceFilesAtPaths(unstableLibs);
+
+for (const file of project.getSourceFiles()) {
+ for (
+ const node of file.getDescendants().filter((descendant) =>
+ Node.isExportable(descendant)
+ )
+ ) {
+ if (
+ node.getKind() === ts.SyntaxKind.ModuleDeclaration &&
+ node.getName() === "Deno"
+ ) {
+ continue;
+ }
+
+ const parent = node.getFirstAncestorByKind(ts.SyntaxKind.ModuleDeclaration);
+
+ if (parent) {
+ if (!node.isExported()) {
+ errors.push(getErrorPrefix(node) + "export keyword");
+ continue;
+ }
+ } else if (!node.hasDeclareKeyword()) {
+ errors.push(getErrorPrefix(node) + "declare keyword");
+ continue;
+ }
+
+ const jsDoc = node.getFirstChildIfKind(ts.SyntaxKind.JSDoc);
+ if (!jsDoc) {
+ errors.push(getErrorPrefix(node) + "JSDoc comment");
+ continue;
+ }
+
+ const tags = jsDoc.getTags();
+
+ if (!tags.find((tag) => tag.getTagName() === "category")) {
+ errors.push(getErrorPrefix(node) + "JSDoc @category tag");
+ continue;
+ }
+
+ if (unstableFiles.includes(file)) {
+ const tagsTag = tags.find((tag) => tag.getTagName() === "tags");
+ if (
+ !(tagsTag?.getComment() &&
+ tagsTag.getCommentText().includes("unstable"))
+ ) {
+ errors.push(
+ getErrorPrefix(node) + "JSDoc @tags tag with value 'unstable'",
+ );
+ }
+ }
+ }
+}
+
+if (errors.length > 0) {
+ throw new AggregateError(errors);
+}
+
+function getErrorPrefix(node) {
+ return `Symbol at file://${node.getSourceFile().getFilePath()}:${node.getStartLineNumber()} is missing a `;
+}