diff --git a/CHANGELOG.md b/CHANGELOG.md index db2020835213..a78733e77cb5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,25 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [2.21.0](https://github.com/typescript-eslint/typescript-eslint/compare/v2.20.0...v2.21.0) (2020-02-24) + + +### Bug Fixes + +* **eslint-plugin:** [embt] ignore JSX callbacks ([#1630](https://github.com/typescript-eslint/typescript-eslint/issues/1630)) ([4d45b33](https://github.com/typescript-eslint/typescript-eslint/commit/4d45b331b920113c97a90df7dc703f8dfbcc04f3)) +* **eslint-plugin:** [no-floating-promises] handle finally callback ([#1620](https://github.com/typescript-eslint/typescript-eslint/issues/1620)) ([1aa7135](https://github.com/typescript-eslint/typescript-eslint/commit/1aa7135bbfbf55cec52925fc0224188cd3c319e7)) +* **eslint-plugin:** [typedef] allow array/object destructuring in for/of ([#1570](https://github.com/typescript-eslint/typescript-eslint/issues/1570)) ([660bace](https://github.com/typescript-eslint/typescript-eslint/commit/660bace4c3da569d71cf1e296ac4f6ed35bdfc44)) +* **typescript-estree:** process.stdout can be undefined ([#1619](https://github.com/typescript-eslint/typescript-eslint/issues/1619)) ([0d8e87e](https://github.com/typescript-eslint/typescript-eslint/commit/0d8e87e09704588273bc94a740279b3e8af7474f)) + + +### Features + +* **eslint-plugin:** [require-await] add --fix support ([#1561](https://github.com/typescript-eslint/typescript-eslint/issues/1561)) ([9edd863](https://github.com/typescript-eslint/typescript-eslint/commit/9edd863b2a66ee44bd4a439903973e6c207480aa)) + + + + + # [2.20.0](https://github.com/typescript-eslint/typescript-eslint/compare/v2.19.2...v2.20.0) (2020-02-17) diff --git a/lerna.json b/lerna.json index b4c62e5e783f..f38de2345022 100644 --- a/lerna.json +++ b/lerna.json @@ -1,5 +1,5 @@ { - "version": "2.20.0", + "version": "2.21.0", "npmClient": "yarn", "useWorkspaces": true, "stream": true diff --git a/packages/eslint-plugin-internal/CHANGELOG.md b/packages/eslint-plugin-internal/CHANGELOG.md index a9f9f05b7c11..9ccbe0f64764 100644 --- a/packages/eslint-plugin-internal/CHANGELOG.md +++ b/packages/eslint-plugin-internal/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [2.21.0](https://github.com/typescript-eslint/typescript-eslint/compare/v2.20.0...v2.21.0) (2020-02-24) + +**Note:** Version bump only for package @typescript-eslint/eslint-plugin-internal + + + + + # [2.20.0](https://github.com/typescript-eslint/typescript-eslint/compare/v2.19.2...v2.20.0) (2020-02-17) **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 29967952fa04..1a10da87b029 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": "2.20.0", + "version": "2.21.0", "private": true, "main": "dist/index.js", "scripts": { @@ -12,6 +12,6 @@ "typecheck": "tsc -p tsconfig.json --noEmit" }, "dependencies": { - "@typescript-eslint/experimental-utils": "2.20.0" + "@typescript-eslint/experimental-utils": "2.21.0" } } diff --git a/packages/eslint-plugin-tslint/CHANGELOG.md b/packages/eslint-plugin-tslint/CHANGELOG.md index bf7070f5ee6a..10645006953a 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. +# [2.21.0](https://github.com/typescript-eslint/typescript-eslint/compare/v2.20.0...v2.21.0) (2020-02-24) + +**Note:** Version bump only for package @typescript-eslint/eslint-plugin-tslint + + + + + # [2.20.0](https://github.com/typescript-eslint/typescript-eslint/compare/v2.19.2...v2.20.0) (2020-02-17) **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 553be2e38d48..74c97b0cd0c8 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": "2.20.0", + "version": "2.21.0", "main": "dist/index.js", "typings": "src/index.ts", "description": "TSLint wrapper plugin for ESLint", @@ -31,7 +31,7 @@ "typecheck": "tsc -p tsconfig.json --noEmit" }, "dependencies": { - "@typescript-eslint/experimental-utils": "2.20.0", + "@typescript-eslint/experimental-utils": "2.21.0", "lodash": "^4.17.15" }, "peerDependencies": { @@ -41,6 +41,6 @@ }, "devDependencies": { "@types/lodash": "^4.14.149", - "@typescript-eslint/parser": "2.20.0" + "@typescript-eslint/parser": "2.21.0" } } diff --git a/packages/eslint-plugin/CHANGELOG.md b/packages/eslint-plugin/CHANGELOG.md index fd4a172bfd6b..99f1a97c32bc 100644 --- a/packages/eslint-plugin/CHANGELOG.md +++ b/packages/eslint-plugin/CHANGELOG.md @@ -3,6 +3,24 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [2.21.0](https://github.com/typescript-eslint/typescript-eslint/compare/v2.20.0...v2.21.0) (2020-02-24) + + +### Bug Fixes + +* **eslint-plugin:** [embt] ignore JSX callbacks ([#1630](https://github.com/typescript-eslint/typescript-eslint/issues/1630)) ([4d45b33](https://github.com/typescript-eslint/typescript-eslint/commit/4d45b331b920113c97a90df7dc703f8dfbcc04f3)) +* **eslint-plugin:** [no-floating-promises] handle finally callback ([#1620](https://github.com/typescript-eslint/typescript-eslint/issues/1620)) ([1aa7135](https://github.com/typescript-eslint/typescript-eslint/commit/1aa7135bbfbf55cec52925fc0224188cd3c319e7)) +* **eslint-plugin:** [typedef] allow array/object destructuring in for/of ([#1570](https://github.com/typescript-eslint/typescript-eslint/issues/1570)) ([660bace](https://github.com/typescript-eslint/typescript-eslint/commit/660bace4c3da569d71cf1e296ac4f6ed35bdfc44)) + + +### Features + +* **eslint-plugin:** [require-await] add --fix support ([#1561](https://github.com/typescript-eslint/typescript-eslint/issues/1561)) ([9edd863](https://github.com/typescript-eslint/typescript-eslint/commit/9edd863b2a66ee44bd4a439903973e6c207480aa)) + + + + + # [2.20.0](https://github.com/typescript-eslint/typescript-eslint/compare/v2.19.2...v2.20.0) (2020-02-17) diff --git a/packages/eslint-plugin/README.md b/packages/eslint-plugin/README.md index 0f55ace3d5de..fcc422386b4c 100644 --- a/packages/eslint-plugin/README.md +++ b/packages/eslint-plugin/README.md @@ -185,7 +185,7 @@ In these cases, we create what we call an extension rule; a rule within our plug | [`@typescript-eslint/no-useless-constructor`](./docs/rules/no-useless-constructor.md) | Disallow unnecessary constructors | | | | | [`@typescript-eslint/quotes`](./docs/rules/quotes.md) | Enforce the consistent use of either backticks, double, or single quotes | | :wrench: | | | [`@typescript-eslint/require-await`](./docs/rules/require-await.md) | Disallow async functions which have no `await` expression | :heavy_check_mark: | | :thought_balloon: | -| [`@typescript-eslint/return-await`](./docs/rules/return-await.md) | Enforces consistent returning of awaited values | | | :thought_balloon: | +| [`@typescript-eslint/return-await`](./docs/rules/return-await.md) | Enforces consistent returning of awaited values | | :wrench: | :thought_balloon: | | [`@typescript-eslint/semi`](./docs/rules/semi.md) | Require or disallow semicolons instead of ASI | | :wrench: | | | [`@typescript-eslint/space-before-function-paren`](./docs/rules/space-before-function-paren.md) | Enforces consistent spacing before function parenthesis | | :wrench: | | diff --git a/packages/eslint-plugin/ROADMAP.md b/packages/eslint-plugin/ROADMAP.md index c4f99f947af4..3c7b5b4edc66 100644 --- a/packages/eslint-plugin/ROADMAP.md +++ b/packages/eslint-plugin/ROADMAP.md @@ -18,6 +18,7 @@ It lists all TSLint rules along side rules from the ESLint ecosystem that are th | [`adjacent-overload-signatures`] | βœ… | [`@typescript-eslint/adjacent-overload-signatures`] | | [`ban-ts-ignore`] | βœ… | [`@typescript-eslint/ban-ts-ignore`] | | [`ban-types`] | πŸŒ“ | [`@typescript-eslint/ban-types`][1] | +| [`invalid-void`] | πŸ›‘ | N/A | | [`member-access`] | βœ… | [`@typescript-eslint/explicit-member-accessibility`] | | [`member-ordering`] | βœ… | [`@typescript-eslint/member-ordering`] | | [`no-any`] | βœ… | [`@typescript-eslint/no-explicit-any`] | @@ -43,67 +44,73 @@ It lists all TSLint rules along side rules from the ESLint ecosystem that are th ### Functionality -| TSLint rule | | ESLint rule | -| ------------------------------------ | :-: | --------------------------------------------------------------------- | -| [`await-promise`] | βœ… | [`@typescript-eslint/await-thenable`] | -| [`ban-comma-operator`] | 🌟 | [`no-sequences`][no-sequences] | -| [`ban`] | 🌟 | [`no-restricted-properties`][no-restricted-properties] | -| [`curly`] | 🌟 | [`curly`][curly] | -| [`forin`] | 🌟 | [`guard-for-in`][guard-for-in] | -| [`function-constructor`] | 🌟 | [`no-new-func`][no-new-func] | -| [`import-blacklist`] | 🌟 | [`no-restricted-imports`][no-restricted-imports] | -| [`label-position`] | 🌟 | [`no-unused-labels`][no-unused-labels] (similar) | -| [`no-arg`] | 🌟 | [`no-caller`][no-caller] (also blocks `arguments.caller`) | -| [`no-async-without-await`] | βœ… | [`@typescript-eslint/require-await`] | -| [`no-bitwise`] | 🌟 | [`no-bitwise`][no-bitwise] | -| [`no-conditional-assignment`] | 🌟 | [`no-cond-assign`][no-cond-assign][1] | -| [`no-console`] | 🌟 | [`no-console`][no-console] (configuration works slightly differently) | -| [`no-construct`] | 🌟 | [`no-new-wrappers`][no-new-wrappers] | -| [`no-debugger`] | 🌟 | [`no-debugger`][no-debugger] | -| [`no-duplicate-super`] | 🌟 | [`constructor-super`][constructor-super] | -| [`no-duplicate-switch-case`] | 🌟 | [`no-duplicate-case`][no-duplicate-case] | -| [`no-duplicate-variable`] | 🌟 | [`no-redeclare`][no-redeclare] | -| [`no-dynamic-delete`] | βœ… | [`@typescript-eslint/no-dynamic-delete`] | -| [`no-empty`] | 🌟 | [`no-empty`][no-empty] | -| [`no-eval`] | 🌟 | [`no-eval`][no-eval] | -| [`no-floating-promises`] | βœ… | [`@typescript-eslint/no-floating-promises`] | -| [`no-for-in-array`] | βœ… | [`@typescript-eslint/no-for-in-array`] | -| [`no-implicit-dependencies`] | πŸ”Œ | [`import/no-extraneous-dependencies`] | -| [`no-inferred-empty-object-type`] | πŸ›‘ | N/A | -| [`no-invalid-template-strings`] | 🌟 | [`no-template-curly-in-string`][no-template-curly-in-string] | -| [`no-invalid-this`] | 🌟 | [`no-invalid-this`][no-invalid-this] | -| [`no-misused-new`] | βœ… | [`@typescript-eslint/no-misused-new`] | -| [`no-null-keyword`] | πŸ”Œ | [`no-null/no-null`] (doesn’t handle `null` type) | -| [`no-object-literal-type-assertion`] | βœ… | [`@typescript-eslint/consistent-type-assertions`] | -| [`no-return-await`] | 🌟 | [`no-return-await`][no-return-await] | -| [`no-shadowed-variable`] | 🌟 | [`no-shadow`][no-shadow] | -| [`no-sparse-arrays`] | 🌟 | [`no-sparse-arrays`][no-sparse-arrays] | -| [`no-string-literal`] | 🌟 | [`dot-notation`][dot-notation] | -| [`no-string-throw`] | βœ… | [`@typescript-eslint/no-throw-literal`] | -| [`no-submodule-imports`] | πŸŒ“ | [`import/no-internal-modules`] (slightly different) | -| [`no-switch-case-fall-through`] | 🌟 | [`no-fallthrough`][no-fallthrough] | -| [`no-this-assignment`] | βœ… | [`@typescript-eslint/no-this-alias`] | -| [`no-unbound-method`] | βœ… | [`@typescript-eslint/unbound-method`] | -| [`no-unnecessary-class`] | βœ… | [`@typescript-eslint/no-extraneous-class`] | -| [`no-unsafe-any`] | πŸ›‘ | N/A | -| [`no-unsafe-finally`] | 🌟 | [`no-unsafe-finally`][no-unsafe-finally] | -| [`no-unused-expression`] | 🌟 | [`no-unused-expressions`][no-unused-expressions] | -| [`no-unused-variable`] | πŸŒ“ | [`@typescript-eslint/no-unused-vars`] | -| [`no-use-before-declare`] | βœ… | [`@typescript-eslint/no-use-before-define`] | -| [`no-var-keyword`] | 🌟 | [`no-var`][no-var] | -| [`no-void-expression`] | 🌟 | [`no-void`][no-void] | -| [`prefer-conditional-expression`] | πŸ›‘ | N/A | -| [`prefer-object-spread`] | 🌟 | [`prefer-object-spread`][prefer-object-spread] | -| [`radix`] | 🌟 | [`radix`][radix] | -| [`restrict-plus-operands`] | βœ… | [`@typescript-eslint/restrict-plus-operands`] | -| [`strict-boolean-expressions`] | βœ… | [`@typescript-eslint/strict-boolean-expressions`] | -| [`strict-type-predicates`] | πŸ›‘ | N/A | -| [`switch-default`] | 🌟 | [`default-case`][default-case] | -| [`triple-equals`] | 🌟 | [`eqeqeq`][eqeqeq] | -| [`typeof-compare`] | 🌟 | [`valid-typeof`][valid-typeof] | -| [`unnecessary-constructor`] | 🌟 | [`no-useless-constructor`][no-useless-constructor] | -| [`use-default-type-parameter`] | βœ… | [`@typescript-eslint/no-unnecessary-type-arguments`] | -| [`use-isnan`] | 🌟 | [`use-isnan`][use-isnan] | +| TSLint rule | | ESLint rule | +| ------------------------------------ | :-: | ---------------------------------------------------------------------------------------------------- | +| [`await-promise`] | βœ… | [`@typescript-eslint/await-thenable`] | +| [`ban-comma-operator`] | 🌟 | [`no-sequences`][no-sequences] | +| [`ban`] | 🌟 | [`no-restricted-properties`][no-restricted-properties] | +| [`curly`] | 🌟 | [`curly`][curly] | +| [`forin`] | 🌟 | [`guard-for-in`][guard-for-in] | +| [`function-constructor`] | 🌟 | [`no-new-func`][no-new-func] | +| [`import-blacklist`] | 🌟 | [`no-restricted-imports`][no-restricted-imports] | +| [`label-position`] | 🌟 | [`no-unused-labels`][no-unused-labels] (similar) | +| [`no-arg`] | 🌟 | [`no-caller`][no-caller] (also blocks `arguments.caller`) | +| [`no-async-without-await`] | βœ… | [`@typescript-eslint/require-await`] | +| [`no-bitwise`] | 🌟 | [`no-bitwise`][no-bitwise] | +| [`no-conditional-assignment`] | 🌟 | [`no-cond-assign`][no-cond-assign][1] | +| [`no-console`] | 🌟 | [`no-console`][no-console] (configuration works slightly differently) | +| [`no-construct`] | 🌟 | [`no-new-wrappers`][no-new-wrappers] | +| [`no-debugger`] | 🌟 | [`no-debugger`][no-debugger] | +| [`no-duplicate-super`] | 🌟 | [`constructor-super`][constructor-super] | +| [`no-duplicate-switch-case`] | 🌟 | [`no-duplicate-case`][no-duplicate-case] | +| [`no-duplicate-variable`] | 🌟 | [`no-redeclare`][no-redeclare] | +| [`no-dynamic-delete`] | βœ… | [`@typescript-eslint/no-dynamic-delete`] | +| [`no-empty`] | 🌟 | [`no-empty`][no-empty] | +| [`no-eval`] | 🌟 | [`no-eval`][no-eval] | +| [`no-floating-promises`] | βœ… | [`@typescript-eslint/no-floating-promises`] | +| [`no-for-in-array`] | βœ… | [`@typescript-eslint/no-for-in-array`] | +| [`no-implicit-dependencies`] | πŸ”Œ | [`import/no-extraneous-dependencies`] | +| [`no-inferred-empty-object-type`] | πŸ›‘ | N/A | +| [`no-invalid-template-strings`] | 🌟 | [`no-template-curly-in-string`][no-template-curly-in-string] | +| [`no-invalid-this`] | 🌟 | [`no-invalid-this`][no-invalid-this] | +| [`no-misused-new`] | βœ… | [`@typescript-eslint/no-misused-new`] | +| [`no-null-keyword`] | πŸ”Œ | [`no-null/no-null`] (doesn’t handle `null` type) | +| [`no-null-undefined-union`] | πŸ›‘ | N/A | +| [`no-object-literal-type-assertion`] | βœ… | [`@typescript-eslint/consistent-type-assertions`] | +| [`no-promise-as-boolean`] | βœ… | [`@typescript-eslint/no-misused-promises`] | +| [`no-restricted-globals`] | βœ… | [`no-restricted-globals`][no-restricted-globals] | +| [`no-return-await`] | 🌟 | [`no-return-await`][no-return-await] | +| [`no-shadowed-variable`] | 🌟 | [`no-shadow`][no-shadow] | +| [`no-sparse-arrays`] | 🌟 | [`no-sparse-arrays`][no-sparse-arrays] | +| [`no-string-literal`] | 🌟 | [`dot-notation`][dot-notation] | +| [`no-string-throw`] | βœ… | [`@typescript-eslint/no-throw-literal`] | +| [`no-submodule-imports`] | πŸŒ“ | [`import/no-internal-modules`] (slightly different) | +| [`no-switch-case-fall-through`] | 🌟 | [`no-fallthrough`][no-fallthrough] | +| [`no-tautology-expression`] | πŸ›‘ | N/A | +| [`no-this-assignment`] | βœ… | [`@typescript-eslint/no-this-alias`] | +| [`no-unbound-method`] | βœ… | [`@typescript-eslint/unbound-method`] | +| [`no-unnecessary-class`] | βœ… | [`@typescript-eslint/no-extraneous-class`] | +| [`no-unsafe-any`] | πŸ›‘ | N/A | +| [`no-unsafe-finally`] | 🌟 | [`no-unsafe-finally`][no-unsafe-finally] | +| [`no-unused-expression`] | 🌟 | [`no-unused-expressions`][no-unused-expressions] | +| [`no-unused-variable`] | πŸŒ“ | [`@typescript-eslint/no-unused-vars`] | +| [`no-use-before-declare`] | βœ… | [`@typescript-eslint/no-use-before-define`] | +| [`no-var-keyword`] | 🌟 | [`no-var`][no-var] | +| [`no-void-expression`] | 🌟 | [`no-void`][no-void] | +| [`prefer-conditional-expression`] | πŸ›‘ | N/A | +| [`prefer-object-spread`] | 🌟 | [`prefer-object-spread`][prefer-object-spread] | +| [`radix`] | 🌟 | [`radix`][radix] | +| [`restrict-plus-operands`] | βœ… | [`@typescript-eslint/restrict-plus-operands`] | +| [`static-this`] | πŸ›‘ | N/A | +| [`strict-boolean-expressions`] | βœ… | [`@typescript-eslint/strict-boolean-expressions`] | +| [`strict-string-expressions`] | βœ… | [`@typescript-eslint/restrict-plus-operands`] & [`@typescript-eslint/restrict-template-expressions`] | +| [`strict-type-predicates`] | πŸ›‘ | N/A | +| [`switch-default`] | 🌟 | [`default-case`][default-case] | +| [`triple-equals`] | 🌟 | [`eqeqeq`][eqeqeq] | +| [`typeof-compare`] | 🌟 | [`valid-typeof`][valid-typeof] | +| [`unnecessary-constructor`] | 🌟 | [`no-useless-constructor`][no-useless-constructor] | +| [`use-default-type-parameter`] | βœ… | [`@typescript-eslint/no-unnecessary-type-arguments`] | +| [`use-isnan`] | 🌟 | [`use-isnan`][use-isnan] | [1] The ESLint rule also supports silencing with an extra set of parentheses (`if ((foo = bar)) {}`)
@@ -112,7 +119,7 @@ It lists all TSLint rules along side rules from the ESLint ecosystem that are th | TSLint rule | | ESLint rule | | ---------------------------- | :-: | -------------------------------------------------- | | [`cyclomatic-complexity`] | 🌟 | [`complexity`][complexity] | -| [`deprecation`] | πŸŒ“ | [`import/no-deprecated`] [1] | +| [`deprecation`] | πŸ”Œ | [`deprecation/deprecation`] | | [`eofline`] | 🌟 | [`eol-last`][eol-last] | | [`indent`] | βœ… | [`@typescript-eslint/indent`] or [Prettier] | | [`linebreak-style`] | 🌟 | [`linebreak-style`][linebreak-style] or [Prettier] | @@ -164,9 +171,10 @@ It lists all TSLint rules along side rules from the ESLint ecosystem that are th | [`no-irregular-whitespace`] | 🌟 | [`no-irregular-whitespace`][no-irregular-whitespace] with `skipStrings: false` | | [`no-parameter-properties`] | βœ… | [`@typescript-eslint/no-parameter-properties`] | | [`no-redundant-jsdoc`] | πŸ”Œ | [`jsdoc/no-types`] | -| [`no-reference-import`] | πŸ›‘ | N/A | +| [`no-reference-import`] | βœ… | [`@typescript-eslint/triple-slash-reference`] | | [`no-trailing-whitespace`] | 🌟 | [`no-trailing-spaces`][no-trailing-spaces] | | [`no-unnecessary-callback-wrapper`] | πŸ›‘ | N/A and this might be unsafe (i.e. with `forEach`) | +| [`no-unnecessary-else`] | 🌟 | [`no-else-return`][no-else-return] [2][2] | +| [`variable-name`] | βœ… | [`@typescript-eslint/naming-convention`] | | [`whitespace`] | πŸ”Œ | Use [Prettier] | [1] Recommended config: `["error", { blankLine: "always", prev: "*", next: "return" }]`
-[2] [`camelcase`][camelcase], [`no-underscore-dangle`][no-underscore-dangle], [`id-blacklist`][id-blacklist], and/or [`id-match`][id-match] +[2] Doesn't check other control flow statements, such as `break` or `continue`. ## tslint-microsoft-contrib rules @@ -486,6 +494,7 @@ Relevant plugins: [`chai-expect-keywords`](https://github.com/gavinaiken/eslint- [no-magic-numbers]: https://eslint.org/docs/rules/no-magic-numbers [no-param-reassign]: https://eslint.org/docs/rules/no-param-reassign [no-sequences]: https://eslint.org/docs/rules/no-sequences +[no-restricted-globals]: https://eslint.org/docs/rules/no-restricted-globals [no-restricted-properties]: https://eslint.org/docs/rules/no-restricted-properties [no-restricted-syntax]: https://eslint.org/docs/rules/no-restricted-syntax [curly]: https://eslint.org/docs/rules/curly @@ -541,6 +550,7 @@ Relevant plugins: [`chai-expect-keywords`](https://github.com/gavinaiken/eslint- [padding-line-between-statements]: https://eslint.org/docs/rules/padding-line-between-statements [newline-per-chained-call]: https://eslint.org/docs/rules/newline-per-chained-call [new-parens]: https://eslint.org/docs/rules/new-parens +[no-else-return]: https://eslint.org/docs/rules/no-else-return [no-multiple-empty-lines]: https://eslint.org/docs/rules/no-multiple-empty-lines [no-irregular-whitespace]: https://eslint.org/docs/rules/no-irregular-whitespace [no-trailing-spaces]: https://eslint.org/docs/rules/no-trailing-spaces @@ -591,6 +601,7 @@ Relevant plugins: [`chai-expect-keywords`](https://github.com/gavinaiken/eslint- [`@typescript-eslint/no-inferrable-types`]: https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/no-inferrable-types.md [`@typescript-eslint/prefer-namespace-keyword`]: https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/prefer-namespace-keyword.md [`@typescript-eslint/promise-function-async`]: https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/promise-function-async.md +[`@typescript-eslint/no-misused-promises`]: https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/no-misused-promises.md [`@typescript-eslint/no-namespace`]: https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/no-namespace.md [`@typescript-eslint/no-non-null-assertion`]: https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/no-non-null-assertion.md [`@typescript-eslint/triple-slash-reference`]: https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/triple-slash-reference.md @@ -614,6 +625,7 @@ Relevant plugins: [`chai-expect-keywords`](https://github.com/gavinaiken/eslint- [`@typescript-eslint/array-type`]: https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/array-type.md [`@typescript-eslint/class-name-casing`]: https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/class-name-casing.md [`@typescript-eslint/interface-name-prefix`]: https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/interface-name-prefix.md +[`@typescript-eslint/naming-convention`]: https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/naming-convention.md [`@typescript-eslint/no-parameter-properties`]: https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/no-parameter-properties.md [`@typescript-eslint/member-delimiter-style`]: https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/member-delimiter-style.md [`@typescript-eslint/prefer-for-of`]: https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/prefer-for-of.md @@ -686,3 +698,4 @@ Relevant plugins: [`chai-expect-keywords`](https://github.com/gavinaiken/eslint- [`jest/no-focused-tests`]: https://github.com/jest-community/eslint-plugin-jest/blob/master/docs/rules/no-focused-tests.md [`jsx-a11y/heading-has-content`]: https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/heading-has-content.md [`lodash/chaining`]: https://github.com/wix/eslint-plugin-lodash/blob/master/docs/rules/chaining.md +[`deprecation/deprecation`]: https://github.com/gund/eslint-plugin-deprecation diff --git a/packages/eslint-plugin/docs/rules/no-floating-promises.md b/packages/eslint-plugin/docs/rules/no-floating-promises.md index c3f8f8c77a86..ffaa542f3f11 100644 --- a/packages/eslint-plugin/docs/rules/no-floating-promises.md +++ b/packages/eslint-plugin/docs/rules/no-floating-promises.md @@ -20,6 +20,8 @@ async function returnsPromise() { returnsPromise().then(() => {}); Promise.reject('value').catch(); + +Promise.reject('value').finally(); ``` Examples of **correct** code for this rule: @@ -37,6 +39,8 @@ returnsPromise().then( ); Promise.reject('value').catch(() => {}); + +Promise.reject('value').finally(() => {}); ``` ## Options diff --git a/packages/eslint-plugin/docs/rules/no-parameter-properties.md b/packages/eslint-plugin/docs/rules/no-parameter-properties.md index 86ebed8bc7fd..bb2fd2691967 100644 --- a/packages/eslint-plugin/docs/rules/no-parameter-properties.md +++ b/packages/eslint-plugin/docs/rules/no-parameter-properties.md @@ -13,7 +13,7 @@ declare all properties in the class. This rule, in its default state, does not require any argument and would completely disallow the use of parameter properties. If you would like to allow certain types of parameter properties then you may pass an object with the following options: -- `allows`, an array containing one or more fo the allowed modifiers. Valid values are: +- `allows`, an array containing one or more of the allowed modifiers. Valid values are: - `readonly`, allows **readonly** parameter properties. - `private`, allows **private** parameter properties. - `protected`, allows **protected** parameter properties. diff --git a/packages/eslint-plugin/docs/rules/typedef.md b/packages/eslint-plugin/docs/rules/typedef.md index eac8472d9462..17a57412bc22 100644 --- a/packages/eslint-plugin/docs/rules/typedef.md +++ b/packages/eslint-plugin/docs/rules/typedef.md @@ -76,6 +76,9 @@ Examples of **correct** code with `{ "arrayDestructuring": true }`: const [a]: number[] = [1]; const [b]: [number] = [2]; const [c, d]: [boolean, string] = [true, 'text']; + +for (const [key, val] of new Map([['key', 1]])) { +} ``` ### `arrowParameter` @@ -144,6 +147,9 @@ Examples of **correct** code with `{ "objectDestructuring": true }`: ```ts const { length }: { length: number } = 'text'; const [b, c]: [number, number] = Math.random() ? [1, 2] : [3, 4]; + +for (const { key, val } of [{ key: 'key', val: 1 }]) { +} ``` ### `parameter` diff --git a/packages/eslint-plugin/package.json b/packages/eslint-plugin/package.json index 098f3b39588c..595fab7aa6cb 100644 --- a/packages/eslint-plugin/package.json +++ b/packages/eslint-plugin/package.json @@ -1,6 +1,6 @@ { "name": "@typescript-eslint/eslint-plugin", - "version": "2.20.0", + "version": "2.21.0", "description": "TypeScript plugin for ESLint", "keywords": [ "eslint", @@ -41,7 +41,7 @@ "typecheck": "tsc -p tsconfig.json --noEmit" }, "dependencies": { - "@typescript-eslint/experimental-utils": "2.20.0", + "@typescript-eslint/experimental-utils": "2.21.0", "eslint-utils": "^1.4.3", "functional-red-black-tree": "^1.0.1", "regexpp": "^3.0.0", 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 f003977d8fb9..55c6bd29f99e 100644 --- a/packages/eslint-plugin/src/rules/explicit-module-boundary-types.ts +++ b/packages/eslint-plugin/src/rules/explicit-module-boundary-types.ts @@ -79,6 +79,10 @@ export default util.createRule({ return false; } + if (node.type === AST_NODE_TYPES.JSXExpressionContainer) { + return true; + } + if (node.type === AST_NODE_TYPES.ReturnStatement) { isReturnedValue = true; } diff --git a/packages/eslint-plugin/src/rules/no-floating-promises.ts b/packages/eslint-plugin/src/rules/no-floating-promises.ts index 466e29bbb9f6..c3ee7ffccf3c 100644 --- a/packages/eslint-plugin/src/rules/no-floating-promises.ts +++ b/packages/eslint-plugin/src/rules/no-floating-promises.ts @@ -114,7 +114,8 @@ export default util.createRule({ // `.catch()` that handles the promise. return ( !isPromiseCatchCallWithHandler(node) && - !isPromiseThenCallWithRejectionHandler(node) + !isPromiseThenCallWithRejectionHandler(node) && + !isPromiseFinallyCallWithHandler(node) ); } else if (ts.isConditionalExpression(node)) { // We must be getting the promise-like value from one of the branches of the @@ -216,3 +217,13 @@ function isPromiseThenCallWithRejectionHandler( expression.arguments.length >= 2 ); } + +function isPromiseFinallyCallWithHandler( + expression: ts.CallExpression, +): boolean { + return ( + tsutils.isPropertyAccessExpression(expression.expression) && + expression.expression.name.text === 'finally' && + expression.arguments.length >= 1 + ); +} diff --git a/packages/eslint-plugin/src/rules/return-await.ts b/packages/eslint-plugin/src/rules/return-await.ts index f77d80fe5d40..d18e41ef00e0 100644 --- a/packages/eslint-plugin/src/rules/return-await.ts +++ b/packages/eslint-plugin/src/rules/return-await.ts @@ -1,6 +1,7 @@ import { AST_NODE_TYPES, TSESTree, + TSESLint, } from '@typescript-eslint/experimental-utils'; import * as tsutils from 'tsutils'; import * as ts from 'typescript'; @@ -16,6 +17,7 @@ export default util.createRule({ requiresTypeChecking: true, extendsBaseRule: 'no-return-await', }, + fixable: 'code', type: 'problem', messages: { nonPromiseAwait: @@ -36,6 +38,7 @@ export default util.createRule({ create(context, [option]) { const parserServices = util.getParserServices(context); const checker = parserServices.program.getTypeChecker(); + const sourceCode = context.getSourceCode(); function inTryCatch(node: ts.Node): boolean { let ancestor = node.parent; @@ -54,13 +57,66 @@ export default util.createRule({ return false; } + // function findTokensToRemove() + + function removeAwait( + fixer: TSESLint.RuleFixer, + node: TSESTree.ReturnStatement | TSESTree.ArrowFunctionExpression, + ): TSESLint.RuleFix | null { + const awaitNode = + node.type === AST_NODE_TYPES.ReturnStatement + ? node.argument + : node.body; + // Should always be an await node; but let's be safe. + /* istanbul ignore if */ if (!util.isAwaitExpression(awaitNode)) { + return null; + } + + const awaitToken = sourceCode.getFirstToken( + awaitNode, + util.isAwaitKeyword, + ); + // Should always be the case; but let's be safe. + /* istanbul ignore if */ if (!awaitToken) { + return null; + } + + const startAt = awaitToken.range[0]; + let endAt = awaitToken.range[1]; + // Also remove any extraneous whitespace after `await`, if there is any. + const nextToken = sourceCode.getTokenAfter(awaitToken, { + includeComments: true, + }); + if (nextToken) { + endAt = nextToken.range[0]; + } + + return fixer.removeRange([startAt, endAt]); + } + + function insertAwait( + fixer: TSESLint.RuleFixer, + node: TSESTree.ReturnStatement | TSESTree.ArrowFunctionExpression, + ): TSESLint.RuleFix | null { + const targetNode = + node.type === AST_NODE_TYPES.ReturnStatement + ? node.argument + : node.body; + // There should always be a target node; but let's be safe. + /* istanbul ignore if */ if (!targetNode) { + return null; + } + + return fixer.insertTextBefore(targetNode, 'await '); + } + function test( node: TSESTree.ReturnStatement | TSESTree.ArrowFunctionExpression, expression: ts.Node, ): void { let child: ts.Node; - const isAwait = expression.kind === ts.SyntaxKind.AwaitExpression; + const isAwait = tsutils.isAwaitExpression(expression); if (isAwait) { child = expression.getChildAt(1); @@ -79,6 +135,7 @@ export default util.createRule({ context.report({ messageId: 'nonPromiseAwait', node, + fix: fixer => removeAwait(fixer, node), }); return; } @@ -88,6 +145,7 @@ export default util.createRule({ context.report({ messageId: 'requiredPromiseAwait', node, + fix: fixer => insertAwait(fixer, node), }); } @@ -99,6 +157,7 @@ export default util.createRule({ context.report({ messageId: 'disallowedPromiseAwait', node, + fix: fixer => removeAwait(fixer, node), }); } @@ -111,11 +170,13 @@ export default util.createRule({ context.report({ messageId: 'disallowedPromiseAwait', node, + fix: fixer => removeAwait(fixer, node), }); } else if (!isAwait && isInTryCatch) { context.report({ messageId: 'requiredPromiseAwait', node, + fix: fixer => insertAwait(fixer, node), }); } diff --git a/packages/eslint-plugin/src/rules/typedef.ts b/packages/eslint-plugin/src/rules/typedef.ts index 19c4244d9f99..dd7bcc29c61f 100644 --- a/packages/eslint-plugin/src/rules/typedef.ts +++ b/packages/eslint-plugin/src/rules/typedef.ts @@ -69,6 +69,31 @@ export default util.createRule<[Options], MessageIds>({ return node.type === AST_NODE_TYPES.Identifier ? node.name : undefined; } + function isForOfStatementContext( + node: TSESTree.ArrayPattern | TSESTree.ObjectPattern, + ): boolean { + let current: TSESTree.Node | undefined = node.parent; + while (current) { + switch (current.type) { + case AST_NODE_TYPES.VariableDeclarator: + case AST_NODE_TYPES.VariableDeclaration: + case AST_NODE_TYPES.ObjectPattern: + case AST_NODE_TYPES.ArrayPattern: + case AST_NODE_TYPES.Property: + current = current.parent; + break; + + case AST_NODE_TYPES.ForOfStatement: + return true; + + default: + current = undefined; + } + } + + return false; + } + function checkParameters(params: TSESTree.Parameter[]): void { for (const param of params) { let annotationNode: TSESTree.Node | undefined; @@ -102,7 +127,11 @@ export default util.createRule<[Options], MessageIds>({ return { ArrayPattern(node): void { - if (options[OptionKeys.ArrayDestructuring] && !node.typeAnnotation) { + if ( + options[OptionKeys.ArrayDestructuring] && + !node.typeAnnotation && + !isForOfStatementContext(node) + ) { report(node); } }, @@ -132,7 +161,11 @@ export default util.createRule<[Options], MessageIds>({ } }, ObjectPattern(node): void { - if (options[OptionKeys.ObjectDestructuring] && !node.typeAnnotation) { + if ( + options[OptionKeys.ObjectDestructuring] && + !node.typeAnnotation && + !isForOfStatementContext(node) + ) { report(node); } }, diff --git a/packages/eslint-plugin/src/util/astUtils.ts b/packages/eslint-plugin/src/util/astUtils.ts index 367bd93350bb..29dcdc0b459f 100644 --- a/packages/eslint-plugin/src/util/astUtils.ts +++ b/packages/eslint-plugin/src/util/astUtils.ts @@ -114,7 +114,27 @@ function isIdentifier( return node?.type === AST_NODE_TYPES.Identifier; } +/** + * Checks if a node represents an `await …` expression. + */ +function isAwaitExpression( + node: TSESTree.Node | undefined | null, +): node is TSESTree.AwaitExpression { + return node?.type === AST_NODE_TYPES.AwaitExpression; +} + +/** + * Checks if a possible token is the `await` keyword. + */ +function isAwaitKeyword( + node: TSESTree.Token | TSESTree.Comment | undefined | null, +): node is TSESTree.KeywordToken & { value: 'await' } { + return node?.type === AST_TOKEN_TYPES.Identifier && node.value === 'await'; +} + export { + isAwaitExpression, + isAwaitKeyword, isConstructor, isIdentifier, isLogicalOrOperator, diff --git a/packages/eslint-plugin/tests/rules/explicit-module-boundary-types.test.ts b/packages/eslint-plugin/tests/rules/explicit-module-boundary-types.test.ts index 20a9f14a57e8..388adb994315 100644 --- a/packages/eslint-plugin/tests/rules/explicit-module-boundary-types.test.ts +++ b/packages/eslint-plugin/tests/rules/explicit-module-boundary-types.test.ts @@ -312,6 +312,35 @@ export class Test { }, ], }, + { + code: ` +export const Foo: FC = () => ( +
{}} + b={function (e) {}} + c={function foo(e) {}} + > +
+) + `, + parserOptions: { + ecmaFeatures: { jsx: true }, + }, + }, + { + code: ` +export const Foo: JSX.Element = +
{}} + b={function (e) {}} + c={function foo(e) {}} + > +
+ `, + parserOptions: { + ecmaFeatures: { jsx: true }, + }, + }, ], invalid: [ { diff --git a/packages/eslint-plugin/tests/rules/no-floating-promises.test.ts b/packages/eslint-plugin/tests/rules/no-floating-promises.test.ts index a6fcf7777542..efdbf5e1a48c 100644 --- a/packages/eslint-plugin/tests/rules/no-floating-promises.test.ts +++ b/packages/eslint-plugin/tests/rules/no-floating-promises.test.ts @@ -19,7 +19,9 @@ async function test() { await Promise.resolve("value"); Promise.resolve("value").then(() => {}, () => {}); Promise.resolve("value").then(() => {}).catch(() => {}); + Promise.resolve("value").then(() => {}).catch(() => {}).finally(() => {}); Promise.resolve("value").catch(() => {}); + Promise.resolve("value").finally(() => {}); return Promise.resolve("value"); } `, @@ -36,7 +38,9 @@ async function test() { await Promise.reject(new Error("message")); Promise.reject(new Error("message")).then(() => {}, () => {}); Promise.reject(new Error("message")).then(() => {}).catch(() => {}); + Promise.reject(new Error("message")).then(() => {}).catch(() => {}).finally(() => {}); Promise.reject(new Error("message")).catch(() => {}); + Promise.reject(new Error("message")).finally(() => {}); return Promise.reject(new Error("message")); } `, @@ -45,7 +49,9 @@ async function test() { await (async () => true)(); (async () => true)().then(() => {}, () => {}); (async () => true)().then(() => {}).catch(() => {}); + (async () => true)().then(() => {}).catch(() => {}).finally(() => {}); (async () => true)().catch(() => {}); + (async () => true)().finally(() => {}); return (async () => true)(); } `, @@ -55,7 +61,9 @@ async function test() { await returnsPromise(); returnsPromise().then(() => {}, () => {}); returnsPromise().then(() => {}).catch(() => {}); + returnsPromise().then(() => {}).catch(() => {}).finally(() => {}); returnsPromise().catch(() => {}); + returnsPromise().finally(() => {}); return returnsPromise(); } `, @@ -64,6 +72,7 @@ async function test() { const x = Promise.resolve(); const y = x.then(() => {}); y.catch(() => {}); + y.finally(() => {}); } `, ` @@ -74,6 +83,7 @@ async function test() { ` async function test() { Promise.resolve().catch(() => {}), 123; + Promise.resolve().finally(() => {}), 123; 123, Promise.resolve().then(() => {}, () => {}); 123, Promise.resolve().then(() => {}, () => {}), 123; } @@ -95,7 +105,9 @@ async function test() { await promiseValue; promiseValue.then(() => {}, () => {}); promiseValue.then(() => {}).catch(() => {}); + promiseValue.then(() => {}).catch(() => {}).finally(() => {}); promiseValue.catch(() => {}); + promiseValue.finally(() => {}); return promiseValue; } `, @@ -106,7 +118,9 @@ async function test() { await promiseUnion; promiseUnion.then(() => {}, () => {}); promiseUnion.then(() => {}).catch(() => {}); + promiseUnion.then(() => {}).catch(() => {}).finally(() => {}); promiseUnion.catch(() => {}); + promiseValue.finally(() => {}); return promiseUnion; } `, @@ -117,7 +131,9 @@ async function test() { await promiseIntersection; promiseIntersection.then(() => {}, () => {}); promiseIntersection.then(() => {}).catch(() => {}); + promiseIntersection.then(() => {}).catch(() => {}).finally(() => {}); promiseIntersection.catch(() => {}); + promiseIntersection.finally(() => {}); return promiseIntersection; } `, @@ -129,7 +145,9 @@ async function test() { await canThen; canThen.then(() => {}, () => {}); canThen.then(() => {}).catch(() => {}); + canThen.then(() => {}).catch(() => {}).finally(() => {}); canThen.catch(() => {}); + canThen.finally(() => {}); return canThen; } `, @@ -214,7 +232,9 @@ async function test() { await promise; promise.then(() => {}, () => {}); promise.then(() => {}).catch(() => {}); + promise.then(() => {}).catch(() => {}).finally(() => {}); promise.catch(() => {}); + promise.finally(() => {}); return promise; } `, @@ -227,6 +247,7 @@ async function test() { returnsPromise()?.then(() => {}, () => {}); returnsPromise()?.then(() => {})?.catch(() => {}); returnsPromise()?.catch(() => {}); + returnsPromise()?.finally(() => {}); return returnsPromise(); } `, @@ -239,6 +260,7 @@ async function test() { Promise.resolve("value"); Promise.resolve("value").then(() => {}); Promise.resolve("value").catch(); + Promise.resolve("value").finally(); } `, errors: [ @@ -254,6 +276,10 @@ async function test() { line: 5, messageId: 'floating', }, + { + line: 6, + messageId: 'floating', + }, ], }, { @@ -286,6 +312,7 @@ async function test() { Promise.reject(new Error("message")); Promise.reject(new Error("message")).then(() => {}); Promise.reject(new Error("message")).catch(); + Promise.reject(new Error("message")).finally(); } `, errors: [ @@ -301,6 +328,10 @@ async function test() { line: 5, messageId: 'floating', }, + { + line: 6, + messageId: 'floating', + }, ], }, { @@ -309,6 +340,7 @@ async function test() { (async () => true)(); (async () => true)().then(() => {}); (async () => true)().catch(); + (async () => true)().finally(); } `, errors: [ @@ -324,6 +356,10 @@ async function test() { line: 5, messageId: 'floating', }, + { + line: 6, + messageId: 'floating', + }, ], }, { @@ -334,6 +370,7 @@ async function test() { returnsPromise(); returnsPromise().then(() => {}); returnsPromise().catch(); + returnsPromise().finally(); } `, errors: [ @@ -349,6 +386,10 @@ async function test() { line: 7, messageId: 'floating', }, + { + line: 8, + messageId: 'floating', + }, ], }, { @@ -440,6 +481,7 @@ async function test() { promiseValue; promiseValue.then(() => {}); promiseValue.catch(); + promiseValue.finally(); } `, errors: [ @@ -455,6 +497,10 @@ async function test() { line: 7, messageId: 'floating', }, + { + line: 8, + messageId: 'floating', + }, ], }, { @@ -480,6 +526,7 @@ async function test() { promiseIntersection; promiseIntersection.then(() => {}) promiseIntersection.catch(); + promiseIntersection.finally(); } `, errors: [ @@ -495,6 +542,10 @@ async function test() { line: 7, messageId: 'floating', }, + { + line: 8, + messageId: 'floating', + }, ], }, { @@ -506,6 +557,7 @@ async function test() { canThen; canThen.then(() => {}); canThen.catch(); + canThen.finally(); } `, errors: [ @@ -521,6 +573,10 @@ async function test() { line: 8, messageId: 'floating', }, + { + line: 9, + messageId: 'floating', + }, ], }, { diff --git a/packages/eslint-plugin/tests/rules/return-await.test.ts b/packages/eslint-plugin/tests/rules/return-await.test.ts index fc5f2597ebf4..8599a937e198 100644 --- a/packages/eslint-plugin/tests/rules/return-await.test.ts +++ b/packages/eslint-plugin/tests/rules/return-await.test.ts @@ -164,6 +164,9 @@ ruleTester.run('return-await', rule, { code: `async function test() { return await 1; }`, + output: `async function test() { + return 1; + }`, errors: [ { line: 2, @@ -171,8 +174,52 @@ ruleTester.run('return-await', rule, { }, ], }, + { + code: `async function test() { + const foo = 1; + return await{foo}; + }`, + output: `async function test() { + const foo = 1; + return {foo}; + }`, + errors: [ + { + line: 3, + messageId: 'nonPromiseAwait', + }, + ], + }, + { + code: `async function test() { + const foo = 1; + return await + foo; + }`, + output: `async function test() { + const foo = 1; + return foo; + }`, + errors: [ + { + line: 3, + messageId: 'nonPromiseAwait', + }, + ], + }, { code: `const test = async () => await 1;`, + output: `const test = async () => 1;`, + errors: [ + { + line: 1, + messageId: 'nonPromiseAwait', + }, + ], + }, + { + code: `const test = async () => await/* comment */1;`, + output: `const test = async () => /* comment */1;`, errors: [ { line: 1, @@ -182,6 +229,7 @@ ruleTester.run('return-await', rule, { }, { code: `const test = async () => await Promise.resolve(1);`, + output: `const test = async () => Promise.resolve(1);`, errors: [ { line: 1, @@ -199,6 +247,15 @@ ruleTester.run('return-await', rule, { console.log('cleanup'); } }`, + output: `async function test() { + try { + return await Promise.resolve(1); + } catch (e) { + return await Promise.resolve(2); + } finally { + console.log('cleanup'); + } + }`, errors: [ { line: 3, @@ -214,6 +271,9 @@ ruleTester.run('return-await', rule, { code: `async function test() { return await Promise.resolve(1); }`, + output: `async function test() { + return Promise.resolve(1); + }`, errors: [ { line: 2, @@ -226,6 +286,9 @@ ruleTester.run('return-await', rule, { code: `async function test() { return await 1; }`, + output: `async function test() { + return 1; + }`, errors: [ { line: 2, @@ -236,6 +299,7 @@ ruleTester.run('return-await', rule, { { options: ['in-try-catch'], code: `const test = async () => await 1;`, + output: `const test = async () => 1;`, errors: [ { line: 1, @@ -246,6 +310,7 @@ ruleTester.run('return-await', rule, { { options: ['in-try-catch'], code: `const test = async () => await Promise.resolve(1);`, + output: `const test = async () => Promise.resolve(1);`, errors: [ { line: 1, @@ -264,6 +329,15 @@ ruleTester.run('return-await', rule, { console.log('cleanup'); } }`, + output: `async function test() { + try { + return await Promise.resolve(1); + } catch (e) { + return await Promise.resolve(2); + } finally { + console.log('cleanup'); + } + }`, errors: [ { line: 3, @@ -280,6 +354,9 @@ ruleTester.run('return-await', rule, { code: `async function test() { return await Promise.resolve(1); }`, + output: `async function test() { + return Promise.resolve(1); + }`, errors: [ { line: 2, @@ -292,6 +369,9 @@ ruleTester.run('return-await', rule, { code: `async function test() { return await 1; }`, + output: `async function test() { + return 1; + }`, errors: [ { line: 2, @@ -310,6 +390,15 @@ ruleTester.run('return-await', rule, { console.log('cleanup'); } }`, + output: `async function test() { + try { + return Promise.resolve(1); + } catch (e) { + return Promise.resolve(2); + } finally { + console.log('cleanup'); + } + }`, errors: [ { line: 3, @@ -326,6 +415,9 @@ ruleTester.run('return-await', rule, { code: `async function test() { return await Promise.resolve(1); }`, + output: `async function test() { + return Promise.resolve(1); + }`, errors: [ { line: 2, @@ -338,6 +430,9 @@ ruleTester.run('return-await', rule, { code: `async function test() { return await 1; }`, + output: `async function test() { + return 1; + }`, errors: [ { line: 2, @@ -356,6 +451,15 @@ ruleTester.run('return-await', rule, { console.log('cleanup'); } }`, + output: `async function test() { + try { + return await Promise.resolve(1); + } catch (e) { + return await Promise.resolve(2); + } finally { + console.log('cleanup'); + } + }`, errors: [ { line: 3, @@ -372,6 +476,9 @@ ruleTester.run('return-await', rule, { code: `async function test() { return Promise.resolve(1); }`, + output: `async function test() { + return await Promise.resolve(1); + }`, errors: [ { line: 2, diff --git a/packages/eslint-plugin/tests/rules/typedef.test.ts b/packages/eslint-plugin/tests/rules/typedef.test.ts index c9e35c356eb2..679ed1a8a519 100644 --- a/packages/eslint-plugin/tests/rules/typedef.test.ts +++ b/packages/eslint-plugin/tests/rules/typedef.test.ts @@ -38,6 +38,30 @@ ruleTester.run('typedef', rule, { }, ], }, + { + code: `for (const [key, val] of new Map([['key', 1]])) {}`, + options: [ + { + arrayDestructuring: true, + }, + ], + }, + { + code: `for (const [[key]] of [[['key']]]) {}`, + options: [ + { + arrayDestructuring: true, + }, + ], + }, + { + code: `for (const [[{ key }]] of [[[{ key: 'value' }]]]) {}`, + options: [ + { + arrayDestructuring: true, + }, + ], + }, `let a: number; [a] = [1];`, // Arrow parameters @@ -93,6 +117,22 @@ ruleTester.run('typedef', rule, { }, ], }, + { + code: `for (const {p1: {p2: { p3 }}} of [{p1: {p2: {p3: 'value'}}}]) {}`, + options: [ + { + objectDestructuring: true, + }, + ], + }, + { + code: `for (const {p1: {p2: { p3: [key] }}} of [{p1: {p2: {p3: ['value']}}}]) {}`, + options: [ + { + objectDestructuring: true, + }, + ], + }, { code: `const { a } = { a: 1 };`, options: [ @@ -101,6 +141,14 @@ ruleTester.run('typedef', rule, { }, ], }, + { + code: `for (const { key, val } of [{ key: 'key', val: 1 }]) {}`, + options: [ + { + objectDestructuring: true, + }, + ], + }, // Function parameters `function receivesNumber(a: number): void { }`, `function receivesStrings(a: string, b: string): void { }`, diff --git a/packages/experimental-utils/CHANGELOG.md b/packages/experimental-utils/CHANGELOG.md index e85cdffc4b2c..6ed1898fe0ba 100644 --- a/packages/experimental-utils/CHANGELOG.md +++ b/packages/experimental-utils/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [2.21.0](https://github.com/typescript-eslint/typescript-eslint/compare/v2.20.0...v2.21.0) (2020-02-24) + +**Note:** Version bump only for package @typescript-eslint/experimental-utils + + + + + # [2.20.0](https://github.com/typescript-eslint/typescript-eslint/compare/v2.19.2...v2.20.0) (2020-02-17) **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 31eccbf1f64f..927154687061 100644 --- a/packages/experimental-utils/package.json +++ b/packages/experimental-utils/package.json @@ -1,6 +1,6 @@ { "name": "@typescript-eslint/experimental-utils", - "version": "2.20.0", + "version": "2.21.0", "description": "(Experimental) Utilities for working with TypeScript + ESLint together", "keywords": [ "eslint", @@ -37,7 +37,7 @@ }, "dependencies": { "@types/json-schema": "^7.0.3", - "@typescript-eslint/typescript-estree": "2.20.0", + "@typescript-eslint/typescript-estree": "2.21.0", "eslint-scope": "^5.0.0" }, "peerDependencies": { diff --git a/packages/parser/CHANGELOG.md b/packages/parser/CHANGELOG.md index 0a89b836d18a..039e2d78eda6 100644 --- a/packages/parser/CHANGELOG.md +++ b/packages/parser/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [2.21.0](https://github.com/typescript-eslint/typescript-eslint/compare/v2.20.0...v2.21.0) (2020-02-24) + +**Note:** Version bump only for package @typescript-eslint/parser + + + + + # [2.20.0](https://github.com/typescript-eslint/typescript-eslint/compare/v2.19.2...v2.20.0) (2020-02-17) **Note:** Version bump only for package @typescript-eslint/parser diff --git a/packages/parser/package.json b/packages/parser/package.json index 17ac2bae6c0e..13918ec8784d 100644 --- a/packages/parser/package.json +++ b/packages/parser/package.json @@ -1,6 +1,6 @@ { "name": "@typescript-eslint/parser", - "version": "2.20.0", + "version": "2.21.0", "description": "An ESLint custom parser which leverages TypeScript ESTree", "main": "dist/parser.js", "types": "dist/parser.d.ts", @@ -43,13 +43,13 @@ }, "dependencies": { "@types/eslint-visitor-keys": "^1.0.0", - "@typescript-eslint/experimental-utils": "2.20.0", - "@typescript-eslint/typescript-estree": "2.20.0", + "@typescript-eslint/experimental-utils": "2.21.0", + "@typescript-eslint/typescript-estree": "2.21.0", "eslint-visitor-keys": "^1.1.0" }, "devDependencies": { "@types/glob": "^7.1.1", - "@typescript-eslint/shared-fixtures": "2.20.0", + "@typescript-eslint/shared-fixtures": "2.21.0", "glob": "*" }, "peerDependenciesMeta": { diff --git a/packages/shared-fixtures/CHANGELOG.md b/packages/shared-fixtures/CHANGELOG.md index 4bc15b28871c..5eef3db60f0f 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. +# [2.21.0](https://github.com/typescript-eslint/typescript-eslint/compare/v2.20.0...v2.21.0) (2020-02-24) + +**Note:** Version bump only for package @typescript-eslint/shared-fixtures + + + + + # [2.20.0](https://github.com/typescript-eslint/typescript-eslint/compare/v2.19.2...v2.20.0) (2020-02-17) **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 f955ffcc367f..8b9f8ebf381d 100644 --- a/packages/shared-fixtures/package.json +++ b/packages/shared-fixtures/package.json @@ -1,6 +1,6 @@ { "name": "@typescript-eslint/shared-fixtures", - "version": "2.20.0", + "version": "2.21.0", "private": true, "scripts": { "build": "tsc -b tsconfig.build.json", diff --git a/packages/typescript-estree/CHANGELOG.md b/packages/typescript-estree/CHANGELOG.md index bcd32357a487..681a0d9a72a3 100644 --- a/packages/typescript-estree/CHANGELOG.md +++ b/packages/typescript-estree/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. +# [2.21.0](https://github.com/typescript-eslint/typescript-eslint/compare/v2.20.0...v2.21.0) (2020-02-24) + + +### Bug Fixes + +* **typescript-estree:** process.stdout can be undefined ([#1619](https://github.com/typescript-eslint/typescript-eslint/issues/1619)) ([0d8e87e](https://github.com/typescript-eslint/typescript-eslint/commit/0d8e87e09704588273bc94a740279b3e8af7474f)) + + + + + # [2.20.0](https://github.com/typescript-eslint/typescript-eslint/compare/v2.19.2...v2.20.0) (2020-02-17) **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 894aa7565a21..a9697fc59cad 100644 --- a/packages/typescript-estree/package.json +++ b/packages/typescript-estree/package.json @@ -1,6 +1,6 @@ { "name": "@typescript-eslint/typescript-estree", - "version": "2.20.0", + "version": "2.21.0", "description": "A parser that converts TypeScript source code into an ESTree compatible form", "main": "dist/parser.js", "types": "dist/parser.d.ts", @@ -58,7 +58,7 @@ "@types/lodash": "^4.14.149", "@types/semver": "^6.2.0", "@types/tmp": "^0.1.0", - "@typescript-eslint/shared-fixtures": "2.20.0", + "@typescript-eslint/shared-fixtures": "2.21.0", "tmp": "^0.1.0", "typescript": "*" }, diff --git a/packages/typescript-estree/src/parser.ts b/packages/typescript-estree/src/parser.ts index 6142efaf1af2..b5e75d155595 100644 --- a/packages/typescript-estree/src/parser.ts +++ b/packages/typescript-estree/src/parser.ts @@ -261,7 +261,7 @@ function applyParserOptionsToExtra(options: TSESTreeOptions): void { function warnAboutTSVersion(): void { if (!isRunningSupportedTypeScriptVersion && !warnedAboutTSVersion) { - const isTTY = typeof process === undefined ? false : process.stdout.isTTY; + const isTTY = typeof process === undefined ? false : process.stdout?.isTTY; if (isTTY) { const border = '============='; const versionWarning = [