diff --git a/.eslintrc.js b/.eslintrc.js index c789421b024a..1c18917bbcbe 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -221,6 +221,15 @@ module.exports = { '@typescript-eslint/internal/plugin-test-formatting': 'error', }, }, + // files which list all the things + { + files: ['packages/eslint-plugin/src/rules/index.ts'], + rules: { + // enforce alphabetical ordering + 'sort-keys': 'error', + 'import/order': ['error', { alphabetize: { order: 'asc' } }], + }, + }, // tools and tests { files: ['**/tools/**/*.ts', '**/tests/**/*.ts'], diff --git a/.prettierignore b/.prettierignore index ac7951991af0..8212dba92beb 100644 --- a/.prettierignore +++ b/.prettierignore @@ -16,6 +16,8 @@ CONTRIBUTORS.md # Ignore CHANGELOG.md files to avoid issues with automated release job CHANGELOG.md -# TODO - remove this once prettier supports labelled tuples -packages/scope-manager/tests/fixtures/type-declaration/tuple-labelled.ts -packages/scope-manager/tests/fixtures/type-declaration/tuple-labelled-rest.ts +# TODO - remove this once prettier supports TS4.1 +packages/scope-manager/tests/fixtures/type-declaration/literal-type1.ts +packages/scope-manager/tests/fixtures/type-declaration/literal-type2.ts +packages/scope-manager/tests/fixtures/type-declaration/literal-type3.ts +packages/scope-manager/tests/fixtures/type-declaration/mapped-named.ts diff --git a/CHANGELOG.md b/CHANGELOG.md index 23c2b1f6053f..42c87af74e73 100644 --- a/CHANGELOG.md +++ b/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. +# [4.7.0](https://github.com/typescript-eslint/typescript-eslint/compare/v4.6.1...v4.7.0) (2020-11-09) + + +### Bug Fixes + +* **eslint-plugin:** [array-type] parenthesize ReadonlyArray fix ([#2747](https://github.com/typescript-eslint/typescript-eslint/issues/2747)) ([83385ac](https://github.com/typescript-eslint/typescript-eslint/commit/83385ac351f45d3bcbd19f72711838e9a8473827)) +* **eslint-plugin:** [no-extra-non-null-assertion] false positive with non-nullable computed key ([#2737](https://github.com/typescript-eslint/typescript-eslint/issues/2737)) ([e82698c](https://github.com/typescript-eslint/typescript-eslint/commit/e82698c0ec796e460e40c3dd90a30bd100db05c2)) + + +### Features + +* **eslint-plugin:** add rule `no-void-expression` ([#2605](https://github.com/typescript-eslint/typescript-eslint/issues/2605)) ([c8a4dad](https://github.com/typescript-eslint/typescript-eslint/commit/c8a4dadeab8a64fb4768deda8f65475435dd2cad)) +* support TS4.1 features ([#2748](https://github.com/typescript-eslint/typescript-eslint/issues/2748)) ([2be354b](https://github.com/typescript-eslint/typescript-eslint/commit/2be354bb15f9013a2da1b13a0c0836e9ef057e16)), closes [#2583](https://github.com/typescript-eslint/typescript-eslint/issues/2583) + + + + + ## [4.6.1](https://github.com/typescript-eslint/typescript-eslint/compare/v4.6.0...v4.6.1) (2020-11-02) diff --git a/lerna.json b/lerna.json index 937dd2ac582d..b57c134a4d70 100644 --- a/lerna.json +++ b/lerna.json @@ -1,5 +1,5 @@ { - "version": "4.6.1", + "version": "4.7.0", "npmClient": "yarn", "useWorkspaces": true, "stream": true diff --git a/package.json b/package.json index 60668f219cf2..aa878c185452 100644 --- a/package.json +++ b/package.json @@ -86,7 +86,7 @@ "all-contributors-cli": "^6.17.2", "cspell": "^4.1.0", "cz-conventional-changelog": "^3.3.0", - "downlevel-dts": "^0.6.0", + "downlevel-dts": "^0.7.0", "eslint": "^7.7.0", "eslint-plugin-eslint-comments": "^3.2.0", "eslint-plugin-eslint-plugin": "^2.3.0", @@ -106,9 +106,9 @@ "ts-jest": "^26.3.0", "ts-node": "^9.0.0", "tslint": "^6.1.3", - "typescript": ">=3.3.1 <4.1.0" + "typescript": ">=3.3.1 <4.2.0 || 4.1.1-rc" }, "resolutions": { - "typescript": "4.0.2" + "typescript": "4.1.1-rc" } } diff --git a/packages/eslint-plugin-internal/CHANGELOG.md b/packages/eslint-plugin-internal/CHANGELOG.md index 99ed098ea393..54df34bba4fb 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. +# [4.7.0](https://github.com/typescript-eslint/typescript-eslint/compare/v4.6.1...v4.7.0) (2020-11-09) + +**Note:** Version bump only for package @typescript-eslint/eslint-plugin-internal + + + + + ## [4.6.1](https://github.com/typescript-eslint/typescript-eslint/compare/v4.6.0...v4.6.1) (2020-11-02) **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 69dd33d6d79f..11fa6e86bd8f 100644 --- a/packages/eslint-plugin-internal/package.json +++ b/packages/eslint-plugin-internal/package.json @@ -1,6 +1,6 @@ { "name": "@typescript-eslint/eslint-plugin-internal", - "version": "4.6.1", + "version": "4.7.0", "private": true, "main": "dist/index.js", "scripts": { @@ -14,7 +14,7 @@ }, "dependencies": { "@types/prettier": "*", - "@typescript-eslint/experimental-utils": "4.6.1", + "@typescript-eslint/experimental-utils": "4.7.0", "prettier": "*" } } diff --git a/packages/eslint-plugin-tslint/CHANGELOG.md b/packages/eslint-plugin-tslint/CHANGELOG.md index 971dd4f6cf5d..eb4a5f2e9831 100644 --- a/packages/eslint-plugin-tslint/CHANGELOG.md +++ b/packages/eslint-plugin-tslint/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [4.7.0](https://github.com/typescript-eslint/typescript-eslint/compare/v4.6.1...v4.7.0) (2020-11-09) + +**Note:** Version bump only for package @typescript-eslint/eslint-plugin-tslint + + + + + ## [4.6.1](https://github.com/typescript-eslint/typescript-eslint/compare/v4.6.0...v4.6.1) (2020-11-02) **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 166e93177ade..02cf08776107 100644 --- a/packages/eslint-plugin-tslint/package.json +++ b/packages/eslint-plugin-tslint/package.json @@ -1,6 +1,6 @@ { "name": "@typescript-eslint/eslint-plugin-tslint", - "version": "4.6.1", + "version": "4.7.0", "main": "dist/index.js", "typings": "src/index.ts", "description": "TSLint wrapper plugin for ESLint", @@ -38,7 +38,7 @@ "typecheck": "tsc -p tsconfig.json --noEmit" }, "dependencies": { - "@typescript-eslint/experimental-utils": "4.6.1", + "@typescript-eslint/experimental-utils": "4.7.0", "lodash": "^4.17.15" }, "peerDependencies": { @@ -48,6 +48,6 @@ }, "devDependencies": { "@types/lodash": "*", - "@typescript-eslint/parser": "4.6.1" + "@typescript-eslint/parser": "4.7.0" } } diff --git a/packages/eslint-plugin/CHANGELOG.md b/packages/eslint-plugin/CHANGELOG.md index 2022362b2edd..860f51982352 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. +# [4.7.0](https://github.com/typescript-eslint/typescript-eslint/compare/v4.6.1...v4.7.0) (2020-11-09) + + +### Bug Fixes + +* **eslint-plugin:** [array-type] parenthesize ReadonlyArray fix ([#2747](https://github.com/typescript-eslint/typescript-eslint/issues/2747)) ([83385ac](https://github.com/typescript-eslint/typescript-eslint/commit/83385ac351f45d3bcbd19f72711838e9a8473827)) +* **eslint-plugin:** [no-extra-non-null-assertion] false positive with non-nullable computed key ([#2737](https://github.com/typescript-eslint/typescript-eslint/issues/2737)) ([e82698c](https://github.com/typescript-eslint/typescript-eslint/commit/e82698c0ec796e460e40c3dd90a30bd100db05c2)) + + +### Features + +* **eslint-plugin:** add rule `no-void-expression` ([#2605](https://github.com/typescript-eslint/typescript-eslint/issues/2605)) ([c8a4dad](https://github.com/typescript-eslint/typescript-eslint/commit/c8a4dadeab8a64fb4768deda8f65475435dd2cad)) +* support TS4.1 features ([#2748](https://github.com/typescript-eslint/typescript-eslint/issues/2748)) ([2be354b](https://github.com/typescript-eslint/typescript-eslint/commit/2be354bb15f9013a2da1b13a0c0836e9ef057e16)), closes [#2583](https://github.com/typescript-eslint/typescript-eslint/issues/2583) + + + + + ## [4.6.1](https://github.com/typescript-eslint/typescript-eslint/compare/v4.6.0...v4.6.1) (2020-11-02) diff --git a/packages/eslint-plugin/README.md b/packages/eslint-plugin/README.md index 9213a8d52735..4cf27e64a83c 100644 --- a/packages/eslint-plugin/README.md +++ b/packages/eslint-plugin/README.md @@ -117,6 +117,7 @@ Pro Tip: For larger codebases you may want to consider splitting our linting int | [`@typescript-eslint/naming-convention`](./docs/rules/naming-convention.md) | Enforces naming conventions for everything across a codebase | | | :thought_balloon: | | [`@typescript-eslint/no-base-to-string`](./docs/rules/no-base-to-string.md) | Requires that `.toString()` is only called on objects which provide useful information when stringified | | | :thought_balloon: | | [`@typescript-eslint/no-confusing-non-null-assertion`](./docs/rules/no-confusing-non-null-assertion.md) | Disallow non-null assertion in locations that may be confusing | | :wrench: | | +| [`@typescript-eslint/no-confusing-void-expression`](./docs/rules/no-confusing-void-expression.md) | Requires expressions of type void to appear in statement position | | :wrench: | :thought_balloon: | | [`@typescript-eslint/no-dynamic-delete`](./docs/rules/no-dynamic-delete.md) | Disallow the delete operator with computed key expressions | | :wrench: | | | [`@typescript-eslint/no-empty-interface`](./docs/rules/no-empty-interface.md) | Disallow the declaration of empty interfaces | :heavy_check_mark: | :wrench: | | | [`@typescript-eslint/no-explicit-any`](./docs/rules/no-explicit-any.md) | Disallow usage of the `any` type | :heavy_check_mark: | :wrench: | | @@ -125,7 +126,6 @@ Pro Tip: For larger codebases you may want to consider splitting our linting int | [`@typescript-eslint/no-floating-promises`](./docs/rules/no-floating-promises.md) | Requires Promise-like values to be handled appropriately | :heavy_check_mark: | | :thought_balloon: | | [`@typescript-eslint/no-for-in-array`](./docs/rules/no-for-in-array.md) | Disallow iterating over an array with a for-in loop | :heavy_check_mark: | | :thought_balloon: | | [`@typescript-eslint/no-implicit-any-catch`](./docs/rules/no-implicit-any-catch.md) | Disallow usage of the implicit `any` type in catch clauses | | :wrench: | | -| [`@typescript-eslint/no-implied-eval`](./docs/rules/no-implied-eval.md) | Disallow the use of `eval()`-like methods | :heavy_check_mark: | | :thought_balloon: | | [`@typescript-eslint/no-inferrable-types`](./docs/rules/no-inferrable-types.md) | Disallows explicit type declarations for variables or parameters initialized to a number, string, or boolean | :heavy_check_mark: | :wrench: | | | [`@typescript-eslint/no-invalid-void-type`](./docs/rules/no-invalid-void-type.md) | Disallows usage of `void` type outside of generic or return types | | | | | [`@typescript-eslint/no-misused-new`](./docs/rules/no-misused-new.md) | Enforce valid definition of `new` and `constructor` | :heavy_check_mark: | | | @@ -136,7 +136,6 @@ Pro Tip: For larger codebases you may want to consider splitting our linting int | [`@typescript-eslint/no-parameter-properties`](./docs/rules/no-parameter-properties.md) | Disallow the use of parameter properties in class constructors | | | | | [`@typescript-eslint/no-require-imports`](./docs/rules/no-require-imports.md) | Disallows invocation of `require()` | | | | | [`@typescript-eslint/no-this-alias`](./docs/rules/no-this-alias.md) | Disallow aliasing `this` | :heavy_check_mark: | | | -| [`@typescript-eslint/no-throw-literal`](./docs/rules/no-throw-literal.md) | Disallow throwing literals as exceptions | | | :thought_balloon: | | [`@typescript-eslint/no-type-alias`](./docs/rules/no-type-alias.md) | Disallow the use of type aliases | | | | | [`@typescript-eslint/no-unnecessary-boolean-literal-compare`](./docs/rules/no-unnecessary-boolean-literal-compare.md) | Flags unnecessary equality comparisons against boolean literals | | :wrench: | :thought_balloon: | | [`@typescript-eslint/no-unnecessary-condition`](./docs/rules/no-unnecessary-condition.md) | Prevents conditionals where the type is always truthy or always falsy | | :wrench: | :thought_balloon: | @@ -205,12 +204,14 @@ In these cases, we create what we call an extension rule; a rule within our plug | [`@typescript-eslint/no-empty-function`](./docs/rules/no-empty-function.md) | Disallow empty functions | :heavy_check_mark: | | | | [`@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-implied-eval`](./docs/rules/no-implied-eval.md) | Disallow the use of `eval()`-like methods | :heavy_check_mark: | | :thought_balloon: | +| [`@typescript-eslint/no-invalid-this`](./docs/rules/no-invalid-this.md) | Disallow `this` keywords outside of classes or class-like objects | | | | | [`@typescript-eslint/no-loop-func`](./docs/rules/no-loop-func.md) | Disallow function declarations that contain unsafe references inside loop statements | | | | | [`@typescript-eslint/no-loss-of-precision`](./docs/rules/no-loss-of-precision.md) | Disallow literal numbers that lose precision | | | | | [`@typescript-eslint/no-magic-numbers`](./docs/rules/no-magic-numbers.md) | Disallow magic numbers | | | | | [`@typescript-eslint/no-redeclare`](./docs/rules/no-redeclare.md) | Disallow variable redeclaration | | | | | [`@typescript-eslint/no-shadow`](./docs/rules/no-shadow.md) | Disallow variable declarations from shadowing variables declared in the outer scope | | | | +| [`@typescript-eslint/no-throw-literal`](./docs/rules/no-throw-literal.md) | Disallow throwing literals as exceptions | | | :thought_balloon: | | [`@typescript-eslint/no-unused-expressions`](./docs/rules/no-unused-expressions.md) | Disallow unused expressions | | | | | [`@typescript-eslint/no-unused-vars`](./docs/rules/no-unused-vars.md) | Disallow unused variables | :heavy_check_mark: | | | | [`@typescript-eslint/no-use-before-define`](./docs/rules/no-use-before-define.md) | Disallow the use of variables before they are defined | | | | diff --git a/packages/eslint-plugin/ROADMAP.md b/packages/eslint-plugin/ROADMAP.md index aece78f33577..749ba2bdf829 100644 --- a/packages/eslint-plugin/ROADMAP.md +++ b/packages/eslint-plugin/ROADMAP.md @@ -96,7 +96,7 @@ It lists all TSLint rules along side rules from the ESLint ecosystem that are th | [`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`] | 🛑 | N/A (unrelated to the similarly named ESLint rule `no-void`) | +| [`no-void-expression`] | ✅ | [`@typescript-eslint/no-confusing-void-expression`] | | [`prefer-conditional-expression`] | 🛑 | N/A | | [`prefer-object-spread`] | 🌟 | [`prefer-object-spread`][prefer-object-spread] | | [`radix`] | 🌟 | [`radix`][radix] | @@ -650,6 +650,8 @@ Relevant plugins: [`chai-expect-keywords`](https://github.com/gavinaiken/eslint- [`@typescript-eslint/no-floating-promises`]: https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/no-floating-promises.md [`@typescript-eslint/no-magic-numbers`]: https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/no-magic-numbers.md [`@typescript-eslint/no-unsafe-member-access`]: https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/no-unsafe-member-access.md +[`@typescript-eslint/restrict-template-expressions`]: https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/restrict-template-expressions.md +[`@typescript-eslint/no-confusing-void-expression`]: https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/no-confusing-void-expression.md diff --git a/packages/eslint-plugin/docs/rules/no-confusing-void-expression.md b/packages/eslint-plugin/docs/rules/no-confusing-void-expression.md new file mode 100644 index 000000000000..8a00255170d5 --- /dev/null +++ b/packages/eslint-plugin/docs/rules/no-confusing-void-expression.md @@ -0,0 +1,149 @@ +# Requires expressions of type void to appear in statement position (`no-confusing-void-expression`) + +Returning the results of an expression whose type is void can be misleading. +Attempting to do so is likely a symptom of expecting a different return type from a function. +Even if used correctly, it can be misleading for other developers, +who don't know what a particular function does and if its result matters. + +This rule provides automatic fixes for most common cases. + +## Examples + +Examples of **incorrect** code for this rule: + +```ts +// somebody forgot that `alert` doesn't return anything +const response = alert('Are you sure?'); +console.log(alert('Are you sure?')); + +// it's not obvious whether the chained promise will contain the response (fixable) +promise.then(value => window.postMessage(value)); + +// it looks like we are returning the result of `console.error` (fixable) +function doSomething() { + if (!somethingToDo) { + return console.error('Nothing to do!'); + } + + console.log('Doing a thing...'); +} +``` + +Examples of **correct** code for this rule: + +```ts +// just a regular void function in a statement position +alert('Hello, world!'); + +// this function returns a boolean value so it's ok +const response = confirm('Are you sure?'); +console.log(confirm('Are you sure?')); + +// now it's obvious that `postMessage` doesn't return any response +promise.then(value => { + window.postMessage(value); +}); + +// now it's explicit that we want to log the error and return early +function doSomething() { + if (!somethingToDo) { + console.error('Nothing to do!'); + return; + } + + console.log('Doing a thing...'); +} + +// using logical expressions for their side effects is fine +cond && console.log('true'); +cond || console.error('false'); +cond ? console.log('true') : console.error('false'); +``` + +## Options + +An object option can be specified. Each boolean flag makes the rule less strict. + +```ts +type Options = { + ignoreArrowShorthand?: boolean; + ignoreVoidOperator?: boolean; +}; + +const defaults: Options = { + ignoreArrowShorthand: false, + ignoreVoidOperator: false, +}; +``` + +### `ignoreArrowShorthand` + +`false` by default. + +```json +{ + "@typescript-eslint/no-confusing-void-expression": [ + "error", + { "ignoreArrowShorthand": true } + ] +} +``` + +It might be undesirable to wrap every arrow function shorthand expression with braces. +Especially when using Prettier formatter, which spreads such code across 3 lines instead of 1. + +Examples of additional **correct** code with this option enabled: + +```ts +promise.then(value => window.postMessage(value)); +``` + +### `ignoreVoidOperator` + +`false` by default. + +```json +{ + "@typescript-eslint/no-confusing-void-expression": [ + "error", + { "ignoreVoidOperator": true } + ] +} +``` + +It might be preferable to only use some distinct syntax +to explicitly mark the confusing but valid usage of void expressions. +This option allows void expressions which are explicitly wrapped in the `void` operator. +This can help avoid confusion among other developers as long as they are made aware of this code style. + +This option also changes the automatic fixes for common cases to use the `void` operator. +It also enables a suggestion fix to wrap the void expression with `void` operator for every problem reported. + +Examples of additional **correct** code with this option enabled: + +```ts +// now it's obvious that we don't expect any response +promise.then(value => void window.postMessage(value)); + +// now it's explicit that we don't want to return anything +function doSomething() { + if (!somethingToDo) { + return void console.error('Nothing to do!'); + } + + console.log('Doing a thing...'); +} + +// we are sure that we want to always log `undefined` +console.log(void alert('Hello, world!')); +``` + +## When Not To Use It + +The return type of a function can be inspected by going to its definition or hovering over it in an IDE. +If you don't care about being explicit about the void type in actual code then don't use this rule. +Also, if you prefer concise coding style then also don't use it. + +## Related to + +- TSLint: ['no-void-expression'](https://palantir.github.io/tslint/rules/no-void-expression/) diff --git a/packages/eslint-plugin/docs/rules/no-invalid-this.md b/packages/eslint-plugin/docs/rules/no-invalid-this.md index 728c42b7f2cf..a7f907380af9 100644 --- a/packages/eslint-plugin/docs/rules/no-invalid-this.md +++ b/packages/eslint-plugin/docs/rules/no-invalid-this.md @@ -1,4 +1,4 @@ -# disallow `this` keywords outside of classes or class-like objects (`no-invalid-this`) +# Disallow `this` keywords outside of classes or class-like objects (`no-invalid-this`) ## Rule Details diff --git a/packages/eslint-plugin/package.json b/packages/eslint-plugin/package.json index 44c3d3efbb31..6f50dbb60310 100644 --- a/packages/eslint-plugin/package.json +++ b/packages/eslint-plugin/package.json @@ -1,6 +1,6 @@ { "name": "@typescript-eslint/eslint-plugin", - "version": "4.6.1", + "version": "4.7.0", "description": "TypeScript plugin for ESLint", "keywords": [ "eslint", @@ -42,8 +42,8 @@ "typecheck": "tsc -p tsconfig.json --noEmit" }, "dependencies": { - "@typescript-eslint/experimental-utils": "4.6.1", - "@typescript-eslint/scope-manager": "4.6.1", + "@typescript-eslint/experimental-utils": "4.7.0", + "@typescript-eslint/scope-manager": "4.7.0", "debug": "^4.1.1", "functional-red-black-tree": "^1.0.1", "regexpp": "^3.0.0", diff --git a/packages/eslint-plugin/src/configs/all.ts b/packages/eslint-plugin/src/configs/all.ts index d847322d9860..07234c9950f5 100644 --- a/packages/eslint-plugin/src/configs/all.ts +++ b/packages/eslint-plugin/src/configs/all.ts @@ -47,6 +47,7 @@ export = { '@typescript-eslint/no-array-constructor': 'error', '@typescript-eslint/no-base-to-string': 'error', '@typescript-eslint/no-confusing-non-null-assertion': 'error', + '@typescript-eslint/no-confusing-void-expression': 'error', 'no-dupe-class-members': 'off', '@typescript-eslint/no-dupe-class-members': 'error', 'no-duplicate-imports': 'off', @@ -65,6 +66,7 @@ export = { '@typescript-eslint/no-floating-promises': 'error', '@typescript-eslint/no-for-in-array': 'error', '@typescript-eslint/no-implicit-any-catch': 'error', + 'no-implied-eval': 'off', '@typescript-eslint/no-implied-eval': 'error', '@typescript-eslint/no-inferrable-types': 'error', 'no-invalid-this': 'off', @@ -88,14 +90,15 @@ export = { 'no-shadow': 'off', '@typescript-eslint/no-shadow': 'error', '@typescript-eslint/no-this-alias': 'error', + 'no-throw-literal': 'off', '@typescript-eslint/no-throw-literal': 'error', '@typescript-eslint/no-type-alias': 'error', '@typescript-eslint/no-unnecessary-boolean-literal-compare': 'error', '@typescript-eslint/no-unnecessary-condition': 'error', - '@typescript-eslint/no-unnecessary-type-constraint': 'error', '@typescript-eslint/no-unnecessary-qualifier': 'error', '@typescript-eslint/no-unnecessary-type-arguments': 'error', '@typescript-eslint/no-unnecessary-type-assertion': 'error', + '@typescript-eslint/no-unnecessary-type-constraint': 'error', '@typescript-eslint/no-unsafe-assignment': 'error', '@typescript-eslint/no-unsafe-call': 'error', '@typescript-eslint/no-unsafe-member-access': 'error', diff --git a/packages/eslint-plugin/src/configs/recommended-requiring-type-checking.ts b/packages/eslint-plugin/src/configs/recommended-requiring-type-checking.ts index 40872fa72f35..fecfa6002af9 100644 --- a/packages/eslint-plugin/src/configs/recommended-requiring-type-checking.ts +++ b/packages/eslint-plugin/src/configs/recommended-requiring-type-checking.ts @@ -8,6 +8,7 @@ export = { '@typescript-eslint/await-thenable': 'error', '@typescript-eslint/no-floating-promises': 'error', '@typescript-eslint/no-for-in-array': 'error', + 'no-implied-eval': 'off', '@typescript-eslint/no-implied-eval': 'error', '@typescript-eslint/no-misused-promises': 'error', '@typescript-eslint/no-unnecessary-type-assertion': 'error', diff --git a/packages/eslint-plugin/src/rules/array-type.ts b/packages/eslint-plugin/src/rules/array-type.ts index c77e2fa59fd9..8c97729623a7 100644 --- a/packages/eslint-plugin/src/rules/array-type.ts +++ b/packages/eslint-plugin/src/rules/array-type.ts @@ -244,7 +244,14 @@ export default util.createRule({ } const type = typeParams[0]; - const parens = typeNeedsParentheses(type); + const typeParens = typeNeedsParentheses(type); + const parentParens = + readonlyPrefix && node.parent?.type === AST_NODE_TYPES.TSArrayType; + + const start = `${parentParens ? '(' : ''}${readonlyPrefix}${ + typeParens ? '(' : '' + }`; + const end = `${typeParens ? ')' : ''}[]${parentParens ? ')' : ''}`; context.report({ node, @@ -254,14 +261,8 @@ export default util.createRule({ }, fix(fixer) { return [ - fixer.replaceTextRange( - [node.range[0], type.range[0]], - `${readonlyPrefix}${parens ? '(' : ''}`, - ), - fixer.replaceTextRange( - [type.range[1], node.range[1]], - parens ? ')[]' : '[]', - ), + fixer.replaceTextRange([node.range[0], type.range[0]], start), + fixer.replaceTextRange([type.range[1], node.range[1]], end), ]; }, }); diff --git a/packages/eslint-plugin/src/rules/index.ts b/packages/eslint-plugin/src/rules/index.ts index a4540aa5788d..de982a91d87c 100644 --- a/packages/eslint-plugin/src/rules/index.ts +++ b/packages/eslint-plugin/src/rules/index.ts @@ -8,14 +8,12 @@ import braceStyle from './brace-style'; import classLiteralPropertyStyle from './class-literal-property-style'; import commaDangle from './comma-dangle'; import commaSpacing from './comma-spacing'; -import confusingNonNullAssertionLikeNotEqual from './no-confusing-non-null-assertion'; import consistentIndexedObjectStyle from './consistent-indexed-object-style'; import consistentTypeAssertions from './consistent-type-assertions'; import consistentTypeDefinitions from './consistent-type-definitions'; import consistentTypeImports from './consistent-type-imports'; import defaultParamLast from './default-param-last'; import dotNotation from './dot-notation'; -import enumMembersSpacing from './space-infix-ops'; import explicitFunctionReturnType from './explicit-function-return-type'; import explicitMemberAccessibility from './explicit-member-accessibility'; import explicitModuleBoundaryTypes from './explicit-module-boundary-types'; @@ -30,25 +28,27 @@ import methodSignatureStyle from './method-signature-style'; import namingConvention from './naming-convention'; import noArrayConstructor from './no-array-constructor'; import noBaseToString from './no-base-to-string'; +import confusingNonNullAssertionLikeNotEqual from './no-confusing-non-null-assertion'; +import noConfusingVoidExpression from './no-confusing-void-expression'; import noDupeClassMembers from './no-dupe-class-members'; +import noDuplicateImports from './no-duplicate-imports'; import noDynamicDelete from './no-dynamic-delete'; import noEmptyFunction from './no-empty-function'; import noEmptyInterface from './no-empty-interface'; import noExplicitAny from './no-explicit-any'; -import noImplicitAnyCatch from './no-implicit-any-catch'; -import noExtraneousClass from './no-extraneous-class'; import noExtraNonNullAssertion from './no-extra-non-null-assertion'; import noExtraParens from './no-extra-parens'; import noExtraSemi from './no-extra-semi'; +import noExtraneousClass from './no-extraneous-class'; import noFloatingPromises from './no-floating-promises'; import noForInArray from './no-for-in-array'; -import preferLiteralEnumMember from './prefer-literal-enum-member'; +import noImplicitAnyCatch from './no-implicit-any-catch'; import noImpliedEval from './no-implied-eval'; import noInferrableTypes from './no-inferrable-types'; import noInvalidThis from './no-invalid-this'; import noInvalidVoidType from './no-invalid-void-type'; -import noLossOfPrecision from './no-loss-of-precision'; import noLoopFunc from './no-loop-func'; +import noLossOfPrecision from './no-loss-of-precision'; import noMagicNumbers from './no-magic-numbers'; import noMisusedNew from './no-misused-new'; import noMisusedPromises from './no-misused-promises'; @@ -83,6 +83,7 @@ import preferEnumInitializers from './prefer-enum-initializers'; import preferForOf from './prefer-for-of'; import preferFunctionType from './prefer-function-type'; import preferIncludes from './prefer-includes'; +import preferLiteralEnumMember from './prefer-literal-enum-member'; import preferNamespaceKeyword from './prefer-namespace-keyword'; import preferNullishCoalescing from './prefer-nullish-coalescing'; import preferOptionalChain from './prefer-optional-chain'; @@ -101,6 +102,7 @@ import restrictTemplateExpressions from './restrict-template-expressions'; import returnAwait from './return-await'; import semi from './semi'; import spaceBeforeFunctionParen from './space-before-function-paren'; +import spaceInfixOps from './space-infix-ops'; import strictBooleanExpressions from './strict-boolean-expressions'; import switchExhaustivenessCheck from './switch-exhaustiveness-check'; import tripleSlashReference from './triple-slash-reference'; @@ -108,7 +110,6 @@ import typeAnnotationSpacing from './type-annotation-spacing'; import typedef from './typedef'; import unboundMethod from './unbound-method'; import unifiedSignatures from './unified-signatures'; -import noDuplicateImports from './no-duplicate-imports'; export default { 'adjacent-overload-signatures': adjacentOverloadSignatures, @@ -127,11 +128,11 @@ export default { 'consistent-type-imports': consistentTypeImports, 'default-param-last': defaultParamLast, 'dot-notation': dotNotation, - 'space-infix-ops': enumMembersSpacing, 'explicit-function-return-type': explicitFunctionReturnType, 'explicit-member-accessibility': explicitMemberAccessibility, 'explicit-module-boundary-types': explicitModuleBoundaryTypes, 'func-call-spacing': funcCallSpacing, + indent: indent, 'init-declarations': initDeclarations, 'keyword-spacing': keywordSpacing, 'lines-between-class-members': linesBetweenClassMembers, @@ -142,7 +143,9 @@ export default { 'no-array-constructor': noArrayConstructor, 'no-base-to-string': noBaseToString, 'no-confusing-non-null-assertion': confusingNonNullAssertionLikeNotEqual, + 'no-confusing-void-expression': noConfusingVoidExpression, 'no-dupe-class-members': noDupeClassMembers, + 'no-duplicate-imports': noDuplicateImports, 'no-dynamic-delete': noDynamicDelete, 'no-empty-function': noEmptyFunction, 'no-empty-interface': noEmptyInterface, @@ -184,8 +187,8 @@ export default { 'no-unsafe-member-access': noUnsafeMemberAccess, 'no-unsafe-return': noUnsafeReturn, 'no-unused-expressions': noUnusedExpressions, - 'no-unused-vars-experimental': noUnusedVarsExperimental, 'no-unused-vars': noUnusedVars, + 'no-unused-vars-experimental': noUnusedVarsExperimental, 'no-use-before-define': noUseBeforeDefine, 'no-useless-constructor': noUselessConstructor, 'no-var-requires': noVarRequires, @@ -198,28 +201,27 @@ export default { 'prefer-namespace-keyword': preferNamespaceKeyword, 'prefer-nullish-coalescing': preferNullishCoalescing, 'prefer-optional-chain': preferOptionalChain, - 'prefer-readonly-parameter-types': preferReadonlyParameterTypes, 'prefer-readonly': preferReadonly, + 'prefer-readonly-parameter-types': preferReadonlyParameterTypes, 'prefer-reduce-type-parameter': preferReduceTypeParameter, 'prefer-regexp-exec': preferRegexpExec, 'prefer-string-starts-ends-with': preferStringStartsEndsWith, 'prefer-ts-expect-error': preferTsExpectError, 'promise-function-async': promiseFunctionAsync, + quotes: quotes, 'require-array-sort-compare': requireArraySortCompare, 'require-await': requireAwait, 'restrict-plus-operands': restrictPlusOperands, 'restrict-template-expressions': restrictTemplateExpressions, 'return-await': returnAwait, + semi: semi, 'space-before-function-paren': spaceBeforeFunctionParen, + 'space-infix-ops': spaceInfixOps, 'strict-boolean-expressions': strictBooleanExpressions, 'switch-exhaustiveness-check': switchExhaustivenessCheck, 'triple-slash-reference': tripleSlashReference, 'type-annotation-spacing': typeAnnotationSpacing, + typedef: typedef, 'unbound-method': unboundMethod, 'unified-signatures': unifiedSignatures, - 'no-duplicate-imports': noDuplicateImports, - indent: indent, - quotes: quotes, - semi: semi, - typedef: typedef, }; diff --git a/packages/eslint-plugin/src/rules/no-confusing-void-expression.ts b/packages/eslint-plugin/src/rules/no-confusing-void-expression.ts new file mode 100644 index 000000000000..a9b715350e99 --- /dev/null +++ b/packages/eslint-plugin/src/rules/no-confusing-void-expression.ts @@ -0,0 +1,331 @@ +import { + AST_NODE_TYPES, + TSESLint, + TSESTree, +} from '@typescript-eslint/experimental-utils'; +import * as tsutils from 'tsutils'; +import * as ts from 'typescript'; +import * as util from '../util'; + +export type Options = [ + { + ignoreArrowShorthand?: boolean; + ignoreVoidOperator?: boolean; + }, +]; + +export type MessageId = + | 'invalidVoidExpr' + | 'invalidVoidExprWrapVoid' + | 'invalidVoidExprArrow' + | 'invalidVoidExprArrowWrapVoid' + | 'invalidVoidExprReturn' + | 'invalidVoidExprReturnLast' + | 'invalidVoidExprReturnWrapVoid' + | 'voidExprWrapVoid'; + +export default util.createRule({ + name: 'no-confusing-void-expression', + meta: { + docs: { + description: + 'Requires expressions of type void to appear in statement position', + category: 'Best Practices', + recommended: false, + requiresTypeChecking: true, + }, + messages: { + invalidVoidExpr: + 'Placing a void expression inside another expression is forbidden. ' + + 'Move it to its own statement instead.', + invalidVoidExprWrapVoid: + 'Void expressions used inside another expression ' + + 'must be moved to its own statement ' + + 'or marked explicitly with the `void` operator.', + invalidVoidExprArrow: + 'Returning a void expression from an arrow function shorthand is forbidden. ' + + 'Please add braces to the arrow function.', + invalidVoidExprArrowWrapVoid: + 'Void expressions returned from an arrow function shorthand ' + + 'must be marked explicitly with the `void` operator.', + invalidVoidExprReturn: + 'Returning a void expression from a function is forbidden. ' + + 'Please move it before the `return` statement.', + invalidVoidExprReturnLast: + 'Returning a void expression from a function is forbidden. ' + + 'Please remove the `return` statement.', + invalidVoidExprReturnWrapVoid: + 'Void expressions returned from a function ' + + 'must be marked explicitly with the `void` operator.', + voidExprWrapVoid: 'Mark with an explicit `void` operator', + }, + schema: [ + { + type: 'object', + properties: { + ignoreArrowShorthand: { type: 'boolean' }, + ignoreVoidOperator: { type: 'boolean' }, + }, + additionalProperties: false, + }, + ], + type: 'problem', + fixable: 'code', + }, + defaultOptions: [{}], + + create(context, [options]) { + return { + 'AwaitExpression, CallExpression, TaggedTemplateExpression'( + node: + | TSESTree.AwaitExpression + | TSESTree.CallExpression + | TSESTree.TaggedTemplateExpression, + ): void { + const parserServices = util.getParserServices(context); + const checker = parserServices.program.getTypeChecker(); + const tsNode = parserServices.esTreeNodeToTSNodeMap.get(node); + const type = util.getConstrainedTypeAtLocation(checker, tsNode); + if (!tsutils.isTypeFlagSet(type, ts.TypeFlags.VoidLike)) { + // not a void expression + return; + } + + const invalidAncestor = findInvalidAncestor(node); + if (invalidAncestor == null) { + // void expression is in valid position + return; + } + + const sourceCode = context.getSourceCode(); + const wrapVoidFix = (fixer: TSESLint.RuleFixer): TSESLint.RuleFix => { + const nodeText = sourceCode.getText(node); + const newNodeText = `void ${nodeText}`; + return fixer.replaceText(node, newNodeText); + }; + + if (invalidAncestor.type === AST_NODE_TYPES.ArrowFunctionExpression) { + // handle arrow function shorthand + + if (options.ignoreVoidOperator) { + // handle wrapping with `void` + return context.report({ + node, + messageId: 'invalidVoidExprArrowWrapVoid', + fix: wrapVoidFix, + }); + } + + // handle wrapping with braces + const arrowFunction = invalidAncestor; + return context.report({ + node, + messageId: 'invalidVoidExprArrow', + fix(fixer) { + const arrowBody = arrowFunction.body; + const arrowBodyText = sourceCode.getText(arrowBody); + const newArrowBodyText = `{ ${arrowBodyText}; }`; + if (util.isParenthesized(arrowBody, sourceCode)) { + const bodyOpeningParen = sourceCode.getTokenBefore( + arrowBody, + util.isOpeningParenToken, + )!; + const bodyClosingParen = sourceCode.getTokenAfter( + arrowBody, + util.isClosingParenToken, + )!; + return fixer.replaceTextRange( + [bodyOpeningParen.range[0], bodyClosingParen.range[1]], + newArrowBodyText, + ); + } + return fixer.replaceText(arrowBody, newArrowBodyText); + }, + }); + } + + if (invalidAncestor.type === AST_NODE_TYPES.ReturnStatement) { + // handle return statement + + if (options.ignoreVoidOperator) { + // handle wrapping with `void` + return context.report({ + node, + messageId: 'invalidVoidExprReturnWrapVoid', + fix: wrapVoidFix, + }); + } + + const returnStmt = invalidAncestor; + + if (isFinalReturn(returnStmt)) { + // remove the `return` keyword + return context.report({ + node, + messageId: 'invalidVoidExprReturnLast', + fix(fixer) { + const returnValue = returnStmt.argument!; + const returnValueText = sourceCode.getText(returnValue); + let newReturnStmtText = `${returnValueText};`; + if (isPreventingASI(returnValue, sourceCode)) { + // put a semicolon at the beginning of the line + newReturnStmtText = `;${newReturnStmtText}`; + } + return fixer.replaceText(returnStmt, newReturnStmtText); + }, + }); + } + + // move before the `return` keyword + return context.report({ + node, + messageId: 'invalidVoidExprReturn', + fix(fixer) { + const returnValue = returnStmt.argument!; + const returnValueText = sourceCode.getText(returnValue); + let newReturnStmtText = `${returnValueText}; return;`; + if (isPreventingASI(returnValue, sourceCode)) { + // put a semicolon at the beginning of the line + newReturnStmtText = `;${newReturnStmtText}`; + } + if (returnStmt.parent?.type !== AST_NODE_TYPES.BlockStatement) { + // e.g. `if (cond) return console.error();` + // add braces if not inside a block + newReturnStmtText = `{ ${newReturnStmtText} }`; + } + return fixer.replaceText(returnStmt, newReturnStmtText); + }, + }); + } + + // handle generic case + if (options.ignoreVoidOperator) { + // this would be reported by this rule btw. such irony + return context.report({ + node, + messageId: 'invalidVoidExprWrapVoid', + suggest: [{ messageId: 'voidExprWrapVoid', fix: wrapVoidFix }], + }); + } + context.report({ + node, + messageId: 'invalidVoidExpr', + }); + }, + }; + + /** + * Inspects the void expression's ancestors and finds closest invalid one. + * By default anything other than an ExpressionStatement is invalid. + * Parent expressions which can be used for their short-circuiting behavior + * are ignored and their parents are checked instead. + * @param node The void expression node to check. + * @returns Invalid ancestor node if it was found. `null` otherwise. + */ + function findInvalidAncestor(node: TSESTree.Node): TSESTree.Node | null { + const parent = util.nullThrows( + node.parent, + util.NullThrowsReasons.MissingParent, + ); + + if (parent.type === AST_NODE_TYPES.ExpressionStatement) { + // e.g. `{ console.log("foo"); }` + // this is always valid + return null; + } + + if (parent.type === AST_NODE_TYPES.LogicalExpression) { + if (parent.right === node) { + // e.g. `x && console.log(x)` + // this is valid only if the next ancestor is valid + return findInvalidAncestor(parent); + } + } + + if (parent.type === AST_NODE_TYPES.ConditionalExpression) { + if (parent.consequent === node || parent.alternate === node) { + // e.g. `cond ? console.log(true) : console.log(false)` + // this is valid only if the next ancestor is valid + return findInvalidAncestor(parent); + } + } + + if (parent.type === AST_NODE_TYPES.ArrowFunctionExpression) { + // e.g. `() => console.log("foo")` + // this is valid with an appropriate option + if (options.ignoreArrowShorthand) { + return null; + } + } + + if (parent.type === AST_NODE_TYPES.UnaryExpression) { + if (parent.operator === 'void') { + // e.g. `void console.log("foo")` + // this is valid with an appropriate option + if (options.ignoreVoidOperator) { + return null; + } + } + } + + // any other parent is invalid + return parent; + } + + /** Checks whether the return statement is the last statement in a function body. */ + function isFinalReturn(node: TSESTree.ReturnStatement): boolean { + // the parent must be a block + const block = util.nullThrows( + node.parent, + util.NullThrowsReasons.MissingParent, + ); + if (block.type !== AST_NODE_TYPES.BlockStatement) { + // e.g. `if (cond) return;` (not in a block) + return false; + } + + // the block's parent must be a function + const blockParent = util.nullThrows( + block.parent, + util.NullThrowsReasons.MissingParent, + ); + if ( + ![ + AST_NODE_TYPES.FunctionDeclaration, + AST_NODE_TYPES.FunctionExpression, + AST_NODE_TYPES.ArrowFunctionExpression, + ].includes(blockParent.type) + ) { + // e.g. `if (cond) { return; }` + // not in a top-level function block + return false; + } + + // must be the last child of the block + if (block.body.indexOf(node) < block.body.length - 1) { + // not the last statement in the block + return false; + } + + return true; + } + + /** + * Checks whether the given node, if placed on its own line, + * would prevent automatic semicolon insertion on the line before. + * + * This happens if the line begins with `(`, `[` or `` ` `` + */ + function isPreventingASI( + node: TSESTree.Expression, + sourceCode: Readonly, + ): boolean { + const startToken = util.nullThrows( + sourceCode.getFirstToken(node), + util.NullThrowsReasons.MissingToken('first token', node.type), + ); + + return ['(', '[', '`'].includes(startToken.value); + } + }, +}); diff --git a/packages/eslint-plugin/src/rules/no-extra-non-null-assertion.ts b/packages/eslint-plugin/src/rules/no-extra-non-null-assertion.ts index b0b4921dfaf1..b58edd99ed6a 100644 --- a/packages/eslint-plugin/src/rules/no-extra-non-null-assertion.ts +++ b/packages/eslint-plugin/src/rules/no-extra-non-null-assertion.ts @@ -32,7 +32,7 @@ export default util.createRule({ return { 'TSNonNullExpression > TSNonNullExpression': checkExtraNonNullAssertion, - 'MemberExpression[optional = true] > TSNonNullExpression': checkExtraNonNullAssertion, + 'MemberExpression[optional = true] > TSNonNullExpression.object': checkExtraNonNullAssertion, 'CallExpression[optional = true] > TSNonNullExpression.callee': checkExtraNonNullAssertion, }; }, diff --git a/packages/eslint-plugin/src/rules/no-implied-eval.ts b/packages/eslint-plugin/src/rules/no-implied-eval.ts index 1e063847da3f..25eac2adbc65 100644 --- a/packages/eslint-plugin/src/rules/no-implied-eval.ts +++ b/packages/eslint-plugin/src/rules/no-implied-eval.ts @@ -22,6 +22,7 @@ export default util.createRule({ description: 'Disallow the use of `eval()`-like methods', category: 'Best Practices', recommended: 'error', + extendsBaseRule: true, requiresTypeChecking: true, }, messages: { diff --git a/packages/eslint-plugin/src/rules/no-invalid-this.ts b/packages/eslint-plugin/src/rules/no-invalid-this.ts index 3f579655f0b7..5d056308771f 100644 --- a/packages/eslint-plugin/src/rules/no-invalid-this.ts +++ b/packages/eslint-plugin/src/rules/no-invalid-this.ts @@ -18,7 +18,7 @@ export default createRule({ type: 'suggestion', docs: { description: - 'disallow `this` keywords outside of classes or class-like objects', + 'Disallow `this` keywords outside of classes or class-like objects', category: 'Best Practices', recommended: false, extendsBaseRule: true, diff --git a/packages/eslint-plugin/src/rules/no-throw-literal.ts b/packages/eslint-plugin/src/rules/no-throw-literal.ts index acaa4adf9878..92bf3b02a135 100644 --- a/packages/eslint-plugin/src/rules/no-throw-literal.ts +++ b/packages/eslint-plugin/src/rules/no-throw-literal.ts @@ -13,6 +13,7 @@ export default util.createRule({ description: 'Disallow throwing literals as exceptions', category: 'Best Practices', recommended: false, + extendsBaseRule: true, requiresTypeChecking: true, }, schema: [], diff --git a/packages/eslint-plugin/tests/rules/array-type.test.ts b/packages/eslint-plugin/tests/rules/array-type.test.ts index 73c1f517d682..6551bf6e7b97 100644 --- a/packages/eslint-plugin/tests/rules/array-type.test.ts +++ b/packages/eslint-plugin/tests/rules/array-type.test.ts @@ -1648,6 +1648,19 @@ interface FooInterface { }, ], }, + { + code: 'type Foo = ReadonlyArray[];', + output: 'type Foo = (readonly object[])[];', + options: [{ default: 'array' }], + errors: [ + { + messageId: 'errorStringArray', + data: { type: 'object' }, + line: 1, + column: 12, + }, + ], + }, ], }); diff --git a/packages/eslint-plugin/tests/rules/no-confusing-void-expression.test.ts b/packages/eslint-plugin/tests/rules/no-confusing-void-expression.test.ts new file mode 100644 index 000000000000..3586c3388f4f --- /dev/null +++ b/packages/eslint-plugin/tests/rules/no-confusing-void-expression.test.ts @@ -0,0 +1,291 @@ +import rule, { + MessageId, + Options, +} from '../../src/rules/no-confusing-void-expression'; +import { + batchedSingleLineTests, + getFixturesRootDir, + noFormat, + RuleTester, +} from '../RuleTester'; + +const rootPath = getFixturesRootDir(); +const ruleTester = new RuleTester({ + parser: '@typescript-eslint/parser', + parserOptions: { + tsconfigRootDir: rootPath, + project: './tsconfig.json', + }, +}); + +ruleTester.run('no-confusing-void-expression', rule, { + valid: [ + ...batchedSingleLineTests({ + code: ` + () => Math.random(); + console.log('foo'); + foo && console.log(foo); + foo || console.log(foo); + foo ? console.log(true) : console.log(false); + `, + }), + + ...batchedSingleLineTests({ + options: [{ ignoreArrowShorthand: true }], + code: ` + () => console.log('foo'); + foo => foo && console.log(foo); + foo => foo || console.log(foo); + foo => (foo ? console.log(true) : console.log(false)); + `, + }), + + ...batchedSingleLineTests({ + options: [{ ignoreVoidOperator: true }], + code: ` + !void console.log('foo'); + +void (foo && console.log(foo)); + -void (foo || console.log(foo)); + () => void ((foo && void console.log(true)) || console.log(false)); + const x = void (foo ? console.log(true) : console.log(false)); + !(foo && void console.log(foo)); + !!(foo || void console.log(foo)); + const x = (foo && void console.log(true)) || void console.log(false); + () => (foo ? void console.log(true) : void console.log(false)); + return void console.log('foo'); + `, + }), + ], + + invalid: [ + ...batchedSingleLineTests({ + code: ` + const x = console.log('foo'); + console.error(console.log('foo')); + [console.log('foo')]; + ({ x: console.log('foo') }); + void console.log('foo'); + console.log('foo') ? true : false; + (console.log('foo') && true) || false; + (cond && console.log('ok')) || console.log('error'); + !console.log('foo'); + `, + errors: [ + { line: 2, column: 11, messageId: 'invalidVoidExpr' }, + { line: 3, column: 23, messageId: 'invalidVoidExpr' }, + { line: 4, column: 10, messageId: 'invalidVoidExpr' }, + { line: 5, column: 15, messageId: 'invalidVoidExpr' }, + { line: 6, column: 14, messageId: 'invalidVoidExpr' }, + { line: 7, column: 9, messageId: 'invalidVoidExpr' }, + { line: 8, column: 10, messageId: 'invalidVoidExpr' }, + { line: 9, column: 18, messageId: 'invalidVoidExpr' }, + { line: 10, column: 10, messageId: 'invalidVoidExpr' }, + ], + }), + + { + code: "() => console.log('foo');", + errors: [{ line: 1, column: 7, messageId: 'invalidVoidExprArrow' }], + output: noFormat`() => { console.log('foo'); };`, + }, + { + code: 'foo => foo && console.log(foo);', + errors: [{ line: 1, column: 15, messageId: 'invalidVoidExprArrow' }], + output: noFormat`foo => { foo && console.log(foo); };`, + }, + { + code: 'foo => foo || console.log(foo);', + errors: [{ line: 1, column: 15, messageId: 'invalidVoidExprArrow' }], + output: noFormat`foo => { foo || console.log(foo); };`, + }, + { + code: 'foo => (foo ? console.log(true) : console.log(false));', + errors: [ + { line: 1, column: 15, messageId: 'invalidVoidExprArrow' }, + { line: 1, column: 35, messageId: 'invalidVoidExprArrow' }, + ], + output: noFormat`foo => { foo ? console.log(true) : console.log(false); };`, + }, + { + code: ` + function f() { + return console.log('foo'); + console.log('bar'); + } + `, + errors: [{ line: 3, column: 18, messageId: 'invalidVoidExprReturn' }], + output: noFormat` + function f() { + console.log('foo'); return; + console.log('bar'); + } + `, + }, + { + code: noFormat` + function f() { + console.log('foo') + return ['bar', 'baz'].forEach(console.log) + console.log('quux') + } + `, + errors: [{ line: 4, column: 18, messageId: 'invalidVoidExprReturn' }], + output: noFormat` + function f() { + console.log('foo') + ;['bar', 'baz'].forEach(console.log); return; + console.log('quux') + } + `, + }, + { + code: ` + function f() { + console.log('foo'); + return console.log('bar'); + } + `, + errors: [{ line: 4, column: 18, messageId: 'invalidVoidExprReturnLast' }], + output: ` + function f() { + console.log('foo'); + console.log('bar'); + } + `, + }, + { + code: noFormat` + function f() { + console.log('foo') + return ['bar', 'baz'].forEach(console.log) + } + `, + errors: [{ line: 4, column: 18, messageId: 'invalidVoidExprReturnLast' }], + output: noFormat` + function f() { + console.log('foo') + ;['bar', 'baz'].forEach(console.log); + } + `, + }, + { + code: ` + const f = () => { + if (cond) { + return console.error('foo'); + } + console.log('bar'); + }; + `, + errors: [{ line: 4, column: 20, messageId: 'invalidVoidExprReturn' }], + output: noFormat` + const f = () => { + if (cond) { + console.error('foo'); return; + } + console.log('bar'); + }; + `, + }, + { + code: ` + const f = function () { + if (cond) return console.error('foo'); + console.log('bar'); + }; + `, + errors: [{ line: 3, column: 28, messageId: 'invalidVoidExprReturn' }], + output: noFormat` + const f = function () { + if (cond) { console.error('foo'); return; } + console.log('bar'); + }; + `, + }, + + { + options: [{ ignoreVoidOperator: true }], + code: "return console.log('foo');", + errors: [ + { line: 1, column: 8, messageId: 'invalidVoidExprReturnWrapVoid' }, + ], + output: "return void console.log('foo');", + }, + { + options: [{ ignoreVoidOperator: true }], + code: "console.error(console.log('foo'));", + errors: [ + { + line: 1, + column: 15, + messageId: 'invalidVoidExprWrapVoid', + suggestions: [ + { + messageId: 'voidExprWrapVoid', + output: "console.error(void console.log('foo'));", + }, + ], + }, + ], + }, + { + options: [{ ignoreVoidOperator: true }], + code: "console.log('foo') ? true : false;", + errors: [ + { + line: 1, + column: 1, + messageId: 'invalidVoidExprWrapVoid', + suggestions: [ + { + messageId: 'voidExprWrapVoid', + output: "void console.log('foo') ? true : false;", + }, + ], + }, + ], + }, + { + options: [{ ignoreVoidOperator: true }], + code: "const x = foo ?? console.log('foo');", + errors: [ + { + line: 1, + column: 18, + messageId: 'invalidVoidExprWrapVoid', + suggestions: [ + { + messageId: 'voidExprWrapVoid', + output: "const x = foo ?? void console.log('foo');", + }, + ], + }, + ], + }, + { + options: [{ ignoreVoidOperator: true }], + code: 'foo => foo || console.log(foo);', + errors: [ + { line: 1, column: 15, messageId: 'invalidVoidExprArrowWrapVoid' }, + ], + output: 'foo => foo || void console.log(foo);', + }, + { + options: [{ ignoreVoidOperator: true }], + code: "!!console.log('foo');", + errors: [ + { + line: 1, + column: 3, + messageId: 'invalidVoidExprWrapVoid', + suggestions: [ + { + messageId: 'voidExprWrapVoid', + output: "!!void console.log('foo');", + }, + ], + }, + ], + }, + ], +}); diff --git a/packages/eslint-plugin/tests/rules/no-extra-non-null-assertion.test.ts b/packages/eslint-plugin/tests/rules/no-extra-non-null-assertion.test.ts index 8afbbcf072f3..39ad4da3ebf0 100644 --- a/packages/eslint-plugin/tests/rules/no-extra-non-null-assertion.test.ts +++ b/packages/eslint-plugin/tests/rules/no-extra-non-null-assertion.test.ts @@ -33,6 +33,15 @@ function foo(bar?: { n: number }) { checksCounter?.textContent!.trim(); `, }, + // https://github.com/typescript-eslint/typescript-eslint/issues/2732 + { + code: ` +function foo(key: string | null) { + const obj = {}; + return obj?.[key!]; +} + `, + }, ], invalid: [ { diff --git a/packages/eslint-plugin/tests/rules/no-unused-vars.test.ts b/packages/eslint-plugin/tests/rules/no-unused-vars.test.ts index b3d9c92491d2..9bc46bc75ade 100644 --- a/packages/eslint-plugin/tests/rules/no-unused-vars.test.ts +++ b/packages/eslint-plugin/tests/rules/no-unused-vars.test.ts @@ -1,5 +1,5 @@ import rule from '../../src/rules/no-unused-vars'; -import { RuleTester } from '../RuleTester'; +import { noFormat, RuleTester } from '../RuleTester'; const ruleTester = new RuleTester({ parserOptions: { @@ -387,6 +387,17 @@ export const map: { [name in Foo]: Bar } = { a: 1, b: 2, c: 3, +}; + `, + // 4.1 remapped mapped type + noFormat` +type Foo = 'a' | 'b' | 'c'; +type Bar = number; + +export const map: { [name in Foo as string]: Bar } = { + a: 1, + b: 2, + c: 3, }; `, ` @@ -900,6 +911,22 @@ declare function A(A: string): string; `, filename: 'foo.d.ts', }, + // 4.1 template literal types + noFormat` +type Color = 'red' | 'blue'; +type Quantity = 'one' | 'two'; +export type SeussFish = \`\${Quantity | Color} fish\`; + `, + noFormat` +type VerticalAlignment = "top" | "middle" | "bottom"; +type HorizontalAlignment = "left" | "center" | "right"; + +export declare function setAlignment(value: \`\${VerticalAlignment}-\${HorizontalAlignment}\`): void; + `, + noFormat` +type EnthusiasticGreeting = \`\${Uppercase} - \${Lowercase} - \${Capitalize} - \${Uncapitalize}\`; +export type HELLO = EnthusiasticGreeting<"heLLo">; + `, ], invalid: [ diff --git a/packages/experimental-utils/CHANGELOG.md b/packages/experimental-utils/CHANGELOG.md index 255f62ad51f8..ae01c57dfb02 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. +# [4.7.0](https://github.com/typescript-eslint/typescript-eslint/compare/v4.6.1...v4.7.0) (2020-11-09) + +**Note:** Version bump only for package @typescript-eslint/experimental-utils + + + + + ## [4.6.1](https://github.com/typescript-eslint/typescript-eslint/compare/v4.6.0...v4.6.1) (2020-11-02) **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 dc2de08f347f..5b08a7b7a7b5 100644 --- a/packages/experimental-utils/package.json +++ b/packages/experimental-utils/package.json @@ -1,6 +1,6 @@ { "name": "@typescript-eslint/experimental-utils", - "version": "4.6.1", + "version": "4.7.0", "description": "(Experimental) Utilities for working with TypeScript + ESLint together", "keywords": [ "eslint", @@ -40,9 +40,9 @@ }, "dependencies": { "@types/json-schema": "^7.0.3", - "@typescript-eslint/scope-manager": "4.6.1", - "@typescript-eslint/types": "4.6.1", - "@typescript-eslint/typescript-estree": "4.6.1", + "@typescript-eslint/scope-manager": "4.7.0", + "@typescript-eslint/types": "4.7.0", + "@typescript-eslint/typescript-estree": "4.7.0", "eslint-scope": "^5.0.0", "eslint-utils": "^2.0.0" }, diff --git a/packages/parser/CHANGELOG.md b/packages/parser/CHANGELOG.md index 7889e45e0044..16160c94e635 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. +# [4.7.0](https://github.com/typescript-eslint/typescript-eslint/compare/v4.6.1...v4.7.0) (2020-11-09) + +**Note:** Version bump only for package @typescript-eslint/parser + + + + + ## [4.6.1](https://github.com/typescript-eslint/typescript-eslint/compare/v4.6.0...v4.6.1) (2020-11-02) **Note:** Version bump only for package @typescript-eslint/parser diff --git a/packages/parser/package.json b/packages/parser/package.json index 3564c5d7cbd7..9d6e2ec84454 100644 --- a/packages/parser/package.json +++ b/packages/parser/package.json @@ -1,6 +1,6 @@ { "name": "@typescript-eslint/parser", - "version": "4.6.1", + "version": "4.7.0", "description": "An ESLint custom parser which leverages TypeScript ESTree", "main": "dist/index.js", "types": "dist/index.d.ts", @@ -44,15 +44,15 @@ "eslint": "^5.0.0 || ^6.0.0 || ^7.0.0" }, "dependencies": { - "@typescript-eslint/scope-manager": "4.6.1", - "@typescript-eslint/types": "4.6.1", - "@typescript-eslint/typescript-estree": "4.6.1", + "@typescript-eslint/scope-manager": "4.7.0", + "@typescript-eslint/types": "4.7.0", + "@typescript-eslint/typescript-estree": "4.7.0", "debug": "^4.1.1" }, "devDependencies": { "@types/glob": "*", - "@typescript-eslint/experimental-utils": "4.6.1", - "@typescript-eslint/shared-fixtures": "4.6.1", + "@typescript-eslint/experimental-utils": "4.7.0", + "@typescript-eslint/shared-fixtures": "4.7.0", "glob": "*", "typescript": "*" }, diff --git a/packages/scope-manager/CHANGELOG.md b/packages/scope-manager/CHANGELOG.md index 49c29546f684..8423871370c0 100644 --- a/packages/scope-manager/CHANGELOG.md +++ b/packages/scope-manager/CHANGELOG.md @@ -3,6 +3,17 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [4.7.0](https://github.com/typescript-eslint/typescript-eslint/compare/v4.6.1...v4.7.0) (2020-11-09) + + +### Features + +* support TS4.1 features ([#2748](https://github.com/typescript-eslint/typescript-eslint/issues/2748)) ([2be354b](https://github.com/typescript-eslint/typescript-eslint/commit/2be354bb15f9013a2da1b13a0c0836e9ef057e16)), closes [#2583](https://github.com/typescript-eslint/typescript-eslint/issues/2583) + + + + + ## [4.6.1](https://github.com/typescript-eslint/typescript-eslint/compare/v4.6.0...v4.6.1) (2020-11-02) **Note:** Version bump only for package @typescript-eslint/scope-manager diff --git a/packages/scope-manager/package.json b/packages/scope-manager/package.json index 7f0286c9aeb0..480eaef447f1 100644 --- a/packages/scope-manager/package.json +++ b/packages/scope-manager/package.json @@ -1,6 +1,6 @@ { "name": "@typescript-eslint/scope-manager", - "version": "4.6.1", + "version": "4.7.0", "description": "TypeScript scope analyser for ESLint", "keywords": [ "eslint", @@ -39,12 +39,12 @@ "typecheck": "tsc -p tsconfig.json --noEmit" }, "dependencies": { - "@typescript-eslint/types": "4.6.1", - "@typescript-eslint/visitor-keys": "4.6.1" + "@typescript-eslint/types": "4.7.0", + "@typescript-eslint/visitor-keys": "4.7.0" }, "devDependencies": { "@types/glob": "*", - "@typescript-eslint/typescript-estree": "4.6.1", + "@typescript-eslint/typescript-estree": "4.7.0", "glob": "*", "jest-specific-snapshot": "*", "make-dir": "*", diff --git a/packages/scope-manager/src/lib/dom.iterable.ts b/packages/scope-manager/src/lib/dom.iterable.ts index 2893ddae28ad..582f11704e2b 100644 --- a/packages/scope-manager/src/lib/dom.iterable.ts +++ b/packages/scope-manager/src/lib/dom.iterable.ts @@ -125,6 +125,12 @@ export const dom_iterable = { isValueVariable: false, name: 'Headers', }, + IDBDatabase: { + eslintImplicitGlobalSetting: 'readonly', + isTypeVariable: true, + isValueVariable: false, + name: 'IDBDatabase', + }, IDBObjectStore: { eslintImplicitGlobalSetting: 'readonly', isTypeVariable: true, diff --git a/packages/scope-manager/src/lib/dom.ts b/packages/scope-manager/src/lib/dom.ts index 8f578d13349c..e736f675fd4c 100644 --- a/packages/scope-manager/src/lib/dom.ts +++ b/packages/scope-manager/src/lib/dom.ts @@ -299,6 +299,12 @@ export const dom = { isValueVariable: false, name: 'CredentialCreationOptions', }, + CredentialPropertiesOutput: { + eslintImplicitGlobalSetting: 'readonly', + isTypeVariable: true, + isValueVariable: false, + name: 'CredentialPropertiesOutput', + }, CredentialRequestOptions: { eslintImplicitGlobalSetting: 'readonly', isTypeVariable: true, @@ -1745,12 +1751,6 @@ export const dom = { isValueVariable: false, name: 'WorkletOptions', }, - txAuthGenericArg: { - eslintImplicitGlobalSetting: 'readonly', - isTypeVariable: true, - isValueVariable: false, - name: 'txAuthGenericArg', - }, EventListener: { eslintImplicitGlobalSetting: 'readonly', isTypeVariable: true, @@ -2369,12 +2369,6 @@ export const dom = { isValueVariable: true, name: 'ConvolverNode', }, - Coordinates: { - eslintImplicitGlobalSetting: 'readonly', - isTypeVariable: true, - isValueVariable: false, - name: 'Coordinates', - }, CountQueuingStrategy: { eslintImplicitGlobalSetting: 'readonly', isTypeVariable: true, @@ -2906,9 +2900,27 @@ export const dom = { Geolocation: { eslintImplicitGlobalSetting: 'readonly', isTypeVariable: true, - isValueVariable: false, + isValueVariable: true, name: 'Geolocation', }, + GeolocationCoordinates: { + eslintImplicitGlobalSetting: 'readonly', + isTypeVariable: true, + isValueVariable: true, + name: 'GeolocationCoordinates', + }, + GeolocationPosition: { + eslintImplicitGlobalSetting: 'readonly', + isTypeVariable: true, + isValueVariable: true, + name: 'GeolocationPosition', + }, + GeolocationPositionError: { + eslintImplicitGlobalSetting: 'readonly', + isTypeVariable: true, + isValueVariable: true, + name: 'GeolocationPositionError', + }, GlobalEventHandlersEventMap: { eslintImplicitGlobalSetting: 'readonly', isTypeVariable: true, @@ -3473,12 +3485,6 @@ export const dom = { isValueVariable: true, name: 'History', }, - HkdfCtrParams: { - eslintImplicitGlobalSetting: 'readonly', - isTypeVariable: true, - isValueVariable: false, - name: 'HkdfCtrParams', - }, IDBArrayKey: { eslintImplicitGlobalSetting: 'readonly', isTypeVariable: true, @@ -4415,18 +4421,6 @@ export const dom = { isValueVariable: true, name: 'PopStateEvent', }, - Position: { - eslintImplicitGlobalSetting: 'readonly', - isTypeVariable: true, - isValueVariable: false, - name: 'Position', - }, - PositionError: { - eslintImplicitGlobalSetting: 'readonly', - isTypeVariable: true, - isValueVariable: false, - name: 'PositionError', - }, ProcessingInstruction: { eslintImplicitGlobalSetting: 'readonly', isTypeVariable: true, @@ -4724,7 +4718,7 @@ export const dom = { ReadableByteStreamController: { eslintImplicitGlobalSetting: 'readonly', isTypeVariable: true, - isValueVariable: false, + isValueVariable: true, name: 'ReadableByteStreamController', }, ReadableStream: { @@ -4736,25 +4730,25 @@ export const dom = { ReadableStreamBYOBReader: { eslintImplicitGlobalSetting: 'readonly', isTypeVariable: true, - isValueVariable: false, + isValueVariable: true, name: 'ReadableStreamBYOBReader', }, ReadableStreamBYOBRequest: { eslintImplicitGlobalSetting: 'readonly', isTypeVariable: true, - isValueVariable: false, + isValueVariable: true, name: 'ReadableStreamBYOBRequest', }, ReadableStreamDefaultController: { eslintImplicitGlobalSetting: 'readonly', isTypeVariable: true, - isValueVariable: false, + isValueVariable: true, name: 'ReadableStreamDefaultController', }, ReadableStreamDefaultReader: { eslintImplicitGlobalSetting: 'readonly', isTypeVariable: true, - isValueVariable: false, + isValueVariable: true, name: 'ReadableStreamDefaultReader', }, ReadableStreamReader: { @@ -5954,7 +5948,7 @@ export const dom = { TransformStreamDefaultController: { eslintImplicitGlobalSetting: 'readonly', isTypeVariable: true, - isValueVariable: false, + isValueVariable: true, name: 'TransformStreamDefaultController', }, TransitionEvent: { @@ -6374,13 +6368,13 @@ export const dom = { WritableStreamDefaultController: { eslintImplicitGlobalSetting: 'readonly', isTypeVariable: true, - isValueVariable: false, + isValueVariable: true, name: 'WritableStreamDefaultController', }, WritableStreamDefaultWriter: { eslintImplicitGlobalSetting: 'readonly', isTypeVariable: true, - isValueVariable: false, + isValueVariable: true, name: 'WritableStreamDefaultWriter', }, XMLDocument: { @@ -6851,24 +6845,6 @@ export const dom = { isValueVariable: false, name: 'COSEAlgorithmIdentifier', }, - AuthenticatorSelectionList: { - eslintImplicitGlobalSetting: 'readonly', - isTypeVariable: true, - isValueVariable: false, - name: 'AuthenticatorSelectionList', - }, - AAGUID: { - eslintImplicitGlobalSetting: 'readonly', - isTypeVariable: true, - isValueVariable: false, - name: 'AAGUID', - }, - AuthenticationExtensionsSupported: { - eslintImplicitGlobalSetting: 'readonly', - isTypeVariable: true, - isValueVariable: false, - name: 'AuthenticationExtensionsSupported', - }, UvmEntry: { eslintImplicitGlobalSetting: 'readonly', isTypeVariable: true, @@ -7769,6 +7745,12 @@ export const dom = { isValueVariable: false, name: 'RequestRedirect', }, + ResidentKeyRequirement: { + eslintImplicitGlobalSetting: 'readonly', + isTypeVariable: true, + isValueVariable: false, + name: 'ResidentKeyRequirement', + }, ResizeQuality: { eslintImplicitGlobalSetting: 'readonly', isTypeVariable: true, diff --git a/packages/scope-manager/src/lib/es2015.iterable.ts b/packages/scope-manager/src/lib/es2015.iterable.ts index 6bfb232406aa..200317477303 100644 --- a/packages/scope-manager/src/lib/es2015.iterable.ts +++ b/packages/scope-manager/src/lib/es2015.iterable.ts @@ -145,12 +145,6 @@ export const es2015_iterable = { isValueVariable: false, name: 'PromiseConstructor', }, - Reflect: { - eslintImplicitGlobalSetting: 'readonly', - isTypeVariable: true, - isValueVariable: true, - name: 'Reflect', - }, String: { eslintImplicitGlobalSetting: 'readonly', isTypeVariable: true, diff --git a/packages/scope-manager/src/lib/es2020.sharedmemory.ts b/packages/scope-manager/src/lib/es2020.sharedmemory.ts new file mode 100644 index 000000000000..83569efc09f3 --- /dev/null +++ b/packages/scope-manager/src/lib/es2020.sharedmemory.ts @@ -0,0 +1,14 @@ +// THIS CODE WAS AUTOMATICALLY GENERATED +// DO NOT EDIT THIS CODE BY HAND +// YOU CAN REGENERATE IT USING yarn generate:lib + +import { ImplicitLibVariableOptions } from '../variable'; + +export const es2020_sharedmemory = { + Atomics: { + eslintImplicitGlobalSetting: 'readonly', + isTypeVariable: true, + isValueVariable: false, + name: 'Atomics', + }, +} as Record; diff --git a/packages/scope-manager/src/lib/es2020.ts b/packages/scope-manager/src/lib/es2020.ts index 684c28fe2d2f..a55bf1e519da 100644 --- a/packages/scope-manager/src/lib/es2020.ts +++ b/packages/scope-manager/src/lib/es2020.ts @@ -6,6 +6,7 @@ import { ImplicitLibVariableOptions } from '../variable'; import { es2019 } from './es2019'; import { es2020_bigint } from './es2020.bigint'; import { es2020_promise } from './es2020.promise'; +import { es2020_sharedmemory } from './es2020.sharedmemory'; import { es2020_string } from './es2020.string'; import { es2020_symbol_wellknown } from './es2020.symbol.wellknown'; import { es2020_intl } from './es2020.intl'; @@ -14,6 +15,7 @@ export const es2020 = { ...es2019, ...es2020_bigint, ...es2020_promise, + ...es2020_sharedmemory, ...es2020_string, ...es2020_symbol_wellknown, ...es2020_intl, diff --git a/packages/scope-manager/src/lib/es5.ts b/packages/scope-manager/src/lib/es5.ts index 81a8af4b0674..2141fc6ceee1 100644 --- a/packages/scope-manager/src/lib/es5.ts +++ b/packages/scope-manager/src/lib/es5.ts @@ -419,6 +419,30 @@ export const es5 = { isValueVariable: false, name: 'InstanceType', }, + Uppercase: { + eslintImplicitGlobalSetting: 'readonly', + isTypeVariable: true, + isValueVariable: false, + name: 'Uppercase', + }, + Lowercase: { + eslintImplicitGlobalSetting: 'readonly', + isTypeVariable: true, + isValueVariable: false, + name: 'Lowercase', + }, + Capitalize: { + eslintImplicitGlobalSetting: 'readonly', + isTypeVariable: true, + isValueVariable: false, + name: 'Capitalize', + }, + Uncapitalize: { + eslintImplicitGlobalSetting: 'readonly', + isTypeVariable: true, + isValueVariable: false, + name: 'Uncapitalize', + }, ThisType: { eslintImplicitGlobalSetting: 'readonly', isTypeVariable: true, diff --git a/packages/scope-manager/src/lib/esnext.ts b/packages/scope-manager/src/lib/esnext.ts index cdd59bb0bcf5..347f63158c6e 100644 --- a/packages/scope-manager/src/lib/esnext.ts +++ b/packages/scope-manager/src/lib/esnext.ts @@ -7,10 +7,12 @@ import { es2020 } from './es2020'; import { esnext_intl } from './esnext.intl'; import { esnext_string } from './esnext.string'; import { esnext_promise } from './esnext.promise'; +import { esnext_weakref } from './esnext.weakref'; export const esnext = { ...es2020, ...esnext_intl, ...esnext_string, ...esnext_promise, + ...esnext_weakref, } as Record; diff --git a/packages/scope-manager/src/lib/esnext.weakref.ts b/packages/scope-manager/src/lib/esnext.weakref.ts new file mode 100644 index 000000000000..2ae60fb7230b --- /dev/null +++ b/packages/scope-manager/src/lib/esnext.weakref.ts @@ -0,0 +1,32 @@ +// THIS CODE WAS AUTOMATICALLY GENERATED +// DO NOT EDIT THIS CODE BY HAND +// YOU CAN REGENERATE IT USING yarn generate:lib + +import { ImplicitLibVariableOptions } from '../variable'; + +export const esnext_weakref = { + WeakRef: { + eslintImplicitGlobalSetting: 'readonly', + isTypeVariable: true, + isValueVariable: true, + name: 'WeakRef', + }, + WeakRefConstructor: { + eslintImplicitGlobalSetting: 'readonly', + isTypeVariable: true, + isValueVariable: false, + name: 'WeakRefConstructor', + }, + FinalizationRegistry: { + eslintImplicitGlobalSetting: 'readonly', + isTypeVariable: true, + isValueVariable: true, + name: 'FinalizationRegistry', + }, + FinalizationRegistryConstructor: { + eslintImplicitGlobalSetting: 'readonly', + isTypeVariable: true, + isValueVariable: false, + name: 'FinalizationRegistryConstructor', + }, +} as Record; diff --git a/packages/scope-manager/src/lib/index.ts b/packages/scope-manager/src/lib/index.ts index a23f0349cbe5..dfae31e07962 100644 --- a/packages/scope-manager/src/lib/index.ts +++ b/packages/scope-manager/src/lib/index.ts @@ -16,6 +16,7 @@ import { dom } from './dom'; import { dom_iterable } from './dom.iterable'; import { webworker } from './webworker'; import { webworker_importscripts } from './webworker.importscripts'; +import { webworker_iterable } from './webworker.iterable'; import { scripthost } from './scripthost'; import { es2015_core } from './es2015.core'; import { es2015_collection } from './es2015.collection'; @@ -43,6 +44,7 @@ import { es2019_string } from './es2019.string'; import { es2019_symbol } from './es2019.symbol'; import { es2020_bigint } from './es2020.bigint'; import { es2020_promise } from './es2020.promise'; +import { es2020_sharedmemory } from './es2020.sharedmemory'; import { es2020_string } from './es2020.string'; import { es2020_symbol_wellknown } from './es2020.symbol.wellknown'; import { es2020_intl } from './es2020.intl'; @@ -53,6 +55,7 @@ import { esnext_intl } from './esnext.intl'; import { esnext_bigint } from './esnext.bigint'; import { esnext_string } from './esnext.string'; import { esnext_promise } from './esnext.promise'; +import { esnext_weakref } from './esnext.weakref'; import { es2016_full } from './es2016.full'; import { es2017_full } from './es2017.full'; import { es2018_full } from './es2018.full'; @@ -76,6 +79,7 @@ const lib = { 'dom.iterable': dom_iterable, webworker, 'webworker.importscripts': webworker_importscripts, + 'webworker.iterable': webworker_iterable, scripthost, 'es2015.core': es2015_core, 'es2015.collection': es2015_collection, @@ -103,6 +107,7 @@ const lib = { 'es2019.symbol': es2019_symbol, 'es2020.bigint': es2020_bigint, 'es2020.promise': es2020_promise, + 'es2020.sharedmemory': es2020_sharedmemory, 'es2020.string': es2020_string, 'es2020.symbol.wellknown': es2020_symbol_wellknown, 'es2020.intl': es2020_intl, @@ -113,6 +118,7 @@ const lib = { 'esnext.bigint': esnext_bigint, 'esnext.string': esnext_string, 'esnext.promise': esnext_promise, + 'esnext.weakref': esnext_weakref, 'es2016.full': es2016_full, 'es2017.full': es2017_full, 'es2018.full': es2018_full, diff --git a/packages/scope-manager/src/lib/webworker.iterable.ts b/packages/scope-manager/src/lib/webworker.iterable.ts new file mode 100644 index 000000000000..e7f5e11cbe9e --- /dev/null +++ b/packages/scope-manager/src/lib/webworker.iterable.ts @@ -0,0 +1,92 @@ +// THIS CODE WAS AUTOMATICALLY GENERATED +// DO NOT EDIT THIS CODE BY HAND +// YOU CAN REGENERATE IT USING yarn generate:lib + +import { ImplicitLibVariableOptions } from '../variable'; + +export const webworker_iterable = { + Cache: { + eslintImplicitGlobalSetting: 'readonly', + isTypeVariable: true, + isValueVariable: false, + name: 'Cache', + }, + CanvasPathDrawingStyles: { + eslintImplicitGlobalSetting: 'readonly', + isTypeVariable: true, + isValueVariable: false, + name: 'CanvasPathDrawingStyles', + }, + DOMStringList: { + eslintImplicitGlobalSetting: 'readonly', + isTypeVariable: true, + isValueVariable: false, + name: 'DOMStringList', + }, + FileList: { + eslintImplicitGlobalSetting: 'readonly', + isTypeVariable: true, + isValueVariable: false, + name: 'FileList', + }, + FormData: { + eslintImplicitGlobalSetting: 'readonly', + isTypeVariable: true, + isValueVariable: false, + name: 'FormData', + }, + Headers: { + eslintImplicitGlobalSetting: 'readonly', + isTypeVariable: true, + isValueVariable: false, + name: 'Headers', + }, + IDBDatabase: { + eslintImplicitGlobalSetting: 'readonly', + isTypeVariable: true, + isValueVariable: false, + name: 'IDBDatabase', + }, + IDBObjectStore: { + eslintImplicitGlobalSetting: 'readonly', + isTypeVariable: true, + isValueVariable: false, + name: 'IDBObjectStore', + }, + URLSearchParams: { + eslintImplicitGlobalSetting: 'readonly', + isTypeVariable: true, + isValueVariable: false, + name: 'URLSearchParams', + }, + WEBGL_draw_buffers: { + eslintImplicitGlobalSetting: 'readonly', + isTypeVariable: true, + isValueVariable: false, + name: 'WEBGL_draw_buffers', + }, + WebGL2RenderingContextBase: { + eslintImplicitGlobalSetting: 'readonly', + isTypeVariable: true, + isValueVariable: false, + name: 'WebGL2RenderingContextBase', + }, + WebGL2RenderingContextOverloads: { + eslintImplicitGlobalSetting: 'readonly', + isTypeVariable: true, + isValueVariable: false, + name: 'WebGL2RenderingContextOverloads', + }, + WebGLRenderingContextBase: { + eslintImplicitGlobalSetting: 'readonly', + isTypeVariable: true, + isValueVariable: false, + name: 'WebGLRenderingContextBase', + }, + WebGLRenderingContextOverloads: { + eslintImplicitGlobalSetting: 'readonly', + isTypeVariable: true, + isValueVariable: false, + name: 'WebGLRenderingContextOverloads', + }, +} as Record; diff --git a/packages/scope-manager/src/lib/webworker.ts b/packages/scope-manager/src/lib/webworker.ts index 250c3db95007..c56ee9885241 100644 --- a/packages/scope-manager/src/lib/webworker.ts +++ b/packages/scope-manager/src/lib/webworker.ts @@ -209,6 +209,12 @@ export const webworker = { isValueVariable: false, name: 'GetNotificationOptions', }, + HkdfParams: { + eslintImplicitGlobalSetting: 'readonly', + isTypeVariable: true, + isValueVariable: false, + name: 'HkdfParams', + }, HmacImportParams: { eslintImplicitGlobalSetting: 'readonly', isTypeVariable: true, @@ -1001,12 +1007,6 @@ export const webworker = { isValueVariable: true, name: 'Headers', }, - HkdfCtrParams: { - eslintImplicitGlobalSetting: 'readonly', - isTypeVariable: true, - isValueVariable: false, - name: 'HkdfCtrParams', - }, IDBArrayKey: { eslintImplicitGlobalSetting: 'readonly', isTypeVariable: true, @@ -1376,7 +1376,7 @@ export const webworker = { ReadableByteStreamController: { eslintImplicitGlobalSetting: 'readonly', isTypeVariable: true, - isValueVariable: false, + isValueVariable: true, name: 'ReadableByteStreamController', }, ReadableStream: { @@ -1388,25 +1388,25 @@ export const webworker = { ReadableStreamBYOBReader: { eslintImplicitGlobalSetting: 'readonly', isTypeVariable: true, - isValueVariable: false, + isValueVariable: true, name: 'ReadableStreamBYOBReader', }, ReadableStreamBYOBRequest: { eslintImplicitGlobalSetting: 'readonly', isTypeVariable: true, - isValueVariable: false, + isValueVariable: true, name: 'ReadableStreamBYOBRequest', }, ReadableStreamDefaultController: { eslintImplicitGlobalSetting: 'readonly', isTypeVariable: true, - isValueVariable: false, + isValueVariable: true, name: 'ReadableStreamDefaultController', }, ReadableStreamDefaultReader: { eslintImplicitGlobalSetting: 'readonly', isTypeVariable: true, - isValueVariable: false, + isValueVariable: true, name: 'ReadableStreamDefaultReader', }, ReadableStreamReader: { @@ -1568,7 +1568,7 @@ export const webworker = { TransformStreamDefaultController: { eslintImplicitGlobalSetting: 'readonly', isTypeVariable: true, - isValueVariable: false, + isValueVariable: true, name: 'TransformStreamDefaultController', }, URL: { @@ -1844,13 +1844,13 @@ export const webworker = { WritableStreamDefaultController: { eslintImplicitGlobalSetting: 'readonly', isTypeVariable: true, - isValueVariable: false, + isValueVariable: true, name: 'WritableStreamDefaultController', }, WritableStreamDefaultWriter: { eslintImplicitGlobalSetting: 'readonly', isTypeVariable: true, - isValueVariable: false, + isValueVariable: true, name: 'WritableStreamDefaultWriter', }, XMLHttpRequestEventMap: { diff --git a/packages/scope-manager/tests/fixtures/type-declaration/literal-type1.ts b/packages/scope-manager/tests/fixtures/type-declaration/literal-type1.ts new file mode 100644 index 000000000000..62d52177631d --- /dev/null +++ b/packages/scope-manager/tests/fixtures/type-declaration/literal-type1.ts @@ -0,0 +1,3 @@ +type Color = "red" | "blue"; +type Quantity = "one" | "two"; +type SeussFish = `${Quantity | Color} fish`; diff --git a/packages/scope-manager/tests/fixtures/type-declaration/literal-type1.ts.shot b/packages/scope-manager/tests/fixtures/type-declaration/literal-type1.ts.shot new file mode 100644 index 000000000000..341b30deea37 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/type-declaration/literal-type1.ts.shot @@ -0,0 +1,87 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`type-declaration literal-type1 1`] = ` +ScopeManager { + variables: Array [ + ImplicitGlobalConstTypeVariable, + Variable$2 { + defs: Array [ + TypeDefinition$1 { + name: Identifier<"Color">, + node: TSTypeAliasDeclaration$1, + }, + ], + name: "Color", + references: Array [ + Reference$2 { + identifier: Identifier<"Color">, + isRead: true, + isTypeReference: true, + isValueReference: false, + isWrite: false, + resolved: Variable$2, + }, + ], + isValueVariable: false, + isTypeVariable: true, + }, + Variable$3 { + defs: Array [ + TypeDefinition$2 { + name: Identifier<"Quantity">, + node: TSTypeAliasDeclaration$2, + }, + ], + name: "Quantity", + references: Array [ + Reference$1 { + identifier: Identifier<"Quantity">, + isRead: true, + isTypeReference: true, + isValueReference: false, + isWrite: false, + resolved: Variable$3, + }, + ], + isValueVariable: false, + isTypeVariable: true, + }, + Variable$4 { + defs: Array [ + TypeDefinition$3 { + name: Identifier<"SeussFish">, + node: TSTypeAliasDeclaration$3, + }, + ], + name: "SeussFish", + references: Array [], + isValueVariable: false, + isTypeVariable: true, + }, + ], + scopes: Array [ + GlobalScope$1 { + block: Program$4, + isStrict: false, + references: Array [ + Reference$1, + Reference$2, + ], + set: Map { + "const" => ImplicitGlobalConstTypeVariable, + "Color" => Variable$2, + "Quantity" => Variable$3, + "SeussFish" => Variable$4, + }, + type: "global", + upper: null, + variables: Array [ + ImplicitGlobalConstTypeVariable, + Variable$2, + Variable$3, + Variable$4, + ], + }, + ], +} +`; diff --git a/packages/scope-manager/tests/fixtures/type-declaration/literal-type2.ts b/packages/scope-manager/tests/fixtures/type-declaration/literal-type2.ts new file mode 100644 index 000000000000..b08b1843885d --- /dev/null +++ b/packages/scope-manager/tests/fixtures/type-declaration/literal-type2.ts @@ -0,0 +1,2 @@ +type EnthusiasticGreeting = `${Uppercase} - ${Lowercase} - ${Capitalize} - ${Uncapitalize}`; +type HELLO = EnthusiasticGreeting<"heLLo">; diff --git a/packages/scope-manager/tests/fixtures/type-declaration/literal-type2.ts.shot b/packages/scope-manager/tests/fixtures/type-declaration/literal-type2.ts.shot new file mode 100644 index 000000000000..cb70b4ff434b --- /dev/null +++ b/packages/scope-manager/tests/fixtures/type-declaration/literal-type2.ts.shot @@ -0,0 +1,158 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`type-declaration literal-type2 1`] = ` +ScopeManager { + variables: Array [ + ImplicitGlobalConstTypeVariable, + Variable$2 { + defs: Array [ + TypeDefinition$1 { + name: Identifier<"EnthusiasticGreeting">, + node: TSTypeAliasDeclaration$1, + }, + ], + name: "EnthusiasticGreeting", + references: Array [ + Reference$9 { + identifier: Identifier<"EnthusiasticGreeting">, + isRead: true, + isTypeReference: true, + isValueReference: false, + isWrite: false, + resolved: Variable$2, + }, + ], + isValueVariable: false, + isTypeVariable: true, + }, + Variable$3 { + defs: Array [ + TypeDefinition$2 { + name: Identifier<"T">, + node: TSTypeParameter$2, + }, + ], + name: "T", + references: Array [ + Reference$2 { + identifier: Identifier<"T">, + isRead: true, + isTypeReference: true, + isValueReference: false, + isWrite: false, + resolved: Variable$3, + }, + Reference$4 { + identifier: Identifier<"T">, + isRead: true, + isTypeReference: true, + isValueReference: false, + isWrite: false, + resolved: Variable$3, + }, + Reference$6 { + identifier: Identifier<"T">, + isRead: true, + isTypeReference: true, + isValueReference: false, + isWrite: false, + resolved: Variable$3, + }, + Reference$8 { + identifier: Identifier<"T">, + isRead: true, + isTypeReference: true, + isValueReference: false, + isWrite: false, + resolved: Variable$3, + }, + ], + isValueVariable: false, + isTypeVariable: true, + }, + Variable$4 { + defs: Array [ + TypeDefinition$3 { + name: Identifier<"HELLO">, + node: TSTypeAliasDeclaration$3, + }, + ], + name: "HELLO", + references: Array [], + isValueVariable: false, + isTypeVariable: true, + }, + ], + scopes: Array [ + GlobalScope$1 { + block: Program$4, + isStrict: false, + references: Array [ + Reference$9, + ], + set: Map { + "const" => ImplicitGlobalConstTypeVariable, + "EnthusiasticGreeting" => Variable$2, + "HELLO" => Variable$4, + }, + type: "global", + upper: null, + variables: Array [ + ImplicitGlobalConstTypeVariable, + Variable$2, + Variable$4, + ], + }, + TypeScope$2 { + block: TSTypeAliasDeclaration$1, + isStrict: true, + references: Array [ + Reference$1 { + identifier: Identifier<"Uppercase">, + isRead: true, + isTypeReference: true, + isValueReference: false, + isWrite: false, + resolved: null, + }, + Reference$2, + Reference$3 { + identifier: Identifier<"Lowercase">, + isRead: true, + isTypeReference: true, + isValueReference: false, + isWrite: false, + resolved: null, + }, + Reference$4, + Reference$5 { + identifier: Identifier<"Capitalize">, + isRead: true, + isTypeReference: true, + isValueReference: false, + isWrite: false, + resolved: null, + }, + Reference$6, + Reference$7 { + identifier: Identifier<"Uncapitalize">, + isRead: true, + isTypeReference: true, + isValueReference: false, + isWrite: false, + resolved: null, + }, + Reference$8, + ], + set: Map { + "T" => Variable$3, + }, + type: "type", + upper: GlobalScope$1, + variables: Array [ + Variable$3, + ], + }, + ], +} +`; diff --git a/packages/scope-manager/tests/fixtures/type-declaration/literal-type3.ts b/packages/scope-manager/tests/fixtures/type-declaration/literal-type3.ts new file mode 100644 index 000000000000..126a004bf3e8 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/type-declaration/literal-type3.ts @@ -0,0 +1,8 @@ +type VerticalAlignment = "top" | "middle" | "bottom"; +type HorizontalAlignment = "left" | "center" | "right"; + +// Takes +// | "top-left" | "top-center" | "top-right" +// | "middle-left" | "middle-center" | "middle-right" +// | "bottom-left" | "bottom-center" | "bottom-right" +declare function setAlignment(value: `${VerticalAlignment}-${HorizontalAlignment}`): void; diff --git a/packages/scope-manager/tests/fixtures/type-declaration/literal-type3.ts.shot b/packages/scope-manager/tests/fixtures/type-declaration/literal-type3.ts.shot new file mode 100644 index 000000000000..be4f964133e1 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/type-declaration/literal-type3.ts.shot @@ -0,0 +1,121 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`type-declaration literal-type3 1`] = ` +ScopeManager { + variables: Array [ + ImplicitGlobalConstTypeVariable, + Variable$2 { + defs: Array [ + TypeDefinition$1 { + name: Identifier<"VerticalAlignment">, + node: TSTypeAliasDeclaration$1, + }, + ], + name: "VerticalAlignment", + references: Array [ + Reference$1 { + identifier: Identifier<"VerticalAlignment">, + isRead: true, + isTypeReference: true, + isValueReference: false, + isWrite: false, + resolved: Variable$2, + }, + ], + isValueVariable: false, + isTypeVariable: true, + }, + Variable$3 { + defs: Array [ + TypeDefinition$2 { + name: Identifier<"HorizontalAlignment">, + node: TSTypeAliasDeclaration$2, + }, + ], + name: "HorizontalAlignment", + references: Array [ + Reference$2 { + identifier: Identifier<"HorizontalAlignment">, + isRead: true, + isTypeReference: true, + isValueReference: false, + isWrite: false, + resolved: Variable$3, + }, + ], + isValueVariable: false, + isTypeVariable: true, + }, + Variable$4 { + defs: Array [ + FunctionNameDefinition$3 { + name: Identifier<"setAlignment">, + node: TSDeclareFunction$3, + }, + ], + name: "setAlignment", + references: Array [], + isValueVariable: true, + isTypeVariable: false, + }, + Variable$5 { + defs: Array [], + name: "arguments", + references: Array [], + isValueVariable: true, + isTypeVariable: true, + }, + Variable$6 { + defs: Array [ + ParameterDefinition$4 { + name: Identifier<"value">, + node: TSDeclareFunction$3, + }, + ], + name: "value", + references: Array [], + isValueVariable: true, + isTypeVariable: false, + }, + ], + scopes: Array [ + GlobalScope$1 { + block: Program$4, + isStrict: false, + references: Array [], + set: Map { + "const" => ImplicitGlobalConstTypeVariable, + "VerticalAlignment" => Variable$2, + "HorizontalAlignment" => Variable$3, + "setAlignment" => Variable$4, + }, + type: "global", + upper: null, + variables: Array [ + ImplicitGlobalConstTypeVariable, + Variable$2, + Variable$3, + Variable$4, + ], + }, + FunctionScope$2 { + block: TSDeclareFunction$3, + isStrict: false, + references: Array [ + Reference$1, + Reference$2, + ], + set: Map { + "arguments" => Variable$5, + "value" => Variable$6, + }, + type: "function", + upper: GlobalScope$1, + variables: Array [ + Variable$5, + Variable$6, + ], + }, + ], +} +`; diff --git a/packages/scope-manager/tests/fixtures/type-declaration/mapped-named.ts b/packages/scope-manager/tests/fixtures/type-declaration/mapped-named.ts new file mode 100644 index 000000000000..1b1eed00c705 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/type-declaration/mapped-named.ts @@ -0,0 +1,2 @@ +type T = Record; +type A = { [k in string as k]: T[k] }; diff --git a/packages/scope-manager/tests/fixtures/type-declaration/mapped-named.ts.shot b/packages/scope-manager/tests/fixtures/type-declaration/mapped-named.ts.shot new file mode 100644 index 000000000000..b0b19e3e1c19 --- /dev/null +++ b/packages/scope-manager/tests/fixtures/type-declaration/mapped-named.ts.shot @@ -0,0 +1,116 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`type-declaration mapped-named 1`] = ` +ScopeManager { + variables: Array [ + ImplicitGlobalConstTypeVariable, + Variable$2 { + defs: Array [ + TypeDefinition$1 { + name: Identifier<"T">, + node: TSTypeAliasDeclaration$1, + }, + ], + name: "T", + references: Array [ + Reference$4 { + identifier: Identifier<"T">, + isRead: true, + isTypeReference: true, + isValueReference: false, + isWrite: false, + resolved: Variable$2, + }, + ], + isValueVariable: false, + isTypeVariable: true, + }, + Variable$3 { + defs: Array [ + TypeDefinition$2 { + name: Identifier<"A">, + node: TSTypeAliasDeclaration$2, + }, + ], + name: "A", + references: Array [], + isValueVariable: false, + isTypeVariable: true, + }, + Variable$4 { + defs: Array [ + TypeDefinition$3 { + name: Identifier<"k">, + node: TSTypeParameter$3, + }, + ], + name: "k", + references: Array [ + Reference$2 { + identifier: Identifier<"k">, + isRead: true, + isTypeReference: true, + isValueReference: false, + isWrite: false, + resolved: Variable$4, + }, + Reference$3 { + identifier: Identifier<"k">, + isRead: true, + isTypeReference: true, + isValueReference: false, + isWrite: false, + resolved: Variable$4, + }, + ], + isValueVariable: false, + isTypeVariable: true, + }, + ], + scopes: Array [ + GlobalScope$1 { + block: Program$4, + isStrict: false, + references: Array [ + Reference$1 { + identifier: Identifier<"Record">, + isRead: true, + isTypeReference: true, + isValueReference: false, + isWrite: false, + resolved: null, + }, + ], + set: Map { + "const" => ImplicitGlobalConstTypeVariable, + "T" => Variable$2, + "A" => Variable$3, + }, + type: "global", + upper: null, + variables: Array [ + ImplicitGlobalConstTypeVariable, + Variable$2, + Variable$3, + ], + }, + MappedTypeScope$2 { + block: TSMappedType$5, + isStrict: true, + references: Array [ + Reference$2, + Reference$3, + Reference$4, + ], + set: Map { + "k" => Variable$4, + }, + type: "mappedType", + upper: GlobalScope$1, + variables: Array [ + Variable$4, + ], + }, + ], +} +`; diff --git a/packages/shared-fixtures/CHANGELOG.md b/packages/shared-fixtures/CHANGELOG.md index baa481932f68..a1b0701d39e8 100644 --- a/packages/shared-fixtures/CHANGELOG.md +++ b/packages/shared-fixtures/CHANGELOG.md @@ -3,6 +3,17 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [4.7.0](https://github.com/typescript-eslint/typescript-eslint/compare/v4.6.1...v4.7.0) (2020-11-09) + + +### Features + +* support TS4.1 features ([#2748](https://github.com/typescript-eslint/typescript-eslint/issues/2748)) ([2be354b](https://github.com/typescript-eslint/typescript-eslint/commit/2be354bb15f9013a2da1b13a0c0836e9ef057e16)), closes [#2583](https://github.com/typescript-eslint/typescript-eslint/issues/2583) + + + + + ## [4.6.1](https://github.com/typescript-eslint/typescript-eslint/compare/v4.6.0...v4.6.1) (2020-11-02) **Note:** Version bump only for package @typescript-eslint/shared-fixtures diff --git a/packages/shared-fixtures/fixtures/typescript/types/mapped-named-type.src.ts b/packages/shared-fixtures/fixtures/typescript/types/mapped-named-type.src.ts new file mode 100644 index 000000000000..ea3309f4db3f --- /dev/null +++ b/packages/shared-fixtures/fixtures/typescript/types/mapped-named-type.src.ts @@ -0,0 +1,3 @@ +type Test = { + [P in keyof T as 'a']: T[P]; +}; diff --git a/packages/shared-fixtures/fixtures/typescript/types/template-literal-type-1.src.ts b/packages/shared-fixtures/fixtures/typescript/types/template-literal-type-1.src.ts new file mode 100644 index 000000000000..1faa126d51a1 --- /dev/null +++ b/packages/shared-fixtures/fixtures/typescript/types/template-literal-type-1.src.ts @@ -0,0 +1 @@ +type T = `foo`; diff --git a/packages/shared-fixtures/fixtures/typescript/types/template-literal-type-2.src.ts b/packages/shared-fixtures/fixtures/typescript/types/template-literal-type-2.src.ts new file mode 100644 index 000000000000..cffb3ab1b8de --- /dev/null +++ b/packages/shared-fixtures/fixtures/typescript/types/template-literal-type-2.src.ts @@ -0,0 +1 @@ +type T = `foo${'bar'}`; diff --git a/packages/shared-fixtures/fixtures/typescript/types/template-literal-type-3.src.ts b/packages/shared-fixtures/fixtures/typescript/types/template-literal-type-3.src.ts new file mode 100644 index 000000000000..62d52177631d --- /dev/null +++ b/packages/shared-fixtures/fixtures/typescript/types/template-literal-type-3.src.ts @@ -0,0 +1,3 @@ +type Color = "red" | "blue"; +type Quantity = "one" | "two"; +type SeussFish = `${Quantity | Color} fish`; diff --git a/packages/shared-fixtures/fixtures/typescript/types/template-literal-type-4.src.ts b/packages/shared-fixtures/fixtures/typescript/types/template-literal-type-4.src.ts new file mode 100644 index 000000000000..b08b1843885d --- /dev/null +++ b/packages/shared-fixtures/fixtures/typescript/types/template-literal-type-4.src.ts @@ -0,0 +1,2 @@ +type EnthusiasticGreeting = `${Uppercase} - ${Lowercase} - ${Capitalize} - ${Uncapitalize}`; +type HELLO = EnthusiasticGreeting<"heLLo">; diff --git a/packages/shared-fixtures/package.json b/packages/shared-fixtures/package.json index d8647e1017b1..93dcf4e11880 100644 --- a/packages/shared-fixtures/package.json +++ b/packages/shared-fixtures/package.json @@ -1,6 +1,6 @@ { "name": "@typescript-eslint/shared-fixtures", - "version": "4.6.1", + "version": "4.7.0", "private": true, "scripts": { "build": "tsc -b tsconfig.build.json", diff --git a/packages/types/CHANGELOG.md b/packages/types/CHANGELOG.md index a9b6a88c33cd..e082c9de1062 100644 --- a/packages/types/CHANGELOG.md +++ b/packages/types/CHANGELOG.md @@ -3,6 +3,17 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [4.7.0](https://github.com/typescript-eslint/typescript-eslint/compare/v4.6.1...v4.7.0) (2020-11-09) + + +### Features + +* support TS4.1 features ([#2748](https://github.com/typescript-eslint/typescript-eslint/issues/2748)) ([2be354b](https://github.com/typescript-eslint/typescript-eslint/commit/2be354bb15f9013a2da1b13a0c0836e9ef057e16)), closes [#2583](https://github.com/typescript-eslint/typescript-eslint/issues/2583) + + + + + ## [4.6.1](https://github.com/typescript-eslint/typescript-eslint/compare/v4.6.0...v4.6.1) (2020-11-02) **Note:** Version bump only for package @typescript-eslint/types diff --git a/packages/types/package.json b/packages/types/package.json index b9df04ed57bc..fc735df29e94 100644 --- a/packages/types/package.json +++ b/packages/types/package.json @@ -1,6 +1,6 @@ { "name": "@typescript-eslint/types", - "version": "4.6.1", + "version": "4.7.0", "description": "Types for the TypeScript-ESTree AST spec", "keywords": [ "eslint", diff --git a/packages/types/src/ast-node-types.ts b/packages/types/src/ast-node-types.ts index 36699864ede0..97c630d94727 100644 --- a/packages/types/src/ast-node-types.ts +++ b/packages/types/src/ast-node-types.ts @@ -143,6 +143,7 @@ enum AST_NODE_TYPES { TSStaticKeyword = 'TSStaticKeyword', TSStringKeyword = 'TSStringKeyword', TSSymbolKeyword = 'TSSymbolKeyword', + TSTemplateLiteralType = 'TSTemplateLiteralType', TSThisType = 'TSThisType', TSTupleType = 'TSTupleType', TSTypeAliasDeclaration = 'TSTypeAliasDeclaration', diff --git a/packages/types/src/index.ts b/packages/types/src/index.ts index a57fbe661559..59df48302df5 100644 --- a/packages/types/src/index.ts +++ b/packages/types/src/index.ts @@ -1,9 +1,5 @@ -// TODO(Brad Zacher) - convert this to export * as TSESTree from './ts-estree' -// https://github.com/sandersn/downlevel-dts/pull/42 -import * as TSESTree from './ts-estree'; - export { AST_NODE_TYPES } from './ast-node-types'; export { AST_TOKEN_TYPES } from './ast-token-types'; export * from './lib'; export * from './parser-options'; -export { TSESTree }; +export * as TSESTree from './ts-estree'; diff --git a/packages/types/src/lib.ts b/packages/types/src/lib.ts index f72fb61be9af..5f173893b589 100644 --- a/packages/types/src/lib.ts +++ b/packages/types/src/lib.ts @@ -17,6 +17,7 @@ type Lib = | 'dom.iterable' | 'webworker' | 'webworker.importscripts' + | 'webworker.iterable' | 'scripthost' | 'es2015.core' | 'es2015.collection' @@ -44,6 +45,7 @@ type Lib = | 'es2019.symbol' | 'es2020.bigint' | 'es2020.promise' + | 'es2020.sharedmemory' | 'es2020.string' | 'es2020.symbol.wellknown' | 'es2020.intl' @@ -54,6 +56,7 @@ type Lib = | 'esnext.bigint' | 'esnext.string' | 'esnext.promise' + | 'esnext.weakref' | 'es2016.full' | 'es2017.full' | 'es2018.full' diff --git a/packages/types/src/ts-estree.ts b/packages/types/src/ts-estree.ts index 31b051d8b9d2..003b0fd2e736 100644 --- a/packages/types/src/ts-estree.ts +++ b/packages/types/src/ts-estree.ts @@ -274,6 +274,7 @@ export type Node = | TSStaticKeyword | TSStringKeyword | TSSymbolKeyword + | TSTemplateLiteralType | TSThisType | TSTupleType | TSTypeAliasDeclaration @@ -549,6 +550,7 @@ export type TypeNode = | TSRestType | TSStringKeyword | TSSymbolKeyword + | TSTemplateLiteralType | TSThisType | TSTupleType | TSTypeLiteral @@ -1472,6 +1474,7 @@ export interface TSMappedType extends BaseNode { readonly?: boolean | '-' | '+'; optional?: boolean | '-' | '+'; typeAnnotation?: TypeNode; + nameType: TypeNode | null; } export interface TSMethodSignatureComputedName extends TSMethodSignatureBase { @@ -1499,6 +1502,13 @@ export interface TSModuleDeclaration extends BaseNode { modifiers?: Modifier[]; } +export interface TSNamedTupleMember extends BaseNode { + type: AST_NODE_TYPES.TSNamedTupleMember; + elementType: TypeNode; + label: Identifier; + optional: boolean; +} + export interface TSNamespaceExportDeclaration extends BaseNode { type: AST_NODE_TYPES.TSNamespaceExportDeclaration; id: Identifier; @@ -1596,15 +1606,14 @@ export interface TSSymbolKeyword extends BaseNode { type: AST_NODE_TYPES.TSSymbolKeyword; } -export interface TSThisType extends BaseNode { - type: AST_NODE_TYPES.TSThisType; +export interface TSTemplateLiteralType extends BaseNode { + type: AST_NODE_TYPES.TSTemplateLiteralType; + quasis: TemplateElement[]; + types: TypeNode[]; } -export interface TSNamedTupleMember extends BaseNode { - type: AST_NODE_TYPES.TSNamedTupleMember; - elementType: TypeNode; - label: Identifier; - optional: boolean; +export interface TSThisType extends BaseNode { + type: AST_NODE_TYPES.TSThisType; } export interface TSTupleType extends BaseNode { diff --git a/packages/typescript-estree/CHANGELOG.md b/packages/typescript-estree/CHANGELOG.md index 4df0a01634d3..f45f6c9734ad 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. +# [4.7.0](https://github.com/typescript-eslint/typescript-eslint/compare/v4.6.1...v4.7.0) (2020-11-09) + + +### Features + +* support TS4.1 features ([#2748](https://github.com/typescript-eslint/typescript-eslint/issues/2748)) ([2be354b](https://github.com/typescript-eslint/typescript-eslint/commit/2be354bb15f9013a2da1b13a0c0836e9ef057e16)), closes [#2583](https://github.com/typescript-eslint/typescript-eslint/issues/2583) + + + + + ## [4.6.1](https://github.com/typescript-eslint/typescript-eslint/compare/v4.6.0...v4.6.1) (2020-11-02) **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 102d3e3c46d3..76f911b5c8df 100644 --- a/packages/typescript-estree/package.json +++ b/packages/typescript-estree/package.json @@ -1,6 +1,6 @@ { "name": "@typescript-eslint/typescript-estree", - "version": "4.6.1", + "version": "4.7.0", "description": "A parser that converts TypeScript source code into an ESTree compatible form", "main": "dist/index.js", "types": "dist/index.d.ts", @@ -41,8 +41,8 @@ "typecheck": "tsc -p tsconfig.json --noEmit" }, "dependencies": { - "@typescript-eslint/types": "4.6.1", - "@typescript-eslint/visitor-keys": "4.6.1", + "@typescript-eslint/types": "4.7.0", + "@typescript-eslint/visitor-keys": "4.7.0", "debug": "^4.1.1", "globby": "^11.0.1", "is-glob": "^4.0.1", @@ -52,16 +52,16 @@ }, "devDependencies": { "@babel/code-frame": "^7.10.4", - "@babel/parser": "^7.11.3", - "@babel/types": "^7.11.0", - "@types/babel__code-frame": "^7.0.1", + "@babel/parser": "^7.12.5", + "@babel/types": "^7.12.6", + "@types/babel__code-frame": "^7.0.2", "@types/debug": "*", "@types/glob": "*", "@types/is-glob": "^4.0.1", "@types/lodash": "*", "@types/semver": "^7.1.0", "@types/tmp": "^0.2.0", - "@typescript-eslint/shared-fixtures": "4.6.1", + "@typescript-eslint/shared-fixtures": "4.7.0", "glob": "*", "jest-specific-snapshot": "*", "make-dir": "*", diff --git a/packages/typescript-estree/src/convert.ts b/packages/typescript-estree/src/convert.ts index a35c869c72e1..a22eae1a5df5 100644 --- a/packages/typescript-estree/src/convert.ts +++ b/packages/typescript-estree/src/convert.ts @@ -2272,6 +2272,7 @@ export class Converter { const result = this.createNode(node, { type: AST_NODE_TYPES.TSMappedType, typeParameter: this.convertType(node.typeParameter), + nameType: this.convertType(node.nameType) ?? null, }); if (node.readonlyToken) { @@ -2740,6 +2741,21 @@ export class Converter { }); } + // Template Literal Types + case SyntaxKind.TemplateLiteralType: { + const result = this.createNode(node, { + type: AST_NODE_TYPES.TSTemplateLiteralType, + quasis: [this.convertChild(node.head)], + types: [], + }); + + node.templateSpans.forEach(templateSpan => { + result.types.push(this.convertChild(templateSpan.type)); + result.quasis.push(this.convertChild(templateSpan.literal)); + }); + return result; + } + default: return this.deeplyCopy(node); } diff --git a/packages/typescript-estree/src/parser.ts b/packages/typescript-estree/src/parser.ts index 2b9970e48cf5..d2554bf61954 100644 --- a/packages/typescript-estree/src/parser.ts +++ b/packages/typescript-estree/src/parser.ts @@ -20,12 +20,12 @@ const log = debug('typescript-eslint:typescript-estree:parser'); * This needs to be kept in sync with the top-level README.md in the * typescript-eslint monorepo */ -const SUPPORTED_TYPESCRIPT_VERSIONS = '>=3.3.1 <4.1.0'; +const SUPPORTED_TYPESCRIPT_VERSIONS = '>=3.3.1 <4.2.0'; /* * The semver package will ignore prerelease ranges, and we don't want to explicitly document every one * List them all separately here, so we can automatically create the full string */ -const SUPPORTED_PRERELEASE_RANGES: string[] = []; +const SUPPORTED_PRERELEASE_RANGES: string[] = ['4.1.1-rc', '4.1.0-beta']; const ACTIVE_TYPESCRIPT_VERSION = ts.version; const isRunningSupportedTypeScriptVersion = semver.satisfies( ACTIVE_TYPESCRIPT_VERSION, diff --git a/packages/typescript-estree/src/ts-estree/estree-to-ts-node-types.ts b/packages/typescript-estree/src/ts-estree/estree-to-ts-node-types.ts index 707477a162f5..620539202805 100644 --- a/packages/typescript-estree/src/ts-estree/estree-to-ts-node-types.ts +++ b/packages/typescript-estree/src/ts-estree/estree-to-ts-node-types.ts @@ -200,6 +200,7 @@ export interface EstreeToTsNodeTypes { | ts.NamedTupleMember; [AST_NODE_TYPES.TSThisType]: ts.ThisTypeNode; [AST_NODE_TYPES.TSTupleType]: ts.TupleTypeNode; + [AST_NODE_TYPES.TSTemplateLiteralType]: ts.TemplateLiteralTypeNode; [AST_NODE_TYPES.TSTypeAliasDeclaration]: ts.TypeAliasDeclaration; [AST_NODE_TYPES.TSTypeAnnotation]: undefined; [AST_NODE_TYPES.TSTypeAssertion]: ts.TypeAssertion; diff --git a/packages/typescript-estree/src/ts-estree/ts-nodes.ts b/packages/typescript-estree/src/ts-estree/ts-nodes.ts index 354d4ce21d5e..693f0e8305b4 100644 --- a/packages/typescript-estree/src/ts-estree/ts-nodes.ts +++ b/packages/typescript-estree/src/ts-estree/ts-nodes.ts @@ -170,6 +170,7 @@ export type TSNode = | ts.InputFiles | ts.UnparsedSource | ts.JsonMinusNumericLiteral + | ts.TemplateLiteralTypeNode // JSDoc: Unsupported | ts.JSDoc diff --git a/packages/typescript-estree/tests/ast-alignment/fixtures-to-test.ts b/packages/typescript-estree/tests/ast-alignment/fixtures-to-test.ts index c4573651fa0a..b9378f6692d2 100644 --- a/packages/typescript-estree/tests/ast-alignment/fixtures-to-test.ts +++ b/packages/typescript-estree/tests/ast-alignment/fixtures-to-test.ts @@ -141,7 +141,15 @@ tester.addFixturePatternConfig('javascript/arrayLiteral'); tester.addFixturePatternConfig('javascript/simple-literals'); -tester.addFixturePatternConfig('javascript/directives'); +tester.addFixturePatternConfig('javascript/directives', { + ignore: [ + /** + * Babel errors on accessors: + * https://github.com/babel/babel/issues/12335 + */ + 'directive-in-class', + ], +}); tester.addFixturePatternConfig('javascript/experimentalObjectRestSpread'); @@ -202,6 +210,13 @@ tester.addFixturePatternConfig('javascript/classes', { * TS3.6 made computed constructors parse as actual constructors. */ 'class-two-methods-computed-constructor', + /** + * Babel errors on accessors: + * https://github.com/babel/babel/issues/12335 + */ + 'class-accessor-properties', + 'class-static-methods-and-accessor-properties', + 'invalid-class-setter-declaration', ], }); @@ -272,7 +287,15 @@ tester.addFixturePatternConfig('javascript/modules', { tester.addFixturePatternConfig('javascript/newTarget'); tester.addFixturePatternConfig('javascript/objectLiteral'); -tester.addFixturePatternConfig('javascript/objectLiteralComputedProperties'); +tester.addFixturePatternConfig('javascript/objectLiteralComputedProperties', { + ignore: [ + /** + * Babel errors on accessors: + * https://github.com/babel/babel/issues/12335 + */ + 'computed-getter-and-setter', + ], +}); tester.addFixturePatternConfig('javascript/objectLiteralDuplicateProperties', { ignore: [ @@ -403,6 +426,8 @@ tester.addFixturePatternConfig('typescript/basics', { * [BABEL ERRORED, BUT TS-ESTREE DID NOT] * This is intentional; we don't error on semantic problems for these cases */ + 'class-with-constructor-and-type-parameters', + 'class-with-two-methods-computed-constructor', 'catch-clause-with-invalid-annotation', 'export-type-star-from', 'import-type-error', @@ -411,6 +436,11 @@ tester.addFixturePatternConfig('typescript/basics', { * https://github.com/babel/babel/issues/11939 */ 'catch-clause-with-annotation', + /** + * Babel errors on accessors: + * https://github.com/babel/babel/issues/12335 + */ + 'object-with-typed-methods', ], ignoreSourceType: [ /** @@ -440,6 +470,16 @@ tester.addFixturePatternConfig('typescript/basics', { tester.addFixturePatternConfig('typescript/decorators/accessor-decorators', { fileType: 'ts', + ignore: [ + /** + * Babel errors on accessors: + * https://github.com/babel/babel/issues/12335 + */ + 'accessor-decorator-factory-instance-member', + 'accessor-decorator-factory-static-member', + 'accessor-decorator-instance-member', + 'accessor-decorator-static-member', + ], }); tester.addFixturePatternConfig('typescript/decorators/class-decorators', { fileType: 'ts', @@ -498,6 +538,19 @@ tester.addFixturePatternConfig('typescript/errorRecovery', { tester.addFixturePatternConfig('typescript/types', { fileType: 'ts', + ignore: [ + /** + * TS Template Literal Types + * + * Babel uses a representation much further from TS's representation. + * They produce TSTypeLiteral -> TemplateLiteral, and then force override the expression parser to parse types + * We instead just emit TSTemplateLiteralType. + */ + 'template-literal-type-1', + 'template-literal-type-2', + 'template-literal-type-3', + 'template-literal-type-4', + ], }); tester.addFixturePatternConfig('typescript/declare', { diff --git a/packages/typescript-estree/tests/ast-alignment/parse.ts b/packages/typescript-estree/tests/ast-alignment/parse.ts index be37945b3a34..46bef153a0f1 100644 --- a/packages/typescript-estree/tests/ast-alignment/parse.ts +++ b/packages/typescript-estree/tests/ast-alignment/parse.ts @@ -1,5 +1,6 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ +import type babelParser from '@babel/parser'; import { ParserPlugin } from '@babel/parser'; import { codeFrameColumns } from '@babel/code-frame'; import * as parser from '../../src/parser'; @@ -19,7 +20,7 @@ function createError( } function parseWithBabelParser(text: string, jsx = true): any { - const babel = require('@babel/parser'); + const babel: typeof babelParser = require('@babel/parser'); const plugins: ParserPlugin[] = [ 'classProperties', 'decorators-legacy', diff --git a/packages/typescript-estree/tests/lib/__snapshots__/semantic-diagnostics-enabled.test.ts.snap b/packages/typescript-estree/tests/lib/__snapshots__/semantic-diagnostics-enabled.test.ts.snap index 2b7e4bf9e872..61608bd35953 100644 --- a/packages/typescript-estree/tests/lib/__snapshots__/semantic-diagnostics-enabled.test.ts.snap +++ b/packages/typescript-estree/tests/lib/__snapshots__/semantic-diagnostics-enabled.test.ts.snap @@ -2650,6 +2650,8 @@ exports[`Parse all fixtures with "errorOnTypeScriptSyntacticAndSemanticIssues" e exports[`Parse all fixtures with "errorOnTypeScriptSyntacticAndSemanticIssues" enabled fixtures/typescript/types/mapped.src 1`] = `"TEST OUTPUT: No semantic or syntactic issues found"`; +exports[`Parse all fixtures with "errorOnTypeScriptSyntacticAndSemanticIssues" enabled fixtures/typescript/types/mapped-named-type.src 1`] = `"TEST OUTPUT: No semantic or syntactic issues found"`; + exports[`Parse all fixtures with "errorOnTypeScriptSyntacticAndSemanticIssues" enabled fixtures/typescript/types/mapped-readonly.src 1`] = `"TEST OUTPUT: No semantic or syntactic issues found"`; exports[`Parse all fixtures with "errorOnTypeScriptSyntacticAndSemanticIssues" enabled fixtures/typescript/types/mapped-readonly-minus.src 1`] = `"TEST OUTPUT: No semantic or syntactic issues found"`; @@ -2668,6 +2670,14 @@ exports[`Parse all fixtures with "errorOnTypeScriptSyntacticAndSemanticIssues" e exports[`Parse all fixtures with "errorOnTypeScriptSyntacticAndSemanticIssues" enabled fixtures/typescript/types/reference-generic-nested.src 1`] = `"TEST OUTPUT: No semantic or syntactic issues found"`; +exports[`Parse all fixtures with "errorOnTypeScriptSyntacticAndSemanticIssues" enabled fixtures/typescript/types/template-literal-type-1.src 1`] = `"TEST OUTPUT: No semantic or syntactic issues found"`; + +exports[`Parse all fixtures with "errorOnTypeScriptSyntacticAndSemanticIssues" enabled fixtures/typescript/types/template-literal-type-2.src 1`] = `"TEST OUTPUT: No semantic or syntactic issues found"`; + +exports[`Parse all fixtures with "errorOnTypeScriptSyntacticAndSemanticIssues" enabled fixtures/typescript/types/template-literal-type-3.src 1`] = `"TEST OUTPUT: No semantic or syntactic issues found"`; + +exports[`Parse all fixtures with "errorOnTypeScriptSyntacticAndSemanticIssues" enabled fixtures/typescript/types/template-literal-type-4.src 1`] = `"TEST OUTPUT: No semantic or syntactic issues found"`; + exports[`Parse all fixtures with "errorOnTypeScriptSyntacticAndSemanticIssues" enabled fixtures/typescript/types/this-type.src 1`] = `"TEST OUTPUT: No semantic or syntactic issues found"`; exports[`Parse all fixtures with "errorOnTypeScriptSyntacticAndSemanticIssues" enabled fixtures/typescript/types/this-type-expanded.src 1`] = `"TEST OUTPUT: No semantic or syntactic issues found"`; diff --git a/packages/typescript-estree/tests/snapshots/typescript/types/mapped-named-type.src.ts.shot b/packages/typescript-estree/tests/snapshots/typescript/types/mapped-named-type.src.ts.shot new file mode 100644 index 000000000000..4adec74e80a9 --- /dev/null +++ b/packages/typescript-estree/tests/snapshots/typescript/types/mapped-named-type.src.ts.shot @@ -0,0 +1,764 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`typescript types mapped-named-type.src 1`] = ` +Object { + "body": Array [ + Object { + "id": Object { + "loc": Object { + "end": Object { + "column": 9, + "line": 1, + }, + "start": Object { + "column": 5, + "line": 1, + }, + }, + "name": "Test", + "range": Array [ + 5, + 9, + ], + "type": "Identifier", + }, + "loc": Object { + "end": Object { + "column": 2, + "line": 3, + }, + "start": Object { + "column": 0, + "line": 1, + }, + }, + "range": Array [ + 0, + 50, + ], + "type": "TSTypeAliasDeclaration", + "typeAnnotation": Object { + "loc": Object { + "end": Object { + "column": 1, + "line": 3, + }, + "start": Object { + "column": 15, + "line": 1, + }, + }, + "nameType": Object { + "literal": Object { + "loc": Object { + "end": Object { + "column": 22, + "line": 2, + }, + "start": Object { + "column": 19, + "line": 2, + }, + }, + "range": Array [ + 36, + 39, + ], + "raw": "'a'", + "type": "Literal", + "value": "a", + }, + "loc": Object { + "end": Object { + "column": 22, + "line": 2, + }, + "start": Object { + "column": 19, + "line": 2, + }, + }, + "range": Array [ + 36, + 39, + ], + "type": "TSLiteralType", + }, + "range": Array [ + 15, + 49, + ], + "type": "TSMappedType", + "typeAnnotation": Object { + "indexType": Object { + "loc": Object { + "end": Object { + "column": 28, + "line": 2, + }, + "start": Object { + "column": 27, + "line": 2, + }, + }, + "range": Array [ + 44, + 45, + ], + "type": "TSTypeReference", + "typeName": Object { + "loc": Object { + "end": Object { + "column": 28, + "line": 2, + }, + "start": Object { + "column": 27, + "line": 2, + }, + }, + "name": "P", + "range": Array [ + 44, + 45, + ], + "type": "Identifier", + }, + "typeParameters": undefined, + }, + "loc": Object { + "end": Object { + "column": 29, + "line": 2, + }, + "start": Object { + "column": 25, + "line": 2, + }, + }, + "objectType": Object { + "loc": Object { + "end": Object { + "column": 26, + "line": 2, + }, + "start": Object { + "column": 25, + "line": 2, + }, + }, + "range": Array [ + 42, + 43, + ], + "type": "TSTypeReference", + "typeName": Object { + "loc": Object { + "end": Object { + "column": 26, + "line": 2, + }, + "start": Object { + "column": 25, + "line": 2, + }, + }, + "name": "T", + "range": Array [ + 42, + 43, + ], + "type": "Identifier", + }, + "typeParameters": undefined, + }, + "range": Array [ + 42, + 46, + ], + "type": "TSIndexedAccessType", + }, + "typeParameter": Object { + "constraint": Object { + "loc": Object { + "end": Object { + "column": 15, + "line": 2, + }, + "start": Object { + "column": 8, + "line": 2, + }, + }, + "operator": "keyof", + "range": Array [ + 25, + 32, + ], + "type": "TSTypeOperator", + "typeAnnotation": Object { + "loc": Object { + "end": Object { + "column": 15, + "line": 2, + }, + "start": Object { + "column": 14, + "line": 2, + }, + }, + "range": Array [ + 31, + 32, + ], + "type": "TSTypeReference", + "typeName": Object { + "loc": Object { + "end": Object { + "column": 15, + "line": 2, + }, + "start": Object { + "column": 14, + "line": 2, + }, + }, + "name": "T", + "range": Array [ + 31, + 32, + ], + "type": "Identifier", + }, + "typeParameters": undefined, + }, + }, + "default": undefined, + "loc": Object { + "end": Object { + "column": 15, + "line": 2, + }, + "start": Object { + "column": 3, + "line": 2, + }, + }, + "name": Object { + "loc": Object { + "end": Object { + "column": 4, + "line": 2, + }, + "start": Object { + "column": 3, + "line": 2, + }, + }, + "name": "P", + "range": Array [ + 20, + 21, + ], + "type": "Identifier", + }, + "range": Array [ + 20, + 32, + ], + "type": "TSTypeParameter", + }, + }, + "typeParameters": Object { + "loc": Object { + "end": Object { + "column": 12, + "line": 1, + }, + "start": Object { + "column": 9, + "line": 1, + }, + }, + "params": Array [ + Object { + "constraint": undefined, + "default": undefined, + "loc": Object { + "end": Object { + "column": 11, + "line": 1, + }, + "start": Object { + "column": 10, + "line": 1, + }, + }, + "name": Object { + "loc": Object { + "end": Object { + "column": 11, + "line": 1, + }, + "start": Object { + "column": 10, + "line": 1, + }, + }, + "name": "T", + "range": Array [ + 10, + 11, + ], + "type": "Identifier", + }, + "range": Array [ + 10, + 11, + ], + "type": "TSTypeParameter", + }, + ], + "range": Array [ + 9, + 12, + ], + "type": "TSTypeParameterDeclaration", + }, + }, + ], + "comments": Array [], + "loc": Object { + "end": Object { + "column": 0, + "line": 4, + }, + "start": Object { + "column": 0, + "line": 1, + }, + }, + "range": Array [ + 0, + 51, + ], + "sourceType": "script", + "tokens": Array [ + Object { + "loc": Object { + "end": Object { + "column": 4, + "line": 1, + }, + "start": Object { + "column": 0, + "line": 1, + }, + }, + "range": Array [ + 0, + 4, + ], + "type": "Identifier", + "value": "type", + }, + Object { + "loc": Object { + "end": Object { + "column": 9, + "line": 1, + }, + "start": Object { + "column": 5, + "line": 1, + }, + }, + "range": Array [ + 5, + 9, + ], + "type": "Identifier", + "value": "Test", + }, + Object { + "loc": Object { + "end": Object { + "column": 10, + "line": 1, + }, + "start": Object { + "column": 9, + "line": 1, + }, + }, + "range": Array [ + 9, + 10, + ], + "type": "Punctuator", + "value": "<", + }, + Object { + "loc": Object { + "end": Object { + "column": 11, + "line": 1, + }, + "start": Object { + "column": 10, + "line": 1, + }, + }, + "range": Array [ + 10, + 11, + ], + "type": "Identifier", + "value": "T", + }, + Object { + "loc": Object { + "end": Object { + "column": 12, + "line": 1, + }, + "start": Object { + "column": 11, + "line": 1, + }, + }, + "range": Array [ + 11, + 12, + ], + "type": "Punctuator", + "value": ">", + }, + Object { + "loc": Object { + "end": Object { + "column": 14, + "line": 1, + }, + "start": Object { + "column": 13, + "line": 1, + }, + }, + "range": Array [ + 13, + 14, + ], + "type": "Punctuator", + "value": "=", + }, + Object { + "loc": Object { + "end": Object { + "column": 16, + "line": 1, + }, + "start": Object { + "column": 15, + "line": 1, + }, + }, + "range": Array [ + 15, + 16, + ], + "type": "Punctuator", + "value": "{", + }, + Object { + "loc": Object { + "end": Object { + "column": 3, + "line": 2, + }, + "start": Object { + "column": 2, + "line": 2, + }, + }, + "range": Array [ + 19, + 20, + ], + "type": "Punctuator", + "value": "[", + }, + Object { + "loc": Object { + "end": Object { + "column": 4, + "line": 2, + }, + "start": Object { + "column": 3, + "line": 2, + }, + }, + "range": Array [ + 20, + 21, + ], + "type": "Identifier", + "value": "P", + }, + Object { + "loc": Object { + "end": Object { + "column": 7, + "line": 2, + }, + "start": Object { + "column": 5, + "line": 2, + }, + }, + "range": Array [ + 22, + 24, + ], + "type": "Keyword", + "value": "in", + }, + Object { + "loc": Object { + "end": Object { + "column": 13, + "line": 2, + }, + "start": Object { + "column": 8, + "line": 2, + }, + }, + "range": Array [ + 25, + 30, + ], + "type": "Identifier", + "value": "keyof", + }, + Object { + "loc": Object { + "end": Object { + "column": 15, + "line": 2, + }, + "start": Object { + "column": 14, + "line": 2, + }, + }, + "range": Array [ + 31, + 32, + ], + "type": "Identifier", + "value": "T", + }, + Object { + "loc": Object { + "end": Object { + "column": 18, + "line": 2, + }, + "start": Object { + "column": 16, + "line": 2, + }, + }, + "range": Array [ + 33, + 35, + ], + "type": "Identifier", + "value": "as", + }, + Object { + "loc": Object { + "end": Object { + "column": 22, + "line": 2, + }, + "start": Object { + "column": 19, + "line": 2, + }, + }, + "range": Array [ + 36, + 39, + ], + "type": "String", + "value": "'a'", + }, + Object { + "loc": Object { + "end": Object { + "column": 23, + "line": 2, + }, + "start": Object { + "column": 22, + "line": 2, + }, + }, + "range": Array [ + 39, + 40, + ], + "type": "Punctuator", + "value": "]", + }, + Object { + "loc": Object { + "end": Object { + "column": 24, + "line": 2, + }, + "start": Object { + "column": 23, + "line": 2, + }, + }, + "range": Array [ + 40, + 41, + ], + "type": "Punctuator", + "value": ":", + }, + Object { + "loc": Object { + "end": Object { + "column": 26, + "line": 2, + }, + "start": Object { + "column": 25, + "line": 2, + }, + }, + "range": Array [ + 42, + 43, + ], + "type": "Identifier", + "value": "T", + }, + Object { + "loc": Object { + "end": Object { + "column": 27, + "line": 2, + }, + "start": Object { + "column": 26, + "line": 2, + }, + }, + "range": Array [ + 43, + 44, + ], + "type": "Punctuator", + "value": "[", + }, + Object { + "loc": Object { + "end": Object { + "column": 28, + "line": 2, + }, + "start": Object { + "column": 27, + "line": 2, + }, + }, + "range": Array [ + 44, + 45, + ], + "type": "Identifier", + "value": "P", + }, + Object { + "loc": Object { + "end": Object { + "column": 29, + "line": 2, + }, + "start": Object { + "column": 28, + "line": 2, + }, + }, + "range": Array [ + 45, + 46, + ], + "type": "Punctuator", + "value": "]", + }, + Object { + "loc": Object { + "end": Object { + "column": 30, + "line": 2, + }, + "start": Object { + "column": 29, + "line": 2, + }, + }, + "range": Array [ + 46, + 47, + ], + "type": "Punctuator", + "value": ";", + }, + Object { + "loc": Object { + "end": Object { + "column": 1, + "line": 3, + }, + "start": Object { + "column": 0, + "line": 3, + }, + }, + "range": Array [ + 48, + 49, + ], + "type": "Punctuator", + "value": "}", + }, + Object { + "loc": Object { + "end": Object { + "column": 2, + "line": 3, + }, + "start": Object { + "column": 1, + "line": 3, + }, + }, + "range": Array [ + 49, + 50, + ], + "type": "Punctuator", + "value": ";", + }, + ], + "type": "Program", +} +`; diff --git a/packages/typescript-estree/tests/snapshots/typescript/types/mapped-readonly-minus.src.ts.shot b/packages/typescript-estree/tests/snapshots/typescript/types/mapped-readonly-minus.src.ts.shot index a27c04550c7b..5bc1ed74e225 100644 --- a/packages/typescript-estree/tests/snapshots/typescript/types/mapped-readonly-minus.src.ts.shot +++ b/packages/typescript-estree/tests/snapshots/typescript/types/mapped-readonly-minus.src.ts.shot @@ -50,6 +50,7 @@ Object { "line": 1, }, }, + "nameType": null, "optional": "-", "range": Array [ 9, diff --git a/packages/typescript-estree/tests/snapshots/typescript/types/mapped-readonly-plus.src.ts.shot b/packages/typescript-estree/tests/snapshots/typescript/types/mapped-readonly-plus.src.ts.shot index f6e0ad2f0d86..0529961e6651 100644 --- a/packages/typescript-estree/tests/snapshots/typescript/types/mapped-readonly-plus.src.ts.shot +++ b/packages/typescript-estree/tests/snapshots/typescript/types/mapped-readonly-plus.src.ts.shot @@ -50,6 +50,7 @@ Object { "line": 1, }, }, + "nameType": null, "optional": "+", "range": Array [ 9, diff --git a/packages/typescript-estree/tests/snapshots/typescript/types/mapped-readonly.src.ts.shot b/packages/typescript-estree/tests/snapshots/typescript/types/mapped-readonly.src.ts.shot index e8919b9cb6fa..b18350797d01 100644 --- a/packages/typescript-estree/tests/snapshots/typescript/types/mapped-readonly.src.ts.shot +++ b/packages/typescript-estree/tests/snapshots/typescript/types/mapped-readonly.src.ts.shot @@ -50,6 +50,7 @@ Object { "line": 1, }, }, + "nameType": null, "optional": true, "range": Array [ 9, diff --git a/packages/typescript-estree/tests/snapshots/typescript/types/mapped-untypped.src.ts.shot b/packages/typescript-estree/tests/snapshots/typescript/types/mapped-untypped.src.ts.shot index 7d5ff18f8815..d254c7d59336 100644 --- a/packages/typescript-estree/tests/snapshots/typescript/types/mapped-untypped.src.ts.shot +++ b/packages/typescript-estree/tests/snapshots/typescript/types/mapped-untypped.src.ts.shot @@ -50,6 +50,7 @@ Object { "line": 1, }, }, + "nameType": null, "range": Array [ 9, 27, diff --git a/packages/typescript-estree/tests/snapshots/typescript/types/mapped.src.ts.shot b/packages/typescript-estree/tests/snapshots/typescript/types/mapped.src.ts.shot index 75e8fe602028..75f22d34e024 100644 --- a/packages/typescript-estree/tests/snapshots/typescript/types/mapped.src.ts.shot +++ b/packages/typescript-estree/tests/snapshots/typescript/types/mapped.src.ts.shot @@ -50,6 +50,7 @@ Object { "line": 1, }, }, + "nameType": null, "range": Array [ 9, 35, diff --git a/packages/typescript-estree/tests/snapshots/typescript/types/template-literal-type-1.src.ts.shot b/packages/typescript-estree/tests/snapshots/typescript/types/template-literal-type-1.src.ts.shot new file mode 100644 index 000000000000..36df58b13db0 --- /dev/null +++ b/packages/typescript-estree/tests/snapshots/typescript/types/template-literal-type-1.src.ts.shot @@ -0,0 +1,211 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`typescript types template-literal-type-1.src 1`] = ` +Object { + "body": Array [ + Object { + "id": Object { + "loc": Object { + "end": Object { + "column": 6, + "line": 1, + }, + "start": Object { + "column": 5, + "line": 1, + }, + }, + "name": "T", + "range": Array [ + 5, + 6, + ], + "type": "Identifier", + }, + "loc": Object { + "end": Object { + "column": 15, + "line": 1, + }, + "start": Object { + "column": 0, + "line": 1, + }, + }, + "range": Array [ + 0, + 15, + ], + "type": "TSTypeAliasDeclaration", + "typeAnnotation": Object { + "literal": Object { + "expressions": Array [], + "loc": Object { + "end": Object { + "column": 14, + "line": 1, + }, + "start": Object { + "column": 9, + "line": 1, + }, + }, + "quasis": Array [ + Object { + "loc": Object { + "end": Object { + "column": 14, + "line": 1, + }, + "start": Object { + "column": 9, + "line": 1, + }, + }, + "range": Array [ + 9, + 14, + ], + "tail": true, + "type": "TemplateElement", + "value": Object { + "cooked": "foo", + "raw": "foo", + }, + }, + ], + "range": Array [ + 9, + 14, + ], + "type": "TemplateLiteral", + }, + "loc": Object { + "end": Object { + "column": 14, + "line": 1, + }, + "start": Object { + "column": 9, + "line": 1, + }, + }, + "range": Array [ + 9, + 14, + ], + "type": "TSLiteralType", + }, + }, + ], + "comments": Array [], + "loc": Object { + "end": Object { + "column": 0, + "line": 2, + }, + "start": Object { + "column": 0, + "line": 1, + }, + }, + "range": Array [ + 0, + 16, + ], + "sourceType": "script", + "tokens": Array [ + Object { + "loc": Object { + "end": Object { + "column": 4, + "line": 1, + }, + "start": Object { + "column": 0, + "line": 1, + }, + }, + "range": Array [ + 0, + 4, + ], + "type": "Identifier", + "value": "type", + }, + Object { + "loc": Object { + "end": Object { + "column": 6, + "line": 1, + }, + "start": Object { + "column": 5, + "line": 1, + }, + }, + "range": Array [ + 5, + 6, + ], + "type": "Identifier", + "value": "T", + }, + Object { + "loc": Object { + "end": Object { + "column": 8, + "line": 1, + }, + "start": Object { + "column": 7, + "line": 1, + }, + }, + "range": Array [ + 7, + 8, + ], + "type": "Punctuator", + "value": "=", + }, + Object { + "loc": Object { + "end": Object { + "column": 14, + "line": 1, + }, + "start": Object { + "column": 9, + "line": 1, + }, + }, + "range": Array [ + 9, + 14, + ], + "type": "Template", + "value": "\`foo\`", + }, + Object { + "loc": Object { + "end": Object { + "column": 15, + "line": 1, + }, + "start": Object { + "column": 14, + "line": 1, + }, + }, + "range": Array [ + 14, + 15, + ], + "type": "Punctuator", + "value": ";", + }, + ], + "type": "Program", +} +`; diff --git a/packages/typescript-estree/tests/snapshots/typescript/types/template-literal-type-2.src.ts.shot b/packages/typescript-estree/tests/snapshots/typescript/types/template-literal-type-2.src.ts.shot new file mode 100644 index 000000000000..f8832d8c8ade --- /dev/null +++ b/packages/typescript-estree/tests/snapshots/typescript/types/template-literal-type-2.src.ts.shot @@ -0,0 +1,289 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`typescript types template-literal-type-2.src 1`] = ` +Object { + "body": Array [ + Object { + "id": Object { + "loc": Object { + "end": Object { + "column": 6, + "line": 1, + }, + "start": Object { + "column": 5, + "line": 1, + }, + }, + "name": "T", + "range": Array [ + 5, + 6, + ], + "type": "Identifier", + }, + "loc": Object { + "end": Object { + "column": 23, + "line": 1, + }, + "start": Object { + "column": 0, + "line": 1, + }, + }, + "range": Array [ + 0, + 23, + ], + "type": "TSTypeAliasDeclaration", + "typeAnnotation": Object { + "loc": Object { + "end": Object { + "column": 22, + "line": 1, + }, + "start": Object { + "column": 9, + "line": 1, + }, + }, + "quasis": Array [ + Object { + "loc": Object { + "end": Object { + "column": 15, + "line": 1, + }, + "start": Object { + "column": 9, + "line": 1, + }, + }, + "range": Array [ + 9, + 15, + ], + "tail": false, + "type": "TemplateElement", + "value": Object { + "cooked": "foo", + "raw": "foo", + }, + }, + Object { + "loc": Object { + "end": Object { + "column": 22, + "line": 1, + }, + "start": Object { + "column": 20, + "line": 1, + }, + }, + "range": Array [ + 20, + 22, + ], + "tail": true, + "type": "TemplateElement", + "value": Object { + "cooked": "", + "raw": "", + }, + }, + ], + "range": Array [ + 9, + 22, + ], + "type": "TSTemplateLiteralType", + "types": Array [ + Object { + "literal": Object { + "loc": Object { + "end": Object { + "column": 20, + "line": 1, + }, + "start": Object { + "column": 15, + "line": 1, + }, + }, + "range": Array [ + 15, + 20, + ], + "raw": "'bar'", + "type": "Literal", + "value": "bar", + }, + "loc": Object { + "end": Object { + "column": 20, + "line": 1, + }, + "start": Object { + "column": 15, + "line": 1, + }, + }, + "range": Array [ + 15, + 20, + ], + "type": "TSLiteralType", + }, + ], + }, + }, + ], + "comments": Array [], + "loc": Object { + "end": Object { + "column": 0, + "line": 2, + }, + "start": Object { + "column": 0, + "line": 1, + }, + }, + "range": Array [ + 0, + 24, + ], + "sourceType": "script", + "tokens": Array [ + Object { + "loc": Object { + "end": Object { + "column": 4, + "line": 1, + }, + "start": Object { + "column": 0, + "line": 1, + }, + }, + "range": Array [ + 0, + 4, + ], + "type": "Identifier", + "value": "type", + }, + Object { + "loc": Object { + "end": Object { + "column": 6, + "line": 1, + }, + "start": Object { + "column": 5, + "line": 1, + }, + }, + "range": Array [ + 5, + 6, + ], + "type": "Identifier", + "value": "T", + }, + Object { + "loc": Object { + "end": Object { + "column": 8, + "line": 1, + }, + "start": Object { + "column": 7, + "line": 1, + }, + }, + "range": Array [ + 7, + 8, + ], + "type": "Punctuator", + "value": "=", + }, + Object { + "loc": Object { + "end": Object { + "column": 15, + "line": 1, + }, + "start": Object { + "column": 9, + "line": 1, + }, + }, + "range": Array [ + 9, + 15, + ], + "type": "Template", + "value": "\`foo\${", + }, + Object { + "loc": Object { + "end": Object { + "column": 20, + "line": 1, + }, + "start": Object { + "column": 15, + "line": 1, + }, + }, + "range": Array [ + 15, + 20, + ], + "type": "String", + "value": "'bar'", + }, + Object { + "loc": Object { + "end": Object { + "column": 22, + "line": 1, + }, + "start": Object { + "column": 20, + "line": 1, + }, + }, + "range": Array [ + 20, + 22, + ], + "type": "Template", + "value": "}\`", + }, + Object { + "loc": Object { + "end": Object { + "column": 23, + "line": 1, + }, + "start": Object { + "column": 22, + "line": 1, + }, + }, + "range": Array [ + 22, + 23, + ], + "type": "Punctuator", + "value": ";", + }, + ], + "type": "Program", +} +`; diff --git a/packages/typescript-estree/tests/snapshots/typescript/types/template-literal-type-3.src.ts.shot b/packages/typescript-estree/tests/snapshots/typescript/types/template-literal-type-3.src.ts.shot new file mode 100644 index 000000000000..c4d2582a33cf --- /dev/null +++ b/packages/typescript-estree/tests/snapshots/typescript/types/template-literal-type-3.src.ts.shot @@ -0,0 +1,884 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`typescript types template-literal-type-3.src 1`] = ` +Object { + "body": Array [ + Object { + "id": Object { + "loc": Object { + "end": Object { + "column": 10, + "line": 1, + }, + "start": Object { + "column": 5, + "line": 1, + }, + }, + "name": "Color", + "range": Array [ + 5, + 10, + ], + "type": "Identifier", + }, + "loc": Object { + "end": Object { + "column": 28, + "line": 1, + }, + "start": Object { + "column": 0, + "line": 1, + }, + }, + "range": Array [ + 0, + 28, + ], + "type": "TSTypeAliasDeclaration", + "typeAnnotation": Object { + "loc": Object { + "end": Object { + "column": 27, + "line": 1, + }, + "start": Object { + "column": 13, + "line": 1, + }, + }, + "range": Array [ + 13, + 27, + ], + "type": "TSUnionType", + "types": Array [ + Object { + "literal": Object { + "loc": Object { + "end": Object { + "column": 18, + "line": 1, + }, + "start": Object { + "column": 13, + "line": 1, + }, + }, + "range": Array [ + 13, + 18, + ], + "raw": "\\"red\\"", + "type": "Literal", + "value": "red", + }, + "loc": Object { + "end": Object { + "column": 18, + "line": 1, + }, + "start": Object { + "column": 13, + "line": 1, + }, + }, + "range": Array [ + 13, + 18, + ], + "type": "TSLiteralType", + }, + Object { + "literal": Object { + "loc": Object { + "end": Object { + "column": 27, + "line": 1, + }, + "start": Object { + "column": 21, + "line": 1, + }, + }, + "range": Array [ + 21, + 27, + ], + "raw": "\\"blue\\"", + "type": "Literal", + "value": "blue", + }, + "loc": Object { + "end": Object { + "column": 27, + "line": 1, + }, + "start": Object { + "column": 21, + "line": 1, + }, + }, + "range": Array [ + 21, + 27, + ], + "type": "TSLiteralType", + }, + ], + }, + }, + Object { + "id": Object { + "loc": Object { + "end": Object { + "column": 13, + "line": 2, + }, + "start": Object { + "column": 5, + "line": 2, + }, + }, + "name": "Quantity", + "range": Array [ + 34, + 42, + ], + "type": "Identifier", + }, + "loc": Object { + "end": Object { + "column": 30, + "line": 2, + }, + "start": Object { + "column": 0, + "line": 2, + }, + }, + "range": Array [ + 29, + 59, + ], + "type": "TSTypeAliasDeclaration", + "typeAnnotation": Object { + "loc": Object { + "end": Object { + "column": 29, + "line": 2, + }, + "start": Object { + "column": 16, + "line": 2, + }, + }, + "range": Array [ + 45, + 58, + ], + "type": "TSUnionType", + "types": Array [ + Object { + "literal": Object { + "loc": Object { + "end": Object { + "column": 21, + "line": 2, + }, + "start": Object { + "column": 16, + "line": 2, + }, + }, + "range": Array [ + 45, + 50, + ], + "raw": "\\"one\\"", + "type": "Literal", + "value": "one", + }, + "loc": Object { + "end": Object { + "column": 21, + "line": 2, + }, + "start": Object { + "column": 16, + "line": 2, + }, + }, + "range": Array [ + 45, + 50, + ], + "type": "TSLiteralType", + }, + Object { + "literal": Object { + "loc": Object { + "end": Object { + "column": 29, + "line": 2, + }, + "start": Object { + "column": 24, + "line": 2, + }, + }, + "range": Array [ + 53, + 58, + ], + "raw": "\\"two\\"", + "type": "Literal", + "value": "two", + }, + "loc": Object { + "end": Object { + "column": 29, + "line": 2, + }, + "start": Object { + "column": 24, + "line": 2, + }, + }, + "range": Array [ + 53, + 58, + ], + "type": "TSLiteralType", + }, + ], + }, + }, + Object { + "id": Object { + "loc": Object { + "end": Object { + "column": 14, + "line": 3, + }, + "start": Object { + "column": 5, + "line": 3, + }, + }, + "name": "SeussFish", + "range": Array [ + 65, + 74, + ], + "type": "Identifier", + }, + "loc": Object { + "end": Object { + "column": 44, + "line": 3, + }, + "start": Object { + "column": 0, + "line": 3, + }, + }, + "range": Array [ + 60, + 104, + ], + "type": "TSTypeAliasDeclaration", + "typeAnnotation": Object { + "loc": Object { + "end": Object { + "column": 43, + "line": 3, + }, + "start": Object { + "column": 17, + "line": 3, + }, + }, + "quasis": Array [ + Object { + "loc": Object { + "end": Object { + "column": 20, + "line": 3, + }, + "start": Object { + "column": 17, + "line": 3, + }, + }, + "range": Array [ + 77, + 80, + ], + "tail": false, + "type": "TemplateElement", + "value": Object { + "cooked": "", + "raw": "", + }, + }, + Object { + "loc": Object { + "end": Object { + "column": 43, + "line": 3, + }, + "start": Object { + "column": 36, + "line": 3, + }, + }, + "range": Array [ + 96, + 103, + ], + "tail": true, + "type": "TemplateElement", + "value": Object { + "cooked": " fish", + "raw": " fish", + }, + }, + ], + "range": Array [ + 77, + 103, + ], + "type": "TSTemplateLiteralType", + "types": Array [ + Object { + "loc": Object { + "end": Object { + "column": 36, + "line": 3, + }, + "start": Object { + "column": 20, + "line": 3, + }, + }, + "range": Array [ + 80, + 96, + ], + "type": "TSUnionType", + "types": Array [ + Object { + "loc": Object { + "end": Object { + "column": 28, + "line": 3, + }, + "start": Object { + "column": 20, + "line": 3, + }, + }, + "range": Array [ + 80, + 88, + ], + "type": "TSTypeReference", + "typeName": Object { + "loc": Object { + "end": Object { + "column": 28, + "line": 3, + }, + "start": Object { + "column": 20, + "line": 3, + }, + }, + "name": "Quantity", + "range": Array [ + 80, + 88, + ], + "type": "Identifier", + }, + "typeParameters": undefined, + }, + Object { + "loc": Object { + "end": Object { + "column": 36, + "line": 3, + }, + "start": Object { + "column": 31, + "line": 3, + }, + }, + "range": Array [ + 91, + 96, + ], + "type": "TSTypeReference", + "typeName": Object { + "loc": Object { + "end": Object { + "column": 36, + "line": 3, + }, + "start": Object { + "column": 31, + "line": 3, + }, + }, + "name": "Color", + "range": Array [ + 91, + 96, + ], + "type": "Identifier", + }, + "typeParameters": undefined, + }, + ], + }, + ], + }, + }, + ], + "comments": Array [], + "loc": Object { + "end": Object { + "column": 0, + "line": 4, + }, + "start": Object { + "column": 0, + "line": 1, + }, + }, + "range": Array [ + 0, + 105, + ], + "sourceType": "script", + "tokens": Array [ + Object { + "loc": Object { + "end": Object { + "column": 4, + "line": 1, + }, + "start": Object { + "column": 0, + "line": 1, + }, + }, + "range": Array [ + 0, + 4, + ], + "type": "Identifier", + "value": "type", + }, + Object { + "loc": Object { + "end": Object { + "column": 10, + "line": 1, + }, + "start": Object { + "column": 5, + "line": 1, + }, + }, + "range": Array [ + 5, + 10, + ], + "type": "Identifier", + "value": "Color", + }, + Object { + "loc": Object { + "end": Object { + "column": 12, + "line": 1, + }, + "start": Object { + "column": 11, + "line": 1, + }, + }, + "range": Array [ + 11, + 12, + ], + "type": "Punctuator", + "value": "=", + }, + Object { + "loc": Object { + "end": Object { + "column": 18, + "line": 1, + }, + "start": Object { + "column": 13, + "line": 1, + }, + }, + "range": Array [ + 13, + 18, + ], + "type": "String", + "value": "\\"red\\"", + }, + Object { + "loc": Object { + "end": Object { + "column": 20, + "line": 1, + }, + "start": Object { + "column": 19, + "line": 1, + }, + }, + "range": Array [ + 19, + 20, + ], + "type": "Punctuator", + "value": "|", + }, + Object { + "loc": Object { + "end": Object { + "column": 27, + "line": 1, + }, + "start": Object { + "column": 21, + "line": 1, + }, + }, + "range": Array [ + 21, + 27, + ], + "type": "String", + "value": "\\"blue\\"", + }, + Object { + "loc": Object { + "end": Object { + "column": 28, + "line": 1, + }, + "start": Object { + "column": 27, + "line": 1, + }, + }, + "range": Array [ + 27, + 28, + ], + "type": "Punctuator", + "value": ";", + }, + Object { + "loc": Object { + "end": Object { + "column": 4, + "line": 2, + }, + "start": Object { + "column": 0, + "line": 2, + }, + }, + "range": Array [ + 29, + 33, + ], + "type": "Identifier", + "value": "type", + }, + Object { + "loc": Object { + "end": Object { + "column": 13, + "line": 2, + }, + "start": Object { + "column": 5, + "line": 2, + }, + }, + "range": Array [ + 34, + 42, + ], + "type": "Identifier", + "value": "Quantity", + }, + Object { + "loc": Object { + "end": Object { + "column": 15, + "line": 2, + }, + "start": Object { + "column": 14, + "line": 2, + }, + }, + "range": Array [ + 43, + 44, + ], + "type": "Punctuator", + "value": "=", + }, + Object { + "loc": Object { + "end": Object { + "column": 21, + "line": 2, + }, + "start": Object { + "column": 16, + "line": 2, + }, + }, + "range": Array [ + 45, + 50, + ], + "type": "String", + "value": "\\"one\\"", + }, + Object { + "loc": Object { + "end": Object { + "column": 23, + "line": 2, + }, + "start": Object { + "column": 22, + "line": 2, + }, + }, + "range": Array [ + 51, + 52, + ], + "type": "Punctuator", + "value": "|", + }, + Object { + "loc": Object { + "end": Object { + "column": 29, + "line": 2, + }, + "start": Object { + "column": 24, + "line": 2, + }, + }, + "range": Array [ + 53, + 58, + ], + "type": "String", + "value": "\\"two\\"", + }, + Object { + "loc": Object { + "end": Object { + "column": 30, + "line": 2, + }, + "start": Object { + "column": 29, + "line": 2, + }, + }, + "range": Array [ + 58, + 59, + ], + "type": "Punctuator", + "value": ";", + }, + Object { + "loc": Object { + "end": Object { + "column": 4, + "line": 3, + }, + "start": Object { + "column": 0, + "line": 3, + }, + }, + "range": Array [ + 60, + 64, + ], + "type": "Identifier", + "value": "type", + }, + Object { + "loc": Object { + "end": Object { + "column": 14, + "line": 3, + }, + "start": Object { + "column": 5, + "line": 3, + }, + }, + "range": Array [ + 65, + 74, + ], + "type": "Identifier", + "value": "SeussFish", + }, + Object { + "loc": Object { + "end": Object { + "column": 16, + "line": 3, + }, + "start": Object { + "column": 15, + "line": 3, + }, + }, + "range": Array [ + 75, + 76, + ], + "type": "Punctuator", + "value": "=", + }, + Object { + "loc": Object { + "end": Object { + "column": 20, + "line": 3, + }, + "start": Object { + "column": 17, + "line": 3, + }, + }, + "range": Array [ + 77, + 80, + ], + "type": "Template", + "value": "\`\${", + }, + Object { + "loc": Object { + "end": Object { + "column": 28, + "line": 3, + }, + "start": Object { + "column": 20, + "line": 3, + }, + }, + "range": Array [ + 80, + 88, + ], + "type": "Identifier", + "value": "Quantity", + }, + Object { + "loc": Object { + "end": Object { + "column": 30, + "line": 3, + }, + "start": Object { + "column": 29, + "line": 3, + }, + }, + "range": Array [ + 89, + 90, + ], + "type": "Punctuator", + "value": "|", + }, + Object { + "loc": Object { + "end": Object { + "column": 36, + "line": 3, + }, + "start": Object { + "column": 31, + "line": 3, + }, + }, + "range": Array [ + 91, + 96, + ], + "type": "Identifier", + "value": "Color", + }, + Object { + "loc": Object { + "end": Object { + "column": 43, + "line": 3, + }, + "start": Object { + "column": 36, + "line": 3, + }, + }, + "range": Array [ + 96, + 103, + ], + "type": "Template", + "value": "} fish\`", + }, + Object { + "loc": Object { + "end": Object { + "column": 44, + "line": 3, + }, + "start": Object { + "column": 43, + "line": 3, + }, + }, + "range": Array [ + 103, + 104, + ], + "type": "Punctuator", + "value": ";", + }, + ], + "type": "Program", +} +`; diff --git a/packages/typescript-estree/tests/snapshots/typescript/types/template-literal-type-4.src.ts.shot b/packages/typescript-estree/tests/snapshots/typescript/types/template-literal-type-4.src.ts.shot new file mode 100644 index 000000000000..fafb3e04c2f7 --- /dev/null +++ b/packages/typescript-estree/tests/snapshots/typescript/types/template-literal-type-4.src.ts.shot @@ -0,0 +1,1434 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`typescript types template-literal-type-4.src 1`] = ` +Object { + "body": Array [ + Object { + "id": Object { + "loc": Object { + "end": Object { + "column": 25, + "line": 1, + }, + "start": Object { + "column": 5, + "line": 1, + }, + }, + "name": "EnthusiasticGreeting", + "range": Array [ + 5, + 25, + ], + "type": "Identifier", + }, + "loc": Object { + "end": Object { + "column": 122, + "line": 1, + }, + "start": Object { + "column": 0, + "line": 1, + }, + }, + "range": Array [ + 0, + 122, + ], + "type": "TSTypeAliasDeclaration", + "typeAnnotation": Object { + "loc": Object { + "end": Object { + "column": 121, + "line": 1, + }, + "start": Object { + "column": 46, + "line": 1, + }, + }, + "quasis": Array [ + Object { + "loc": Object { + "end": Object { + "column": 49, + "line": 1, + }, + "start": Object { + "column": 46, + "line": 1, + }, + }, + "range": Array [ + 46, + 49, + ], + "tail": false, + "type": "TemplateElement", + "value": Object { + "cooked": "", + "raw": "", + }, + }, + Object { + "loc": Object { + "end": Object { + "column": 67, + "line": 1, + }, + "start": Object { + "column": 61, + "line": 1, + }, + }, + "range": Array [ + 61, + 67, + ], + "tail": false, + "type": "TemplateElement", + "value": Object { + "cooked": " - ", + "raw": " - ", + }, + }, + Object { + "loc": Object { + "end": Object { + "column": 85, + "line": 1, + }, + "start": Object { + "column": 79, + "line": 1, + }, + }, + "range": Array [ + 79, + 85, + ], + "tail": false, + "type": "TemplateElement", + "value": Object { + "cooked": " - ", + "raw": " - ", + }, + }, + Object { + "loc": Object { + "end": Object { + "column": 104, + "line": 1, + }, + "start": Object { + "column": 98, + "line": 1, + }, + }, + "range": Array [ + 98, + 104, + ], + "tail": false, + "type": "TemplateElement", + "value": Object { + "cooked": " - ", + "raw": " - ", + }, + }, + Object { + "loc": Object { + "end": Object { + "column": 121, + "line": 1, + }, + "start": Object { + "column": 119, + "line": 1, + }, + }, + "range": Array [ + 119, + 121, + ], + "tail": true, + "type": "TemplateElement", + "value": Object { + "cooked": "", + "raw": "", + }, + }, + ], + "range": Array [ + 46, + 121, + ], + "type": "TSTemplateLiteralType", + "types": Array [ + Object { + "loc": Object { + "end": Object { + "column": 61, + "line": 1, + }, + "start": Object { + "column": 49, + "line": 1, + }, + }, + "range": Array [ + 49, + 61, + ], + "type": "TSTypeReference", + "typeName": Object { + "loc": Object { + "end": Object { + "column": 58, + "line": 1, + }, + "start": Object { + "column": 49, + "line": 1, + }, + }, + "name": "Uppercase", + "range": Array [ + 49, + 58, + ], + "type": "Identifier", + }, + "typeParameters": Object { + "loc": Object { + "end": Object { + "column": 61, + "line": 1, + }, + "start": Object { + "column": 58, + "line": 1, + }, + }, + "params": Array [ + Object { + "loc": Object { + "end": Object { + "column": 60, + "line": 1, + }, + "start": Object { + "column": 59, + "line": 1, + }, + }, + "range": Array [ + 59, + 60, + ], + "type": "TSTypeReference", + "typeName": Object { + "loc": Object { + "end": Object { + "column": 60, + "line": 1, + }, + "start": Object { + "column": 59, + "line": 1, + }, + }, + "name": "T", + "range": Array [ + 59, + 60, + ], + "type": "Identifier", + }, + "typeParameters": undefined, + }, + ], + "range": Array [ + 58, + 61, + ], + "type": "TSTypeParameterInstantiation", + }, + }, + Object { + "loc": Object { + "end": Object { + "column": 79, + "line": 1, + }, + "start": Object { + "column": 67, + "line": 1, + }, + }, + "range": Array [ + 67, + 79, + ], + "type": "TSTypeReference", + "typeName": Object { + "loc": Object { + "end": Object { + "column": 76, + "line": 1, + }, + "start": Object { + "column": 67, + "line": 1, + }, + }, + "name": "Lowercase", + "range": Array [ + 67, + 76, + ], + "type": "Identifier", + }, + "typeParameters": Object { + "loc": Object { + "end": Object { + "column": 79, + "line": 1, + }, + "start": Object { + "column": 76, + "line": 1, + }, + }, + "params": Array [ + Object { + "loc": Object { + "end": Object { + "column": 78, + "line": 1, + }, + "start": Object { + "column": 77, + "line": 1, + }, + }, + "range": Array [ + 77, + 78, + ], + "type": "TSTypeReference", + "typeName": Object { + "loc": Object { + "end": Object { + "column": 78, + "line": 1, + }, + "start": Object { + "column": 77, + "line": 1, + }, + }, + "name": "T", + "range": Array [ + 77, + 78, + ], + "type": "Identifier", + }, + "typeParameters": undefined, + }, + ], + "range": Array [ + 76, + 79, + ], + "type": "TSTypeParameterInstantiation", + }, + }, + Object { + "loc": Object { + "end": Object { + "column": 98, + "line": 1, + }, + "start": Object { + "column": 85, + "line": 1, + }, + }, + "range": Array [ + 85, + 98, + ], + "type": "TSTypeReference", + "typeName": Object { + "loc": Object { + "end": Object { + "column": 95, + "line": 1, + }, + "start": Object { + "column": 85, + "line": 1, + }, + }, + "name": "Capitalize", + "range": Array [ + 85, + 95, + ], + "type": "Identifier", + }, + "typeParameters": Object { + "loc": Object { + "end": Object { + "column": 98, + "line": 1, + }, + "start": Object { + "column": 95, + "line": 1, + }, + }, + "params": Array [ + Object { + "loc": Object { + "end": Object { + "column": 97, + "line": 1, + }, + "start": Object { + "column": 96, + "line": 1, + }, + }, + "range": Array [ + 96, + 97, + ], + "type": "TSTypeReference", + "typeName": Object { + "loc": Object { + "end": Object { + "column": 97, + "line": 1, + }, + "start": Object { + "column": 96, + "line": 1, + }, + }, + "name": "T", + "range": Array [ + 96, + 97, + ], + "type": "Identifier", + }, + "typeParameters": undefined, + }, + ], + "range": Array [ + 95, + 98, + ], + "type": "TSTypeParameterInstantiation", + }, + }, + Object { + "loc": Object { + "end": Object { + "column": 119, + "line": 1, + }, + "start": Object { + "column": 104, + "line": 1, + }, + }, + "range": Array [ + 104, + 119, + ], + "type": "TSTypeReference", + "typeName": Object { + "loc": Object { + "end": Object { + "column": 116, + "line": 1, + }, + "start": Object { + "column": 104, + "line": 1, + }, + }, + "name": "Uncapitalize", + "range": Array [ + 104, + 116, + ], + "type": "Identifier", + }, + "typeParameters": Object { + "loc": Object { + "end": Object { + "column": 119, + "line": 1, + }, + "start": Object { + "column": 116, + "line": 1, + }, + }, + "params": Array [ + Object { + "loc": Object { + "end": Object { + "column": 118, + "line": 1, + }, + "start": Object { + "column": 117, + "line": 1, + }, + }, + "range": Array [ + 117, + 118, + ], + "type": "TSTypeReference", + "typeName": Object { + "loc": Object { + "end": Object { + "column": 118, + "line": 1, + }, + "start": Object { + "column": 117, + "line": 1, + }, + }, + "name": "T", + "range": Array [ + 117, + 118, + ], + "type": "Identifier", + }, + "typeParameters": undefined, + }, + ], + "range": Array [ + 116, + 119, + ], + "type": "TSTypeParameterInstantiation", + }, + }, + ], + }, + "typeParameters": Object { + "loc": Object { + "end": Object { + "column": 43, + "line": 1, + }, + "start": Object { + "column": 25, + "line": 1, + }, + }, + "params": Array [ + Object { + "constraint": Object { + "loc": Object { + "end": Object { + "column": 42, + "line": 1, + }, + "start": Object { + "column": 36, + "line": 1, + }, + }, + "range": Array [ + 36, + 42, + ], + "type": "TSStringKeyword", + }, + "default": undefined, + "loc": Object { + "end": Object { + "column": 42, + "line": 1, + }, + "start": Object { + "column": 26, + "line": 1, + }, + }, + "name": Object { + "loc": Object { + "end": Object { + "column": 27, + "line": 1, + }, + "start": Object { + "column": 26, + "line": 1, + }, + }, + "name": "T", + "range": Array [ + 26, + 27, + ], + "type": "Identifier", + }, + "range": Array [ + 26, + 42, + ], + "type": "TSTypeParameter", + }, + ], + "range": Array [ + 25, + 43, + ], + "type": "TSTypeParameterDeclaration", + }, + }, + Object { + "id": Object { + "loc": Object { + "end": Object { + "column": 10, + "line": 2, + }, + "start": Object { + "column": 5, + "line": 2, + }, + }, + "name": "HELLO", + "range": Array [ + 128, + 133, + ], + "type": "Identifier", + }, + "loc": Object { + "end": Object { + "column": 43, + "line": 2, + }, + "start": Object { + "column": 0, + "line": 2, + }, + }, + "range": Array [ + 123, + 166, + ], + "type": "TSTypeAliasDeclaration", + "typeAnnotation": Object { + "loc": Object { + "end": Object { + "column": 42, + "line": 2, + }, + "start": Object { + "column": 13, + "line": 2, + }, + }, + "range": Array [ + 136, + 165, + ], + "type": "TSTypeReference", + "typeName": Object { + "loc": Object { + "end": Object { + "column": 33, + "line": 2, + }, + "start": Object { + "column": 13, + "line": 2, + }, + }, + "name": "EnthusiasticGreeting", + "range": Array [ + 136, + 156, + ], + "type": "Identifier", + }, + "typeParameters": Object { + "loc": Object { + "end": Object { + "column": 42, + "line": 2, + }, + "start": Object { + "column": 33, + "line": 2, + }, + }, + "params": Array [ + Object { + "literal": Object { + "loc": Object { + "end": Object { + "column": 41, + "line": 2, + }, + "start": Object { + "column": 34, + "line": 2, + }, + }, + "range": Array [ + 157, + 164, + ], + "raw": "\\"heLLo\\"", + "type": "Literal", + "value": "heLLo", + }, + "loc": Object { + "end": Object { + "column": 41, + "line": 2, + }, + "start": Object { + "column": 34, + "line": 2, + }, + }, + "range": Array [ + 157, + 164, + ], + "type": "TSLiteralType", + }, + ], + "range": Array [ + 156, + 165, + ], + "type": "TSTypeParameterInstantiation", + }, + }, + }, + ], + "comments": Array [], + "loc": Object { + "end": Object { + "column": 0, + "line": 3, + }, + "start": Object { + "column": 0, + "line": 1, + }, + }, + "range": Array [ + 0, + 167, + ], + "sourceType": "script", + "tokens": Array [ + Object { + "loc": Object { + "end": Object { + "column": 4, + "line": 1, + }, + "start": Object { + "column": 0, + "line": 1, + }, + }, + "range": Array [ + 0, + 4, + ], + "type": "Identifier", + "value": "type", + }, + Object { + "loc": Object { + "end": Object { + "column": 25, + "line": 1, + }, + "start": Object { + "column": 5, + "line": 1, + }, + }, + "range": Array [ + 5, + 25, + ], + "type": "Identifier", + "value": "EnthusiasticGreeting", + }, + Object { + "loc": Object { + "end": Object { + "column": 26, + "line": 1, + }, + "start": Object { + "column": 25, + "line": 1, + }, + }, + "range": Array [ + 25, + 26, + ], + "type": "Punctuator", + "value": "<", + }, + Object { + "loc": Object { + "end": Object { + "column": 27, + "line": 1, + }, + "start": Object { + "column": 26, + "line": 1, + }, + }, + "range": Array [ + 26, + 27, + ], + "type": "Identifier", + "value": "T", + }, + Object { + "loc": Object { + "end": Object { + "column": 35, + "line": 1, + }, + "start": Object { + "column": 28, + "line": 1, + }, + }, + "range": Array [ + 28, + 35, + ], + "type": "Keyword", + "value": "extends", + }, + Object { + "loc": Object { + "end": Object { + "column": 42, + "line": 1, + }, + "start": Object { + "column": 36, + "line": 1, + }, + }, + "range": Array [ + 36, + 42, + ], + "type": "Identifier", + "value": "string", + }, + Object { + "loc": Object { + "end": Object { + "column": 43, + "line": 1, + }, + "start": Object { + "column": 42, + "line": 1, + }, + }, + "range": Array [ + 42, + 43, + ], + "type": "Punctuator", + "value": ">", + }, + Object { + "loc": Object { + "end": Object { + "column": 45, + "line": 1, + }, + "start": Object { + "column": 44, + "line": 1, + }, + }, + "range": Array [ + 44, + 45, + ], + "type": "Punctuator", + "value": "=", + }, + Object { + "loc": Object { + "end": Object { + "column": 49, + "line": 1, + }, + "start": Object { + "column": 46, + "line": 1, + }, + }, + "range": Array [ + 46, + 49, + ], + "type": "Template", + "value": "\`\${", + }, + Object { + "loc": Object { + "end": Object { + "column": 58, + "line": 1, + }, + "start": Object { + "column": 49, + "line": 1, + }, + }, + "range": Array [ + 49, + 58, + ], + "type": "Identifier", + "value": "Uppercase", + }, + Object { + "loc": Object { + "end": Object { + "column": 59, + "line": 1, + }, + "start": Object { + "column": 58, + "line": 1, + }, + }, + "range": Array [ + 58, + 59, + ], + "type": "Punctuator", + "value": "<", + }, + Object { + "loc": Object { + "end": Object { + "column": 60, + "line": 1, + }, + "start": Object { + "column": 59, + "line": 1, + }, + }, + "range": Array [ + 59, + 60, + ], + "type": "Identifier", + "value": "T", + }, + Object { + "loc": Object { + "end": Object { + "column": 61, + "line": 1, + }, + "start": Object { + "column": 60, + "line": 1, + }, + }, + "range": Array [ + 60, + 61, + ], + "type": "Punctuator", + "value": ">", + }, + Object { + "loc": Object { + "end": Object { + "column": 67, + "line": 1, + }, + "start": Object { + "column": 61, + "line": 1, + }, + }, + "range": Array [ + 61, + 67, + ], + "type": "Template", + "value": "} - \${", + }, + Object { + "loc": Object { + "end": Object { + "column": 76, + "line": 1, + }, + "start": Object { + "column": 67, + "line": 1, + }, + }, + "range": Array [ + 67, + 76, + ], + "type": "Identifier", + "value": "Lowercase", + }, + Object { + "loc": Object { + "end": Object { + "column": 77, + "line": 1, + }, + "start": Object { + "column": 76, + "line": 1, + }, + }, + "range": Array [ + 76, + 77, + ], + "type": "Punctuator", + "value": "<", + }, + Object { + "loc": Object { + "end": Object { + "column": 78, + "line": 1, + }, + "start": Object { + "column": 77, + "line": 1, + }, + }, + "range": Array [ + 77, + 78, + ], + "type": "Identifier", + "value": "T", + }, + Object { + "loc": Object { + "end": Object { + "column": 79, + "line": 1, + }, + "start": Object { + "column": 78, + "line": 1, + }, + }, + "range": Array [ + 78, + 79, + ], + "type": "Punctuator", + "value": ">", + }, + Object { + "loc": Object { + "end": Object { + "column": 85, + "line": 1, + }, + "start": Object { + "column": 79, + "line": 1, + }, + }, + "range": Array [ + 79, + 85, + ], + "type": "Template", + "value": "} - \${", + }, + Object { + "loc": Object { + "end": Object { + "column": 95, + "line": 1, + }, + "start": Object { + "column": 85, + "line": 1, + }, + }, + "range": Array [ + 85, + 95, + ], + "type": "Identifier", + "value": "Capitalize", + }, + Object { + "loc": Object { + "end": Object { + "column": 96, + "line": 1, + }, + "start": Object { + "column": 95, + "line": 1, + }, + }, + "range": Array [ + 95, + 96, + ], + "type": "Punctuator", + "value": "<", + }, + Object { + "loc": Object { + "end": Object { + "column": 97, + "line": 1, + }, + "start": Object { + "column": 96, + "line": 1, + }, + }, + "range": Array [ + 96, + 97, + ], + "type": "Identifier", + "value": "T", + }, + Object { + "loc": Object { + "end": Object { + "column": 98, + "line": 1, + }, + "start": Object { + "column": 97, + "line": 1, + }, + }, + "range": Array [ + 97, + 98, + ], + "type": "Punctuator", + "value": ">", + }, + Object { + "loc": Object { + "end": Object { + "column": 104, + "line": 1, + }, + "start": Object { + "column": 98, + "line": 1, + }, + }, + "range": Array [ + 98, + 104, + ], + "type": "Template", + "value": "} - \${", + }, + Object { + "loc": Object { + "end": Object { + "column": 116, + "line": 1, + }, + "start": Object { + "column": 104, + "line": 1, + }, + }, + "range": Array [ + 104, + 116, + ], + "type": "Identifier", + "value": "Uncapitalize", + }, + Object { + "loc": Object { + "end": Object { + "column": 117, + "line": 1, + }, + "start": Object { + "column": 116, + "line": 1, + }, + }, + "range": Array [ + 116, + 117, + ], + "type": "Punctuator", + "value": "<", + }, + Object { + "loc": Object { + "end": Object { + "column": 118, + "line": 1, + }, + "start": Object { + "column": 117, + "line": 1, + }, + }, + "range": Array [ + 117, + 118, + ], + "type": "Identifier", + "value": "T", + }, + Object { + "loc": Object { + "end": Object { + "column": 119, + "line": 1, + }, + "start": Object { + "column": 118, + "line": 1, + }, + }, + "range": Array [ + 118, + 119, + ], + "type": "Punctuator", + "value": ">", + }, + Object { + "loc": Object { + "end": Object { + "column": 121, + "line": 1, + }, + "start": Object { + "column": 119, + "line": 1, + }, + }, + "range": Array [ + 119, + 121, + ], + "type": "Template", + "value": "}\`", + }, + Object { + "loc": Object { + "end": Object { + "column": 122, + "line": 1, + }, + "start": Object { + "column": 121, + "line": 1, + }, + }, + "range": Array [ + 121, + 122, + ], + "type": "Punctuator", + "value": ";", + }, + Object { + "loc": Object { + "end": Object { + "column": 4, + "line": 2, + }, + "start": Object { + "column": 0, + "line": 2, + }, + }, + "range": Array [ + 123, + 127, + ], + "type": "Identifier", + "value": "type", + }, + Object { + "loc": Object { + "end": Object { + "column": 10, + "line": 2, + }, + "start": Object { + "column": 5, + "line": 2, + }, + }, + "range": Array [ + 128, + 133, + ], + "type": "Identifier", + "value": "HELLO", + }, + Object { + "loc": Object { + "end": Object { + "column": 12, + "line": 2, + }, + "start": Object { + "column": 11, + "line": 2, + }, + }, + "range": Array [ + 134, + 135, + ], + "type": "Punctuator", + "value": "=", + }, + Object { + "loc": Object { + "end": Object { + "column": 33, + "line": 2, + }, + "start": Object { + "column": 13, + "line": 2, + }, + }, + "range": Array [ + 136, + 156, + ], + "type": "Identifier", + "value": "EnthusiasticGreeting", + }, + Object { + "loc": Object { + "end": Object { + "column": 34, + "line": 2, + }, + "start": Object { + "column": 33, + "line": 2, + }, + }, + "range": Array [ + 156, + 157, + ], + "type": "Punctuator", + "value": "<", + }, + Object { + "loc": Object { + "end": Object { + "column": 41, + "line": 2, + }, + "start": Object { + "column": 34, + "line": 2, + }, + }, + "range": Array [ + 157, + 164, + ], + "type": "String", + "value": "\\"heLLo\\"", + }, + Object { + "loc": Object { + "end": Object { + "column": 42, + "line": 2, + }, + "start": Object { + "column": 41, + "line": 2, + }, + }, + "range": Array [ + 164, + 165, + ], + "type": "Punctuator", + "value": ">", + }, + Object { + "loc": Object { + "end": Object { + "column": 43, + "line": 2, + }, + "start": Object { + "column": 42, + "line": 2, + }, + }, + "range": Array [ + 165, + 166, + ], + "type": "Punctuator", + "value": ";", + }, + ], + "type": "Program", +} +`; diff --git a/packages/visitor-keys/CHANGELOG.md b/packages/visitor-keys/CHANGELOG.md index dfa8e0bae8f8..1998425b819f 100644 --- a/packages/visitor-keys/CHANGELOG.md +++ b/packages/visitor-keys/CHANGELOG.md @@ -3,6 +3,17 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [4.7.0](https://github.com/typescript-eslint/typescript-eslint/compare/v4.6.1...v4.7.0) (2020-11-09) + + +### Features + +* support TS4.1 features ([#2748](https://github.com/typescript-eslint/typescript-eslint/issues/2748)) ([2be354b](https://github.com/typescript-eslint/typescript-eslint/commit/2be354bb15f9013a2da1b13a0c0836e9ef057e16)), closes [#2583](https://github.com/typescript-eslint/typescript-eslint/issues/2583) + + + + + ## [4.6.1](https://github.com/typescript-eslint/typescript-eslint/compare/v4.6.0...v4.6.1) (2020-11-02) **Note:** Version bump only for package @typescript-eslint/visitor-keys diff --git a/packages/visitor-keys/package.json b/packages/visitor-keys/package.json index 416b275a25de..3af54d385939 100644 --- a/packages/visitor-keys/package.json +++ b/packages/visitor-keys/package.json @@ -1,6 +1,6 @@ { "name": "@typescript-eslint/visitor-keys", - "version": "4.6.1", + "version": "4.7.0", "description": "Visitor keys used to help traverse the TypeScript-ESTree AST", "keywords": [ "eslint", @@ -38,7 +38,7 @@ "typecheck": "tsc -p tsconfig.json --noEmit" }, "dependencies": { - "@typescript-eslint/types": "4.6.1", + "@typescript-eslint/types": "4.7.0", "eslint-visitor-keys": "^2.0.0" }, "devDependencies": { diff --git a/packages/visitor-keys/src/visitor-keys.ts b/packages/visitor-keys/src/visitor-keys.ts index a279aef46bff..68c6b806bcc6 100644 --- a/packages/visitor-keys/src/visitor-keys.ts +++ b/packages/visitor-keys/src/visitor-keys.ts @@ -100,7 +100,7 @@ const additionalKeys: AdditionalKeys = { TSInterfaceHeritage: ['expression', 'typeParameters'], TSIntersectionType: ['types'], TSLiteralType: ['literal'], - TSMappedType: ['typeParameter', 'typeAnnotation'], + TSMappedType: ['nameType', 'typeParameter', 'typeAnnotation'], TSMethodSignature: ['typeParameters', 'key', 'params', 'returnType'], TSModuleBlock: ['body'], TSModuleDeclaration: ['id', 'body'], @@ -124,6 +124,7 @@ const additionalKeys: AdditionalKeys = { TSStaticKeyword: [], TSStringKeyword: [], TSSymbolKeyword: [], + TSTemplateLiteralType: ['quasis', 'types'], TSThisType: [], TSTupleType: ['elementTypes'], TSTypeAliasDeclaration: ['id', 'typeParameters', 'typeAnnotation'], diff --git a/yarn.lock b/yarn.lock index 1f9392516f0e..7dec3d717079 100644 --- a/yarn.lock +++ b/yarn.lock @@ -143,11 +143,16 @@ chalk "^2.0.0" js-tokens "^4.0.0" -"@babel/parser@^7.1.0", "@babel/parser@^7.10.4", "@babel/parser@^7.11.0", "@babel/parser@^7.11.3", "@babel/parser@^7.11.4": +"@babel/parser@^7.1.0", "@babel/parser@^7.10.4", "@babel/parser@^7.11.0", "@babel/parser@^7.11.4": version "7.11.4" resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.11.4.tgz#6fa1a118b8b0d80d0267b719213dc947e88cc0ca" integrity sha512-MggwidiH+E9j5Sh8pbrX5sJvMcsqS5o+7iB42M9/k0CD63MjYbdP4nhSh7uB5wnv2/RVzTZFTxzF/kIa5mrCqA== +"@babel/parser@^7.12.5": + version "7.12.5" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.12.5.tgz#b4af32ddd473c0bfa643bd7ff0728b8e71b81ea0" + integrity sha512-FVM6RZQ0mn2KCf1VUED7KepYeUWoVShczewOCfm3nzoBybaih51h+sYVVGthW9M6lPByEPTQf+xm27PBdlpwmQ== + "@babel/plugin-syntax-async-generators@^7.8.4": version "7.8.4" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz#a983fb1aeb2ec3f6ed042a210f640e90e786fe0d" @@ -265,6 +270,15 @@ lodash "^4.17.19" to-fast-properties "^2.0.0" +"@babel/types@^7.12.6": + version "7.12.6" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.12.6.tgz#ae0e55ef1cce1fbc881cd26f8234eb3e657edc96" + integrity sha512-hwyjw6GvjBLiyy3W0YQf0Z5Zf4NpYejUnKFcfcUhZCSffoBBp30w6wP2Wn6pk31jMYZvcOrB/1b7cGXvEoKogA== + dependencies: + "@babel/helper-validator-identifier" "^7.10.4" + lodash "^4.17.19" + to-fast-properties "^2.0.0" + "@bcoe/v8-coverage@^0.2.3": version "0.2.3" resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39" @@ -1536,10 +1550,10 @@ dependencies: "@sinonjs/commons" "^1.7.0" -"@types/babel__code-frame@^7.0.1": - version "7.0.1" - resolved "https://registry.yarnpkg.com/@types/babel__code-frame/-/babel__code-frame-7.0.1.tgz#baf2529c4abbfb5e4008c845efcfe39a187e2f99" - integrity sha512-FFfbQozKxYmOnCKFYV+EQprjBI7u2yaNc2ly/K9AhzyC8MzXtCtSRqptpw+HUJxhwCOo5mLwf1ATmzyhOaVbDg== +"@types/babel__code-frame@^7.0.2": + version "7.0.2" + resolved "https://registry.yarnpkg.com/@types/babel__code-frame/-/babel__code-frame-7.0.2.tgz#e0c0f1648cbc09a9d4e5b4ed2ae9a6f7c8f5aeb0" + integrity sha512-imO+jT/yjOKOAS5GQZ8SDtwiIloAGGr6OaZDKB0V5JVaSfGZLat5K5/ZRtyKW6R60XHV3RHYPTFfhYb+wDKyKg== "@types/babel__core@^7.0.0", "@types/babel__core@^7.1.7": version "7.1.9" @@ -3514,13 +3528,14 @@ dot-prop@^5.1.0, dot-prop@^5.2.0: dependencies: is-obj "^2.0.0" -downlevel-dts@^0.6.0: - version "0.6.0" - resolved "https://registry.yarnpkg.com/downlevel-dts/-/downlevel-dts-0.6.0.tgz#1e52db9fa3ad9e3919a36545412f0b41a44289d1" - integrity sha512-Jy3ZZcXWPzTn5jJRW5WpdEtIq8+UowWWi5TEBgHHvzw320kouV//2KgVhfcuOpP93KS3UAokTxnZKU4L75kRSQ== +downlevel-dts@^0.7.0: + version "0.7.0" + resolved "https://registry.yarnpkg.com/downlevel-dts/-/downlevel-dts-0.7.0.tgz#155c24310dad8a4820ad077e64b15a8c461aa932" + integrity sha512-tcjGqElN0/oad/LJBlaxmZ3zOYEQOBbGuirKzif8s1jeRiWBdNX9H6OBFlRjOQkosXgV+qSjs4osuGCivyZ4Jw== dependencies: + semver "^7.3.2" shelljs "^0.8.3" - typescript "^4.1.0-dev.20200804" + typescript "^4.1.0-dev.20201026" duplexer@^0.1.1: version "0.1.2" @@ -8669,10 +8684,10 @@ typedarray@^0.0.6: resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c= -typescript@*, typescript@4.0.2, "typescript@>=3.3.1 <4.1.0", typescript@^4.1.0-dev.20200804: - version "4.0.2" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.0.2.tgz#7ea7c88777c723c681e33bf7988be5d008d05ac2" - integrity sha512-e4ERvRV2wb+rRZ/IQeb3jm2VxBsirQLpQhdxplZ2MEzGvDkkMmPglecnNDfSUBivMjP93vRbngYYDQqQ/78bcQ== +typescript@*, typescript@4.1.1-rc, "typescript@>=3.3.1 <4.2.0 || 4.1.1-rc", typescript@^4.1.0-dev.20201026: + version "4.1.1-rc" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.1.1-rc.tgz#4a335244b9b2754995849ca4b607c74d6ee73719" + integrity sha512-tgNcFrLIjlaMWEc7bKC0bxLNIt8BIAauY/HLUOQDyTP75HGskETtXOt46x4EKAHRKhWVLMc7yM02puTHa/yhCA== uc.micro@^1.0.1, uc.micro@^1.0.5: version "1.0.6"