diff --git a/.eslintrc.js b/.eslintrc.js index df695f85e94..1ef4f373c8d 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -59,13 +59,21 @@ module.exports = { '@typescript-eslint/prefer-optional-chain': 'error', '@typescript-eslint/unbound-method': 'off', '@typescript-eslint/prefer-as-const': 'error', + '@typescript-eslint/restrict-template-expressions': [ + 'error', + { + allowNumber: true, + allowBoolean: true, + allowAny: true, + allowNullish: true, + allowRegExp: true, + }, + ], '@typescript-eslint/no-unused-vars': [ 'warn', { varsIgnorePattern: '^_', argsIgnorePattern: '^_' }, ], - // TODO - enable these new recommended rules - '@typescript-eslint/restrict-template-expressions': 'off', // TODO - enable this '@typescript-eslint/naming-convention': 'off', diff --git a/CHANGELOG.md b/CHANGELOG.md index d94553bb093..05027c8584c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,34 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [4.32.0](https://github.com/typescript-eslint/typescript-eslint/compare/v4.31.2...v4.32.0) (2021-09-27) + + +### Bug Fixes + +* **eslint-plugin:** [consistent-type-definitions] correct fix for `export default` ([#3899](https://github.com/typescript-eslint/typescript-eslint/issues/3899)) ([ebb33ed](https://github.com/typescript-eslint/typescript-eslint/commit/ebb33ed8bc29f69ca2a657ec5b31857c0aeb4b56)) +* **eslint-plugin:** [no-require-imports] report only global `require` ([#3871](https://github.com/typescript-eslint/typescript-eslint/issues/3871)) ([8aa87a1](https://github.com/typescript-eslint/typescript-eslint/commit/8aa87a136e7cd7b40fbf09fcfa26bf04d1c6d5fe)) +* **eslint-plugin:** [no-shadow] ignore type-only imports properly ([#3868](https://github.com/typescript-eslint/typescript-eslint/issues/3868)) ([dda9cee](https://github.com/typescript-eslint/typescript-eslint/commit/dda9cee68a5cd78b358a854027999c739ac623e9)) +* **eslint-plugin:** [no-var-requires] report problems within `NewExpression` ([#3884](https://github.com/typescript-eslint/typescript-eslint/issues/3884)) ([ed5e459](https://github.com/typescript-eslint/typescript-eslint/commit/ed5e45983fa052accf3a7b5fcdbfcb15ed09490f)) +* **eslint-plugin:** [padding-line-between-statements] problems within namespaces not being reported ([#3869](https://github.com/typescript-eslint/typescript-eslint/issues/3869)) ([1861356](https://github.com/typescript-eslint/typescript-eslint/commit/186135698b40b510ffff6a2402aa34f2726596ea)) +* **eslint-plugin:** [prefer-regexp-exec] respect flags when using `RegExp` ([#3855](https://github.com/typescript-eslint/typescript-eslint/issues/3855)) ([ffdb5ff](https://github.com/typescript-eslint/typescript-eslint/commit/ffdb5ff9900e07374a2f3686447e3e2c78fbc38a)) +* **eslint-plugin:** [prefer-return-this-type] handle generics properly in fixer ([#3852](https://github.com/typescript-eslint/typescript-eslint/issues/3852)) ([9e98b8f](https://github.com/typescript-eslint/typescript-eslint/commit/9e98b8f43ca6aadc9758a4e9a0d1d3c250af6cca)) +* **eslint-plugin:** false-positive/negative with array index in no-unnecessary-condition ([#3805](https://github.com/typescript-eslint/typescript-eslint/issues/3805)) ([bdb8f0b](https://github.com/typescript-eslint/typescript-eslint/commit/bdb8f0be1466e4a4b713e91199be91030650ed01)) +* **experimental-utils:** add missing signature for `isParenthesized` ([#3887](https://github.com/typescript-eslint/typescript-eslint/issues/3887)) ([806eaac](https://github.com/typescript-eslint/typescript-eslint/commit/806eaac6af5325664634690e9ebd7ffaed276549)) + + +### Features + +* **eslint-plugin:** [no-type-alias]: add allowGenerics option ([#3865](https://github.com/typescript-eslint/typescript-eslint/issues/3865)) ([4195919](https://github.com/typescript-eslint/typescript-eslint/commit/41959199735a6d4fe3ae7825f3087e8fb249be9f)) +* **eslint-plugin:** add `no-non-null-asserted-nullish-coalescing` rule ([#3349](https://github.com/typescript-eslint/typescript-eslint/issues/3349)) ([4e99961](https://github.com/typescript-eslint/typescript-eslint/commit/4e999614e9761f6dc7e5aa0c5bad76ab164ab3fb)) +* **eslint-plugin:** add new extended rule `no-restricted-imports` ([#3775](https://github.com/typescript-eslint/typescript-eslint/issues/3775)) ([ec5d506](https://github.com/typescript-eslint/typescript-eslint/commit/ec5d50696b249a207d322e4a2fc66582122eb010)) +* **eslint-plugin-internal:** [prefer-ast-types-enum] add `DefinitionType` enum ([#3916](https://github.com/typescript-eslint/typescript-eslint/issues/3916)) ([13b7de5](https://github.com/typescript-eslint/typescript-eslint/commit/13b7de508e0f8eac492879ff9ab99acd8d3e977e)) +* Support `'latest'` as `ecmaVersion` ([#3873](https://github.com/typescript-eslint/typescript-eslint/issues/3873)) ([25a42c0](https://github.com/typescript-eslint/typescript-eslint/commit/25a42c0bbe92d1ecbc2e8ff9ef3a3ef413f728b0)) + + + + + ## [4.31.2](https://github.com/typescript-eslint/typescript-eslint/compare/v4.31.1...v4.31.2) (2021-09-20) **Note:** Version bump only for package @typescript-eslint/typescript-eslint diff --git a/lerna.json b/lerna.json index b2c599ea750..3a7290b4fef 100644 --- a/lerna.json +++ b/lerna.json @@ -1,5 +1,5 @@ { - "version": "4.31.2", + "version": "4.32.0", "npmClient": "yarn", "useWorkspaces": true, "stream": true diff --git a/package.json b/package.json index 2e42c438b86..5e93f9be4ca 100644 --- a/package.json +++ b/package.json @@ -72,7 +72,7 @@ }, "devDependencies": { "@babel/code-frame": "^7.12.13", - "@babel/parser": "^7.14.6", + "@babel/parser": "^7.15.6", "@babel/types": "^7.14.4", "@commitlint/cli": "^13.1.0", "@commitlint/config-conventional": "^13.1.0", @@ -91,7 +91,7 @@ "@types/lodash": "^4.14.170", "@types/marked": "^2.0.3", "@types/node": "^15.6.1", - "@types/node-fetch": "^2.5.10", + "@types/node-fetch": "^3.0.3", "@types/prettier": "^2.2.3", "@types/rimraf": "^3.0.0", "@types/semver": "^7.3.6", @@ -114,7 +114,7 @@ "lint-staged": "^11.0.0", "make-dir": "^3.1.0", "markdownlint-cli": "^0.28.1", - "node-fetch": "^2.6.1", + "node-fetch": "^3.0.0", "prettier": "2.3.2", "pretty-format": "^27.0.2", "rimraf": "^3.0.2", diff --git a/packages/ast-spec/CHANGELOG.md b/packages/ast-spec/CHANGELOG.md index 62a35978406..2ad145708ec 100644 --- a/packages/ast-spec/CHANGELOG.md +++ b/packages/ast-spec/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. +# [4.32.0](https://github.com/typescript-eslint/typescript-eslint/compare/v4.31.2...v4.32.0) (2021-09-27) + +**Note:** Version bump only for package @typescript-eslint/ast-spec + + + + + ## [4.31.2](https://github.com/typescript-eslint/typescript-eslint/compare/v4.31.1...v4.31.2) (2021-09-20) **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 4dc5ed6e731..b0732df28fc 100644 --- a/packages/ast-spec/package.json +++ b/packages/ast-spec/package.json @@ -1,6 +1,6 @@ { "name": "@typescript-eslint/ast-spec", - "version": "4.31.2", + "version": "4.32.0", "description": "TypeScript-ESTree AST spec", "private": true, "keywords": [ diff --git a/packages/eslint-plugin-internal/CHANGELOG.md b/packages/eslint-plugin-internal/CHANGELOG.md index 8ebd34fe72d..ec3c822bf3b 100644 --- a/packages/eslint-plugin-internal/CHANGELOG.md +++ b/packages/eslint-plugin-internal/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. +# [4.32.0](https://github.com/typescript-eslint/typescript-eslint/compare/v4.31.2...v4.32.0) (2021-09-27) + + +### Features + +* **eslint-plugin-internal:** [prefer-ast-types-enum] add `DefinitionType` enum ([#3916](https://github.com/typescript-eslint/typescript-eslint/issues/3916)) ([13b7de5](https://github.com/typescript-eslint/typescript-eslint/commit/13b7de508e0f8eac492879ff9ab99acd8d3e977e)) + + + + + ## [4.31.2](https://github.com/typescript-eslint/typescript-eslint/compare/v4.31.1...v4.31.2) (2021-09-20) **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 672744314a4..6ee03af9082 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": "4.31.2", + "version": "4.32.0", "private": true, "main": "dist/index.js", "scripts": { @@ -14,7 +14,8 @@ }, "dependencies": { "@types/prettier": "*", - "@typescript-eslint/experimental-utils": "4.31.2", + "@typescript-eslint/experimental-utils": "4.32.0", + "@typescript-eslint/scope-manager": "4.32.0", "prettier": "*" } } diff --git a/packages/eslint-plugin-internal/src/rules/no-poorly-typed-ts-props.ts b/packages/eslint-plugin-internal/src/rules/no-poorly-typed-ts-props.ts index d5554ec57d5..96c1405c73f 100644 --- a/packages/eslint-plugin-internal/src/rules/no-poorly-typed-ts-props.ts +++ b/packages/eslint-plugin-internal/src/rules/no-poorly-typed-ts-props.ts @@ -1,7 +1,7 @@ import { - TSESTree, ESLintUtils, TSESLint, + TSESTree, } from '@typescript-eslint/experimental-utils'; import { createRule } from '../util'; @@ -24,6 +24,7 @@ const BANNED_PROPERTIES = [ fixWith: 'getDeclarations()', }, { + // eslint-disable-next-line @typescript-eslint/internal/prefer-ast-types-enum type: 'Type', property: 'symbol', fixWith: 'getSymbol()', diff --git a/packages/eslint-plugin-internal/src/rules/prefer-ast-types-enum.ts b/packages/eslint-plugin-internal/src/rules/prefer-ast-types-enum.ts index 8a5ec63bb4e..c4a95695d96 100755 --- a/packages/eslint-plugin-internal/src/rules/prefer-ast-types-enum.ts +++ b/packages/eslint-plugin-internal/src/rules/prefer-ast-types-enum.ts @@ -3,6 +3,7 @@ import { AST_TOKEN_TYPES, TSESTree, } from '@typescript-eslint/experimental-utils'; +import { DefinitionType } from '@typescript-eslint/scope-manager'; import { createRule } from '../util'; const isStringLiteral = ( @@ -17,7 +18,7 @@ export default createRule({ category: 'Best Practices', recommended: 'error', description: - 'Ensures consistent usage of AST_NODE_TYPES & AST_TOKEN_TYPES enums.', + 'Ensures consistent usage of `AST_NODE_TYPES`, `AST_TOKEN_TYPES` and `DefinitionType` enums.', }, messages: { preferEnum: 'Prefer {{ enumName }}.{{ literal }} over raw literal', @@ -28,7 +29,7 @@ export default createRule({ defaultOptions: [], create(context) { const report = ( - enumName: 'AST_NODE_TYPES' | 'AST_TOKEN_TYPES', + enumName: 'AST_NODE_TYPES' | 'AST_TOKEN_TYPES' | 'DefinitionType', literal: TSESTree.StringLiteral, ): void => context.report({ @@ -44,7 +45,7 @@ export default createRule({ if ( node.parent?.type === AST_NODE_TYPES.TSEnumMember && node.parent.parent?.type === AST_NODE_TYPES.TSEnumDeclaration && - ['AST_NODE_TYPES', 'AST_TOKEN_TYPES'].includes( + ['AST_NODE_TYPES', 'AST_TOKEN_TYPES', 'DefinitionType'].includes( node.parent.parent.id.name, ) ) { @@ -64,6 +65,10 @@ export default createRule({ if (Object.prototype.hasOwnProperty.call(AST_TOKEN_TYPES, value)) { report('AST_TOKEN_TYPES', node); } + + if (Object.prototype.hasOwnProperty.call(DefinitionType, value)) { + report('DefinitionType', node); + } }, }; }, diff --git a/packages/eslint-plugin-internal/tests/rules/no-poorly-typed-ts-props.test.ts b/packages/eslint-plugin-internal/tests/rules/no-poorly-typed-ts-props.test.ts index 8fe109ee3d1..4c9751489bd 100644 --- a/packages/eslint-plugin-internal/tests/rules/no-poorly-typed-ts-props.test.ts +++ b/packages/eslint-plugin-internal/tests/rules/no-poorly-typed-ts-props.test.ts @@ -1,5 +1,6 @@ +/* eslint-disable @typescript-eslint/internal/prefer-ast-types-enum */ import rule from '../../src/rules/no-poorly-typed-ts-props'; -import { RuleTester, getFixturesRootDir } from '../RuleTester'; +import { getFixturesRootDir, RuleTester } from '../RuleTester'; const ruleTester = new RuleTester({ parser: '@typescript-eslint/parser', diff --git a/packages/eslint-plugin-internal/tests/rules/prefer-ast-types-enum.test.ts b/packages/eslint-plugin-internal/tests/rules/prefer-ast-types-enum.test.ts index c2ffd8e489e..94f8830a04e 100644 --- a/packages/eslint-plugin-internal/tests/rules/prefer-ast-types-enum.test.ts +++ b/packages/eslint-plugin-internal/tests/rules/prefer-ast-types-enum.test.ts @@ -2,8 +2,9 @@ import { AST_NODE_TYPES, AST_TOKEN_TYPES, } from '@typescript-eslint/experimental-utils'; +import { DefinitionType } from '@typescript-eslint/scope-manager'; import rule from '../../src/rules/prefer-ast-types-enum'; -import { RuleTester, batchedSingleLineTests } from '../RuleTester'; +import { batchedSingleLineTests, RuleTester } from '../RuleTester'; const ruleTester = new RuleTester({ parser: '@typescript-eslint/parser', @@ -17,6 +18,7 @@ ruleTester.run('prefer-ast-types-enum', rule, { "node.type === 'constructor';", 'node.type === AST_NODE_TYPES.Literal;', 'node.type === AST_TOKEN_TYPES.Keyword;', + 'node.type === DefinitionType.Parameter;', 'node.type === 1;', ` enum MY_ENUM { @@ -33,10 +35,12 @@ ruleTester.run('prefer-ast-types-enum', rule, { code: ` node.type === 'Literal'; node.type === 'Keyword'; +node.type === 'Parameter'; `, output: ` node.type === AST_NODE_TYPES.Literal; node.type === AST_TOKEN_TYPES.Keyword; +node.type === DefinitionType.Parameter; `, errors: [ { @@ -49,6 +53,11 @@ node.type === AST_TOKEN_TYPES.Keyword; messageId: 'preferEnum', line: 3, }, + { + data: { enumName: 'DefinitionType', literal: DefinitionType.Parameter }, + messageId: 'preferEnum', + line: 4, + }, ], }), }); diff --git a/packages/eslint-plugin-tslint/CHANGELOG.md b/packages/eslint-plugin-tslint/CHANGELOG.md index ef2a3e4042c..78d7fdab633 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. +# [4.32.0](https://github.com/typescript-eslint/typescript-eslint/compare/v4.31.2...v4.32.0) (2021-09-27) + +**Note:** Version bump only for package @typescript-eslint/eslint-plugin-tslint + + + + + ## [4.31.2](https://github.com/typescript-eslint/typescript-eslint/compare/v4.31.1...v4.31.2) (2021-09-20) **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 da344e836d9..ba8dcac39f7 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": "4.31.2", + "version": "4.32.0", "main": "dist/index.js", "typings": "src/index.ts", "description": "TSLint wrapper plugin for ESLint", @@ -38,7 +38,7 @@ "typecheck": "tsc -p tsconfig.json --noEmit" }, "dependencies": { - "@typescript-eslint/experimental-utils": "4.31.2", + "@typescript-eslint/experimental-utils": "4.32.0", "lodash": "^4.17.21" }, "peerDependencies": { @@ -48,6 +48,6 @@ }, "devDependencies": { "@types/lodash": "*", - "@typescript-eslint/parser": "4.31.2" + "@typescript-eslint/parser": "4.32.0" } } diff --git a/packages/eslint-plugin/CHANGELOG.md b/packages/eslint-plugin/CHANGELOG.md index 8c99e9fce56..dc0cf8d2599 100644 --- a/packages/eslint-plugin/CHANGELOG.md +++ b/packages/eslint-plugin/CHANGELOG.md @@ -3,6 +3,32 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [4.32.0](https://github.com/typescript-eslint/typescript-eslint/compare/v4.31.2...v4.32.0) (2021-09-27) + + +### Bug Fixes + +* **eslint-plugin:** [consistent-type-definitions] correct fix for `export default` ([#3899](https://github.com/typescript-eslint/typescript-eslint/issues/3899)) ([ebb33ed](https://github.com/typescript-eslint/typescript-eslint/commit/ebb33ed8bc29f69ca2a657ec5b31857c0aeb4b56)) +* **eslint-plugin:** [no-require-imports] report only global `require` ([#3871](https://github.com/typescript-eslint/typescript-eslint/issues/3871)) ([8aa87a1](https://github.com/typescript-eslint/typescript-eslint/commit/8aa87a136e7cd7b40fbf09fcfa26bf04d1c6d5fe)) +* **eslint-plugin:** [no-shadow] ignore type-only imports properly ([#3868](https://github.com/typescript-eslint/typescript-eslint/issues/3868)) ([dda9cee](https://github.com/typescript-eslint/typescript-eslint/commit/dda9cee68a5cd78b358a854027999c739ac623e9)) +* **eslint-plugin:** [no-var-requires] report problems within `NewExpression` ([#3884](https://github.com/typescript-eslint/typescript-eslint/issues/3884)) ([ed5e459](https://github.com/typescript-eslint/typescript-eslint/commit/ed5e45983fa052accf3a7b5fcdbfcb15ed09490f)) +* **eslint-plugin:** [padding-line-between-statements] problems within namespaces not being reported ([#3869](https://github.com/typescript-eslint/typescript-eslint/issues/3869)) ([1861356](https://github.com/typescript-eslint/typescript-eslint/commit/186135698b40b510ffff6a2402aa34f2726596ea)) +* **eslint-plugin:** [prefer-regexp-exec] respect flags when using `RegExp` ([#3855](https://github.com/typescript-eslint/typescript-eslint/issues/3855)) ([ffdb5ff](https://github.com/typescript-eslint/typescript-eslint/commit/ffdb5ff9900e07374a2f3686447e3e2c78fbc38a)) +* **eslint-plugin:** [prefer-return-this-type] handle generics properly in fixer ([#3852](https://github.com/typescript-eslint/typescript-eslint/issues/3852)) ([9e98b8f](https://github.com/typescript-eslint/typescript-eslint/commit/9e98b8f43ca6aadc9758a4e9a0d1d3c250af6cca)) +* **eslint-plugin:** false-positive/negative with array index in no-unnecessary-condition ([#3805](https://github.com/typescript-eslint/typescript-eslint/issues/3805)) ([bdb8f0b](https://github.com/typescript-eslint/typescript-eslint/commit/bdb8f0be1466e4a4b713e91199be91030650ed01)) + + +### Features + +* **eslint-plugin:** [no-type-alias]: add allowGenerics option ([#3865](https://github.com/typescript-eslint/typescript-eslint/issues/3865)) ([4195919](https://github.com/typescript-eslint/typescript-eslint/commit/41959199735a6d4fe3ae7825f3087e8fb249be9f)) +* **eslint-plugin:** add `no-non-null-asserted-nullish-coalescing` rule ([#3349](https://github.com/typescript-eslint/typescript-eslint/issues/3349)) ([4e99961](https://github.com/typescript-eslint/typescript-eslint/commit/4e999614e9761f6dc7e5aa0c5bad76ab164ab3fb)) +* **eslint-plugin:** add new extended rule `no-restricted-imports` ([#3775](https://github.com/typescript-eslint/typescript-eslint/issues/3775)) ([ec5d506](https://github.com/typescript-eslint/typescript-eslint/commit/ec5d50696b249a207d322e4a2fc66582122eb010)) +* **eslint-plugin-internal:** [prefer-ast-types-enum] add `DefinitionType` enum ([#3916](https://github.com/typescript-eslint/typescript-eslint/issues/3916)) ([13b7de5](https://github.com/typescript-eslint/typescript-eslint/commit/13b7de508e0f8eac492879ff9ab99acd8d3e977e)) + + + + + ## [4.31.2](https://github.com/typescript-eslint/typescript-eslint/compare/v4.31.1...v4.31.2) (2021-09-20) **Note:** Version bump only for package @typescript-eslint/eslint-plugin diff --git a/packages/eslint-plugin/README.md b/packages/eslint-plugin/README.md index 5b32c4ef29e..c8c783dba6f 100644 --- a/packages/eslint-plugin/README.md +++ b/packages/eslint-plugin/README.md @@ -95,90 +95,91 @@ Pro Tip: For larger codebases you may want to consider splitting our linting int **Key**: :white_check_mark: = recommended, :wrench: = fixable, :thought_balloon: = requires type information -| Name | Description | :white_check_mark: | :wrench: | :thought_balloon: | -| --------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------- | ------------------ | -------- | ----------------- | -| [`@typescript-eslint/adjacent-overload-signatures`](./docs/rules/adjacent-overload-signatures.md) | Require that member overloads be consecutive | :white_check_mark: | | | -| [`@typescript-eslint/array-type`](./docs/rules/array-type.md) | Requires using either `T[]` or `Array` for arrays | | :wrench: | | -| [`@typescript-eslint/await-thenable`](./docs/rules/await-thenable.md) | Disallows awaiting a value that is not a Thenable | :white_check_mark: | | :thought_balloon: | -| [`@typescript-eslint/ban-ts-comment`](./docs/rules/ban-ts-comment.md) | Bans `@ts-` comments from being used or requires descriptions after directive | :white_check_mark: | | | -| [`@typescript-eslint/ban-tslint-comment`](./docs/rules/ban-tslint-comment.md) | Bans `// tslint:` comments from being used | | :wrench: | | -| [`@typescript-eslint/ban-types`](./docs/rules/ban-types.md) | Bans specific types from being used | :white_check_mark: | :wrench: | | -| [`@typescript-eslint/class-literal-property-style`](./docs/rules/class-literal-property-style.md) | Ensures that literals on classes are exposed in a consistent style | | :wrench: | | -| [`@typescript-eslint/consistent-indexed-object-style`](./docs/rules/consistent-indexed-object-style.md) | Enforce or disallow the use of the record type | | :wrench: | | -| [`@typescript-eslint/consistent-type-assertions`](./docs/rules/consistent-type-assertions.md) | Enforces consistent usage of type assertions | | | | -| [`@typescript-eslint/consistent-type-definitions`](./docs/rules/consistent-type-definitions.md) | Consistent with type definition either `interface` or `type` | | :wrench: | | -| [`@typescript-eslint/consistent-type-imports`](./docs/rules/consistent-type-imports.md) | Enforces consistent usage of type imports | | :wrench: | | -| [`@typescript-eslint/explicit-function-return-type`](./docs/rules/explicit-function-return-type.md) | Require explicit return types on functions and class methods | | | | -| [`@typescript-eslint/explicit-member-accessibility`](./docs/rules/explicit-member-accessibility.md) | Require explicit accessibility modifiers on class properties and methods | | :wrench: | | -| [`@typescript-eslint/explicit-module-boundary-types`](./docs/rules/explicit-module-boundary-types.md) | Require explicit return and argument types on exported functions' and classes' public class methods | :white_check_mark: | | | -| [`@typescript-eslint/member-delimiter-style`](./docs/rules/member-delimiter-style.md) | Require a specific member delimiter style for interfaces and type literals | | :wrench: | | -| [`@typescript-eslint/member-ordering`](./docs/rules/member-ordering.md) | Require a consistent member declaration order | | | | -| [`@typescript-eslint/method-signature-style`](./docs/rules/method-signature-style.md) | Enforces using a particular method signature syntax. | | :wrench: | | -| [`@typescript-eslint/naming-convention`](./docs/rules/naming-convention.md) | Enforces naming conventions for everything across a codebase | | | :thought_balloon: | -| [`@typescript-eslint/no-base-to-string`](./docs/rules/no-base-to-string.md) | Requires that `.toString()` is only called on objects which provide useful information when stringified | | | :thought_balloon: | -| [`@typescript-eslint/no-confusing-non-null-assertion`](./docs/rules/no-confusing-non-null-assertion.md) | Disallow non-null assertion in locations that may be confusing | | :wrench: | | -| [`@typescript-eslint/no-confusing-void-expression`](./docs/rules/no-confusing-void-expression.md) | Requires expressions of type void to appear in statement position | | :wrench: | :thought_balloon: | -| [`@typescript-eslint/no-dynamic-delete`](./docs/rules/no-dynamic-delete.md) | Disallow the delete operator with computed key expressions | | :wrench: | | -| [`@typescript-eslint/no-empty-interface`](./docs/rules/no-empty-interface.md) | Disallow the declaration of empty interfaces | :white_check_mark: | :wrench: | | -| [`@typescript-eslint/no-explicit-any`](./docs/rules/no-explicit-any.md) | Disallow usage of the `any` type | :white_check_mark: | :wrench: | | -| [`@typescript-eslint/no-extra-non-null-assertion`](./docs/rules/no-extra-non-null-assertion.md) | Disallow extra non-null assertion | :white_check_mark: | :wrench: | | -| [`@typescript-eslint/no-extraneous-class`](./docs/rules/no-extraneous-class.md) | Forbids the use of classes as namespaces | | | | -| [`@typescript-eslint/no-floating-promises`](./docs/rules/no-floating-promises.md) | Requires Promise-like values to be handled appropriately | :white_check_mark: | | :thought_balloon: | -| [`@typescript-eslint/no-for-in-array`](./docs/rules/no-for-in-array.md) | Disallow iterating over an array with a for-in loop | :white_check_mark: | | :thought_balloon: | -| [`@typescript-eslint/no-implicit-any-catch`](./docs/rules/no-implicit-any-catch.md) | Disallow usage of the implicit `any` type in catch clauses | | :wrench: | | -| [`@typescript-eslint/no-inferrable-types`](./docs/rules/no-inferrable-types.md) | Disallows explicit type declarations for variables or parameters initialized to a number, string, or boolean | :white_check_mark: | :wrench: | | -| [`@typescript-eslint/no-invalid-void-type`](./docs/rules/no-invalid-void-type.md) | Disallows usage of `void` type outside of generic or return types | | | | -| [`@typescript-eslint/no-meaningless-void-operator`](./docs/rules/no-meaningless-void-operator.md) | Disallow the `void` operator except when used to discard a value | | :wrench: | :thought_balloon: | -| [`@typescript-eslint/no-misused-new`](./docs/rules/no-misused-new.md) | Enforce valid definition of `new` and `constructor` | :white_check_mark: | | | -| [`@typescript-eslint/no-misused-promises`](./docs/rules/no-misused-promises.md) | Avoid using promises in places not designed to handle them | :white_check_mark: | | :thought_balloon: | -| [`@typescript-eslint/no-namespace`](./docs/rules/no-namespace.md) | Disallow the use of custom TypeScript modules and namespaces | :white_check_mark: | | | -| [`@typescript-eslint/no-non-null-asserted-optional-chain`](./docs/rules/no-non-null-asserted-optional-chain.md) | Disallows using a non-null assertion after an optional chain expression | :white_check_mark: | | | -| [`@typescript-eslint/no-non-null-assertion`](./docs/rules/no-non-null-assertion.md) | Disallows non-null assertions using the `!` postfix operator | :white_check_mark: | | | -| [`@typescript-eslint/no-parameter-properties`](./docs/rules/no-parameter-properties.md) | Disallow the use of parameter properties in class constructors | | | | -| [`@typescript-eslint/no-require-imports`](./docs/rules/no-require-imports.md) | Disallows invocation of `require()` | | | | -| [`@typescript-eslint/no-this-alias`](./docs/rules/no-this-alias.md) | Disallow aliasing `this` | :white_check_mark: | | | -| [`@typescript-eslint/no-type-alias`](./docs/rules/no-type-alias.md) | Disallow the use of type aliases | | | | -| [`@typescript-eslint/no-unnecessary-boolean-literal-compare`](./docs/rules/no-unnecessary-boolean-literal-compare.md) | Flags unnecessary equality comparisons against boolean literals | | :wrench: | :thought_balloon: | -| [`@typescript-eslint/no-unnecessary-condition`](./docs/rules/no-unnecessary-condition.md) | Prevents conditionals where the type is always truthy or always falsy | | :wrench: | :thought_balloon: | -| [`@typescript-eslint/no-unnecessary-qualifier`](./docs/rules/no-unnecessary-qualifier.md) | Warns when a namespace qualifier is unnecessary | | :wrench: | :thought_balloon: | -| [`@typescript-eslint/no-unnecessary-type-arguments`](./docs/rules/no-unnecessary-type-arguments.md) | Enforces that type arguments will not be used if not required | | :wrench: | :thought_balloon: | -| [`@typescript-eslint/no-unnecessary-type-assertion`](./docs/rules/no-unnecessary-type-assertion.md) | Warns if a type assertion does not change the type of an expression | :white_check_mark: | :wrench: | :thought_balloon: | -| [`@typescript-eslint/no-unnecessary-type-constraint`](./docs/rules/no-unnecessary-type-constraint.md) | Disallows unnecessary constraints on generic types | | :wrench: | | -| [`@typescript-eslint/no-unsafe-argument`](./docs/rules/no-unsafe-argument.md) | Disallows calling an function with an any type value | | | :thought_balloon: | -| [`@typescript-eslint/no-unsafe-assignment`](./docs/rules/no-unsafe-assignment.md) | Disallows assigning any to variables and properties | :white_check_mark: | | :thought_balloon: | -| [`@typescript-eslint/no-unsafe-call`](./docs/rules/no-unsafe-call.md) | Disallows calling an any type value | :white_check_mark: | | :thought_balloon: | -| [`@typescript-eslint/no-unsafe-member-access`](./docs/rules/no-unsafe-member-access.md) | Disallows member access on any typed variables | :white_check_mark: | | :thought_balloon: | -| [`@typescript-eslint/no-unsafe-return`](./docs/rules/no-unsafe-return.md) | Disallows returning any from a function | :white_check_mark: | | :thought_balloon: | -| [`@typescript-eslint/no-var-requires`](./docs/rules/no-var-requires.md) | Disallows the use of require statements except in import statements | :white_check_mark: | | | -| [`@typescript-eslint/non-nullable-type-assertion-style`](./docs/rules/non-nullable-type-assertion-style.md) | Prefers a non-null assertion over explicit type cast when possible | | :wrench: | :thought_balloon: | -| [`@typescript-eslint/prefer-as-const`](./docs/rules/prefer-as-const.md) | Prefer usage of `as const` over literal type | :white_check_mark: | :wrench: | | -| [`@typescript-eslint/prefer-enum-initializers`](./docs/rules/prefer-enum-initializers.md) | Prefer initializing each enums member value | | | | -| [`@typescript-eslint/prefer-for-of`](./docs/rules/prefer-for-of.md) | Prefer a ‘for-of’ loop over a standard ‘for’ loop if the index is only used to access the array being iterated | | | | -| [`@typescript-eslint/prefer-function-type`](./docs/rules/prefer-function-type.md) | Use function types instead of interfaces with call signatures | | :wrench: | | -| [`@typescript-eslint/prefer-includes`](./docs/rules/prefer-includes.md) | Enforce `includes` method over `indexOf` method | | :wrench: | :thought_balloon: | -| [`@typescript-eslint/prefer-literal-enum-member`](./docs/rules/prefer-literal-enum-member.md) | Require that all enum members be literal values to prevent unintended enum member name shadow issues | | | | -| [`@typescript-eslint/prefer-namespace-keyword`](./docs/rules/prefer-namespace-keyword.md) | Require the use of the `namespace` keyword instead of the `module` keyword to declare custom TypeScript modules | :white_check_mark: | :wrench: | | -| [`@typescript-eslint/prefer-nullish-coalescing`](./docs/rules/prefer-nullish-coalescing.md) | Enforce the usage of the nullish coalescing operator instead of logical chaining | | | :thought_balloon: | -| [`@typescript-eslint/prefer-optional-chain`](./docs/rules/prefer-optional-chain.md) | Prefer using concise optional chain expressions instead of chained logical ands | | | | -| [`@typescript-eslint/prefer-readonly`](./docs/rules/prefer-readonly.md) | Requires that private members are marked as `readonly` if they're never modified outside of the constructor | | :wrench: | :thought_balloon: | -| [`@typescript-eslint/prefer-readonly-parameter-types`](./docs/rules/prefer-readonly-parameter-types.md) | Requires that function parameters are typed as readonly to prevent accidental mutation of inputs | | | :thought_balloon: | -| [`@typescript-eslint/prefer-reduce-type-parameter`](./docs/rules/prefer-reduce-type-parameter.md) | Prefer using type parameter when calling `Array#reduce` instead of casting | | :wrench: | :thought_balloon: | -| [`@typescript-eslint/prefer-regexp-exec`](./docs/rules/prefer-regexp-exec.md) | Enforce that `RegExp#exec` is used instead of `String#match` if no global flag is provided | :white_check_mark: | :wrench: | :thought_balloon: | -| [`@typescript-eslint/prefer-return-this-type`](./docs/rules/prefer-return-this-type.md) | Enforce that `this` is used when only `this` type is returned | | :wrench: | :thought_balloon: | -| [`@typescript-eslint/prefer-string-starts-ends-with`](./docs/rules/prefer-string-starts-ends-with.md) | Enforce the use of `String#startsWith` and `String#endsWith` instead of other equivalent methods of checking substrings | | :wrench: | :thought_balloon: | -| [`@typescript-eslint/prefer-ts-expect-error`](./docs/rules/prefer-ts-expect-error.md) | Recommends using `@ts-expect-error` over `@ts-ignore` | | :wrench: | | -| [`@typescript-eslint/promise-function-async`](./docs/rules/promise-function-async.md) | Requires any function or method that returns a Promise to be marked async | | :wrench: | :thought_balloon: | -| [`@typescript-eslint/require-array-sort-compare`](./docs/rules/require-array-sort-compare.md) | Requires `Array#sort` calls to always provide a `compareFunction` | | | :thought_balloon: | -| [`@typescript-eslint/restrict-plus-operands`](./docs/rules/restrict-plus-operands.md) | When adding two variables, operands must both be of type number or of type string | :white_check_mark: | | :thought_balloon: | -| [`@typescript-eslint/restrict-template-expressions`](./docs/rules/restrict-template-expressions.md) | Enforce template literal expressions to be of string type | :white_check_mark: | | :thought_balloon: | -| [`@typescript-eslint/sort-type-union-intersection-members`](./docs/rules/sort-type-union-intersection-members.md) | Enforces that members of a type union/intersection are sorted alphabetically | | :wrench: | | -| [`@typescript-eslint/strict-boolean-expressions`](./docs/rules/strict-boolean-expressions.md) | Restricts the types allowed in boolean expressions | | :wrench: | :thought_balloon: | -| [`@typescript-eslint/switch-exhaustiveness-check`](./docs/rules/switch-exhaustiveness-check.md) | Exhaustiveness checking in switch with union type | | | :thought_balloon: | -| [`@typescript-eslint/triple-slash-reference`](./docs/rules/triple-slash-reference.md) | Sets preference level for triple slash directives versus ES6-style import declarations | :white_check_mark: | | | -| [`@typescript-eslint/type-annotation-spacing`](./docs/rules/type-annotation-spacing.md) | Require consistent spacing around type annotations | | :wrench: | | -| [`@typescript-eslint/typedef`](./docs/rules/typedef.md) | Requires type annotations to exist | | | | -| [`@typescript-eslint/unbound-method`](./docs/rules/unbound-method.md) | Enforces unbound methods are called with their expected scope | :white_check_mark: | | :thought_balloon: | -| [`@typescript-eslint/unified-signatures`](./docs/rules/unified-signatures.md) | Warns for any two overloads that could be unified into one by using a union or an optional/rest parameter | | | | +| Name | Description | :white_check_mark: | :wrench: | :thought_balloon: | +| ----------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------- | ------------------ | -------- | ----------------- | +| [`@typescript-eslint/adjacent-overload-signatures`](./docs/rules/adjacent-overload-signatures.md) | Require that member overloads be consecutive | :white_check_mark: | | | +| [`@typescript-eslint/array-type`](./docs/rules/array-type.md) | Requires using either `T[]` or `Array` for arrays | | :wrench: | | +| [`@typescript-eslint/await-thenable`](./docs/rules/await-thenable.md) | Disallows awaiting a value that is not a Thenable | :white_check_mark: | | :thought_balloon: | +| [`@typescript-eslint/ban-ts-comment`](./docs/rules/ban-ts-comment.md) | Bans `@ts-` comments from being used or requires descriptions after directive | :white_check_mark: | | | +| [`@typescript-eslint/ban-tslint-comment`](./docs/rules/ban-tslint-comment.md) | Bans `// tslint:` comments from being used | | :wrench: | | +| [`@typescript-eslint/ban-types`](./docs/rules/ban-types.md) | Bans specific types from being used | :white_check_mark: | :wrench: | | +| [`@typescript-eslint/class-literal-property-style`](./docs/rules/class-literal-property-style.md) | Ensures that literals on classes are exposed in a consistent style | | :wrench: | | +| [`@typescript-eslint/consistent-indexed-object-style`](./docs/rules/consistent-indexed-object-style.md) | Enforce or disallow the use of the record type | | :wrench: | | +| [`@typescript-eslint/consistent-type-assertions`](./docs/rules/consistent-type-assertions.md) | Enforces consistent usage of type assertions | | | | +| [`@typescript-eslint/consistent-type-definitions`](./docs/rules/consistent-type-definitions.md) | Consistent with type definition either `interface` or `type` | | :wrench: | | +| [`@typescript-eslint/consistent-type-imports`](./docs/rules/consistent-type-imports.md) | Enforces consistent usage of type imports | | :wrench: | | +| [`@typescript-eslint/explicit-function-return-type`](./docs/rules/explicit-function-return-type.md) | Require explicit return types on functions and class methods | | | | +| [`@typescript-eslint/explicit-member-accessibility`](./docs/rules/explicit-member-accessibility.md) | Require explicit accessibility modifiers on class properties and methods | | :wrench: | | +| [`@typescript-eslint/explicit-module-boundary-types`](./docs/rules/explicit-module-boundary-types.md) | Require explicit return and argument types on exported functions' and classes' public class methods | :white_check_mark: | | | +| [`@typescript-eslint/member-delimiter-style`](./docs/rules/member-delimiter-style.md) | Require a specific member delimiter style for interfaces and type literals | | :wrench: | | +| [`@typescript-eslint/member-ordering`](./docs/rules/member-ordering.md) | Require a consistent member declaration order | | | | +| [`@typescript-eslint/method-signature-style`](./docs/rules/method-signature-style.md) | Enforces using a particular method signature syntax. | | :wrench: | | +| [`@typescript-eslint/naming-convention`](./docs/rules/naming-convention.md) | Enforces naming conventions for everything across a codebase | | | :thought_balloon: | +| [`@typescript-eslint/no-base-to-string`](./docs/rules/no-base-to-string.md) | Requires that `.toString()` is only called on objects which provide useful information when stringified | | | :thought_balloon: | +| [`@typescript-eslint/no-confusing-non-null-assertion`](./docs/rules/no-confusing-non-null-assertion.md) | Disallow non-null assertion in locations that may be confusing | | :wrench: | | +| [`@typescript-eslint/no-confusing-void-expression`](./docs/rules/no-confusing-void-expression.md) | Requires expressions of type void to appear in statement position | | :wrench: | :thought_balloon: | +| [`@typescript-eslint/no-dynamic-delete`](./docs/rules/no-dynamic-delete.md) | Disallow the delete operator with computed key expressions | | :wrench: | | +| [`@typescript-eslint/no-empty-interface`](./docs/rules/no-empty-interface.md) | Disallow the declaration of empty interfaces | :white_check_mark: | :wrench: | | +| [`@typescript-eslint/no-explicit-any`](./docs/rules/no-explicit-any.md) | Disallow usage of the `any` type | :white_check_mark: | :wrench: | | +| [`@typescript-eslint/no-extra-non-null-assertion`](./docs/rules/no-extra-non-null-assertion.md) | Disallow extra non-null assertion | :white_check_mark: | :wrench: | | +| [`@typescript-eslint/no-extraneous-class`](./docs/rules/no-extraneous-class.md) | Forbids the use of classes as namespaces | | | | +| [`@typescript-eslint/no-floating-promises`](./docs/rules/no-floating-promises.md) | Requires Promise-like values to be handled appropriately | :white_check_mark: | | :thought_balloon: | +| [`@typescript-eslint/no-for-in-array`](./docs/rules/no-for-in-array.md) | Disallow iterating over an array with a for-in loop | :white_check_mark: | | :thought_balloon: | +| [`@typescript-eslint/no-implicit-any-catch`](./docs/rules/no-implicit-any-catch.md) | Disallow usage of the implicit `any` type in catch clauses | | :wrench: | | +| [`@typescript-eslint/no-inferrable-types`](./docs/rules/no-inferrable-types.md) | Disallows explicit type declarations for variables or parameters initialized to a number, string, or boolean | :white_check_mark: | :wrench: | | +| [`@typescript-eslint/no-invalid-void-type`](./docs/rules/no-invalid-void-type.md) | Disallows usage of `void` type outside of generic or return types | | | | +| [`@typescript-eslint/no-meaningless-void-operator`](./docs/rules/no-meaningless-void-operator.md) | Disallow the `void` operator except when used to discard a value | | :wrench: | :thought_balloon: | +| [`@typescript-eslint/no-misused-new`](./docs/rules/no-misused-new.md) | Enforce valid definition of `new` and `constructor` | :white_check_mark: | | | +| [`@typescript-eslint/no-misused-promises`](./docs/rules/no-misused-promises.md) | Avoid using promises in places not designed to handle them | :white_check_mark: | | :thought_balloon: | +| [`@typescript-eslint/no-namespace`](./docs/rules/no-namespace.md) | Disallow the use of custom TypeScript modules and namespaces | :white_check_mark: | | | +| [`@typescript-eslint/no-non-null-asserted-nullish-coalescing`](./docs/rules/no-non-null-asserted-nullish-coalescing.md) | Disallows using a non-null assertion in the left operand of the nullish coalescing operator | | | | +| [`@typescript-eslint/no-non-null-asserted-optional-chain`](./docs/rules/no-non-null-asserted-optional-chain.md) | Disallows using a non-null assertion after an optional chain expression | :white_check_mark: | | | +| [`@typescript-eslint/no-non-null-assertion`](./docs/rules/no-non-null-assertion.md) | Disallows non-null assertions using the `!` postfix operator | :white_check_mark: | | | +| [`@typescript-eslint/no-parameter-properties`](./docs/rules/no-parameter-properties.md) | Disallow the use of parameter properties in class constructors | | | | +| [`@typescript-eslint/no-require-imports`](./docs/rules/no-require-imports.md) | Disallows invocation of `require()` | | | | +| [`@typescript-eslint/no-this-alias`](./docs/rules/no-this-alias.md) | Disallow aliasing `this` | :white_check_mark: | | | +| [`@typescript-eslint/no-type-alias`](./docs/rules/no-type-alias.md) | Disallow the use of type aliases | | | | +| [`@typescript-eslint/no-unnecessary-boolean-literal-compare`](./docs/rules/no-unnecessary-boolean-literal-compare.md) | Flags unnecessary equality comparisons against boolean literals | | :wrench: | :thought_balloon: | +| [`@typescript-eslint/no-unnecessary-condition`](./docs/rules/no-unnecessary-condition.md) | Prevents conditionals where the type is always truthy or always falsy | | :wrench: | :thought_balloon: | +| [`@typescript-eslint/no-unnecessary-qualifier`](./docs/rules/no-unnecessary-qualifier.md) | Warns when a namespace qualifier is unnecessary | | :wrench: | :thought_balloon: | +| [`@typescript-eslint/no-unnecessary-type-arguments`](./docs/rules/no-unnecessary-type-arguments.md) | Enforces that type arguments will not be used if not required | | :wrench: | :thought_balloon: | +| [`@typescript-eslint/no-unnecessary-type-assertion`](./docs/rules/no-unnecessary-type-assertion.md) | Warns if a type assertion does not change the type of an expression | :white_check_mark: | :wrench: | :thought_balloon: | +| [`@typescript-eslint/no-unnecessary-type-constraint`](./docs/rules/no-unnecessary-type-constraint.md) | Disallows unnecessary constraints on generic types | | :wrench: | | +| [`@typescript-eslint/no-unsafe-argument`](./docs/rules/no-unsafe-argument.md) | Disallows calling an function with an any type value | | | :thought_balloon: | +| [`@typescript-eslint/no-unsafe-assignment`](./docs/rules/no-unsafe-assignment.md) | Disallows assigning any to variables and properties | :white_check_mark: | | :thought_balloon: | +| [`@typescript-eslint/no-unsafe-call`](./docs/rules/no-unsafe-call.md) | Disallows calling an any type value | :white_check_mark: | | :thought_balloon: | +| [`@typescript-eslint/no-unsafe-member-access`](./docs/rules/no-unsafe-member-access.md) | Disallows member access on any typed variables | :white_check_mark: | | :thought_balloon: | +| [`@typescript-eslint/no-unsafe-return`](./docs/rules/no-unsafe-return.md) | Disallows returning any from a function | :white_check_mark: | | :thought_balloon: | +| [`@typescript-eslint/no-var-requires`](./docs/rules/no-var-requires.md) | Disallows the use of require statements except in import statements | :white_check_mark: | | | +| [`@typescript-eslint/non-nullable-type-assertion-style`](./docs/rules/non-nullable-type-assertion-style.md) | Prefers a non-null assertion over explicit type cast when possible | | :wrench: | :thought_balloon: | +| [`@typescript-eslint/prefer-as-const`](./docs/rules/prefer-as-const.md) | Prefer usage of `as const` over literal type | :white_check_mark: | :wrench: | | +| [`@typescript-eslint/prefer-enum-initializers`](./docs/rules/prefer-enum-initializers.md) | Prefer initializing each enums member value | | | | +| [`@typescript-eslint/prefer-for-of`](./docs/rules/prefer-for-of.md) | Prefer a ‘for-of’ loop over a standard ‘for’ loop if the index is only used to access the array being iterated | | | | +| [`@typescript-eslint/prefer-function-type`](./docs/rules/prefer-function-type.md) | Use function types instead of interfaces with call signatures | | :wrench: | | +| [`@typescript-eslint/prefer-includes`](./docs/rules/prefer-includes.md) | Enforce `includes` method over `indexOf` method | | :wrench: | :thought_balloon: | +| [`@typescript-eslint/prefer-literal-enum-member`](./docs/rules/prefer-literal-enum-member.md) | Require that all enum members be literal values to prevent unintended enum member name shadow issues | | | | +| [`@typescript-eslint/prefer-namespace-keyword`](./docs/rules/prefer-namespace-keyword.md) | Require the use of the `namespace` keyword instead of the `module` keyword to declare custom TypeScript modules | :white_check_mark: | :wrench: | | +| [`@typescript-eslint/prefer-nullish-coalescing`](./docs/rules/prefer-nullish-coalescing.md) | Enforce the usage of the nullish coalescing operator instead of logical chaining | | | :thought_balloon: | +| [`@typescript-eslint/prefer-optional-chain`](./docs/rules/prefer-optional-chain.md) | Prefer using concise optional chain expressions instead of chained logical ands | | | | +| [`@typescript-eslint/prefer-readonly`](./docs/rules/prefer-readonly.md) | Requires that private members are marked as `readonly` if they're never modified outside of the constructor | | :wrench: | :thought_balloon: | +| [`@typescript-eslint/prefer-readonly-parameter-types`](./docs/rules/prefer-readonly-parameter-types.md) | Requires that function parameters are typed as readonly to prevent accidental mutation of inputs | | | :thought_balloon: | +| [`@typescript-eslint/prefer-reduce-type-parameter`](./docs/rules/prefer-reduce-type-parameter.md) | Prefer using type parameter when calling `Array#reduce` instead of casting | | :wrench: | :thought_balloon: | +| [`@typescript-eslint/prefer-regexp-exec`](./docs/rules/prefer-regexp-exec.md) | Enforce that `RegExp#exec` is used instead of `String#match` if no global flag is provided | :white_check_mark: | :wrench: | :thought_balloon: | +| [`@typescript-eslint/prefer-return-this-type`](./docs/rules/prefer-return-this-type.md) | Enforce that `this` is used when only `this` type is returned | | :wrench: | :thought_balloon: | +| [`@typescript-eslint/prefer-string-starts-ends-with`](./docs/rules/prefer-string-starts-ends-with.md) | Enforce the use of `String#startsWith` and `String#endsWith` instead of other equivalent methods of checking substrings | | :wrench: | :thought_balloon: | +| [`@typescript-eslint/prefer-ts-expect-error`](./docs/rules/prefer-ts-expect-error.md) | Recommends using `@ts-expect-error` over `@ts-ignore` | | :wrench: | | +| [`@typescript-eslint/promise-function-async`](./docs/rules/promise-function-async.md) | Requires any function or method that returns a Promise to be marked async | | :wrench: | :thought_balloon: | +| [`@typescript-eslint/require-array-sort-compare`](./docs/rules/require-array-sort-compare.md) | Requires `Array#sort` calls to always provide a `compareFunction` | | | :thought_balloon: | +| [`@typescript-eslint/restrict-plus-operands`](./docs/rules/restrict-plus-operands.md) | When adding two variables, operands must both be of type number or of type string | :white_check_mark: | | :thought_balloon: | +| [`@typescript-eslint/restrict-template-expressions`](./docs/rules/restrict-template-expressions.md) | Enforce template literal expressions to be of string type | :white_check_mark: | | :thought_balloon: | +| [`@typescript-eslint/sort-type-union-intersection-members`](./docs/rules/sort-type-union-intersection-members.md) | Enforces that members of a type union/intersection are sorted alphabetically | | :wrench: | | +| [`@typescript-eslint/strict-boolean-expressions`](./docs/rules/strict-boolean-expressions.md) | Restricts the types allowed in boolean expressions | | :wrench: | :thought_balloon: | +| [`@typescript-eslint/switch-exhaustiveness-check`](./docs/rules/switch-exhaustiveness-check.md) | Exhaustiveness checking in switch with union type | | | :thought_balloon: | +| [`@typescript-eslint/triple-slash-reference`](./docs/rules/triple-slash-reference.md) | Sets preference level for triple slash directives versus ES6-style import declarations | :white_check_mark: | | | +| [`@typescript-eslint/type-annotation-spacing`](./docs/rules/type-annotation-spacing.md) | Require consistent spacing around type annotations | | :wrench: | | +| [`@typescript-eslint/typedef`](./docs/rules/typedef.md) | Requires type annotations to exist | | | | +| [`@typescript-eslint/unbound-method`](./docs/rules/unbound-method.md) | Enforces unbound methods are called with their expected scope | :white_check_mark: | | :thought_balloon: | +| [`@typescript-eslint/unified-signatures`](./docs/rules/unified-signatures.md) | Warns for any two overloads that could be unified into one by using a union or an optional/rest parameter | | | | @@ -215,6 +216,7 @@ In these cases, we create what we call an extension rule; a rule within our plug | [`@typescript-eslint/no-loss-of-precision`](./docs/rules/no-loss-of-precision.md) | Disallow literal numbers that lose precision | | | | | [`@typescript-eslint/no-magic-numbers`](./docs/rules/no-magic-numbers.md) | Disallow magic numbers | | | | | [`@typescript-eslint/no-redeclare`](./docs/rules/no-redeclare.md) | Disallow variable redeclaration | | | | +| [`@typescript-eslint/no-restricted-imports`](./docs/rules/no-restricted-imports.md) | Disallow specified modules when loaded by `import` | | | | | [`@typescript-eslint/no-shadow`](./docs/rules/no-shadow.md) | Disallow variable declarations from shadowing variables declared in the outer scope | | | | | [`@typescript-eslint/no-throw-literal`](./docs/rules/no-throw-literal.md) | Disallow throwing literals as exceptions | | | :thought_balloon: | | [`@typescript-eslint/no-unused-expressions`](./docs/rules/no-unused-expressions.md) | Disallow unused expressions | | | | diff --git a/packages/eslint-plugin/docs/rules/no-misused-promises.md b/packages/eslint-plugin/docs/rules/no-misused-promises.md index 6a4c2a55792..0d908890eda 100644 --- a/packages/eslint-plugin/docs/rules/no-misused-promises.md +++ b/packages/eslint-plugin/docs/rules/no-misused-promises.md @@ -23,6 +23,25 @@ while (promise) { } ``` +Examples of **correct** code with `checksConditionals: true`: + +```ts +const promise = Promise.resolve('value'); + +// Always `await` the Promise in a conditional +if (await promise) { + // Do something +} + +const val = (await promise) ? 123 : 456; + +while (await promise) { + // Do something +} +``` + +--- + Examples of **incorrect** code for this rule with `checksVoidReturn: true`: ```ts @@ -37,37 +56,51 @@ new Promise(async (resolve, reject) => { const eventEmitter = new EventEmitter(); eventEmitter.on('some-event', async () => { + synchronousCall(); await doSomething(); + otherSynchronousCall(); }); ``` -Examples of **correct** code for this rule: +Examples of **correct** code with `checksVoidReturn: true`: ```ts -const promise = Promise.resolve('value'); - -if (await promise) { - // Do something -} - -const val = (await promise) ? 123 : 456; - -while (await promise) { - // Do something -} - +// for-of puts `await` in outer context for (const value of [1, 2, 3]) { await doSomething(value); } +// If outer context is not `async`, handle error explicitly +Promise.all( + [1, 2, 3].map(async value => { + await doSomething(value); + }), +).catch(handleError); + +// Use an async IIFE wrapper new Promise((resolve, reject) => { - // Do something - resolve(); + // combine with `void` keyword to tell `no-floating-promises` rule to ignore unhandled rejection + void (async () => { + await doSomething(); + resolve(); + })(); }); +// Name the async wrapper to call it later const eventEmitter = new EventEmitter(); eventEmitter.on('some-event', () => { - doSomething(); + const handler = async () => { + await doSomething(); + otherSynchronousCall(); + }; + + try { + synchronousCall(); + } catch (err) { + handleSpecificError(err); + } + + handler().catch(handleError); }); ``` diff --git a/packages/eslint-plugin/docs/rules/no-non-null-asserted-nullish-coalescing.md b/packages/eslint-plugin/docs/rules/no-non-null-asserted-nullish-coalescing.md new file mode 100644 index 00000000000..799100f2993 --- /dev/null +++ b/packages/eslint-plugin/docs/rules/no-non-null-asserted-nullish-coalescing.md @@ -0,0 +1,49 @@ +# Disallows using a non-null assertion in the left operand of the nullish coalescing operator (`no-non-null-asserted-nullish-coalescing`) + +## Rule Details + +The nullish coalescing operator is designed to provide a default value when dealing with `null` or `undefined`. +Using non-null assertions in the left operand of the nullish coalescing operator is redundant. + +Examples of **incorrect** code for this rule: + +```ts +/* eslint @typescript-eslint/no-non-null-asserted-nullish-coalescing: "error" */ + +foo! ?? bar; +foo.bazz! ?? bar; +foo!.bazz! ?? bar; +foo()! ?? bar; + +let x!: string; +x! ?? ''; + +let x: string; +x = foo(); +x! ?? ''; +``` + +Examples of **correct** code for this rule: + +```ts +/* eslint @typescript-eslint/no-non-null-asserted-nullish-coalescing: "error" */ + +foo ?? bar; +foo ?? bar!; +foo!.bazz ?? bar; +foo!.bazz ?? bar!; +foo() ?? bar; + +// This is considered correct code because because there's no way for the user to satisfy it. +let x: string; +x! ?? ''; +``` + +## When Not To Use It + +If you are not using TypeScript 3.7 (or greater), then you will not need to use this rule, as the nullish coalescing operator is not supported. + +## Further Reading + +- [TypeScript 3.7 Release Notes](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-7.html) +- [Nullish Coalescing Proposal](https://github.com/tc39/proposal-nullish-coalescing) diff --git a/packages/eslint-plugin/docs/rules/no-restricted-imports.md b/packages/eslint-plugin/docs/rules/no-restricted-imports.md new file mode 100644 index 00000000000..6e2e8d3e3dc --- /dev/null +++ b/packages/eslint-plugin/docs/rules/no-restricted-imports.md @@ -0,0 +1,64 @@ +# Disallow specified modules when loaded by `import` (`no-restricted-imports`) + +## Rule Details + +This rule extends the base [`eslint/no-restricted-imports`](https://eslint.org/docs/rules/no-restricted-imports) rule. + +## How to use + +```jsonc +{ + // note you must disable the base rule as it can report incorrect errors + "no-restricted-imports": "off", + "@typescript-eslint/no-restricted-imports": "off" +} +``` + +## Options + +See [`eslint/no-restricted-imports` options](https://eslint.org/docs/rules/no-restricted-imports#options). +This rule adds the following options: + +### `allowTypeImports` + +(default: `false`) + +You can specify this option for a specific path or pattern as follows: + +```jsonc +"@typescript-eslint/no-restricted-imports": ["error", { + "paths": [{ + "name": "import-foo", + "message": "Please use import-bar instead.", + "allowTypeImports": true + }, { + "name": "import-baz", + "message": "Please use import-quux instead.", + "allowTypeImports": true + }] +}] +``` + +When set to `true`, the rule will allow [Type-Only Imports](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-8.html#type-only-imports-and-export). + +Examples of **correct** code with the above config: + +```ts +import { foo } from 'other-module'; + +import type foo from 'import-foo'; +export type { Foo } from 'import-foo'; + +import type baz from 'import-baz'; +export type { Baz } from 'import-baz'; +``` + +Example of **incorrect** code with the above config: + +```ts +import foo from 'import-foo'; +export { Foo } from 'import-foo'; + +import baz from 'import-baz'; +export { Baz } from 'import-baz'; +``` diff --git a/packages/eslint-plugin/docs/rules/no-type-alias.md b/packages/eslint-plugin/docs/rules/no-type-alias.md index 5b720b2f331..a3b61f1da44 100644 --- a/packages/eslint-plugin/docs/rules/no-type-alias.md +++ b/packages/eslint-plugin/docs/rules/no-type-alias.md @@ -89,6 +89,7 @@ or more of the following you may pass an object with the options set as follows: - `allowLiterals` set to `"always"` will allow you to use type aliases with literal objects (Defaults to `"never"`) - `allowMappedTypes` set to `"always"` will allow you to use type aliases as mapping tools (Defaults to `"never"`) - `allowTupleTypes` set to `"always"` will allow you to use type aliases with tuples (Defaults to `"never"`) +- `allowGenerics` set to `"always"` will allow you to use type aliases with generics (Defaults to `"never"`) ### `allowAliases` @@ -555,6 +556,28 @@ type Foo = [number] & [number, number]; type Foo = [string] | [number]; ``` +### `allowGenerics` + +This applies to generic types, including TypeScript provided global utility types (`type Foo = Record`). + +The setting accepts the following options: + +- `"always"` or `"never"` to active or deactivate the feature. + +Examples of **correct** code for the `{ "allowGenerics": "always" }` options: + +```ts +type Foo = Bar; + +type Foo = Record; + +type Foo = Readonly; + +type Foo = Partial; + +type Foo = Omit; +``` + ## When Not To Use It When you can't express some shape with an interface or you need to use a union, tuple type, diff --git a/packages/eslint-plugin/package.json b/packages/eslint-plugin/package.json index 0235818f166..eb7f95c789f 100644 --- a/packages/eslint-plugin/package.json +++ b/packages/eslint-plugin/package.json @@ -1,6 +1,6 @@ { "name": "@typescript-eslint/eslint-plugin", - "version": "4.31.2", + "version": "4.32.0", "description": "TypeScript plugin for ESLint", "keywords": [ "eslint", @@ -44,10 +44,11 @@ "typecheck": "tsc -p tsconfig.json --noEmit" }, "dependencies": { - "@typescript-eslint/experimental-utils": "4.31.2", - "@typescript-eslint/scope-manager": "4.31.2", + "@typescript-eslint/experimental-utils": "4.32.0", + "@typescript-eslint/scope-manager": "4.32.0", "debug": "^4.3.1", "functional-red-black-tree": "^1.0.1", + "ignore": "^5.1.8", "regexpp": "^3.1.0", "semver": "^7.3.5", "tsutils": "^3.21.0" diff --git a/packages/eslint-plugin/src/configs/all.ts b/packages/eslint-plugin/src/configs/all.ts index 9d7fde81314..eff553b5b9b 100644 --- a/packages/eslint-plugin/src/configs/all.ts +++ b/packages/eslint-plugin/src/configs/all.ts @@ -82,12 +82,15 @@ export = { '@typescript-eslint/no-misused-new': 'error', '@typescript-eslint/no-misused-promises': 'error', '@typescript-eslint/no-namespace': 'error', + '@typescript-eslint/no-non-null-asserted-nullish-coalescing': 'error', '@typescript-eslint/no-non-null-asserted-optional-chain': 'error', '@typescript-eslint/no-non-null-assertion': 'error', '@typescript-eslint/no-parameter-properties': 'error', 'no-redeclare': 'off', '@typescript-eslint/no-redeclare': 'error', '@typescript-eslint/no-require-imports': 'error', + 'no-restricted-imports': 'off', + '@typescript-eslint/no-restricted-imports': 'error', 'no-shadow': 'off', '@typescript-eslint/no-shadow': 'error', '@typescript-eslint/no-this-alias': 'error', diff --git a/packages/eslint-plugin/src/rules/consistent-type-definitions.ts b/packages/eslint-plugin/src/rules/consistent-type-definitions.ts index f5b2c48a44f..07d848db298 100644 --- a/packages/eslint-plugin/src/rules/consistent-type-definitions.ts +++ b/packages/eslint-plugin/src/rules/consistent-type-definitions.ts @@ -122,6 +122,19 @@ export default util.createRule({ }); } + if ( + node.parent?.type === + AST_NODE_TYPES.ExportDefaultDeclaration + ) { + fixes.push( + fixer.removeRange([node.parent.range[0], node.range[0]]), + fixer.insertTextAfter( + node.body, + `\nexport default ${node.id.name}`, + ), + ); + } + return fixes; }, }); diff --git a/packages/eslint-plugin/src/rules/explicit-module-boundary-types.ts b/packages/eslint-plugin/src/rules/explicit-module-boundary-types.ts index bdcd9750c88..33caf65f19b 100644 --- a/packages/eslint-plugin/src/rules/explicit-module-boundary-types.ts +++ b/packages/eslint-plugin/src/rules/explicit-module-boundary-types.ts @@ -1,7 +1,8 @@ import { - TSESTree, AST_NODE_TYPES, + TSESTree, } from '@typescript-eslint/experimental-utils'; +import { DefinitionType } from '@typescript-eslint/scope-manager'; import * as util from '../util'; import { checkFunctionExpressionReturnType, @@ -294,11 +295,12 @@ export default util.createRule({ for (const definition of variable.defs) { // cases we don't care about in this rule if ( - definition.type === 'ImplicitGlobalVariable' || - definition.type === 'ImportBinding' || - // eslint-disable-next-line @typescript-eslint/internal/prefer-ast-types-enum - definition.type === 'CatchClause' || - definition.type === 'Parameter' + [ + DefinitionType.ImplicitGlobalVariable, + DefinitionType.ImportBinding, + DefinitionType.CatchClause, + DefinitionType.Parameter, + ].includes(definition.type) ) { continue; } diff --git a/packages/eslint-plugin/src/rules/index.ts b/packages/eslint-plugin/src/rules/index.ts index 1f6aa56c7cb..3ab88b478e2 100644 --- a/packages/eslint-plugin/src/rules/index.ts +++ b/packages/eslint-plugin/src/rules/index.ts @@ -54,11 +54,13 @@ import noMeaninglessVoidOperator from './no-meaningless-void-operator'; import noMisusedNew from './no-misused-new'; import noMisusedPromises from './no-misused-promises'; import noNamespace from './no-namespace'; +import noNonNullAssertedNullishCoalescing from './no-non-null-asserted-nullish-coalescing'; import noNonNullAssertedOptionalChain from './no-non-null-asserted-optional-chain'; import noNonNullAssertion from './no-non-null-assertion'; import noParameterProperties from './no-parameter-properties'; import noRedeclare from './no-redeclare'; import noRequireImports from './no-require-imports'; +import noRestrictedImports from './no-restricted-imports'; import noShadow from './no-shadow'; import noThisAlias from './no-this-alias'; import noThrowLiteral from './no-throw-literal'; @@ -175,11 +177,13 @@ export default { 'no-misused-new': noMisusedNew, 'no-misused-promises': noMisusedPromises, 'no-namespace': noNamespace, + 'no-non-null-asserted-nullish-coalescing': noNonNullAssertedNullishCoalescing, 'no-non-null-asserted-optional-chain': noNonNullAssertedOptionalChain, 'no-non-null-assertion': noNonNullAssertion, 'no-parameter-properties': noParameterProperties, 'no-redeclare': noRedeclare, 'no-require-imports': noRequireImports, + 'no-restricted-imports': noRestrictedImports, 'no-shadow': noShadow, 'no-this-alias': noThisAlias, 'no-throw-literal': noThrowLiteral, diff --git a/packages/eslint-plugin/src/rules/no-inferrable-types.ts b/packages/eslint-plugin/src/rules/no-inferrable-types.ts index 110bda41aea..4edcf69c975 100644 --- a/packages/eslint-plugin/src/rules/no-inferrable-types.ts +++ b/packages/eslint-plugin/src/rules/no-inferrable-types.ts @@ -1,3 +1,4 @@ +/* eslint-disable @typescript-eslint/internal/prefer-ast-types-enum */ import { AST_NODE_TYPES, TSESTree, @@ -129,7 +130,6 @@ export default util.createRule({ case AST_NODE_TYPES.TSBooleanKeyword: return ( hasUnaryPrefix(init, '!') || - // eslint-disable-next-line @typescript-eslint/internal/prefer-ast-types-enum isFunctionCall(init, 'Boolean') || isLiteral(init, 'boolean') ); @@ -151,7 +151,6 @@ export default util.createRule({ case AST_NODE_TYPES.TSStringKeyword: return ( - // eslint-disable-next-line @typescript-eslint/internal/prefer-ast-types-enum isFunctionCall(init, 'String') || isLiteral(init, 'string') || init.type === AST_NODE_TYPES.TemplateLiteral diff --git a/packages/eslint-plugin/src/rules/no-non-null-asserted-nullish-coalescing.ts b/packages/eslint-plugin/src/rules/no-non-null-asserted-nullish-coalescing.ts new file mode 100644 index 00000000000..b7619f1a82b --- /dev/null +++ b/packages/eslint-plugin/src/rules/no-non-null-asserted-nullish-coalescing.ts @@ -0,0 +1,108 @@ +import { + ASTUtils, + TSESTree, + TSESLint, +} from '@typescript-eslint/experimental-utils'; +import { Definition, DefinitionType } from '@typescript-eslint/scope-manager'; +import * as util from '../util'; + +function hasAssignmentBeforeNode( + variable: TSESLint.Scope.Variable, + node: TSESTree.Node, +): boolean { + return ( + variable.references.some( + ref => ref.isWrite() && ref.identifier.range[1] < node.range[1], + ) || + variable.defs.some( + def => + isDefinitionWithAssignment(def) && def.node.range[1] < node.range[1], + ) + ); +} + +function isDefinitionWithAssignment(definition: Definition): boolean { + if (definition.type !== DefinitionType.Variable) { + return false; + } + + const variableDeclarator = definition.node; + return ( + variableDeclarator.definite === true || variableDeclarator.init !== null + ); +} + +export default util.createRule({ + name: 'no-non-null-asserted-nullish-coalescing', + meta: { + type: 'problem', + docs: { + description: + 'Disallows using a non-null assertion in the left operand of the nullish coalescing operator', + category: 'Possible Errors', + recommended: false, + suggestion: true, + }, + messages: { + noNonNullAssertedNullishCoalescing: + 'The nullish coalescing operator is designed to handle undefined and null - using a non-null assertion is not needed.', + suggestRemovingNonNull: 'Remove the non-null assertion.', + }, + schema: [], + }, + defaultOptions: [], + create(context) { + return { + 'LogicalExpression[operator = "??"] > TSNonNullExpression.left'( + node: TSESTree.TSNonNullExpression, + ): void { + if (node.expression.type === TSESTree.AST_NODE_TYPES.Identifier) { + const scope = context.getScope(); + const identifier = node.expression; + const variable = ASTUtils.findVariable(scope, identifier.name); + if (variable && !hasAssignmentBeforeNode(variable, node)) { + return; + } + } + + const sourceCode = context.getSourceCode(); + + context.report({ + node, + messageId: 'noNonNullAssertedNullishCoalescing', + /* + Use a suggestion instead of a fixer, because this can break type checks. + The resulting type of the nullish coalesce is only influenced by the right operand if the left operand can be `null` or `undefined`. + After removing the non-null assertion the type of the left operand might contain `null` or `undefined` and then the type of the right operand + might change the resulting type of the nullish coalesce. + See the following example: + + function test(x?: string): string { + const bar = x! ?? false; // type analysis reports `bar` has type `string` + // x ?? false; // type analysis reports `bar` has type `string | false` + return bar; + } + */ + suggest: [ + { + messageId: 'suggestRemovingNonNull', + fix(fixer): TSESLint.RuleFix { + const exclamationMark = util.nullThrows( + sourceCode.getLastToken( + node, + ASTUtils.isNonNullAssertionPunctuator, + ), + util.NullThrowsReasons.MissingToken( + '!', + 'Non-null Assertion', + ), + ); + return fixer.remove(exclamationMark); + }, + }, + ], + }); + }, + }; + }, +}); diff --git a/packages/eslint-plugin/src/rules/no-require-imports.ts b/packages/eslint-plugin/src/rules/no-require-imports.ts index 91d81e0d8c5..9aa4b685dd2 100644 --- a/packages/eslint-plugin/src/rules/no-require-imports.ts +++ b/packages/eslint-plugin/src/rules/no-require-imports.ts @@ -1,4 +1,4 @@ -import { TSESTree } from '@typescript-eslint/experimental-utils'; +import { ASTUtils, TSESTree } from '@typescript-eslint/experimental-utils'; import * as util from '../util'; export default util.createRule({ @@ -18,13 +18,19 @@ export default util.createRule({ defaultOptions: [], create(context) { return { - 'CallExpression > Identifier[name="require"]'( - node: TSESTree.Identifier, + 'CallExpression[callee.name="require"]'( + node: TSESTree.CallExpression, ): void { - context.report({ - node: node.parent!, - messageId: 'noRequireImports', - }); + const variable = ASTUtils.findVariable(context.getScope(), 'require'); + + // ignore non-global require usage as it's something user-land custom instead + // of the commonjs standard + if (!variable?.identifiers.length) { + context.report({ + node, + messageId: 'noRequireImports', + }); + } }, TSExternalModuleReference(node): void { context.report({ diff --git a/packages/eslint-plugin/src/rules/no-restricted-imports.ts b/packages/eslint-plugin/src/rules/no-restricted-imports.ts new file mode 100644 index 00000000000..2a01a54c62e --- /dev/null +++ b/packages/eslint-plugin/src/rules/no-restricted-imports.ts @@ -0,0 +1,191 @@ +import { AST_NODE_TYPES } from '@typescript-eslint/experimental-utils'; +import baseRule, { + ArrayOfStringOrObjectPatterns, + ArrayOfStringOrObject, +} from 'eslint/lib/rules/no-restricted-imports'; +import ignore, { Ignore } from 'ignore'; +import { + InferOptionsTypeFromRule, + InferMessageIdsTypeFromRule, + createRule, + deepMerge, +} from '../util'; + +export type Options = InferOptionsTypeFromRule; +export type MessageIds = InferMessageIdsTypeFromRule; + +const allowTypeImportsOptionSchema = { + allowTypeImports: { + type: 'boolean', + default: false, + }, +}; +const schemaForMergeArrayOfStringsOrObjects = { + items: { + anyOf: [ + {}, + { + properties: allowTypeImportsOptionSchema, + }, + ], + }, +}; +const schemaForMergeArrayOfStringsOrObjectPatterns = { + anyOf: [ + {}, + { + items: { + properties: allowTypeImportsOptionSchema, + }, + }, + ], +}; +const schema = deepMerge( + { ...baseRule.meta.schema }, + { + anyOf: [ + schemaForMergeArrayOfStringsOrObjects, + { + items: { + properties: { + paths: schemaForMergeArrayOfStringsOrObjects, + patterns: schemaForMergeArrayOfStringsOrObjectPatterns, + }, + }, + }, + ], + }, +); + +function isObjectOfPaths( + obj: unknown, +): obj is { paths: ArrayOfStringOrObject } { + return Object.prototype.hasOwnProperty.call(obj, 'paths'); +} + +function isObjectOfPatterns( + obj: unknown, +): obj is { patterns: ArrayOfStringOrObjectPatterns } { + return Object.prototype.hasOwnProperty.call(obj, 'patterns'); +} + +function isOptionsArrayOfStringOrObject( + options: Options, +): options is ArrayOfStringOrObject { + if (isObjectOfPaths(options[0])) { + return false; + } + if (isObjectOfPatterns(options[0])) { + return false; + } + return true; +} + +function getRestrictedPaths(options: Options): ArrayOfStringOrObject { + if (isOptionsArrayOfStringOrObject(options)) { + return options; + } + if (isObjectOfPaths(options[0])) { + return options[0].paths; + } + return []; +} + +function getRestrictedPatterns( + options: Options, +): ArrayOfStringOrObjectPatterns { + if (isObjectOfPatterns(options[0])) { + return options[0].patterns; + } + return []; +} + +export default createRule({ + name: 'no-restricted-imports', + meta: { + type: 'suggestion', + docs: { + description: 'Disallow specified modules when loaded by `import`', + category: 'Best Practices', + recommended: false, + extendsBaseRule: true, + }, + messages: baseRule.meta.messages, + fixable: baseRule.meta.fixable, + schema, + }, + defaultOptions: [], + create(context) { + const rules = baseRule.create(context); + const { options } = context; + + const restrictedPaths = getRestrictedPaths(options); + const allowedTypeImportPathNameSet: Set = new Set(); + for (const restrictedPath of restrictedPaths) { + if ( + typeof restrictedPath === 'object' && + restrictedPath.allowTypeImports + ) { + allowedTypeImportPathNameSet.add(restrictedPath.name); + } + } + function isAllowedTypeImportPath(importSource: string): boolean { + return allowedTypeImportPathNameSet.has(importSource); + } + + const restrictedPatterns = getRestrictedPatterns(options); + const allowedImportTypeMatchers: Ignore[] = []; + for (const restrictedPattern of restrictedPatterns) { + if ( + typeof restrictedPattern === 'object' && + restrictedPattern.allowTypeImports + ) { + allowedImportTypeMatchers.push(ignore().add(restrictedPattern.group)); + } + } + function isAllowedTypeImportPattern(importSource: string): boolean { + return allowedImportTypeMatchers.every(matcher => { + return matcher.ignores(importSource); + }); + } + + return { + ImportDeclaration(node): void { + if (typeof node.source.value !== 'string') { + return; + } + if (node.importKind === 'type') { + const importSource = node.source.value.trim(); + if ( + !isAllowedTypeImportPath(importSource) && + !isAllowedTypeImportPattern(importSource) + ) { + return rules.ImportDeclaration(node); + } + } else { + return rules.ImportDeclaration(node); + } + }, + ExportNamedDeclaration(node): void { + if ( + node.source?.type !== AST_NODE_TYPES.Literal || + typeof node.source.value !== 'string' + ) { + return; + } + if (node.exportKind === 'type') { + const importSource = node.source.value.trim(); + if ( + !isAllowedTypeImportPath(importSource) && + !isAllowedTypeImportPattern(importSource) + ) { + return rules.ExportNamedDeclaration(node); + } + } else { + return rules.ExportNamedDeclaration(node); + } + }, + ExportAllDeclaration: rules.ExportAllDeclaration, + }; + }, +}); diff --git a/packages/eslint-plugin/src/rules/no-shadow.ts b/packages/eslint-plugin/src/rules/no-shadow.ts index 6eb2ef38f7c..61a34c231d0 100644 --- a/packages/eslint-plugin/src/rules/no-shadow.ts +++ b/packages/eslint-plugin/src/rules/no-shadow.ts @@ -1,9 +1,14 @@ import { - TSESTree, - TSESLint, AST_NODE_TYPES, + TSESLint, + TSESTree, } from '@typescript-eslint/experimental-utils'; -import { ScopeType } from '@typescript-eslint/scope-manager'; +import { + Definition, + DefinitionType, + ImportBindingDefinition, + ScopeType, +} from '@typescript-eslint/scope-manager'; import * as util from '../util'; type MessageIds = 'noShadow'; @@ -82,7 +87,19 @@ export default util.createRule({ * Check if variable is a `this` parameter. */ function isThisParam(variable: TSESLint.Scope.Variable): boolean { - return variable.defs[0].type === 'Parameter' && variable.name === 'this'; + return ( + variable.defs[0].type === DefinitionType.Parameter && + variable.name === 'this' + ); + } + + function isTypeImport( + definition: Definition, + ): definition is ImportBindingDefinition { + return ( + definition.type === DefinitionType.ImportBinding && + definition.parent.importKind === 'type' + ); } function isTypeValueShadow( @@ -98,8 +115,11 @@ export default util.createRule({ return false; } + const [firstDefinition] = shadowed.defs; const isShadowedValue = - 'isValueVariable' in shadowed ? shadowed.isValueVariable : true; + !('isValueVariable' in shadowed) || + !firstDefinition || + (!isTypeImport(firstDefinition) && shadowed.isValueVariable); return variable.isValueVariable !== isShadowedValue; } @@ -276,7 +296,7 @@ export default util.createRule({ inner && outer[0] < inner[0] && inner[1] < outer[1] && - ((innerDef.type === 'FunctionName' && + ((innerDef.type === DefinitionType.FunctionName && innerDef.node.type === AST_NODE_TYPES.FunctionExpression) || innerDef.node.type === AST_NODE_TYPES.ClassExpression) && outerScope === innerScope.upper diff --git a/packages/eslint-plugin/src/rules/no-type-alias.ts b/packages/eslint-plugin/src/rules/no-type-alias.ts index 3e93a995e64..cf56745ca90 100644 --- a/packages/eslint-plugin/src/rules/no-type-alias.ts +++ b/packages/eslint-plugin/src/rules/no-type-alias.ts @@ -1,5 +1,6 @@ import { AST_NODE_TYPES, + AST_TOKEN_TYPES, TSESTree, } from '@typescript-eslint/experimental-utils'; import * as util from '../util'; @@ -27,6 +28,7 @@ type Options = [ allowLiterals?: Values; allowMappedTypes?: Values; allowTupleTypes?: Values; + allowGenerics?: 'always' | 'never'; }, ]; type MessageIds = 'noTypeAlias' | 'noCompositionAlias'; @@ -79,6 +81,9 @@ export default util.createRule({ allowTupleTypes: { enum: enumValues, }, + allowGenerics: { + enum: ['always', 'never'], + }, }, additionalProperties: false, }, @@ -93,6 +98,7 @@ export default util.createRule({ allowLiterals: 'never', allowMappedTypes: 'never', allowTupleTypes: 'never', + allowGenerics: 'never', }, ], create( @@ -106,6 +112,7 @@ export default util.createRule({ allowLiterals, allowMappedTypes, allowTupleTypes, + allowGenerics, }, ], ) { @@ -203,6 +210,13 @@ export default util.createRule({ return false; }; + const isValidGeneric = (type: TypeWithLabel): boolean => { + return ( + type.node.type === AST_NODE_TYPES.TSTypeReference && + type.node.typeParameters !== undefined + ); + }; + const checkAndReport = ( optionValue: Values, isTopLevel: boolean, @@ -260,9 +274,12 @@ export default util.createRule({ } else if (isValidTupleType(type)) { // tuple types checkAndReport(allowTupleTypes!, isTopLevel, type, 'Tuple Types'); + } else if (isValidGeneric(type)) { + if (allowGenerics === 'never') { + reportError(type.node, type.compositionType, isTopLevel, 'Generics'); + } } else if ( - // eslint-disable-next-line @typescript-eslint/internal/prefer-ast-types-enum - type.node.type.endsWith('Keyword') || + type.node.type.endsWith(AST_TOKEN_TYPES.Keyword) || aliasTypes.has(type.node.type) || (type.node.type === AST_NODE_TYPES.TSTypeOperator && (type.node.operator === 'keyof' || diff --git a/packages/eslint-plugin/src/rules/no-unnecessary-condition.ts b/packages/eslint-plugin/src/rules/no-unnecessary-condition.ts index 5ae3f93408a..caca4f8bedb 100644 --- a/packages/eslint-plugin/src/rules/no-unnecessary-condition.ts +++ b/packages/eslint-plugin/src/rules/no-unnecessary-condition.ts @@ -261,12 +261,6 @@ export default createRule({ } function checkNodeForNullish(node: TSESTree.Expression): void { - // Since typescript array index signature types don't represent the - // possibility of out-of-bounds access, if we're indexing into an array - // just skip the check, to avoid false positives - if (isArrayIndexExpression(node)) { - return; - } const type = getNodeType(node); // Conditional is always necessary if it involves `any` or `unknown` if (isTypeAnyType(type) || isTypeUnknownType(type)) { @@ -277,7 +271,19 @@ export default createRule({ if (isTypeFlagSet(type, ts.TypeFlags.Never)) { messageId = 'never'; } else if (!isPossiblyNullish(type)) { - messageId = 'neverNullish'; + // Since typescript array index signature types don't represent the + // possibility of out-of-bounds access, if we're indexing into an array + // just skip the check, to avoid false positives + if ( + !isArrayIndexExpression(node) && + !( + node.type === AST_NODE_TYPES.ChainExpression && + node.expression.type !== AST_NODE_TYPES.TSNonNullExpression && + optionChainContainsOptionArrayIndex(node.expression) + ) + ) { + messageId = 'neverNullish'; + } } else if (isAlwaysNullish(type)) { messageId = 'alwaysNullish'; } @@ -477,19 +483,19 @@ export default createRule({ // ?.x // type is {y: "z"} // ?.y // This access is considered "unnecessary" according to the types // ``` - function optionChainContainsArrayIndex( + function optionChainContainsOptionArrayIndex( node: TSESTree.MemberExpression | TSESTree.CallExpression, ): boolean { const lhsNode = node.type === AST_NODE_TYPES.CallExpression ? node.callee : node.object; - if (isArrayIndexExpression(lhsNode)) { + if (node.optional && isArrayIndexExpression(lhsNode)) { return true; } if ( lhsNode.type === AST_NODE_TYPES.MemberExpression || lhsNode.type === AST_NODE_TYPES.CallExpression ) { - return optionChainContainsArrayIndex(lhsNode); + return optionChainContainsOptionArrayIndex(lhsNode); } return false; } @@ -584,7 +590,7 @@ export default createRule({ // Since typescript array index signature types don't represent the // possibility of out-of-bounds access, if we're indexing into an array // just skip the check, to avoid false positives - if (optionChainContainsArrayIndex(node)) { + if (optionChainContainsOptionArrayIndex(node)) { return; } diff --git a/packages/eslint-plugin/src/rules/no-unused-vars-experimental.ts b/packages/eslint-plugin/src/rules/no-unused-vars-experimental.ts index 0aedd20cbb2..75154329522 100644 --- a/packages/eslint-plugin/src/rules/no-unused-vars-experimental.ts +++ b/packages/eslint-plugin/src/rules/no-unused-vars-experimental.ts @@ -1,5 +1,4 @@ -/* eslint-disable no-fallthrough */ - +/* eslint-disable @typescript-eslint/internal/prefer-ast-types-enum, no-fallthrough */ import { TSESTree } from '@typescript-eslint/experimental-utils'; import * as ts from 'typescript'; import * as util from '../util'; @@ -161,7 +160,6 @@ export default util.createRule({ break; case ts.SyntaxKind.PropertyDeclaration: - // eslint-disable-next-line @typescript-eslint/internal/prefer-ast-types-enum report('Property'); break; diff --git a/packages/eslint-plugin/src/rules/no-use-before-define.ts b/packages/eslint-plugin/src/rules/no-use-before-define.ts index 59680863c9b..ef39ec9a5b7 100644 --- a/packages/eslint-plugin/src/rules/no-use-before-define.ts +++ b/packages/eslint-plugin/src/rules/no-use-before-define.ts @@ -3,6 +3,7 @@ import { TSESLint, TSESTree, } from '@typescript-eslint/experimental-utils'; +import { DefinitionType } from '@typescript-eslint/scope-manager'; import * as util from '../util'; const SENTINEL_TYPE = @@ -44,14 +45,14 @@ function parseOptions(options: string | Config | null): Required { * Checks whether or not a given variable is a function declaration. */ function isFunction(variable: TSESLint.Scope.Variable): boolean { - return variable.defs[0].type === 'FunctionName'; + return variable.defs[0].type === DefinitionType.FunctionName; } /** * Checks whether or not a given variable is a type declaration. */ function isTypedef(variable: TSESLint.Scope.Variable): boolean { - return variable.defs[0].type === 'Type'; + return variable.defs[0].type === DefinitionType.Type; } /** @@ -62,7 +63,7 @@ function isOuterEnum( reference: TSESLint.Scope.Reference, ): boolean { return ( - variable.defs[0].type == 'TSEnumName' && + variable.defs[0].type == DefinitionType.TSEnumName && variable.scope.variableScope !== reference.from.variableScope ); } @@ -75,7 +76,7 @@ function isOuterClass( reference: TSESLint.Scope.Reference, ): boolean { return ( - variable.defs[0].type === 'ClassName' && + variable.defs[0].type === DefinitionType.ClassName && variable.scope.variableScope !== reference.from.variableScope ); } @@ -88,7 +89,7 @@ function isOuterVariable( reference: TSESLint.Scope.Reference, ): boolean { return ( - variable.defs[0].type === 'Variable' && + variable.defs[0].type === DefinitionType.Variable && variable.scope.variableScope !== reference.from.variableScope ); } @@ -142,7 +143,7 @@ function isClassRefInClassDecorator( variable: TSESLint.Scope.Variable, reference: TSESLint.Scope.Reference, ): boolean { - if (variable.defs[0].type !== 'ClassName') { + if (variable.defs[0].type !== DefinitionType.ClassName) { return false; } diff --git a/packages/eslint-plugin/src/rules/no-var-requires.ts b/packages/eslint-plugin/src/rules/no-var-requires.ts index 26c49cc9dd2..d7ed1d16f7f 100644 --- a/packages/eslint-plugin/src/rules/no-var-requires.ts +++ b/packages/eslint-plugin/src/rules/no-var-requires.ts @@ -25,20 +25,24 @@ export default util.createRule({ defaultOptions: [], create(context) { return { - CallExpression(node: TSESTree.CallExpression): void { + 'CallExpression[callee.name="require"]'( + node: TSESTree.CallExpression, + ): void { const parent = node.parent?.type === AST_NODE_TYPES.ChainExpression ? node.parent.parent : node.parent; + if ( - node.callee.type === AST_NODE_TYPES.Identifier && - node.callee.name === 'require' && parent && - (parent.type === AST_NODE_TYPES.VariableDeclarator || - parent.type === AST_NODE_TYPES.CallExpression || - parent.type === AST_NODE_TYPES.TSAsExpression || - parent.type === AST_NODE_TYPES.TSTypeAssertion || - parent.type === AST_NODE_TYPES.MemberExpression) + [ + AST_NODE_TYPES.CallExpression, + AST_NODE_TYPES.MemberExpression, + AST_NODE_TYPES.NewExpression, + AST_NODE_TYPES.TSAsExpression, + AST_NODE_TYPES.TSTypeAssertion, + AST_NODE_TYPES.VariableDeclarator, + ].includes(parent.type) ) { context.report({ node, diff --git a/packages/eslint-plugin/src/rules/padding-line-between-statements.ts b/packages/eslint-plugin/src/rules/padding-line-between-statements.ts index f686476e5de..2da4042fbf0 100644 --- a/packages/eslint-plugin/src/rules/padding-line-between-statements.ts +++ b/packages/eslint-plugin/src/rules/padding-line-between-statements.ts @@ -723,10 +723,11 @@ export default util.createRule({ if ( !node.parent || ![ - AST_NODE_TYPES.SwitchStatement, AST_NODE_TYPES.BlockStatement, AST_NODE_TYPES.Program, AST_NODE_TYPES.SwitchCase, + AST_NODE_TYPES.SwitchStatement, + AST_NODE_TYPES.TSModuleBlock, ].includes(node.parent.type) ) { return; diff --git a/packages/eslint-plugin/src/rules/prefer-readonly.ts b/packages/eslint-plugin/src/rules/prefer-readonly.ts index 56ab8265a9a..36c6c7ea81a 100644 --- a/packages/eslint-plugin/src/rules/prefer-readonly.ts +++ b/packages/eslint-plugin/src/rules/prefer-readonly.ts @@ -3,12 +3,12 @@ import * as ts from 'typescript'; import * as util from '../util'; import { typeIsOrHasBaseType } from '../util'; import { - TSESTree, + ASTUtils, AST_NODE_TYPES, + TSESTree, } from '@typescript-eslint/experimental-utils'; type MessageIds = 'preferReadonly'; - type Options = [ { onlyInlineLambdas?: boolean; @@ -135,15 +135,6 @@ export default util.createRule({ return false; } - function isConstructor( - node: TSESTree.Node, - ): node is TSESTree.MethodDefinition { - return ( - node.type === AST_NODE_TYPES.MethodDefinition && - node.kind === 'constructor' - ); - } - function isFunctionScopeBoundaryInStack( node: | TSESTree.ArrowFunctionExpression @@ -231,7 +222,7 @@ export default util.createRule({ | TSESTree.FunctionExpression | TSESTree.MethodDefinition, ): void { - if (isConstructor(node)) { + if (ASTUtils.isConstructor(node)) { classScopeStack[classScopeStack.length - 1].enterConstructor( parserServices.esTreeNodeToTSNodeMap.get(node), ); @@ -246,7 +237,7 @@ export default util.createRule({ | TSESTree.FunctionExpression | TSESTree.MethodDefinition, ): void { - if (isConstructor(node)) { + if (ASTUtils.isConstructor(node)) { classScopeStack[classScopeStack.length - 1].exitConstructor(); } else if (isFunctionScopeBoundaryInStack(node)) { classScopeStack[classScopeStack.length - 1].exitNonConstructor(); diff --git a/packages/eslint-plugin/src/rules/prefer-regexp-exec.ts b/packages/eslint-plugin/src/rules/prefer-regexp-exec.ts index 0d6693715ba..ebb92364e46 100644 --- a/packages/eslint-plugin/src/rules/prefer-regexp-exec.ts +++ b/packages/eslint-plugin/src/rules/prefer-regexp-exec.ts @@ -75,13 +75,31 @@ export default createRule({ return result; } + function isLikelyToContainGlobalFlag( + node: TSESTree.CallExpressionArgument, + ): boolean { + if ( + node.type === AST_NODE_TYPES.CallExpression || + node.type === AST_NODE_TYPES.NewExpression + ) { + const [, flags] = node.arguments; + return ( + flags.type === AST_NODE_TYPES.Literal && + typeof flags.value === 'string' && + flags.value.includes('g') + ); + } + + return node.type === AST_NODE_TYPES.Identifier; + } + return { "CallExpression[arguments.length=1] > MemberExpression.callee[property.name='match'][computed=false]"( memberNode: TSESTree.MemberExpression, ): void { const objectNode = memberNode.object; const callNode = memberNode.parent as TSESTree.CallExpression; - const argumentNode = callNode.arguments[0]; + const [argumentNode] = callNode.arguments; const argumentValue = getStaticValue(argumentNode, globalScope); if ( @@ -96,9 +114,10 @@ export default createRule({ // Don't report regular expressions with global flag. if ( - argumentValue && - argumentValue.value instanceof RegExp && - argumentValue.value.flags.includes('g') + (!argumentValue && isLikelyToContainGlobalFlag(argumentNode)) || + (argumentValue && + argumentValue.value instanceof RegExp && + argumentValue.value.flags.includes('g')) ) { return; } diff --git a/packages/eslint-plugin/src/rules/prefer-return-this-type.ts b/packages/eslint-plugin/src/rules/prefer-return-this-type.ts index 5a41a29d0a0..9fcfcb04200 100644 --- a/packages/eslint-plugin/src/rules/prefer-return-this-type.ts +++ b/packages/eslint-plugin/src/rules/prefer-return-this-type.ts @@ -1,9 +1,9 @@ import { - TSESTree, AST_NODE_TYPES, + TSESTree, } from '@typescript-eslint/experimental-utils'; -import { createRule, forEachReturnStatement, getParserServices } from '../util'; import * as ts from 'typescript'; +import { createRule, forEachReturnStatement, getParserServices } from '../util'; type ClassLikeDeclaration = | TSESTree.ClassDeclaration @@ -40,13 +40,13 @@ export default createRule({ function tryGetNameInType( name: string, typeNode: TSESTree.TypeNode, - ): TSESTree.Identifier | undefined { + ): TSESTree.TSTypeReference | undefined { if ( typeNode.type === AST_NODE_TYPES.TSTypeReference && typeNode.typeName.type === AST_NODE_TYPES.Identifier && typeNode.typeName.name === name ) { - return typeNode.typeName; + return typeNode; } if (typeNode.type === AST_NODE_TYPES.TSUnionType) { @@ -130,29 +130,23 @@ export default createRule({ originalClass: ClassLikeDeclaration, ): void { const className = originalClass.id?.name; - if (!className) { - return; - } - - if (!originalFunc.returnType) { + if (!className || !originalFunc.returnType) { return; } - const classNameRef = tryGetNameInType( + const node = tryGetNameInType( className, originalFunc.returnType.typeAnnotation, ); - if (!classNameRef) { + if (!node) { return; } if (isFunctionReturningThis(originalFunc, originalClass)) { context.report({ - node: classNameRef, + node, messageId: 'useThisType', - fix(fixer) { - return fixer.replaceText(classNameRef, 'this'); - }, + fix: fixer => fixer.replaceText(node, 'this'), }); } } diff --git a/packages/eslint-plugin/src/rules/switch-exhaustiveness-check.ts b/packages/eslint-plugin/src/rules/switch-exhaustiveness-check.ts index 8881473da05..7535aa6dc54 100644 --- a/packages/eslint-plugin/src/rules/switch-exhaustiveness-check.ts +++ b/packages/eslint-plugin/src/rules/switch-exhaustiveness-check.ts @@ -144,7 +144,7 @@ export default createRule({ missingBranches: missingBranchTypes .map(missingType => isTypeFlagSet(missingType, ts.TypeFlags.ESSymbolLike) - ? `typeof ${missingType.getSymbol()?.escapedName}` + ? `typeof ${missingType.getSymbol()?.escapedName as string}` : checker.typeToString(missingType), ) .join(' | '), diff --git a/packages/eslint-plugin/src/util/explicitReturnTypeUtils.ts b/packages/eslint-plugin/src/util/explicitReturnTypeUtils.ts index c05d6c6dab3..881102b7e84 100644 --- a/packages/eslint-plugin/src/util/explicitReturnTypeUtils.ts +++ b/packages/eslint-plugin/src/util/explicitReturnTypeUtils.ts @@ -225,15 +225,11 @@ function isValidFunctionExpressionReturnType( } // https://github.com/typescript-eslint/typescript-eslint/issues/653 - if ( - options.allowDirectConstAssertionInArrowFunctions && + return ( + options.allowDirectConstAssertionInArrowFunctions === true && node.type === AST_NODE_TYPES.ArrowFunctionExpression && returnsConstAssertionDirectly(node) - ) { - return true; - } - - return false; + ); } /** @@ -250,11 +246,11 @@ function isValidFunctionReturnType( return true; } - if (node.returnType || isConstructor(node.parent) || isSetter(node.parent)) { - return true; - } - - return false; + return ( + node.returnType != null || + isConstructor(node.parent) || + isSetter(node.parent) + ); } /** diff --git a/packages/eslint-plugin/tests/rules/ban-types.test.ts b/packages/eslint-plugin/tests/rules/ban-types.test.ts index 27743ecc5a3..9dbd5344be5 100644 --- a/packages/eslint-plugin/tests/rules/ban-types.test.ts +++ b/packages/eslint-plugin/tests/rules/ban-types.test.ts @@ -1,3 +1,4 @@ +/* eslint-disable @typescript-eslint/internal/prefer-ast-types-enum */ import { TSESLint } from '@typescript-eslint/experimental-utils'; import rule, { MessageIds, @@ -5,7 +6,7 @@ import rule, { TYPE_KEYWORDS, } from '../../src/rules/ban-types'; import { objectReduceKey } from '../../src/util'; -import { RuleTester, noFormat } from '../RuleTester'; +import { noFormat, RuleTester } from '../RuleTester'; const ruleTester = new RuleTester({ parser: '@typescript-eslint/parser', @@ -163,7 +164,6 @@ ruleTester.run('ban-types', rule, { { messageId: 'bannedTypeMessage', data: { - // eslint-disable-next-line @typescript-eslint/internal/prefer-ast-types-enum name: 'String', customMessage: ' Use string instead.', }, @@ -180,7 +180,6 @@ ruleTester.run('ban-types', rule, { { messageId: 'bannedTypeMessage', data: { - // eslint-disable-next-line @typescript-eslint/internal/prefer-ast-types-enum name: 'String', customMessage: ' Use string instead.', }, @@ -197,7 +196,6 @@ ruleTester.run('ban-types', rule, { { messageId: 'bannedTypeMessage', data: { - // eslint-disable-next-line @typescript-eslint/internal/prefer-ast-types-enum name: 'String', customMessage: ' Use string instead.', }, @@ -242,7 +240,6 @@ class Foo extends Bar implements Baz { { messageId: 'bannedTypeMessage', data: { - // eslint-disable-next-line @typescript-eslint/internal/prefer-ast-types-enum name: 'String', customMessage: ' Use string instead.', }, @@ -252,7 +249,6 @@ class Foo extends Bar implements Baz { { messageId: 'bannedTypeMessage', data: { - // eslint-disable-next-line @typescript-eslint/internal/prefer-ast-types-enum name: 'String', customMessage: ' Use string instead.', }, @@ -271,7 +267,6 @@ class Foo extends Bar implements Baz { { messageId: 'bannedTypeMessage', data: { - // eslint-disable-next-line @typescript-eslint/internal/prefer-ast-types-enum name: 'String', customMessage: ' Use string instead.', }, @@ -296,7 +291,6 @@ class Foo extends Bar implements Baz { { messageId: 'bannedTypeMessage', data: { - // eslint-disable-next-line @typescript-eslint/internal/prefer-ast-types-enum name: 'String', customMessage: ' Use string instead.', }, @@ -306,7 +300,6 @@ class Foo extends Bar implements Baz { { messageId: 'bannedTypeMessage', data: { - // eslint-disable-next-line @typescript-eslint/internal/prefer-ast-types-enum name: 'String', customMessage: ' Use string instead.', }, @@ -316,7 +309,6 @@ class Foo extends Bar implements Baz { { messageId: 'bannedTypeMessage', data: { - // eslint-disable-next-line @typescript-eslint/internal/prefer-ast-types-enum name: 'String', customMessage: ' Use string instead.', }, diff --git a/packages/eslint-plugin/tests/rules/consistent-type-definitions.test.ts b/packages/eslint-plugin/tests/rules/consistent-type-definitions.test.ts index 105c25724c2..f96672a213f 100644 --- a/packages/eslint-plugin/tests/rules/consistent-type-definitions.test.ts +++ b/packages/eslint-plugin/tests/rules/consistent-type-definitions.test.ts @@ -1,5 +1,5 @@ import rule from '../../src/rules/consistent-type-definitions'; -import { RuleTester, noFormat } from '../RuleTester'; +import { noFormat, RuleTester } from '../RuleTester'; const ruleTester = new RuleTester({ parser: '@typescript-eslint/parser', @@ -281,5 +281,29 @@ declare global { }, ], }, + { + // https://github.com/typescript-eslint/typescript-eslint/issues/3894 + code: ` +export default interface Test { + bar(): string; + foo(): number; +} + `, + output: noFormat` +type Test = { + bar(): string; + foo(): number; +} +export default Test + `, + options: ['type'], + errors: [ + { + messageId: 'typeOverInterface', + line: 2, + column: 26, + }, + ], + }, ], }); diff --git a/packages/eslint-plugin/tests/rules/naming-convention.test.ts b/packages/eslint-plugin/tests/rules/naming-convention.test.ts index 5aa1606eaff..1c693b4fde0 100644 --- a/packages/eslint-plugin/tests/rules/naming-convention.test.ts +++ b/packages/eslint-plugin/tests/rules/naming-convention.test.ts @@ -1,11 +1,12 @@ +/* eslint-disable @typescript-eslint/internal/prefer-ast-types-enum */ import { TSESLint } from '@typescript-eslint/experimental-utils'; import rule, { MessageIds, Options } from '../../src/rules/naming-convention'; import { PredefinedFormatsString, - selectorTypeToMessageString, Selector, + selectorTypeToMessageString, } from '../../src/rules/naming-convention-utils'; -import { RuleTester, getFixturesRootDir } from '../RuleTester'; +import { getFixturesRootDir, RuleTester } from '../RuleTester'; const ruleTester = new RuleTester({ parser: '@typescript-eslint/parser', diff --git a/packages/eslint-plugin/tests/rules/no-non-null-asserted-nullish-coalescing.test.ts b/packages/eslint-plugin/tests/rules/no-non-null-asserted-nullish-coalescing.test.ts new file mode 100644 index 00000000000..3b47a3c2bf0 --- /dev/null +++ b/packages/eslint-plugin/tests/rules/no-non-null-asserted-nullish-coalescing.test.ts @@ -0,0 +1,332 @@ +import rule from '../../src/rules/no-non-null-asserted-nullish-coalescing'; +import { RuleTester, noFormat } from '../RuleTester'; + +const ruleTester = new RuleTester({ + parser: '@typescript-eslint/parser', +}); + +ruleTester.run('no-non-null-asserted-nullish-coalescing', rule, { + valid: [ + 'foo ?? bar;', + 'foo ?? bar!;', + 'foo.bazz ?? bar;', + 'foo.bazz ?? bar!;', + 'foo!.bazz ?? bar;', + 'foo!.bazz ?? bar!;', + 'foo() ?? bar;', + 'foo() ?? bar!;', + '(foo ?? bar)!;', + ` + let x: string; + x! ?? ''; + `, + ` + let x: string; + x ?? ''; + `, + ` + let x!: string; + x ?? ''; + `, + ` + let x: string; + foo(x); + x! ?? ''; + `, + ` + let x: string; + x! ?? ''; + x = foo(); + `, + ` + let x: string; + foo(x); + x! ?? ''; + x = foo(); + `, + ` + let x = foo(); + x ?? ''; + `, + ` + function foo() { + let x: string; + return x ?? ''; + } + `, + ` + let x: string; + function foo() { + return x ?? ''; + } + `, + ], + invalid: [ + { + code: 'foo! ?? bar;', + errors: [ + { + messageId: 'noNonNullAssertedNullishCoalescing', + suggestions: [ + { + messageId: 'suggestRemovingNonNull', + output: 'foo ?? bar;', + }, + ], + }, + ], + }, + { + code: 'foo! ?? bar!;', + errors: [ + { + messageId: 'noNonNullAssertedNullishCoalescing', + suggestions: [ + { + messageId: 'suggestRemovingNonNull', + output: 'foo ?? bar!;', + }, + ], + }, + ], + }, + { + code: 'foo.bazz! ?? bar;', + errors: [ + { + messageId: 'noNonNullAssertedNullishCoalescing', + suggestions: [ + { + messageId: 'suggestRemovingNonNull', + output: 'foo.bazz ?? bar;', + }, + ], + }, + ], + }, + { + code: 'foo.bazz! ?? bar!;', + errors: [ + { + messageId: 'noNonNullAssertedNullishCoalescing', + suggestions: [ + { + messageId: 'suggestRemovingNonNull', + output: 'foo.bazz ?? bar!;', + }, + ], + }, + ], + }, + { + code: 'foo!.bazz! ?? bar;', + errors: [ + { + messageId: 'noNonNullAssertedNullishCoalescing', + suggestions: [ + { + messageId: 'suggestRemovingNonNull', + output: 'foo!.bazz ?? bar;', + }, + ], + }, + ], + }, + { + code: 'foo!.bazz! ?? bar!;', + errors: [ + { + messageId: 'noNonNullAssertedNullishCoalescing', + suggestions: [ + { + messageId: 'suggestRemovingNonNull', + output: 'foo!.bazz ?? bar!;', + }, + ], + }, + ], + }, + { + code: 'foo()! ?? bar;', + errors: [ + { + messageId: 'noNonNullAssertedNullishCoalescing', + suggestions: [ + { + messageId: 'suggestRemovingNonNull', + output: 'foo() ?? bar;', + }, + ], + }, + ], + }, + { + code: 'foo()! ?? bar!;', + errors: [ + { + messageId: 'noNonNullAssertedNullishCoalescing', + suggestions: [ + { + messageId: 'suggestRemovingNonNull', + output: 'foo() ?? bar!;', + }, + ], + }, + ], + }, + { + code: ` +let x!: string; +x! ?? ''; + `.trimRight(), + errors: [ + { + messageId: 'noNonNullAssertedNullishCoalescing', + suggestions: [ + { + messageId: 'suggestRemovingNonNull', + output: ` +let x!: string; +x ?? ''; + `.trimRight(), + }, + ], + }, + ], + }, + { + code: ` +let x: string; +x = foo(); +x! ?? ''; + `.trimRight(), + errors: [ + { + messageId: 'noNonNullAssertedNullishCoalescing', + suggestions: [ + { + messageId: 'suggestRemovingNonNull', + output: ` +let x: string; +x = foo(); +x ?? ''; + `.trimRight(), + }, + ], + }, + ], + }, + { + code: ` +let x: string; +x = foo(); +x! ?? ''; +x = foo(); + `.trimRight(), + errors: [ + { + messageId: 'noNonNullAssertedNullishCoalescing', + suggestions: [ + { + messageId: 'suggestRemovingNonNull', + output: ` +let x: string; +x = foo(); +x ?? ''; +x = foo(); + `.trimRight(), + }, + ], + }, + ], + }, + { + code: ` +let x = foo(); +x! ?? ''; + `.trimRight(), + errors: [ + { + messageId: 'noNonNullAssertedNullishCoalescing', + suggestions: [ + { + messageId: 'suggestRemovingNonNull', + output: ` +let x = foo(); +x ?? ''; + `.trimRight(), + }, + ], + }, + ], + }, + { + code: ` +function foo() { + let x!: string; + return x! ?? ''; +} + `.trimRight(), + errors: [ + { + messageId: 'noNonNullAssertedNullishCoalescing', + suggestions: [ + { + messageId: 'suggestRemovingNonNull', + output: ` +function foo() { + let x!: string; + return x ?? ''; +} + `.trimRight(), + }, + ], + }, + ], + }, + { + code: ` +let x!: string; +function foo() { + return x! ?? ''; +} + `.trimRight(), + errors: [ + { + messageId: 'noNonNullAssertedNullishCoalescing', + suggestions: [ + { + messageId: 'suggestRemovingNonNull', + output: ` +let x!: string; +function foo() { + return x ?? ''; +} + `.trimRight(), + }, + ], + }, + ], + }, + { + code: noFormat` +let x = foo(); +x ! ?? ''; + `.trimRight(), + errors: [ + { + messageId: 'noNonNullAssertedNullishCoalescing', + suggestions: [ + { + messageId: 'suggestRemovingNonNull', + output: noFormat` +let x = foo(); +x ?? ''; + `.trimRight(), + }, + ], + }, + ], + }, + ], +}); diff --git a/packages/eslint-plugin/tests/rules/no-require-imports.test.ts b/packages/eslint-plugin/tests/rules/no-require-imports.test.ts index 606e4c47ce2..d884c77a6d6 100644 --- a/packages/eslint-plugin/tests/rules/no-require-imports.test.ts +++ b/packages/eslint-plugin/tests/rules/no-require-imports.test.ts @@ -17,6 +17,11 @@ ruleTester.run('no-require-imports', rule, { 'import lib9 = lib2.anotherSubImport;', "import lib10 from 'lib10';", "var lib3 = load?.('not_an_import');", + ` +import { createRequire } from 'module'; +const require = createRequire(); +require('remark-preset-prettier'); + `, ], invalid: [ { diff --git a/packages/eslint-plugin/tests/rules/no-restricted-imports.test.ts b/packages/eslint-plugin/tests/rules/no-restricted-imports.test.ts new file mode 100644 index 00000000000..a2c5951a8d1 --- /dev/null +++ b/packages/eslint-plugin/tests/rules/no-restricted-imports.test.ts @@ -0,0 +1,546 @@ +import { AST_NODE_TYPES } from '@typescript-eslint/experimental-utils'; +import rule from '../../src/rules/no-restricted-imports'; +import { RuleTester } from '../RuleTester'; + +const ruleTester = new RuleTester({ + parser: '@typescript-eslint/parser', +}); + +ruleTester.run('no-restricted-imports', rule, { + valid: [ + { + code: "import foo from 'foo';", + options: ['import1', 'import2'], + }, + { + code: "export { foo } from 'foo';", + options: ['import1', 'import2'], + }, + { + code: "import foo from 'foo';", + options: [{ paths: ['import1', 'import2'] }], + }, + { + code: "export { foo } from 'foo';", + options: [{ paths: ['import1', 'import2'] }], + }, + { + code: "import foo from 'foo';", + options: [ + { + paths: ['import1', 'import2'], + patterns: ['import1/private/*', 'import2/*', '!import2/good'], + }, + ], + }, + { + code: "export { foo } from 'foo';", + options: [ + { + paths: ['import1', 'import2'], + patterns: ['import1/private/*', 'import2/*', '!import2/good'], + }, + ], + }, + { + code: "import foo from 'foo';", + options: [ + { + paths: [ + { + name: 'import-foo', + message: 'Please use import-bar instead.', + }, + { + name: 'import-baz', + message: 'Please use import-quux instead.', + }, + ], + }, + ], + }, + { + code: "export { foo } from 'foo';", + options: [ + { + paths: [ + { + name: 'import-foo', + message: 'Please use import-bar instead.', + }, + { + name: 'import-baz', + message: 'Please use import-quux instead.', + }, + ], + }, + ], + }, + { + code: "import foo from 'foo';", + options: [ + { + paths: [ + { + name: 'import-foo', + importNames: ['Bar'], + message: 'Please use Bar from /import-bar/baz/ instead.', + }, + ], + }, + ], + }, + { + code: "export { foo } from 'foo';", + options: [ + { + paths: [ + { + name: 'import-foo', + importNames: ['Bar'], + message: 'Please use Bar from /import-bar/baz/ instead.', + }, + ], + }, + ], + }, + { + code: "import foo from 'foo';", + options: [ + { + patterns: [ + { + group: ['import1/private/*'], + message: 'usage of import1 private modules not allowed.', + }, + { + group: ['import2/*', '!import2/good'], + message: + 'import2 is deprecated, except the modules in import2/good.', + }, + ], + }, + ], + }, + { + code: "export { foo } from 'foo';", + options: [ + { + patterns: [ + { + group: ['import1/private/*'], + message: 'usage of import1 private modules not allowed.', + }, + { + group: ['import2/*', '!import2/good'], + message: + 'import2 is deprecated, except the modules in import2/good.', + }, + ], + }, + ], + }, + { + code: "import type foo from 'import-foo';", + options: [ + { + paths: [ + { + name: 'import-foo', + message: 'Please use import-bar instead.', + allowTypeImports: true, + }, + ], + }, + ], + }, + { + code: "import type { Bar } from 'import-foo';", + options: [ + { + paths: [ + { + name: 'import-foo', + importNames: ['Bar'], + message: 'Please use Bar from /import-bar/baz/ instead.', + allowTypeImports: true, + }, + ], + }, + ], + }, + { + code: "export type { Bar } from 'import-foo';", + options: [ + { + paths: [ + { + name: 'import-foo', + importNames: ['Bar'], + message: 'Please use Bar from /import-bar/baz/ instead.', + allowTypeImports: true, + }, + ], + }, + ], + }, + { + code: "import type foo from 'import1/private/bar';", + options: [ + { + patterns: [ + { + group: ['import1/private/*'], + message: 'usage of import1 private modules not allowed.', + allowTypeImports: true, + }, + ], + }, + ], + }, + { + code: "export type { foo } from 'import1/private/bar';", + options: [ + { + patterns: [ + { + group: ['import1/private/*'], + message: 'usage of import1 private modules not allowed.', + allowTypeImports: true, + }, + ], + }, + ], + }, + { + code: "export * from 'foo';", + options: ['import1'], + }, + { + code: 'export { foo } from foo;', + options: ['import1', 'import2'], + }, + { + code: 'import { foo } from foo;', + options: ['import1', 'import2'], + }, + ], + invalid: [ + { + code: "import foo from 'import1';", + options: ['import1', 'import2'], + errors: [ + { + messageId: 'path', + type: AST_NODE_TYPES.ImportDeclaration, + }, + ], + }, + { + code: "export { foo } from 'import1';", + options: ['import1', 'import2'], + errors: [ + { + messageId: 'path', + type: AST_NODE_TYPES.ExportNamedDeclaration, + }, + ], + }, + { + code: "import foo from 'import1';", + options: [{ paths: ['import1', 'import2'] }], + errors: [ + { + messageId: 'path', + type: AST_NODE_TYPES.ImportDeclaration, + }, + ], + }, + { + code: "export { foo } from 'import1';", + options: [{ paths: ['import1', 'import2'] }], + errors: [ + { + messageId: 'path', + type: AST_NODE_TYPES.ExportNamedDeclaration, + }, + ], + }, + { + code: "import foo from 'import1/private/foo';", + options: [ + { + paths: ['import1', 'import2'], + patterns: ['import1/private/*', 'import2/*', '!import2/good'], + }, + ], + errors: [ + { + messageId: 'patterns', + type: AST_NODE_TYPES.ImportDeclaration, + }, + ], + }, + { + code: "export { foo } from 'import1/private/foo';", + options: [ + { + paths: ['import1', 'import2'], + patterns: ['import1/private/*', 'import2/*', '!import2/good'], + }, + ], + errors: [ + { + messageId: 'patterns', + type: AST_NODE_TYPES.ExportNamedDeclaration, + }, + ], + }, + { + code: "import foo from 'import-foo';", + options: [ + { + paths: [ + { + name: 'import-foo', + message: 'Please use import-bar instead.', + }, + { + name: 'import-baz', + message: 'Please use import-quux instead.', + }, + ], + }, + ], + errors: [ + { + messageId: 'pathWithCustomMessage', + type: AST_NODE_TYPES.ImportDeclaration, + }, + ], + }, + { + code: "export { foo } from 'import-foo';", + options: [ + { + paths: [ + { + name: 'import-foo', + message: 'Please use import-bar instead.', + }, + { + name: 'import-baz', + message: 'Please use import-quux instead.', + }, + ], + }, + ], + errors: [ + { + messageId: 'pathWithCustomMessage', + type: AST_NODE_TYPES.ExportNamedDeclaration, + }, + ], + }, + { + code: "import { Bar } from 'import-foo';", + options: [ + { + paths: [ + { + name: 'import-foo', + importNames: ['Bar'], + message: 'Please use Bar from /import-bar/baz/ instead.', + }, + ], + }, + ], + errors: [ + { + messageId: 'importNameWithCustomMessage', + type: AST_NODE_TYPES.ImportDeclaration, + }, + ], + }, + { + code: "export { Bar } from 'import-foo';", + options: [ + { + paths: [ + { + name: 'import-foo', + importNames: ['Bar'], + message: 'Please use Bar from /import-bar/baz/ instead.', + }, + ], + }, + ], + errors: [ + { + messageId: 'importNameWithCustomMessage', + type: AST_NODE_TYPES.ExportNamedDeclaration, + }, + ], + }, + { + code: "import foo from 'import1/private/foo';", + options: [ + { + patterns: [ + { + group: ['import1/private/*'], + message: 'usage of import1 private modules not allowed.', + }, + { + group: ['import2/*', '!import2/good'], + message: + 'import2 is deprecated, except the modules in import2/good.', + }, + ], + }, + ], + errors: [ + { + messageId: 'patternWithCustomMessage', + type: AST_NODE_TYPES.ImportDeclaration, + }, + ], + }, + { + code: "export { foo } from 'import1/private/foo';", + options: [ + { + patterns: [ + { + group: ['import1/private/*'], + message: 'usage of import1 private modules not allowed.', + }, + { + group: ['import2/*', '!import2/good'], + message: + 'import2 is deprecated, except the modules in import2/good.', + }, + ], + }, + ], + errors: [ + { + messageId: 'patternWithCustomMessage', + type: AST_NODE_TYPES.ExportNamedDeclaration, + }, + ], + }, + { + code: "import foo from 'import-foo';", + options: [ + { + paths: [ + { + name: 'import-foo', + message: 'Please use import-bar instead.', + allowTypeImports: true, + }, + ], + }, + ], + errors: [ + { + messageId: 'pathWithCustomMessage', + type: AST_NODE_TYPES.ImportDeclaration, + }, + ], + }, + { + code: "import { Bar } from 'import-foo';", + options: [ + { + paths: [ + { + name: 'import-foo', + importNames: ['Bar'], + message: 'Please use Bar from /import-bar/baz/ instead.', + allowTypeImports: true, + }, + ], + }, + ], + errors: [ + { + messageId: 'importNameWithCustomMessage', + type: AST_NODE_TYPES.ImportDeclaration, + }, + ], + }, + { + code: "export { Bar } from 'import-foo';", + options: [ + { + paths: [ + { + name: 'import-foo', + importNames: ['Bar'], + message: 'Please use Bar from /import-bar/baz/ instead.', + allowTypeImports: true, + }, + ], + }, + ], + errors: [ + { + messageId: 'importNameWithCustomMessage', + type: AST_NODE_TYPES.ExportNamedDeclaration, + }, + ], + }, + { + code: "import foo from 'import1/private/bar';", + options: [ + { + patterns: [ + { + group: ['import1/private/*'], + message: 'usage of import1 private modules not allowed.', + allowTypeImports: true, + }, + ], + }, + ], + errors: [ + { + messageId: 'patternWithCustomMessage', + type: AST_NODE_TYPES.ImportDeclaration, + }, + ], + }, + { + code: "export { foo } from 'import1/private/bar';", + options: [ + { + patterns: [ + { + group: ['import1/private/*'], + message: 'usage of import1 private modules not allowed.', + allowTypeImports: true, + }, + ], + }, + ], + errors: [ + { + messageId: 'patternWithCustomMessage', + type: AST_NODE_TYPES.ExportNamedDeclaration, + }, + ], + }, + { + code: "export * from 'import1';", + options: ['import1'], + errors: [ + { + messageId: 'path', + type: AST_NODE_TYPES.ExportAllDeclaration, + }, + ], + }, + ], +}); diff --git a/packages/eslint-plugin/tests/rules/no-shadow.test.ts b/packages/eslint-plugin/tests/rules/no-shadow.test.ts index f48adfc1b57..c3e5a09f344 100644 --- a/packages/eslint-plugin/tests/rules/no-shadow.test.ts +++ b/packages/eslint-plugin/tests/rules/no-shadow.test.ts @@ -1,6 +1,6 @@ +import { AST_NODE_TYPES } from '@typescript-eslint/experimental-utils'; import rule from '../../src/rules/no-shadow'; import { RuleTester } from '../RuleTester'; -import { AST_NODE_TYPES } from '@typescript-eslint/experimental-utils'; const ruleTester = new RuleTester({ parserOptions: { @@ -172,6 +172,18 @@ export class Wrapper { } } `, + { + // https://github.com/typescript-eslint/typescript-eslint/issues/3862 + code: ` +import type { foo } from './foo'; +type bar = number; + +// 'foo' is already declared in the upper scope +// 'bar' is fine +function doThing(foo: number, bar: number) {} + `, + options: [{ ignoreTypeValueShadow: true }], + }, ], invalid: [ { @@ -1398,5 +1410,37 @@ function foo(cb) { }, ], }, + { + code: ` +import type { foo } from './foo'; +function doThing(foo: number, bar: number) {} + `, + options: [{ ignoreTypeValueShadow: false }], + errors: [ + { + messageId: 'noShadow', + data: { name: 'foo' }, + type: AST_NODE_TYPES.Identifier, + line: 3, + column: 18, + }, + ], + }, + { + code: ` +import { foo } from './foo'; +function doThing(foo: number, bar: number) {} + `, + options: [{ ignoreTypeValueShadow: true }], + errors: [ + { + messageId: 'noShadow', + data: { name: 'foo' }, + type: AST_NODE_TYPES.Identifier, + line: 3, + column: 18, + }, + ], + }, ], }); diff --git a/packages/eslint-plugin/tests/rules/no-type-alias.test.ts b/packages/eslint-plugin/tests/rules/no-type-alias.test.ts index 1f44675a851..06d06f7672e 100644 --- a/packages/eslint-plugin/tests/rules/no-type-alias.test.ts +++ b/packages/eslint-plugin/tests/rules/no-type-alias.test.ts @@ -481,6 +481,10 @@ type KeyNames = keyof typeof SCALARS; code: 'type Foo = new (bar: number) => string | null;', options: [{ allowConstructors: 'always' }], }, + { + code: 'type Foo = Record;', + options: [{ allowGenerics: 'always' }], + }, ], invalid: [ { @@ -3329,5 +3333,18 @@ type Foo = { }, ], }, + { + code: 'type Foo = Record;', + errors: [ + { + messageId: 'noTypeAlias', + data: { + alias: 'generics', + }, + line: 1, + column: 12, + }, + ], + }, ], }); diff --git a/packages/eslint-plugin/tests/rules/no-unnecessary-condition.test.ts b/packages/eslint-plugin/tests/rules/no-unnecessary-condition.test.ts index 2658061a357..82196fbc8a1 100644 --- a/packages/eslint-plugin/tests/rules/no-unnecessary-condition.test.ts +++ b/packages/eslint-plugin/tests/rules/no-unnecessary-condition.test.ts @@ -315,6 +315,11 @@ returnsArr?.()[42]?.toUpperCase(); ` declare const arr: string[][]; arr[x] ?? []; + `, + // nullish + optional array index + ` +declare const arr: { foo: number }[]; +const bar = arr[42]?.foo ?? 0; `, // Doesn't check the right-hand side of a logical expression // in a non-conditional context @@ -751,6 +756,15 @@ function test(a: string) { code: ` function test(a: string | false) { return a ?? 'default'; +} + `, + errors: [ruleError(3, 10, 'neverNullish')], + }, + // nullish + array index without optional chaining + { + code: ` +function test(a: { foo: string }[]) { + return a[0].foo ?? 'default'; } `, errors: [ruleError(3, 10, 'neverNullish')], @@ -765,6 +779,14 @@ function test(a: null) { }, { code: ` +function test(a: null[]) { + return a[0] ?? 'default'; +} + `, + errors: [ruleError(3, 10, 'alwaysNullish')], + }, + { + code: ` function test(a: never) { return a ?? 'default'; } @@ -1315,6 +1337,17 @@ foo?.fooOrBar.baz?.qux; }, { code: ` +declare const x: { a: { b: number } }[]; +x[0].a?.b; + `, + output: ` +declare const x: { a: { b: number } }[]; +x[0].a.b; + `, + errors: [ruleError(3, 7, 'neverOptionalChain')], + }, + { + code: ` type Foo = { [key: string]: string; foo: 'foo'; bar: 'bar' } | null; type Key = 'bar' | 'foo'; declare const foo: Foo; diff --git a/packages/eslint-plugin/tests/rules/no-unused-vars-experimental.test.ts b/packages/eslint-plugin/tests/rules/no-unused-vars-experimental.test.ts index 67b9d22c86f..6beaa6f0a0a 100644 --- a/packages/eslint-plugin/tests/rules/no-unused-vars-experimental.test.ts +++ b/packages/eslint-plugin/tests/rules/no-unused-vars-experimental.test.ts @@ -1,13 +1,14 @@ +/* eslint-disable @typescript-eslint/internal/prefer-ast-types-enum */ import { InvalidTestCase, ValidTestCase, } from '@typescript-eslint/experimental-utils/dist/ts-eslint'; import rule, { DEFAULT_IGNORED_REGEX_STRING, - Options, MessageIds, + Options, } from '../../src/rules/no-unused-vars-experimental'; -import { RuleTester, getFixturesRootDir } from '../RuleTester'; +import { getFixturesRootDir, RuleTester } from '../RuleTester'; const rootDir = getFixturesRootDir(); const ruleTester = new RuleTester({ @@ -544,7 +545,6 @@ export class Foo { messageId: 'unusedWithIgnorePattern', data: { name: 'foo', - // eslint-disable-next-line @typescript-eslint/internal/prefer-ast-types-enum type: 'Property', pattern: DEFAULT_IGNORED_REGEX, }, diff --git a/packages/eslint-plugin/tests/rules/no-var-requires.test.ts b/packages/eslint-plugin/tests/rules/no-var-requires.test.ts index 688b010e417..8c6ef638a16 100644 --- a/packages/eslint-plugin/tests/rules/no-var-requires.test.ts +++ b/packages/eslint-plugin/tests/rules/no-var-requires.test.ts @@ -132,5 +132,24 @@ ruleTester.run('no-var-requires', rule, { }, ], }, + { + // https://github.com/typescript-eslint/typescript-eslint/issues/3883 + code: ` +const configValidator = new Validator(require('./a.json')); +configValidator.addSchema(require('./a.json')); + `, + errors: [ + { + messageId: 'noVarReqs', + line: 2, + column: 39, + }, + { + messageId: 'noVarReqs', + line: 3, + column: 27, + }, + ], + }, ], }); diff --git a/packages/eslint-plugin/tests/rules/padding-line-between-statements.test.ts b/packages/eslint-plugin/tests/rules/padding-line-between-statements.test.ts index d018f189929..c55a85de08b 100644 --- a/packages/eslint-plugin/tests/rules/padding-line-between-statements.test.ts +++ b/packages/eslint-plugin/tests/rules/padding-line-between-statements.test.ts @@ -5056,5 +5056,45 @@ var a = 1 { messageId: 'expectedBlankLine' }, ], }, + { + // https://github.com/typescript-eslint/typescript-eslint/issues/3863 + code: ` +declare namespace Types { + type Foo = string; + type Bar = string; + interface FooBar { + [key: string]: string; + } + interface BarBaz { + [key: string]: string; + } +} + `, + output: ` +declare namespace Types { + type Foo = string; + + type Bar = string; + + interface FooBar { + [key: string]: string; + } + + interface BarBaz { + [key: string]: string; + } +} + + `, + options: [ + { blankLine: 'always', prev: '*', next: ['interface', 'type'] }, + ], + errors: [ + { messageId: 'expectedBlankLine' }, + { messageId: 'expectedBlankLine' }, + { messageId: 'expectedBlankLine' }, + { messageId: 'expectedBlankLine' }, + ], + }, ], }); diff --git a/packages/eslint-plugin/tests/rules/prefer-regexp-exec.test.ts b/packages/eslint-plugin/tests/rules/prefer-regexp-exec.test.ts index b4593510807..8a5bdfd099d 100644 --- a/packages/eslint-plugin/tests/rules/prefer-regexp-exec.test.ts +++ b/packages/eslint-plugin/tests/rules/prefer-regexp-exec.test.ts @@ -1,5 +1,5 @@ import rule from '../../src/rules/prefer-regexp-exec'; -import { RuleTester, getFixturesRootDir } from '../RuleTester'; +import { getFixturesRootDir, RuleTester } from '../RuleTester'; const rootPath = getFixturesRootDir(); @@ -56,6 +56,24 @@ const matchers = [{ match: (s: RegExp) => false }]; const file = ''; matchers.some(matcher => !!file.match(matcher)); `, + // https://github.com/typescript-eslint/typescript-eslint/issues/3477 + ` +function test(pattern: string) { + 'hello hello'.match(RegExp(pattern, 'g'))?.reduce(() => []); +} + `, + // https://github.com/typescript-eslint/typescript-eslint/issues/3477 + ` +function test(pattern: string) { + 'hello hello'.match(new RegExp(pattern, 'gi'))?.reduce(() => []); +} + `, + // https://github.com/typescript-eslint/typescript-eslint/issues/3477 + ` +const matchCount = (str: string, re: RegExp) => { + return (str.match(re) || []).length; +}; + `, ], invalid: [ { @@ -174,6 +192,44 @@ function f(s: T) { output: ` function f(s: T) { /thing/.exec(s); +} + `, + }, + { + code: ` +const text = 'something'; +const search = new RegExp('test', ''); +text.match(search); + `, + errors: [ + { + messageId: 'regExpExecOverStringMatch', + line: 4, + column: 6, + }, + ], + output: ` +const text = 'something'; +const search = new RegExp('test', ''); +search.exec(text); + `, + }, + { + code: ` +function test(pattern: string) { + 'check'.match(new RegExp(pattern, undefined)); +} + `, + errors: [ + { + messageId: 'regExpExecOverStringMatch', + line: 3, + column: 11, + }, + ], + output: ` +function test(pattern: string) { + new RegExp(pattern, undefined).exec('check'); } `, }, diff --git a/packages/eslint-plugin/tests/rules/prefer-return-this-type.test.ts b/packages/eslint-plugin/tests/rules/prefer-return-this-type.test.ts index 67864d22b6c..a93590dfec0 100644 --- a/packages/eslint-plugin/tests/rules/prefer-return-this-type.test.ts +++ b/packages/eslint-plugin/tests/rules/prefer-return-this-type.test.ts @@ -1,5 +1,5 @@ import rule from '../../src/rules/prefer-return-this-type'; -import { RuleTester, getFixturesRootDir } from '../RuleTester'; +import { getFixturesRootDir, RuleTester } from '../RuleTester'; const rootPath = getFixturesRootDir(); @@ -281,6 +281,33 @@ class Foo { return this; } } +} + `, + }, + { + // https://github.com/typescript-eslint/typescript-eslint/issues/3842 + code: ` +class Animal { + eat(): Animal { + console.log("I'm moving!"); + return this; + } +} + `, + errors: [ + { + messageId: 'useThisType', + line: 3, + column: 10, + endColumn: 19, + }, + ], + output: ` +class Animal { + eat(): this { + console.log("I'm moving!"); + return this; + } } `, }, diff --git a/packages/eslint-plugin/typings/eslint-rules.d.ts b/packages/eslint-plugin/typings/eslint-rules.d.ts index d6677e9dc93..ada68c89a76 100644 --- a/packages/eslint-plugin/typings/eslint-rules.d.ts +++ b/packages/eslint-plugin/typings/eslint-rules.d.ts @@ -860,3 +860,51 @@ declare module 'eslint/lib/rules/object-curly-spacing' { >; export = rule; } + +declare module 'eslint/lib/rules/no-restricted-imports' { + import { TSESLint, TSESTree } from '@typescript-eslint/experimental-utils'; + + namespace rule { + export type ArrayOfStringOrObject = ( + | string + | { + name: string; + message?: string; + importNames?: string[]; + // extended + allowTypeImports?: boolean; + } + )[]; + export type ArrayOfStringOrObjectPatterns = + | string[] + | { + group: string[]; + message?: string; + // extended + allowTypeImports?: boolean; + }[]; + } + + interface ObjectOfPathsAndPatterns { + paths?: rule.ArrayOfStringOrObject; + patterns?: rule.ArrayOfStringOrObjectPatterns; + } + + const rule: TSESLint.RuleModule< + | 'path' + | 'pathWithCustomMessage' + | 'patterns' + | 'patternWithCustomMessage' + | 'everything' + | 'everythingWithCustomMessage' + | 'importName' + | 'importNameWithCustomMessage', + rule.ArrayOfStringOrObject | [ObjectOfPathsAndPatterns], + { + ImportDeclaration(node: TSESTree.ImportDeclaration): void; + ExportNamedDeclaration(node: TSESTree.ExportNamedDeclaration): void; + ExportAllDeclaration(node: TSESTree.ExportAllDeclaration): void; + } + >; + export = rule; +} diff --git a/packages/experimental-utils/CHANGELOG.md b/packages/experimental-utils/CHANGELOG.md index 0b8fafa0d2b..ef9ae813f91 100644 --- a/packages/experimental-utils/CHANGELOG.md +++ b/packages/experimental-utils/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. +# [4.32.0](https://github.com/typescript-eslint/typescript-eslint/compare/v4.31.2...v4.32.0) (2021-09-27) + + +### Bug Fixes + +* **experimental-utils:** add missing signature for `isParenthesized` ([#3887](https://github.com/typescript-eslint/typescript-eslint/issues/3887)) ([806eaac](https://github.com/typescript-eslint/typescript-eslint/commit/806eaac6af5325664634690e9ebd7ffaed276549)) + + + + + ## [4.31.2](https://github.com/typescript-eslint/typescript-eslint/compare/v4.31.1...v4.31.2) (2021-09-20) **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 5f011a169ee..d7a11ad7313 100644 --- a/packages/experimental-utils/package.json +++ b/packages/experimental-utils/package.json @@ -1,6 +1,6 @@ { "name": "@typescript-eslint/experimental-utils", - "version": "4.31.2", + "version": "4.32.0", "description": "(Experimental) Utilities for working with TypeScript + ESLint together", "keywords": [ "eslint", @@ -40,9 +40,9 @@ }, "dependencies": { "@types/json-schema": "^7.0.7", - "@typescript-eslint/scope-manager": "4.31.2", - "@typescript-eslint/types": "4.31.2", - "@typescript-eslint/typescript-estree": "4.31.2", + "@typescript-eslint/scope-manager": "4.32.0", + "@typescript-eslint/types": "4.32.0", + "@typescript-eslint/typescript-estree": "4.32.0", "eslint-scope": "^5.1.1", "eslint-utils": "^3.0.0" }, diff --git a/packages/experimental-utils/src/ast-utils/eslint-utils/astUtilities.ts b/packages/experimental-utils/src/ast-utils/eslint-utils/astUtilities.ts index a7db43689a7..8666ba8704d 100644 --- a/packages/experimental-utils/src/ast-utils/eslint-utils/astUtilities.ts +++ b/packages/experimental-utils/src/ast-utils/eslint-utils/astUtilities.ts @@ -1,6 +1,6 @@ import * as eslintUtils from 'eslint-utils'; -import { TSESTree } from '../../ts-estree'; import * as TSESLint from '../../ts-eslint'; +import { TSESTree } from '../../ts-estree'; /** * Get the proper location of a given function node to report. @@ -101,19 +101,23 @@ const hasSideEffect = eslintUtils.hasSideEffect as ( }, ) => boolean; -/** - * Check whether a given node is parenthesized or not. - * This function detects it correctly even if it's parenthesized by specific syntax. - * - * @see {@link https://eslint-utils.mysticatea.dev/api/ast-utils.html#isparenthesized} - * @returns `true` if the node is parenthesized. - * If `times` was given, it returns `true` only if the node is parenthesized the `times` times. - * For example, `isParenthesized(2, node, sourceCode)` returns true for `((foo))`, but not for `(foo)`. - */ -const isParenthesized = eslintUtils.isParenthesized as ( - node: TSESTree.Node, - sourceCode: TSESLint.SourceCode, -) => boolean; +const isParenthesized = eslintUtils.isParenthesized as { + /** + * Check whether a given node is parenthesized or not. + * This function detects it correctly even if it's parenthesized by specific syntax. + * + * @see {@link https://eslint-utils.mysticatea.dev/api/ast-utils.html#isparenthesized} + * @returns `true` if the node is parenthesized. + * If `times` was given, it returns `true` only if the node is parenthesized the `times` times. + * For example, `isParenthesized(2, node, sourceCode)` returns true for `((foo))`, but not for `(foo)`. + */ + (node: TSESTree.Node, sourceCode: TSESLint.SourceCode): boolean; + ( + times: number, + node: TSESTree.Node, + sourceCode: TSESLint.SourceCode, + ): boolean; +}; export { getFunctionHeadLocation, diff --git a/packages/parser/CHANGELOG.md b/packages/parser/CHANGELOG.md index efb5da20489..210eae073da 100644 --- a/packages/parser/CHANGELOG.md +++ b/packages/parser/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. +# [4.32.0](https://github.com/typescript-eslint/typescript-eslint/compare/v4.31.2...v4.32.0) (2021-09-27) + + +### Features + +* Support `'latest'` as `ecmaVersion` ([#3873](https://github.com/typescript-eslint/typescript-eslint/issues/3873)) ([25a42c0](https://github.com/typescript-eslint/typescript-eslint/commit/25a42c0bbe92d1ecbc2e8ff9ef3a3ef413f728b0)) + + + + + ## [4.31.2](https://github.com/typescript-eslint/typescript-eslint/compare/v4.31.1...v4.31.2) (2021-09-20) **Note:** Version bump only for package @typescript-eslint/parser diff --git a/packages/parser/README.md b/packages/parser/README.md index d76219e1ae9..f928738ceb2 100644 --- a/packages/parser/README.md +++ b/packages/parser/README.md @@ -53,7 +53,7 @@ interface ParserOptions { jsx?: boolean; globalReturn?: boolean; }; - ecmaVersion?: number; + ecmaVersion?: number | 'latest'; jsxPragma?: string | null; jsxFragmentName?: string | null; @@ -97,12 +97,13 @@ This options allows you to tell the parser if you want to allow global `return` Default `2018`. -Accepts any valid ECMAScript version number: +Accepts any valid ECMAScript version number or `'latest'`: -- A version: es3, es5, es6, es7, es8, es9, es10, es11, ..., or -- A year: es2015, es2016, es2017, es2018, es2019, es2020, ... +- A version: es3, es5, es6, es7, es8, es9, es10, es11, es12, es13, ..., or +- A year: es2015, es2016, es2017, es2018, es2019, es2020, es2021, es2022, ..., or +- `'latest'` -The value **must** be a number - so do not include the `es` prefix. +When it's a version or a year, the value **must** be a number - so do not include the `es` prefix. Specifies the version of ECMAScript syntax you want to use. This is used by the parser to determine how to perform scope analysis, and it affects the default diff --git a/packages/parser/package.json b/packages/parser/package.json index 8a463e8cec9..f5ad76b71ea 100644 --- a/packages/parser/package.json +++ b/packages/parser/package.json @@ -1,6 +1,6 @@ { "name": "@typescript-eslint/parser", - "version": "4.31.2", + "version": "4.32.0", "description": "An ESLint custom parser which leverages TypeScript ESTree", "main": "dist/index.js", "types": "dist/index.d.ts", @@ -44,14 +44,14 @@ "eslint": "^5.0.0 || ^6.0.0 || ^7.0.0" }, "dependencies": { - "@typescript-eslint/scope-manager": "4.31.2", - "@typescript-eslint/types": "4.31.2", - "@typescript-eslint/typescript-estree": "4.31.2", + "@typescript-eslint/scope-manager": "4.32.0", + "@typescript-eslint/types": "4.32.0", + "@typescript-eslint/typescript-estree": "4.32.0", "debug": "^4.3.1" }, "devDependencies": { "@types/glob": "*", - "@typescript-eslint/experimental-utils": "4.31.2", + "@typescript-eslint/experimental-utils": "4.32.0", "glob": "*", "typescript": "*" }, diff --git a/packages/parser/src/parser.ts b/packages/parser/src/parser.ts index f304a837d8b..bbb0e3a04d7 100644 --- a/packages/parser/src/parser.ts +++ b/packages/parser/src/parser.ts @@ -102,7 +102,7 @@ function parseForESLint( jsx: validateBoolean(options.ecmaFeatures.jsx), }); const analyzeOptions: AnalyzeOptions = { - ecmaVersion: options.ecmaVersion, + ecmaVersion: options.ecmaVersion === 'latest' ? 1e8 : options.ecmaVersion, globalReturn: options.ecmaFeatures.globalReturn, jsxPragma: options.jsxPragma, jsxFragmentName: options.jsxFragmentName, diff --git a/packages/parser/tests/lib/parser.ts b/packages/parser/tests/lib/parser.ts index 41e22a911f9..0432c94252e 100644 --- a/packages/parser/tests/lib/parser.ts +++ b/packages/parser/tests/lib/parser.ts @@ -18,6 +18,11 @@ describe('parser', () => { expect(() => parseForESLint(code, null)).not.toThrow(); }); + it("parseForESLint() should work if options.ecmaVersion is `'latest'`", () => { + const code = 'const valid = true;'; + expect(() => parseForESLint(code, { ecmaVersion: 'latest' })).not.toThrow(); + }); + it('parseAndGenerateServices() should be called with options', () => { const code = 'const valid = true;'; const spy = jest.spyOn(typescriptESTree, 'parseAndGenerateServices'); diff --git a/packages/scope-manager/CHANGELOG.md b/packages/scope-manager/CHANGELOG.md index 5662feb7769..d3e5bac3b5d 100644 --- a/packages/scope-manager/CHANGELOG.md +++ b/packages/scope-manager/CHANGELOG.md @@ -3,6 +3,18 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [4.32.0](https://github.com/typescript-eslint/typescript-eslint/compare/v4.31.2...v4.32.0) (2021-09-27) + + +### Features + +* **eslint-plugin-internal:** [prefer-ast-types-enum] add `DefinitionType` enum ([#3916](https://github.com/typescript-eslint/typescript-eslint/issues/3916)) ([13b7de5](https://github.com/typescript-eslint/typescript-eslint/commit/13b7de508e0f8eac492879ff9ab99acd8d3e977e)) +* Support `'latest'` as `ecmaVersion` ([#3873](https://github.com/typescript-eslint/typescript-eslint/issues/3873)) ([25a42c0](https://github.com/typescript-eslint/typescript-eslint/commit/25a42c0bbe92d1ecbc2e8ff9ef3a3ef413f728b0)) + + + + + ## [4.31.2](https://github.com/typescript-eslint/typescript-eslint/compare/v4.31.1...v4.31.2) (2021-09-20) **Note:** Version bump only for package @typescript-eslint/scope-manager diff --git a/packages/scope-manager/README.md b/packages/scope-manager/README.md index 7671214e8d7..5e62019ba87 100644 --- a/packages/scope-manager/README.md +++ b/packages/scope-manager/README.md @@ -39,8 +39,9 @@ interface AnalyzeOptions { /** * Which ECMAScript version is considered. * Defaults to `2018`. + * `'latest'` is converted to 1e8 at parser. */ - ecmaVersion?: EcmaVersion; + ecmaVersion?: EcmaVersion | 1e8; /** * Whether the whole script is executed under node.js environment. diff --git a/packages/scope-manager/package.json b/packages/scope-manager/package.json index c83b24422aa..ad4cdea5cdf 100644 --- a/packages/scope-manager/package.json +++ b/packages/scope-manager/package.json @@ -1,6 +1,6 @@ { "name": "@typescript-eslint/scope-manager", - "version": "4.31.2", + "version": "4.32.0", "description": "TypeScript scope analyser for ESLint", "keywords": [ "eslint", @@ -39,12 +39,12 @@ "typecheck": "tsc -p tsconfig.json --noEmit" }, "dependencies": { - "@typescript-eslint/types": "4.31.2", - "@typescript-eslint/visitor-keys": "4.31.2" + "@typescript-eslint/types": "4.32.0", + "@typescript-eslint/visitor-keys": "4.32.0" }, "devDependencies": { "@types/glob": "*", - "@typescript-eslint/typescript-estree": "4.31.2", + "@typescript-eslint/typescript-estree": "4.32.0", "glob": "*", "jest-specific-snapshot": "*", "make-dir": "*", diff --git a/packages/scope-manager/src/analyze.ts b/packages/scope-manager/src/analyze.ts index 9845a3c1750..febd7a26652 100644 --- a/packages/scope-manager/src/analyze.ts +++ b/packages/scope-manager/src/analyze.ts @@ -17,8 +17,9 @@ interface AnalyzeOptions { /** * Which ECMAScript version is considered. * Defaults to `2018`. + * `'latest'` is converted to 1e8 at parser. */ - ecmaVersion?: EcmaVersion; + ecmaVersion?: EcmaVersion | 1e8; /** * Whether the whole script is executed under node.js environment. @@ -81,7 +82,11 @@ const DEFAULT_OPTIONS: Required = { emitDecoratorMetadata: false, }; -function mapEcmaVersion(version: EcmaVersion | undefined): Lib { +/** + * Convert ecmaVersion to lib. + * `'latest'` is converted to 1e8 at parser. + */ +function mapEcmaVersion(version: EcmaVersion | 1e8 | undefined): Lib { if (version == null || version === 3 || version === 5) { return 'es5'; } diff --git a/packages/scope-manager/src/definition/DefinitionType.ts b/packages/scope-manager/src/definition/DefinitionType.ts index 7f689d45ed5..5b01718ce7f 100644 --- a/packages/scope-manager/src/definition/DefinitionType.ts +++ b/packages/scope-manager/src/definition/DefinitionType.ts @@ -1,5 +1,4 @@ enum DefinitionType { - // eslint-disable-next-line @typescript-eslint/internal/prefer-ast-types-enum CatchClause = 'CatchClause', ClassName = 'ClassName', FunctionName = 'FunctionName', diff --git a/packages/scope-manager/tests/eslint-scope/map-ecma-version.test.ts b/packages/scope-manager/tests/eslint-scope/map-ecma-version.test.ts index d8646fbb353..9cf4cfab3d7 100644 --- a/packages/scope-manager/tests/eslint-scope/map-ecma-version.test.ts +++ b/packages/scope-manager/tests/eslint-scope/map-ecma-version.test.ts @@ -31,6 +31,11 @@ describe('ecma version mapping', () => { it("should map to 'es2018' when undefined", () => { expectMapping(undefined, 'es2018'); }); + + it("should map to 'esnext' when 'latest'", () => { + // `'latest'` is converted to 1e8 at parser. + expectMapping(1e8, 'esnext'); + }); }); const fakeNode = {} as unknown as TSESTree.Node; diff --git a/packages/scope-manager/tests/eslint-scope/references.test.ts b/packages/scope-manager/tests/eslint-scope/references.test.ts index 5f07dd671e9..8458fbfe657 100644 --- a/packages/scope-manager/tests/eslint-scope/references.test.ts +++ b/packages/scope-manager/tests/eslint-scope/references.test.ts @@ -643,6 +643,7 @@ describe('References:', () => { expect(constructorParamTypeRef1.isValueReference).toBe(true); const setterParamTypeRef3 = classBScope.childScopes[1].references[0]; + // eslint-disable-next-line @typescript-eslint/internal/prefer-ast-types-enum expect(setterParamTypeRef3.identifier.name).toBe('Type'); expect(setterParamTypeRef3.isTypeReference).toBe(true); expect(setterParamTypeRef3.isValueReference).toBe(false); diff --git a/packages/scope-manager/tests/fixtures.test.ts b/packages/scope-manager/tests/fixtures.test.ts index af327985df3..b504710c4cf 100644 --- a/packages/scope-manager/tests/fixtures.test.ts +++ b/packages/scope-manager/tests/fixtures.test.ts @@ -124,7 +124,7 @@ function nestDescribe( throw new Error( `Expected value for ${key} to be one of (${Array.from(type[1]).join( ' | ', - )}), but got ${value}`, + )}), but got ${value as string}`, ); } diff --git a/packages/scope-manager/tests/util/serializers/TSESTreeNode.ts b/packages/scope-manager/tests/util/serializers/TSESTreeNode.ts index 8a75e729fd8..806ad70a8b2 100644 --- a/packages/scope-manager/tests/util/serializers/TSESTreeNode.ts +++ b/packages/scope-manager/tests/util/serializers/TSESTreeNode.ts @@ -14,6 +14,7 @@ const EXCLUDED_KEYS = new Set([ const generator = createIdGenerator(); type Node = Record & { type: AST_NODE_TYPES }; +type Identifier = Node & { name: string; type: AST_NODE_TYPES.Identifier }; const SEEN_NODES = new Map(); const serializer: NewPlugin = { @@ -29,7 +30,7 @@ const serializer: NewPlugin = { }, serialize(node: Node): string { if (node.type === AST_NODE_TYPES.Identifier) { - return `Identifier<"${node.name}">`; + return `Identifier<"${(node as Identifier).name}">`; } const keys = Object.keys(node).filter(k => !EXCLUDED_KEYS.has(k)); diff --git a/packages/scope-manager/tests/util/serializers/baseSerializer.ts b/packages/scope-manager/tests/util/serializers/baseSerializer.ts index 7d571803067..a5d11b2a9f3 100644 --- a/packages/scope-manager/tests/util/serializers/baseSerializer.ts +++ b/packages/scope-manager/tests/util/serializers/baseSerializer.ts @@ -62,7 +62,7 @@ function createSerializer( } outputLines.push( - `${childIndentation}${key}: ${printer( + `${childIndentation}${key as string}: ${printer( value, config, childIndentation, diff --git a/packages/shared-fixtures/CHANGELOG.md b/packages/shared-fixtures/CHANGELOG.md index c4af0f153f0..8210405eac6 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. +# [4.32.0](https://github.com/typescript-eslint/typescript-eslint/compare/v4.31.2...v4.32.0) (2021-09-27) + +**Note:** Version bump only for package @typescript-eslint/shared-fixtures + + + + + ## [4.31.2](https://github.com/typescript-eslint/typescript-eslint/compare/v4.31.1...v4.31.2) (2021-09-20) **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 ccad5ff03a2..7f854b6450b 100644 --- a/packages/shared-fixtures/package.json +++ b/packages/shared-fixtures/package.json @@ -1,5 +1,5 @@ { "name": "@typescript-eslint/shared-fixtures", - "version": "4.31.2", + "version": "4.32.0", "private": true } diff --git a/packages/types/CHANGELOG.md b/packages/types/CHANGELOG.md index f9567e3da2a..ad7cce491e2 100644 --- a/packages/types/CHANGELOG.md +++ b/packages/types/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. +# [4.32.0](https://github.com/typescript-eslint/typescript-eslint/compare/v4.31.2...v4.32.0) (2021-09-27) + + +### Features + +* Support `'latest'` as `ecmaVersion` ([#3873](https://github.com/typescript-eslint/typescript-eslint/issues/3873)) ([25a42c0](https://github.com/typescript-eslint/typescript-eslint/commit/25a42c0bbe92d1ecbc2e8ff9ef3a3ef413f728b0)) + + + + + ## [4.31.2](https://github.com/typescript-eslint/typescript-eslint/compare/v4.31.1...v4.31.2) (2021-09-20) **Note:** Version bump only for package @typescript-eslint/types diff --git a/packages/types/package.json b/packages/types/package.json index 99ae47c7428..b91fad4c218 100644 --- a/packages/types/package.json +++ b/packages/types/package.json @@ -1,6 +1,6 @@ { "name": "@typescript-eslint/types", - "version": "4.31.2", + "version": "4.32.0", "description": "Types for the TypeScript-ESTree AST spec", "keywords": [ "eslint", diff --git a/packages/types/src/parser-options.ts b/packages/types/src/parser-options.ts index 9a761a37b97..18ecbee7943 100644 --- a/packages/types/src/parser-options.ts +++ b/packages/types/src/parser-options.ts @@ -12,12 +12,16 @@ type EcmaVersion = | 9 | 10 | 11 + | 12 + | 13 | 2015 | 2016 | 2017 | 2018 | 2019 - | 2020; + | 2020 + | 2021 + | 2022; type SourceType = 'script' | 'module'; @@ -26,7 +30,7 @@ interface ParserOptions { globalReturn?: boolean; jsx?: boolean; }; - ecmaVersion?: EcmaVersion; + ecmaVersion?: EcmaVersion | 'latest'; // scope-manager specific jsxPragma?: string | null; diff --git a/packages/typescript-estree/CHANGELOG.md b/packages/typescript-estree/CHANGELOG.md index 8c0ced40e8c..3c059a4cd53 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. +# [4.32.0](https://github.com/typescript-eslint/typescript-eslint/compare/v4.31.2...v4.32.0) (2021-09-27) + +**Note:** Version bump only for package @typescript-eslint/typescript-estree + + + + + ## [4.31.2](https://github.com/typescript-eslint/typescript-eslint/compare/v4.31.1...v4.31.2) (2021-09-20) **Note:** Version bump only for package @typescript-eslint/typescript-estree diff --git a/packages/typescript-estree/package.json b/packages/typescript-estree/package.json index 6dd84a22124..d6ab57be6f2 100644 --- a/packages/typescript-estree/package.json +++ b/packages/typescript-estree/package.json @@ -1,6 +1,6 @@ { "name": "@typescript-eslint/typescript-estree", - "version": "4.31.2", + "version": "4.32.0", "description": "A parser that converts TypeScript source code into an ESTree compatible form", "main": "dist/index.js", "types": "dist/index.d.ts", @@ -41,8 +41,8 @@ "typecheck": "tsc -p tsconfig.json --noEmit" }, "dependencies": { - "@typescript-eslint/types": "4.31.2", - "@typescript-eslint/visitor-keys": "4.31.2", + "@typescript-eslint/types": "4.32.0", + "@typescript-eslint/visitor-keys": "4.32.0", "debug": "^4.3.1", "globby": "^11.0.3", "is-glob": "^4.0.1", @@ -59,7 +59,7 @@ "@types/is-glob": "*", "@types/semver": "*", "@types/tmp": "*", - "@typescript-eslint/shared-fixtures": "4.31.2", + "@typescript-eslint/shared-fixtures": "4.32.0", "glob": "*", "jest-specific-snapshot": "*", "make-dir": "*", diff --git a/packages/typescript-estree/tests/ast-alignment/fixtures-to-test.ts b/packages/typescript-estree/tests/ast-alignment/fixtures-to-test.ts index cab81a426fe..a3400b97d33 100644 --- a/packages/typescript-estree/tests/ast-alignment/fixtures-to-test.ts +++ b/packages/typescript-estree/tests/ast-alignment/fixtures-to-test.ts @@ -386,6 +386,14 @@ tester.addFixturePatternConfig('typescript/basics', { * This is intentional; babel is not checking types */ 'catch-clause-with-invalid-annotation', + /** + * [TS-ESTREE ERRORED, BUT BABEL DID NOT] + * TypeScript 4.4 new feature + * @see https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-4.html#abstract-properties-do-not-allow-initializers + */ + 'abstract-class-with-abstract-readonly-property', + 'abstract-class-with-abstract-properties', + 'abstract-class-with-override-property', ], ignoreSourceType: [ /** diff --git a/packages/typescript-estree/tests/ast-alignment/utils.ts b/packages/typescript-estree/tests/ast-alignment/utils.ts index 7427c1b1831..3cecac3f09f 100644 --- a/packages/typescript-estree/tests/ast-alignment/utils.ts +++ b/packages/typescript-estree/tests/ast-alignment/utils.ts @@ -250,16 +250,6 @@ export function preprocessBabylonAST(ast: BabelTypes.File): any { } } }, - /** - * Babel adds a `static` property to the StaticBlock when the - * `typescript` plugin and the `classStaticBlock` plugin are enabled. - * @see https://github.com/babel/babel/issues/13674 - */ - StaticBlock(node: any) { - if (node.static != null) { - delete node.static; - } - }, }, ); } diff --git a/packages/visitor-keys/CHANGELOG.md b/packages/visitor-keys/CHANGELOG.md index ab8eb606e43..d5b55170843 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. +# [4.32.0](https://github.com/typescript-eslint/typescript-eslint/compare/v4.31.2...v4.32.0) (2021-09-27) + +**Note:** Version bump only for package @typescript-eslint/visitor-keys + + + + + ## [4.31.2](https://github.com/typescript-eslint/typescript-eslint/compare/v4.31.1...v4.31.2) (2021-09-20) **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 6b99e6cc612..155fd9be2a4 100644 --- a/packages/visitor-keys/package.json +++ b/packages/visitor-keys/package.json @@ -1,6 +1,6 @@ { "name": "@typescript-eslint/visitor-keys", - "version": "4.31.2", + "version": "4.32.0", "description": "Visitor keys used to help traverse the TypeScript-ESTree AST", "keywords": [ "eslint", @@ -38,7 +38,7 @@ "typecheck": "tsc -p tsconfig.json --noEmit" }, "dependencies": { - "@typescript-eslint/types": "4.31.2", + "@typescript-eslint/types": "4.32.0", "eslint-visitor-keys": "^2.0.0" }, "devDependencies": { diff --git a/yarn.lock b/yarn.lock index b999c1b3b09..8483f61f60a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -169,10 +169,10 @@ chalk "^2.0.0" js-tokens "^4.0.0" -"@babel/parser@*", "@babel/parser@^7.14.6": - version "7.14.6" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.14.6.tgz#d85cc68ca3cac84eae384c06f032921f5227f4b2" - integrity sha512-oG0ej7efjEXxb4UgE+klVx+3j4MVo+A2vCzm7OUN4CLo6WhQ+vSOD2yJ8m7B+DghObxtLxt3EfgMWpq+AsWehQ== +"@babel/parser@*", "@babel/parser@^7.15.6": + version "7.15.6" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.15.6.tgz#043b9aa3c303c0722e5377fef9197f4cf1796549" + integrity sha512-S/TSCcsRuCkmpUuoWijua0Snt+f3ewU/8spLo+4AXJCZfT0bVCzLD5MuOKdrx0mlAptbKzn5AdgEIIKXxXkz9Q== "@babel/parser@^7.1.0", "@babel/parser@^7.12.13", "@babel/parser@^7.14.2", "@babel/parser@^7.14.3", "@babel/parser@^7.7.2": version "7.14.4" @@ -461,10 +461,10 @@ dependencies: chalk "^4.0.0" -"@cspell/cspell-bundled-dicts@^5.9.0": - version "5.9.0" - resolved "https://registry.yarnpkg.com/@cspell/cspell-bundled-dicts/-/cspell-bundled-dicts-5.9.0.tgz#4afef125ddedf13d43bb4114fdfcc3b42450e91e" - integrity sha512-qI/MVTYjGh0Uhhx2YiqCIodfazHojcwJx6yzNkQQXZN7px0rGUPsRPiPx83LuHl1aE+APc5x8cblCwnnZUbPxg== +"@cspell/cspell-bundled-dicts@^5.10.1": + version "5.10.1" + resolved "https://registry.yarnpkg.com/@cspell/cspell-bundled-dicts/-/cspell-bundled-dicts-5.10.1.tgz#31108cf2ef630d28601113191bc00a5278650900" + integrity sha512-4NXeyTMXsl0bV6tIG7N6LAeATkBIGCjQEuh9fNjGduOYCXn3HgTSNgOSdgdlLnnLt2zwvoFtwHDU1vXCDN8IrQ== dependencies: "@cspell/dict-ada" "^1.1.2" "@cspell/dict-aws" "^1.0.14" @@ -475,10 +475,10 @@ "@cspell/dict-csharp" "^1.0.11" "@cspell/dict-css" "^1.0.12" "@cspell/dict-django" "^1.0.26" - "@cspell/dict-dotnet" "^1.0.30" + "@cspell/dict-dotnet" "^1.0.31" "@cspell/dict-elixir" "^1.0.25" "@cspell/dict-en-gb" "^1.1.33" - "@cspell/dict-en_us" "^2.0.2" + "@cspell/dict-en_us" "^2.1.1" "@cspell/dict-filetypes" "^1.1.8" "@cspell/dict-fonts" "^1.0.14" "@cspell/dict-fullstack" "^1.0.38" @@ -499,13 +499,13 @@ "@cspell/dict-ruby" "^1.0.14" "@cspell/dict-rust" "^1.0.23" "@cspell/dict-scala" "^1.0.21" - "@cspell/dict-software-terms" "^1.0.41" + "@cspell/dict-software-terms" "^1.0.42" "@cspell/dict-typescript" "^1.0.19" -"@cspell/cspell-types@^5.9.0": - version "5.9.0" - resolved "https://registry.yarnpkg.com/@cspell/cspell-types/-/cspell-types-5.9.0.tgz#1d74c2cb191f9dc7d899364a3ac366d00df181d8" - integrity sha512-S3O/4CNTTljQmWZpbBrG8IHPg9zWQ5rYpQ0tc9zoM1q/RzZev8xc55rggRu3IqtkwzyZUjVFo8apwQF5UZHXMg== +"@cspell/cspell-types@^5.10.0": + version "5.10.0" + resolved "https://registry.yarnpkg.com/@cspell/cspell-types/-/cspell-types-5.10.0.tgz#edf94262b763be67ca5e0b870930604bcc1de413" + integrity sha512-jssGvbGGfAKwrCetyBuFHrSC/8OIYF4fNXLkUQDiftHj/V5YOpAuRE57EzH2nGLkQ1pGGD5fjvLuYYDU1ZcioQ== "@cspell/dict-ada@^1.1.2": version "1.1.2" @@ -552,10 +552,10 @@ resolved "https://registry.yarnpkg.com/@cspell/dict-django/-/dict-django-1.0.26.tgz#b97ce0112fbe8c3c3ada0387c68971b5e27483ab" integrity sha512-mn9bd7Et1L2zuibc08GVHTiD2Go3/hdjyX5KLukXDklBkq06r+tb0OtKtf1zKodtFDTIaYekGADhNhA6AnKLkg== -"@cspell/dict-dotnet@^1.0.30": - version "1.0.30" - resolved "https://registry.yarnpkg.com/@cspell/dict-dotnet/-/dict-dotnet-1.0.30.tgz#0e80294fe2894b65d059130115a54c33adcb76f8" - integrity sha512-86kC5191GACB95IGtLnmYHZjuNl/Ee7lvZRcwEyvktoYiRAryd1YKSX+c/qU1OEx7Y52FTaEl07tf9uYS1wKNQ== +"@cspell/dict-dotnet@^1.0.31": + version "1.0.31" + resolved "https://registry.yarnpkg.com/@cspell/dict-dotnet/-/dict-dotnet-1.0.31.tgz#31d2f2602ddd6be038e00148860162d2b44d56e0" + integrity sha512-65yZTMcEdYkNx9sNs18OxcE0zfbZ5VsAZ0KgDvl/1YCkTomxr9vmtnrzFz4+vxfjV4eSuaL1SPRMZODaM7SSTg== "@cspell/dict-elixir@^1.0.25": version "1.0.25" @@ -567,10 +567,10 @@ resolved "https://registry.yarnpkg.com/@cspell/dict-en-gb/-/dict-en-gb-1.1.33.tgz#7f1fd90fc364a5cb77111b5438fc9fcf9cc6da0e" integrity sha512-tKSSUf9BJEV+GJQAYGw5e+ouhEe2ZXE620S7BLKe3ZmpnjlNG9JqlnaBhkIMxKnNFkLY2BP/EARzw31AZnOv4g== -"@cspell/dict-en_us@^2.0.2": - version "2.0.2" - resolved "https://registry.yarnpkg.com/@cspell/dict-en_us/-/dict-en_us-2.0.2.tgz#9087b99ef9efa9e77d1b2546feb454e4067cbaac" - integrity sha512-g6TL4ynWHoxVKvQ0kdiMCbh4+FeXwmHFTL/dWgQbyfy6cqKXjsOqPK0OPVFIbqI5rV8QeBx5IH6ny/q/XQOvXQ== +"@cspell/dict-en_us@^2.1.1": + version "2.1.1" + resolved "https://registry.yarnpkg.com/@cspell/dict-en_us/-/dict-en_us-2.1.1.tgz#3db0fec45a821ad66747e42d303d2448d37a158e" + integrity sha512-7kHOqve9DVFsb1e/wKME3CZhj48zOqvXNaA1Cd82ZkaHf3aL7pUBx3cxI7Xopj/dcK1ZkhUKh+2nBxPIWIibNg== "@cspell/dict-filetypes@^1.1.8": version "1.1.8" @@ -672,10 +672,10 @@ resolved "https://registry.yarnpkg.com/@cspell/dict-scala/-/dict-scala-1.0.21.tgz#bfda392329061e2352fbcd33d228617742c93831" integrity sha512-5V/R7PRbbminTpPS3ywgdAalI9BHzcEjEj9ug4kWYvBIGwSnS7T6QCFCiu+e9LvEGUqQC+NHgLY4zs1NaBj2vA== -"@cspell/dict-software-terms@^1.0.41": - version "1.0.41" - resolved "https://registry.yarnpkg.com/@cspell/dict-software-terms/-/dict-software-terms-1.0.41.tgz#c8b9ca8e8891e09c2e55afd889bde38f6d7b109a" - integrity sha512-/RWiv99XoDUYh3eCo5PyF2nwDh0U8kuKmSW+UXpzbT4sj7oBl/la19h6Ahgq0Qmr0JGjTF/RxbQkz85Hcp1t5w== +"@cspell/dict-software-terms@^1.0.42": + version "1.0.42" + resolved "https://registry.yarnpkg.com/@cspell/dict-software-terms/-/dict-software-terms-1.0.42.tgz#748b7d4b33182b2fbf51924f3242e3b9c03affb4" + integrity sha512-VRIq7b6NnWVHeO0pzpHT10btQNYcRCyiSZc162xGlyO8+IMXq9Noemyqv+POS9oRknhtlF0rL1Hrg4ypHP3B+w== "@cspell/dict-typescript@^1.0.19": version "1.0.19" @@ -823,15 +823,15 @@ jest-util "^27.2.0" slash "^3.0.0" -"@jest/core@^27.2.0": - version "27.2.0" - resolved "https://registry.yarnpkg.com/@jest/core/-/core-27.2.0.tgz#61fc27b244e9709170ed9ffe41b006add569f1b3" - integrity sha512-E/2NHhq+VMo18DpKkoty8Sjey8Kps5Cqa88A8NP757s6JjYqPdioMuyUBhDiIOGCdQByEp0ou3jskkTszMS0nw== +"@jest/core@^27.2.1": + version "27.2.1" + resolved "https://registry.yarnpkg.com/@jest/core/-/core-27.2.1.tgz#93dc50e2aaba2c944e5765cf658dcd98d804c970" + integrity sha512-XcGt9UgPyzylThvezwUIMCNVp8xxN78Ic3WwhJZehZt4n2hPHR6Bd85A1nKFZBeqW58Vd+Cx/LaN6YL4n58KlA== dependencies: "@jest/console" "^27.2.0" - "@jest/reporters" "^27.2.0" + "@jest/reporters" "^27.2.1" "@jest/test-result" "^27.2.0" - "@jest/transform" "^27.2.0" + "@jest/transform" "^27.2.1" "@jest/types" "^27.1.1" "@types/node" "*" ansi-escapes "^4.2.1" @@ -840,15 +840,15 @@ exit "^0.1.2" graceful-fs "^4.2.4" jest-changed-files "^27.1.1" - jest-config "^27.2.0" + jest-config "^27.2.1" jest-haste-map "^27.2.0" jest-message-util "^27.2.0" jest-regex-util "^27.0.6" jest-resolve "^27.2.0" - jest-resolve-dependencies "^27.2.0" - jest-runner "^27.2.0" - jest-runtime "^27.2.0" - jest-snapshot "^27.2.0" + jest-resolve-dependencies "^27.2.1" + jest-runner "^27.2.1" + jest-runtime "^27.2.1" + jest-snapshot "^27.2.1" jest-util "^27.2.0" jest-validate "^27.2.0" jest-watcher "^27.2.0" @@ -911,14 +911,14 @@ "@jest/types" "^27.0.6" expect "^27.0.6" -"@jest/globals@^27.2.0": - version "27.2.0" - resolved "https://registry.yarnpkg.com/@jest/globals/-/globals-27.2.0.tgz#4d7085f51df5ac70c8240eb3501289676503933d" - integrity sha512-raqk9Gf9WC3hlBa57rmRmJfRl9hom2b+qEE/ifheMtwn5USH5VZxzrHHOZg0Zsd/qC2WJ8UtyTwHKQAnNlDMdg== +"@jest/globals@^27.2.1": + version "27.2.1" + resolved "https://registry.yarnpkg.com/@jest/globals/-/globals-27.2.1.tgz#6842c70b6713fbe2fcaf89eac20d77eeeb0e282c" + integrity sha512-4P46Zr4cckSitsWtOMRvgMMn7mOKbBsQdYxHeGSIG3kpI4gNR2vk51balPulZHnBQCQb/XBptprtoSv1REfaew== dependencies: "@jest/environment" "^27.2.0" "@jest/types" "^27.1.1" - expect "^27.2.0" + expect "^27.2.1" "@jest/reporters@27.0.6": version "27.0.6" @@ -950,15 +950,15 @@ terminal-link "^2.0.0" v8-to-istanbul "^8.0.0" -"@jest/reporters@^27.2.0": - version "27.2.0" - resolved "https://registry.yarnpkg.com/@jest/reporters/-/reporters-27.2.0.tgz#629886d9a42218e504a424889a293abb27919e25" - integrity sha512-7wfkE3iRTLaT0F51h1mnxH3nQVwDCdbfgXiLuCcNkF1FnxXLH9utHqkSLIiwOTV1AtmiE0YagHbOvx4rnMP/GA== +"@jest/reporters@^27.2.1": + version "27.2.1" + resolved "https://registry.yarnpkg.com/@jest/reporters/-/reporters-27.2.1.tgz#2e43361b962e26975d40eafd7b4f14c70b4fe9a0" + integrity sha512-ILqR+bIIBlhaHjDtQR/0Z20YkKAQVM+NVRuJLaWFCoRx/rKQQSxG01ZLiLV0MsA6wkBHf6J9fzFuXp0k5l7epw== dependencies: "@bcoe/v8-coverage" "^0.2.3" "@jest/console" "^27.2.0" "@jest/test-result" "^27.2.0" - "@jest/transform" "^27.2.0" + "@jest/transform" "^27.2.1" "@jest/types" "^27.1.1" chalk "^4.0.0" collect-v8-coverage "^1.0.0" @@ -1019,15 +1019,15 @@ jest-haste-map "^27.0.6" jest-runtime "^27.0.6" -"@jest/test-sequencer@^27.2.0": - version "27.2.0" - resolved "https://registry.yarnpkg.com/@jest/test-sequencer/-/test-sequencer-27.2.0.tgz#b02b507687825af2fdc84e90c539d36fd8cf7bc9" - integrity sha512-PrqarcpzOU1KSAK7aPwfL8nnpaqTMwPe7JBPnaOYRDSe/C6AoJiL5Kbnonqf1+DregxZIRAoDg69R9/DXMGqXA== +"@jest/test-sequencer@^27.2.1": + version "27.2.1" + resolved "https://registry.yarnpkg.com/@jest/test-sequencer/-/test-sequencer-27.2.1.tgz#1682cd3a16198fa358ff9565b0d2792919f36562" + integrity sha512-fWcEgWQXgvU4DFY5YHfQsGwqfJWyuCUzdOzLZTYtyLB3WK1mFPQGYAszM7mCEZjyVon5XRuCa+2/+hif/uMucQ== dependencies: "@jest/test-result" "^27.2.0" graceful-fs "^4.2.4" jest-haste-map "^27.2.0" - jest-runtime "^27.2.0" + jest-runtime "^27.2.1" "@jest/transform@^27.0.2": version "27.0.2" @@ -1071,10 +1071,10 @@ source-map "^0.6.1" write-file-atomic "^3.0.0" -"@jest/transform@^27.2.0": - version "27.2.0" - resolved "https://registry.yarnpkg.com/@jest/transform/-/transform-27.2.0.tgz#e7e6e49d2591792db2385c33cdbb4379d407068d" - integrity sha512-Q8Q/8xXIZYllk1AF7Ou5sV3egOZsdY/Wlv09CSbcexBRcC1Qt6lVZ7jRFAZtbHsEEzvOCyFEC4PcrwKwyjXtCg== +"@jest/transform@^27.2.1": + version "27.2.1" + resolved "https://registry.yarnpkg.com/@jest/transform/-/transform-27.2.1.tgz#743443adb84b3b7419951fc702515ce20ba6285e" + integrity sha512-xmB5vh81KK8DiiCMtI5vI59mP+GggNmc9BiN+fg4mKdQHV369+WuZc1Lq2xWFCOCsRPHt24D9h7Idp4YaMB1Ww== dependencies: "@babel/core" "^7.1.0" "@jest/types" "^27.1.1" @@ -1092,29 +1092,7 @@ source-map "^0.6.1" write-file-atomic "^3.0.0" -"@jest/types@^27.0.2": - version "27.0.2" - resolved "https://registry.yarnpkg.com/@jest/types/-/types-27.0.2.tgz#e153d6c46bda0f2589f0702b071f9898c7bbd37e" - integrity sha512-XpjCtJ/99HB4PmyJ2vgmN7vT+JLP7RW1FBT9RgnMFS4Dt7cvIyBee8O3/j98aUZ34ZpenPZFqmaaObWSeL65dg== - dependencies: - "@types/istanbul-lib-coverage" "^2.0.0" - "@types/istanbul-reports" "^3.0.0" - "@types/node" "*" - "@types/yargs" "^16.0.0" - chalk "^4.0.0" - -"@jest/types@^27.0.6": - version "27.0.6" - resolved "https://registry.yarnpkg.com/@jest/types/-/types-27.0.6.tgz#9a992bc517e0c49f035938b8549719c2de40706b" - integrity sha512-aSquT1qa9Pik26JK5/3rvnYb4bGtm1VFNesHKmNTwmPIgOrixvhL2ghIvFRNEpzy3gU+rUgjIF/KodbkFAl++g== - dependencies: - "@types/istanbul-lib-coverage" "^2.0.0" - "@types/istanbul-reports" "^3.0.0" - "@types/node" "*" - "@types/yargs" "^16.0.0" - chalk "^4.0.0" - -"@jest/types@^27.1.1": +"@jest/types@^27.0.2", "@jest/types@^27.0.6", "@jest/types@^27.1.1": version "27.1.1" resolved "https://registry.yarnpkg.com/@jest/types/-/types-27.1.1.tgz#77a3fc014f906c65752d12123a0134359707c0ad" integrity sha512-yqJPDDseb0mXgKqmNqypCsb85C22K1aY5+LUxh7syIM9n/b0AsaltxNy+o6tt29VcfGDpYEve175bm3uOhcehA== @@ -1810,24 +1788,24 @@ npmlog "^4.1.2" write-file-atomic "^2.3.0" -"@microsoft/api-extractor-model@7.13.5": - version "7.13.5" - resolved "https://registry.yarnpkg.com/@microsoft/api-extractor-model/-/api-extractor-model-7.13.5.tgz#7836a81ba47b9a654062ed0361e4eee69afae51e" - integrity sha512-il6AebNltYo5hEtqXZw4DMvrwBPn6+F58TxwqmsLY+U+sSJNxaYn2jYksArrjErXVPR3gUgRMqD6zsdIkg+WEQ== +"@microsoft/api-extractor-model@7.13.7": + version "7.13.7" + resolved "https://registry.yarnpkg.com/@microsoft/api-extractor-model/-/api-extractor-model-7.13.7.tgz#2ae0948cb7458b336694c458675717ef8a9dcc85" + integrity sha512-emwhcaSF/h3WdqBWps4UU0RtGOGzy53IsplxuoLwtCuMAx3namYvJSfUGa5ajGPBao4MCyRYGsMc3EZ6IdR8cQ== dependencies: "@microsoft/tsdoc" "0.13.2" "@microsoft/tsdoc-config" "~0.15.2" - "@rushstack/node-core-library" "3.40.0" + "@rushstack/node-core-library" "3.40.2" "@microsoft/api-extractor@^7.15.2": - version "7.18.7" - resolved "https://registry.yarnpkg.com/@microsoft/api-extractor/-/api-extractor-7.18.7.tgz#851d2413a3c5d696f7cc914eb59de7a7882b2e8b" - integrity sha512-JhtV8LoyLuIecbgCPyZQg08G1kngIRWpai2UzwNil9mGVGYiDZVeeKx8c2phmlPcogmMDm4oQROxyuiYt5sJiw== + version "7.18.9" + resolved "https://registry.yarnpkg.com/@microsoft/api-extractor/-/api-extractor-7.18.9.tgz#82f50f8791bfacd5e3dd5d9400cdb6d69a499249" + integrity sha512-N+fbG+6SwA1i6EW3iGRp/nAT8vQpRSDvZ1DzBUr8xIS7tNfJ0C75ndPPziUT8EmalhLixRnIw6Ncmur8AFELRg== dependencies: - "@microsoft/api-extractor-model" "7.13.5" + "@microsoft/api-extractor-model" "7.13.7" "@microsoft/tsdoc" "0.13.2" "@microsoft/tsdoc-config" "~0.15.2" - "@rushstack/node-core-library" "3.40.0" + "@rushstack/node-core-library" "3.40.2" "@rushstack/rig-package" "0.3.0" "@rushstack/ts-command-line" "4.9.0" colors "~1.2.1" @@ -2101,10 +2079,10 @@ dependencies: "@types/node" ">= 8" -"@rushstack/node-core-library@3.40.0": - version "3.40.0" - resolved "https://registry.yarnpkg.com/@rushstack/node-core-library/-/node-core-library-3.40.0.tgz#2551915ea34e34ec2abb7172b9d7f4546144d9d4" - integrity sha512-P6uMPI7cqTdawLSPAG5BQrBu1MHlGRPqecp7ruIRgyukIEzkmh0QAnje4jAL/l1r3hw0qe4e+Dz5ZSnukT/Egg== +"@rushstack/node-core-library@3.40.2": + version "3.40.2" + resolved "https://registry.yarnpkg.com/@rushstack/node-core-library/-/node-core-library-3.40.2.tgz#71d92180f14bafd212f720b2cfe8892e688159b6" + integrity sha512-wzcRucwnhOENTfx6hZ2M+CA1Zmp8Dr572mFFtjxmcQzBWTbNFRB1Mi1wLb7DLza+69OUBoSZcHUqydlwL+gvSA== dependencies: "@types/node" "10.17.13" colors "~1.2.1" @@ -2298,14 +2276,14 @@ integrity sha1-7ihweulOEdK4J7y+UnC86n8+ce4= "@types/lodash@*", "@types/lodash@^4.14.170": - version "4.14.172" - resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.172.tgz#aad774c28e7bfd7a67de25408e03ee5a8c3d028a" - integrity sha512-/BHF5HAx3em7/KkzVKm3LrsD6HZAXuXO1AJZQ3cRRBZj4oHZDviWPYu0aEplAqDFNHZPW6d3G7KN+ONcCCC7pw== + version "4.14.173" + resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.173.tgz#9d3b674c67a26cf673756f6aca7b429f237f91ed" + integrity sha512-vv0CAYoaEjCw/mLy96GBTnRoZrSxkGE0BKzKimdR8P3OzrNYNvBgtW7p055A+E8C31vXNUhWKoFCbhq7gbyhFg== "@types/marked@*", "@types/marked@^2.0.3": - version "2.0.4" - resolved "https://registry.yarnpkg.com/@types/marked/-/marked-2.0.4.tgz#34a0ea548afe6e0c01095229d47b48b2af650613" - integrity sha512-L9VRSe0Id8xbPL99mUo/4aKgD7ZoRwFZqUQScNKHi2pFjF9ZYSMNShUHD6VlMT6J/prQq0T1mxuU25m3R7dFzg== + version "2.0.5" + resolved "https://registry.yarnpkg.com/@types/marked/-/marked-2.0.5.tgz#453e27f1e97199d45bb25297b0dd2b9bbc1e05ea" + integrity sha512-shRZ7XnYFD/8n8zSjKvFdto1QNSf4tONZIlNEZGrJe8GsOE8DL/hG1Hbl8gZlfLnjS7+f5tZGIaTgfpyW38h4w== "@types/minimatch@*": version "3.0.4" @@ -2322,13 +2300,12 @@ resolved "https://registry.yarnpkg.com/@types/ms/-/ms-0.7.31.tgz#31b7ca6407128a3d2bbc27fe2d21b345397f6197" integrity sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA== -"@types/node-fetch@^2.5.10": - version "2.5.12" - resolved "https://registry.yarnpkg.com/@types/node-fetch/-/node-fetch-2.5.12.tgz#8a6f779b1d4e60b7a57fb6fd48d84fb545b9cc66" - integrity sha512-MKgC4dlq4kKNa/mYrwpKfzQMB5X3ee5U6fSprkKpToBqBmX4nFZL9cW5jl6sWn+xpRJ7ypWh2yyqqr8UUCstSw== +"@types/node-fetch@^3.0.3": + version "3.0.3" + resolved "https://registry.yarnpkg.com/@types/node-fetch/-/node-fetch-3.0.3.tgz#9d969c9a748e841554a40ee435d26e53fa3ee899" + integrity sha512-HhggYPH5N+AQe/OmN6fmhKmRRt2XuNJow+R3pQwJxOOF9GuwM7O2mheyGeIrs5MOIeNjDEdgdoyHBOrFeJBR3g== dependencies: - "@types/node" "*" - form-data "^3.0.0" + node-fetch "*" "@types/node@*", "@types/node@10.17.13", "@types/node@>= 8", "@types/node@^15.6.1": version "15.12.2" @@ -2800,12 +2777,12 @@ babel-jest@^27.0.6: graceful-fs "^4.2.4" slash "^3.0.0" -babel-jest@^27.2.0: - version "27.2.0" - resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-27.2.0.tgz#c0f129a81f1197028aeb4447acbc04564c8bfc52" - integrity sha512-bS2p+KGGVVmWXBa8+i6SO/xzpiz2Q/2LnqLbQknPKefWXVZ67YIjA4iXup/jMOEZplga9PpWn+wrdb3UdDwRaA== +babel-jest@^27.2.1: + version "27.2.1" + resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-27.2.1.tgz#48edfa5cf8d59ab293da94321a369ccc7b67a4b1" + integrity sha512-kkaekSJHew1zfDW3cA2QiSBPg4uiLpiW0OwJKqFv0r2/mFgym/IBn7hxPntL6FvS66G/ROh+lz4pRiCJAH1/UQ== dependencies: - "@jest/transform" "^27.2.0" + "@jest/transform" "^27.2.1" "@jest/types" "^27.1.1" "@types/babel__core" "^7.1.14" babel-plugin-istanbul "^6.0.0" @@ -3392,10 +3369,10 @@ commander@^7.2.0: resolved "https://registry.yarnpkg.com/commander/-/commander-7.2.0.tgz#a36cb57d0b501ce108e4d20559a150a391d97ab7" integrity sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw== -commander@^8.1.0: - version "8.1.0" - resolved "https://registry.yarnpkg.com/commander/-/commander-8.1.0.tgz#db36e3e66edf24ff591d639862c6ab2c52664362" - integrity sha512-mf45ldcuHSYShkplHHGKWb4TrmwQadxOn7v4WuhDJy0ZVoY5JFajaRDKD0PNe5qXzBX0rhovjTnP6Kz9LETcuA== +commander@^8.2.0: + version "8.2.0" + resolved "https://registry.yarnpkg.com/commander/-/commander-8.2.0.tgz#37fe2bde301d87d47a53adeff8b5915db1381ca8" + integrity sha512-LLKxDvHeL91/8MIyTAD5BFMNtoIwztGPMiM/7Bl8rIPmHCZXRxmSWr91h57dpOpnQ6jIUqEWdXE/uBYMfiVZDA== commander@~8.0.0: version "8.0.0" @@ -3694,35 +3671,32 @@ crypto-random-string@^2.0.0: resolved "https://registry.yarnpkg.com/crypto-random-string/-/crypto-random-string-2.0.0.tgz#ef2a7a966ec11083388369baa02ebead229b30d5" integrity sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA== -cspell-glob@^5.9.0: - version "5.9.0" - resolved "https://registry.yarnpkg.com/cspell-glob/-/cspell-glob-5.9.0.tgz#ecb493cd3e12ea9cbefe4aca1cb9e86638825288" - integrity sha512-4yhDg/oJpujKNOIX6EBmeb935vyBVXgd0SVb7AR183En9lTUPkT7PR4lTYKxolNs3/z4Ajx+xwA8DORW7E5Rtw== +cspell-glob@^5.10.0: + version "5.10.0" + resolved "https://registry.yarnpkg.com/cspell-glob/-/cspell-glob-5.10.0.tgz#04c1ed153fedc2b9bfaafbef4efb4865fbd65893" + integrity sha512-aMt4OxvrdP1QM7rhsOvmkmdKmMY1oq11iHwEf/e/XCezmkab61QJaSM+oGk2Io+xKjdJrJVKOnkikxfQtyP6vw== dependencies: micromatch "^4.0.4" -cspell-io@^5.9.0: - version "5.9.0" - resolved "https://registry.yarnpkg.com/cspell-io/-/cspell-io-5.9.0.tgz#f74867e43823965ddd3018920b1dddf71fe27d60" - integrity sha512-T+JO9RZrgW9StS6pg2yVQfNpR503lCzPCLM/24lBykPChaXOk2VTGiBa5TPu7qKRxP9x9p7zHLiawlTkgfIjzQ== - dependencies: - iconv-lite "^0.6.3" - iterable-to-stream "^2.0.0" +cspell-io@^5.10.0: + version "5.10.0" + resolved "https://registry.yarnpkg.com/cspell-io/-/cspell-io-5.10.0.tgz#5bfe04d5c924aa808d5129034e572b587ada90ef" + integrity sha512-vOJ44cGueqd6GWCmJSAeZ/GbmgJiZdGcvS0mkDhBW3CS5+L8ZH3NItSiH70H/zZUAPCelkyqoJP2zj0MxSVqXA== -cspell-lib@^5.9.0: - version "5.9.0" - resolved "https://registry.yarnpkg.com/cspell-lib/-/cspell-lib-5.9.0.tgz#2efec17a98ac4b7e2da294fac747f236a820a125" - integrity sha512-86SsD7lOAu9ia5j2o7tBUIUrTrAjwEjMgP96+bE8NdSCArjvnY7FiTkes7AHGZ9g3KhluMEaDKhzJhK0TaZenQ== +cspell-lib@^5.10.1: + version "5.10.1" + resolved "https://registry.yarnpkg.com/cspell-lib/-/cspell-lib-5.10.1.tgz#e91ac9caa4101c62634b6be149041e1f41c0bf60" + integrity sha512-Oaa+jP90dP1ipeRqoYIGCkgiVg4O4ZzGQr9qGHY1QMu62aknIURo2tzkH6HHtofRRodazGxW0VYl9XAscvOLAA== dependencies: - "@cspell/cspell-bundled-dicts" "^5.9.0" - "@cspell/cspell-types" "^5.9.0" + "@cspell/cspell-bundled-dicts" "^5.10.1" + "@cspell/cspell-types" "^5.10.0" clear-module "^4.1.1" comment-json "^4.1.1" configstore "^5.0.1" cosmiconfig "^7.0.1" - cspell-glob "^5.9.0" - cspell-io "^5.9.0" - cspell-trie-lib "^5.9.0" + cspell-glob "^5.10.0" + cspell-io "^5.10.0" + cspell-trie-lib "^5.10.1" find-up "^5.0.0" fs-extra "^10.0.0" gensequence "^3.1.1" @@ -3731,24 +3705,24 @@ cspell-lib@^5.9.0: resolve-global "^1.0.0" vscode-uri "^3.0.2" -cspell-trie-lib@^5.9.0: - version "5.9.0" - resolved "https://registry.yarnpkg.com/cspell-trie-lib/-/cspell-trie-lib-5.9.0.tgz#ca857a7468fa443bf6a9de4143849e770ca70a48" - integrity sha512-/m0kgxYuLyxeZGjajVC/oxrbi2zpv+1boKSjHBElPrE8MytDgdBgdCojsYAYNAl30QEF4GtxB+q0NlWV4laLdA== +cspell-trie-lib@^5.10.1: + version "5.10.1" + resolved "https://registry.yarnpkg.com/cspell-trie-lib/-/cspell-trie-lib-5.10.1.tgz#5c083e108bc054cb40093698cf61235bc1097188" + integrity sha512-pDlMM4aNBA8pwc6aZTtClr//e2kwyl7bLBRJ8aG608EICzHphfH8Hl0qopnFWCGvr3h52slYyOVuQ/frAcC4dg== dependencies: fs-extra "^10.0.0" gensequence "^3.1.1" cspell@^5.5.2: - version "5.9.0" - resolved "https://registry.yarnpkg.com/cspell/-/cspell-5.9.0.tgz#2db3c85a9b0bf68bb4d49b0f72e35325a68170c3" - integrity sha512-TrPg5fmdd09S+alS8HjRvYPFBd8Qoxb8XxWGrH3JDsQGA7m6EljGcNjR6Mh19mMP5cQVOv7XmwEMy/EqwaHWTA== + version "5.10.1" + resolved "https://registry.yarnpkg.com/cspell/-/cspell-5.10.1.tgz#dfbada1536db121342a4606d9a027e3839844be4" + integrity sha512-jTj8gErwM+B0VnB2YULQ2ABHEc4Ch2udSnFoVRBGWRYKVqXYuRdqpX58j/UA9ByeDqXhx7Hoqg/1Q6vsHAJdZQ== dependencies: chalk "^4.1.2" - commander "^8.1.0" + commander "^8.2.0" comment-json "^4.1.1" - cspell-glob "^5.9.0" - cspell-lib "^5.9.0" + cspell-glob "^5.10.0" + cspell-lib "^5.10.1" fs-extra "^10.0.0" get-stdin "^8.0.0" glob "^7.1.7" @@ -3831,6 +3805,11 @@ dashdash@^1.12.0: dependencies: assert-plus "^1.0.0" +data-uri-to-buffer@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/data-uri-to-buffer/-/data-uri-to-buffer-3.0.1.tgz#594b8973938c5bc2c33046535785341abc4f3636" + integrity sha512-WboRycPNsVw3B3TL559F7kuBUM4d8CgMEvk6xEJlOp7OBPjt6G7z8WMWlD2rOFZLk6OYfFIUGsCOWzcQH9K2og== + data-urls@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/data-urls/-/data-urls-2.0.0.tgz#156485a72963a970f5d5821aaf642bef2bf2db9b" @@ -4304,9 +4283,9 @@ eslint-plugin-import@^2.23.4: tsconfig-paths "^3.11.0" eslint-plugin-jest@^24.3.6: - version "24.4.0" - resolved "https://registry.yarnpkg.com/eslint-plugin-jest/-/eslint-plugin-jest-24.4.0.tgz#fa4b614dbd46a98b652d830377971f097bda9262" - integrity sha512-8qnt/hgtZ94E9dA6viqfViKBfkJwFHXgJmTWlMGDgunw1XJEGqm3eiPjDsTanM3/u/3Az82nyQM9GX7PM/QGmg== + version "24.4.2" + resolved "https://registry.yarnpkg.com/eslint-plugin-jest/-/eslint-plugin-jest-24.4.2.tgz#9e8cf05ee6a0e3025e6149df2f36950abfa8d5bf" + integrity sha512-jNMnqwX75z0RXRMXkxwb/+9ylKJYJLJ8nT8nBT0XFM5qx4IQGxP4edMawa0qGkSbHae0BDPBmi8I2QF0/F04XQ== dependencies: "@typescript-eslint/experimental-utils" "^4.0.1" @@ -4517,10 +4496,10 @@ expect@^27.0.6: jest-message-util "^27.0.6" jest-regex-util "^27.0.6" -expect@^27.2.0: - version "27.2.0" - resolved "https://registry.yarnpkg.com/expect/-/expect-27.2.0.tgz#40eb89a492afb726a3929ccf3611ee0799ab976f" - integrity sha512-oOTbawMQv7AK1FZURbPTgGSzmhxkjFzoARSvDjOMnOpeWuYQx1tP6rXu9MIX5mrACmyCAM7fSNP8IJO2f1p0CQ== +expect@^27.2.1: + version "27.2.1" + resolved "https://registry.yarnpkg.com/expect/-/expect-27.2.1.tgz#5f882b308716618613f0106a488b46c303908157" + integrity sha512-ekOA2mBtT2phxcoPVHCXIzbJxCvRXhx2fr7m28IgGdZxUOh8UvxvoRz1FcPlfgZMpE92biHB6woIcAKXqR28hA== dependencies: "@jest/types" "^27.1.1" ansi-styles "^5.0.0" @@ -4635,6 +4614,13 @@ fb-watchman@^2.0.0: dependencies: bser "2.1.1" +fetch-blob@^3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/fetch-blob/-/fetch-blob-3.1.2.tgz#6bc438675f3851ecea51758ac91f6a1cd1bacabd" + integrity sha512-hunJbvy/6OLjCD0uuhLdp0mMPzP/yd2ssd1t2FCJsaA7wkWhpbp9xfuNVpv7Ll4jFhzp6T4LAupSiV9uOeg0VQ== + dependencies: + web-streams-polyfill "^3.0.3" + figgy-pudding@^3.4.1, figgy-pudding@^3.5.1: version "3.5.2" resolved "https://registry.yarnpkg.com/figgy-pudding/-/figgy-pudding-3.5.2.tgz#b4eee8148abb01dcf1d1ac34367d59e12fa61d6e" @@ -5390,7 +5376,7 @@ iconv-lite@0.4.24, iconv-lite@^0.4.24: dependencies: safer-buffer ">= 2.1.2 < 3" -iconv-lite@^0.6.2, iconv-lite@^0.6.3: +iconv-lite@^0.6.2: version "0.6.3" resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.6.3.tgz#a52f80bf38da1952eb5c681790719871a1a72501" integrity sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw== @@ -5421,7 +5407,7 @@ ignore@^4.0.3, ignore@^4.0.6: resolved "https://registry.yarnpkg.com/ignore/-/ignore-4.0.6.tgz#750e3db5862087b4737ebac8207ffd1ef27b25fc" integrity sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg== -ignore@^5.0.4, ignore@^5.0.5, ignore@^5.1.4, ignore@~5.1.8: +ignore@^5.0.4, ignore@^5.0.5, ignore@^5.1.4, ignore@^5.1.8, ignore@~5.1.8: version "5.1.8" resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.1.8.tgz#f150a8b50a34289b33e22f5889abd4d8016f0e57" integrity sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw== @@ -5960,11 +5946,6 @@ istanbul-reports@^3.0.2: html-escaper "^2.0.0" istanbul-lib-report "^3.0.0" -iterable-to-stream@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/iterable-to-stream/-/iterable-to-stream-2.0.0.tgz#8cc654ab9b1011dc138e681fee2c0f0bb3cc7e3c" - integrity sha512-efkLePxXjJk92hvN+2rS3tGJTRn8/tqXjmZvPI6LQ29xCj2sUF4zW8hkMsVe3jpTkxtMZ89xsKnz9FaRqNWM6g== - jake@^10.6.1: version "10.8.2" resolved "https://registry.yarnpkg.com/jake/-/jake-10.8.2.tgz#ebc9de8558160a66d82d0eadc6a2e58fbc500a7b" @@ -6009,10 +5990,10 @@ jest-circus@^27.0.6: stack-utils "^2.0.3" throat "^6.0.1" -jest-circus@^27.2.0: - version "27.2.0" - resolved "https://registry.yarnpkg.com/jest-circus/-/jest-circus-27.2.0.tgz#ad0d6d75514050f539d422bae41344224d2328f9" - integrity sha512-WwENhaZwOARB1nmcboYPSv/PwHBUGRpA4MEgszjr9DLCl97MYw0qZprBwLb7rNzvMwfIvNGG7pefQ5rxyBlzIA== +jest-circus@^27.2.1: + version "27.2.1" + resolved "https://registry.yarnpkg.com/jest-circus/-/jest-circus-27.2.1.tgz#c5166052b328c0df932cdaf89f5982085e7b4812" + integrity sha512-9q/8X8DgJmW8IqXsJNnS2E28iarx990hf6D+frS3P0lB+avhFDD33alLwZzKgm45u0wvEi6iFh43WjNbp5fhjw== dependencies: "@jest/environment" "^27.2.0" "@jest/test-result" "^27.2.0" @@ -6021,32 +6002,32 @@ jest-circus@^27.2.0: chalk "^4.0.0" co "^4.6.0" dedent "^0.7.0" - expect "^27.2.0" + expect "^27.2.1" is-generator-fn "^2.0.0" jest-each "^27.2.0" jest-matcher-utils "^27.2.0" jest-message-util "^27.2.0" - jest-runtime "^27.2.0" - jest-snapshot "^27.2.0" + jest-runtime "^27.2.1" + jest-snapshot "^27.2.1" jest-util "^27.2.0" pretty-format "^27.2.0" slash "^3.0.0" stack-utils "^2.0.3" throat "^6.0.1" -jest-cli@^27.2.0: - version "27.2.0" - resolved "https://registry.yarnpkg.com/jest-cli/-/jest-cli-27.2.0.tgz#6da5ecca5bd757e20449f5ec1f1cad5b0303d16b" - integrity sha512-bq1X/B/b1kT9y1zIFMEW3GFRX1HEhFybiqKdbxM+j11XMMYSbU9WezfyWIhrSOmPT+iODLATVjfsCnbQs7cfIA== +jest-cli@^27.2.1: + version "27.2.1" + resolved "https://registry.yarnpkg.com/jest-cli/-/jest-cli-27.2.1.tgz#031e887245945864cc6ed8605c939f1937858c09" + integrity sha512-IfxuGkBZS/ogY7yFvvD1dFidzQRXlSBHtUZQ3UTIHydzNMF4/ZRTdGFso6HkbCkemwLh4hnNybONexEqWmYwjw== dependencies: - "@jest/core" "^27.2.0" + "@jest/core" "^27.2.1" "@jest/test-result" "^27.2.0" "@jest/types" "^27.1.1" chalk "^4.0.0" exit "^0.1.2" graceful-fs "^4.2.4" import-local "^3.0.2" - jest-config "^27.2.0" + jest-config "^27.2.1" jest-util "^27.2.0" jest-validate "^27.2.0" prompts "^2.0.1" @@ -6079,28 +6060,28 @@ jest-config@27.0.6: micromatch "^4.0.4" pretty-format "^27.0.6" -jest-config@^27.2.0: - version "27.2.0" - resolved "https://registry.yarnpkg.com/jest-config/-/jest-config-27.2.0.tgz#d1c359253927005c53d11ab3e50d3b2f402a673a" - integrity sha512-Z1romHpxeNwLxQtouQ4xt07bY6HSFGKTo0xJcvOK3u6uJHveA4LB2P+ty9ArBLpTh3AqqPxsyw9l9GMnWBYS9A== +jest-config@^27.2.1: + version "27.2.1" + resolved "https://registry.yarnpkg.com/jest-config/-/jest-config-27.2.1.tgz#2e727e023fc4b77a9f067a40c5448a939aa8386b" + integrity sha512-BAOemP8udmFw9nkgaLAac7vXORdvrt4yrJWoh7uYb0nPZeSsu0kGwJU18SwtY4paq9fed5OgAssC3A+Bf4WMQA== dependencies: "@babel/core" "^7.1.0" - "@jest/test-sequencer" "^27.2.0" + "@jest/test-sequencer" "^27.2.1" "@jest/types" "^27.1.1" - babel-jest "^27.2.0" + babel-jest "^27.2.1" chalk "^4.0.0" deepmerge "^4.2.2" glob "^7.1.1" graceful-fs "^4.2.4" is-ci "^3.0.0" - jest-circus "^27.2.0" + jest-circus "^27.2.1" jest-environment-jsdom "^27.2.0" jest-environment-node "^27.2.0" jest-get-type "^27.0.6" - jest-jasmine2 "^27.2.0" + jest-jasmine2 "^27.2.1" jest-regex-util "^27.0.6" jest-resolve "^27.2.0" - jest-runner "^27.2.0" + jest-runner "^27.2.1" jest-util "^27.2.0" jest-validate "^27.2.0" micromatch "^4.0.4" @@ -6289,10 +6270,10 @@ jest-jasmine2@^27.0.6: pretty-format "^27.0.6" throat "^6.0.1" -jest-jasmine2@^27.2.0: - version "27.2.0" - resolved "https://registry.yarnpkg.com/jest-jasmine2/-/jest-jasmine2-27.2.0.tgz#1ece0ee37c348b59ed3dfcfe509fc24e3377b12d" - integrity sha512-NcPzZBk6IkDW3Z2V8orGueheGJJYfT5P0zI/vTO/Jp+R9KluUdgFrgwfvZ0A34Kw6HKgiWFILZmh3oQ/eS+UxA== +jest-jasmine2@^27.2.1: + version "27.2.1" + resolved "https://registry.yarnpkg.com/jest-jasmine2/-/jest-jasmine2-27.2.1.tgz#30ee71f38670a621ecf3b6dcb89875933f780de6" + integrity sha512-3vytj3+S49+XYsxGJyjlchDo4xblYzjDY4XK7pV2IAdspbMFOpmeNMOeDonYuvlbUtcV8yrFLA6XtliXapDmMA== dependencies: "@babel/traverse" "^7.1.0" "@jest/environment" "^27.2.0" @@ -6302,13 +6283,13 @@ jest-jasmine2@^27.2.0: "@types/node" "*" chalk "^4.0.0" co "^4.6.0" - expect "^27.2.0" + expect "^27.2.1" is-generator-fn "^2.0.0" jest-each "^27.2.0" jest-matcher-utils "^27.2.0" jest-message-util "^27.2.0" - jest-runtime "^27.2.0" - jest-snapshot "^27.2.0" + jest-runtime "^27.2.1" + jest-snapshot "^27.2.1" jest-util "^27.2.0" pretty-format "^27.2.0" throat "^6.0.1" @@ -6435,14 +6416,14 @@ jest-regex-util@^27.0.6: resolved "https://registry.yarnpkg.com/jest-regex-util/-/jest-regex-util-27.0.6.tgz#02e112082935ae949ce5d13b2675db3d8c87d9c5" integrity sha512-SUhPzBsGa1IKm8hx2F4NfTGGp+r7BXJ4CulsZ1k2kI+mGLG+lxGrs76veN2LF/aUdGosJBzKgXmNCw+BzFqBDQ== -jest-resolve-dependencies@^27.2.0: - version "27.2.0" - resolved "https://registry.yarnpkg.com/jest-resolve-dependencies/-/jest-resolve-dependencies-27.2.0.tgz#b56a1aab95b0fd21e0a69a15fda985c05f902b8a" - integrity sha512-EY5jc/Y0oxn+oVEEldTidmmdVoZaknKPyDORA012JUdqPyqPL+lNdRyI3pGti0RCydds6coaw6xt4JQY54dKsg== +jest-resolve-dependencies@^27.2.1: + version "27.2.1" + resolved "https://registry.yarnpkg.com/jest-resolve-dependencies/-/jest-resolve-dependencies-27.2.1.tgz#239be969ece749d4dc2e1efcf3d2b86c99525c2e" + integrity sha512-9bKEwmz4YshGPjGZAVZOVw6jt7pq2/FjWJmyhnWhvDuiRCHVZBcJhycinX+e/EJ7jafsq26bTpzBIQas3xql1g== dependencies: "@jest/types" "^27.1.1" jest-regex-util "^27.0.6" - jest-snapshot "^27.2.0" + jest-snapshot "^27.2.1" jest-resolve@27.0.6, jest-resolve@^27.0.6: version "27.0.6" @@ -6518,15 +6499,15 @@ jest-runner@^27.0.6: source-map-support "^0.5.6" throat "^6.0.1" -jest-runner@^27.2.0: - version "27.2.0" - resolved "https://registry.yarnpkg.com/jest-runner/-/jest-runner-27.2.0.tgz#281b255d88a473aebc0b5cb46e58a83a1251cab3" - integrity sha512-Cl+BHpduIc0cIVTjwoyx0pQk4Br8gn+wkr35PmKCmzEdOUnQ2wN7QVXA8vXnMQXSlFkN/+KWnk20TAVBmhgrww== +jest-runner@^27.2.1: + version "27.2.1" + resolved "https://registry.yarnpkg.com/jest-runner/-/jest-runner-27.2.1.tgz#3443b1fc08b8a50f305dfc2d41dd2badf335843b" + integrity sha512-USHitkUUzcB3Y5mRdzlp+KHgRRR2VsXDq5OeATuDmq1qXfT/RwwnQykUhn+KVx3FotxK3pID74UY7o6HYIR8vA== dependencies: "@jest/console" "^27.2.0" "@jest/environment" "^27.2.0" "@jest/test-result" "^27.2.0" - "@jest/transform" "^27.2.0" + "@jest/transform" "^27.2.1" "@jest/types" "^27.1.1" "@types/node" "*" chalk "^4.0.0" @@ -6540,7 +6521,7 @@ jest-runner@^27.2.0: jest-leak-detector "^27.2.0" jest-message-util "^27.2.0" jest-resolve "^27.2.0" - jest-runtime "^27.2.0" + jest-runtime "^27.2.1" jest-util "^27.2.0" jest-worker "^27.2.0" source-map-support "^0.5.6" @@ -6578,18 +6559,18 @@ jest-runtime@^27.0.6: strip-bom "^4.0.0" yargs "^16.0.3" -jest-runtime@^27.2.0: - version "27.2.0" - resolved "https://registry.yarnpkg.com/jest-runtime/-/jest-runtime-27.2.0.tgz#998295ccd80008b3031eeb5cc60e801e8551024b" - integrity sha512-6gRE9AVVX49hgBbWQ9PcNDeM4upMUXzTpBs0kmbrjyotyUyIJixLPsYjpeTFwAA07PVLDei1iAm2chmWycdGdQ== +jest-runtime@^27.2.1: + version "27.2.1" + resolved "https://registry.yarnpkg.com/jest-runtime/-/jest-runtime-27.2.1.tgz#db506f679356f5b94b7be20e770f2541b7c2b339" + integrity sha512-QJNnwL4iteDE/Jq4TfQK7AjhPoUZflBKTtUIkRnFYFkTAZTP/o8k7ekaROiVjmo+NYop5+DQPqX6pz4vWbZSOQ== dependencies: "@jest/console" "^27.2.0" "@jest/environment" "^27.2.0" "@jest/fake-timers" "^27.2.0" - "@jest/globals" "^27.2.0" + "@jest/globals" "^27.2.1" "@jest/source-map" "^27.0.6" "@jest/test-result" "^27.2.0" - "@jest/transform" "^27.2.0" + "@jest/transform" "^27.2.1" "@jest/types" "^27.1.1" "@types/yargs" "^16.0.0" chalk "^4.0.0" @@ -6604,7 +6585,7 @@ jest-runtime@^27.2.0: jest-mock "^27.1.1" jest-regex-util "^27.0.6" jest-resolve "^27.2.0" - jest-snapshot "^27.2.0" + jest-snapshot "^27.2.1" jest-util "^27.2.0" jest-validate "^27.2.0" slash "^3.0.0" @@ -6687,10 +6668,10 @@ jest-snapshot@^27.0.6: pretty-format "^27.0.6" semver "^7.3.2" -jest-snapshot@^27.2.0: - version "27.2.0" - resolved "https://registry.yarnpkg.com/jest-snapshot/-/jest-snapshot-27.2.0.tgz#7961e7107ac666a46fbb23e7bb48ce0b8c6a9285" - integrity sha512-MukJvy3KEqemCT2FoT3Gum37CQqso/62PKTfIzWmZVTsLsuyxQmJd2PI5KPcBYFqLlA8LgZLHM8ZlazkVt8LsQ== +jest-snapshot@^27.2.1: + version "27.2.1" + resolved "https://registry.yarnpkg.com/jest-snapshot/-/jest-snapshot-27.2.1.tgz#385accf3bb71ac84e9a6bda4fc9bb458d53abb35" + integrity sha512-8CTg2YrgZuQbPHW7G0YvLTj4yTRXLmSeEO+ka3eC5lbu5dsTRyoDNS1L7x7EFUTyYQhFH9HQG1/TNlbUgR9Lug== dependencies: "@babel/core" "^7.7.2" "@babel/generator" "^7.7.2" @@ -6698,13 +6679,13 @@ jest-snapshot@^27.2.0: "@babel/plugin-syntax-typescript" "^7.7.2" "@babel/traverse" "^7.7.2" "@babel/types" "^7.0.0" - "@jest/transform" "^27.2.0" + "@jest/transform" "^27.2.1" "@jest/types" "^27.1.1" "@types/babel__traverse" "^7.0.4" "@types/prettier" "^2.1.5" babel-preset-current-node-syntax "^1.0.0" chalk "^4.0.0" - expect "^27.2.0" + expect "^27.2.1" graceful-fs "^4.2.4" jest-diff "^27.2.0" jest-get-type "^27.0.6" @@ -6825,13 +6806,13 @@ jest-worker@^27.2.0: supports-color "^8.0.0" jest@^27.0.3: - version "27.2.0" - resolved "https://registry.yarnpkg.com/jest/-/jest-27.2.0.tgz#3bc329287d699d26361e2094919630eefdf1ac0d" - integrity sha512-oUqVXyvh5YwEWl263KWdPUAqEzBFzGHdFLQ05hUnITr1tH+9SscEI9A/GH9eBClA+Nw1ct+KNuuOV6wlnmBPcg== + version "27.2.1" + resolved "https://registry.yarnpkg.com/jest/-/jest-27.2.1.tgz#9263102056fe152fd2478d181cf9bbbd2a6a8da4" + integrity sha512-0MyvNS7J1HbkeotYaqKNGioN+p1/AAPtI1Z8iwMtCBE+PwBT+M4l25D9Pve8/KdhktYLgZaGyyj9CoDytD+R2Q== dependencies: - "@jest/core" "^27.2.0" + "@jest/core" "^27.2.1" import-local "^3.0.2" - jest-cli "^27.2.0" + jest-cli "^27.2.1" jju@~1.4.0: version "1.4.0" @@ -7765,7 +7746,15 @@ node-fetch-npm@^2.0.2: json-parse-better-errors "^1.0.0" safe-buffer "^5.1.1" -node-fetch@^2.3.0, node-fetch@^2.5.0, node-fetch@^2.6.0, node-fetch@^2.6.1: +node-fetch@*, node-fetch@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-3.0.0.tgz#79da7146a520036f2c5f644e4a26095f17e411ea" + integrity sha512-bKMI+C7/T/SPU1lKnbQbwxptpCrG9ashG+VkytmXCPZyuM9jB6VU+hY0oi4lC8LxTtAeWdckNCTa3nrGsAdA3Q== + dependencies: + data-uri-to-buffer "^3.0.1" + fetch-blob "^3.1.2" + +node-fetch@^2.3.0, node-fetch@^2.5.0, node-fetch@^2.6.0: version "2.6.1" resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.1.tgz#045bd323631f76ed2e2b55573394416b639a0052" integrity sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw== @@ -8473,11 +8462,11 @@ prettier@2.3.2: integrity sha512-lnJzDfJ66zkMy58OL5/NY5zp70S7Nz6KqcKkXYzn2tMVrNxvbqaBpg7H3qHaLxCJ5lNMsGuM8+ohS7cZrthdLQ== pretty-format@*, pretty-format@^27.0.0, pretty-format@^27.0.2, pretty-format@^27.0.6, pretty-format@^27.2.0: - version "27.0.6" - resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-27.0.6.tgz#ab770c47b2c6f893a21aefc57b75da63ef49a11f" - integrity sha512-8tGD7gBIENgzqA+UBzObyWqQ5B778VIFZA/S66cclyd5YkFLYs2Js7gxDKf0MXtTc9zcS7t1xhdfcElJ3YIvkQ== + version "27.2.0" + resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-27.2.0.tgz#ee37a94ce2a79765791a8649ae374d468c18ef19" + integrity sha512-KyJdmgBkMscLqo8A7K77omgLx5PWPiXJswtTtFV7XgVZv2+qPk6UivpXXO+5k6ZEbWIbLoKdx1pZ6ldINzbwTA== dependencies: - "@jest/types" "^27.0.6" + "@jest/types" "^27.1.1" ansi-regex "^5.0.0" ansi-styles "^5.0.0" react-is "^17.0.1" @@ -9723,9 +9712,9 @@ tmp@^0.2.1, tmp@~0.2.1: rimraf "^3.0.0" tmpl@1.0.x: - version "1.0.4" - resolved "https://registry.yarnpkg.com/tmpl/-/tmpl-1.0.4.tgz#23640dd7b42d00433911140820e5cf440e521dd1" - integrity sha1-I2QN17QtAEM5ERQIIOXPRA5SHdE= + version "1.0.5" + resolved "https://registry.yarnpkg.com/tmpl/-/tmpl-1.0.5.tgz#8683e0b902bb9c20c4f726e3c0b69f36518c07cc" + integrity sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw== to-fast-properties@^2.0.0: version "2.0.0" @@ -10189,6 +10178,11 @@ wcwidth@^1.0.0: dependencies: defaults "^1.0.3" +web-streams-polyfill@^3.0.3: + version "3.1.1" + resolved "https://registry.yarnpkg.com/web-streams-polyfill/-/web-streams-polyfill-3.1.1.tgz#1516f2d4ea8f1bdbfed15eb65cb2df87098c8364" + integrity sha512-Czi3fG883e96T4DLEPRvufrF2ydhOOW1+1a6c3gNjH2aIh50DNFBdfwh2AKoOf1rXvpvavAoA11Qdq9+BKjE0Q== + webidl-conversions@^4.0.2: version "4.0.2" resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-4.0.2.tgz#a855980b1f0b6b359ba1d5d9fb39ae941faa63ad"