From 3c718983dce640178989cb81407dd29c76ed08e1 Mon Sep 17 00:00:00 2001 From: Jake Bailey <5341706+jakebailey@users.noreply.github.com> Date: Mon, 24 Jul 2023 12:58:45 -0700 Subject: [PATCH 1/3] Enable eslint rule @typescript-eslint/no-unused-vars, disable compiler rule --- .eslintrc.json | 7 +- package-lock.json | 197 +++++++++++++++++++++++++++++ package.json | 1 + src/compiler/core.ts | 6 +- src/compiler/emitter.ts | 1 + src/compiler/moduleNameResolver.ts | 2 +- src/compiler/watchPublic.ts | 14 +- src/server/editorServices.ts | 1 + src/tsconfig-base.json | 2 - 9 files changed, 216 insertions(+), 15 deletions(-) diff --git a/.eslintrc.json b/.eslintrc.json index 30e6bb6ef2f65..26ea9ec19f431 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -16,7 +16,7 @@ "plugin:@typescript-eslint/stylistic" ], "plugins": [ - "@typescript-eslint", "no-null", "eslint-plugin-local", "simple-import-sort" + "@typescript-eslint", "no-null", "eslint-plugin-local", "simple-import-sort", "jsdoc" ], "ignorePatterns": [ "**/node_modules/**", @@ -70,6 +70,7 @@ { "selector": "enumMember", "format": ["camelCase", "PascalCase"], "leadingUnderscore": "allow", "filter": { "regex": "^[A-Za-z]+_[A-Za-z]+$", "match": false } }, { "selector": "property", "format": null } ], + "@typescript-eslint/no-unused-vars": ["error", { "argsIgnorePattern": "^_", "varsIgnorePattern": "^_" }], // Rules enabled in typescript-eslint configs that are not applicable here "@typescript-eslint/ban-ts-comment": "off", @@ -80,6 +81,9 @@ "@typescript-eslint/no-non-null-asserted-optional-chain": "off", "@typescript-eslint/no-var-requires": "off", + // Solely for marking things as used for the purposes of the no-unused-vars rule. + "jsdoc/no-undefined-types": ["error", { "disableReporting": true }], + // Todo: For each of these, investigate whether we want to enable them ✨ "@typescript-eslint/ban-types": "off", "no-case-declarations": "off", @@ -95,7 +99,6 @@ "@typescript-eslint/no-empty-function": "off", "@typescript-eslint/no-empty-interface": "off", "@typescript-eslint/no-explicit-any": "off", - "@typescript-eslint/no-unused-vars": "off", // Pending https://github.com/typescript-eslint/typescript-eslint/issues/4820 "@typescript-eslint/prefer-optional-chain": "off", diff --git a/package-lock.json b/package-lock.json index db331ab62fc54..93929a591a3ed 100644 --- a/package-lock.json +++ b/package-lock.json @@ -38,6 +38,7 @@ "esbuild": "^0.18.1", "eslint": "^8.22.0", "eslint-formatter-autolinkable-stylish": "^1.2.0", + "eslint-plugin-jsdoc": "^46.4.4", "eslint-plugin-local": "^1.0.0", "eslint-plugin-no-null": "^1.0.2", "eslint-plugin-simple-import-sort": "^10.0.0", @@ -75,6 +76,20 @@ "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", "dev": true }, + "node_modules/@es-joy/jsdoccomment": { + "version": "0.39.4", + "resolved": "https://registry.npmjs.org/@es-joy/jsdoccomment/-/jsdoccomment-0.39.4.tgz", + "integrity": "sha512-Jvw915fjqQct445+yron7Dufix9A+m9j1fCJYlCo1FWlRvTxa3pjJelxdSTdaLWcTwRU6vbL+NYjO4YuNIS5Qg==", + "dev": true, + "dependencies": { + "comment-parser": "1.3.1", + "esquery": "^1.5.0", + "jsdoc-type-pratt-parser": "~4.0.0" + }, + "engines": { + "node": ">=16" + } + }, "node_modules/@esbuild/android-arm": { "version": "0.18.16", "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.18.16.tgz", @@ -1182,6 +1197,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/argparse": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", @@ -1289,6 +1313,18 @@ "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", "dev": true }, + "node_modules/builtin-modules": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-3.3.0.tgz", + "integrity": "sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw==", + "dev": true, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/c8": { "version": "7.14.0", "resolved": "https://registry.npmjs.org/c8/-/c8-7.14.0.tgz", @@ -1543,6 +1579,15 @@ "node": ">=4" } }, + "node_modules/comment-parser": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/comment-parser/-/comment-parser-1.3.1.tgz", + "integrity": "sha512-B52sN2VNghyq5ofvUsqZjmk6YkihBX5vMSChmSK9v4ShjKf3Vk5Xcmgpw4o+iIgtrnM/u5FiMpz9VKb8lpBveA==", + "dev": true, + "engines": { + "node": ">= 12.0.0" + } + }, "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", @@ -1835,6 +1880,29 @@ "eslint": "^8.3.0" } }, + "node_modules/eslint-plugin-jsdoc": { + "version": "46.4.4", + "resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-46.4.4.tgz", + "integrity": "sha512-D8TGPOkq3bnzmYmA7Q6jdsW+Slx7CunhJk1tlouVq6wJjlP1p6eigZPvxFn7aufud/D66xBsNVMhkDQEuqumMg==", + "dev": true, + "dependencies": { + "@es-joy/jsdoccomment": "~0.39.4", + "are-docs-informative": "^0.0.2", + "comment-parser": "1.3.1", + "debug": "^4.3.4", + "escape-string-regexp": "^4.0.0", + "esquery": "^1.5.0", + "is-builtin-module": "^3.2.1", + "semver": "^7.5.1", + "spdx-expression-parse": "^3.0.1" + }, + "engines": { + "node": ">=16" + }, + "peerDependencies": { + "eslint": "^7.0.0 || ^8.0.0" + } + }, "node_modules/eslint-plugin-local": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/eslint-plugin-local/-/eslint-plugin-local-1.0.0.tgz", @@ -2494,6 +2562,21 @@ "node": ">=8" } }, + "node_modules/is-builtin-module": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-3.2.1.tgz", + "integrity": "sha512-BSLE3HnV2syZ0FK0iMA/yUGplUeMmNz4AW5fnTunbCIqZi4vG3WjJT9FHMy5D69xmAYBHXQhJdALdpwVxV501A==", + "dev": true, + "dependencies": { + "builtin-modules": "^3.3.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/is-extglob": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", @@ -2635,6 +2718,15 @@ "js-yaml": "bin/js-yaml.js" } }, + "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/json-schema-traverse": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", @@ -3490,6 +3582,28 @@ "source-map": "^0.6.0" } }, + "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": "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/spdx-license-ids": { + "version": "3.0.13", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.13.tgz", + "integrity": "sha512-XkD+zwiqXHikFZm4AX/7JSCXA98U5Db4AFd5XUg/+9UNtnH75+Z9KxtpYiJZx36mUDVOwH83pl7yvCer6ewM3w==", + "dev": true + }, "node_modules/string-width": { "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", @@ -3921,6 +4035,17 @@ "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", "dev": true }, + "@es-joy/jsdoccomment": { + "version": "0.39.4", + "resolved": "https://registry.npmjs.org/@es-joy/jsdoccomment/-/jsdoccomment-0.39.4.tgz", + "integrity": "sha512-Jvw915fjqQct445+yron7Dufix9A+m9j1fCJYlCo1FWlRvTxa3pjJelxdSTdaLWcTwRU6vbL+NYjO4YuNIS5Qg==", + "dev": true, + "requires": { + "comment-parser": "1.3.1", + "esquery": "^1.5.0", + "jsdoc-type-pratt-parser": "~4.0.0" + } + }, "@esbuild/android-arm": { "version": "0.18.16", "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.18.16.tgz", @@ -4626,6 +4751,12 @@ "picomatch": "^2.0.4" } }, + "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 + }, "argparse": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", @@ -4715,6 +4846,12 @@ "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", "dev": true }, + "builtin-modules": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-3.3.0.tgz", + "integrity": "sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw==", + "dev": true + }, "c8": { "version": "7.14.0", "resolved": "https://registry.npmjs.org/c8/-/c8-7.14.0.tgz", @@ -4906,6 +5043,12 @@ } } }, + "comment-parser": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/comment-parser/-/comment-parser-1.3.1.tgz", + "integrity": "sha512-B52sN2VNghyq5ofvUsqZjmk6YkihBX5vMSChmSK9v4ShjKf3Vk5Xcmgpw4o+iIgtrnM/u5FiMpz9VKb8lpBveA==", + "dev": true + }, "concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", @@ -5139,6 +5282,23 @@ "plur": "^4.0.0" } }, + "eslint-plugin-jsdoc": { + "version": "46.4.4", + "resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-46.4.4.tgz", + "integrity": "sha512-D8TGPOkq3bnzmYmA7Q6jdsW+Slx7CunhJk1tlouVq6wJjlP1p6eigZPvxFn7aufud/D66xBsNVMhkDQEuqumMg==", + "dev": true, + "requires": { + "@es-joy/jsdoccomment": "~0.39.4", + "are-docs-informative": "^0.0.2", + "comment-parser": "1.3.1", + "debug": "^4.3.4", + "escape-string-regexp": "^4.0.0", + "esquery": "^1.5.0", + "is-builtin-module": "^3.2.1", + "semver": "^7.5.1", + "spdx-expression-parse": "^3.0.1" + } + }, "eslint-plugin-local": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/eslint-plugin-local/-/eslint-plugin-local-1.0.0.tgz", @@ -5600,6 +5760,15 @@ "binary-extensions": "^2.0.0" } }, + "is-builtin-module": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-3.2.1.tgz", + "integrity": "sha512-BSLE3HnV2syZ0FK0iMA/yUGplUeMmNz4AW5fnTunbCIqZi4vG3WjJT9FHMy5D69xmAYBHXQhJdALdpwVxV501A==", + "dev": true, + "requires": { + "builtin-modules": "^3.3.0" + } + }, "is-extglob": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", @@ -5699,6 +5868,12 @@ "argparse": "^2.0.1" } }, + "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 + }, "json-schema-traverse": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", @@ -6290,6 +6465,28 @@ "source-map": "^0.6.0" } }, + "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 + }, + "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, + "requires": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-license-ids": { + "version": "3.0.13", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.13.tgz", + "integrity": "sha512-XkD+zwiqXHikFZm4AX/7JSCXA98U5Db4AFd5XUg/+9UNtnH75+Z9KxtpYiJZx36mUDVOwH83pl7yvCer6ewM3w==", + "dev": true + }, "string-width": { "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", diff --git a/package.json b/package.json index deec92a87bcd7..cdd4e7a84a8cd 100644 --- a/package.json +++ b/package.json @@ -64,6 +64,7 @@ "esbuild": "^0.18.1", "eslint": "^8.22.0", "eslint-formatter-autolinkable-stylish": "^1.2.0", + "eslint-plugin-jsdoc": "^46.4.4", "eslint-plugin-local": "^1.0.0", "eslint-plugin-no-null": "^1.0.2", "eslint-plugin-simple-import-sort": "^10.0.0", diff --git a/src/compiler/core.ts b/src/compiler/core.ts index 495cc2e3a700c..580215d1ad394 100644 --- a/src/compiler/core.ts +++ b/src/compiler/core.ts @@ -288,7 +288,7 @@ export function filter<T>(array: T[], f: (x: T) => boolean): T[]; /** @internal */ export function filter<T, U extends T>(array: readonly T[], f: (x: T) => x is U): readonly U[]; /** @internal */ -export function filter<T, U extends T>(array: readonly T[], f: (x: T) => boolean): readonly T[]; +export function filter<T>(array: readonly T[], f: (x: T) => boolean): readonly T[]; /** @internal */ export function filter<T, U extends T>(array: T[] | undefined, f: (x: T) => x is U): U[] | undefined; /** @internal */ @@ -296,7 +296,7 @@ export function filter<T>(array: T[] | undefined, f: (x: T) => boolean): T[] | u /** @internal */ export function filter<T, U extends T>(array: readonly T[] | undefined, f: (x: T) => x is U): readonly U[] | undefined; /** @internal */ -export function filter<T, U extends T>(array: readonly T[] | undefined, f: (x: T) => boolean): readonly T[] | undefined; +export function filter<T>(array: readonly T[] | undefined, f: (x: T) => boolean): readonly T[] | undefined; /** @internal */ export function filter<T>(array: readonly T[] | undefined, f: (x: T) => boolean): readonly T[] | undefined { if (array) { @@ -835,7 +835,7 @@ export function insertSorted<T>(array: SortedArray<T>, insert: T, compare: Compa } /** @internal */ -export function sortAndDeduplicate<T>(array: readonly string[]): SortedReadonlyArray<string>; +export function sortAndDeduplicate(array: readonly string[]): SortedReadonlyArray<string>; /** @internal */ export function sortAndDeduplicate<T>(array: readonly T[], comparer: Comparer<T>, equalityComparer?: EqualityComparer<T>): SortedReadonlyArray<T>; /** @internal */ diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index a58223868f8b0..94d5c1747cdec 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -4083,6 +4083,7 @@ export function createPrinter(printerOptions: PrinterOptions = {}, handlers: Pri writeSpace(); nextPos = emitTokenWithComment(SyntaxKind.AsKeyword, nextPos, writeKeyword, node); writeSpace(); + // eslint-disable-next-line @typescript-eslint/no-unused-vars nextPos = emitTokenWithComment(SyntaxKind.NamespaceKeyword, nextPos, writeKeyword, node); writeSpace(); emit(node.name); diff --git a/src/compiler/moduleNameResolver.ts b/src/compiler/moduleNameResolver.ts index 4538377dafd3d..7598ed836f64e 100644 --- a/src/compiler/moduleNameResolver.ts +++ b/src/compiler/moduleNameResolver.ts @@ -331,7 +331,7 @@ interface PackageJson extends PackageJsonPathFields { version?: string; } -function readPackageJsonField<TMatch, K extends MatchingKeys<PackageJson, string | undefined>>(jsonContent: PackageJson, fieldName: K, typeOfTag: "string", state: ModuleResolutionState): PackageJson[K] | undefined; +function readPackageJsonField<K extends MatchingKeys<PackageJson, string | undefined>>(jsonContent: PackageJson, fieldName: K, typeOfTag: "string", state: ModuleResolutionState): PackageJson[K] | undefined; function readPackageJsonField<K extends MatchingKeys<PackageJson, object | undefined>>(jsonContent: PackageJson, fieldName: K, typeOfTag: "object", state: ModuleResolutionState): PackageJson[K] | undefined; function readPackageJsonField<K extends keyof PackageJson>(jsonContent: PackageJson, fieldName: K, typeOfTag: "string" | "object", state: ModuleResolutionState): PackageJson[K] | undefined { if (!hasProperty(jsonContent, fieldName)) { diff --git a/src/compiler/watchPublic.ts b/src/compiler/watchPublic.ts index f5eb07f44dd62..c6ff74e2aafc6 100644 --- a/src/compiler/watchPublic.ts +++ b/src/compiler/watchPublic.ts @@ -249,18 +249,18 @@ export interface ProgramHost<T extends BuilderProgram> { * Returns the module resolution cache used by a provided `resolveModuleNames` implementation so that any non-name module resolution operations (eg, package.json lookup) can reuse it */ getModuleResolutionCache?(): ModuleResolutionCache | undefined; -} -/** - * Internal interface used to wire emit through same host - * - * @internal - */ -export interface ProgramHost<T extends BuilderProgram> { + + // Internal interface used to wire emit through same host + // TODO: GH#18217 Optional methods are frequently asserted + /** @internal */ createDirectory?(path: string): void; + /** @internal */ writeFile?(path: string, data: string, writeByteOrderMark?: boolean): void; // For testing + /** @internal */ storeFilesChangingSignatureDuringEmit?: boolean; + /** @internal */ now?(): Date; } diff --git a/src/server/editorServices.ts b/src/server/editorServices.ts index 3c53534bb7594..3e78b22ecede0 100644 --- a/src/server/editorServices.ts +++ b/src/server/editorServices.ts @@ -477,6 +477,7 @@ export function convertScriptKindName(scriptKindName: protocol.ScriptKindName) { /** @internal */ export function convertUserPreferences(preferences: protocol.UserPreferences): UserPreferences { + // eslint-disable-next-line @typescript-eslint/no-unused-vars const { lazyConfiguredProjectsFromExternalProject, ...userPreferences } = preferences; return userPreferences; } diff --git a/src/tsconfig-base.json b/src/tsconfig-base.json index 3b772f7d33f0f..34c76b9542b13 100644 --- a/src/tsconfig-base.json +++ b/src/tsconfig-base.json @@ -21,8 +21,6 @@ "useUnknownInCatchVariables": false, "noImplicitOverride": true, - "noUnusedLocals": true, - "noUnusedParameters": true, "allowUnusedLabels": false, "skipLibCheck": true, From 00f223742857a239d39c25880ec6585b039c7091 Mon Sep 17 00:00:00 2001 From: Jake Bailey <5341706+jakebailey@users.noreply.github.com> Date: Mon, 14 Aug 2023 11:39:53 -0700 Subject: [PATCH 2/3] Attempt to DIY the jsdoc stuff using a local plugin --- .eslintrc.json | 6 +- package-lock.json | 197 ------------------ package.json | 1 - .../eslint/rules/mark-jsdoc-types-used.cjs | 102 +++++++++ src/compiler/parser.ts | 1 + 5 files changed, 106 insertions(+), 201 deletions(-) create mode 100644 scripts/eslint/rules/mark-jsdoc-types-used.cjs diff --git a/.eslintrc.json b/.eslintrc.json index dfe38fee99ad8..a9514a1fa389e 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -16,7 +16,7 @@ "plugin:@typescript-eslint/stylistic" ], "plugins": [ - "@typescript-eslint", "no-null", "eslint-plugin-local", "simple-import-sort", "jsdoc" + "@typescript-eslint", "no-null", "eslint-plugin-local", "simple-import-sort" ], "ignorePatterns": [ "**/node_modules/**", @@ -90,8 +90,6 @@ "@typescript-eslint/no-non-null-asserted-optional-chain": "off", "@typescript-eslint/no-var-requires": "off", - // Solely for marking things as used for the purposes of the no-unused-vars rule. - "jsdoc/no-undefined-types": ["error", { "disableReporting": true }], "@typescript-eslint/no-empty-interface": "off", "@typescript-eslint/no-explicit-any": "off", "@typescript-eslint/ban-types": [ @@ -123,6 +121,8 @@ "local/debug-assert": "error", "local/no-keywords": "error", "local/jsdoc-format": "error", + // Solely for marking things as used for the purposes of the no-unused-vars rule. + "local/mark-jsdoc-types-used": "error", // eslint-plugin-no-null "no-null/no-null": "error", diff --git a/package-lock.json b/package-lock.json index 985c4abe33f57..de3c6fd1e757b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -38,7 +38,6 @@ "esbuild": "^0.19.0", "eslint": "^8.22.0", "eslint-formatter-autolinkable-stylish": "^1.2.0", - "eslint-plugin-jsdoc": "^46.4.4", "eslint-plugin-local": "^1.0.0", "eslint-plugin-no-null": "^1.0.2", "eslint-plugin-simple-import-sort": "^10.0.0", @@ -76,20 +75,6 @@ "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", "dev": true }, - "node_modules/@es-joy/jsdoccomment": { - "version": "0.39.4", - "resolved": "https://registry.npmjs.org/@es-joy/jsdoccomment/-/jsdoccomment-0.39.4.tgz", - "integrity": "sha512-Jvw915fjqQct445+yron7Dufix9A+m9j1fCJYlCo1FWlRvTxa3pjJelxdSTdaLWcTwRU6vbL+NYjO4YuNIS5Qg==", - "dev": true, - "dependencies": { - "comment-parser": "1.3.1", - "esquery": "^1.5.0", - "jsdoc-type-pratt-parser": "~4.0.0" - }, - "engines": { - "node": ">=16" - } - }, "node_modules/@esbuild/android-arm": { "version": "0.19.0", "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.19.0.tgz", @@ -1197,15 +1182,6 @@ "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/argparse": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", @@ -1313,18 +1289,6 @@ "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", "dev": true }, - "node_modules/builtin-modules": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-3.3.0.tgz", - "integrity": "sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw==", - "dev": true, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/c8": { "version": "7.14.0", "resolved": "https://registry.npmjs.org/c8/-/c8-7.14.0.tgz", @@ -1579,15 +1543,6 @@ "node": ">=4" } }, - "node_modules/comment-parser": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/comment-parser/-/comment-parser-1.3.1.tgz", - "integrity": "sha512-B52sN2VNghyq5ofvUsqZjmk6YkihBX5vMSChmSK9v4ShjKf3Vk5Xcmgpw4o+iIgtrnM/u5FiMpz9VKb8lpBveA==", - "dev": true, - "engines": { - "node": ">= 12.0.0" - } - }, "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", @@ -1880,29 +1835,6 @@ "eslint": "^8.3.0" } }, - "node_modules/eslint-plugin-jsdoc": { - "version": "46.4.4", - "resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-46.4.4.tgz", - "integrity": "sha512-D8TGPOkq3bnzmYmA7Q6jdsW+Slx7CunhJk1tlouVq6wJjlP1p6eigZPvxFn7aufud/D66xBsNVMhkDQEuqumMg==", - "dev": true, - "dependencies": { - "@es-joy/jsdoccomment": "~0.39.4", - "are-docs-informative": "^0.0.2", - "comment-parser": "1.3.1", - "debug": "^4.3.4", - "escape-string-regexp": "^4.0.0", - "esquery": "^1.5.0", - "is-builtin-module": "^3.2.1", - "semver": "^7.5.1", - "spdx-expression-parse": "^3.0.1" - }, - "engines": { - "node": ">=16" - }, - "peerDependencies": { - "eslint": "^7.0.0 || ^8.0.0" - } - }, "node_modules/eslint-plugin-local": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/eslint-plugin-local/-/eslint-plugin-local-1.0.0.tgz", @@ -2562,21 +2494,6 @@ "node": ">=8" } }, - "node_modules/is-builtin-module": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-3.2.1.tgz", - "integrity": "sha512-BSLE3HnV2syZ0FK0iMA/yUGplUeMmNz4AW5fnTunbCIqZi4vG3WjJT9FHMy5D69xmAYBHXQhJdALdpwVxV501A==", - "dev": true, - "dependencies": { - "builtin-modules": "^3.3.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/is-extglob": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", @@ -2718,15 +2635,6 @@ "js-yaml": "bin/js-yaml.js" } }, - "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/json-schema-traverse": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", @@ -3573,28 +3481,6 @@ "source-map": "^0.6.0" } }, - "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": "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/spdx-license-ids": { - "version": "3.0.13", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.13.tgz", - "integrity": "sha512-XkD+zwiqXHikFZm4AX/7JSCXA98U5Db4AFd5XUg/+9UNtnH75+Z9KxtpYiJZx36mUDVOwH83pl7yvCer6ewM3w==", - "dev": true - }, "node_modules/string-width": { "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", @@ -4026,17 +3912,6 @@ "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", "dev": true }, - "@es-joy/jsdoccomment": { - "version": "0.39.4", - "resolved": "https://registry.npmjs.org/@es-joy/jsdoccomment/-/jsdoccomment-0.39.4.tgz", - "integrity": "sha512-Jvw915fjqQct445+yron7Dufix9A+m9j1fCJYlCo1FWlRvTxa3pjJelxdSTdaLWcTwRU6vbL+NYjO4YuNIS5Qg==", - "dev": true, - "requires": { - "comment-parser": "1.3.1", - "esquery": "^1.5.0", - "jsdoc-type-pratt-parser": "~4.0.0" - } - }, "@esbuild/android-arm": { "version": "0.19.0", "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.19.0.tgz", @@ -4742,12 +4617,6 @@ "picomatch": "^2.0.4" } }, - "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 - }, "argparse": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", @@ -4837,12 +4706,6 @@ "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", "dev": true }, - "builtin-modules": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-3.3.0.tgz", - "integrity": "sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw==", - "dev": true - }, "c8": { "version": "7.14.0", "resolved": "https://registry.npmjs.org/c8/-/c8-7.14.0.tgz", @@ -5034,12 +4897,6 @@ } } }, - "comment-parser": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/comment-parser/-/comment-parser-1.3.1.tgz", - "integrity": "sha512-B52sN2VNghyq5ofvUsqZjmk6YkihBX5vMSChmSK9v4ShjKf3Vk5Xcmgpw4o+iIgtrnM/u5FiMpz9VKb8lpBveA==", - "dev": true - }, "concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", @@ -5273,23 +5130,6 @@ "plur": "^4.0.0" } }, - "eslint-plugin-jsdoc": { - "version": "46.4.4", - "resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-46.4.4.tgz", - "integrity": "sha512-D8TGPOkq3bnzmYmA7Q6jdsW+Slx7CunhJk1tlouVq6wJjlP1p6eigZPvxFn7aufud/D66xBsNVMhkDQEuqumMg==", - "dev": true, - "requires": { - "@es-joy/jsdoccomment": "~0.39.4", - "are-docs-informative": "^0.0.2", - "comment-parser": "1.3.1", - "debug": "^4.3.4", - "escape-string-regexp": "^4.0.0", - "esquery": "^1.5.0", - "is-builtin-module": "^3.2.1", - "semver": "^7.5.1", - "spdx-expression-parse": "^3.0.1" - } - }, "eslint-plugin-local": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/eslint-plugin-local/-/eslint-plugin-local-1.0.0.tgz", @@ -5751,15 +5591,6 @@ "binary-extensions": "^2.0.0" } }, - "is-builtin-module": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-3.2.1.tgz", - "integrity": "sha512-BSLE3HnV2syZ0FK0iMA/yUGplUeMmNz4AW5fnTunbCIqZi4vG3WjJT9FHMy5D69xmAYBHXQhJdALdpwVxV501A==", - "dev": true, - "requires": { - "builtin-modules": "^3.3.0" - } - }, "is-extglob": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", @@ -5859,12 +5690,6 @@ "argparse": "^2.0.1" } }, - "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 - }, "json-schema-traverse": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", @@ -6448,28 +6273,6 @@ "source-map": "^0.6.0" } }, - "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 - }, - "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, - "requires": { - "spdx-exceptions": "^2.1.0", - "spdx-license-ids": "^3.0.0" - } - }, - "spdx-license-ids": { - "version": "3.0.13", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.13.tgz", - "integrity": "sha512-XkD+zwiqXHikFZm4AX/7JSCXA98U5Db4AFd5XUg/+9UNtnH75+Z9KxtpYiJZx36mUDVOwH83pl7yvCer6ewM3w==", - "dev": true - }, "string-width": { "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", diff --git a/package.json b/package.json index a0b8eb36c63f3..cc39f6cba399e 100644 --- a/package.json +++ b/package.json @@ -64,7 +64,6 @@ "esbuild": "^0.19.0", "eslint": "^8.22.0", "eslint-formatter-autolinkable-stylish": "^1.2.0", - "eslint-plugin-jsdoc": "^46.4.4", "eslint-plugin-local": "^1.0.0", "eslint-plugin-no-null": "^1.0.2", "eslint-plugin-simple-import-sort": "^10.0.0", diff --git a/scripts/eslint/rules/mark-jsdoc-types-used.cjs b/scripts/eslint/rules/mark-jsdoc-types-used.cjs new file mode 100644 index 0000000000000..90cb457aa71bc --- /dev/null +++ b/scripts/eslint/rules/mark-jsdoc-types-used.cjs @@ -0,0 +1,102 @@ +const { TSESTree, ESLintUtils } = require("@typescript-eslint/utils"); +const { createRule } = require("./utils.cjs"); +const ts = require("typescript"); + +/** + * @param {ts.Identifier} node + */ +function isBareIdentifier(node) { + if (ts.isPropertyAccessExpression(node.parent)) { + return node.parent.expression === node; + } + + if (ts.isQualifiedName(node.parent)) { + return node.parent.left === node; + } + + // TODO(jakebailey): surely I'm missing something here. + // Also, how does eslint deal with type space versus value space? Or does it not? + + return true; +} + +module.exports = createRule({ + name: "mark-jsdoc-types-used", + meta: { + docs: { + description: ``, + }, + messages: {}, + schema: [], + type: "problem", + fixable: "whitespace", + }, + defaultOptions: [], + + create(context) { + /** @type {(node: TSESTree.Node) => void} */ + const checkProgram = (node) => { + const parserServices = ESLintUtils.getParserServices(context, /*allowWithoutFullTypeInformation*/ true); + const ast = parserServices.esTreeNodeToTSNodeMap.get(node); + + // TODO(jakebailey): I almost guarantee this is overzealous and wrong in some way. + + /** + * @param {ts.Node} node + */ + function markIdentifiersUsed(node) { + if (ts.isIdentifier(node) && isBareIdentifier(node)) { + context.markVariableAsUsed(node.text); + return; + } + ts.forEachChild(node, markIdentifiersUsed); + } + + /** + * @param {ts.Node} node + */ + function visit(node) { + const jsDoc = ts.getJSDocTags(node); + for (const tag of jsDoc) { + if (ts.isJSDocTypeTag(tag)) { + markIdentifiersUsed(tag.typeExpression); + } + else if (ts.isJSDocTypedefTag(tag) || ts.isJSDocPropertyLikeTag(tag) || ts.isJSDocReturnTag(tag) || ts.isJSDocThrowsTag(tag)) { + if (tag.typeExpression) { + markIdentifiersUsed(tag.typeExpression); + } + } + else if (ts.isJSDocTemplateTag(tag)) { + if (tag.constraint) { + markIdentifiersUsed(tag.constraint); + } + // tag.typeParameters? + } + else if (ts.isJSDocEnumTag(tag)) { + markIdentifiersUsed(tag.typeExpression); + } + else if (ts.isJSDocUnknownTag(tag)) { + // Ignore. + // TODO(jakebailey): Something's wrong here, though, becuase we're getting @parameter tags as unknown. See new code in parser. + } + else if (ts.isJSDocOverrideTag(tag) || ts.isJSDocDeprecatedTag(tag)) { + // Ignore. + } + else if (ts.isJSDocSeeTag(tag)) { + markIdentifiersUsed(tag.tagName); + } + else { + throw new Error(`Unexpected node kind: ${ts.SyntaxKind[tag.kind]} ${tag.getText()}}`); + } + } + ts.forEachChild(node, visit); + } + + visit(ast); + }; + + return { + Program: checkProgram, + }; + }, +}); diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index bd8081d1267a1..b19c18e4705ed 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -8973,6 +8973,7 @@ namespace Parser { case "arg": case "argument": case "param": + case "parameter": // TODO(jakebailey): why is this missing? return parseParameterOrPropertyTag(start, tagName, PropertyLikeParse.Parameter, margin); case "return": case "returns": From bf6a46bfe7b300c528a822b2440751a367698ce6 Mon Sep 17 00:00:00 2001 From: Jake Bailey <5341706+jakebailey@users.noreply.github.com> Date: Mon, 22 Jan 2024 12:06:21 -0800 Subject: [PATCH 3/3] fmt --- scripts/eslint/rules/mark-jsdoc-types-used.cjs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/eslint/rules/mark-jsdoc-types-used.cjs b/scripts/eslint/rules/mark-jsdoc-types-used.cjs index 90cb457aa71bc..570c0ff115b5b 100644 --- a/scripts/eslint/rules/mark-jsdoc-types-used.cjs +++ b/scripts/eslint/rules/mark-jsdoc-types-used.cjs @@ -35,7 +35,7 @@ module.exports = createRule({ create(context) { /** @type {(node: TSESTree.Node) => void} */ - const checkProgram = (node) => { + const checkProgram = node => { const parserServices = ESLintUtils.getParserServices(context, /*allowWithoutFullTypeInformation*/ true); const ast = parserServices.esTreeNodeToTSNodeMap.get(node);