diff options
author | Leo Kettmeir <crowlkats@toaxl.com> | 2024-04-26 09:04:29 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-04-26 09:04:29 -0700 |
commit | c5193556242117737fc3ba95ee3692b7831ca04a (patch) | |
tree | 914870befca84cc3bd928f5a0c3f6c39ed281fbd /tools | |
parent | 0b0af5c635872132d1c727f13ca05aa9be3d1c3a (diff) |
feat(ci): category & unstable tags checker (#23568)
Diffstat (limited to 'tools')
-rw-r--r-- | tools/jsdoc_checker.js | 92 |
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 `; +} |