From 47074b0cb8ac34508e662deefea6138b3106dea4 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 24 Jan 2023 12:02:25 +0400 Subject: [PATCH 01/19] chore(deps): update nx to v15.5.2 (#6361) --- .github/actions/prepare-build/action.yml | 2 +- package.json | 18 ++-- yarn.lock | 125 +++++++++++++---------- 3 files changed, 80 insertions(+), 65 deletions(-) diff --git a/.github/actions/prepare-build/action.yml b/.github/actions/prepare-build/action.yml index ce69eddedc50..d656587ca56a 100644 --- a/.github/actions/prepare-build/action.yml +++ b/.github/actions/prepare-build/action.yml @@ -19,4 +19,4 @@ runs: shell: bash # Website will be built by the Netlify GitHub App run: | - yarn build --exclude website + npx nx run-many --target=build --parallel --exclude website diff --git a/package.json b/package.json index 6607ca6146fc..16fef2bf3ba0 100644 --- a/package.json +++ b/package.json @@ -22,10 +22,10 @@ "url": "https://github.com/typescript-eslint/typescript-eslint/issues" }, "scripts": { - "build": "nx run-many --target=build --all --parallel --exclude website", + "build": "nx run-many --target=build --parallel --exclude website", "check-clean-workspace-after-install": "git diff --quiet --exit-code", - "check-configs": "nx run-many --target=check-configs --all --parallel", - "check-docs": "nx run-many --target=check-docs --all --parallel", + "check-configs": "nx run-many --target=check-configs --parallel", + "check-docs": "nx run-many --target=check-docs --parallel", "check-format": "prettier --list-different .", "check-spelling": "cspell --config=.cspell.json \"**/*.{md,mdx,ts,mts,cts,js,cjs,mjs,tsx,jsx}\"", "clean": "lerna clean -y && nx run-many --target=clean", @@ -37,13 +37,13 @@ "lint-fix": "eslint . --fix", "lint-markdown-fix": "yarn lint-markdown --fix", "lint-markdown": "markdownlint \"**/*.md\" --config=.markdownlint.json --ignore-path=.markdownlintignore", - "lint": "nx run-many --target=lint --all --parallel", + "lint": "nx run-many --target=lint --parallel", "postinstall": "yarn tsx ./tools/postinstall.ts", "pre-commit": "yarn lint-staged", "start": "nx run website:start", - "test": "nx run-many --target=test --all --parallel", + "test": "nx run-many --target=test --parallel", "test-integration": "yarn jest -c ./tests/integration/jest.config.js", - "typecheck": "nx run-many --target=typecheck --all --parallel" + "typecheck": "nx run-many --target=typecheck --parallel" }, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -54,9 +54,9 @@ "@babel/eslint-parser": "^7.19.1", "@babel/parser": "^7.20.7", "@babel/types": "^7.20.2", - "@nrwl/jest": "15.3.2", + "@nrwl/jest": "15.5.3", "@nrwl/nx-cloud": "15.0.2", - "@nrwl/workspace": "15.3.2", + "@nrwl/workspace": "15.5.3", "@swc/core": "^1.3.1", "@swc/jest": "^0.2.21", "@types/babel__code-frame": "^7.0.3", @@ -99,7 +99,7 @@ "make-dir": "^3.1.0", "markdownlint-cli": "^0.33.0", "ncp": "^2.0.0", - "nx": "15.3.2", + "nx": "15.5.3", "patch-package": "^6.4.7", "prettier": "2.8.1", "pretty-format": "^29.0.3", diff --git a/yarn.lock b/yarn.lock index 16ac4cfec250..4d8f7f823440 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3246,13 +3246,6 @@ read-package-json-fast "^2.0.3" which "^2.0.2" -"@nrwl/cli@15.3.2": - version "15.3.2" - resolved "https://registry.yarnpkg.com/@nrwl/cli/-/cli-15.3.2.tgz#dd713e6d6a064587a0ededd75d301b72f820e222" - integrity sha512-3xlH5LlNDzQ1mvVk+8w2WPoDwaOuUKR+9+38nnxTW6jW8g8S+h259/2IGsXnJ+cD7oEv3TARTC6aCrwVNn7egA== - dependencies: - nx "15.3.2" - "@nrwl/cli@15.4.5": version "15.4.5" resolved "https://registry.yarnpkg.com/@nrwl/cli/-/cli-15.4.5.tgz#2a8f663e5265379812ba83c0577abdc94dcdba8f" @@ -3260,10 +3253,17 @@ dependencies: nx "15.4.5" -"@nrwl/devkit@15.3.2": - version "15.3.2" - resolved "https://registry.yarnpkg.com/@nrwl/devkit/-/devkit-15.3.2.tgz#44ea9bc038ce87d9ea24447f6b3f3e1351a58787" - integrity sha512-h0MmDOjvhBJCrpXaAEK6eojpO5juaV6OEX0XjadPAQs4McxTALJxNP7Te6wIfgsY8t9WecARPIt85zKsLJeCjg== +"@nrwl/cli@15.5.3": + version "15.5.3" + resolved "https://registry.npmjs.org/@nrwl/cli/-/cli-15.5.3.tgz#13277e5a0e8ba713850bcf13fa76717ea747a2bb" + integrity sha512-NWf9CWswvdYM6YzXuweaZPAZ2erMtQrrHZdgFbUGeojZBZ+b4TCGzLWNodZj4yQOa/eTwlyPMYO2LEw9CoapDQ== + dependencies: + nx "15.5.3" + +"@nrwl/devkit@15.5.3": + version "15.5.3" + resolved "https://registry.npmjs.org/@nrwl/devkit/-/devkit-15.5.3.tgz#16fac0147c2ab6ebba7b5357b2b959ad46b6eb26" + integrity sha512-GGNLLGXDGWflrpaLimnE6hChfZfq3+XWZ0LJWL0IuCnchngPbNzuyh8S8KPgNKKgq4Nv0hglWefIwMg2UhHysA== dependencies: "@phenomnomnominal/tsquery" "4.1.1" ejs "^3.1.7" @@ -3282,16 +3282,16 @@ semver "7.3.4" tslib "^2.3.0" -"@nrwl/jest@15.3.2": - version "15.3.2" - resolved "https://registry.yarnpkg.com/@nrwl/jest/-/jest-15.3.2.tgz#5616af79444914e8a6c4b0dd7426eac8993accfb" - integrity sha512-3ksxm7gtJjXp/WeThxs2H5bAYI0zWQwquTjaNwaGKWvtwjtUbu+sM4zEF2HgOu4CKP6In3wFA4q0gZH7QlCEsw== +"@nrwl/jest@15.5.3": + version "15.5.3" + resolved "https://registry.npmjs.org/@nrwl/jest/-/jest-15.5.3.tgz#492ab42ac3171354a9afd6f93a7c43a6c56b3f61" + integrity sha512-BSs4ZQJtRjQ+OAPHdfeemoAiYsGL3Zuq2Ezj8XwGp50SkgVLUBZdXg2Ld1ARjTh/d3pMg+Mf+yKfjoYqFzKx+A== dependencies: "@jest/reporters" "28.1.1" "@jest/test-result" "28.1.1" - "@nrwl/devkit" "15.3.2" + "@nrwl/devkit" "15.5.3" "@phenomnomnominal/tsquery" "4.1.1" - chalk "4.1.0" + chalk "^4.1.0" dotenv "~10.0.0" identity-obj-proxy "3.0.0" jest-config "28.1.1" @@ -3300,12 +3300,12 @@ resolve.exports "1.1.0" tslib "^2.3.0" -"@nrwl/linter@15.3.2": - version "15.3.2" - resolved "https://registry.yarnpkg.com/@nrwl/linter/-/linter-15.3.2.tgz#7c947ece44d964d7331795e405966da71a02318b" - integrity sha512-sMOgmMufH5jhsseRLipKTk7GTfW3l0edjHFj9zVo49tQmGjMeurXdIw4MkJhX23JdSc1w1JGdrqeUi10iqtMyg== +"@nrwl/linter@15.5.3": + version "15.5.3" + resolved "https://registry.npmjs.org/@nrwl/linter/-/linter-15.5.3.tgz#de9c10c51d2ec92d51cc89207f642d41493314ba" + integrity sha512-ZeUtLOT0olORBL4FpEXmJoaiSKq4VIffW/vmCbosRIuHZqL4Cye5uHyQ6/KJXjD44Z+P6QCkyfr0etcy3lhSkg== dependencies: - "@nrwl/devkit" "15.3.2" + "@nrwl/devkit" "15.5.3" "@phenomnomnominal/tsquery" "4.1.1" tmp "~0.2.1" tslib "^2.3.0" @@ -3324,13 +3324,6 @@ tar "6.1.11" yargs-parser ">=21.0.1" -"@nrwl/tao@15.3.2": - version "15.3.2" - resolved "https://registry.yarnpkg.com/@nrwl/tao/-/tao-15.3.2.tgz#3498bd6596e582cbc5b922a45e5d8db5bcb2ce47" - integrity sha512-iP7e7gxSLn7xahz13Mj0c6KMSd9S2sUmD1Z6+F/H/lThikkrgURckSyZFtAW6OQNYOkWWi9RwdzVsH5He0syhQ== - dependencies: - nx "15.3.2" - "@nrwl/tao@15.4.5": version "15.4.5" resolved "https://registry.yarnpkg.com/@nrwl/tao/-/tao-15.4.5.tgz#d07f6d06cecb6acb84259e0654cfc59fcc5edd53" @@ -3338,15 +3331,22 @@ dependencies: nx "15.4.5" -"@nrwl/workspace@15.3.2": - version "15.3.2" - resolved "https://registry.yarnpkg.com/@nrwl/workspace/-/workspace-15.3.2.tgz#143609997f1e391083a2934a7e5305f0ef385ea5" - integrity sha512-h5WtTpRTHBmcO/V7WPnkzGJADQtAubZAinTn5ptkvFOYr0jnidwiVOidm0AgNvYMJtHIUf8h3jbKUIBAsRFF0g== +"@nrwl/tao@15.5.3": + version "15.5.3" + resolved "https://registry.npmjs.org/@nrwl/tao/-/tao-15.5.3.tgz#08c05715d2ecb108ed8b2c5381b9017cf1448b4a" + integrity sha512-vgPLIW9IoBfQ4IkHRT5RC4LqNwFBK5jmHYmFIRgbIeFRudFBbnpmOaKRME0OwN7qJ6964PVVbzahAPvYVD02xw== + dependencies: + nx "15.5.3" + +"@nrwl/workspace@15.5.3": + version "15.5.3" + resolved "https://registry.npmjs.org/@nrwl/workspace/-/workspace-15.5.3.tgz#3343b0de3a0fb8b0b7176c0c3cb7c19907e1485e" + integrity sha512-/Udv+dF4Z/9GZ4QmdCu/6e4QUJYx7zGTcoCOZi+Pt+OPRqOULkBbfKmB+xtiG/D32WnFePsxcssaZGux/aysUQ== dependencies: - "@nrwl/devkit" "15.3.2" - "@nrwl/linter" "15.3.2" + "@nrwl/devkit" "15.5.3" + "@nrwl/linter" "15.5.3" "@parcel/watcher" "2.0.4" - chalk "4.1.0" + chalk "^4.1.0" chokidar "^3.5.1" cli-cursor "3.1.0" cli-spinners "2.6.1" @@ -3354,12 +3354,13 @@ enquirer "~2.3.6" figures "3.2.0" flat "^5.0.2" - fs-extra "^10.1.0" + fs-extra "^11.1.0" glob "7.1.4" ignore "^5.0.4" + jsonc-parser "3.2.0" minimatch "3.0.5" npm-run-path "^4.0.1" - nx "15.3.2" + nx "15.5.3" open "^8.4.0" rxjs "^6.5.4" semver "7.3.4" @@ -7703,6 +7704,15 @@ fs-extra@^10.1.0: jsonfile "^6.0.1" universalify "^2.0.0" +fs-extra@^11.1.0: + version "11.1.0" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-11.1.0.tgz#5784b102104433bb0e090f48bfc4a30742c357ed" + integrity sha512-0rcTq621PD5jM/e0a3EJoGC/1TC5ZBCERW82LQuwfGnCa1V8w7dpYH1yNu+SLb6E5dkeCBzKEyLGlFrnr+dUyw== + dependencies: + graceful-fs "^4.2.0" + jsonfile "^6.0.1" + universalify "^2.0.0" + fs-extra@^7.0.1, fs-extra@~7.0.1: version "7.0.1" resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-7.0.1.tgz#4f189c44aa123b895f722804f55ea23eadc348e9" @@ -9774,6 +9784,11 @@ lines-and-columns@^1.1.6: resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.1.6.tgz#1c00c743b433cd0a4e80758f7b64a57440d9ff00" integrity sha1-HADHQ7QzzQpOgHWPe2SldEDZ/wA= +lines-and-columns@~2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-2.0.3.tgz#b2f0badedb556b747020ab8ea7f0373e22efac1b" + integrity sha512-cNOjgCnLB+FnvWWtyRTzmB3POJ+cXxTA81LoW7u8JdmhfXzriropYwpjShnz1QLLWsQwY7nIxoDmcPTwphDK9w== + linkify-it@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/linkify-it/-/linkify-it-4.0.1.tgz#01f1d5e508190d06669982ba31a7d9f56a5751ec" @@ -10774,13 +10789,13 @@ nth-check@^2.0.0, nth-check@^2.0.1: dependencies: boolbase "^1.0.0" -nx@15.3.2: - version "15.3.2" - resolved "https://registry.yarnpkg.com/nx/-/nx-15.3.2.tgz#3269b7c1c0be4dc4c389a4c54f463eb43636d542" - integrity sha512-i/y9pkZj6OACnk/+VmJaqrRIhY9VZw0twyeUp9z3gy7KElFoQZ7EMm4LcacFpVYy/MTsHYi0c87CDzkSyPogOA== +nx@15.4.5, "nx@>=15.4.2 < 16": + version "15.4.5" + resolved "https://registry.yarnpkg.com/nx/-/nx-15.4.5.tgz#12daa740256fa29ba634fbc4f3f87b6d078c2990" + integrity sha512-1spZL6sgOV8JJJuN8W5CLtJYwTOnlyaV32jPXfidavU0QMS8MP+rW3+NUQ9Uzc1UYhOu8llZWtnen93neVGQRw== dependencies: - "@nrwl/cli" "15.3.2" - "@nrwl/tao" "15.3.2" + "@nrwl/cli" "15.4.5" + "@nrwl/tao" "15.4.5" "@parcel/watcher" "2.0.4" "@yarnpkg/lockfile" "^1.1.0" "@yarnpkg/parsers" "^3.0.0-rc.18" @@ -10809,26 +10824,25 @@ nx@15.3.2: strong-log-transformer "^2.1.0" tar-stream "~2.2.0" tmp "~0.2.1" - tsconfig-paths "^3.9.0" + tsconfig-paths "^4.1.2" tslib "^2.3.0" v8-compile-cache "2.3.0" yargs "^17.6.2" yargs-parser "21.1.1" -nx@15.4.5, "nx@>=15.4.2 < 16": - version "15.4.5" - resolved "https://registry.yarnpkg.com/nx/-/nx-15.4.5.tgz#12daa740256fa29ba634fbc4f3f87b6d078c2990" - integrity sha512-1spZL6sgOV8JJJuN8W5CLtJYwTOnlyaV32jPXfidavU0QMS8MP+rW3+NUQ9Uzc1UYhOu8llZWtnen93neVGQRw== +nx@15.5.3: + version "15.5.3" + resolved "https://registry.npmjs.org/nx/-/nx-15.5.3.tgz#bf6252e7d9e17121dd82dec4f6fce319b9e005fa" + integrity sha512-PHB8VbiBLP108xb+yR8IGEsYWr7OcmDDOjHL+73oP4lVjyPgT8wdTMe6tI5LdBgv+KZ+0kiThK3ckvcPsfgvLQ== dependencies: - "@nrwl/cli" "15.4.5" - "@nrwl/tao" "15.4.5" + "@nrwl/cli" "15.5.3" + "@nrwl/tao" "15.5.3" "@parcel/watcher" "2.0.4" "@yarnpkg/lockfile" "^1.1.0" "@yarnpkg/parsers" "^3.0.0-rc.18" "@zkochan/js-yaml" "0.0.6" axios "^1.0.0" - chalk "4.1.0" - chokidar "^3.5.1" + chalk "^4.1.0" cli-cursor "3.1.0" cli-spinners "2.6.1" cliui "^7.0.2" @@ -10837,11 +10851,12 @@ nx@15.4.5, "nx@>=15.4.2 < 16": fast-glob "3.2.7" figures "3.2.0" flat "^5.0.2" - fs-extra "^10.1.0" + fs-extra "^11.1.0" glob "7.1.4" ignore "^5.0.4" js-yaml "4.1.0" jsonc-parser "3.2.0" + lines-and-columns "~2.0.3" minimatch "3.0.5" npm-run-path "^4.0.1" open "^8.4.0" @@ -13663,7 +13678,7 @@ ts-node@10.7.0: v8-compile-cache-lib "^3.0.0" yn "3.1.1" -tsconfig-paths@^3.14.1, tsconfig-paths@^3.9.0: +tsconfig-paths@^3.14.1: version "3.14.1" resolved "https://registry.yarnpkg.com/tsconfig-paths/-/tsconfig-paths-3.14.1.tgz#ba0734599e8ea36c862798e920bcf163277b137a" integrity sha512-fxDhWnFSLt3VuTwtvJt5fpwxBHg5AdKWMsgcPOOIilyjymcYVZoCQF8fvFRezCNfblEXmi+PcM1eYHeOAgXCOQ== From 09d57cec8901880c6b24ea80dfa7d9fcdc463930 Mon Sep 17 00:00:00 2001 From: Sosuke Suzuki Date: Wed, 25 Jan 2023 08:01:35 +0900 Subject: [PATCH 02/19] fix(eslint-plugin): [ban-ts-comment] counts graphemes instead of `String.prototype.length` (#5704) * fix: counts graphemes instead of String length * Update packages/eslint-plugin/src/rules/ban-ts-comment.ts Co-authored-by: Josh Goldberg * chore: add valid tests * Add grapheme-splitter to peerDependencies * Move to standard dependency * No more peerDependency Co-authored-by: Josh Goldberg Co-authored-by: Josh Goldberg --- packages/eslint-plugin/package.json | 2 + .../eslint-plugin/src/rules/ban-ts-comment.ts | 19 +++- .../tests/rules/ban-ts-comment.test.ts | 96 +++++++++++++++++++ yarn.lock | 5 + 4 files changed, 121 insertions(+), 1 deletion(-) diff --git a/packages/eslint-plugin/package.json b/packages/eslint-plugin/package.json index de64bdb760ef..5e2304c49e0c 100644 --- a/packages/eslint-plugin/package.json +++ b/packages/eslint-plugin/package.json @@ -48,6 +48,7 @@ "@typescript-eslint/type-utils": "5.49.0", "@typescript-eslint/utils": "5.49.0", "debug": "^4.3.4", + "grapheme-splitter": "^1.0.4", "ignore": "^5.2.0", "natural-compare-lite": "^1.4.0", "regexpp": "^3.2.0", @@ -61,6 +62,7 @@ "@types/natural-compare-lite": "^1.4.0", "@types/prettier": "*", "chalk": "^5.0.1", + "grapheme-splitter": "^1.0.4", "cross-fetch": "^3.1.5", "json-schema": "*", "markdown-table": "^3.0.2", diff --git a/packages/eslint-plugin/src/rules/ban-ts-comment.ts b/packages/eslint-plugin/src/rules/ban-ts-comment.ts index 9c55b437da63..f0bfce93ff6e 100644 --- a/packages/eslint-plugin/src/rules/ban-ts-comment.ts +++ b/packages/eslint-plugin/src/rules/ban-ts-comment.ts @@ -1,7 +1,22 @@ import { AST_TOKEN_TYPES } from '@typescript-eslint/utils'; +import GraphemeSplitter from 'grapheme-splitter'; import * as util from '../util'; +let splitter: GraphemeSplitter; +function isASCII(value: string): boolean { + return /^[\u0020-\u007f]*$/u.test(value); +} +function getStringLength(value: string): number { + if (isASCII(value)) { + return value.length; + } + + splitter ??= new GraphemeSplitter(); + + return splitter.countGraphemes(value); +} + type DirectiveConfig = | boolean | 'allow-with-description' @@ -147,7 +162,9 @@ export default util.createRule<[Options], MessageIds>({ minimumDescriptionLength = defaultMinimumDescriptionLength, } = options; const format = descriptionFormats.get(fullDirective); - if (description.trim().length < minimumDescriptionLength) { + if ( + getStringLength(description.trim()) < minimumDescriptionLength + ) { context.report({ data: { directive, minimumDescriptionLength }, node: comment, diff --git a/packages/eslint-plugin/tests/rules/ban-ts-comment.test.ts b/packages/eslint-plugin/tests/rules/ban-ts-comment.test.ts index 7e8ef295ba91..54855f19cf39 100644 --- a/packages/eslint-plugin/tests/rules/ban-ts-comment.test.ts +++ b/packages/eslint-plugin/tests/rules/ban-ts-comment.test.ts @@ -45,6 +45,14 @@ ruleTester.run('ts-expect-error', rule, { }, ], }, + { + code: noFormat`// @ts-expect-error ๐Ÿ‘จโ€๐Ÿ‘ฉโ€๐Ÿ‘งโ€๐Ÿ‘ฆ๐Ÿ‘จโ€๐Ÿ‘ฉโ€๐Ÿ‘งโ€๐Ÿ‘ฆ๐Ÿ‘จโ€๐Ÿ‘ฉโ€๐Ÿ‘งโ€๐Ÿ‘ฆ`, + options: [ + { + 'ts-expect-error': 'allow-with-description', + }, + ], + }, ], invalid: [ { @@ -228,6 +236,22 @@ if (false) { }, ], }, + { + code: noFormat`// @ts-expect-error ๐Ÿ‘จโ€๐Ÿ‘ฉโ€๐Ÿ‘งโ€๐Ÿ‘ฆ`, + options: [ + { + 'ts-expect-error': 'allow-with-description', + }, + ], + errors: [ + { + data: { directive: 'expect-error', minimumDescriptionLength: 3 }, + messageId: 'tsDirectiveCommentRequiresDescription', + line: 1, + column: 1, + }, + ], + }, ], }); @@ -266,6 +290,14 @@ ruleTester.run('ts-ignore', rule, { }, ], }, + { + code: noFormat`// @ts-ignore ๐Ÿ‘จโ€๐Ÿ‘ฉโ€๐Ÿ‘งโ€๐Ÿ‘ฆ๐Ÿ‘จโ€๐Ÿ‘ฉโ€๐Ÿ‘งโ€๐Ÿ‘ฆ๐Ÿ‘จโ€๐Ÿ‘ฉโ€๐Ÿ‘งโ€๐Ÿ‘ฆ`, + options: [ + { + 'ts-ignore': 'allow-with-description', + }, + ], + }, ], invalid: [ { @@ -460,6 +492,22 @@ if (false) { }, ], }, + { + code: noFormat`// @ts-ignore ๐Ÿ‘จโ€๐Ÿ‘ฉโ€๐Ÿ‘งโ€๐Ÿ‘ฆ`, + options: [ + { + 'ts-ignore': 'allow-with-description', + }, + ], + errors: [ + { + data: { directive: 'ignore', minimumDescriptionLength: 3 }, + messageId: 'tsDirectiveCommentRequiresDescription', + line: 1, + column: 1, + }, + ], + }, ], }); @@ -498,6 +546,14 @@ ruleTester.run('ts-nocheck', rule, { }, ], }, + { + code: noFormat`// @ts-nocheck ๐Ÿ‘จโ€๐Ÿ‘ฉโ€๐Ÿ‘งโ€๐Ÿ‘ฆ๐Ÿ‘จโ€๐Ÿ‘ฉโ€๐Ÿ‘งโ€๐Ÿ‘ฆ๐Ÿ‘จโ€๐Ÿ‘ฉโ€๐Ÿ‘งโ€๐Ÿ‘ฆ`, + options: [ + { + 'ts-nocheck': 'allow-with-description', + }, + ], + }, ], invalid: [ { @@ -668,6 +724,22 @@ if (false) { }, ], }, + { + code: noFormat`// @ts-nocheck ๐Ÿ‘จโ€๐Ÿ‘ฉโ€๐Ÿ‘งโ€๐Ÿ‘ฆ`, + options: [ + { + 'ts-nocheck': 'allow-with-description', + }, + ], + errors: [ + { + data: { directive: 'nocheck', minimumDescriptionLength: 3 }, + messageId: 'tsDirectiveCommentRequiresDescription', + line: 1, + column: 1, + }, + ], + }, ], }); @@ -700,6 +772,14 @@ ruleTester.run('ts-check', rule, { }, ], }, + { + code: noFormat`// @ts-check ๐Ÿ‘จโ€๐Ÿ‘ฉโ€๐Ÿ‘งโ€๐Ÿ‘ฆ๐Ÿ‘จโ€๐Ÿ‘ฉโ€๐Ÿ‘งโ€๐Ÿ‘ฆ๐Ÿ‘จโ€๐Ÿ‘ฉโ€๐Ÿ‘งโ€๐Ÿ‘ฆ`, + options: [ + { + 'ts-check': 'allow-with-description', + }, + ], + }, ], invalid: [ { @@ -863,5 +943,21 @@ if (false) { }, ], }, + { + code: noFormat`// @ts-check ๐Ÿ‘จโ€๐Ÿ‘ฉโ€๐Ÿ‘งโ€๐Ÿ‘ฆ`, + options: [ + { + 'ts-check': 'allow-with-description', + }, + ], + errors: [ + { + data: { directive: 'check', minimumDescriptionLength: 3 }, + messageId: 'tsDirectiveCommentRequiresDescription', + line: 1, + column: 1, + }, + ], + }, ], }); diff --git a/yarn.lock b/yarn.lock index 4d8f7f823440..a1ed83510144 100644 --- a/yarn.lock +++ b/yarn.lock @@ -8086,6 +8086,11 @@ graceful-fs@^4.1.11, graceful-fs@^4.1.15, graceful-fs@^4.1.2, graceful-fs@^4.1.6 resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.9.tgz#041b05df45755e587a24942279b9d113146e1c96" integrity sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ== +grapheme-splitter@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz#9cf3a665c6247479896834af35cf1dbb4400767e" + integrity sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ== + gray-matter@^4.0.3: version "4.0.3" resolved "https://registry.yarnpkg.com/gray-matter/-/gray-matter-4.0.3.tgz#e893c064825de73ea1f5f7d88c7a9f7274288798" From 67706e72e332bf11c82fdf51f3d417d3c93a86cf Mon Sep 17 00:00:00 2001 From: Eliott C Date: Wed, 25 Jan 2023 00:27:50 +0100 Subject: [PATCH 03/19] feat(eslint-plugin): add `key-spacing` rule extension for interface & type declarations (#6211) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * ๐Ÿšง key-spacing for interface on default settings * ๐Ÿšง Support type literals as welll * ๐Ÿšง Add full typing for the options * ๐Ÿšง Add 'mode' param * ๐Ÿ› Fix index signatures * โœจ Support classes * ๐Ÿฉน fixes * โœ… Add tests on mode, multiLine, singleLine * ๐Ÿท๏ธ Allow options.multiline.align to be an object * ๐ŸŽจ Use ast utils to locate last character before token * โœจ Support comments in-between properties * โœ… Add test cases for nested type declarations & multiline type annotations * โœจ Autofix for non-aligned values * โœจ Autofix for aligned values * โœ๏ธ * ๐Ÿšจ * ๐Ÿ› Support optional ? token * โœ… Add tests with class property assignments * ๐Ÿ“ Add documentation on key-spacing * ๐ŸŽจ Use .at() to access last element of array * โœ… Fix tests * fixup! โœ… Fix tests * โœ… Add some coverage * ๐Ÿ› Fix edge case in determining aligned groups In case there is three statements in one line, and one statement in the line after * โšก๏ธ Use Array.concat instead of .push(...) .push could error if 60k + arguments * ๐ŸŽจ Improve readability * ๐ŸŽจ Use tempate literals in tests * โœ… Add test with anonymous types * โœ… Add test with quoted keys * โž• Add grapheme-splitter to deal with emojis * โœ… Add test case for multiline comments * ๐Ÿšจ Remove 'in' statements, reduce amount of null-assertions * โœ… Add test case for properties without type annotation or assignments * โœ… Add wacky test cases * โœ… Add coverage * โœ… Add coverage, again * โœ… Add coverage, again * โœ… Add coverage when align is an object, but align.on is missing It defaults to 'colon' in this case * KeyTypeNodeWithTypeAnnotation * Extract to shared helper Co-authored-by: Josh Goldberg --- .../eslint-plugin/docs/rules/key-spacing.md | 12 + packages/eslint-plugin/package.json | 1 + packages/eslint-plugin/src/configs/all.ts | 2 + .../eslint-plugin/src/rules/ban-ts-comment.ts | 18 +- packages/eslint-plugin/src/rules/index.ts | 2 + .../eslint-plugin/src/rules/key-spacing.ts | 421 ++++++ .../src/util/getESLintCoreRule.ts | 1 + .../eslint-plugin/src/util/getStringLength.ts | 17 + packages/eslint-plugin/src/util/index.ts | 1 + .../tests/rules/key-spacing.test.ts | 1278 +++++++++++++++++ .../eslint-plugin/typings/eslint-rules.d.ts | 52 + 11 files changed, 1789 insertions(+), 16 deletions(-) create mode 100644 packages/eslint-plugin/docs/rules/key-spacing.md create mode 100644 packages/eslint-plugin/src/rules/key-spacing.ts create mode 100644 packages/eslint-plugin/src/util/getStringLength.ts create mode 100644 packages/eslint-plugin/tests/rules/key-spacing.test.ts diff --git a/packages/eslint-plugin/docs/rules/key-spacing.md b/packages/eslint-plugin/docs/rules/key-spacing.md new file mode 100644 index 000000000000..3bfcf5f389f0 --- /dev/null +++ b/packages/eslint-plugin/docs/rules/key-spacing.md @@ -0,0 +1,12 @@ +--- +description: 'Enforce consistent spacing between property names and type annotations in types and interfaces.' +--- + +> ๐Ÿ›‘ This file is source code, not the primary documentation location! ๐Ÿ›‘ +> +> See **https://typescript-eslint.io/rules/key-spacing** for documentation. + +## Examples + +This rule extends the base [`eslint/keyword-spacing`](https://eslint.org/docs/rules/key-spacing) rule. +This version adds support for type annotations on interfaces, classes and type literals properties. diff --git a/packages/eslint-plugin/package.json b/packages/eslint-plugin/package.json index 5e2304c49e0c..55992f5b7272 100644 --- a/packages/eslint-plugin/package.json +++ b/packages/eslint-plugin/package.json @@ -50,6 +50,7 @@ "debug": "^4.3.4", "grapheme-splitter": "^1.0.4", "ignore": "^5.2.0", + "grapheme-splitter": "^1.0.4", "natural-compare-lite": "^1.4.0", "regexpp": "^3.2.0", "semver": "^7.3.7", diff --git a/packages/eslint-plugin/src/configs/all.ts b/packages/eslint-plugin/src/configs/all.ts index 20ea892f581d..452035c4ebf2 100644 --- a/packages/eslint-plugin/src/configs/all.ts +++ b/packages/eslint-plugin/src/configs/all.ts @@ -37,6 +37,8 @@ export = { '@typescript-eslint/indent': 'error', 'init-declarations': 'off', '@typescript-eslint/init-declarations': 'error', + 'key-spacing': 'off', + '@typescript-eslint/key-spacing': 'error', 'keyword-spacing': 'off', '@typescript-eslint/keyword-spacing': 'error', 'lines-between-class-members': 'off', diff --git a/packages/eslint-plugin/src/rules/ban-ts-comment.ts b/packages/eslint-plugin/src/rules/ban-ts-comment.ts index f0bfce93ff6e..511a951280e7 100644 --- a/packages/eslint-plugin/src/rules/ban-ts-comment.ts +++ b/packages/eslint-plugin/src/rules/ban-ts-comment.ts @@ -1,22 +1,7 @@ import { AST_TOKEN_TYPES } from '@typescript-eslint/utils'; -import GraphemeSplitter from 'grapheme-splitter'; import * as util from '../util'; -let splitter: GraphemeSplitter; -function isASCII(value: string): boolean { - return /^[\u0020-\u007f]*$/u.test(value); -} -function getStringLength(value: string): number { - if (isASCII(value)) { - return value.length; - } - - splitter ??= new GraphemeSplitter(); - - return splitter.countGraphemes(value); -} - type DirectiveConfig = | boolean | 'allow-with-description' @@ -163,7 +148,8 @@ export default util.createRule<[Options], MessageIds>({ } = options; const format = descriptionFormats.get(fullDirective); if ( - getStringLength(description.trim()) < minimumDescriptionLength + util.getStringLength(description.trim()) < + minimumDescriptionLength ) { context.report({ data: { directive, minimumDescriptionLength }, diff --git a/packages/eslint-plugin/src/rules/index.ts b/packages/eslint-plugin/src/rules/index.ts index 8a3c2bbf4371..f7e51fdabd58 100644 --- a/packages/eslint-plugin/src/rules/index.ts +++ b/packages/eslint-plugin/src/rules/index.ts @@ -22,6 +22,7 @@ import explicitModuleBoundaryTypes from './explicit-module-boundary-types'; import funcCallSpacing from './func-call-spacing'; import indent from './indent'; import initDeclarations from './init-declarations'; +import keySpacing from './key-spacing'; import keywordSpacing from './keyword-spacing'; import linesBetweenClassMembers from './lines-between-class-members'; import memberDelimiterStyle from './member-delimiter-style'; @@ -153,6 +154,7 @@ export default { 'func-call-spacing': funcCallSpacing, indent: indent, 'init-declarations': initDeclarations, + 'key-spacing': keySpacing, 'keyword-spacing': keywordSpacing, 'lines-between-class-members': linesBetweenClassMembers, 'member-delimiter-style': memberDelimiterStyle, diff --git a/packages/eslint-plugin/src/rules/key-spacing.ts b/packages/eslint-plugin/src/rules/key-spacing.ts new file mode 100644 index 000000000000..587d2674f4f3 --- /dev/null +++ b/packages/eslint-plugin/src/rules/key-spacing.ts @@ -0,0 +1,421 @@ +import type { TSESTree } from '@typescript-eslint/utils'; +import { AST_NODE_TYPES } from '@typescript-eslint/utils'; + +import * as util from '../util'; +import { getESLintCoreRule } from '../util/getESLintCoreRule'; + +const baseRule = getESLintCoreRule('key-spacing'); + +export type Options = util.InferOptionsTypeFromRule; +export type MessageIds = util.InferMessageIdsTypeFromRule; + +// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment +const baseSchema = Array.isArray(baseRule.meta.schema) + ? baseRule.meta.schema[0] + : baseRule.meta.schema; + +export default util.createRule({ + name: 'key-spacing', + meta: { + type: 'layout', + docs: { + description: + 'Enforce consistent spacing between property names and type annotations in types and interfaces', + recommended: false, + extendsBaseRule: true, + }, + fixable: 'whitespace', + hasSuggestions: baseRule.meta.hasSuggestions, + schema: [baseSchema], + messages: baseRule.meta.messages, + }, + defaultOptions: [{}], + + create(context, [options]) { + const sourceCode = context.getSourceCode(); + const baseRules = baseRule.create(context); + + /** + * @returns the column of the position after converting all unicode characters in the line to 1 char length + */ + function adjustedColumn(position: TSESTree.Position): number { + const line = position.line - 1; // position.line is 1-indexed + return util.getStringLength( + sourceCode.lines[line].slice(0, position.column), + ); + } + + /** + * Starting from the given a node (a property.key node here) looks forward + * until it finds the last token before a colon punctuator and returns it. + */ + function getLastTokenBeforeColon(node: TSESTree.Node): TSESTree.Token { + const colonToken = sourceCode.getTokenAfter(node, util.isColonToken)!; + + return sourceCode.getTokenBefore(colonToken)!; + } + + type KeyTypeNode = + | TSESTree.TSIndexSignature + | TSESTree.TSPropertySignature + | TSESTree.PropertyDefinition; + + type KeyTypeNodeWithTypeAnnotation = KeyTypeNode & { + typeAnnotation: TSESTree.TSTypeAnnotation; + }; + + function isKeyTypeNode( + node: TSESTree.Node, + ): node is KeyTypeNodeWithTypeAnnotation { + return ( + (node.type === AST_NODE_TYPES.TSPropertySignature || + node.type === AST_NODE_TYPES.TSIndexSignature || + node.type === AST_NODE_TYPES.PropertyDefinition) && + !!node.typeAnnotation + ); + } + + /** + * To handle index signatures, to get the whole text for the parameters + */ + function getKeyText(node: KeyTypeNodeWithTypeAnnotation): string { + if (node.type !== AST_NODE_TYPES.TSIndexSignature) { + return sourceCode.getText(node.key); + } + + const code = sourceCode.getText(node); + return code.slice( + 0, + sourceCode.getTokenAfter( + node.parameters.at(-1)!, + util.isClosingBracketToken, + )!.range[1] - node.range[0], + ); + } + + /** + * To handle index signatures, be able to get the end position of the parameters + */ + function getKeyLocEnd( + node: KeyTypeNodeWithTypeAnnotation, + ): TSESTree.Position { + return getLastTokenBeforeColon( + node.type !== AST_NODE_TYPES.TSIndexSignature + ? node.key + : node.parameters.at(-1)!, + ).loc.end; + } + + function checkBeforeColon( + node: KeyTypeNodeWithTypeAnnotation, + expectedWhitespaceBeforeColon: number, + mode: 'strict' | 'minimum', + ): void { + const { typeAnnotation } = node; + const colon = typeAnnotation.loc.start.column; + const keyEnd = getKeyLocEnd(node); + const difference = colon - keyEnd.column - expectedWhitespaceBeforeColon; + if (mode === 'strict' ? difference : difference < 0) { + context.report({ + node, + messageId: difference > 0 ? 'extraKey' : 'missingKey', + fix: fixer => { + if (difference > 0) { + return fixer.removeRange([ + typeAnnotation.range[0] - difference, + typeAnnotation.range[0], + ]); + } else { + return fixer.insertTextBefore( + typeAnnotation, + ' '.repeat(-difference), + ); + } + }, + data: { + computed: '', + key: getKeyText(node), + }, + }); + } + } + + function checkAfterColon( + node: KeyTypeNodeWithTypeAnnotation, + expectedWhitespaceAfterColon: number, + mode: 'strict' | 'minimum', + ): void { + const { typeAnnotation } = node; + const colon = typeAnnotation.loc.start.column; + const typeStart = typeAnnotation.typeAnnotation.loc.start.column; + const difference = typeStart - colon - 1 - expectedWhitespaceAfterColon; + if (mode === 'strict' ? difference : difference < 0) { + context.report({ + node, + messageId: difference > 0 ? 'extraValue' : 'missingValue', + fix: fixer => { + if (difference > 0) { + return fixer.removeRange([ + typeAnnotation.typeAnnotation.range[0] - difference, + typeAnnotation.typeAnnotation.range[0], + ]); + } else { + return fixer.insertTextBefore( + typeAnnotation.typeAnnotation, + ' '.repeat(-difference), + ); + } + }, + data: { + computed: '', + key: getKeyText(node), + }, + }); + } + } + + // adapted from https://github.com/eslint/eslint/blob/ba74253e8bd63e9e163bbee0540031be77e39253/lib/rules/key-spacing.js#L356 + function continuesAlignGroup( + lastMember: TSESTree.Node, + candidate: TSESTree.Node, + ): boolean { + const groupEndLine = lastMember.loc.start.line; + const candidateValueStartLine = ( + isKeyTypeNode(candidate) ? candidate.typeAnnotation : candidate + ).loc.start.line; + + if (candidateValueStartLine === groupEndLine) { + return false; + } + + if (candidateValueStartLine - groupEndLine === 1) { + return true; + } + + /* + * Check that the first comment is adjacent to the end of the group, the + * last comment is adjacent to the candidate property, and that successive + * comments are adjacent to each other. + */ + const leadingComments = sourceCode.getCommentsBefore(candidate); + + if ( + leadingComments.length && + leadingComments[0].loc.start.line - groupEndLine <= 1 && + candidateValueStartLine - leadingComments.at(-1)!.loc.end.line <= 1 + ) { + for (let i = 1; i < leadingComments.length; i++) { + if ( + leadingComments[i].loc.start.line - + leadingComments[i - 1].loc.end.line > + 1 + ) { + return false; + } + } + return true; + } + + return false; + } + + function checkAlignGroup(group: TSESTree.Node[]): void { + let alignColumn = 0; + const align: 'value' | 'colon' = + (typeof options.align === 'object' + ? options.align.on + : typeof options.multiLine?.align === 'object' + ? options.multiLine.align.on + : options.multiLine?.align ?? options.align) ?? 'colon'; + const beforeColon = + (typeof options.align === 'object' + ? options.align.beforeColon + : options.multiLine + ? typeof options.multiLine.align === 'object' + ? options.multiLine.align.beforeColon + : options.multiLine.beforeColon + : options.beforeColon) ?? false; + const expectedWhitespaceBeforeColon = beforeColon ? 1 : 0; + const afterColon = + (typeof options.align === 'object' + ? options.align.afterColon + : options.multiLine + ? typeof options.multiLine.align === 'object' + ? options.multiLine.align.afterColon + : options.multiLine.afterColon + : options.afterColon) ?? true; + const expectedWhitespaceAfterColon = afterColon ? 1 : 0; + const mode = + (typeof options.align === 'object' + ? options.align.mode + : options.multiLine + ? typeof options.multiLine.align === 'object' + ? // same behavior as in original rule + options.multiLine.align.mode ?? options.multiLine.mode + : options.multiLine.mode + : options.mode) ?? 'strict'; + + for (const node of group) { + if (isKeyTypeNode(node)) { + const keyEnd = adjustedColumn(getKeyLocEnd(node)); + alignColumn = Math.max( + alignColumn, + align === 'colon' + ? keyEnd + expectedWhitespaceBeforeColon + : keyEnd + + ':'.length + + expectedWhitespaceAfterColon + + expectedWhitespaceBeforeColon, + ); + } + } + + for (const node of group) { + if (!isKeyTypeNode(node)) { + continue; + } + const { typeAnnotation } = node; + const toCheck = + align === 'colon' ? typeAnnotation : typeAnnotation.typeAnnotation; + const difference = adjustedColumn(toCheck.loc.start) - alignColumn; + + if (difference) { + context.report({ + node, + messageId: + difference > 0 + ? align === 'colon' + ? 'extraKey' + : 'extraValue' + : align === 'colon' + ? 'missingKey' + : 'missingValue', + fix: fixer => { + if (difference > 0) { + return fixer.removeRange([ + toCheck.range[0] - difference, + toCheck.range[0], + ]); + } else { + return fixer.insertTextBefore(toCheck, ' '.repeat(-difference)); + } + }, + data: { + computed: '', + key: getKeyText(node), + }, + }); + } + + if (align === 'colon') { + checkAfterColon(node, expectedWhitespaceAfterColon, mode); + } else { + checkBeforeColon(node, expectedWhitespaceBeforeColon, mode); + } + } + } + + function checkIndividualNode( + node: TSESTree.Node, + { singleLine }: { singleLine: boolean }, + ): void { + const beforeColon = + (singleLine + ? options.singleLine + ? options.singleLine.beforeColon + : options.beforeColon + : options.multiLine + ? options.multiLine.beforeColon + : options.beforeColon) ?? false; + const expectedWhitespaceBeforeColon = beforeColon ? 1 : 0; + const afterColon = + (singleLine + ? options.singleLine + ? options.singleLine.afterColon + : options.afterColon + : options.multiLine + ? options.multiLine.afterColon + : options.afterColon) ?? true; + const expectedWhitespaceAfterColon = afterColon ? 1 : 0; + const mode = + (singleLine + ? options.singleLine + ? options.singleLine.mode + : options.mode + : options.multiLine + ? options.multiLine.mode + : options.mode) ?? 'strict'; + + if (isKeyTypeNode(node)) { + checkBeforeColon(node, expectedWhitespaceBeforeColon, mode); + checkAfterColon(node, expectedWhitespaceAfterColon, mode); + } + } + + function validateBody( + body: + | TSESTree.TSTypeLiteral + | TSESTree.TSInterfaceBody + | TSESTree.ClassBody, + ): void { + const isSingleLine = body.loc.start.line === body.loc.end.line; + + const members = + body.type === AST_NODE_TYPES.TSTypeLiteral ? body.members : body.body; + + let alignGroups: TSESTree.Node[][] = []; + let unalignedElements: TSESTree.Node[] = []; + + if (options.align || options.multiLine?.align) { + let currentAlignGroup: TSESTree.Node[] = []; + alignGroups.push(currentAlignGroup); + + let prevNode: TSESTree.Node | undefined = undefined; + + for (const node of members) { + let prevAlignedNode = currentAlignGroup.at(-1); + if (prevAlignedNode !== prevNode) { + prevAlignedNode = undefined; + } + + if (prevAlignedNode && continuesAlignGroup(prevAlignedNode, node)) { + currentAlignGroup.push(node); + } else if (prevNode?.loc.start.line === node.loc.start.line) { + if (prevAlignedNode) { + // Here, prevNode === prevAlignedNode === currentAlignGroup.at(-1) + unalignedElements.push(prevAlignedNode); + currentAlignGroup.pop(); + } + unalignedElements.push(node); + } else { + currentAlignGroup = [node]; + alignGroups.push(currentAlignGroup); + } + + prevNode = node; + } + + unalignedElements = unalignedElements.concat( + ...alignGroups.filter(group => group.length === 1), + ); + alignGroups = alignGroups.filter(group => group.length >= 2); + } else { + unalignedElements = members; + } + + for (const group of alignGroups) { + checkAlignGroup(group); + } + + for (const node of unalignedElements) { + checkIndividualNode(node, { singleLine: isSingleLine }); + } + } + return { + ...baseRules, + TSTypeLiteral: validateBody, + TSInterfaceBody: validateBody, + ClassBody: validateBody, + }; + }, +}); diff --git a/packages/eslint-plugin/src/util/getESLintCoreRule.ts b/packages/eslint-plugin/src/util/getESLintCoreRule.ts index 1678903acd32..80962a677b05 100644 --- a/packages/eslint-plugin/src/util/getESLintCoreRule.ts +++ b/packages/eslint-plugin/src/util/getESLintCoreRule.ts @@ -12,6 +12,7 @@ interface RuleMap { 'dot-notation': typeof import('eslint/lib/rules/dot-notation'); indent: typeof import('eslint/lib/rules/indent'); 'init-declarations': typeof import('eslint/lib/rules/init-declarations'); + 'key-spacing': typeof import('eslint/lib/rules/key-spacing'); 'keyword-spacing': typeof import('eslint/lib/rules/keyword-spacing'); 'lines-between-class-members': typeof import('eslint/lib/rules/lines-between-class-members'); 'no-dupe-args': typeof import('eslint/lib/rules/no-dupe-args'); diff --git a/packages/eslint-plugin/src/util/getStringLength.ts b/packages/eslint-plugin/src/util/getStringLength.ts new file mode 100644 index 000000000000..65a22551949a --- /dev/null +++ b/packages/eslint-plugin/src/util/getStringLength.ts @@ -0,0 +1,17 @@ +import GraphemeSplitter from 'grapheme-splitter'; + +let splitter: GraphemeSplitter; + +function isASCII(value: string): boolean { + return /^[\u0020-\u007f]*$/u.test(value); +} + +export function getStringLength(value: string): number { + if (isASCII(value)) { + return value.length; + } + + splitter ??= new GraphemeSplitter(); + + return splitter.countGraphemes(value); +} diff --git a/packages/eslint-plugin/src/util/index.ts b/packages/eslint-plugin/src/util/index.ts index b2ad2927773a..53a19a96d368 100644 --- a/packages/eslint-plugin/src/util/index.ts +++ b/packages/eslint-plugin/src/util/index.ts @@ -5,6 +5,7 @@ export * from './collectUnusedVariables'; export * from './createRule'; export * from './getFunctionHeadLoc'; export * from './getOperatorPrecedence'; +export * from './getStringLength'; export * from './getThisExpression'; export * from './getWrappingFixer'; export * from './isNodeEqual'; diff --git a/packages/eslint-plugin/tests/rules/key-spacing.test.ts b/packages/eslint-plugin/tests/rules/key-spacing.test.ts new file mode 100644 index 000000000000..40206258671c --- /dev/null +++ b/packages/eslint-plugin/tests/rules/key-spacing.test.ts @@ -0,0 +1,1278 @@ +/* eslint-disable eslint-comments/no-use */ +// this rule tests the new lines, which prettier will want to fix and break the tests +/* eslint "@typescript-eslint/internal/plugin-test-formatting": ["error", { formatWithPrettier: false }] */ +/* eslint-enable eslint-comments/no-use */ +import rule from '../../src/rules/key-spacing'; +import { RuleTester } from '../RuleTester'; + +const ruleTester = new RuleTester({ + parser: '@typescript-eslint/parser', +}); + +ruleTester.run('key-spacing', rule, { + valid: [ + // align: value + { + code: ` +interface X { + a: number; + abc: string +}; + `, + options: [{ align: 'value' }], + }, + { + code: ` +interface X { + "a:b": number; + abcde: string +}; + `, + options: [{ align: 'value' }], + }, + { + code: ` +let x: { + a: number; + abc: string +}; + `, + options: [{ align: 'value' }], + }, + { + code: ` +let x: { + a: number; + "๐Œ˜": string; + [๐Œ˜]: Date; + "๐ŸŒท": "bar", // 2 code points + "๐ŸŽ": "baz", // 2 code points + "๐Ÿ‡ฎ๐Ÿ‡ณ": "qux", // 4 code points + "๐Ÿณ๏ธโ€๐ŸŒˆ": "xyz", // 6 code points +}; + `, + options: [{ align: 'value' }], + }, + { + code: ` +interface X { + a: number; + abc: string; c: number; +}; + `, + options: [{ align: 'value' }], + }, + { + code: ` +interface X { + a: number; + abc: string; c: number; de: boolean; + abcef: number; +}; + `, + options: [{ align: 'colon' }], + }, + { + code: ` +interface X { + a : number; + abc; + abcef: number; +}; + `, + options: [{ align: 'colon' }], + }, + { + code: ` +interface X { + a?: number; + abc: string +}; + `, + options: [{ align: 'value' }], + }, + { + code: ` +interface X { + a: number; + // Some comment + abc: string +}; + `, + options: [{ align: 'value' }], + }, + { + code: ` +interface X { + a: number; + // Some comment + // on multiple lines + abc: string +}; + `, + options: [{ align: 'value' }], + }, + { + code: ` +interface X { + a: number; + /** + * Some comment + * on multiple lines + */ + abc: string +}; + `, + options: [{ align: 'value' }], + }, + { + code: ` +interface X { + a: number; + /** + * Doc comment + */ + abc: string +}; + `, + options: [{ align: 'value' }], + }, + { + code: ` +interface X { + a: number; + + abc: string +}; + `, + options: [{ align: 'value' }], + }, + { + code: ` +class X { + a: number; + abc: string +}; + `, + options: [{ align: 'value' }], + }, + { + code: ` +class X { + a?: number; + abc: string +}; + `, + options: [{ align: 'value' }], + }, + { + code: ` +class X { + x: number; + z = 1; + xbcef: number; + } + `, + options: [{ align: 'value' }], + }, + { + code: ` +class X { + a: number; + + abc: string +}; + `, + options: [{ align: 'value' }], + }, + { + code: ` +type X = { + a: number; + abc: string +}; + `, + options: [{ align: 'value' }], + }, + { + code: ` +type X = { + a: number; + + abc: string +}; + `, + options: [{ align: 'value' }], + }, + { + code: ` +type X = { + a : number; + abc: string +}; + `, + options: [{ align: 'value', mode: 'minimum' }], + }, + { + code: ` +type X = { + a : number; + abc: string +}; + `, + options: [ + { + align: { + on: 'value', + mode: 'minimum', + beforeColon: false, + afterColon: true, + }, + }, + ], + }, + { + code: ` +interface X { + a: number; + prop: { + abc: number; + a: number; + }; + abc: string +} + `, + options: [{ align: 'value' }], + }, + { + code: ` +class X { + a: number; + prop: { + abc: number; + a: number; + }; + abc: string + x = 1; + d: number; + z: number = 1; + ef: string; +} + `, + options: [{ align: 'value' }], + }, + // align: colon + { + code: ` +interface X { + a : number; + abc: string +}; + `, + options: [{ align: 'colon' }], + }, + { + code: ` +interface X { + a :number; + abc:string +}; + `, + options: [{ align: 'colon', afterColon: false }], + }, + { + code: ` +interface X { + a : number; + abc: string +}; + `, + options: [{ align: 'colon', mode: 'minimum' }], + }, + // no align + { + code: ` +interface X { + a: number; + abc: string +}; + `, + options: [{}], + }, + { + code: ` +interface X { + a : number; + abc : string +}; + `, + options: [{ beforeColon: true }], + }, + // singleLine / multiLine + { + code: ` +interface X { + a : number; + abc : string +}; + `, + options: [ + { + singleLine: { beforeColon: false, afterColon: false }, + multiLine: { beforeColon: true, afterColon: true }, + }, + ], + }, + { + code: ` +interface X { + a : number; + abc : string +}; + `, + options: [ + { + align: { on: 'value', beforeColon: true, afterColon: true }, + singleLine: { beforeColon: false, afterColon: false }, + multiLine: { beforeColon: false, afterColon: false }, + }, + ], + }, + { + code: ` +interface X { + a : number; + abc : string +}; + `, + options: [ + { + align: { beforeColon: true, afterColon: true }, // defaults to 'colon' + singleLine: { beforeColon: false, afterColon: false }, + multiLine: { beforeColon: false, afterColon: false }, + }, + ], + }, + { + code: ` +interface X { + a : number; + abc : string +}; + `, + options: [ + { + singleLine: { beforeColon: false, afterColon: false }, + multiLine: { beforeColon: true, afterColon: true, align: 'value' }, + }, + ], + }, + { + code: ` +interface X { + a : number; + abc : string +}; + `, + options: [ + { + singleLine: { beforeColon: false, afterColon: false }, + multiLine: { + beforeColon: true, + afterColon: true, + align: { + on: 'colon', + mode: 'strict', + afterColon: true, + beforeColon: true, + }, + }, + }, + ], + }, + { + code: ` +interface X { + a : number; + abc : string +}; + `, + options: [ + { + singleLine: { beforeColon: false, afterColon: false }, + multiLine: { + beforeColon: true, + afterColon: true, + align: { + mode: 'strict', + afterColon: true, + beforeColon: true, + }, + }, + }, + ], + }, + { + code: ` +interface X { + a : number; + abc : string +}; + `, + options: [ + { + beforeColon: true, + afterColon: true, + align: { + on: 'colon', + mode: 'strict', + afterColon: true, + beforeColon: true, + }, + }, + ], + }, + { + code: ` +interface X { + a : number; + abc : string +}; + `, + options: [ + { + beforeColon: true, + afterColon: true, + align: { + mode: 'strict', + afterColon: true, + beforeColon: true, + }, + }, + ], + }, + { + code: ` +interface X { + a : number; + abc: string + + xadzd : number; +}; + `, + options: [ + { + singleLine: { beforeColon: false, afterColon: false }, + multiLine: { + beforeColon: true, + afterColon: true, + align: { + on: 'colon', + mode: 'strict', + afterColon: true, + beforeColon: false, + }, + }, + }, + ], + }, + { + code: ` +interface X { + a : number; + abc: string + + xadzd : number; +}; + `, + options: [ + { + singleLine: { beforeColon: false, afterColon: false }, + multiLine: { + beforeColon: true, + afterColon: true, + mode: 'strict', + align: { + on: 'colon', + afterColon: true, + beforeColon: false, + }, + }, + }, + ], + }, + { + code: ` +interface X { + a : number; + abc: string + + xadzd : number; +}; + `, + options: [ + { + singleLine: { beforeColon: false, afterColon: false }, + multiLine: { + beforeColon: true, + afterColon: true, + mode: 'minimum', + align: { + on: 'colon', + afterColon: true, + beforeColon: false, + }, + }, + }, + ], + }, + { + code: ` +interface X { a:number; abc:string; }; + `, + options: [ + { + singleLine: { beforeColon: false, afterColon: false }, + multiLine: { beforeColon: true, afterColon: true }, + }, + ], + }, + ], + invalid: [ + // align: value + { + code: ` +interface X { + a: number; + abc: string +}; + `, + output: ` +interface X { + a: number; + abc: string +}; + `, + options: [{ align: 'value' }], + errors: [{ messageId: 'missingValue' }], + }, + { + code: ` +interface X { + a: number; + "a:c": string +}; + `, + output: ` +interface X { + a: number; + "a:c": string +}; + `, + options: [{ align: 'value' }], + errors: [{ messageId: 'missingValue' }], + }, + { + code: ` +let x: { + a: number; + abc: string +}; + `, + output: ` +let x: { + a: number; + abc: string +}; + `, + options: [{ align: 'value' }], + errors: [{ messageId: 'missingValue' }], + }, + { + code: ` +let x: { + a: number; + abc: string +}; + `, + output: ` +let x: { + a: number; + abc: string +}; + `, + options: [{ align: { on: 'value' } }], + errors: [{ messageId: 'missingValue' }], + }, + { + code: ` +let x: { + a: number; + "๐ŸŒท": "bar", // 2 code points + "๐ŸŽ": "baz", // 2 code points + "๐Ÿ‡ฎ๐Ÿ‡ณ": "qux", // 4 code points + "๐Ÿณ๏ธโ€๐ŸŒˆ": "xyz", // 6 code points + [๐Œ˜]: string + "๐Œ˜": string +}; + `, + output: ` +let x: { + a: number; + "๐ŸŒท": "bar", // 2 code points + "๐ŸŽ": "baz", // 2 code points + "๐Ÿ‡ฎ๐Ÿ‡ณ": "qux", // 4 code points + "๐Ÿณ๏ธโ€๐ŸŒˆ": "xyz", // 6 code points + [๐Œ˜]: string + "๐Œ˜": string +}; + `, + options: [{ align: 'value' }], + errors: [{ messageId: 'missingValue' }], + }, + { + code: ` +class X { + a: number; + abc: string +}; + `, + output: ` +class X { + a: number; + abc: string +}; + `, + options: [{ align: 'value' }], + errors: [{ messageId: 'missingValue' }], + }, + { + code: ` +class X { + a: number; + abc: string +}; + `, + output: ` +class X { + a: number; + abc: string +}; + `, + options: [{ align: 'value', mode: 'minimum' }], + errors: [{ messageId: 'missingValue' }], + }, + { + code: ` +class X { + a: number; + b; + abc: string +}; + `, + output: ` +class X { + a: number; + b; + abc: string +}; + `, + options: [{ align: 'value', mode: 'minimum' }], + errors: [{ messageId: 'missingValue' }], + }, + { + code: ` +type X = { + a: number; + abc: string +}; + `, + output: ` +type X = { + a: number; + abc: string +}; + `, + options: [{ align: 'value' }], + errors: [{ messageId: 'missingValue' }], + }, + { + code: ` +interface X { + a: number; + abc: string +}; + `, + output: ` +interface X { + a: number; + abc: string +}; + `, + options: [{ align: 'value' }], + errors: [{ messageId: 'extraValue' }], + }, + { + code: ` +class X { + a: number; + abc: string +}; + `, + output: ` +class X { + a: number; + abc: string +}; + `, + options: [{ align: 'value' }], + errors: [{ messageId: 'extraValue' }], + }, + { + code: ` +class X { + x: number; + z = 1; + xbcef: number; + } + `, + output: ` +class X { + x: number; + z = 1; + xbcef: number; + } + `, + options: [{ align: 'value' }], + errors: [{ messageId: 'missingValue' }], + }, + { + code: ` +interface X { + a: number; + + abc : string +}; + `, + output: ` +interface X { + a: number; + + abc: string +}; + `, + options: [{ align: 'value' }], + errors: [{ messageId: 'extraValue' }, { messageId: 'extraKey' }], + }, + { + code: ` +class X { + a: number; + + abc : string +}; + `, + output: ` +class X { + a: number; + + abc: string +}; + `, + options: [{ align: 'value' }], + errors: [{ messageId: 'extraValue' }, { messageId: 'extraKey' }], + }, + { + code: ` +interface X { + a: number; + // Some comment + + // interrupted in the middle + abc: string +}; + `, + output: ` +interface X { + a: number; + // Some comment + + // interrupted in the middle + abc: string +}; + `, + options: [{ align: 'value' }], + errors: [{ messageId: 'extraValue' }], + }, + { + code: ` +interface X { + a: number; + /** + * Multiline comment + */ + + /** interrupted in the middle */ + abc: string +}; + `, + output: ` +interface X { + a: number; + /** + * Multiline comment + */ + + /** interrupted in the middle */ + abc: string +}; + `, + options: [{ align: 'value' }], + errors: [{ messageId: 'extraValue' }], + }, + { + code: ` +interface X { + a: number; + prop: { + abc: number; + a: number; + }, + abc: string +} + `, + output: ` +interface X { + a: number; + prop: { + abc: number; + a: number; + }, + abc: string +} + `, + options: [{ align: 'value' }], + errors: [{ messageId: 'missingValue' }], + }, + { + code: ` +interface X { + a: number; + prop: { + abc: number; + a: number; + }, + abc: string +} + `, + output: ` +interface X { + a: number; + prop: { + abc: number; + a: number; + }, + abc: string +} + `, + options: [{ align: 'value' }], + errors: [{ messageId: 'missingValue' }], + }, + { + code: ` +interface X { + a: number; + prop: { + abc: number; + a: number; + }, + abc: string +} + `, + output: ` +interface X { + a: number; + prop: { + abc: number; + a: number; + }, + abc: string +} + `, + options: [{ align: 'value' }], + errors: [{ messageId: 'extraValue' }], + }, + { + code: ` +class X { + a: number; + prop: { + abc: number; + a?: number; + }; + abc: string; + x = 1; + d: number; + z: number = 1; + ef: string; +} + `, + output: ` +class X { + a: number; + prop: { + abc: number; + a?: number; + }; + abc: string; + x = 1; + d: number; + z: number = 1; + ef: string; +} + `, + options: [{ align: 'value' }], + errors: [ + { messageId: 'extraValue' }, + { messageId: 'missingValue' }, + { messageId: 'missingValue' }, + { messageId: 'missingValue' }, + { messageId: 'missingValue' }, + ], + }, + // align: colon + { + code: ` +interface X { + a : number; + abc: string +}; + `, + output: ` +interface X { + a : number; + abc: string +}; + `, + options: [{ align: 'colon' }], + errors: [{ messageId: 'extraKey' }], + }, + { + code: ` +interface X { + a : number; + abc: string +}; + `, + output: ` +interface X { + a : number; + abc: string +}; + `, + options: [{ align: { on: 'colon' } }], + errors: [{ messageId: 'extraKey' }], + }, + { + code: ` +interface X { + a : number; + abc: string +}; + `, + output: ` +interface X { + a : number; + abc : string +}; + `, + options: [{ align: 'colon', beforeColon: true, afterColon: true }], + errors: [{ messageId: 'missingKey' }], + }, + // no align + { + code: ` +interface X { + [x: number]: string; +} + `, + output: ` +interface X { + [x: number]: string; +} + `, + errors: [{ messageId: 'extraValue' }], + }, + { + code: ` +interface X { + [x: number]:string; +} + `, + output: ` +interface X { + [x: number]: string; +} + `, + errors: [{ messageId: 'missingValue' }], + }, + // singleLine / multiLine + { + code: ` +interface X { + a:number; + abc:string +}; + `, + output: ` +interface X { + a : number; + abc : string +}; + `, + options: [ + { + singleLine: { beforeColon: false, afterColon: false }, + multiLine: { beforeColon: true, afterColon: true }, + }, + ], + errors: [ + { messageId: 'missingKey' }, + { messageId: 'missingValue' }, + { messageId: 'missingKey' }, + { messageId: 'missingValue' }, + ], + }, + { + code: ` +interface X { a : number; abc : string; }; + `, + output: ` +interface X { a:number; abc:string; }; + `, + options: [ + { + singleLine: { beforeColon: false, afterColon: false }, + multiLine: { beforeColon: true, afterColon: true }, + }, + ], + errors: [ + { messageId: 'extraKey' }, + { messageId: 'extraValue' }, + { messageId: 'extraKey' }, + { messageId: 'extraValue' }, + ], + }, + { + code: ` +interface X { a : number; abc : string; }; + `, + output: ` +interface X { a: number; abc: string; }; + `, + options: [ + { + singleLine: { beforeColon: false, afterColon: true }, + multiLine: { beforeColon: true, afterColon: true }, + }, + ], + errors: [{ messageId: 'extraKey' }, { messageId: 'extraKey' }], + }, + { + code: ` +interface X { a:number; abc:string; }; + `, + output: ` +interface X { a : number; abc : string; }; + `, + options: [ + { + singleLine: { beforeColon: true, afterColon: true, mode: 'strict' }, + multiLine: { beforeColon: true, afterColon: true }, + }, + ], + errors: [ + { messageId: 'missingKey' }, + { messageId: 'missingValue' }, + { messageId: 'missingKey' }, + { messageId: 'missingValue' }, + ], + }, + { + code: ` +interface X { a:number; abc: string; }; + `, + output: ` +interface X { a : number; abc : string; }; + `, + options: [ + { + singleLine: { beforeColon: true, afterColon: true, mode: 'minimum' }, + multiLine: { beforeColon: true, afterColon: true }, + }, + ], + errors: [ + { messageId: 'missingKey' }, + { messageId: 'missingValue' }, + { messageId: 'missingKey' }, + ], + }, + { + code: ` +interface X { a : number; abc : string; }; + `, + output: ` +interface X { a:number; abc:string; }; + `, + options: [ + { + beforeColon: false, + afterColon: false, + }, + ], + errors: [ + { messageId: 'extraKey' }, + { messageId: 'extraValue' }, + { messageId: 'extraKey' }, + { messageId: 'extraValue' }, + ], + }, + { + code: ` +interface X { a:number; abc:string; }; + `, + output: ` +interface X { a : number; abc : string; }; + `, + options: [ + { + beforeColon: true, + afterColon: true, + mode: 'strict', + }, + ], + errors: [ + { messageId: 'missingKey' }, + { messageId: 'missingValue' }, + { messageId: 'missingKey' }, + { messageId: 'missingValue' }, + ], + }, + { + code: ` +type Wacky = { + a: number; + b: string; + agc: number; + middle: Date | { + inner: { + a: boolean; + bc: boolean; + "๐ŸŒท": "rose"; + } + [x: number]: string; + abc: boolean; + } +} & { + a: "string"; + abc: number; +} + `, + output: ` +type Wacky = { + a: number; + b: string; + agc: number; + middle: Date | { + inner: { + a: boolean; + bc: boolean; + "๐ŸŒท": "rose"; + } + [x: number]: string; + abc: boolean; + } +} & { + a: "string"; + abc: number; +} + `, + options: [{ align: 'value' }], + errors: [ + { messageId: 'missingValue' }, + { messageId: 'missingValue' }, + { messageId: 'missingValue' }, + { messageId: 'missingValue' }, + { messageId: 'missingValue' }, + { messageId: 'missingValue' }, + { messageId: 'missingValue' }, + ], + }, + { + code: ` +class Wacky { + a: number; + b?: string; + public z: number; + abc = 10; + private override xy: number; + static x = "test"; + static abcdef: number = 1; + get fn(): number { return 0; }; + inter: number; + get fn2(): number { + return 1; + }; + agc: number; + middle: Date | { + inner: { + a: boolean; + bc: boolean; + "๐ŸŒท": "rose"; + } + [x: number]: string; + abc: boolean; + } +} + `, + output: ` +class Wacky { + a: number; + b?: string; + public z: number; + abc = 10; + private override xy: number; + static x = "test"; + static abcdef: number = 1; + get fn(): number { return 0; }; + inter: number; + get fn2(): number { + return 1; + }; + agc: number; + middle: Date | { + inner: { + a: boolean; + bc: boolean; + "๐ŸŒท": "rose"; + } + [x: number]: string; + abc: boolean; + } +} + `, + options: [{ align: 'value' }], + errors: [ + { messageId: 'missingValue' }, + { messageId: 'missingValue' }, + { messageId: 'missingValue' }, + { messageId: 'missingValue' }, + { messageId: 'missingValue' }, + { messageId: 'missingValue' }, + { messageId: 'missingValue' }, + { messageId: 'missingValue' }, + { messageId: 'missingValue' }, + ], + }, + ], +}); diff --git a/packages/eslint-plugin/typings/eslint-rules.d.ts b/packages/eslint-plugin/typings/eslint-rules.d.ts index 09b54ae4a516..38682f60c5b2 100644 --- a/packages/eslint-plugin/typings/eslint-rules.d.ts +++ b/packages/eslint-plugin/typings/eslint-rules.d.ts @@ -141,6 +141,58 @@ declare module 'eslint/lib/rules/indent' { export = rule; } +declare module 'eslint/lib/rules/key-spacing' { + import type { TSESLint, TSESTree } from '@typescript-eslint/utils'; + import type { RuleFunction } from '@typescript-eslint/utils/dist/ts-eslint'; + + type Options = [ + { + beforeColon?: boolean; + afterColon?: boolean; + mode?: 'strict' | 'minimum'; + align?: + | 'value' + | 'colon' + | { + on?: 'value' | 'colon'; + beforeColon?: boolean; + afterColon?: boolean; + mode?: 'strict' | 'minimum'; + }; + singleLine?: { + beforeColon?: boolean; + afterColon?: boolean; + mode?: 'strict' | 'minimum'; + }; + multiLine?: { + beforeColon?: boolean; + afterColon?: boolean; + mode?: 'strict' | 'minimum'; + align?: + | 'value' + | 'colon' + | { + on?: 'value' | 'colon'; + beforeColon?: boolean; + afterColon?: boolean; + mode?: 'strict' | 'minimum'; + }; + }; + }, + ]; + type MessageIds = 'extraKey' | 'extraValue' | 'missingKey' | 'missingValue'; + + const rule: TSESLint.RuleModule< + MessageIds, + Options, + { + ObjectExpression: RuleFunction; + Property: RuleFunction; + } + >; + export = rule; +} + declare module 'eslint/lib/rules/keyword-spacing' { import type { TSESLint, TSESTree } from '@typescript-eslint/utils'; import type { RuleFunction } from '@typescript-eslint/utils/dist/ts-eslint'; From 033e87cb71a54c895a6165da3fe514bb5ba5b6c6 Mon Sep 17 00:00:00 2001 From: Jeffrey Bosch Date: Wed, 25 Jan 2023 18:30:13 +0100 Subject: [PATCH 04/19] test: verify that there are no errors on the website (#6365) closes: #6354 --- packages/website/tests/index.spec.ts | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/packages/website/tests/index.spec.ts b/packages/website/tests/index.spec.ts index 1fd2a70b413d..e0a99f3d12cc 100644 --- a/packages/website/tests/index.spec.ts +++ b/packages/website/tests/index.spec.ts @@ -1,7 +1,22 @@ import AxeBuilder from '@axe-core/playwright'; -import { test } from '@playwright/test'; +import { expect, test } from '@playwright/test'; -test('Index', async ({ page }) => { - await page.goto('/'); - await new AxeBuilder({ page }).analyze(); +test.describe('Website', () => { + test('Axe', async ({ page }) => { + await page.goto('/'); + await new AxeBuilder({ page }).analyze(); + }); + + test('should have no errors', async ({ page }) => { + const errorMessages: string[] = []; + page.on('console', msg => { + if (['error', 'warning'].includes(msg.type())) { + errorMessages.push(`[${msg.type()}] ${msg.text()}`); + } + }); + await page.goto('/'); + expect(errorMessages).toStrictEqual([ + "[error] Warning: ReactDOM.render is no longer supported in React 18. Use createRoot instead. Until you switch to the new API, your app will behave as if it's running React 17. Learn more: https://reactjs.org/link/switch-to-createroot", + ]); + }); }); From b0f6c8ec0b372696ef26ca3a2b4f82dafd9dc417 Mon Sep 17 00:00:00 2001 From: Sviatoslav Zaytsev Date: Thu, 26 Jan 2023 19:18:52 +0300 Subject: [PATCH 05/19] fix(eslint-plugin): [prefer-optional-chain] fixer produces wrong logic (#5919) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix(eslint-plugin): [prefer-optional-chain] fixer produces wrong logic (#1438) * Update packages/eslint-plugin/src/rules/prefer-optional-chain.ts * fix(eslint-plugin): [prefer-optional-chain] fix tests * fix(eslint-plugin): [prefer-optional-chain] fix tests Co-authored-by: Josh Goldberg Co-authored-by: ะกะฒัั‚ะพัะปะฐะฒ ะ—ะฐะนั†ะตะฒ --- .../src/rules/prefer-optional-chain.ts | 16 +- .../rules/prefer-optional-chain/base-cases.ts | 228 ++++++++++++++++++ .../prefer-optional-chain.test.ts | 208 +++------------- 3 files changed, 273 insertions(+), 179 deletions(-) create mode 100644 packages/eslint-plugin/tests/rules/prefer-optional-chain/base-cases.ts rename packages/eslint-plugin/tests/rules/{ => prefer-optional-chain}/prefer-optional-chain.test.ts (85%) diff --git a/packages/eslint-plugin/src/rules/prefer-optional-chain.ts b/packages/eslint-plugin/src/rules/prefer-optional-chain.ts index 9a4949b734bc..f5ed3ccb5897 100644 --- a/packages/eslint-plugin/src/rules/prefer-optional-chain.ts +++ b/packages/eslint-plugin/src/rules/prefer-optional-chain.ts @@ -490,10 +490,20 @@ function reportIfMoreThanOne({ shouldHandleChainedAnds && previous.right.type === AST_NODE_TYPES.BinaryExpression ) { + let operator = previous.right.operator; + if ( + previous.right.operator === '!==' && + // TODO(#4820): Use the type checker to know whether this is `null` + previous.right.right.type === AST_NODE_TYPES.Literal && + previous.right.right.raw === 'null' + ) { + // case like foo !== null && foo.bar !== null + operator = '!='; + } // case like foo && foo.bar !== someValue - optionallyChainedCode += ` ${ - previous.right.operator - } ${sourceCode.getText(previous.right.right)}`; + optionallyChainedCode += ` ${operator} ${sourceCode.getText( + previous.right.right, + )}`; } context.report({ diff --git a/packages/eslint-plugin/tests/rules/prefer-optional-chain/base-cases.ts b/packages/eslint-plugin/tests/rules/prefer-optional-chain/base-cases.ts new file mode 100644 index 000000000000..99cfe6b0ff9b --- /dev/null +++ b/packages/eslint-plugin/tests/rules/prefer-optional-chain/base-cases.ts @@ -0,0 +1,228 @@ +import type { TSESLint } from '@typescript-eslint/utils'; + +import type rule from '../../../src/rules/prefer-optional-chain'; +import type { + InferMessageIdsTypeFromRule, + InferOptionsTypeFromRule, +} from '../../../src/util'; + +type InvalidTestCase = TSESLint.InvalidTestCase< + InferMessageIdsTypeFromRule, + InferOptionsTypeFromRule +>; + +interface BaseCase { + canReplaceAndWithOr: boolean; + output: string; + code: string; +} + +const mapper = (c: BaseCase): InvalidTestCase => ({ + code: c.code.trim(), + output: null, + errors: [ + { + messageId: 'preferOptionalChain', + suggestions: [ + { + messageId: 'optionalChainSuggest', + output: c.output.trim(), + }, + ], + }, + ], +}); + +const baseCases: Array = [ + // chained members + { + code: 'foo && foo.bar', + output: 'foo?.bar', + canReplaceAndWithOr: true, + }, + { + code: 'foo.bar && foo.bar.baz', + output: 'foo.bar?.baz', + canReplaceAndWithOr: true, + }, + { + code: 'foo && foo()', + output: 'foo?.()', + canReplaceAndWithOr: true, + }, + { + code: 'foo.bar && foo.bar()', + output: 'foo.bar?.()', + canReplaceAndWithOr: true, + }, + { + code: 'foo && foo.bar && foo.bar.baz && foo.bar.baz.buzz', + output: 'foo?.bar?.baz?.buzz', + canReplaceAndWithOr: true, + }, + { + code: 'foo.bar && foo.bar.baz && foo.bar.baz.buzz', + output: 'foo.bar?.baz?.buzz', + canReplaceAndWithOr: true, + }, + // case with a jump (i.e. a non-nullish prop) + { + code: 'foo && foo.bar && foo.bar.baz.buzz', + output: 'foo?.bar?.baz.buzz', + canReplaceAndWithOr: true, + }, + { + code: 'foo.bar && foo.bar.baz.buzz', + output: 'foo.bar?.baz.buzz', + canReplaceAndWithOr: true, + }, + // case where for some reason there is a doubled up expression + { + code: 'foo && foo.bar && foo.bar.baz && foo.bar.baz && foo.bar.baz.buzz', + output: 'foo?.bar?.baz?.buzz', + canReplaceAndWithOr: true, + }, + { + code: 'foo.bar && foo.bar.baz && foo.bar.baz && foo.bar.baz.buzz', + output: 'foo.bar?.baz?.buzz', + canReplaceAndWithOr: true, + }, + // chained members with element access + { + code: 'foo && foo[bar] && foo[bar].baz && foo[bar].baz.buzz', + output: 'foo?.[bar]?.baz?.buzz', + canReplaceAndWithOr: true, + }, + { + // case with a jump (i.e. a non-nullish prop) + code: 'foo && foo[bar].baz && foo[bar].baz.buzz', + output: 'foo?.[bar].baz?.buzz', + canReplaceAndWithOr: true, + }, + // case with a property access in computed property + { + code: 'foo && foo[bar.baz] && foo[bar.baz].buzz', + output: 'foo?.[bar.baz]?.buzz', + canReplaceAndWithOr: true, + }, + // case with this keyword + { + code: 'foo[this.bar] && foo[this.bar].baz', + output: 'foo[this.bar]?.baz', + canReplaceAndWithOr: true, + }, + // chained calls + { + code: 'foo && foo.bar && foo.bar.baz && foo.bar.baz.buzz()', + output: 'foo?.bar?.baz?.buzz()', + canReplaceAndWithOr: true, + }, + { + code: 'foo && foo.bar && foo.bar.baz && foo.bar.baz.buzz && foo.bar.baz.buzz()', + output: 'foo?.bar?.baz?.buzz?.()', + canReplaceAndWithOr: true, + }, + { + code: 'foo.bar && foo.bar.baz && foo.bar.baz.buzz && foo.bar.baz.buzz()', + output: 'foo.bar?.baz?.buzz?.()', + canReplaceAndWithOr: true, + }, + // case with a jump (i.e. a non-nullish prop) + { + code: 'foo && foo.bar && foo.bar.baz.buzz()', + output: 'foo?.bar?.baz.buzz()', + canReplaceAndWithOr: true, + }, + { + code: 'foo.bar && foo.bar.baz.buzz()', + output: 'foo.bar?.baz.buzz()', + canReplaceAndWithOr: true, + }, + { + // case with a jump (i.e. a non-nullish prop) + code: 'foo && foo.bar && foo.bar.baz.buzz && foo.bar.baz.buzz()', + output: 'foo?.bar?.baz.buzz?.()', + canReplaceAndWithOr: true, + }, + { + // case with a call expr inside the chain for some inefficient reason + code: 'foo && foo.bar() && foo.bar().baz && foo.bar().baz.buzz && foo.bar().baz.buzz()', + output: 'foo?.bar()?.baz?.buzz?.()', + canReplaceAndWithOr: true, + }, + // chained calls with element access + { + code: 'foo && foo.bar && foo.bar.baz && foo.bar.baz[buzz]()', + output: 'foo?.bar?.baz?.[buzz]()', + canReplaceAndWithOr: true, + }, + { + code: 'foo && foo.bar && foo.bar.baz && foo.bar.baz[buzz] && foo.bar.baz[buzz]()', + output: 'foo?.bar?.baz?.[buzz]?.()', + canReplaceAndWithOr: true, + }, + // (partially) pre-optional chained + { + code: 'foo && foo?.bar && foo?.bar.baz && foo?.bar.baz[buzz] && foo?.bar.baz[buzz]()', + output: 'foo?.bar?.baz?.[buzz]?.()', + canReplaceAndWithOr: true, + }, + { + code: 'foo && foo?.bar.baz && foo?.bar.baz[buzz]', + output: 'foo?.bar.baz?.[buzz]', + canReplaceAndWithOr: true, + }, + { + code: 'foo && foo?.() && foo?.().bar', + output: 'foo?.()?.bar', + canReplaceAndWithOr: true, + }, + { + code: 'foo.bar && foo.bar?.() && foo.bar?.().baz', + output: 'foo.bar?.()?.baz', + canReplaceAndWithOr: true, + }, + { + code: 'foo !== null && foo.bar !== null', + output: 'foo?.bar != null', + canReplaceAndWithOr: false, + }, + { + code: 'foo != null && foo.bar != null', + output: 'foo?.bar != null', + canReplaceAndWithOr: false, + }, + { + code: 'foo != null && foo.bar !== null', + output: 'foo?.bar != null', + canReplaceAndWithOr: false, + }, + { + code: 'foo !== null && foo.bar != null', + output: 'foo?.bar != null', + canReplaceAndWithOr: false, + }, +]; + +interface Selector { + all(): Array; + select>( + key: K, + value: BaseCase[K], + ): Selector; +} + +const selector = (cases: Array): Selector => ({ + all: () => cases.map(mapper), + select: >( + key: K, + value: BaseCase[K], + ): Selector => { + const selectedCases = baseCases.filter(c => c[key] === value); + return selector(selectedCases); + }, +}); + +const { all, select } = selector(baseCases); + +export { all, select }; diff --git a/packages/eslint-plugin/tests/rules/prefer-optional-chain.test.ts b/packages/eslint-plugin/tests/rules/prefer-optional-chain/prefer-optional-chain.test.ts similarity index 85% rename from packages/eslint-plugin/tests/rules/prefer-optional-chain.test.ts rename to packages/eslint-plugin/tests/rules/prefer-optional-chain/prefer-optional-chain.test.ts index 120ad20aaeac..ca783df13b32 100644 --- a/packages/eslint-plugin/tests/rules/prefer-optional-chain.test.ts +++ b/packages/eslint-plugin/tests/rules/prefer-optional-chain/prefer-optional-chain.test.ts @@ -1,160 +1,11 @@ -import type { TSESLint } from '@typescript-eslint/utils'; - -import rule from '../../src/rules/prefer-optional-chain'; -import type { - InferMessageIdsTypeFromRule, - InferOptionsTypeFromRule, -} from '../../src/util'; -import { noFormat, RuleTester } from '../RuleTester'; +import rule from '../../../src/rules/prefer-optional-chain'; +import { noFormat, RuleTester } from '../../RuleTester'; +import * as BaseCases from './base-cases'; const ruleTester = new RuleTester({ parser: '@typescript-eslint/parser', }); -const baseCases = [ - // chained members - { - code: 'foo && foo.bar', - output: 'foo?.bar', - }, - { - code: 'foo.bar && foo.bar.baz', - output: 'foo.bar?.baz', - }, - { - code: 'foo && foo()', - output: 'foo?.()', - }, - { - code: 'foo.bar && foo.bar()', - output: 'foo.bar?.()', - }, - { - code: 'foo && foo.bar && foo.bar.baz && foo.bar.baz.buzz', - output: 'foo?.bar?.baz?.buzz', - }, - { - code: 'foo.bar && foo.bar.baz && foo.bar.baz.buzz', - output: 'foo.bar?.baz?.buzz', - }, - // case with a jump (i.e. a non-nullish prop) - { - code: 'foo && foo.bar && foo.bar.baz.buzz', - output: 'foo?.bar?.baz.buzz', - }, - { - code: 'foo.bar && foo.bar.baz.buzz', - output: 'foo.bar?.baz.buzz', - }, - // case where for some reason there is a doubled up expression - { - code: 'foo && foo.bar && foo.bar.baz && foo.bar.baz && foo.bar.baz.buzz', - output: 'foo?.bar?.baz?.buzz', - }, - { - code: 'foo.bar && foo.bar.baz && foo.bar.baz && foo.bar.baz.buzz', - output: 'foo.bar?.baz?.buzz', - }, - // chained members with element access - { - code: 'foo && foo[bar] && foo[bar].baz && foo[bar].baz.buzz', - output: 'foo?.[bar]?.baz?.buzz', - }, - { - // case with a jump (i.e. a non-nullish prop) - code: 'foo && foo[bar].baz && foo[bar].baz.buzz', - output: 'foo?.[bar].baz?.buzz', - }, - // case with a property access in computed property - { - code: 'foo && foo[bar.baz] && foo[bar.baz].buzz', - output: 'foo?.[bar.baz]?.buzz', - }, - // case with this keyword - { - code: 'foo[this.bar] && foo[this.bar].baz', - output: 'foo[this.bar]?.baz', - }, - // chained calls - { - code: 'foo && foo.bar && foo.bar.baz && foo.bar.baz.buzz()', - output: 'foo?.bar?.baz?.buzz()', - }, - { - code: 'foo && foo.bar && foo.bar.baz && foo.bar.baz.buzz && foo.bar.baz.buzz()', - output: 'foo?.bar?.baz?.buzz?.()', - }, - { - code: 'foo.bar && foo.bar.baz && foo.bar.baz.buzz && foo.bar.baz.buzz()', - output: 'foo.bar?.baz?.buzz?.()', - }, - // case with a jump (i.e. a non-nullish prop) - { - code: 'foo && foo.bar && foo.bar.baz.buzz()', - output: 'foo?.bar?.baz.buzz()', - }, - { - code: 'foo.bar && foo.bar.baz.buzz()', - output: 'foo.bar?.baz.buzz()', - }, - { - // case with a jump (i.e. a non-nullish prop) - code: 'foo && foo.bar && foo.bar.baz.buzz && foo.bar.baz.buzz()', - output: 'foo?.bar?.baz.buzz?.()', - }, - { - // case with a call expr inside the chain for some inefficient reason - code: 'foo && foo.bar() && foo.bar().baz && foo.bar().baz.buzz && foo.bar().baz.buzz()', - output: 'foo?.bar()?.baz?.buzz?.()', - }, - // chained calls with element access - { - code: 'foo && foo.bar && foo.bar.baz && foo.bar.baz[buzz]()', - output: 'foo?.bar?.baz?.[buzz]()', - }, - { - code: 'foo && foo.bar && foo.bar.baz && foo.bar.baz[buzz] && foo.bar.baz[buzz]()', - output: 'foo?.bar?.baz?.[buzz]?.()', - }, - // (partially) pre-optional chained - { - code: 'foo && foo?.bar && foo?.bar.baz && foo?.bar.baz[buzz] && foo?.bar.baz[buzz]()', - output: 'foo?.bar?.baz?.[buzz]?.()', - }, - { - code: 'foo && foo?.bar.baz && foo?.bar.baz[buzz]', - output: 'foo?.bar.baz?.[buzz]', - }, - { - code: 'foo && foo?.() && foo?.().bar', - output: 'foo?.()?.bar', - }, - { - code: 'foo.bar && foo.bar?.() && foo.bar?.().baz', - output: 'foo.bar?.()?.baz', - }, -].map( - c => - ({ - code: c.code.trim(), - output: null, - errors: [ - { - messageId: 'preferOptionalChain', - suggestions: [ - { - messageId: 'optionalChainSuggest', - output: c.output.trim(), - }, - ], - }, - ], - } as TSESLint.InvalidTestCase< - InferMessageIdsTypeFromRule, - InferOptionsTypeFromRule - >), -); - ruleTester.run('prefer-optional-chain', rule, { valid: [ '!a || !b;', @@ -219,18 +70,18 @@ ruleTester.run('prefer-optional-chain', rule, { '!new.target || true;', ], invalid: [ - ...baseCases, + ...BaseCases.all(), // it should ignore whitespace in the expressions - ...baseCases.map(c => ({ + ...BaseCases.all().map(c => ({ ...c, code: c.code.replace(/\./g, '. '), })), - ...baseCases.map(c => ({ + ...BaseCases.all().map(c => ({ ...c, code: c.code.replace(/\./g, '.\n'), })), // it should ignore parts of the expression that aren't part of the expression chain - ...baseCases.map(c => ({ + ...BaseCases.all().map(c => ({ ...c, code: `${c.code} && bing`, errors: [ @@ -245,7 +96,7 @@ ruleTester.run('prefer-optional-chain', rule, { }, ], })), - ...baseCases.map(c => ({ + ...BaseCases.all().map(c => ({ ...c, code: `${c.code} && bing.bong`, errors: [ @@ -261,22 +112,42 @@ ruleTester.run('prefer-optional-chain', rule, { ], })), // strict nullish equality checks x !== null && x.y !== null - ...baseCases.map(c => ({ + ...BaseCases.all().map(c => ({ ...c, code: c.code.replace(/&&/g, '!== null &&'), })), - ...baseCases.map(c => ({ + ...BaseCases.all().map(c => ({ ...c, code: c.code.replace(/&&/g, '!= null &&'), })), - ...baseCases.map(c => ({ + ...BaseCases.all().map(c => ({ ...c, code: c.code.replace(/&&/g, '!== undefined &&'), })), - ...baseCases.map(c => ({ + ...BaseCases.all().map(c => ({ ...c, code: c.code.replace(/&&/g, '!= undefined &&'), })), + + // replace && with ||: foo && foo.bar -> !foo || !foo.bar + ...BaseCases.select('canReplaceAndWithOr', true) + .all() + .map(c => ({ + ...c, + code: c.code.replace(/(^|\s)foo/g, '$1!foo').replace(/&&/g, '||'), + errors: [ + { + ...c.errors[0], + suggestions: [ + { + ...c.errors[0].suggestions![0], + output: `!${c.errors[0].suggestions![0].output}`, + }, + ], + }, + ], + })), + // two errors { code: noFormat`foo && foo.bar && foo.bar.baz || baz && baz.bar && baz.bar.foo`, @@ -1211,21 +1082,6 @@ foo?.bar(/* comment */a, }, ], }, - ...baseCases.map(c => ({ - ...c, - code: c.code.replace(/foo/g, '!foo').replace(/&&/g, '||'), - errors: [ - { - ...c.errors[0], - suggestions: [ - { - ...c.errors[0].suggestions![0], - output: `!${c.errors[0].suggestions![0].output}`, - }, - ], - }, - ], - })), // case with this keyword at the start of expression { code: '!this.bar || !this.bar.baz;', From f17d34b74c83d4fed8dc4224d3594a6b44c19952 Mon Sep 17 00:00:00 2001 From: Josh Goldberg Date: Sun, 29 Jan 2023 20:44:01 -0500 Subject: [PATCH 06/19] docs(eslint-plugin): update site description of ban-types docs (#6209) --- packages/eslint-plugin/docs/rules/ban-types.md | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/packages/eslint-plugin/docs/rules/ban-types.md b/packages/eslint-plugin/docs/rules/ban-types.md index 016b2a7217e7..3f2e663669a8 100644 --- a/packages/eslint-plugin/docs/rules/ban-types.md +++ b/packages/eslint-plugin/docs/rules/ban-types.md @@ -72,12 +72,6 @@ The default options provide a set of "best practices", intended to provide safet - This is a point of confusion for many developers, who think it means "any object type". - See [this comment for more information](https://github.com/typescript-eslint/typescript-eslint/issues/2063#issuecomment-675156492). -:::important - -The default options suggest using `Record`; this was a stylistic decision, as the built-in `Record` type is considered to look cleaner. - -::: -
Default Options @@ -115,15 +109,16 @@ const defaultTypes = { Object: { message: [ 'The `Object` type actually means "any non-nullish value", so it is marginally better than `unknown`.', - '- If you want a type meaning "any object", you probably want `Record` instead.', + '- If you want a type meaning "any object", you probably want `object` instead.', '- If you want a type meaning "any value", you probably want `unknown` instead.', ].join('\n'), }, '{}': { message: [ '`{}` actually means "any non-nullish value".', - '- If you want a type meaning "any object", you probably want `Record` instead.', + '- If you want a type meaning "any object", you probably want `object` instead.', '- If you want a type meaning "any value", you probably want `unknown` instead.', + '- If you want a type meaning "empty object", you probably want `Record` instead.', ].join('\n'), }, }; From 1623350899c5d0ac8776933ca99f0561d0ec1827 Mon Sep 17 00:00:00 2001 From: Josh Goldberg Date: Sun, 29 Jan 2023 20:44:14 -0500 Subject: [PATCH 07/19] docs(eslint-plugin): corrected eslint-plugin README.md getting started link (#6223) --- packages/eslint-plugin/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/eslint-plugin/README.md b/packages/eslint-plugin/README.md index b9dd0cecd032..9c98f8c7d4b6 100644 --- a/packages/eslint-plugin/README.md +++ b/packages/eslint-plugin/README.md @@ -5,6 +5,6 @@ An ESLint plugin which provides lint rules for TypeScript codebases. [![NPM Version](https://img.shields.io/npm/v/@typescript-eslint/eslint-plugin.svg?style=flat-square)](https://www.npmjs.com/package/@typescript-eslint/eslint-plugin) [![NPM Downloads](https://img.shields.io/npm/dm/@typescript-eslint/eslint-plugin.svg?style=flat-square)](https://www.npmjs.com/package/@typescript-eslint/eslint-plugin) -๐Ÿ‘‰ See **https://typescript-eslint.io/architecture/utils** for our Getting Started docs. +๐Ÿ‘‰ See **https://typescript-eslint.io/getting-started** for our Getting Started docs. > See https://typescript-eslint.io for general documentation on typescript-eslint, the tooling that allows you to run ESLint and Prettier on TypeScript code. From 403f2afc1a33f9ef3d6e4f6b97894c4773424815 Mon Sep 17 00:00:00 2001 From: Josh Goldberg Date: Sun, 29 Jan 2023 20:44:55 -0500 Subject: [PATCH 08/19] docs: explained tsconfigRootDir in website (#6236) --- docs/architecture/Parser.mdx | 3 ++- docs/linting/Typed_Linting.md | 22 +++++++++++----------- 2 files changed, 13 insertions(+), 12 deletions(-) diff --git a/docs/architecture/Parser.mdx b/docs/architecture/Parser.mdx index 9f5d51a53bb6..d8d4f05ee43d 100644 --- a/docs/architecture/Parser.mdx +++ b/docs/architecture/Parser.mdx @@ -226,7 +226,8 @@ For example, by default it will ensure that a glob like `./**/tsconfig.json` wil > Default `undefined`. -This option allows you to provide the root directory for relative tsconfig paths specified in the `project` option above. +This option allows you to provide the root directory for relative TSConfig paths specified in the `project` option above. +Doing so ensures running ESLint from a directory other than the root will still be able to find your TSConfig. ### `warnOnUnsupportedTypeScriptVersion` diff --git a/docs/linting/Typed_Linting.md b/docs/linting/Typed_Linting.md index 3e1beb396a8a..65e2c875fff9 100644 --- a/docs/linting/Typed_Linting.md +++ b/docs/linting/Typed_Linting.md @@ -8,30 +8,30 @@ To tap into TypeScript's additional powers, there are two small changes you need ```js title=".eslintrc.js" module.exports = { - root: true, - parser: '@typescript-eslint/parser', - // Added lines start - parserOptions: { - tsconfigRootDir: __dirname, - project: ['./tsconfig.json'], - }, - // Added lines end - plugins: ['@typescript-eslint'], extends: [ 'eslint:recommended', 'plugin:@typescript-eslint/recommended', // Add this line 'plugin:@typescript-eslint/recommended-requiring-type-checking', ], + plugins: ['@typescript-eslint'], + parser: '@typescript-eslint/parser', + // Added lines start + parserOptions: { + project: ['./tsconfig.json'], + tsconfigRootDir: __dirname, + }, + // Added lines end + root: true, }; ``` In more detail: -- `parserOptions.tsconfigRootDir` tells our parser the absolute path of your project's root directory. +- `plugin:@typescript-eslint/recommended-requiring-type-checking` is another [recommended configuration](./CONFIGURATIONS.mdx) we provide. This one contains recommended rules that additionally require type information. - `parserOptions.project` tells our parser the relative path where your project's `tsconfig.json` is. - If your project is a multi-package monorepo, see [our docs on configuring a monorepo](./typed-linting/Monorepos.md). -- `plugin:@typescript-eslint/recommended-requiring-type-checking` is another recommended configuration we provide. This one contains rules that specifically require type information. +- `parserOptions.tsconfigRootDir` tells our parser the absolute path of your project's root directory (see [Parser#tsconfigRootDir](../architecture/Parser.mdx#tsconfigRootDir)). With that done, run the same lint command you ran before. You may see new rules reporting errors based on type information! From e8d2af308eb9e82181e47c553d13cda65083e678 Mon Sep 17 00:00:00 2001 From: Josh Goldberg Date: Sun, 29 Jan 2023 21:09:43 -0500 Subject: [PATCH 09/19] docs: added Contributing > Discussions page (#6249) --- .cspell.json | 1 + docs/contributing/Discussions.md | 28 +++++++++++++++++++++++ docs/maintenance/ISSUES.md | 2 +- packages/website/sidebars/sidebar.base.js | 1 + 4 files changed, 31 insertions(+), 1 deletion(-) create mode 100644 docs/contributing/Discussions.md diff --git a/.cspell.json b/.cspell.json index f1806362b478..edd2532abf92 100644 --- a/.cspell.json +++ b/.cspell.json @@ -62,6 +62,7 @@ "declarators", "destructure", "destructured", + "discoverability", "dprint", "errored", "erroring", diff --git a/docs/contributing/Discussions.md b/docs/contributing/Discussions.md new file mode 100644 index 000000000000..52de99914096 --- /dev/null +++ b/docs/contributing/Discussions.md @@ -0,0 +1,28 @@ +--- +id: discussions +title: Discussions +--- + +Most proposals in the typescript-eslint repository happen in [GitHub Issues](https://docs.github.com/issues). +We generally try to keep conversations inside issues for their discoverability and ability to be linked to [GitHub Pull Requests](https://docs.github.com/pull-requests). + +We have [GitHub Discussions](https://docs.github.com/discussions) enabled to enable three kinds of deeper, threaded conversations: + +- **Community Feedback**: Questions from the maintainer team that should be raised to the broader community +- **RFCs (Requests For Comments)**: Formalized proposals for larger changes that should be discussed before turned into issues +- **Technical Discussions**: Deeper questions about typescript-eslint's architecture and/or APIs + +Before filing a Discussion, search the issue tracker for any related conversations. +Link to them in the Discussion, along with a detailed description of what you'd like to discuss. + +:::tip +For change proposals that match an [existing issue format](https://github.com/typescript-eslint/typescript-eslint/issues/new/choose), keep to filing issues. +Most don't need to be moved to this separate format. +We can always move an issue to a discussion if it becomes unexpectedly deep. +::: + +:::caution +Please don't use Discussions as a support forum. +We don't have the maintainer-budget to handle that. +See [Issues > Questions and Support Requests](./Issues.mdx#questions-and-support-requests). +::: diff --git a/docs/maintenance/ISSUES.md b/docs/maintenance/ISSUES.md index ebddcc6df1b4..012ece57fff7 100644 --- a/docs/maintenance/ISSUES.md +++ b/docs/maintenance/ISSUES.md @@ -3,7 +3,7 @@ id: issues title: Issues --- -This document serves as a guide for how you might manage issues, also known as issue triaging. +This document serves as a guide for how you might manage our [GitHub Issues](https://docs.github.com/issues), also known as issue triaging. Use your best judgement when triaging issues, and most of all remember to be **kind, friendly, and encouraging** when responding to users. Many users are new to open source and/or typed linting. diff --git a/packages/website/sidebars/sidebar.base.js b/packages/website/sidebars/sidebar.base.js index e6e7401727f1..770ab620ec02 100644 --- a/packages/website/sidebars/sidebar.base.js +++ b/packages/website/sidebars/sidebar.base.js @@ -39,6 +39,7 @@ module.exports = { 'custom-rules', { items: [ + 'contributing/discussions', 'contributing/issues', 'contributing/local-development', 'contributing/pull-requests', From 2545b6828780612d31f270c4cba75bcbdcbc33c2 Mon Sep 17 00:00:00 2001 From: Josh Goldberg Date: Sun, 29 Jan 2023 21:16:52 -0500 Subject: [PATCH 10/19] docs(website): added maintenance docs for rule feature requests (#6254) --- docs/maintenance/ISSUES.md | 36 ++++++++++++++++++++++++++++++++---- 1 file changed, 32 insertions(+), 4 deletions(-) diff --git a/docs/maintenance/ISSUES.md b/docs/maintenance/ISSUES.md index 012ece57fff7..e7850e3a4b3c 100644 --- a/docs/maintenance/ISSUES.md +++ b/docs/maintenance/ISSUES.md @@ -93,13 +93,41 @@ These bugs should be reported with a link to a GitHub repository that can be che If you cannot reproduce the issue as described using repository's README.md and issue description, it has not provided enough information. Consider using a specific response like the _Needs Full Reproduction_ response. -### โœจ Rule Enhancements +### ๐Ÿ— Feature Requests -TODO: This will be filled out... soon! +For any feature request, make sure the requested support is either: -### ๐Ÿš€ New Rules +- Very useful for at least one commonly used way to run TypeScript (e.g. tsc-built CLI package; bundler-managed web app) +- Relevant for _most_ projects that would be using typescript-eslint -TODO: This will be filled out... soon! +We avoid features that: + +- Are only relevant for a minority of users, as they aren't likely worth the maintenance burden +- Aren't TypeScript-specific (e.g. should be in ESLint core instead) +- Are only relevant with specific userland frameworks or libraries, such as Jest or React +- Are for "formatting" functionality (we [strongly recommend users use a separate dedicated formatter](../linting/troubleshooting/FORMATTING.md)) + +#### โœจ Rule Enhancements + +We're generally accepting of rule enhancements that meet the above feature request criteria. +If a rule enhancement would substantially change the target area of the rule, consider whether it should instead be a new rule. +Common signs of this are the rule's original name now being inaccurate, or some options being relevant just for the old functionality. + +Enhancements that can cause new reports to be reported are considered breaking changes. +We have two common strategies for them: + +- Treat the enhancement as a breaking change, and block merging it until the next major version +- Add an option to disable the new logic: which is a breaking change if opt-in, and a non-breaking change if opt-out +- Add an option to enable the new logic: which is a breaking change if opt-out, and a non-breaking change if opt-in + +See [Can we standardize logical direction of rule options?](https://github.com/typescript-eslint/typescript-eslint/discussions/6101) for context on naming options. + +For enhancements meant to limit which kinds of nodes the rule targets, mark the issue as blocked on [RFC: Common format to specify a type or value as a rule option](https://github.com/typescript-eslint/typescript-eslint/discussions/6017). + +#### ๐Ÿš€ New Rules + +We're generally accepting of new rules that meet the above feature request criteria. +The biggest exception is rules that can roughly be implemented with [`@typescript-eslint/ban-types`](https://typescript-eslint.io/rules/ban-types) and/or [`no-restricted-syntax`](https://eslint.org/docs/latest/rules/no-restricted-syntax). ## Pruning Old Issues From f53bcbc4ba9d67612b61340a2c98d12fe9186985 Mon Sep 17 00:00:00 2001 From: Josh Goldberg Date: Mon, 30 Jan 2023 02:31:23 -0500 Subject: [PATCH 11/19] chore(website): add links to and widen Silver Supporters (#6327) --- .../FinancialContributors/Sponsor.tsx | 34 ++++++++----------- .../FinancialContributors/Sponsors/index.tsx | 8 ++--- .../Sponsors/styles.module.css | 1 - .../FinancialContributors/index.tsx | 3 +- .../FinancialContributors/styles.module.css | 15 ++++---- .../components/FinancialContributors/types.ts | 5 --- 6 files changed, 29 insertions(+), 37 deletions(-) diff --git a/packages/website/src/components/FinancialContributors/Sponsor.tsx b/packages/website/src/components/FinancialContributors/Sponsor.tsx index 06f53dd438f1..c50ab89b609c 100644 --- a/packages/website/src/components/FinancialContributors/Sponsor.tsx +++ b/packages/website/src/components/FinancialContributors/Sponsor.tsx @@ -1,17 +1,17 @@ import React from 'react'; import styles from './styles.module.css'; -import type { SponsorData, SponsorIncludeOptions } from './types'; +import type { SponsorData } from './types'; interface SponsorProps { - include?: SponsorIncludeOptions; + includeName?: boolean; sponsor: SponsorData; } -export function Sponsor({ include = {}, sponsor }: SponsorProps): JSX.Element { +export function Sponsor({ includeName, sponsor }: SponsorProps): JSX.Element { let children = {`${sponsor.name}; - if (include.name) { + if (includeName) { children = ( <> {children} @@ -20,19 +20,15 @@ export function Sponsor({ include = {}, sponsor }: SponsorProps): JSX.Element { ); } - if (include.link) { - children = ( - - {children} - - ); - } - - return children; + return ( + + {children} + + ); } diff --git a/packages/website/src/components/FinancialContributors/Sponsors/index.tsx b/packages/website/src/components/FinancialContributors/Sponsors/index.tsx index dfcdad8c7b96..6c2d8874593c 100644 --- a/packages/website/src/components/FinancialContributors/Sponsors/index.tsx +++ b/packages/website/src/components/FinancialContributors/Sponsors/index.tsx @@ -2,12 +2,12 @@ import clsx from 'clsx'; import React from 'react'; import { Sponsor } from '../Sponsor'; -import type { SponsorData, SponsorIncludeOptions } from '../types'; +import type { SponsorData } from '../types'; import styles from './styles.module.css'; interface SponsorsProps { className: string; - include?: SponsorIncludeOptions; + includeName?: boolean; expanded?: boolean; sponsors: SponsorData[]; title: string; @@ -16,7 +16,7 @@ interface SponsorsProps { export function Sponsors({ className, - include, + includeName, title, tier, sponsors, @@ -27,7 +27,7 @@ export function Sponsors({
    {sponsors.map(sponsor => (
  • - +
  • ))}
diff --git a/packages/website/src/components/FinancialContributors/Sponsors/styles.module.css b/packages/website/src/components/FinancialContributors/Sponsors/styles.module.css index b92051eddcba..526e1ab745eb 100644 --- a/packages/website/src/components/FinancialContributors/Sponsors/styles.module.css +++ b/packages/website/src/components/FinancialContributors/Sponsors/styles.module.css @@ -82,7 +82,6 @@ .tierArea { margin: 16px 0; width: auto; - padding: 0 60px; } .tier-gold-supporter { diff --git a/packages/website/src/components/FinancialContributors/index.tsx b/packages/website/src/components/FinancialContributors/index.tsx index d71bd0650045..0460e1e8694e 100644 --- a/packages/website/src/components/FinancialContributors/index.tsx +++ b/packages/website/src/components/FinancialContributors/index.tsx @@ -16,14 +16,13 @@ export function FinancialContributors(): JSX.Element {
Date: Mon, 30 Jan 2023 02:33:27 -0500 Subject: [PATCH 12/19] chore(website): mention 3 months SLA for issue and PR questions (#6313) --- docs/contributing/Issues.mdx | 1 + docs/contributing/Pull_Requests.mdx | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/contributing/Issues.mdx b/docs/contributing/Issues.mdx index ae61dd0e3123..d577248b2e61 100644 --- a/docs/contributing/Issues.mdx +++ b/docs/contributing/Issues.mdx @@ -21,6 +21,7 @@ Please don't: - Leave useless comments such as _"+1"_ or _"when's this getting fixed?"_ that only act as spam - If you have nothing to add but enthusiasm and joy, add a reaction such as ๐Ÿ‘ + - One exception: if an issue has been blocked on a question to a maintainer for 3 or more months, please ping us - we probably lost track of it - Bring up unrelated topics in existing issues: instead, file a new issue - Comment on closed PRs: instead, [file a new issue](#raising-issues) - Comment on commits directly, as those comments are not searchable: instead, file a new issue diff --git a/docs/contributing/Pull_Requests.mdx b/docs/contributing/Pull_Requests.mdx index edb76feb7d6f..c5af830718ce 100644 --- a/docs/contributing/Pull_Requests.mdx +++ b/docs/contributing/Pull_Requests.mdx @@ -19,8 +19,9 @@ Please don't: - Force push after opening a PR - Reasoning: GitHub is not able to track changes across force pushes, which makes it take longer for us to perform incremental reviews -- Comment asking for updates +- Comment on an existing PR asking for updates - Reasoning: Your PR hasn't been forgotten! The volunteer maintainers have limited time to work on the project, and they will get to it as soon as they are able. + - One exception: if a PR has been blocked on a question to a maintainer for 3 or more months, please ping us - we probably lost track of it. ### Raising a PR From 4b27777ed26cc83d6efc52a89b2d3fc6c01bc0d7 Mon Sep 17 00:00:00 2001 From: Yuri Pieters Date: Mon, 30 Jan 2023 07:39:36 +0000 Subject: [PATCH 13/19] fix(ast-spec): a JSXEmptyExpression is not a possible JSXExpression (#6321) --- packages/ast-spec/src/unions/JSXExpression.ts | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/packages/ast-spec/src/unions/JSXExpression.ts b/packages/ast-spec/src/unions/JSXExpression.ts index 78dfad53525b..d30c150cc6f0 100644 --- a/packages/ast-spec/src/unions/JSXExpression.ts +++ b/packages/ast-spec/src/unions/JSXExpression.ts @@ -1,8 +1,4 @@ -import type { JSXEmptyExpression } from '../jsx/JSXEmptyExpression/spec'; import type { JSXExpressionContainer } from '../jsx/JSXExpressionContainer/spec'; import type { JSXSpreadChild } from '../jsx/JSXSpreadChild/spec'; -export type JSXExpression = - | JSXEmptyExpression - | JSXExpressionContainer - | JSXSpreadChild; +export type JSXExpression = JSXExpressionContainer | JSXSpreadChild; From 587bd4ebc71061bc652f9a82ede250558785494b Mon Sep 17 00:00:00 2001 From: Josh Goldberg Date: Mon, 30 Jan 2023 15:05:09 -0500 Subject: [PATCH 14/19] docs: describe update steps for ESLint, Node, and TypeScript (#6251) * docs: describe update steps for ESLint, Node, and TypeScript * lil typo fix, and a heart * Finalize VERSIONING/Versioning.md rename --- .../{VERSIONING.md => Versioning.md} | 29 +++-- .../versioning/dependant-version-upgrades.mdx | 121 ++++++++++++++++++ .../src/parseSettings/warnAboutTSVersion.ts | 2 +- packages/website/sidebars/sidebar.base.js | 11 +- 4 files changed, 147 insertions(+), 16 deletions(-) rename docs/maintenance/{VERSIONING.md => Versioning.md} (95%) create mode 100644 docs/maintenance/versioning/dependant-version-upgrades.mdx diff --git a/docs/maintenance/VERSIONING.md b/docs/maintenance/Versioning.md similarity index 95% rename from docs/maintenance/VERSIONING.md rename to docs/maintenance/Versioning.md index 0dd31ae90c1b..d9a4224dbf8a 100644 --- a/docs/maintenance/VERSIONING.md +++ b/docs/maintenance/Versioning.md @@ -1,6 +1,5 @@ --- id: versioning -sidebar_label: Versioning title: Versioning --- @@ -28,9 +27,22 @@ During these periods, we manually publish `canary` releases until we are happy w ## Dependant Versions +> See [Versioning > Dependant Version Upgrades](./versioning/dependant-version-upgrades.mdx) for maintenance steps to update these versions. + +### ESLint + +> The version range of ESLint currently supported is `^6.0.0 || ^7.0.0 || ^8.0.0`. + +We generally support at least the latest two major versions of ESLint. + +### Node + +This project makes an effort to support Active LTS and Maintenance LTS release statuses of Node according to [Node's release document](https://nodejs.org/en/about/releases). +Support for specific Current status releases are considered periodically. + ### TypeScript -> The version range of TypeScript currently supported is `>=3.3.1 <4.9.0`. +> The version range of TypeScript currently supported is `>=3.3.1 <5.0.0`. These versions are what we test against. @@ -42,18 +54,7 @@ Note that our packages have an open `peerDependency` requirement in order to all If you use a non-supported version of TypeScript, the parser will log a warning to the console. If you want to disable this warning, you can configure this in your `parserOptions`. -See: [`@typescript-eslint/parser`](./packages/parser/ TODO JOSH) and [`@typescript-eslint/typescript-estree`](./packages/typescript-estree/ TODO JOSH). - -### ESLint - -> The version range of ESLint currently supported is `^6.0.0 || ^7.0.0 || ^8.0.0`. - -We generally support at least the latest two major versions of ESLint. - -### Node - -This project makes an effort to support Active LTS and Maintenance LTS release statuses of Node according to [Node's release document](https://nodejs.org/en/about/releases). -Support for specific Current status releases are considered periodically. +See: [Parser > `warnOnUnsupportedTypeScriptVersion`](../architecture/Parser.mdx#warnonunsupportedtypescriptversion). ## Breaking Changes diff --git a/docs/maintenance/versioning/dependant-version-upgrades.mdx b/docs/maintenance/versioning/dependant-version-upgrades.mdx new file mode 100644 index 000000000000..49ba51ce1e46 --- /dev/null +++ b/docs/maintenance/versioning/dependant-version-upgrades.mdx @@ -0,0 +1,121 @@ +--- +id: dependant-version-upgrades +title: Dependant Version Upgrades +--- + +## ESLint + +The typescript-eslint repository contains four kinds of version ranges for the `eslint` package: + +- Integration tests: Pinned to our lowest supported ESLint version +- Packages with a `*` `peerDependency` version: These fall back to the explicit `peerDependency` versions +- Packages with explicit `peerDependency` versions: The full range of supported ESLint major versions +- [Root `package.json`](https://github.com/typescript-eslint/typescript-eslint/blob/main/package.json)'s' `devDependency`: A relatively recent release, used only for repository development + +:::tip +Whenever you discover any new areas of work that are blocked by dropping an old ESLint version, such as new ESLint API deprecations, add a _TODO_ comment that will be caught by the regular expressions under [Removing Support for an Old ESLint Version](#removing-support-for-an-old-eslint-version). +::: + +### Adding Support for a New ESLint Version + +1. Upgrade the root `package.json` `devDependency` to the latest ESLint +1. Add the new major version to the explicit `peerDependency` versions +1. Check [`eslint-visitor-keys`](https://www.npmjs.com/package/eslint-visitor-keys) for a new version to be upgraded to as well. +1. Update [Versioning > ESLint](../Versioning.md#eslint) + +### Removing Support for an Old ESLint Version + +1. Increase the integration tests to the next lowest supported major version (`*.0.0`) +1. Remove the old major versions from packages with explicit `peerDependency` versions +1. Search for source code comments (excluding `CHANGELOG.md` files) that mention a now-unsupported version of ESLint. + - For example, to remove support for v5, searches might include: + - `/eslint.*5/i` + - `/todo.*eslint.*5/i` + - `/todo.*eslint/i` +1. Update [Versioning > ESLint](../Versioning.md#eslint) + +See [chore: drop support for ESLint v6](https://github.com/typescript-eslint/typescript-eslint/pull/5972) for reference. + +## Node + +The typescript-eslint repository contains three kinds of version ranges for Node: + +- [`.github/workflows/ci.yml`](https://github.com/typescript-eslint/typescript-eslint/blob/main/.github/workflows/ci.yml)'s `PRIMARY_NODE_VERSION`: Set to the highest Node version we support +- `node-version`: Set to a tuple of our [lowest, highest] supported versions for our unit tests in CI +- `engines` field in all `package.json`s: explicitly lists all supported Node ranges + +Change those numbers accordingly when adding support for a new Node version or removing support for an old Node version. + +See [feat: drop support for node v12](https://github.com/typescript-eslint/typescript-eslint/pull/5918) + [chore: test node v14 on ci.yml](https://github.com/typescript-eslint/typescript-eslint/pull/5512) for reference. + +## TypeScript + +### Adding Support for a New TypeScript Version + +We generally start the process of supporting a new TypeScript version just after the first beta release for that version is made available. + +1. Create and pin an issue with a title like _TypeScript X.Y Support_, `accepting prs`, `AST`, `dependencies`, and `New TypeScript Version` labels, and the following contents: + + 1. A link to the _TypeScript X.Y Iteration Plan_ issue from the Microsoft issue tracker + 2. The following text: + + ```md + This issue is just to track all of the new features and their implementation state in this project. + As with all releases, we will not necessarily support all features until closer to the full release when everything the features are stabilised. + + _Please be patient._ โค๏ธ + ``` + + 3. A heading starting with `๐Ÿ”ฒ ` for each new TypeScript feature called out in the iteration plan that will impact us + 4. A heading titled _๐Ÿ”ฒ `lib.d.ts` Updates_ and the content _We will need to regenerate our types within `scope-manager`_ + 5. A heading titled _Other changes with no impact to us_ containing a list of other changes that we don't believe will impact us + +1. At this stage, it's fine to send and/or review PRs that implement necessary features, but wait to merge them until the new TypeScript version's RC is released + - Whenever a PR is created, add ` (#1234)` to its respective heading, and change the heading's emoji from ๐Ÿ”ฒ to ๐Ÿ— + - Search for `expectBabelToNotSupport` to see how to support syntaxes not yet supported by Babel +1. Once the TypeScript RC version is released, start merging PRs + - Whenever a PR is merged, change the respective heading's emoji from ๐Ÿ— to โœ… +1. Create a PR with a title like `feat: update TypeScript to X.Y-rc` and the following changes: + - In the root `package.json`, add `|| X.Y.2-rc2` to the `dependency` on `typescript` + - In the root `package.json`, change the `devDependency` on `typescript` to `~X.Y.2-rc2` + - Change the `SUPPORTED_TYPESCRIPT_VERSIONS` constant's `<` version to the next version of TypeScript + - Change the `SUPPORTED_PRERELEASE_RANGES` constant to equal `['X.Y.2-rc']` + - Rename and update `patches/typescript*` to the new TypeScript version + - Run `yarn generate:lib` to update `scope-manager` +1. Once all PRs needed for the RC update PR are merged, merge the RC update PR +1. Once TypeScript releases the stable X.Y version, create and merge a PR with a title like `chore: bump TypeScript from X.YRC to X.Y` and the following changes: + - In the root `package.json`, remove `|| X.Y.2-rc2` from the `dependency` on `typescript`, and bump its `<` version to the next version of TypeScript + - In the root `package.json`, change the `devDependency` on `typescript` to `~X.Y.3` + - Rename and update `patches/typescript*` to the new TypeScript version + - Any other changes made necessary due to changes in TypeScript between the RC version and stable version + - Update the supported version range in [Versioning](../Versioning.md) +1. Update [Versioning > TypeScript](../Versioning.md#typescript) +1. Send a PR that updates this documentation page to point to your newer issues and PRs + - Also update any of these steps if you go with a different process + +See for reference (caveat: these don't follow the exact process described here): + +- [TypeScript 4.7 Support](https://github.com/typescript-eslint/typescript-eslint/issues/4800) +- [TypeScript 4.8 Support](https://github.com/typescript-eslint/typescript-eslint/issues/5227) +- [feat: support TypeScript 4.8](https://github.com/typescript-eslint/typescript-eslint/pull/5551) +- [feat: support TypeScript 4.9](https://github.com/typescript-eslint/typescript-eslint/pull/5716) +- [chore: bump TS from 4.9RC to 4.9](https://github.com/typescript-eslint/typescript-eslint/commit/a40a311bb52a2b1cfac43851b201f8cfc96c8d5d) + +### Removing Support for an Old TypeScript Version + +A single PR can remove support for old TypeScript versions as a breaking change: + +1. Update the root `package.json` `devDependency` +1. Update the `SUPPORTED_TYPESCRIPT_VERSIONS` constant in `warnAboutTSVersion.ts` +1. Update the `versions` constant in `version-check.ts` +1. Update [Versioning > TypeScript](../Versioning.md#typescript) +1. Search for source code comments (excluding `CHANGELOG.md` files) that mention a now-unsupported version of TypeScript. + - For example, to remove support for v4.3, searches might include: + - `4.3` + - `/is.*4.*3/i` + - `/semver.*4.*3/i` + - `/semver.satisfies/` + - `/todo.*ts/i` + - `/todo.*typescript/i` + +See [feat: bump minimum supported TS version to 4.2.4](https://github.com/typescript-eslint/typescript-eslint/pull/5915). diff --git a/packages/typescript-estree/src/parseSettings/warnAboutTSVersion.ts b/packages/typescript-estree/src/parseSettings/warnAboutTSVersion.ts index 191ac029325a..13eef19e7964 100644 --- a/packages/typescript-estree/src/parseSettings/warnAboutTSVersion.ts +++ b/packages/typescript-estree/src/parseSettings/warnAboutTSVersion.ts @@ -3,7 +3,7 @@ import * as ts from 'typescript'; import type { ParseSettings } from './index'; /** - * This needs to be kept in sync with /docs/maintenance/VERSIONING.md + * This needs to be kept in sync with /docs/maintenance/Versioning.md * in the typescript-eslint monorepo */ const SUPPORTED_TYPESCRIPT_VERSIONS = '>=3.3.1 <5.0.0'; diff --git a/packages/website/sidebars/sidebar.base.js b/packages/website/sidebars/sidebar.base.js index 770ab620ec02..7f0de7597287 100644 --- a/packages/website/sidebars/sidebar.base.js +++ b/packages/website/sidebars/sidebar.base.js @@ -82,7 +82,16 @@ module.exports = { }, 'maintenance/pull-requests', 'maintenance/releases', - 'maintenance/versioning', + { + collapsible: false, + items: ['maintenance/versioning/dependant-version-upgrades'], + label: 'Versioning', + link: { + id: 'maintenance/versioning', + type: 'doc', + }, + type: 'category', + }, ], label: 'Maintenance', link: { From ca190def071c56c0ebbdbbdfdcb31d2eb2c11809 Mon Sep 17 00:00:00 2001 From: Josh Goldberg Date: Mon, 30 Jan 2023 15:06:52 -0500 Subject: [PATCH 15/19] chore(website): reorganized sidebar and header nav a bit (#6311) * chore(website): reorganized sidebar and header nav a bit * Fix Formatting.md link case --- docs/maintenance/ISSUES.md | 2 +- packages/website/docusaurusConfig.ts | 2 +- packages/website/sidebars/sidebar.base.js | 28 +++++++++++------------ 3 files changed, 16 insertions(+), 16 deletions(-) diff --git a/docs/maintenance/ISSUES.md b/docs/maintenance/ISSUES.md index e7850e3a4b3c..fb5eb655dd69 100644 --- a/docs/maintenance/ISSUES.md +++ b/docs/maintenance/ISSUES.md @@ -105,7 +105,7 @@ We avoid features that: - Are only relevant for a minority of users, as they aren't likely worth the maintenance burden - Aren't TypeScript-specific (e.g. should be in ESLint core instead) - Are only relevant with specific userland frameworks or libraries, such as Jest or React -- Are for "formatting" functionality (we [strongly recommend users use a separate dedicated formatter](../linting/troubleshooting/FORMATTING.md)) +- Are for "formatting" functionality (we [strongly recommend users use a separate dedicated formatter](../linting/troubleshooting/Formatting.md)) #### โœจ Rule Enhancements diff --git a/packages/website/docusaurusConfig.ts b/packages/website/docusaurusConfig.ts index bfa844fc2f0b..ab543e80783e 100644 --- a/packages/website/docusaurusConfig.ts +++ b/packages/website/docusaurusConfig.ts @@ -76,7 +76,7 @@ const themeConfig: ThemeCommonConfig & AlgoliaThemeConfig = { items: [ { to: 'getting-started/', - label: 'Getting started', + label: 'Docs', position: 'left', }, { diff --git a/packages/website/sidebars/sidebar.base.js b/packages/website/sidebars/sidebar.base.js index 7f0de7597287..2a097b02a703 100644 --- a/packages/website/sidebars/sidebar.base.js +++ b/packages/website/sidebars/sidebar.base.js @@ -37,20 +37,6 @@ module.exports = { type: 'category', }, 'custom-rules', - { - items: [ - 'contributing/discussions', - 'contributing/issues', - 'contributing/local-development', - 'contributing/pull-requests', - ], - label: 'Contributing', - link: { - id: 'contributing', - type: 'doc', - }, - type: 'category', - }, { items: [ 'architecture/eslint-plugin', @@ -67,6 +53,20 @@ module.exports = { }, type: 'category', }, + { + items: [ + 'contributing/discussions', + 'contributing/issues', + 'contributing/local-development', + 'contributing/pull-requests', + ], + label: 'Contributing', + link: { + id: 'contributing', + type: 'doc', + }, + type: 'category', + }, { items: [ 'maintenance/branding', From 202d9fb3209c87f25671119296046ef78270b558 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 30 Jan 2023 23:40:14 +0000 Subject: [PATCH 16/19] chore(deps): update dependency eslint-plugin-simple-import-sort to v10 (#6391) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- package.json | 2 +- yarn.lock | 78 ++++------------------------------------------------ 2 files changed, 7 insertions(+), 73 deletions(-) diff --git a/package.json b/package.json index 16fef2bf3ba0..8324e5d971df 100644 --- a/package.json +++ b/package.json @@ -86,7 +86,7 @@ "eslint-plugin-eslint-plugin": "^5.0.1", "eslint-plugin-import": "^2.26.0", "eslint-plugin-jest": "^27.0.0", - "eslint-plugin-simple-import-sort": "^9.0.0", + "eslint-plugin-simple-import-sort": "^10.0.0", "execa": "5.1.1", "glob": "^8.0.1", "husky": "^8.0.1", diff --git a/yarn.lock b/yarn.lock index a1ed83510144..e88792c6fec5 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3246,13 +3246,6 @@ read-package-json-fast "^2.0.3" which "^2.0.2" -"@nrwl/cli@15.4.5": - version "15.4.5" - resolved "https://registry.yarnpkg.com/@nrwl/cli/-/cli-15.4.5.tgz#2a8f663e5265379812ba83c0577abdc94dcdba8f" - integrity sha512-f13s0/hzS9jsV1+QPr1Lp3Um+3dOHD8gEP2h7uw17rEPrtJ5ggRKMj/HcZ9dkT9zDM9EmPtVTb6k38ON+NWcUw== - dependencies: - nx "15.4.5" - "@nrwl/cli@15.5.3": version "15.5.3" resolved "https://registry.npmjs.org/@nrwl/cli/-/cli-15.5.3.tgz#13277e5a0e8ba713850bcf13fa76717ea747a2bb" @@ -3260,7 +3253,7 @@ dependencies: nx "15.5.3" -"@nrwl/devkit@15.5.3": +"@nrwl/devkit@15.5.3", "@nrwl/devkit@>=15.4.2 < 16": version "15.5.3" resolved "https://registry.npmjs.org/@nrwl/devkit/-/devkit-15.5.3.tgz#16fac0147c2ab6ebba7b5357b2b959ad46b6eb26" integrity sha512-GGNLLGXDGWflrpaLimnE6hChfZfq3+XWZ0LJWL0IuCnchngPbNzuyh8S8KPgNKKgq4Nv0hglWefIwMg2UhHysA== @@ -3271,17 +3264,6 @@ semver "7.3.4" tslib "^2.3.0" -"@nrwl/devkit@>=15.4.2 < 16": - version "15.4.5" - resolved "https://registry.yarnpkg.com/@nrwl/devkit/-/devkit-15.4.5.tgz#22b7aa16bc14c171f061f770060d9af480d5f1cb" - integrity sha512-oag+wJgusKz+rwvgcVy9i8bNtTo7ikbjVVtSOmyVBE0ZrgN1CMFjugBj4FEjKGtd73djjpvW9Mm36uJRujrc2w== - dependencies: - "@phenomnomnominal/tsquery" "4.1.1" - ejs "^3.1.7" - ignore "^5.0.4" - semver "7.3.4" - tslib "^2.3.0" - "@nrwl/jest@15.5.3": version "15.5.3" resolved "https://registry.npmjs.org/@nrwl/jest/-/jest-15.5.3.tgz#492ab42ac3171354a9afd6f93a7c43a6c56b3f61" @@ -3324,13 +3306,6 @@ tar "6.1.11" yargs-parser ">=21.0.1" -"@nrwl/tao@15.4.5": - version "15.4.5" - resolved "https://registry.yarnpkg.com/@nrwl/tao/-/tao-15.4.5.tgz#d07f6d06cecb6acb84259e0654cfc59fcc5edd53" - integrity sha512-UMtxXxTWqbyZOdyD9Zt2IsDY/JVXIFZtY6pO4jPha7+UIHWf2Zi8Dszs6UoUTS4mqpNMIkKymwpZGtkDTfiAJA== - dependencies: - nx "15.4.5" - "@nrwl/tao@15.5.3": version "15.5.3" resolved "https://registry.npmjs.org/@nrwl/tao/-/tao-15.5.3.tgz#08c05715d2ecb108ed8b2c5381b9017cf1448b4a" @@ -7135,10 +7110,10 @@ eslint-plugin-react@^7.29.4: semver "^6.3.0" string.prototype.matchall "^4.0.7" -eslint-plugin-simple-import-sort@^9.0.0: - version "9.0.0" - resolved "https://registry.yarnpkg.com/eslint-plugin-simple-import-sort/-/eslint-plugin-simple-import-sort-9.0.0.tgz#04c97f06a2e526afd40e0ac694b70d1aaaec1aef" - integrity sha512-PtrLjyXP8kjRneWT1n0b99y/2Fyup37we7FVoWsI61/O7x4ztLohzhep/pxI/cYlECr/cQ2j6utckdvWpVwXNA== +eslint-plugin-simple-import-sort@^10.0.0: + version "10.0.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-simple-import-sort/-/eslint-plugin-simple-import-sort-10.0.0.tgz#cc4ceaa81ba73252427062705b64321946f61351" + integrity sha512-AeTvO9UCMSNzIHRkg8S6c3RPy5YEwKWSQPx3DYghLedo2ZQxowPFLGDN1AZ2evfg6r6mjBSZSLxLFsWSu3acsw== eslint-scope@5.1.1, eslint-scope@^5.1.1: version "5.1.1" @@ -10794,48 +10769,7 @@ nth-check@^2.0.0, nth-check@^2.0.1: dependencies: boolbase "^1.0.0" -nx@15.4.5, "nx@>=15.4.2 < 16": - version "15.4.5" - resolved "https://registry.yarnpkg.com/nx/-/nx-15.4.5.tgz#12daa740256fa29ba634fbc4f3f87b6d078c2990" - integrity sha512-1spZL6sgOV8JJJuN8W5CLtJYwTOnlyaV32jPXfidavU0QMS8MP+rW3+NUQ9Uzc1UYhOu8llZWtnen93neVGQRw== - dependencies: - "@nrwl/cli" "15.4.5" - "@nrwl/tao" "15.4.5" - "@parcel/watcher" "2.0.4" - "@yarnpkg/lockfile" "^1.1.0" - "@yarnpkg/parsers" "^3.0.0-rc.18" - "@zkochan/js-yaml" "0.0.6" - axios "^1.0.0" - chalk "4.1.0" - chokidar "^3.5.1" - cli-cursor "3.1.0" - cli-spinners "2.6.1" - cliui "^7.0.2" - dotenv "~10.0.0" - enquirer "~2.3.6" - fast-glob "3.2.7" - figures "3.2.0" - flat "^5.0.2" - fs-extra "^10.1.0" - glob "7.1.4" - ignore "^5.0.4" - js-yaml "4.1.0" - jsonc-parser "3.2.0" - minimatch "3.0.5" - npm-run-path "^4.0.1" - open "^8.4.0" - semver "7.3.4" - string-width "^4.2.3" - strong-log-transformer "^2.1.0" - tar-stream "~2.2.0" - tmp "~0.2.1" - tsconfig-paths "^4.1.2" - tslib "^2.3.0" - v8-compile-cache "2.3.0" - yargs "^17.6.2" - yargs-parser "21.1.1" - -nx@15.5.3: +nx@15.5.3, "nx@>=15.4.2 < 16": version "15.5.3" resolved "https://registry.npmjs.org/nx/-/nx-15.5.3.tgz#bf6252e7d9e17121dd82dec4f6fce319b9e005fa" integrity sha512-PHB8VbiBLP108xb+yR8IGEsYWr7OcmDDOjHL+73oP4lVjyPgT8wdTMe6tI5LdBgv+KZ+0kiThK3ckvcPsfgvLQ== From 85e783c1fabe96d390729a5796d6d346e401692b Mon Sep 17 00:00:00 2001 From: Omri Luzon Date: Tue, 31 Jan 2023 09:21:23 +0200 Subject: [PATCH 17/19] fix(eslint-plugin): [prefer-optional-chain] fix `ThisExpression` and `PrivateIdentifier` errors (#6028) --- .../src/rules/prefer-optional-chain.ts | 46 +++++++++++++------ .../prefer-optional-chain.test.ts | 15 +++++- 2 files changed, 46 insertions(+), 15 deletions(-) diff --git a/packages/eslint-plugin/src/rules/prefer-optional-chain.ts b/packages/eslint-plugin/src/rules/prefer-optional-chain.ts index f5ed3ccb5897..efccc2ccfd2d 100644 --- a/packages/eslint-plugin/src/rules/prefer-optional-chain.ts +++ b/packages/eslint-plugin/src/rules/prefer-optional-chain.ts @@ -10,6 +10,7 @@ type ValidChainTarget = | TSESTree.CallExpression | TSESTree.ChainExpression | TSESTree.Identifier + | TSESTree.PrivateIdentifier | TSESTree.MemberExpression | TSESTree.ThisExpression | TSESTree.MetaProperty; @@ -164,7 +165,9 @@ export default util.createRule({ break; } + let invalidOptionallyChainedPrivateProperty; ({ + invalidOptionallyChainedPrivateProperty, expressionCount, previousLeftText, optionallyChainedCode, @@ -178,6 +181,9 @@ export default util.createRule({ previous, current, )); + if (invalidOptionallyChainedPrivateProperty) { + return; + } } reportIfMoreThanOne({ @@ -243,7 +249,9 @@ export default util.createRule({ break; } + let invalidOptionallyChainedPrivateProperty; ({ + invalidOptionallyChainedPrivateProperty, expressionCount, previousLeftText, optionallyChainedCode, @@ -257,6 +265,9 @@ export default util.createRule({ previous, current, )); + if (invalidOptionallyChainedPrivateProperty) { + return; + } } reportIfMoreThanOne({ @@ -343,7 +354,10 @@ export default util.createRule({ return `${calleeText}${argumentsText}`; } - if (node.type === AST_NODE_TYPES.Identifier) { + if ( + node.type === AST_NODE_TYPES.Identifier || + node.type === AST_NODE_TYPES.PrivateIdentifier + ) { return node.name; } @@ -381,15 +395,12 @@ export default util.createRule({ // cases should match the list in ALLOWED_MEMBER_OBJECT_TYPES switch (node.object.type) { - case AST_NODE_TYPES.CallExpression: - case AST_NODE_TYPES.Identifier: - objectText = getText(node.object); - break; - case AST_NODE_TYPES.MemberExpression: objectText = getMemberExpressionText(node.object); break; + case AST_NODE_TYPES.CallExpression: + case AST_NODE_TYPES.Identifier: case AST_NODE_TYPES.MetaProperty: case AST_NODE_TYPES.ThisExpression: objectText = getText(node.object); @@ -397,7 +408,7 @@ export default util.createRule({ /* istanbul ignore next */ default: - throw new Error(`Unexpected member object type: ${node.object.type}`); + return ''; } let propertyText: string; @@ -420,9 +431,7 @@ export default util.createRule({ /* istanbul ignore next */ default: - throw new Error( - `Unexpected member property type: ${node.object.type}`, - ); + return ''; } return `${objectText}${node.optional ? '?.' : ''}[${propertyText}]`; @@ -432,12 +441,12 @@ export default util.createRule({ case AST_NODE_TYPES.Identifier: propertyText = getText(node.property); break; + case AST_NODE_TYPES.PrivateIdentifier: + propertyText = '#' + getText(node.property); + break; - /* istanbul ignore next */ default: - throw new Error( - `Unexpected member property type: ${node.object.type}`, - ); + propertyText = sourceCode.getText(node.property); } return `${objectText}${node.optional ? '?.' : '.'}${propertyText}`; @@ -461,6 +470,7 @@ const ALLOWED_COMPUTED_PROP_TYPES: ReadonlySet = new Set([ ]); const ALLOWED_NON_COMPUTED_PROP_TYPES: ReadonlySet = new Set([ AST_NODE_TYPES.Identifier, + AST_NODE_TYPES.PrivateIdentifier, ]); interface ReportIfMoreThanOneOptions { @@ -525,6 +535,7 @@ function reportIfMoreThanOne({ } interface NormalizedPattern { + invalidOptionallyChainedPrivateProperty: boolean; expressionCount: number; previousLeftText: string; optionallyChainedCode: string; @@ -541,6 +552,7 @@ function normalizeRepeatingPatterns( current: TSESTree.Node, ): NormalizedPattern { const leftText = previousLeftText; + let invalidOptionallyChainedPrivateProperty = false; // omit weird doubled up expression that make no sense like foo.bar && foo.bar if (rightText !== previousLeftText) { expressionCount += 1; @@ -576,6 +588,11 @@ function normalizeRepeatingPatterns( diff === '?.buzz' */ const diff = rightText.replace(leftText, ''); + if (diff.startsWith('.#')) { + // Do not handle direct optional chaining on private properties because of a typescript bug (https://github.com/microsoft/TypeScript/issues/42734) + // We still allow in computed properties + invalidOptionallyChainedPrivateProperty = true; + } if (diff.startsWith('?')) { // item was "pre optional chained" optionallyChainedCode += diff; @@ -591,6 +608,7 @@ function normalizeRepeatingPatterns( util.NullThrowsReasons.MissingParent, ); return { + invalidOptionallyChainedPrivateProperty, expressionCount, previousLeftText, optionallyChainedCode, diff --git a/packages/eslint-plugin/tests/rules/prefer-optional-chain/prefer-optional-chain.test.ts b/packages/eslint-plugin/tests/rules/prefer-optional-chain/prefer-optional-chain.test.ts index ca783df13b32..a18de12bf7b1 100644 --- a/packages/eslint-plugin/tests/rules/prefer-optional-chain/prefer-optional-chain.test.ts +++ b/packages/eslint-plugin/tests/rules/prefer-optional-chain/prefer-optional-chain.test.ts @@ -45,6 +45,16 @@ ruleTester.run('prefer-optional-chain', rule, { 'match && match$1 !== undefined;', 'foo !== null && foo !== undefined;', "x['y'] !== undefined && x['y'] !== null;", + // private properties + 'this.#a && this.#b;', + '!this.#a || !this.#b;', + 'a.#foo?.bar;', + '!a.#foo?.bar;', + '!foo().#a || a;', + '!a.b.#a || a;', + '!new A().#b || a;', + '!(await a).#b || a;', + "!(foo as any).bar || 'anything';", // currently do not handle complex computed properties 'foo && foo[bar as string] && foo[bar as string].baz;', 'foo && foo[1 + 2] && foo[1 + 2].baz;', @@ -68,6 +78,10 @@ ruleTester.run('prefer-optional-chain', rule, { '!import.meta && !import.meta.foo;', 'new.target || new.target.length;', '!new.target || true;', + // Do not handle direct optional chaining on private properties because of a typescript bug (https://github.com/microsoft/TypeScript/issues/42734) + // We still allow in computed properties + 'foo && foo.#bar;', + '!foo || !foo.#bar;', ], invalid: [ ...BaseCases.all(), @@ -1240,7 +1254,6 @@ foo?.bar(/* comment */a, }, ], }, - { code: noFormat`import.meta && import.meta?.() && import.meta?.().baz;`, output: null, From a3ba163ccd73cf369c18493d5393003cc932cc23 Mon Sep 17 00:00:00 2001 From: James Henry Date: Tue, 31 Jan 2023 13:12:09 +0400 Subject: [PATCH 18/19] chore: update nx to 15.6 (#6387) --- nx.json | 35 ++++-- package.json | 6 +- packages/ast-spec/project.json | 2 +- packages/shared-fixtures/project.json | 4 +- .../type-utils/tests/isTypeReadonly.test.ts | 2 +- packages/website-eslint/project.json | 4 +- yarn.lock | 110 +++++++++++++----- 7 files changed, 113 insertions(+), 50 deletions(-) diff --git a/nx.json b/nx.json index b34a91f78001..731dc56a3c7a 100644 --- a/nx.json +++ b/nx.json @@ -1,22 +1,12 @@ { "$schema": "./node_modules/nx/schemas/nx-schema.json", "npmScope": "typescript-eslint", - "affected": { - "defaultBase": "main" - }, - "workspaceLayout": { - "libsDir": "packages" - }, "tasksRunnerOptions": { "default": { "runner": "@nrwl/nx-cloud", "options": { "cacheableOperations": ["build", "lint", "package", "prebuild", "test"], - "accessToken": "YjFjNTBhOWUtY2JmNy00ZDhiLWE5N2UtZjliNDAwNmIzOTdjfHJlYWQtd3JpdGU=", - "canTrackAnalytics": false, - "showUsageWarnings": true, - "runtimeCacheInputs": ["node -v", "echo $NETLIFY"], - "parallel": 1 + "accessToken": "YjFjNTBhOWUtY2JmNy00ZDhiLWE5N2UtZjliNDAwNmIzOTdjfHJlYWQtd3JpdGU=" } } }, @@ -26,11 +16,32 @@ "inputs": ["production", "^production"] }, "test": { + "inputs": [ + "default", + "{workspaceRoot}/jest.config.js", + "{workspaceRoot}/jest.config.base.js" + ], "outputs": ["{projectRoot}/coverage"] + }, + "lint": { + "inputs": [ + "default", + "{workspaceRoot}/.eslintrc.js", + "{workspaceRoot}/.eslintignore" + ] } }, "namedInputs": { - "default": ["{projectRoot}/**/*", "sharedGlobals"], + "default": [ + "{projectRoot}/**/*", + "sharedGlobals", + { + "runtime": "node -v" + }, + { + "runtime": "echo $NETLIFY" + } + ], "sharedGlobals": ["{workspaceRoot}/.github/workflows/ci.yml"], "production": ["default"] } diff --git a/package.json b/package.json index 8324e5d971df..f8b24d34edf6 100644 --- a/package.json +++ b/package.json @@ -54,9 +54,9 @@ "@babel/eslint-parser": "^7.19.1", "@babel/parser": "^7.20.7", "@babel/types": "^7.20.2", - "@nrwl/jest": "15.5.3", + "@nrwl/jest": "15.6.3", "@nrwl/nx-cloud": "15.0.2", - "@nrwl/workspace": "15.5.3", + "@nrwl/workspace": "15.6.3", "@swc/core": "^1.3.1", "@swc/jest": "^0.2.21", "@types/babel__code-frame": "^7.0.3", @@ -99,7 +99,7 @@ "make-dir": "^3.1.0", "markdownlint-cli": "^0.33.0", "ncp": "^2.0.0", - "nx": "15.5.3", + "nx": "15.6.3", "patch-package": "^6.4.7", "prettier": "2.8.1", "pretty-format": "^29.0.3", diff --git a/packages/ast-spec/project.json b/packages/ast-spec/project.json index 682cdbf3d91c..41721d18d711 100644 --- a/packages/ast-spec/project.json +++ b/packages/ast-spec/project.json @@ -10,7 +10,7 @@ "cwd": "packages/ast-spec", "commands": ["yarn build"] }, - "outputs": ["packages/ast-spec/dist/**/*.ts"] + "outputs": ["{projectRoot}/dist/**/*.ts"] }, "lint": { "executor": "@nrwl/linter:eslint", diff --git a/packages/shared-fixtures/project.json b/packages/shared-fixtures/project.json index 18cfac971353..412bca4935ff 100644 --- a/packages/shared-fixtures/project.json +++ b/packages/shared-fixtures/project.json @@ -1,6 +1,6 @@ { + "name": "shared-fixtures", "$schema": "../../node_modules/nx/schemas/project-schema.json", "type": "library", - "implicitDependencies": [], - "name": "shared-fixtures" + "implicitDependencies": [] } diff --git a/packages/type-utils/tests/isTypeReadonly.test.ts b/packages/type-utils/tests/isTypeReadonly.test.ts index 382091a23754..0b171dc12a2c 100644 --- a/packages/type-utils/tests/isTypeReadonly.test.ts +++ b/packages/type-utils/tests/isTypeReadonly.test.ts @@ -4,8 +4,8 @@ import path from 'path'; import type * as ts from 'typescript'; import { - type ReadonlynessOptions, isTypeReadonly, + type ReadonlynessOptions, } from '../src/isTypeReadonly'; describe('isTypeReadonly', () => { diff --git a/packages/website-eslint/project.json b/packages/website-eslint/project.json index 517439cbec3d..862c5b948f1f 100644 --- a/packages/website-eslint/project.json +++ b/packages/website-eslint/project.json @@ -1,6 +1,6 @@ { + "name": "website-eslint", "$schema": "../../node_modules/nx/schemas/project-schema.json", "type": "library", - "implicitDependencies": [], - "name": "website-eslint" + "implicitDependencies": [] } diff --git a/yarn.lock b/yarn.lock index e88792c6fec5..bbe5aba913b6 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3246,14 +3246,25 @@ read-package-json-fast "^2.0.3" which "^2.0.2" -"@nrwl/cli@15.5.3": - version "15.5.3" - resolved "https://registry.npmjs.org/@nrwl/cli/-/cli-15.5.3.tgz#13277e5a0e8ba713850bcf13fa76717ea747a2bb" - integrity sha512-NWf9CWswvdYM6YzXuweaZPAZ2erMtQrrHZdgFbUGeojZBZ+b4TCGzLWNodZj4yQOa/eTwlyPMYO2LEw9CoapDQ== +"@nrwl/cli@15.6.3": + version "15.6.3" + resolved "https://registry.npmjs.org/@nrwl/cli/-/cli-15.6.3.tgz#999531d6efb30afc39373bdcbd7e78254a3a3fd3" + integrity sha512-K4E0spofThZXMnhA6R8hkUTdfqmwSnUE2+DlD5Y3jqsvKTAgwF5U41IFkEouFZCf+dWjy0RA20bWoX48EVFtmQ== + dependencies: + nx "15.6.3" + +"@nrwl/devkit@15.6.3": + version "15.6.3" + resolved "https://registry.npmjs.org/@nrwl/devkit/-/devkit-15.6.3.tgz#e4e96c53ba3304786a49034286c8511534b2b194" + integrity sha512-/JDvdzNxUM+C1PCZPCrvmFx+OfywqZdOq1GS9QR8C0VctTLG4D/SGSFD88O1SAdcbH/f1mMiBGfEYZYd23fghQ== dependencies: - nx "15.5.3" + "@phenomnomnominal/tsquery" "4.1.1" + ejs "^3.1.7" + ignore "^5.0.4" + semver "7.3.4" + tslib "^2.3.0" -"@nrwl/devkit@15.5.3", "@nrwl/devkit@>=15.4.2 < 16": +"@nrwl/devkit@>=15.4.2 < 16": version "15.5.3" resolved "https://registry.npmjs.org/@nrwl/devkit/-/devkit-15.5.3.tgz#16fac0147c2ab6ebba7b5357b2b959ad46b6eb26" integrity sha512-GGNLLGXDGWflrpaLimnE6hChfZfq3+XWZ0LJWL0IuCnchngPbNzuyh8S8KPgNKKgq4Nv0hglWefIwMg2UhHysA== @@ -3264,14 +3275,14 @@ semver "7.3.4" tslib "^2.3.0" -"@nrwl/jest@15.5.3": - version "15.5.3" - resolved "https://registry.npmjs.org/@nrwl/jest/-/jest-15.5.3.tgz#492ab42ac3171354a9afd6f93a7c43a6c56b3f61" - integrity sha512-BSs4ZQJtRjQ+OAPHdfeemoAiYsGL3Zuq2Ezj8XwGp50SkgVLUBZdXg2Ld1ARjTh/d3pMg+Mf+yKfjoYqFzKx+A== +"@nrwl/jest@15.6.3": + version "15.6.3" + resolved "https://registry.npmjs.org/@nrwl/jest/-/jest-15.6.3.tgz#66b1c387352cbbf666959fd7fe921d4980c6084a" + integrity sha512-pG8ESEJFkgyBGOOVZ6bFohklkDXn7JrDPSjmnoKvcOzprluPS7Nx4Ce5bw7wk2Ul3fqJcpAcH5LAZvb+HtA85w== dependencies: "@jest/reporters" "28.1.1" "@jest/test-result" "28.1.1" - "@nrwl/devkit" "15.5.3" + "@nrwl/devkit" "15.6.3" "@phenomnomnominal/tsquery" "4.1.1" chalk "^4.1.0" dotenv "~10.0.0" @@ -3282,12 +3293,12 @@ resolve.exports "1.1.0" tslib "^2.3.0" -"@nrwl/linter@15.5.3": - version "15.5.3" - resolved "https://registry.npmjs.org/@nrwl/linter/-/linter-15.5.3.tgz#de9c10c51d2ec92d51cc89207f642d41493314ba" - integrity sha512-ZeUtLOT0olORBL4FpEXmJoaiSKq4VIffW/vmCbosRIuHZqL4Cye5uHyQ6/KJXjD44Z+P6QCkyfr0etcy3lhSkg== +"@nrwl/linter@15.6.3": + version "15.6.3" + resolved "https://registry.npmjs.org/@nrwl/linter/-/linter-15.6.3.tgz#9cffa150109c604827c06ce0ccd5c925d4cd7c01" + integrity sha512-efGOduHbUa/L6MuJLb2SoDwi4hEKpz6lM1X/Yg36dYDjLuJdpLC23K4WwEOQeZL6jkcUerfY65W8NMPinAHWKg== dependencies: - "@nrwl/devkit" "15.5.3" + "@nrwl/devkit" "15.6.3" "@phenomnomnominal/tsquery" "4.1.1" tmp "~0.2.1" tslib "^2.3.0" @@ -3306,20 +3317,20 @@ tar "6.1.11" yargs-parser ">=21.0.1" -"@nrwl/tao@15.5.3": - version "15.5.3" - resolved "https://registry.npmjs.org/@nrwl/tao/-/tao-15.5.3.tgz#08c05715d2ecb108ed8b2c5381b9017cf1448b4a" - integrity sha512-vgPLIW9IoBfQ4IkHRT5RC4LqNwFBK5jmHYmFIRgbIeFRudFBbnpmOaKRME0OwN7qJ6964PVVbzahAPvYVD02xw== +"@nrwl/tao@15.6.3": + version "15.6.3" + resolved "https://registry.npmjs.org/@nrwl/tao/-/tao-15.6.3.tgz#b24e11345375dea96bc386c60b9b1102a7584932" + integrity sha512-bDZbPIbU5Mf2BvX0q8GjPxrm1WkYyfW+gp7mLuuJth2sEpZiCr47mSwuGko/y4CKXvIX46VQcAS0pKQMKugXsg== dependencies: - nx "15.5.3" + nx "15.6.3" -"@nrwl/workspace@15.5.3": - version "15.5.3" - resolved "https://registry.npmjs.org/@nrwl/workspace/-/workspace-15.5.3.tgz#3343b0de3a0fb8b0b7176c0c3cb7c19907e1485e" - integrity sha512-/Udv+dF4Z/9GZ4QmdCu/6e4QUJYx7zGTcoCOZi+Pt+OPRqOULkBbfKmB+xtiG/D32WnFePsxcssaZGux/aysUQ== +"@nrwl/workspace@15.6.3": + version "15.6.3" + resolved "https://registry.npmjs.org/@nrwl/workspace/-/workspace-15.6.3.tgz#a9fd3c5692dfaebb04642e4e86d930d144bc2fed" + integrity sha512-RkCmDvcMXCVanR0RS8CZ14D7OMojSyvAal+b37P521MpizDkiN+zdRKewKvyOonzDeTAmZODtYccQ/uM5DjRfQ== dependencies: - "@nrwl/devkit" "15.5.3" - "@nrwl/linter" "15.5.3" + "@nrwl/devkit" "15.6.3" + "@nrwl/linter" "15.6.3" "@parcel/watcher" "2.0.4" chalk "^4.1.0" chokidar "^3.5.1" @@ -3335,7 +3346,7 @@ jsonc-parser "3.2.0" minimatch "3.0.5" npm-run-path "^4.0.1" - nx "15.5.3" + nx "15.6.3" open "^8.4.0" rxjs "^6.5.4" semver "7.3.4" @@ -10769,7 +10780,48 @@ nth-check@^2.0.0, nth-check@^2.0.1: dependencies: boolbase "^1.0.0" -nx@15.5.3, "nx@>=15.4.2 < 16": +nx@15.6.3: + version "15.6.3" + resolved "https://registry.npmjs.org/nx/-/nx-15.6.3.tgz#900087bce38c6e5975660c23ebd41ead1bf54f98" + integrity sha512-3t0A0GPLNen1yPAyE+VGZ3nkAzZYb5nfXtAcx8SHBlKq4u42yBY3khBmP1y4Og3jhIwFIj7J7Npeh8ZKrthmYQ== + dependencies: + "@nrwl/cli" "15.6.3" + "@nrwl/tao" "15.6.3" + "@parcel/watcher" "2.0.4" + "@yarnpkg/lockfile" "^1.1.0" + "@yarnpkg/parsers" "^3.0.0-rc.18" + "@zkochan/js-yaml" "0.0.6" + axios "^1.0.0" + chalk "^4.1.0" + cli-cursor "3.1.0" + cli-spinners "2.6.1" + cliui "^7.0.2" + dotenv "~10.0.0" + enquirer "~2.3.6" + fast-glob "3.2.7" + figures "3.2.0" + flat "^5.0.2" + fs-extra "^11.1.0" + glob "7.1.4" + ignore "^5.0.4" + js-yaml "4.1.0" + jsonc-parser "3.2.0" + lines-and-columns "~2.0.3" + minimatch "3.0.5" + npm-run-path "^4.0.1" + open "^8.4.0" + semver "7.3.4" + string-width "^4.2.3" + strong-log-transformer "^2.1.0" + tar-stream "~2.2.0" + tmp "~0.2.1" + tsconfig-paths "^4.1.2" + tslib "^2.3.0" + v8-compile-cache "2.3.0" + yargs "^17.6.2" + yargs-parser "21.1.1" + +"nx@>=15.4.2 < 16": version "15.5.3" resolved "https://registry.npmjs.org/nx/-/nx-15.5.3.tgz#bf6252e7d9e17121dd82dec4f6fce319b9e005fa" integrity sha512-PHB8VbiBLP108xb+yR8IGEsYWr7OcmDDOjHL+73oP4lVjyPgT8wdTMe6tI5LdBgv+KZ+0kiThK3ckvcPsfgvLQ== From 99c091e0e3cf38a28aa5e1d1d2b03b602d51aa0a Mon Sep 17 00:00:00 2001 From: "typescript-eslint[bot]" Date: Tue, 31 Jan 2023 09:39:21 +0000 Subject: [PATCH 19/19] chore: publish v5.50.0 --- CHANGELOG.md | 19 +++++++++++++++++++ lerna.json | 2 +- packages/ast-spec/CHANGELOG.md | 11 +++++++++++ packages/ast-spec/package.json | 2 +- packages/eslint-plugin-internal/CHANGELOG.md | 8 ++++++++ packages/eslint-plugin-internal/package.json | 8 ++++---- packages/eslint-plugin-tslint/CHANGELOG.md | 8 ++++++++ packages/eslint-plugin-tslint/package.json | 6 +++--- packages/eslint-plugin/CHANGELOG.md | 18 ++++++++++++++++++ packages/eslint-plugin/package.json | 11 +++++------ packages/experimental-utils/CHANGELOG.md | 8 ++++++++ packages/experimental-utils/package.json | 4 ++-- packages/parser/CHANGELOG.md | 8 ++++++++ packages/parser/package.json | 8 ++++---- packages/scope-manager/CHANGELOG.md | 8 ++++++++ packages/scope-manager/package.json | 8 ++++---- packages/shared-fixtures/CHANGELOG.md | 8 ++++++++ packages/shared-fixtures/package.json | 2 +- packages/type-utils/CHANGELOG.md | 8 ++++++++ packages/type-utils/package.json | 8 ++++---- packages/types/CHANGELOG.md | 8 ++++++++ packages/types/package.json | 2 +- packages/typescript-estree/CHANGELOG.md | 8 ++++++++ packages/typescript-estree/package.json | 8 ++++---- packages/utils/CHANGELOG.md | 8 ++++++++ packages/utils/package.json | 10 +++++----- packages/visitor-keys/CHANGELOG.md | 8 ++++++++ packages/visitor-keys/package.json | 4 ++-- packages/website-eslint/CHANGELOG.md | 8 ++++++++ packages/website-eslint/package.json | 16 ++++++++-------- packages/website/CHANGELOG.md | 8 ++++++++ packages/website/package.json | 8 ++++---- 32 files changed, 205 insertions(+), 54 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e18c2ad1d33c..9ad61e896afe 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,25 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [5.50.0](https://github.com/typescript-eslint/typescript-eslint/compare/v5.49.0...v5.50.0) (2023-01-31) + + +### Bug Fixes + +* **ast-spec:** a JSXEmptyExpression is not a possible JSXExpression ([#6321](https://github.com/typescript-eslint/typescript-eslint/issues/6321)) ([4b27777](https://github.com/typescript-eslint/typescript-eslint/commit/4b27777ed26cc83d6efc52a89b2d3fc6c01bc0d7)) +* **eslint-plugin:** [ban-ts-comment] counts graphemes instead of `String.prototype.length` ([#5704](https://github.com/typescript-eslint/typescript-eslint/issues/5704)) ([09d57ce](https://github.com/typescript-eslint/typescript-eslint/commit/09d57cec8901880c6b24ea80dfa7d9fcdc463930)) +* **eslint-plugin:** [prefer-optional-chain] fix `ThisExpression` and `PrivateIdentifier` errors ([#6028](https://github.com/typescript-eslint/typescript-eslint/issues/6028)) ([85e783c](https://github.com/typescript-eslint/typescript-eslint/commit/85e783c1fabe96d390729a5796d6d346e401692b)) +* **eslint-plugin:** [prefer-optional-chain] fixer produces wrong logic ([#5919](https://github.com/typescript-eslint/typescript-eslint/issues/5919)) ([b0f6c8e](https://github.com/typescript-eslint/typescript-eslint/commit/b0f6c8ec0b372696ef26ca3a2b4f82dafd9dc417)), closes [#1438](https://github.com/typescript-eslint/typescript-eslint/issues/1438) + + +### Features + +* **eslint-plugin:** add `key-spacing` rule extension for interface & type declarations ([#6211](https://github.com/typescript-eslint/typescript-eslint/issues/6211)) ([67706e7](https://github.com/typescript-eslint/typescript-eslint/commit/67706e72e332bf11c82fdf51f3d417d3c93a86cf)) + + + + + # [5.49.0](https://github.com/typescript-eslint/typescript-eslint/compare/v5.48.2...v5.49.0) (2023-01-23) diff --git a/lerna.json b/lerna.json index ca3b45abd274..e150bc530f7f 100644 --- a/lerna.json +++ b/lerna.json @@ -1,5 +1,5 @@ { - "version": "5.49.0", + "version": "5.50.0", "npmClient": "yarn", "useWorkspaces": true, "stream": true diff --git a/packages/ast-spec/CHANGELOG.md b/packages/ast-spec/CHANGELOG.md index 49507c453596..3b4168eff864 100644 --- a/packages/ast-spec/CHANGELOG.md +++ b/packages/ast-spec/CHANGELOG.md @@ -3,6 +3,17 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [5.50.0](https://github.com/typescript-eslint/typescript-eslint/compare/v5.49.0...v5.50.0) (2023-01-31) + + +### Bug Fixes + +* **ast-spec:** a JSXEmptyExpression is not a possible JSXExpression ([#6321](https://github.com/typescript-eslint/typescript-eslint/issues/6321)) ([4b27777](https://github.com/typescript-eslint/typescript-eslint/commit/4b27777ed26cc83d6efc52a89b2d3fc6c01bc0d7)) + + + + + # [5.49.0](https://github.com/typescript-eslint/typescript-eslint/compare/v5.48.2...v5.49.0) (2023-01-23) **Note:** Version bump only for package @typescript-eslint/ast-spec diff --git a/packages/ast-spec/package.json b/packages/ast-spec/package.json index 75a1485853db..c5e160a5c415 100644 --- a/packages/ast-spec/package.json +++ b/packages/ast-spec/package.json @@ -1,6 +1,6 @@ { "name": "@typescript-eslint/ast-spec", - "version": "5.49.0", + "version": "5.50.0", "description": "Complete specification for the TypeScript-ESTree AST", "private": true, "keywords": [ diff --git a/packages/eslint-plugin-internal/CHANGELOG.md b/packages/eslint-plugin-internal/CHANGELOG.md index 7bb1ad9d0df3..0cd6ad00030d 100644 --- a/packages/eslint-plugin-internal/CHANGELOG.md +++ b/packages/eslint-plugin-internal/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [5.50.0](https://github.com/typescript-eslint/typescript-eslint/compare/v5.49.0...v5.50.0) (2023-01-31) + +**Note:** Version bump only for package @typescript-eslint/eslint-plugin-internal + + + + + # [5.49.0](https://github.com/typescript-eslint/typescript-eslint/compare/v5.48.2...v5.49.0) (2023-01-23) **Note:** Version bump only for package @typescript-eslint/eslint-plugin-internal diff --git a/packages/eslint-plugin-internal/package.json b/packages/eslint-plugin-internal/package.json index b2e03c24a7ac..7b81526e7edd 100644 --- a/packages/eslint-plugin-internal/package.json +++ b/packages/eslint-plugin-internal/package.json @@ -1,6 +1,6 @@ { "name": "@typescript-eslint/eslint-plugin-internal", - "version": "5.49.0", + "version": "5.50.0", "private": true, "main": "dist/index.js", "scripts": { @@ -14,9 +14,9 @@ }, "dependencies": { "@types/prettier": "*", - "@typescript-eslint/scope-manager": "5.49.0", - "@typescript-eslint/type-utils": "5.49.0", - "@typescript-eslint/utils": "5.49.0", + "@typescript-eslint/scope-manager": "5.50.0", + "@typescript-eslint/type-utils": "5.50.0", + "@typescript-eslint/utils": "5.50.0", "prettier": "*" } } diff --git a/packages/eslint-plugin-tslint/CHANGELOG.md b/packages/eslint-plugin-tslint/CHANGELOG.md index 92e446a5cc68..b2551812889f 100644 --- a/packages/eslint-plugin-tslint/CHANGELOG.md +++ b/packages/eslint-plugin-tslint/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [5.50.0](https://github.com/typescript-eslint/typescript-eslint/compare/v5.49.0...v5.50.0) (2023-01-31) + +**Note:** Version bump only for package @typescript-eslint/eslint-plugin-tslint + + + + + # [5.49.0](https://github.com/typescript-eslint/typescript-eslint/compare/v5.48.2...v5.49.0) (2023-01-23) **Note:** Version bump only for package @typescript-eslint/eslint-plugin-tslint diff --git a/packages/eslint-plugin-tslint/package.json b/packages/eslint-plugin-tslint/package.json index 47762f6b1e07..23bf62f3fc5c 100644 --- a/packages/eslint-plugin-tslint/package.json +++ b/packages/eslint-plugin-tslint/package.json @@ -1,6 +1,6 @@ { "name": "@typescript-eslint/eslint-plugin-tslint", - "version": "5.49.0", + "version": "5.50.0", "main": "dist/index.js", "typings": "src/index.ts", "description": "ESLint plugin that wraps a TSLint configuration and lints the whole source using TSLint", @@ -38,7 +38,7 @@ "typecheck": "tsc -p tsconfig.json --noEmit" }, "dependencies": { - "@typescript-eslint/utils": "5.49.0", + "@typescript-eslint/utils": "5.50.0", "lodash": "^4.17.21" }, "peerDependencies": { @@ -48,6 +48,6 @@ }, "devDependencies": { "@types/lodash": "*", - "@typescript-eslint/parser": "5.49.0" + "@typescript-eslint/parser": "5.50.0" } } diff --git a/packages/eslint-plugin/CHANGELOG.md b/packages/eslint-plugin/CHANGELOG.md index 52c4bf72c2a1..25cce92ccc4f 100644 --- a/packages/eslint-plugin/CHANGELOG.md +++ b/packages/eslint-plugin/CHANGELOG.md @@ -3,6 +3,24 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [5.50.0](https://github.com/typescript-eslint/typescript-eslint/compare/v5.49.0...v5.50.0) (2023-01-31) + + +### Bug Fixes + +* **eslint-plugin:** [ban-ts-comment] counts graphemes instead of `String.prototype.length` ([#5704](https://github.com/typescript-eslint/typescript-eslint/issues/5704)) ([09d57ce](https://github.com/typescript-eslint/typescript-eslint/commit/09d57cec8901880c6b24ea80dfa7d9fcdc463930)) +* **eslint-plugin:** [prefer-optional-chain] fix `ThisExpression` and `PrivateIdentifier` errors ([#6028](https://github.com/typescript-eslint/typescript-eslint/issues/6028)) ([85e783c](https://github.com/typescript-eslint/typescript-eslint/commit/85e783c1fabe96d390729a5796d6d346e401692b)) +* **eslint-plugin:** [prefer-optional-chain] fixer produces wrong logic ([#5919](https://github.com/typescript-eslint/typescript-eslint/issues/5919)) ([b0f6c8e](https://github.com/typescript-eslint/typescript-eslint/commit/b0f6c8ec0b372696ef26ca3a2b4f82dafd9dc417)), closes [#1438](https://github.com/typescript-eslint/typescript-eslint/issues/1438) + + +### Features + +* **eslint-plugin:** add `key-spacing` rule extension for interface & type declarations ([#6211](https://github.com/typescript-eslint/typescript-eslint/issues/6211)) ([67706e7](https://github.com/typescript-eslint/typescript-eslint/commit/67706e72e332bf11c82fdf51f3d417d3c93a86cf)) + + + + + # [5.49.0](https://github.com/typescript-eslint/typescript-eslint/compare/v5.48.2...v5.49.0) (2023-01-23) diff --git a/packages/eslint-plugin/package.json b/packages/eslint-plugin/package.json index 55992f5b7272..724b3eea0f1c 100644 --- a/packages/eslint-plugin/package.json +++ b/packages/eslint-plugin/package.json @@ -1,6 +1,6 @@ { "name": "@typescript-eslint/eslint-plugin", - "version": "5.49.0", + "version": "5.50.0", "description": "TypeScript plugin for ESLint", "keywords": [ "eslint", @@ -44,13 +44,12 @@ "typecheck": "tsc -p tsconfig.json --noEmit" }, "dependencies": { - "@typescript-eslint/scope-manager": "5.49.0", - "@typescript-eslint/type-utils": "5.49.0", - "@typescript-eslint/utils": "5.49.0", + "@typescript-eslint/scope-manager": "5.50.0", + "@typescript-eslint/type-utils": "5.50.0", + "@typescript-eslint/utils": "5.50.0", "debug": "^4.3.4", "grapheme-splitter": "^1.0.4", "ignore": "^5.2.0", - "grapheme-splitter": "^1.0.4", "natural-compare-lite": "^1.4.0", "regexpp": "^3.2.0", "semver": "^7.3.7", @@ -63,8 +62,8 @@ "@types/natural-compare-lite": "^1.4.0", "@types/prettier": "*", "chalk": "^5.0.1", - "grapheme-splitter": "^1.0.4", "cross-fetch": "^3.1.5", + "grapheme-splitter": "^1.0.4", "json-schema": "*", "markdown-table": "^3.0.2", "marked": "^4.0.15", diff --git a/packages/experimental-utils/CHANGELOG.md b/packages/experimental-utils/CHANGELOG.md index e578cc75abf2..a11333dc15c7 100644 --- a/packages/experimental-utils/CHANGELOG.md +++ b/packages/experimental-utils/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [5.50.0](https://github.com/typescript-eslint/typescript-eslint/compare/v5.49.0...v5.50.0) (2023-01-31) + +**Note:** Version bump only for package @typescript-eslint/experimental-utils + + + + + # [5.49.0](https://github.com/typescript-eslint/typescript-eslint/compare/v5.48.2...v5.49.0) (2023-01-23) **Note:** Version bump only for package @typescript-eslint/experimental-utils diff --git a/packages/experimental-utils/package.json b/packages/experimental-utils/package.json index ef176c09959a..e3d44a14dfec 100644 --- a/packages/experimental-utils/package.json +++ b/packages/experimental-utils/package.json @@ -1,6 +1,6 @@ { "name": "@typescript-eslint/experimental-utils", - "version": "5.49.0", + "version": "5.50.0", "description": "(Experimental) Utilities for working with TypeScript + ESLint together", "keywords": [ "eslint", @@ -38,7 +38,7 @@ "typecheck": "tsc -p tsconfig.json --noEmit" }, "dependencies": { - "@typescript-eslint/utils": "5.49.0" + "@typescript-eslint/utils": "5.50.0" }, "peerDependencies": { "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" diff --git a/packages/parser/CHANGELOG.md b/packages/parser/CHANGELOG.md index e1b4ba3f6982..8dd79a4e7d19 100644 --- a/packages/parser/CHANGELOG.md +++ b/packages/parser/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [5.50.0](https://github.com/typescript-eslint/typescript-eslint/compare/v5.49.0...v5.50.0) (2023-01-31) + +**Note:** Version bump only for package @typescript-eslint/parser + + + + + # [5.49.0](https://github.com/typescript-eslint/typescript-eslint/compare/v5.48.2...v5.49.0) (2023-01-23) **Note:** Version bump only for package @typescript-eslint/parser diff --git a/packages/parser/package.json b/packages/parser/package.json index fd704210cc82..72b9df7a210c 100644 --- a/packages/parser/package.json +++ b/packages/parser/package.json @@ -1,6 +1,6 @@ { "name": "@typescript-eslint/parser", - "version": "5.49.0", + "version": "5.50.0", "description": "An ESLint custom parser which leverages TypeScript ESTree", "main": "dist/index.js", "types": "dist/index.d.ts", @@ -45,9 +45,9 @@ "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" }, "dependencies": { - "@typescript-eslint/scope-manager": "5.49.0", - "@typescript-eslint/types": "5.49.0", - "@typescript-eslint/typescript-estree": "5.49.0", + "@typescript-eslint/scope-manager": "5.50.0", + "@typescript-eslint/types": "5.50.0", + "@typescript-eslint/typescript-estree": "5.50.0", "debug": "^4.3.4" }, "devDependencies": { diff --git a/packages/scope-manager/CHANGELOG.md b/packages/scope-manager/CHANGELOG.md index 7643d240f880..4243c56c73e5 100644 --- a/packages/scope-manager/CHANGELOG.md +++ b/packages/scope-manager/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [5.50.0](https://github.com/typescript-eslint/typescript-eslint/compare/v5.49.0...v5.50.0) (2023-01-31) + +**Note:** Version bump only for package @typescript-eslint/scope-manager + + + + + # [5.49.0](https://github.com/typescript-eslint/typescript-eslint/compare/v5.48.2...v5.49.0) (2023-01-23) **Note:** Version bump only for package @typescript-eslint/scope-manager diff --git a/packages/scope-manager/package.json b/packages/scope-manager/package.json index b91e07821da8..afa72f7662a5 100644 --- a/packages/scope-manager/package.json +++ b/packages/scope-manager/package.json @@ -1,6 +1,6 @@ { "name": "@typescript-eslint/scope-manager", - "version": "5.49.0", + "version": "5.50.0", "description": "TypeScript scope analyser for ESLint", "keywords": [ "eslint", @@ -38,12 +38,12 @@ "typecheck": "nx typecheck" }, "dependencies": { - "@typescript-eslint/types": "5.49.0", - "@typescript-eslint/visitor-keys": "5.49.0" + "@typescript-eslint/types": "5.50.0", + "@typescript-eslint/visitor-keys": "5.50.0" }, "devDependencies": { "@types/glob": "*", - "@typescript-eslint/typescript-estree": "5.49.0", + "@typescript-eslint/typescript-estree": "5.50.0", "glob": "*", "jest-specific-snapshot": "*", "make-dir": "*", diff --git a/packages/shared-fixtures/CHANGELOG.md b/packages/shared-fixtures/CHANGELOG.md index a5102cf788ee..3548d5254c6d 100644 --- a/packages/shared-fixtures/CHANGELOG.md +++ b/packages/shared-fixtures/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [5.50.0](https://github.com/typescript-eslint/typescript-eslint/compare/v5.49.0...v5.50.0) (2023-01-31) + +**Note:** Version bump only for package @typescript-eslint/shared-fixtures + + + + + # [5.49.0](https://github.com/typescript-eslint/typescript-eslint/compare/v5.48.2...v5.49.0) (2023-01-23) **Note:** Version bump only for package @typescript-eslint/shared-fixtures diff --git a/packages/shared-fixtures/package.json b/packages/shared-fixtures/package.json index 3abb676c6aec..0e3d35976d45 100644 --- a/packages/shared-fixtures/package.json +++ b/packages/shared-fixtures/package.json @@ -1,6 +1,6 @@ { "description": "Code fixtures used to test the typescript-estree parser.", "name": "@typescript-eslint/shared-fixtures", - "version": "5.49.0", + "version": "5.50.0", "private": true } diff --git a/packages/type-utils/CHANGELOG.md b/packages/type-utils/CHANGELOG.md index 97cbdcabbc03..26f418c1436c 100644 --- a/packages/type-utils/CHANGELOG.md +++ b/packages/type-utils/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [5.50.0](https://github.com/typescript-eslint/typescript-eslint/compare/v5.49.0...v5.50.0) (2023-01-31) + +**Note:** Version bump only for package @typescript-eslint/type-utils + + + + + # [5.49.0](https://github.com/typescript-eslint/typescript-eslint/compare/v5.48.2...v5.49.0) (2023-01-23) **Note:** Version bump only for package @typescript-eslint/type-utils diff --git a/packages/type-utils/package.json b/packages/type-utils/package.json index 88b6dc5b8988..2b44585a6821 100644 --- a/packages/type-utils/package.json +++ b/packages/type-utils/package.json @@ -1,6 +1,6 @@ { "name": "@typescript-eslint/type-utils", - "version": "5.49.0", + "version": "5.50.0", "description": "Type utilities for working with TypeScript + ESLint together", "keywords": [ "eslint", @@ -39,13 +39,13 @@ "typecheck": "tsc -p tsconfig.json --noEmit" }, "dependencies": { - "@typescript-eslint/typescript-estree": "5.49.0", - "@typescript-eslint/utils": "5.49.0", + "@typescript-eslint/typescript-estree": "5.50.0", + "@typescript-eslint/utils": "5.50.0", "debug": "^4.3.4", "tsutils": "^3.21.0" }, "devDependencies": { - "@typescript-eslint/parser": "5.49.0", + "@typescript-eslint/parser": "5.50.0", "typescript": "*" }, "peerDependencies": { diff --git a/packages/types/CHANGELOG.md b/packages/types/CHANGELOG.md index 4424df99e42a..0cd6d24aa095 100644 --- a/packages/types/CHANGELOG.md +++ b/packages/types/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [5.50.0](https://github.com/typescript-eslint/typescript-eslint/compare/v5.49.0...v5.50.0) (2023-01-31) + +**Note:** Version bump only for package @typescript-eslint/types + + + + + # [5.49.0](https://github.com/typescript-eslint/typescript-eslint/compare/v5.48.2...v5.49.0) (2023-01-23) **Note:** Version bump only for package @typescript-eslint/types diff --git a/packages/types/package.json b/packages/types/package.json index d35920bf1c59..ccc72bcd6986 100644 --- a/packages/types/package.json +++ b/packages/types/package.json @@ -1,6 +1,6 @@ { "name": "@typescript-eslint/types", - "version": "5.49.0", + "version": "5.50.0", "description": "Types for the TypeScript-ESTree AST spec", "keywords": [ "eslint", diff --git a/packages/typescript-estree/CHANGELOG.md b/packages/typescript-estree/CHANGELOG.md index 7db432d3477e..b74f9d0a82db 100644 --- a/packages/typescript-estree/CHANGELOG.md +++ b/packages/typescript-estree/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [5.50.0](https://github.com/typescript-eslint/typescript-eslint/compare/v5.49.0...v5.50.0) (2023-01-31) + +**Note:** Version bump only for package @typescript-eslint/typescript-estree + + + + + # [5.49.0](https://github.com/typescript-eslint/typescript-eslint/compare/v5.48.2...v5.49.0) (2023-01-23) diff --git a/packages/typescript-estree/package.json b/packages/typescript-estree/package.json index 6972beac90d4..728c8d417e96 100644 --- a/packages/typescript-estree/package.json +++ b/packages/typescript-estree/package.json @@ -1,6 +1,6 @@ { "name": "@typescript-eslint/typescript-estree", - "version": "5.49.0", + "version": "5.50.0", "description": "A parser that converts TypeScript source code into an ESTree compatible form", "main": "dist/index.js", "types": "dist/index.d.ts", @@ -42,8 +42,8 @@ "typecheck": "tsc -p tsconfig.json --noEmit" }, "dependencies": { - "@typescript-eslint/types": "5.49.0", - "@typescript-eslint/visitor-keys": "5.49.0", + "@typescript-eslint/types": "5.50.0", + "@typescript-eslint/visitor-keys": "5.50.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -59,7 +59,7 @@ "@types/is-glob": "*", "@types/semver": "*", "@types/tmp": "*", - "@typescript-eslint/shared-fixtures": "5.49.0", + "@typescript-eslint/shared-fixtures": "5.50.0", "glob": "*", "jest-specific-snapshot": "*", "make-dir": "*", diff --git a/packages/utils/CHANGELOG.md b/packages/utils/CHANGELOG.md index 119494deff16..ec49364f3e77 100644 --- a/packages/utils/CHANGELOG.md +++ b/packages/utils/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [5.50.0](https://github.com/typescript-eslint/typescript-eslint/compare/v5.49.0...v5.50.0) (2023-01-31) + +**Note:** Version bump only for package @typescript-eslint/utils + + + + + # [5.49.0](https://github.com/typescript-eslint/typescript-eslint/compare/v5.48.2...v5.49.0) (2023-01-23) **Note:** Version bump only for package @typescript-eslint/utils diff --git a/packages/utils/package.json b/packages/utils/package.json index 5a1427cd7972..13e83257c675 100644 --- a/packages/utils/package.json +++ b/packages/utils/package.json @@ -1,6 +1,6 @@ { "name": "@typescript-eslint/utils", - "version": "5.49.0", + "version": "5.50.0", "description": "Utilities for working with TypeScript + ESLint together", "keywords": [ "eslint", @@ -41,9 +41,9 @@ "dependencies": { "@types/json-schema": "^7.0.9", "@types/semver": "^7.3.12", - "@typescript-eslint/scope-manager": "5.49.0", - "@typescript-eslint/types": "5.49.0", - "@typescript-eslint/typescript-estree": "5.49.0", + "@typescript-eslint/scope-manager": "5.50.0", + "@typescript-eslint/types": "5.50.0", + "@typescript-eslint/typescript-estree": "5.50.0", "eslint-scope": "^5.1.1", "eslint-utils": "^3.0.0", "semver": "^7.3.7" @@ -52,7 +52,7 @@ "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" }, "devDependencies": { - "@typescript-eslint/parser": "5.49.0", + "@typescript-eslint/parser": "5.50.0", "typescript": "*" }, "funding": { diff --git a/packages/visitor-keys/CHANGELOG.md b/packages/visitor-keys/CHANGELOG.md index 77bc19f5a7d0..a7c260ce870f 100644 --- a/packages/visitor-keys/CHANGELOG.md +++ b/packages/visitor-keys/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [5.50.0](https://github.com/typescript-eslint/typescript-eslint/compare/v5.49.0...v5.50.0) (2023-01-31) + +**Note:** Version bump only for package @typescript-eslint/visitor-keys + + + + + # [5.49.0](https://github.com/typescript-eslint/typescript-eslint/compare/v5.48.2...v5.49.0) (2023-01-23) **Note:** Version bump only for package @typescript-eslint/visitor-keys diff --git a/packages/visitor-keys/package.json b/packages/visitor-keys/package.json index 0227b099772d..14527dc3f80c 100644 --- a/packages/visitor-keys/package.json +++ b/packages/visitor-keys/package.json @@ -1,6 +1,6 @@ { "name": "@typescript-eslint/visitor-keys", - "version": "5.49.0", + "version": "5.50.0", "description": "Visitor keys used to help traverse the TypeScript-ESTree AST", "keywords": [ "eslint", @@ -39,7 +39,7 @@ "typecheck": "tsc -p tsconfig.json --noEmit" }, "dependencies": { - "@typescript-eslint/types": "5.49.0", + "@typescript-eslint/types": "5.50.0", "eslint-visitor-keys": "^3.3.0" }, "devDependencies": { diff --git a/packages/website-eslint/CHANGELOG.md b/packages/website-eslint/CHANGELOG.md index f8a5a882f820..ea36b42047a0 100644 --- a/packages/website-eslint/CHANGELOG.md +++ b/packages/website-eslint/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [5.50.0](https://github.com/typescript-eslint/typescript-eslint/compare/v5.49.0...v5.50.0) (2023-01-31) + +**Note:** Version bump only for package @typescript-eslint/website-eslint + + + + + # [5.49.0](https://github.com/typescript-eslint/typescript-eslint/compare/v5.48.2...v5.49.0) (2023-01-23) **Note:** Version bump only for package @typescript-eslint/website-eslint diff --git a/packages/website-eslint/package.json b/packages/website-eslint/package.json index 978b82451aed..6bb1f6d3f902 100644 --- a/packages/website-eslint/package.json +++ b/packages/website-eslint/package.json @@ -1,6 +1,6 @@ { "name": "@typescript-eslint/website-eslint", - "version": "5.49.0", + "version": "5.50.0", "private": true, "description": "ESLint which works in browsers.", "engines": { @@ -16,19 +16,19 @@ "format": "prettier --write \"./**/*.{ts,mts,cts,tsx,js,mjs,cjs,jsx,json,md,css}\" --ignore-path ../../.prettierignore" }, "dependencies": { - "@typescript-eslint/types": "5.49.0", - "@typescript-eslint/utils": "5.49.0" + "@typescript-eslint/types": "5.50.0", + "@typescript-eslint/utils": "5.50.0" }, "devDependencies": { "@rollup/plugin-commonjs": "^23.0.0", "@rollup/plugin-json": "^5.0.0", "@rollup/plugin-node-resolve": "^15.0.0", "@rollup/pluginutils": "^5.0.0", - "@typescript-eslint/eslint-plugin": "5.49.0", - "@typescript-eslint/parser": "5.49.0", - "@typescript-eslint/scope-manager": "5.49.0", - "@typescript-eslint/typescript-estree": "5.49.0", - "@typescript-eslint/visitor-keys": "5.49.0", + "@typescript-eslint/eslint-plugin": "5.50.0", + "@typescript-eslint/parser": "5.50.0", + "@typescript-eslint/scope-manager": "5.50.0", + "@typescript-eslint/typescript-estree": "5.50.0", + "@typescript-eslint/visitor-keys": "5.50.0", "eslint": "*", "rollup": "^2.75.4", "rollup-plugin-terser": "^7.0.2", diff --git a/packages/website/CHANGELOG.md b/packages/website/CHANGELOG.md index 3558af9ab446..547367d081fd 100644 --- a/packages/website/CHANGELOG.md +++ b/packages/website/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [5.50.0](https://github.com/typescript-eslint/typescript-eslint/compare/v5.49.0...v5.50.0) (2023-01-31) + +**Note:** Version bump only for package website + + + + + # [5.49.0](https://github.com/typescript-eslint/typescript-eslint/compare/v5.48.2...v5.49.0) (2023-01-23) **Note:** Version bump only for package website diff --git a/packages/website/package.json b/packages/website/package.json index 2397fc252a2d..8f4ee2b74aa0 100644 --- a/packages/website/package.json +++ b/packages/website/package.json @@ -1,6 +1,6 @@ { "name": "website", - "version": "5.49.0", + "version": "5.50.0", "private": true, "scripts": { "build": "docusaurus build", @@ -21,8 +21,8 @@ "@docusaurus/remark-plugin-npm2yarn": "~2.2.0", "@docusaurus/theme-common": "~2.2.0", "@mdx-js/react": "1.6.22", - "@typescript-eslint/parser": "5.49.0", - "@typescript-eslint/website-eslint": "5.49.0", + "@typescript-eslint/parser": "5.50.0", + "@typescript-eslint/website-eslint": "5.50.0", "clsx": "^1.1.1", "eslint": "*", "json-schema": "^0.4.0", @@ -48,7 +48,7 @@ "@types/react": "^18.0.9", "@types/react-helmet": "^6.1.5", "@types/react-router-dom": "^5.3.3", - "@typescript-eslint/eslint-plugin": "5.49.0", + "@typescript-eslint/eslint-plugin": "5.50.0", "copy-webpack-plugin": "^11.0.0", "eslint-plugin-jsx-a11y": "^6.5.1", "eslint-plugin-react": "^7.29.4",