diff --git a/.all-contributorsrc b/.all-contributorsrc index bdd6f75d8c99..55cf18e201b1 100644 --- a/.all-contributorsrc +++ b/.all-contributorsrc @@ -16,6 +16,13 @@ "profile": "https://github.com/JamesHenry", "contributions": [] }, + { + "login": "bradzacher", + "name": "Brad Zacher", + "avatar_url": "https://avatars1.githubusercontent.com/u/7462525?v=4", + "profile": "https://github.com/bradzacher", + "contributions": [] + }, { "login": "armano2", "name": "Armano", @@ -24,10 +31,10 @@ "contributions": [] }, { - "login": "bradzacher", - "name": "Brad Zacher", - "avatar_url": "https://avatars1.githubusercontent.com/u/7462525?v=4", - "profile": "https://github.com/bradzacher", + "login": "a-tarasyuk", + "name": "Alexander T.", + "avatar_url": "https://avatars0.githubusercontent.com/u/509265?v=4", + "profile": "https://github.com/a-tarasyuk", "contributions": [] }, { @@ -44,6 +51,13 @@ "profile": "https://github.com/weirdpattern", "contributions": [] }, + { + "login": "G-Rath", + "name": "Gareth Jones", + "avatar_url": "https://avatars2.githubusercontent.com/u/3151613?v=4", + "profile": "https://github.com/G-Rath", + "contributions": [] + }, { "login": "nzakas", "name": "Nicholas C. Zakas", @@ -58,13 +72,6 @@ "profile": "https://github.com/j-f1", "contributions": [] }, - { - "login": "a-tarasyuk", - "name": "Alexander T.", - "avatar_url": "https://avatars0.githubusercontent.com/u/509265?v=4", - "profile": "https://github.com/a-tarasyuk", - "contributions": [] - }, { "login": "uniqueiniquity", "name": "Ben Lichtman", @@ -72,6 +79,13 @@ "profile": "https://github.com/uniqueiniquity", "contributions": [] }, + { + "login": "JoshuaKGoldberg", + "name": "Josh Goldberg", + "avatar_url": "https://avatars1.githubusercontent.com/u/3335181?v=4", + "profile": "https://github.com/JoshuaKGoldberg", + "contributions": [] + }, { "login": "scottohara", "name": "Scott O'Hara", @@ -80,10 +94,10 @@ "contributions": [] }, { - "login": "JoshuaKGoldberg", - "name": "Josh Goldberg", - "avatar_url": "https://avatars1.githubusercontent.com/u/3335181?v=4", - "profile": "https://github.com/JoshuaKGoldberg", + "login": "Retsam", + "name": "Retsam", + "avatar_url": "https://avatars0.githubusercontent.com/u/2281166?v=4", + "profile": "https://github.com/Retsam", "contributions": [] }, { @@ -114,6 +128,13 @@ "profile": "https://github.com/azz", "contributions": [] }, + { + "login": "yeonjuan", + "name": "YeonJuan", + "avatar_url": "https://avatars3.githubusercontent.com/u/41323220?v=4", + "profile": "https://github.com/yeonjuan", + "contributions": [] + }, { "login": "dannyfritz", "name": "Danny Fritz", @@ -135,6 +156,13 @@ "profile": "https://github.com/macklinu", "contributions": [] }, + { + "login": "phaux", + "name": "Nikita Stefaniak", + "avatar_url": "https://avatars1.githubusercontent.com/u/1270987?v=4", + "profile": "https://github.com/phaux", + "contributions": [] + }, { "login": "lukyth", "name": "Kanitkorn Sujautra", @@ -142,6 +170,13 @@ "profile": "https://github.com/lukyth", "contributions": [] }, + { + "login": "anikethsaha", + "name": "Anix", + "avatar_url": "https://avatars1.githubusercontent.com/u/26347874?v=4", + "profile": "https://github.com/anikethsaha", + "contributions": [] + }, { "login": "ldrick", "name": "Ricky Lippmann", @@ -156,6 +191,13 @@ "profile": "https://github.com/SimenB", "contributions": [] }, + { + "login": "vapurrmaid", + "name": "G r e y", + "avatar_url": "https://avatars0.githubusercontent.com/u/11184711?v=4", + "profile": "https://github.com/vapurrmaid", + "contributions": [] + }, { "login": "gavinbarron", "name": "Gavin Barron", @@ -177,6 +219,20 @@ "profile": "https://github.com/duailibe", "contributions": [] }, + { + "login": "Validark", + "name": "Niles", + "avatar_url": "https://avatars2.githubusercontent.com/u/15217173?v=4", + "profile": "https://github.com/Validark", + "contributions": [] + }, + { + "login": "pablobirukov", + "name": "Pavel Birukov ", + "avatar_url": "https://avatars2.githubusercontent.com/u/1861546?v=4", + "profile": "https://github.com/pablobirukov", + "contributions": [] + }, { "login": "octogonz", "name": "Pete Gonzalez", @@ -184,13 +240,6 @@ "profile": "https://github.com/octogonz", "contributions": [] }, - { - "login": "Retsam", - "name": "Retsam", - "avatar_url": "https://avatars0.githubusercontent.com/u/2281166?v=4", - "profile": "https://github.com/Retsam", - "contributions": [] - }, { "login": "mightyiam", "name": "Shahar Dawn Or", @@ -198,6 +247,20 @@ "profile": "https://github.com/mightyiam", "contributions": [] }, + { + "login": "sosukesuzuki", + "name": "Sosuke Suzuki", + "avatar_url": "https://avatars1.githubusercontent.com/u/14838850?v=4", + "profile": "https://github.com/sosukesuzuki", + "contributions": [] + }, + { + "login": "ulrichb", + "name": "ulrichb", + "avatar_url": "https://avatars3.githubusercontent.com/u/388796?v=4", + "profile": "https://github.com/ulrichb", + "contributions": [] + }, { "login": "webschik", "name": "Denys Kniazevych", @@ -206,17 +269,24 @@ "contributions": [] }, { - "login": "Validark", - "name": "Niles", - "avatar_url": "https://avatars2.githubusercontent.com/u/15217173?v=4", - "profile": "https://github.com/Validark", + "login": "dimitropoulos", + "name": "Dimitri Mitropoulos", + "avatar_url": "https://avatars2.githubusercontent.com/u/15232461?v=4", + "profile": "https://github.com/dimitropoulos", "contributions": [] }, { - "login": "pablobirukov", - "name": "Pavel Birukov ", - "avatar_url": "https://avatars2.githubusercontent.com/u/1861546?v=4", - "profile": "https://github.com/pablobirukov", + "login": "nevir", + "name": "Ian MacLeod", + "avatar_url": "https://avatars1.githubusercontent.com/u/41373?v=4", + "profile": "https://github.com/nevir", + "contributions": [] + }, + { + "login": "jonathanrdelgado", + "name": "Jonathan Delgado", + "avatar_url": "https://avatars2.githubusercontent.com/u/1841149?v=4", + "profile": "https://github.com/jonathanrdelgado", "contributions": [] }, { @@ -233,6 +303,13 @@ "profile": "https://github.com/g-plane", "contributions": [] }, + { + "login": "susisu", + "name": "Susisu", + "avatar_url": "https://avatars0.githubusercontent.com/u/2443491?v=4", + "profile": "https://github.com/susisu", + "contributions": [] + }, { "login": "ThomasdenH", "name": "Thomas den Hollander", @@ -240,12 +317,26 @@ "profile": "https://github.com/ThomasdenH", "contributions": [] }, + { + "login": "timkraut", + "name": "Tim Kraut", + "avatar_url": "https://avatars2.githubusercontent.com/u/509669?v=4", + "profile": "https://github.com/timkraut", + "contributions": [] + }, { "login": "madbence", "name": "Bence Dányi", "avatar_url": "https://avatars2.githubusercontent.com/u/296735?v=4", "profile": "https://github.com/madbence", "contributions": [] + }, + { + "login": "dependabot[bot]", + "name": "dependabot[bot]", + "avatar_url": "https://avatars0.githubusercontent.com/in/29110?v=4", + "profile": "https://github.com/apps/dependabot", + "contributions": [] } ], "contributorsPerLine": 5 diff --git a/.eslintrc.js b/.eslintrc.js index 8b4cfa2db36a..2c69c6ecfedf 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -32,6 +32,16 @@ module.exports = { // our plugin :D // + '@typescript-eslint/ban-ts-comment': [ + 'error', + { + 'ts-expect-error': 'allow-with-description', + 'ts-ignore': true, + 'ts-nocheck': true, + 'ts-check': false, + minimumDescriptionLength: 5, + }, + ], '@typescript-eslint/consistent-type-definitions': ['error', 'interface'], '@typescript-eslint/explicit-function-return-type': 'error', '@typescript-eslint/explicit-module-boundary-types': 'off', diff --git a/CHANGELOG.md b/CHANGELOG.md index 19e2f00eaf38..e2500151a516 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,26 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [3.4.0](https://github.com/typescript-eslint/typescript-eslint/compare/v3.3.0...v3.4.0) (2020-06-22) + + +### Bug Fixes + +* **eslint-plugin:** [no-base-to-string] handle intersection types ([#2170](https://github.com/typescript-eslint/typescript-eslint/issues/2170)) ([9cca3a9](https://github.com/typescript-eslint/typescript-eslint/commit/9cca3a9584d5d5ef0536219c5a734f4e87efb543)) +* **eslint-plugin:** [unbound-method] handling destructuring ([#2228](https://github.com/typescript-eslint/typescript-eslint/issues/2228)) ([c3753c2](https://github.com/typescript-eslint/typescript-eslint/commit/c3753c21768d355ecdb9e7ae8e0bfdfbbc1d3bbe)) +* **experimental-utils:** correct types for TS versions older than 3.8 ([#2217](https://github.com/typescript-eslint/typescript-eslint/issues/2217)) ([5e4dda2](https://github.com/typescript-eslint/typescript-eslint/commit/5e4dda264a7d6a6a1626848e7599faea1ac34922)) +* **experimental-utils:** getParserServices takes a readonly context ([#2235](https://github.com/typescript-eslint/typescript-eslint/issues/2235)) ([26da8de](https://github.com/typescript-eslint/typescript-eslint/commit/26da8de7fcde9eddec63212d79af781c4bb22991)) + + +### Features + +* **eslint-plugin:** [no-unnecessary-boolean-literal-compare] add option to check nullable booleans ([#1983](https://github.com/typescript-eslint/typescript-eslint/issues/1983)) ([c0b3057](https://github.com/typescript-eslint/typescript-eslint/commit/c0b3057b7f7d515891ad2efe32e4ef8c01e0478f)) +* **eslint-plugin:** add extension rule `no-loss-of-precision` ([#2196](https://github.com/typescript-eslint/typescript-eslint/issues/2196)) ([535b0f2](https://github.com/typescript-eslint/typescript-eslint/commit/535b0f2ddd82efa6a2c40307a61c480f4b3cdea3)) + + + + + # [3.3.0](https://github.com/typescript-eslint/typescript-eslint/compare/v3.2.0...v3.3.0) (2020-06-15) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 9cd07ba705b6..c8a732fc417b 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -4,11 +4,16 @@ Feel free to raise an issue if you have a question, an enhancement, or a bug report. -Please ensure you use the issue search functionality to search all **_opened and closed_** issues before raising a new issue. +Use the issue search functionality to search all **_opened and closed_** issues before raising a new issue. If you raise a duplicate issue, you're just creating noise for everyone watching this repo. + +Before raising a bug, ensure you are using the latest version of our packages. We release every week, so there's a good chance your issue might have already been fixed. + +Finally, when raising a new issue, please fill out the issue template - **_please don't skip sections_**. -When raising a new issue, please fill out the issue template - please don't skip sections. Please provide **_as much information as possible_**. This project is maintained by volunteers, so the more the more information you provide, the less likely we will have to waste everyone's time in asking you for more information. +If you have a particularly complex issue - consider creating a small, self-contained reproduction repo. This will help you in figuring out the exact problem, and will help us in reproducing and diagnosing the bug. + **_Help us to help you_** ## Commenting diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md index 04023618bf81..23094e083494 100644 --- a/CONTRIBUTORS.md +++ b/CONTRIBUTORS.md @@ -7,52 +7,70 @@ Thanks goes to these wonderful people ([emoji key](https://github.com/all-contri - - - - - + + + + + - - - - - + + + + + - - - - - + + + + + - - - - - + + + + + - - - - - + + + + + - - - - - + + + + + - - - - + + + + + + + + + + + + + + + + + + + + + +
James Henry
James Henry

Armano
Armano

Brad Zacher
Brad Zacher

Reyad Attiyat
Reyad Attiyat

Patricio Trevino
Patricio Trevino


James Henry


Brad Zacher


Armano


Alexander T.


Reyad Attiyat

Nicholas C. Zakas
Nicholas C. Zakas

Jed Fox
Jed Fox

Alexander T.
Alexander T.

Ben Lichtman
Ben Lichtman

Scott O'Hara
Scott O'Hara


Patricio Trevino


Gareth Jones


Nicholas C. Zakas


Jed Fox


Ben Lichtman

Josh Goldberg
Josh Goldberg

Kai Cataldo
Kai Cataldo

Rasmus Eneman
Rasmus Eneman

Toru Nagashima
Toru Nagashima

Lucas Azzola
Lucas Azzola


Josh Goldberg


Scott O'Hara


Retsam


Kai Cataldo


Rasmus Eneman

Danny Fritz
Danny Fritz

Ika
Ika

mackie
mackie

Kanitkorn Sujautra
Kanitkorn Sujautra

Ricky Lippmann
Ricky Lippmann


Toru Nagashima


Lucas Azzola


YeonJuan


Danny Fritz


Ika

Simen Bekkhus
Simen Bekkhus

Gavin Barron
Gavin Barron

Kevin Partington
Kevin Partington

Lucas Duailibe
Lucas Duailibe

Pete Gonzalez
Pete Gonzalez


mackie


Nikita Stefaniak


Kanitkorn Sujautra


Anix


Ricky Lippmann

Retsam
Retsam

Shahar Dawn Or
Shahar Dawn Or

Denys Kniazevych
Denys Kniazevych

Niles
Niles

Pavel Birukov
Pavel Birukov


Simen Bekkhus


G r e y


Gavin Barron


Kevin Partington


Lucas Duailibe

Philipp A.
Philipp A.

Pig Fang
Pig Fang

Thomas den Hollander
Thomas den Hollander

Bence Dányi
Bence Dányi


Niles


Pavel Birukov


Pete Gonzalez


Shahar Dawn Or


Sosuke Suzuki


ulrichb


Denys Kniazevych


Dimitri Mitropoulos


Ian MacLeod


Jonathan Delgado


Philipp A.


Pig Fang


Susisu


Thomas den Hollander


Tim Kraut


Bence Dányi

diff --git a/README.md b/README.md index 89922b3a685f..d327f2d355b2 100644 --- a/README.md +++ b/README.md @@ -3,12 +3,10 @@

Monorepo for all the tooling which enables ESLint to support TypeScript

- GitHub Workflow Status + CI Financial Contributors on Open Collective - GitHub license NPM Downloads Codecov - Commitizen friendly


diff --git a/docs/getting-started/linting/README.md b/docs/getting-started/linting/README.md index f62888df0b73..6abe587e3a32 100644 --- a/docs/getting-started/linting/README.md +++ b/docs/getting-started/linting/README.md @@ -7,13 +7,8 @@ Whether you're adding linting to a new TypeScript codebase, adding TypeScript to First step is to make sure you've got the required packages installed: ```bash -$ yarn add -D eslint @typescript-eslint/parser @typescript-eslint/eslint-plugin -``` - -or with NPM: - -```bash -$ npm i --save-dev eslint @typescript-eslint/parser @typescript-eslint/eslint-plugin +$ yarn add -D eslint typescript @typescript-eslint/parser @typescript-eslint/eslint-plugin +$ npm i --save-dev eslint typescript @typescript-eslint/parser @typescript-eslint/eslint-plugin ``` ## Configuration diff --git a/lerna.json b/lerna.json index 72afa49c8eb2..4f34c322983c 100644 --- a/lerna.json +++ b/lerna.json @@ -1,5 +1,5 @@ { - "version": "3.3.0", + "version": "3.4.0", "npmClient": "yarn", "useWorkspaces": true, "stream": true diff --git a/package.json b/package.json index a3ffa851516a..e01a0ed0c896 100644 --- a/package.json +++ b/package.json @@ -76,7 +76,7 @@ "cspell": "^4.0.61", "cz-conventional-changelog": "^3.2.0", "downlevel-dts": "^0.4.0", - "eslint": "^7.0.0", + "eslint": "^7.2.0", "eslint-plugin-eslint-comments": "^3.1.2", "eslint-plugin-eslint-plugin": "^2.2.1", "eslint-plugin-import": "^2.20.2", diff --git a/packages/eslint-plugin-internal/CHANGELOG.md b/packages/eslint-plugin-internal/CHANGELOG.md index 173a97a02190..f511b95f2840 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. +# [3.4.0](https://github.com/typescript-eslint/typescript-eslint/compare/v3.3.0...v3.4.0) (2020-06-22) + +**Note:** Version bump only for package @typescript-eslint/eslint-plugin-internal + + + + + # [3.3.0](https://github.com/typescript-eslint/typescript-eslint/compare/v3.2.0...v3.3.0) (2020-06-15) **Note:** Version bump only for package @typescript-eslint/eslint-plugin-internal diff --git a/packages/eslint-plugin-internal/README.md b/packages/eslint-plugin-internal/README.md index bf6ed0bbe384..adf369999286 100644 --- a/packages/eslint-plugin-internal/README.md +++ b/packages/eslint-plugin-internal/README.md @@ -1,5 +1,9 @@ -# `eslint-plugin-internal` +

Internal ESLint Plugin

-This is just a collection of internal lint rules to help enforce some guidelines specific to this repository. +

An ESLint plugin used internally in this project to ensure consistency.

-These are not intended to be used externally. +

+ CI +

+ +This plugin is not intended to be used externally. diff --git a/packages/eslint-plugin-internal/package.json b/packages/eslint-plugin-internal/package.json index aaa9957fe8ce..c20031b6bd06 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": "3.3.0", + "version": "3.4.0", "private": true, "main": "dist/index.js", "scripts": { @@ -13,7 +13,7 @@ "typecheck": "tsc -p tsconfig.json --noEmit" }, "dependencies": { - "@typescript-eslint/experimental-utils": "3.3.0", + "@typescript-eslint/experimental-utils": "3.4.0", "prettier": "*" } } diff --git a/packages/eslint-plugin-tslint/CHANGELOG.md b/packages/eslint-plugin-tslint/CHANGELOG.md index 434977a40190..64841ee61b35 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. +# [3.4.0](https://github.com/typescript-eslint/typescript-eslint/compare/v3.3.0...v3.4.0) (2020-06-22) + +**Note:** Version bump only for package @typescript-eslint/eslint-plugin-tslint + + + + + # [3.3.0](https://github.com/typescript-eslint/typescript-eslint/compare/v3.2.0...v3.3.0) (2020-06-15) **Note:** Version bump only for package @typescript-eslint/eslint-plugin-tslint diff --git a/packages/eslint-plugin-tslint/README.md b/packages/eslint-plugin-tslint/README.md index f8a7f4f3e58a..021b8780bfbd 100644 --- a/packages/eslint-plugin-tslint/README.md +++ b/packages/eslint-plugin-tslint/README.md @@ -3,11 +3,9 @@

ESLint plugin wraps a TSLint configuration and lints the whole source using TSLint.

- Azure Pipelines - GitHub license + CI NPM Version NPM Downloads - Commitizen friendly

## Installation diff --git a/packages/eslint-plugin-tslint/package.json b/packages/eslint-plugin-tslint/package.json index 97d415083aad..bf6bb3ec1ea1 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": "3.3.0", + "version": "3.4.0", "main": "dist/index.js", "typings": "src/index.ts", "description": "TSLint wrapper plugin for ESLint", @@ -32,7 +32,7 @@ "typecheck": "tsc -p tsconfig.json --noEmit" }, "dependencies": { - "@typescript-eslint/experimental-utils": "3.3.0", + "@typescript-eslint/experimental-utils": "3.4.0", "lodash": "^4.17.15" }, "peerDependencies": { @@ -42,6 +42,6 @@ }, "devDependencies": { "@types/lodash": "^4.14.149", - "@typescript-eslint/parser": "3.3.0" + "@typescript-eslint/parser": "3.4.0" } } diff --git a/packages/eslint-plugin/CHANGELOG.md b/packages/eslint-plugin/CHANGELOG.md index 42e7e147f901..709a49e455be 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. +# [3.4.0](https://github.com/typescript-eslint/typescript-eslint/compare/v3.3.0...v3.4.0) (2020-06-22) + + +### Bug Fixes + +* **eslint-plugin:** [no-base-to-string] handle intersection types ([#2170](https://github.com/typescript-eslint/typescript-eslint/issues/2170)) ([9cca3a9](https://github.com/typescript-eslint/typescript-eslint/commit/9cca3a9584d5d5ef0536219c5a734f4e87efb543)) +* **eslint-plugin:** [unbound-method] handling destructuring ([#2228](https://github.com/typescript-eslint/typescript-eslint/issues/2228)) ([c3753c2](https://github.com/typescript-eslint/typescript-eslint/commit/c3753c21768d355ecdb9e7ae8e0bfdfbbc1d3bbe)) + + +### Features + +* **eslint-plugin:** [no-unnecessary-boolean-literal-compare] add option to check nullable booleans ([#1983](https://github.com/typescript-eslint/typescript-eslint/issues/1983)) ([c0b3057](https://github.com/typescript-eslint/typescript-eslint/commit/c0b3057b7f7d515891ad2efe32e4ef8c01e0478f)) +* **eslint-plugin:** add extension rule `no-loss-of-precision` ([#2196](https://github.com/typescript-eslint/typescript-eslint/issues/2196)) ([535b0f2](https://github.com/typescript-eslint/typescript-eslint/commit/535b0f2ddd82efa6a2c40307a61c480f4b3cdea3)) + + + + + # [3.3.0](https://github.com/typescript-eslint/typescript-eslint/compare/v3.2.0...v3.3.0) (2020-06-15) diff --git a/packages/eslint-plugin/README.md b/packages/eslint-plugin/README.md index 53b8cbb94129..5f9822ed12f4 100644 --- a/packages/eslint-plugin/README.md +++ b/packages/eslint-plugin/README.md @@ -1,11 +1,11 @@

ESLint Plugin TypeScript

+

An ESLint plugin which provides lint rules for TypeScript codebases.

+

- Azure Pipelines - GitHub license + CI NPM Version NPM Downloads - Commitizen friendly

## Getting Started @@ -19,10 +19,18 @@ These docs walk you through setting up ESLint, this plugin, and our parser. If y ### Installation -Make sure you have TypeScript and [`@typescript-eslint/parser`](../parser) installed, then install the plugin: +Make sure you have TypeScript and [`@typescript-eslint/parser`](../parser) installed: + +```bash +$ yarn add -D typescript @typescript-eslint/parser +$ npm i --save-dev typescript @typescript-eslint/parser +``` + +Then install the plugin: -```sh -yarn add -D @typescript-eslint/eslint-plugin +```bash +$ yarn add -D @typescript-eslint/eslint-plugin +$ npm i --save-dev @typescript-eslint/eslint-plugin ``` It is important that you use the same version number for `@typescript-eslint/parser` and `@typescript-eslint/eslint-plugin`. @@ -191,6 +199,7 @@ In these cases, we create what we call an extension rule; a rule within our plug | [`@typescript-eslint/no-extra-parens`](./docs/rules/no-extra-parens.md) | Disallow unnecessary parentheses | | :wrench: | | | [`@typescript-eslint/no-extra-semi`](./docs/rules/no-extra-semi.md) | Disallow unnecessary semicolons | :heavy_check_mark: | :wrench: | | | [`@typescript-eslint/no-invalid-this`](./docs/rules/no-invalid-this.md) | disallow `this` keywords outside of classes or class-like objects | | | | +| [`@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-unused-expressions`](./docs/rules/no-unused-expressions.md) | Disallow unused expressions | | | | | [`@typescript-eslint/no-unused-vars`](./docs/rules/no-unused-vars.md) | Disallow unused variables | :heavy_check_mark: | | | diff --git a/packages/eslint-plugin/docs/rules/no-loss-of-precision.md b/packages/eslint-plugin/docs/rules/no-loss-of-precision.md new file mode 100644 index 000000000000..d6cf7b71c14a --- /dev/null +++ b/packages/eslint-plugin/docs/rules/no-loss-of-precision.md @@ -0,0 +1,19 @@ +# Disallow literal numbers that lose precision (`no-loss-of-precision`) + +## Rule Details + +This rule extends the base [`eslint/no-loss-of-precision`](https://eslint.org/docs/rules/no-loss-of-precision) rule. +It adds support for [numeric separators](https://github.com/tc39/proposal-numeric-separator). +Note that this rule requires ESLint v7. + +## How to use + +```jsonc +{ + // note you must disable the base rule as it can report incorrect errors + "no-loss-of-precision": "off", + "@typescript-eslint/no-loss-of-precision": ["error"] +} +``` + +Taken with ❤️ [from ESLint core](https://github.com/eslint/eslint/blob/master/docs/rules/no-loss-of-precision.md) diff --git a/packages/eslint-plugin/docs/rules/no-unnecessary-boolean-literal-compare.md b/packages/eslint-plugin/docs/rules/no-unnecessary-boolean-literal-compare.md index 81b4a5c67f6e..d600bb7930c0 100644 --- a/packages/eslint-plugin/docs/rules/no-unnecessary-boolean-literal-compare.md +++ b/packages/eslint-plugin/docs/rules/no-unnecessary-boolean-literal-compare.md @@ -8,6 +8,12 @@ This rule ensures that you do not include unnecessary comparisons with boolean l A comparison is considered unnecessary if it checks a boolean literal against any variable with just the `boolean` type. A comparison is **_not_** considered unnecessary if the type is a union of booleans (`string | boolean`, `someObject | boolean`). +**Note**: Throughout this page, only strict equality (`===` and `!==`) are +used in the examples. However, the implementation of the rule does not +distinguish between strict and loose equality. Any example below that uses +`===` would be treated the same way if `==` was used, and any example below +that uses `!==` would be treated the same way if `!=` was used. + Examples of **incorrect** code for this rule: ```ts @@ -30,12 +36,99 @@ if (someObjectBoolean === true) { declare const someStringBoolean: boolean | string; if (someStringBoolean === true) { } +``` + +## Options + +The rule accepts an options object with the following properties. + +```ts +type Options = { + // if false, comparisons between a nullable boolean variable to `true` will be checked and fixed + allowComparingNullableBooleansToTrue?: boolean; + // if false, comparisons between a nullable boolean variable to `false` will be checked and fixed + allowComparingNullableBooleansToFalse?: boolean; +}; +``` + +### Defaults + +This rule always checks comparisons between a boolean variable and a boolean +literal. Comparisons between nullable boolean variables and boolean literals +are **not** checked by default. + +```ts +const defaults = { + allowComparingNullableBooleansToTrue: true, + allowComparingNullableBooleansToFalse: true, +}; +``` + +### `allowComparingNullableBooleansToTrue` + +Examples of **incorrect** code for this rule with `{ allowComparingNullableBooleansToTrue: false }`: + +```ts +declare const someUndefinedCondition: boolean | undefined; +if (someUndefinedCondition === true) { +} + +declare const someNullCondition: boolean | null; +if (someNullCondition !== true) { +} +``` + +Examples of **correct** code for this rule with `{ allowComparingNullableBooleansToTrue: false }`: + +```ts +declare const someUndefinedCondition: boolean | undefined; +if (someUndefinedCondition) { +} +declare const someNullCondition: boolean | null; +if (!someNullCondition) { +} +``` + +### `allowComparingNullableBooleansToFalse` + +Examples of **incorrect** code for this rule with `{ allowComparingNullableBooleansToFalse: false }`: + +```ts declare const someUndefinedCondition: boolean | undefined; if (someUndefinedCondition === false) { } + +declare const someNullCondition: boolean | null; +if (someNullCondition !== false) { +} ``` +Examples of **correct** code for this rule with `{ allowComparingNullableBooleansToFalse: false }`: + +```ts +declare const someUndefinedCondition: boolean | undefined; +if (someUndefinedCondition ?? true) { +} + +declare const someNullCondition: boolean | null; +if (!(someNullCondition ?? true)) { +} +``` + +## Fixer + +| Comparison | Fixer Output | Notes | +| :----------------------------: | ------------------------------- | ----------------------------------------------------------------------------------- | +| `booleanVar === true` | `booleanLiteral` | | +| `booleanVar !== true` | `!booleanLiteral` | | +| `booleanVar === false` | `!booleanLiteral` | | +| `booleanVar !== false` | `booleanLiteral` | | +| `nullableBooleanVar === true` | `nullableBooleanVar` | Only checked/fixed if the `allowComparingNullableBooleansToTrue` option is `false` | +| `nullableBooleanVar !== true` | `!nullableBooleanVar` | Only checked/fixed if the `allowComparingNullableBooleansToTrue` option is `false` | +| `nullableBooleanVar === false` | `nullableBooleanVar ?? true` | Only checked/fixed if the `allowComparingNullableBooleansToFalse` option is `false` | +| `nullableBooleanVar !== false` | `!(nullableBooleanVar ?? true)` | Only checked/fixed if the `allowComparingNullableBooleansToFalse` option is `false` | + ## Related to - TSLint: [no-boolean-literal-compare](https://palantir.github.io/tslint/rules/no-boolean-literal-compare) diff --git a/packages/eslint-plugin/package.json b/packages/eslint-plugin/package.json index 8ba7451b3889..08a04f8b7605 100644 --- a/packages/eslint-plugin/package.json +++ b/packages/eslint-plugin/package.json @@ -1,6 +1,6 @@ { "name": "@typescript-eslint/eslint-plugin", - "version": "3.3.0", + "version": "3.4.0", "description": "TypeScript plugin for ESLint", "keywords": [ "eslint", @@ -42,7 +42,8 @@ "typecheck": "tsc -p tsconfig.json --noEmit" }, "dependencies": { - "@typescript-eslint/experimental-utils": "3.3.0", + "@typescript-eslint/experimental-utils": "3.4.0", + "debug": "^4.1.1", "functional-red-black-tree": "^1.0.1", "regexpp": "^3.0.0", "semver": "^7.3.2", diff --git a/packages/eslint-plugin/src/configs/all.ts b/packages/eslint-plugin/src/configs/all.ts index 25001233883d..642d6f736d07 100644 --- a/packages/eslint-plugin/src/configs/all.ts +++ b/packages/eslint-plugin/src/configs/all.ts @@ -59,6 +59,8 @@ export = { 'no-invalid-this': 'off', '@typescript-eslint/no-invalid-this': 'error', '@typescript-eslint/no-invalid-void-type': 'error', + 'no-loss-of-precision': 'off', + '@typescript-eslint/no-loss-of-precision': 'error', 'no-magic-numbers': 'off', '@typescript-eslint/no-magic-numbers': 'error', '@typescript-eslint/no-misused-new': 'error', diff --git a/packages/eslint-plugin/src/rules/await-thenable.ts b/packages/eslint-plugin/src/rules/await-thenable.ts index 78b7ad129393..9858bad8ba2a 100644 --- a/packages/eslint-plugin/src/rules/await-thenable.ts +++ b/packages/eslint-plugin/src/rules/await-thenable.ts @@ -1,5 +1,4 @@ import * as tsutils from 'tsutils'; -import * as ts from 'typescript'; import * as util from '../util'; @@ -30,8 +29,8 @@ export default util.createRule({ const type = checker.getTypeAtLocation(originalNode.expression); if ( - !tsutils.isTypeFlagSet(type, ts.TypeFlags.Any) && - !tsutils.isTypeFlagSet(type, ts.TypeFlags.Unknown) && + !util.isTypeAnyType(type) && + !util.isTypeUnknownType(type) && !tsutils.isThenableType(checker, originalNode.expression, type) ) { context.report({ diff --git a/packages/eslint-plugin/src/rules/index.ts b/packages/eslint-plugin/src/rules/index.ts index 05016d5705fa..37ad1da48062 100644 --- a/packages/eslint-plugin/src/rules/index.ts +++ b/packages/eslint-plugin/src/rules/index.ts @@ -96,6 +96,7 @@ import typedef from './typedef'; import unboundMethod from './unbound-method'; import unifiedSignatures from './unified-signatures'; import linesBetweenClassMembers from './lines-between-class-members'; +import noLossOfPrecision from './no-loss-of-precision'; export default { 'adjacent-overload-signatures': adjacentOverloadSignatures, @@ -196,4 +197,5 @@ export default { 'unbound-method': unboundMethod, 'unified-signatures': unifiedSignatures, 'lines-between-class-members': linesBetweenClassMembers, + 'no-loss-of-precision': noLossOfPrecision, }; diff --git a/packages/eslint-plugin/src/rules/no-base-to-string.ts b/packages/eslint-plugin/src/rules/no-base-to-string.ts index 34fa2c7d6dc0..b1593c23d8b0 100644 --- a/packages/eslint-plugin/src/rules/no-base-to-string.ts +++ b/packages/eslint-plugin/src/rules/no-base-to-string.ts @@ -112,6 +112,18 @@ export default util.createRule({ return Usefulness.Always; } + if (type.isIntersection()) { + for (const subType of type.types) { + const subtypeUsefulness = collectToStringCertainty(subType); + + if (subtypeUsefulness === Usefulness.Always) { + return Usefulness.Always; + } + } + + return Usefulness.Never; + } + if (!type.isUnion()) { return Usefulness.Never; } diff --git a/packages/eslint-plugin/src/rules/no-loss-of-precision.ts b/packages/eslint-plugin/src/rules/no-loss-of-precision.ts new file mode 100644 index 000000000000..47ab5b1a74fa --- /dev/null +++ b/packages/eslint-plugin/src/rules/no-loss-of-precision.ts @@ -0,0 +1,53 @@ +import { TSESTree } from '@typescript-eslint/experimental-utils'; +import BaseRule from 'eslint/lib/rules/no-loss-of-precision'; +import * as util from '../util'; + +const baseRule = ((): typeof BaseRule | null => { + try { + return require('eslint/lib/rules/no-loss-of-precision'); + } catch { + /* istanbul ignore next */ + return null; + } +})(); + +type Options = util.InferOptionsTypeFromRule; +type MessageIds = util.InferMessageIdsTypeFromRule; + +export default util.createRule({ + name: 'no-loss-of-precision', + meta: { + type: 'problem', + docs: { + description: 'Disallow literal numbers that lose precision', + category: 'Possible Errors', + recommended: false, + extendsBaseRule: true, + }, + schema: [], + messages: baseRule?.meta.messages ?? { noLossOfPrecision: '' }, + }, + defaultOptions: [], + create(context) { + /* istanbul ignore if */ if (baseRule === null) { + throw new Error( + '@typescript-eslint/no-loss-of-precision requires at least ESLint v7.1.0', + ); + } + + // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion + const rules = baseRule!.create(context); + + function isSeperatedNumeric(node: TSESTree.Literal): boolean { + return typeof node.value === 'number' && node.raw.includes('_'); + } + return { + Literal(node: TSESTree.Literal): void { + rules.Literal({ + ...node, + raw: isSeperatedNumeric(node) ? node.raw.replace(/_/g, '') : node.raw, + }); + }, + }; + }, +}); diff --git a/packages/eslint-plugin/src/rules/no-throw-literal.ts b/packages/eslint-plugin/src/rules/no-throw-literal.ts index b85e0cc742db..67ba9e52ebe5 100644 --- a/packages/eslint-plugin/src/rules/no-throw-literal.ts +++ b/packages/eslint-plugin/src/rules/no-throw-literal.ts @@ -110,7 +110,8 @@ export default util.createRule({ } if ( - type.flags & (ts.TypeFlags.Any | ts.TypeFlags.Unknown) || + util.isTypeAnyType(type) || + util.isTypeUnknownType(type) || isErrorLike(type) ) { return; diff --git a/packages/eslint-plugin/src/rules/no-unnecessary-boolean-literal-compare.ts b/packages/eslint-plugin/src/rules/no-unnecessary-boolean-literal-compare.ts index ffcdd0e07320..fe1fd24cc4f1 100644 --- a/packages/eslint-plugin/src/rules/no-unnecessary-boolean-literal-compare.ts +++ b/packages/eslint-plugin/src/rules/no-unnecessary-boolean-literal-compare.ts @@ -6,16 +6,33 @@ import * as tsutils from 'tsutils'; import * as ts from 'typescript'; import * as util from '../util'; -type MessageIds = 'direct' | 'negated'; +type MessageIds = + | 'direct' + | 'negated' + | 'comparingNullableToTrueDirect' + | 'comparingNullableToTrueNegated' + | 'comparingNullableToFalse'; + +type Options = [ + { + allowComparingNullableBooleansToTrue?: boolean; + allowComparingNullableBooleansToFalse?: boolean; + }, +]; interface BooleanComparison { expression: TSESTree.Expression; + literalBooleanInComparison: boolean; forTruthy: boolean; negated: boolean; range: [number, number]; } -export default util.createRule<[], MessageIds>({ +interface BooleanComparisonWithTypeInformation extends BooleanComparison { + expressionIsNullableBoolean: boolean; +} + +export default util.createRule({ name: 'no-unnecessary-boolean-literal-compare', meta: { docs: { @@ -31,18 +48,42 @@ export default util.createRule<[], MessageIds>({ 'This expression unnecessarily compares a boolean value to a boolean instead of using it directly.', negated: 'This expression unnecessarily compares a boolean value to a boolean instead of negating it.', + comparingNullableToTrueDirect: + 'This expression unnecessarily compares a nullable boolean value to true instead of using it directly.', + comparingNullableToTrueNegated: + 'This expression unnecessarily compares a nullable boolean value to true instead of negating it.', + comparingNullableToFalse: + 'This expression unnecessarily compares a nullable boolean value to false instead of using the ?? operator to provide a default.', }, - schema: [], + schema: [ + { + type: 'object', + properties: { + allowComparingNullableBooleansToTrue: { + type: 'boolean', + }, + allowComparingNullableBooleansToFalse: { + type: 'boolean', + }, + }, + additionalProperties: false, + }, + ], type: 'suggestion', }, - defaultOptions: [], - create(context) { + defaultOptions: [ + { + allowComparingNullableBooleansToTrue: true, + allowComparingNullableBooleansToFalse: true, + }, + ], + create(context, [options]) { const parserServices = util.getParserServices(context); const checker = parserServices.program.getTypeChecker(); function getBooleanComparison( node: TSESTree.BinaryExpression, - ): BooleanComparison | undefined { + ): BooleanComparisonWithTypeInformation | undefined { const comparison = deconstructComparison(node); if (!comparison) { return undefined; @@ -52,16 +93,67 @@ export default util.createRule<[], MessageIds>({ parserServices.esTreeNodeToTSNodeMap.get(comparison.expression), ); - if ( - !tsutils.isTypeFlagSet( - expressionType, - ts.TypeFlags.Boolean | ts.TypeFlags.BooleanLiteral, - ) - ) { - return undefined; + if (isBooleanType(expressionType)) { + return { + ...comparison, + expressionIsNullableBoolean: false, + }; + } + + if (isNullableBoolean(expressionType)) { + return { + ...comparison, + expressionIsNullableBoolean: true, + }; } - return comparison; + return undefined; + } + + function isBooleanType(expressionType: ts.Type): boolean { + return tsutils.isTypeFlagSet( + expressionType, + ts.TypeFlags.Boolean | ts.TypeFlags.BooleanLiteral, + ); + } + + /** + * checks if the expressionType is a union that + * 1) contains at least one nullish type (null or undefined) + * 2) contains at least once boolean type (true or false or boolean) + * 3) does not contain any types besides nullish and boolean types + */ + function isNullableBoolean(expressionType: ts.Type): boolean { + if (!expressionType.isUnion()) { + return false; + } + + const { types } = expressionType; + + const nonNullishTypes = types.filter( + type => + !tsutils.isTypeFlagSet( + type, + ts.TypeFlags.Undefined | ts.TypeFlags.Null, + ), + ); + + const hasNonNullishType = nonNullishTypes.length > 0; + if (!hasNonNullishType) { + return false; + } + + const hasNullableType = nonNullishTypes.length < types.length; + if (!hasNullableType) { + return false; + } + + const allNonNullishTypesAreBoolean = nonNullishTypes.every(isBooleanType); + if (!allNonNullishTypesAreBoolean) { + return false; + } + + return true; } function deconstructComparison( @@ -83,11 +175,12 @@ export default util.createRule<[], MessageIds>({ continue; } - const { value } = against; - const negated = node.operator.startsWith('!'); + const { value: literalBooleanInComparison } = against; + const negated = !comparisonType.isPositive; return { - forTruthy: value ? !negated : negated, + literalBooleanInComparison, + forTruthy: literalBooleanInComparison ? !negated : negated, expression, negated, range: @@ -100,23 +193,85 @@ export default util.createRule<[], MessageIds>({ return undefined; } + function nodeIsUnaryNegation(node: TSESTree.Node): boolean { + return ( + node.type === AST_NODE_TYPES.UnaryExpression && + node.prefix && + node.operator === '!' + ); + } + return { BinaryExpression(node): void { const comparison = getBooleanComparison(node); + if (comparison === undefined) { + return; + } - if (comparison) { - context.report({ - fix: function* (fixer) { - yield fixer.removeRange(comparison.range); + if (comparison.expressionIsNullableBoolean) { + if ( + comparison.literalBooleanInComparison && + options.allowComparingNullableBooleansToTrue + ) { + return; + } + if ( + !comparison.literalBooleanInComparison && + options.allowComparingNullableBooleansToFalse + ) { + return; + } + } + context.report({ + fix: function* (fixer) { + yield fixer.removeRange(comparison.range); + + // if the expression `exp` isn't nullable, or we're comparing to `true`, + // we can just replace the entire comparison with `exp` or `!exp` + if ( + !comparison.expressionIsNullableBoolean || + comparison.literalBooleanInComparison + ) { if (!comparison.forTruthy) { yield fixer.insertTextBefore(node, '!'); } - }, - messageId: comparison.negated ? 'negated' : 'direct', - node, - }); - } + return; + } + + // if we're here, then the expression is a nullable boolean and we're + // comparing to a literal `false` + + // if we're doing `== false` or `=== false`, then we need to negate the expression + if (!comparison.negated) { + const { parent } = node; + // if the parent is a negation, we can instead just get rid of the parent's negation. + // i.e. instead of resulting in `!(!(exp))`, we can just result in `exp` + if (parent != null && nodeIsUnaryNegation(parent)) { + // remove from the beginning of the parent to the beginning of this node + yield fixer.removeRange([parent.range[0], node.range[0]]); + // remove from the end of the node to the end of the parent + yield fixer.removeRange([node.range[1], parent.range[1]]); + } else { + yield fixer.insertTextBefore(node, '!'); + } + } + + // provide the default `true` + yield fixer.insertTextBefore(node, '('); + yield fixer.insertTextAfter(node, ' ?? true)'); + }, + messageId: comparison.expressionIsNullableBoolean + ? comparison.literalBooleanInComparison + ? comparison.negated + ? 'comparingNullableToTrueNegated' + : 'comparingNullableToTrueDirect' + : 'comparingNullableToFalse' + : comparison.negated + ? 'negated' + : 'direct', + node, + }); }, }; }, diff --git a/packages/eslint-plugin/src/rules/no-unnecessary-condition.ts b/packages/eslint-plugin/src/rules/no-unnecessary-condition.ts index bed2ac82e55d..1147957a20cb 100644 --- a/packages/eslint-plugin/src/rules/no-unnecessary-condition.ts +++ b/packages/eslint-plugin/src/rules/no-unnecessary-condition.ts @@ -22,6 +22,8 @@ import { NullThrowsReasons, isMemberOrOptionalMemberExpression, isIdentifier, + isTypeAnyType, + isTypeUnknownType, } from '../util'; // Truthiness utilities @@ -181,13 +183,11 @@ export default createRule({ // Conditional is always necessary if it involves: // `any` or `unknown` or a naked type parameter if ( - unionTypeParts(type).some(part => - isTypeFlagSet( - part, - ts.TypeFlags.Any | - ts.TypeFlags.Unknown | - ts.TypeFlags.TypeParameter, - ), + unionTypeParts(type).some( + part => + isTypeAnyType(part) || + isTypeUnknownType(part) || + isTypeFlagSet(part, ts.TypeFlags.TypeParameter), ) ) { return; @@ -214,7 +214,7 @@ export default createRule({ } const type = getNodeType(node); // Conditional is always necessary if it involves `any` or `unknown` - if (isTypeFlagSet(type, ts.TypeFlags.Any | ts.TypeFlags.Unknown)) { + if (isTypeAnyType(type) || isTypeUnknownType(type)) { return; } const messageId = isTypeFlagSet(type, ts.TypeFlags.Never) @@ -469,8 +469,8 @@ export default createRule({ ? !isNullableOriginFromPrev(node) : true; return ( - isTypeFlagSet(type, ts.TypeFlags.Any) || - isTypeFlagSet(type, ts.TypeFlags.Unknown) || + isTypeAnyType(type) || + isTypeUnknownType(type) || (isNullableType(type, { allowUndefined: true }) && isOwnNullable) ); } diff --git a/packages/eslint-plugin/src/rules/restrict-template-expressions.ts b/packages/eslint-plugin/src/rules/restrict-template-expressions.ts index a3cbb0b6f3bf..a4756266ffca 100644 --- a/packages/eslint-plugin/src/rules/restrict-template-expressions.ts +++ b/packages/eslint-plugin/src/rules/restrict-template-expressions.ts @@ -72,7 +72,7 @@ export default util.createRule({ return true; } - if (options.allowAny && util.isTypeFlagSet(type, ts.TypeFlags.Any)) { + if (options.allowAny && util.isTypeAnyType(type)) { return true; } diff --git a/packages/eslint-plugin/src/rules/strict-boolean-expressions.ts b/packages/eslint-plugin/src/rules/strict-boolean-expressions.ts index df2b59e12ec8..747cbefb7ebe 100644 --- a/packages/eslint-plugin/src/rules/strict-boolean-expressions.ts +++ b/packages/eslint-plugin/src/rules/strict-boolean-expressions.ts @@ -325,8 +325,8 @@ export default util.createRule({ } if ( - types.some(type => - tsutils.isTypeFlagSet(type, ts.TypeFlags.Any | ts.TypeFlags.Unknown), + types.some( + type => util.isTypeAnyType(type) || util.isTypeUnknownType(type), ) ) { variantTypes.add('any'); diff --git a/packages/eslint-plugin/src/rules/unbound-method.ts b/packages/eslint-plugin/src/rules/unbound-method.ts index ade042298875..e8217348a4a6 100644 --- a/packages/eslint-plugin/src/rules/unbound-method.ts +++ b/packages/eslint-plugin/src/rules/unbound-method.ts @@ -99,7 +99,7 @@ const nativelyBoundMembers = SUPPORTED_GLOBALS.map(namespace => { .reduce((arr, names) => arr.concat(names), []) .filter(name => !nativelyNotBoundMembers.has(name)); -const isMemberNotImported = ( +const isNotImported = ( symbol: ts.Symbol, currentSourceFile: ts.SourceFile | undefined, ): boolean => { @@ -176,7 +176,7 @@ export default util.createRule({ if ( objectSymbol && nativelyBoundMembers.includes(getMemberFullName(node)) && - isMemberNotImported(objectSymbol, currentSourceFile) + isNotImported(objectSymbol, currentSourceFile) ) { return; } @@ -191,6 +191,48 @@ export default util.createRule({ }); } }, + 'VariableDeclarator, AssignmentExpression'( + node: TSESTree.VariableDeclarator | TSESTree.AssignmentExpression, + ): void { + const [idNode, initNode] = + node.type === AST_NODE_TYPES.VariableDeclarator + ? [node.id, node.init] + : [node.left, node.right]; + + if (initNode && idNode.type === AST_NODE_TYPES.ObjectPattern) { + const tsNode = parserServices.esTreeNodeToTSNodeMap.get(initNode); + const rightSymbol = checker.getSymbolAtLocation(tsNode); + const initTypes = checker.getTypeAtLocation(tsNode); + + const notImported = + rightSymbol && isNotImported(rightSymbol, currentSourceFile); + + idNode.properties.forEach(property => { + if ( + property.type === AST_NODE_TYPES.Property && + property.key.type === AST_NODE_TYPES.Identifier + ) { + if ( + notImported && + util.isIdentifier(initNode) && + nativelyBoundMembers.includes( + `${initNode.name}.${property.key.name}`, + ) + ) { + return; + } + + const symbol = initTypes.getProperty(property.key.name); + if (symbol && isDangerousMethod(symbol, ignoreStatic)) { + context.report({ + messageId: 'unbound', + node, + }); + } + } + }); + } + }, }; }, }); diff --git a/packages/eslint-plugin/src/util/types.ts b/packages/eslint-plugin/src/util/types.ts index 08a67cd7e5d9..d030b829cd46 100644 --- a/packages/eslint-plugin/src/util/types.ts +++ b/packages/eslint-plugin/src/util/types.ts @@ -1,3 +1,4 @@ +import debug from 'debug'; import { isCallExpression, isJsxExpression, @@ -13,6 +14,8 @@ import { } from 'tsutils'; import * as ts from 'typescript'; +const log = debug('typescript-eslint:eslint-plugin:utils:types'); + /** * Checks if the given type is either an array type, * or a union made up solely of array types. @@ -305,7 +308,7 @@ export function getEqualsKind(operator: string): EqualsKind | undefined { case '!==': return { - isPositive: true, + isPositive: false, isStrict: true, }; @@ -326,11 +329,24 @@ export function getTypeArguments( return type.typeArguments ?? []; } +/** + * @returns true if the type is `unknown` + */ +export function isTypeUnknownType(type: ts.Type): boolean { + return isTypeFlagSet(type, ts.TypeFlags.Unknown); +} + /** * @returns true if the type is `any` */ export function isTypeAnyType(type: ts.Type): boolean { - return isTypeFlagSet(type, ts.TypeFlags.Any); + if (isTypeFlagSet(type, ts.TypeFlags.Any)) { + if (type.intrinsicName === 'error') { + log('Found an "error" any type'); + } + return true; + } + return false; } /** diff --git a/packages/eslint-plugin/tests/rules/no-base-to-string.test.ts b/packages/eslint-plugin/tests/rules/no-base-to-string.test.ts index 86babb99ae1f..542097aa9cb6 100644 --- a/packages/eslint-plugin/tests/rules/no-base-to-string.test.ts +++ b/packages/eslint-plugin/tests/rules/no-base-to-string.test.ts @@ -107,6 +107,12 @@ tag\`\${{}}\`; function tag() {} tag\`\${{}}\`; `, + ` + interface Brand {} + function test(v: string & Brand): string { + return \`\${v}\`; + } + `, ], invalid: [ { @@ -217,5 +223,23 @@ tag\`\${{}}\`; }, ], }, + { + code: ` + interface A {} + interface B {} + function test(intersection: A & B): string { + return \`\${intersection}\`; + } + `, + errors: [ + { + data: { + certainty: 'will', + name: 'intersection', + }, + messageId: 'baseToString', + }, + ], + }, ], }); diff --git a/packages/eslint-plugin/tests/rules/no-loss-of-precision.test.ts b/packages/eslint-plugin/tests/rules/no-loss-of-precision.test.ts new file mode 100644 index 000000000000..f2405bacdb6b --- /dev/null +++ b/packages/eslint-plugin/tests/rules/no-loss-of-precision.test.ts @@ -0,0 +1,36 @@ +import rule from '../../src/rules/no-loss-of-precision'; +import { RuleTester } from '../RuleTester'; + +const ruleTester = new RuleTester({ + parser: '@typescript-eslint/parser', +}); + +ruleTester.run('no-loss-of-precision', rule, { + valid: [ + 'const x = 12345;', + 'const x = 123.456;', + 'const x = -123.456;', + 'const x = 123_456;', + 'const x = 123_00_000_000_000_000_000_000_000;', + 'const x = 123.000_000_000_000_000_000_000_0;', + ], + invalid: [ + { + code: 'const x = 9007199254740993;', + errors: [{ messageId: 'noLossOfPrecision' }], + }, + { + code: 'const x = 9_007_199_254_740_993;', + errors: [{ messageId: 'noLossOfPrecision' }], + }, + { + code: 'const x = 9_007_199_254_740.993e3;', + errors: [{ messageId: 'noLossOfPrecision' }], + }, + { + code: + 'const x = 0b100_000_000_000_000_000_000_000_000_000_000_000_000_000_000_000_000_001;', + errors: [{ messageId: 'noLossOfPrecision' }], + }, + ], +}); diff --git a/packages/eslint-plugin/tests/rules/no-unnecessary-boolean-literal-compare.test.ts b/packages/eslint-plugin/tests/rules/no-unnecessary-boolean-literal-compare.test.ts index 6480d5489062..36eb36033de1 100644 --- a/packages/eslint-plugin/tests/rules/no-unnecessary-boolean-literal-compare.test.ts +++ b/packages/eslint-plugin/tests/rules/no-unnecessary-boolean-literal-compare.test.ts @@ -38,17 +38,39 @@ ruleTester.run('no-unnecessary-boolean-literal-compare', rule, { varObject == false; `, ` - declare const varBooleanOrString: boolean | undefined; + declare const varNullOrUndefined: null | undefined; + varNullOrUndefined === false; + `, + ` + declare const varBooleanOrString: boolean | string; varBooleanOrString === false; `, ` - declare const varBooleanOrString: boolean | undefined; + declare const varBooleanOrString: boolean | string; varBooleanOrString == true; `, + ` + declare const varTrueOrStringOrUndefined: true | string | undefined; + varTrueOrStringOrUndefined == true; + `, ` declare const varBooleanOrUndefined: boolean | undefined; varBooleanOrUndefined === true; `, + { + code: ` + declare const varBooleanOrUndefined: boolean | undefined; + varBooleanOrUndefined === true; + `, + options: [{ allowComparingNullableBooleansToFalse: false }], + }, + { + code: ` + declare const varBooleanOrUndefined: boolean | undefined; + varBooleanOrUndefined === false; + `, + options: [{ allowComparingNullableBooleansToTrue: false }], + }, "'false' === true;", "'true' === false;", ], @@ -106,5 +128,101 @@ ruleTester.run('no-unnecessary-boolean-literal-compare', rule, { } `, }, + { + code: ` + declare const varTrueOrUndefined: true | undefined; + if (varTrueOrUndefined === true) { + } + `, + options: [{ allowComparingNullableBooleansToTrue: false }], + errors: [ + { + messageId: 'comparingNullableToTrueDirect', + }, + ], + output: ` + declare const varTrueOrUndefined: true | undefined; + if (varTrueOrUndefined) { + } + `, + }, + { + code: ` + declare const varFalseOrNull: false | null; + if (varFalseOrNull !== true) { + } + `, + options: [{ allowComparingNullableBooleansToTrue: false }], + errors: [ + { + messageId: 'comparingNullableToTrueNegated', + }, + ], + output: ` + declare const varFalseOrNull: false | null; + if (!varFalseOrNull) { + } + `, + }, + { + code: ` + declare const varBooleanOrNull: boolean | null; + declare const otherBoolean: boolean; + if (varBooleanOrNull === false && otherBoolean) { + } + `, + options: [{ allowComparingNullableBooleansToFalse: false }], + errors: [ + { + messageId: 'comparingNullableToFalse', + }, + ], + output: ` + declare const varBooleanOrNull: boolean | null; + declare const otherBoolean: boolean; + if (!(varBooleanOrNull ?? true) && otherBoolean) { + } + `, + }, + { + code: ` + declare const varBooleanOrNull: boolean | null; + declare const otherBoolean: boolean; + if (!(varBooleanOrNull === false) || otherBoolean) { + } + `, + options: [{ allowComparingNullableBooleansToFalse: false }], + errors: [ + { + messageId: 'comparingNullableToFalse', + }, + ], + output: ` + declare const varBooleanOrNull: boolean | null; + declare const otherBoolean: boolean; + if ((varBooleanOrNull ?? true) || otherBoolean) { + } + `, + }, + { + code: ` + declare const varTrueOrFalseOrUndefined: true | false | undefined; + declare const otherBoolean: boolean; + if (varTrueOrFalseOrUndefined !== false && !otherBoolean) { + } + `, + options: [{ allowComparingNullableBooleansToFalse: false }], + errors: [ + { + messageId: 'comparingNullableToFalse', + }, + ], + output: ` + declare const varTrueOrFalseOrUndefined: true | false | undefined; + declare const otherBoolean: boolean; + if ((varTrueOrFalseOrUndefined ?? true) && !otherBoolean) { + } + `, + }, ], }); diff --git a/packages/eslint-plugin/tests/rules/unbound-method.test.ts b/packages/eslint-plugin/tests/rules/unbound-method.test.ts index 12d6486e09f5..4c0cb8f58d36 100644 --- a/packages/eslint-plugin/tests/rules/unbound-method.test.ts +++ b/packages/eslint-plugin/tests/rules/unbound-method.test.ts @@ -228,6 +228,35 @@ class A { } } `, + 'const { parseInt } = Number;', + 'const { log } = console;', + ` +let parseInt; +({ parseInt } = Number); + `, + ` +let log; +({ log } = console); + `, + ` +const foo = { + bar: 'bar', +}; +const { bar } = foo; + `, + ` +class Foo { + unbnound() {} + bar = 4; +} +const { bar } = new Foo(); + `, + ` +class Foo { + bound = () => 'foo'; +} +const { bound } = new Foo(); + `, ], invalid: [ { @@ -288,8 +317,8 @@ function foo(arg: ContainsMethods | null) { 'const unbound = instance.unbound;', 'const unboundStatic = ContainsMethods.unboundStatic;', - 'const { unbound } = instance.unbound;', - 'const { unboundStatic } = ContainsMethods.unboundStatic;', + 'const { unbound } = instance;', + 'const { unboundStatic } = ContainsMethods;', 'instance.unbound;', 'instance.unbound as any;', @@ -384,5 +413,113 @@ const unbound = new Foo().unbound; }, ], }, + { + code: ` +class Foo { + unbound() {} +} +const { unbound } = new Foo(); + `, + errors: [ + { + line: 5, + messageId: 'unbound', + }, + ], + }, + { + code: ` +class Foo { + unbound = function () {}; +} +const { unbound } = new Foo(); + `, + errors: [ + { + line: 5, + messageId: 'unbound', + }, + ], + }, + { + code: ` +class Foo { + unbound() {} +} +let unbound; +({ unbound } = new Foo()); + `, + errors: [ + { + line: 6, + messageId: 'unbound', + }, + ], + }, + { + code: ` +class Foo { + unbound = function () {}; +} +let unbound; +({ unbound } = new Foo()); + `, + errors: [ + { + line: 6, + messageId: 'unbound', + }, + ], + }, + { + code: ` +class CommunicationError { + foo() {} +} +const { foo } = CommunicationError.prototype; + `, + errors: [ + { + line: 5, + messageId: 'unbound', + }, + ], + }, + { + code: ` +class CommunicationError { + foo() {} +} +let foo; +({ foo } = CommunicationError.prototype); + `, + errors: [ + { + line: 6, + messageId: 'unbound', + }, + ], + }, + { + code: ` +import { console } from './class'; +const { log } = console; + `, + errors: [ + { + line: 3, + messageId: 'unbound', + }, + ], + }, + { + code: 'const { all } = Promise;', + errors: [ + { + line: 1, + messageId: 'unbound', + }, + ], + }, ], }); diff --git a/packages/eslint-plugin/typings/eslint-rules.d.ts b/packages/eslint-plugin/typings/eslint-rules.d.ts index 31a752878b88..add5af1c1bbe 100644 --- a/packages/eslint-plugin/typings/eslint-rules.d.ts +++ b/packages/eslint-plugin/typings/eslint-rules.d.ts @@ -702,3 +702,16 @@ declare module 'eslint/lib/rules/dot-notation' { >; export = rule; } + +declare module 'eslint/lib/rules/no-loss-of-precision' { + import { TSESLint, TSESTree } from '@typescript-eslint/experimental-utils'; + + const rule: TSESLint.RuleModule< + 'noLossOfPrecision', + [], + { + Literal(node: TSESTree.Literal): void; + } + >; + export = rule; +} diff --git a/packages/eslint-plugin/typings/typescript.d.ts b/packages/eslint-plugin/typings/typescript.d.ts index 7c9089158b4b..73304155ee74 100644 --- a/packages/eslint-plugin/typings/typescript.d.ts +++ b/packages/eslint-plugin/typings/typescript.d.ts @@ -23,4 +23,11 @@ declare module 'typescript' { */ getTypeOfPropertyOfType(type: Type, propertyName: string): Type | undefined; } + + interface Type { + /** + * If the type is `any`, and this is set to "error", then TS was unable to resolve the type + */ + intrinsicName?: string; + } } diff --git a/packages/experimental-utils/CHANGELOG.md b/packages/experimental-utils/CHANGELOG.md index 91e2035933e6..585d87d32569 100644 --- a/packages/experimental-utils/CHANGELOG.md +++ b/packages/experimental-utils/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. +# [3.4.0](https://github.com/typescript-eslint/typescript-eslint/compare/v3.3.0...v3.4.0) (2020-06-22) + + +### Bug Fixes + +* **experimental-utils:** correct types for TS versions older than 3.8 ([#2217](https://github.com/typescript-eslint/typescript-eslint/issues/2217)) ([5e4dda2](https://github.com/typescript-eslint/typescript-eslint/commit/5e4dda264a7d6a6a1626848e7599faea1ac34922)) +* **experimental-utils:** getParserServices takes a readonly context ([#2235](https://github.com/typescript-eslint/typescript-eslint/issues/2235)) ([26da8de](https://github.com/typescript-eslint/typescript-eslint/commit/26da8de7fcde9eddec63212d79af781c4bb22991)) + + + + + # [3.3.0](https://github.com/typescript-eslint/typescript-eslint/compare/v3.2.0...v3.3.0) (2020-06-15) **Note:** Version bump only for package @typescript-eslint/experimental-utils diff --git a/packages/experimental-utils/README.md b/packages/experimental-utils/README.md index cba85c84d6e4..05f65ecb7da9 100644 --- a/packages/experimental-utils/README.md +++ b/packages/experimental-utils/README.md @@ -1,6 +1,12 @@ -# `@typescript-eslint/experimental-utils` +

Utils for ESLint Plugins

-(Experimental) Utilities for working with TypeScript + ESLint together. +

Utilities for working with TypeScript + ESLint together.

+ +

+ CI + NPM Version + NPM Downloads +

## Note @@ -10,7 +16,7 @@ i.e. treat it as a `0.x.y` package. Feel free to use it now, and let us know what utilities you need or send us PRs with utilities you build on top of it. -Once it is stable, it will be renamed to `@typescript-eslint/util` for a `3.0.0` release. +Once it is stable, it will be renamed to `@typescript-eslint/util` for a `4.0.0` release. ## Exports diff --git a/packages/experimental-utils/package.json b/packages/experimental-utils/package.json index e94079f0996e..376b75559236 100644 --- a/packages/experimental-utils/package.json +++ b/packages/experimental-utils/package.json @@ -1,6 +1,6 @@ { "name": "@typescript-eslint/experimental-utils", - "version": "3.3.0", + "version": "3.4.0", "description": "(Experimental) Utilities for working with TypeScript + ESLint together", "keywords": [ "eslint", @@ -40,7 +40,7 @@ }, "dependencies": { "@types/json-schema": "^7.0.3", - "@typescript-eslint/typescript-estree": "3.3.0", + "@typescript-eslint/typescript-estree": "3.4.0", "eslint-scope": "^5.0.0", "eslint-utils": "^2.0.0" }, @@ -57,7 +57,7 @@ "typesVersions": { "<3.8": { "*": [ - "ts3.4/*" + "_ts3.4/*" ] } } diff --git a/packages/experimental-utils/src/eslint-utils/getParserServices.ts b/packages/experimental-utils/src/eslint-utils/getParserServices.ts index 481603d7ed51..925d49761522 100644 --- a/packages/experimental-utils/src/eslint-utils/getParserServices.ts +++ b/packages/experimental-utils/src/eslint-utils/getParserServices.ts @@ -11,7 +11,7 @@ function getParserServices< TMessageIds extends string, TOptions extends readonly unknown[] >( - context: TSESLint.RuleContext, + context: Readonly>, allowWithoutFullTypeInformation = false, ): ParserServices { // backwards compatibility check diff --git a/packages/parser/CHANGELOG.md b/packages/parser/CHANGELOG.md index bf6cf0a44377..8f092f231aa4 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. +# [3.4.0](https://github.com/typescript-eslint/typescript-eslint/compare/v3.3.0...v3.4.0) (2020-06-22) + +**Note:** Version bump only for package @typescript-eslint/parser + + + + + # [3.3.0](https://github.com/typescript-eslint/typescript-eslint/compare/v3.2.0...v3.3.0) (2020-06-15) **Note:** Version bump only for package @typescript-eslint/parser diff --git a/packages/parser/README.md b/packages/parser/README.md index 594f89dd6c29..02bb09e561a8 100644 --- a/packages/parser/README.md +++ b/packages/parser/README.md @@ -1,13 +1,11 @@

TypeScript ESLint Parser

-

An ESLint custom parser which leverages TypeScript ESTree to allow for ESLint to lint TypeScript source code.

+

An ESLint parser which leverages TypeScript ESTree to allow for ESLint to lint TypeScript source code.

- Azure Pipelines - GitHub license + CI NPM Version NPM Downloads - Commitizen friendly

## Getting Started @@ -20,8 +18,9 @@ These docs walk you through setting up ESLint, this parser, and our plugin. If y ### Installation -```sh -yarn add -D @typescript-eslint/parser +```bash +$ yarn add -D typescript @typescript-eslint/parser +$ npm i --save-dev typescript @typescript-eslint/parser ``` ### Usage diff --git a/packages/parser/package.json b/packages/parser/package.json index b9ca23514946..cf28e63968e7 100644 --- a/packages/parser/package.json +++ b/packages/parser/package.json @@ -1,6 +1,6 @@ { "name": "@typescript-eslint/parser", - "version": "3.3.0", + "version": "3.4.0", "description": "An ESLint custom parser which leverages TypeScript ESTree", "main": "dist/index.js", "types": "dist/index.d.ts", @@ -44,13 +44,13 @@ }, "dependencies": { "@types/eslint-visitor-keys": "^1.0.0", - "@typescript-eslint/experimental-utils": "3.3.0", - "@typescript-eslint/typescript-estree": "3.3.0", + "@typescript-eslint/experimental-utils": "3.4.0", + "@typescript-eslint/typescript-estree": "3.4.0", "eslint-visitor-keys": "^1.1.0" }, "devDependencies": { "@types/glob": "^7.1.1", - "@typescript-eslint/shared-fixtures": "3.3.0", + "@typescript-eslint/shared-fixtures": "3.4.0", "glob": "*" }, "peerDependenciesMeta": { diff --git a/packages/shared-fixtures/CHANGELOG.md b/packages/shared-fixtures/CHANGELOG.md index c3f5fcda81e9..42e10121707d 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. +# [3.4.0](https://github.com/typescript-eslint/typescript-eslint/compare/v3.3.0...v3.4.0) (2020-06-22) + +**Note:** Version bump only for package @typescript-eslint/shared-fixtures + + + + + # [3.3.0](https://github.com/typescript-eslint/typescript-eslint/compare/v3.2.0...v3.3.0) (2020-06-15) **Note:** Version bump only for package @typescript-eslint/shared-fixtures diff --git a/packages/shared-fixtures/README.md b/packages/shared-fixtures/README.md new file mode 100644 index 000000000000..866a6e866149 --- /dev/null +++ b/packages/shared-fixtures/README.md @@ -0,0 +1,7 @@ +

Fixtures for Testing typescript-eslint

+ +

Code fixtures used to test the parser. This is not intended for external use.

+ +

+ CI +

diff --git a/packages/shared-fixtures/package.json b/packages/shared-fixtures/package.json index b19dae20fe3a..4f5d0982ca50 100644 --- a/packages/shared-fixtures/package.json +++ b/packages/shared-fixtures/package.json @@ -1,6 +1,6 @@ { "name": "@typescript-eslint/shared-fixtures", - "version": "3.3.0", + "version": "3.4.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 e6b50349ca67..aad24b5c9073 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. +# [3.4.0](https://github.com/typescript-eslint/typescript-eslint/compare/v3.3.0...v3.4.0) (2020-06-22) + +**Note:** Version bump only for package @typescript-eslint/typescript-estree + + + + + # [3.3.0](https://github.com/typescript-eslint/typescript-eslint/compare/v3.2.0...v3.3.0) (2020-06-15) diff --git a/packages/typescript-estree/README.md b/packages/typescript-estree/README.md index 5ab7fe44a7b9..eafb1463d530 100644 --- a/packages/typescript-estree/README.md +++ b/packages/typescript-estree/README.md @@ -3,14 +3,14 @@

A parser that converts TypeScript source code into an ESTree-compatible form

- Azure Pipelines - GitHub license + CI NPM Version NPM Downloads - Commitizen friendly

-
+## Getting Started + +**[You can find our Getting Started docs here](../../docs/getting-started/linting/README.md)** ## About diff --git a/packages/typescript-estree/package.json b/packages/typescript-estree/package.json index a83b562bb417..e0d03e774e18 100644 --- a/packages/typescript-estree/package.json +++ b/packages/typescript-estree/package.json @@ -1,6 +1,6 @@ { "name": "@typescript-eslint/typescript-estree", - "version": "3.3.0", + "version": "3.4.0", "description": "A parser that converts TypeScript source code into an ESTree compatible form", "main": "dist/index.js", "types": "dist/index.d.ts", @@ -59,7 +59,7 @@ "@types/lodash": "^4.14.149", "@types/semver": "^7.1.0", "@types/tmp": "^0.2.0", - "@typescript-eslint/shared-fixtures": "3.3.0", + "@typescript-eslint/shared-fixtures": "3.4.0", "tmp": "^0.2.1", "typescript": "*" }, diff --git a/tools/generate-contributors.ts b/tools/generate-contributors.ts index 4c3c2b0a36d4..38c3690cb0a4 100644 --- a/tools/generate-contributors.ts +++ b/tools/generate-contributors.ts @@ -7,6 +7,7 @@ import 'isomorphic-fetch'; import * as path from 'path'; const IGNORED_USERS = new Set([ + 'dependabot[bot]', 'eslint[bot]', 'greenkeeper[bot]', 'semantic-release-bot', diff --git a/yarn.lock b/yarn.lock index 9b6fedc38d80..337037083ad9 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1750,7 +1750,7 @@ acorn@^6.0.1: resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.4.1.tgz#531e58ba3f51b9dacb9a6646ca4debf5b14ca474" integrity sha512-ZVA9k326Nwrj3Cj9jlh3wGFutC2ZornPNARZwsNYqQYgN0EsV2d53w5RN/co65Ohn4sUAUtb1rSUAOD6XN9idA== -acorn@^7.1.0, acorn@^7.1.1: +acorn@^7.1.0, acorn@^7.2.0: version "7.2.0" resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.2.0.tgz#17ea7e40d7c8640ff54a694c889c26f31704effe" integrity sha512-apwXVmYVpQ34m/i71vrApRrRKCWQnZZF1+npOD0WV5xZFfwWOmKGQ2RWlfdy9vWITsenisM8M0Qeq8agcFHNiQ== @@ -3614,6 +3614,14 @@ eslint-scope@^5.0.0: esrecurse "^4.1.0" estraverse "^4.1.1" +eslint-scope@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-5.1.0.tgz#d0f971dfe59c69e0cada684b23d49dbf82600ce5" + integrity sha512-iiGRvtxWqgtx5m8EyQUJihBloE4EnYeGE/bz1wSPwJE6tZuJUtHlhqDM4Xj2ukE8Dyy1+HCZ4hE0fzIVMzb58w== + dependencies: + esrecurse "^4.1.0" + estraverse "^4.1.1" + eslint-utils@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-2.0.0.tgz#7be1cc70f27a72a76cd14aa698bcabed6890e1cd" @@ -3626,10 +3634,15 @@ eslint-visitor-keys@^1.1.0: resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.1.0.tgz#e2a82cea84ff246ad6fb57f9bde5b46621459ec2" integrity sha512-8y9YjtM1JBJU/A9Kc+SbaOV4y29sSWckBwMHa+FGtVj5gN/sbnKDf6xJUl+8g7FAij9LVaP8C24DUiH/f/2Z9A== -eslint@^7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/eslint/-/eslint-7.0.0.tgz#c35dfd04a4372110bd78c69a8d79864273919a08" - integrity sha512-qY1cwdOxMONHJfGqw52UOpZDeqXy8xmD0u8CT6jIstil72jkhURC704W8CFyTPDPllz4z4lu0Ql1+07PG/XdIg== +eslint-visitor-keys@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.2.0.tgz#74415ac884874495f78ec2a97349525344c981fa" + integrity sha512-WFb4ihckKil6hu3Dp798xdzSfddwKKU3+nGniKF6HfeW6OLd2OUDEPP7TcHtB5+QXOKg2s6B2DaMPE1Nn/kxKQ== + +eslint@^7.2.0: + version "7.2.0" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-7.2.0.tgz#d41b2e47804b30dbabb093a967fb283d560082e6" + integrity sha512-B3BtEyaDKC5MlfDa2Ha8/D6DsS4fju95zs0hjS3HdGazw+LNayai38A25qMppK37wWGWNYSPOR6oYzlz5MHsRQ== dependencies: "@babel/code-frame" "^7.0.0" ajv "^6.10.0" @@ -3637,10 +3650,10 @@ eslint@^7.0.0: cross-spawn "^7.0.2" debug "^4.0.1" doctrine "^3.0.0" - eslint-scope "^5.0.0" + eslint-scope "^5.1.0" eslint-utils "^2.0.0" - eslint-visitor-keys "^1.1.0" - espree "^7.0.0" + eslint-visitor-keys "^1.2.0" + espree "^7.1.0" esquery "^1.2.0" esutils "^2.0.2" file-entry-cache "^5.0.1" @@ -3668,14 +3681,14 @@ eslint@^7.0.0: text-table "^0.2.0" v8-compile-cache "^2.0.3" -espree@^7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/espree/-/espree-7.0.0.tgz#8a7a60f218e69f120a842dc24c5a88aa7748a74e" - integrity sha512-/r2XEx5Mw4pgKdyb7GNLQNsu++asx/dltf/CI8RFi9oGHxmQFgvLbc5Op4U6i8Oaj+kdslhJtVlEZeAqH5qOTw== +espree@^7.1.0: + version "7.1.0" + resolved "https://registry.yarnpkg.com/espree/-/espree-7.1.0.tgz#a9c7f18a752056735bf1ba14cb1b70adc3a5ce1c" + integrity sha512-dcorZSyfmm4WTuTnE5Y7MEN1DyoPYy1ZR783QW1FJoenn7RailyWFsq/UL6ZAAA7uXurN9FIpYyUs3OfiIW+Qw== dependencies: - acorn "^7.1.1" + acorn "^7.2.0" acorn-jsx "^5.2.0" - eslint-visitor-keys "^1.1.0" + eslint-visitor-keys "^1.2.0" esprima@^2.7.0: version "2.7.3"