From 34ae8a309f8d0a45a58e4b1da2e04b07a4705c95 Mon Sep 17 00:00:00 2001 From: Colin Rotherham Date: Thu, 20 Jul 2023 07:55:58 +0100 Subject: [PATCH] Enable ESLint JSDoc checks --- .eslintrc.js | 42 +++++++++++++- package-lock.json | 143 +++++++++++++++++++++++++++++++++++++++++++++- package.json | 1 + src/.eslintrc.js | 22 ++++++- 4 files changed, 203 insertions(+), 5 deletions(-) diff --git a/.eslintrc.js b/.eslintrc.js index f38c1f765d..28778ea0e3 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -13,6 +13,7 @@ module.exports = { extends: [ 'eslint:recommended', 'plugin:import/recommended', + 'plugin:jsdoc/recommended-typescript-flavor', 'plugin:n/recommended', 'plugin:promise/recommended', 'prettier' @@ -27,7 +28,7 @@ module.exports = { parserOptions: { ecmaVersion: 'latest' }, - plugins: ['import', 'n', 'promise'], + plugins: ['import', 'jsdoc', 'n', 'promise'], rules: { // Check import or require statements are A-Z ordered 'import/order': [ @@ -38,9 +39,48 @@ module.exports = { } ], + // JSDoc blocks are optional by default + 'jsdoc/require-jsdoc': 'off', + + // Check for valid formatting + 'jsdoc/check-line-alignment': [ + 'warn', + 'never', + { + wrapIndent: ' ' + } + ], + + // Add unknown @jest-environment tag name + 'jsdoc/check-tag-names': [ + 'warn', + { + definedTags: ['jest-environment'] + } + ], + + // Require hyphens before param description + // Aligns with TSDoc style: https://tsdoc.org/pages/tags/param/ + 'jsdoc/require-hyphen-before-param-description': 'warn', + + // Maintain new line after description + 'jsdoc/tag-lines': [ + 'warn', + 'never', + { + startLines: 1 + } + ], + // Automatically use template strings 'no-useless-concat': 'error', 'prefer-template': 'error' + }, + settings: { + jsdoc: { + // Allows us to use type declarations that exist in our dependencies + mode: 'typescript' + } } }, { diff --git a/package-lock.json b/package-lock.json index 25f98c6599..a472c5083b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -36,6 +36,7 @@ "eslint-config-prettier": "^9.0.0", "eslint-config-standard": "^17.0.0", "eslint-plugin-import": "^2.29.0", + "eslint-plugin-jsdoc": "^46.9.0", "eslint-plugin-markdown": "^3.0.1", "eslint-plugin-n": "^16.3.1", "eslint-plugin-promise": "^6.1.1", @@ -2138,6 +2139,20 @@ "postcss-selector-parser": "^6.0.13" } }, + "node_modules/@es-joy/jsdoccomment": { + "version": "0.41.0", + "resolved": "https://registry.npmjs.org/@es-joy/jsdoccomment/-/jsdoccomment-0.41.0.tgz", + "integrity": "sha512-aKUhyn1QI5Ksbqcr3fFJj16p99QdjUxXAEuFst1Z47DRyoiMwivIH9MV/ARcJOCXVjPfjITciej8ZD2O/6qUmw==", + "dev": true, + "dependencies": { + "comment-parser": "1.4.1", + "esquery": "^1.5.0", + "jsdoc-type-pratt-parser": "~4.0.0" + }, + "engines": { + "node": ">=16" + } + }, "node_modules/@eslint-community/eslint-utils": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", @@ -3881,6 +3896,15 @@ "node": ">= 8" } }, + "node_modules/are-docs-informative": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/are-docs-informative/-/are-docs-informative-0.0.2.tgz", + "integrity": "sha512-ixiS0nLNNG5jNQzgZJNoUpBKdo9yTYZMGJ+QgT2jmjR7G7+QHRCc4v6LQ3NgE7EBJq+o0ams3waJwkrlBom8Ig==", + "dev": true, + "engines": { + "node": ">=14" + } + }, "node_modules/arg": { "version": "5.0.2", "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz", @@ -5631,6 +5655,15 @@ "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", "dev": true }, + "node_modules/comment-parser": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/comment-parser/-/comment-parser-1.4.1.tgz", + "integrity": "sha512-buhp5kePrmda3vhc5B9t7pUQXAb2Tnd0qgpkIhPhkHXxJpiPJ11H0ZEU0oBpJ2QztSbzG/ZxMj/CHsYJqRHmyg==", + "dev": true, + "engines": { + "node": ">= 12.0.0" + } + }, "node_modules/common-path-prefix": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/common-path-prefix/-/common-path-prefix-1.0.0.tgz", @@ -7117,6 +7150,95 @@ "semver": "bin/semver.js" } }, + "node_modules/eslint-plugin-jsdoc": { + "version": "46.9.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-46.9.0.tgz", + "integrity": "sha512-UQuEtbqLNkPf5Nr/6PPRCtr9xypXY+g8y/Q7gPa0YK7eDhh0y2lWprXRnaYbW7ACgIUvpDKy9X2bZqxtGzBG9Q==", + "dev": true, + "dependencies": { + "@es-joy/jsdoccomment": "~0.41.0", + "are-docs-informative": "^0.0.2", + "comment-parser": "1.4.1", + "debug": "^4.3.4", + "escape-string-regexp": "^4.0.0", + "esquery": "^1.5.0", + "is-builtin-module": "^3.2.1", + "semver": "^7.5.4", + "spdx-expression-parse": "^3.0.1" + }, + "engines": { + "node": ">=16" + }, + "peerDependencies": { + "eslint": "^7.0.0 || ^8.0.0" + } + }, + "node_modules/eslint-plugin-jsdoc/node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/eslint-plugin-jsdoc/node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint-plugin-jsdoc/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/eslint-plugin-jsdoc/node_modules/semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/eslint-plugin-jsdoc/node_modules/spdx-expression-parse": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", + "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", + "dev": true, + "dependencies": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/eslint-plugin-jsdoc/node_modules/spdx-license-ids": { + "version": "3.0.16", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.16.tgz", + "integrity": "sha512-eWN+LnM3GR6gPu35WxNgbGl8rmY1AEmoMDvL/QD6zYmPWgywxWqJWNdLGT+ke8dKNWrcYgYjPpG5gbTfghP8rw==", + "dev": true + }, "node_modules/eslint-plugin-markdown": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/eslint-plugin-markdown/-/eslint-plugin-markdown-3.0.1.tgz", @@ -7487,9 +7609,9 @@ "dev": true }, "node_modules/esquery": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.2.tgz", - "integrity": "sha512-JVSoLdTlTDkmjFmab7H/9SL9qGSyjElT3myyKp7krqjVFQCDLmj1QFaCLRFBszBKI0XVZaiiXvuPIX3ZwHe1Ng==", + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", + "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", "dev": true, "dependencies": { "estraverse": "^5.1.0" @@ -10680,6 +10802,15 @@ "integrity": "sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg==", "dev": true }, + "node_modules/jsdoc-type-pratt-parser": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsdoc-type-pratt-parser/-/jsdoc-type-pratt-parser-4.0.0.tgz", + "integrity": "sha512-YtOli5Cmzy3q4dP26GraSOeAhqecewG04hoO8DY56CH4KJ9Fvv5qKWUCCo3HZob7esJQHCv6/+bnTy72xZZaVQ==", + "dev": true, + "engines": { + "node": ">=12.0.0" + } + }, "node_modules/jsdom": { "version": "20.0.3", "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-20.0.3.tgz", @@ -15075,6 +15206,12 @@ "spdx-license-ids": "^1.0.2" } }, + "node_modules/spdx-exceptions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz", + "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==", + "dev": true + }, "node_modules/spdx-expression-parse": { "version": "1.0.4", "dev": true, diff --git a/package.json b/package.json index 78283c8258..f93c78c9fc 100644 --- a/package.json +++ b/package.json @@ -57,6 +57,7 @@ "eslint-config-prettier": "^9.0.0", "eslint-config-standard": "^17.0.0", "eslint-plugin-import": "^2.29.0", + "eslint-plugin-jsdoc": "^46.9.0", "eslint-plugin-markdown": "^3.0.1", "eslint-plugin-n": "^16.3.1", "eslint-plugin-promise": "^6.1.1", diff --git a/src/.eslintrc.js b/src/.eslintrc.js index fa40c0a7b5..c60dddd088 100644 --- a/src/.eslintrc.js +++ b/src/.eslintrc.js @@ -11,7 +11,27 @@ module.exports = { // Note: Allow ES2015 for import/export syntax ecmaVersion: '2015' }, - plugins: ['es-x'] + plugins: ['es-x'], + rules: { + // JSDoc blocks are mandatory in source code + 'jsdoc/require-jsdoc': [ + 'error', + { + enableFixer: false, + require: { + ClassDeclaration: true, + ClassExpression: true, + FunctionExpression: true, + MethodDefinition: true + } + } + ], + + // JSDoc @param required in (mandatory) blocks but + // @param description is necessary in source code + 'jsdoc/require-param-description': 'warn', + 'jsdoc/require-param': 'error' + } } ] }