From c5aab46ed2138b06d2e56d73e2e93811e8be94ae Mon Sep 17 00:00:00 2001 From: sonallux <13821543+sonallux@users.noreply.github.com> Date: Tue, 4 May 2021 21:22:04 +0200 Subject: [PATCH 1/4] feat(eslint-plugin): add `no-non-null-asserted-nullish-coalescing` rule fixes #2853 --- packages/eslint-plugin/README.md | 165 +++++++++--------- ...no-non-null-asserted-nullish-coalescing.md | 38 ++++ packages/eslint-plugin/src/configs/all.ts | 1 + packages/eslint-plugin/src/rules/index.ts | 2 + ...no-non-null-asserted-nullish-coalescing.ts | 44 +++++ ...n-null-asserted-nullish-coalescing.test.ts | 134 ++++++++++++++ 6 files changed, 302 insertions(+), 82 deletions(-) create mode 100644 packages/eslint-plugin/docs/rules/no-non-null-asserted-nullish-coalescing.md create mode 100644 packages/eslint-plugin/src/rules/no-non-null-asserted-nullish-coalescing.ts create mode 100644 packages/eslint-plugin/tests/rules/no-non-null-asserted-nullish-coalescing.test.ts diff --git a/packages/eslint-plugin/README.md b/packages/eslint-plugin/README.md index 344764dcb96b..b38cf23abdb1 100644 --- a/packages/eslint-plugin/README.md +++ b/packages/eslint-plugin/README.md @@ -95,88 +95,89 @@ Pro Tip: For larger codebases you may want to consider splitting our linting int **Key**: :white_check_mark: = recommended, :wrench: = fixable, :thought_balloon: = requires type information -| Name | Description | :white_check_mark: | :wrench: | :thought_balloon: | -| --------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------- | ------------------ | -------- | ----------------- | -| [`@typescript-eslint/adjacent-overload-signatures`](./docs/rules/adjacent-overload-signatures.md) | Require that member overloads be consecutive | :white_check_mark: | | | -| [`@typescript-eslint/array-type`](./docs/rules/array-type.md) | Requires using either `T[]` or `Array` for arrays | | :wrench: | | -| [`@typescript-eslint/await-thenable`](./docs/rules/await-thenable.md) | Disallows awaiting a value that is not a Thenable | :white_check_mark: | | :thought_balloon: | -| [`@typescript-eslint/ban-ts-comment`](./docs/rules/ban-ts-comment.md) | Bans `@ts-` comments from being used or requires descriptions after directive | :white_check_mark: | | | -| [`@typescript-eslint/ban-tslint-comment`](./docs/rules/ban-tslint-comment.md) | Bans `// tslint:` comments from being used | | :wrench: | | -| [`@typescript-eslint/ban-types`](./docs/rules/ban-types.md) | Bans specific types from being used | :white_check_mark: | :wrench: | | -| [`@typescript-eslint/class-literal-property-style`](./docs/rules/class-literal-property-style.md) | Ensures that literals on classes are exposed in a consistent style | | :wrench: | | -| [`@typescript-eslint/consistent-indexed-object-style`](./docs/rules/consistent-indexed-object-style.md) | Enforce or disallow the use of the record type | | :wrench: | | -| [`@typescript-eslint/consistent-type-assertions`](./docs/rules/consistent-type-assertions.md) | Enforces consistent usage of type assertions | | | | -| [`@typescript-eslint/consistent-type-definitions`](./docs/rules/consistent-type-definitions.md) | Consistent with type definition either `interface` or `type` | | :wrench: | | -| [`@typescript-eslint/consistent-type-imports`](./docs/rules/consistent-type-imports.md) | Enforces consistent usage of type imports | | :wrench: | | -| [`@typescript-eslint/explicit-function-return-type`](./docs/rules/explicit-function-return-type.md) | Require explicit return types on functions and class methods | | | | -| [`@typescript-eslint/explicit-member-accessibility`](./docs/rules/explicit-member-accessibility.md) | Require explicit accessibility modifiers on class properties and methods | | :wrench: | | -| [`@typescript-eslint/explicit-module-boundary-types`](./docs/rules/explicit-module-boundary-types.md) | Require explicit return and argument types on exported functions' and classes' public class methods | :white_check_mark: | | | -| [`@typescript-eslint/member-delimiter-style`](./docs/rules/member-delimiter-style.md) | Require a specific member delimiter style for interfaces and type literals | | :wrench: | | -| [`@typescript-eslint/member-ordering`](./docs/rules/member-ordering.md) | Require a consistent member declaration order | | | | -| [`@typescript-eslint/method-signature-style`](./docs/rules/method-signature-style.md) | Enforces using a particular method signature syntax. | | :wrench: | | -| [`@typescript-eslint/naming-convention`](./docs/rules/naming-convention.md) | Enforces naming conventions for everything across a codebase | | | :thought_balloon: | -| [`@typescript-eslint/no-base-to-string`](./docs/rules/no-base-to-string.md) | Requires that `.toString()` is only called on objects which provide useful information when stringified | | | :thought_balloon: | -| [`@typescript-eslint/no-confusing-non-null-assertion`](./docs/rules/no-confusing-non-null-assertion.md) | Disallow non-null assertion in locations that may be confusing | | :wrench: | | -| [`@typescript-eslint/no-confusing-void-expression`](./docs/rules/no-confusing-void-expression.md) | Requires expressions of type void to appear in statement position | | :wrench: | :thought_balloon: | -| [`@typescript-eslint/no-dynamic-delete`](./docs/rules/no-dynamic-delete.md) | Disallow the delete operator with computed key expressions | | :wrench: | | -| [`@typescript-eslint/no-empty-interface`](./docs/rules/no-empty-interface.md) | Disallow the declaration of empty interfaces | :white_check_mark: | :wrench: | | -| [`@typescript-eslint/no-explicit-any`](./docs/rules/no-explicit-any.md) | Disallow usage of the `any` type | :white_check_mark: | :wrench: | | -| [`@typescript-eslint/no-extra-non-null-assertion`](./docs/rules/no-extra-non-null-assertion.md) | Disallow extra non-null assertion | :white_check_mark: | :wrench: | | -| [`@typescript-eslint/no-extraneous-class`](./docs/rules/no-extraneous-class.md) | Forbids the use of classes as namespaces | | | | -| [`@typescript-eslint/no-floating-promises`](./docs/rules/no-floating-promises.md) | Requires Promise-like values to be handled appropriately | :white_check_mark: | | :thought_balloon: | -| [`@typescript-eslint/no-for-in-array`](./docs/rules/no-for-in-array.md) | Disallow iterating over an array with a for-in loop | :white_check_mark: | | :thought_balloon: | -| [`@typescript-eslint/no-implicit-any-catch`](./docs/rules/no-implicit-any-catch.md) | Disallow usage of the implicit `any` type in catch clauses | | :wrench: | | -| [`@typescript-eslint/no-inferrable-types`](./docs/rules/no-inferrable-types.md) | Disallows explicit type declarations for variables or parameters initialized to a number, string, or boolean | :white_check_mark: | :wrench: | | -| [`@typescript-eslint/no-invalid-void-type`](./docs/rules/no-invalid-void-type.md) | Disallows usage of `void` type outside of generic or return types | | | | -| [`@typescript-eslint/no-misused-new`](./docs/rules/no-misused-new.md) | Enforce valid definition of `new` and `constructor` | :white_check_mark: | | | -| [`@typescript-eslint/no-misused-promises`](./docs/rules/no-misused-promises.md) | Avoid using promises in places not designed to handle them | :white_check_mark: | | :thought_balloon: | -| [`@typescript-eslint/no-namespace`](./docs/rules/no-namespace.md) | Disallow the use of custom TypeScript modules and namespaces | :white_check_mark: | | | -| [`@typescript-eslint/no-non-null-asserted-optional-chain`](./docs/rules/no-non-null-asserted-optional-chain.md) | Disallows using a non-null assertion after an optional chain expression | :white_check_mark: | | | -| [`@typescript-eslint/no-non-null-assertion`](./docs/rules/no-non-null-assertion.md) | Disallows non-null assertions using the `!` postfix operator | :white_check_mark: | | | -| [`@typescript-eslint/no-parameter-properties`](./docs/rules/no-parameter-properties.md) | Disallow the use of parameter properties in class constructors | | | | -| [`@typescript-eslint/no-require-imports`](./docs/rules/no-require-imports.md) | Disallows invocation of `require()` | | | | -| [`@typescript-eslint/no-this-alias`](./docs/rules/no-this-alias.md) | Disallow aliasing `this` | :white_check_mark: | | | -| [`@typescript-eslint/no-type-alias`](./docs/rules/no-type-alias.md) | Disallow the use of type aliases | | | | -| [`@typescript-eslint/no-unnecessary-boolean-literal-compare`](./docs/rules/no-unnecessary-boolean-literal-compare.md) | Flags unnecessary equality comparisons against boolean literals | | :wrench: | :thought_balloon: | -| [`@typescript-eslint/no-unnecessary-condition`](./docs/rules/no-unnecessary-condition.md) | Prevents conditionals where the type is always truthy or always falsy | | :wrench: | :thought_balloon: | -| [`@typescript-eslint/no-unnecessary-qualifier`](./docs/rules/no-unnecessary-qualifier.md) | Warns when a namespace qualifier is unnecessary | | :wrench: | :thought_balloon: | -| [`@typescript-eslint/no-unnecessary-type-arguments`](./docs/rules/no-unnecessary-type-arguments.md) | Enforces that type arguments will not be used if not required | | :wrench: | :thought_balloon: | -| [`@typescript-eslint/no-unnecessary-type-assertion`](./docs/rules/no-unnecessary-type-assertion.md) | Warns if a type assertion does not change the type of an expression | :white_check_mark: | :wrench: | :thought_balloon: | -| [`@typescript-eslint/no-unnecessary-type-constraint`](./docs/rules/no-unnecessary-type-constraint.md) | Disallows unnecessary constraints on generic types | | :wrench: | | -| [`@typescript-eslint/no-unsafe-argument`](./docs/rules/no-unsafe-argument.md) | Disallows calling an function with an any type value | | | :thought_balloon: | -| [`@typescript-eslint/no-unsafe-assignment`](./docs/rules/no-unsafe-assignment.md) | Disallows assigning any to variables and properties | :white_check_mark: | | :thought_balloon: | -| [`@typescript-eslint/no-unsafe-call`](./docs/rules/no-unsafe-call.md) | Disallows calling an any type value | :white_check_mark: | | :thought_balloon: | -| [`@typescript-eslint/no-unsafe-member-access`](./docs/rules/no-unsafe-member-access.md) | Disallows member access on any typed variables | :white_check_mark: | | :thought_balloon: | -| [`@typescript-eslint/no-unsafe-return`](./docs/rules/no-unsafe-return.md) | Disallows returning any from a function | :white_check_mark: | | :thought_balloon: | -| [`@typescript-eslint/no-var-requires`](./docs/rules/no-var-requires.md) | Disallows the use of require statements except in import statements | :white_check_mark: | | | -| [`@typescript-eslint/non-nullable-type-assertion-style`](./docs/rules/non-nullable-type-assertion-style.md) | Prefers a non-null assertion over explicit type cast when possible | | :wrench: | :thought_balloon: | -| [`@typescript-eslint/prefer-as-const`](./docs/rules/prefer-as-const.md) | Prefer usage of `as const` over literal type | :white_check_mark: | :wrench: | | -| [`@typescript-eslint/prefer-enum-initializers`](./docs/rules/prefer-enum-initializers.md) | Prefer initializing each enums member value | | | | -| [`@typescript-eslint/prefer-for-of`](./docs/rules/prefer-for-of.md) | Prefer a ‘for-of’ loop over a standard ‘for’ loop if the index is only used to access the array being iterated | | | | -| [`@typescript-eslint/prefer-function-type`](./docs/rules/prefer-function-type.md) | Use function types instead of interfaces with call signatures | | :wrench: | | -| [`@typescript-eslint/prefer-includes`](./docs/rules/prefer-includes.md) | Enforce `includes` method over `indexOf` method | | :wrench: | :thought_balloon: | -| [`@typescript-eslint/prefer-literal-enum-member`](./docs/rules/prefer-literal-enum-member.md) | Require that all enum members be literal values to prevent unintended enum member name shadow issues | | | | -| [`@typescript-eslint/prefer-namespace-keyword`](./docs/rules/prefer-namespace-keyword.md) | Require the use of the `namespace` keyword instead of the `module` keyword to declare custom TypeScript modules | :white_check_mark: | :wrench: | | -| [`@typescript-eslint/prefer-nullish-coalescing`](./docs/rules/prefer-nullish-coalescing.md) | Enforce the usage of the nullish coalescing operator instead of logical chaining | | | :thought_balloon: | -| [`@typescript-eslint/prefer-optional-chain`](./docs/rules/prefer-optional-chain.md) | Prefer using concise optional chain expressions instead of chained logical ands | | | | -| [`@typescript-eslint/prefer-readonly`](./docs/rules/prefer-readonly.md) | Requires that private members are marked as `readonly` if they're never modified outside of the constructor | | :wrench: | :thought_balloon: | -| [`@typescript-eslint/prefer-readonly-parameter-types`](./docs/rules/prefer-readonly-parameter-types.md) | Requires that function parameters are typed as readonly to prevent accidental mutation of inputs | | | :thought_balloon: | -| [`@typescript-eslint/prefer-reduce-type-parameter`](./docs/rules/prefer-reduce-type-parameter.md) | Prefer using type parameter when calling `Array#reduce` instead of casting | | :wrench: | :thought_balloon: | -| [`@typescript-eslint/prefer-regexp-exec`](./docs/rules/prefer-regexp-exec.md) | Enforce that `RegExp#exec` is used instead of `String#match` if no global flag is provided | :white_check_mark: | :wrench: | :thought_balloon: | -| [`@typescript-eslint/prefer-string-starts-ends-with`](./docs/rules/prefer-string-starts-ends-with.md) | Enforce the use of `String#startsWith` and `String#endsWith` instead of other equivalent methods of checking substrings | | :wrench: | :thought_balloon: | -| [`@typescript-eslint/prefer-ts-expect-error`](./docs/rules/prefer-ts-expect-error.md) | Recommends using `@ts-expect-error` over `@ts-ignore` | | :wrench: | | -| [`@typescript-eslint/promise-function-async`](./docs/rules/promise-function-async.md) | Requires any function or method that returns a Promise to be marked async | | :wrench: | :thought_balloon: | -| [`@typescript-eslint/require-array-sort-compare`](./docs/rules/require-array-sort-compare.md) | Requires `Array#sort` calls to always provide a `compareFunction` | | | :thought_balloon: | -| [`@typescript-eslint/restrict-plus-operands`](./docs/rules/restrict-plus-operands.md) | When adding two variables, operands must both be of type number or of type string | :white_check_mark: | | :thought_balloon: | -| [`@typescript-eslint/restrict-template-expressions`](./docs/rules/restrict-template-expressions.md) | Enforce template literal expressions to be of string type | :white_check_mark: | | :thought_balloon: | -| [`@typescript-eslint/sort-type-union-intersection-members`](./docs/rules/sort-type-union-intersection-members.md) | Enforces that members of a type union/intersection are sorted alphabetically | | :wrench: | | -| [`@typescript-eslint/strict-boolean-expressions`](./docs/rules/strict-boolean-expressions.md) | Restricts the types allowed in boolean expressions | | :wrench: | :thought_balloon: | -| [`@typescript-eslint/switch-exhaustiveness-check`](./docs/rules/switch-exhaustiveness-check.md) | Exhaustiveness checking in switch with union type | | | :thought_balloon: | -| [`@typescript-eslint/triple-slash-reference`](./docs/rules/triple-slash-reference.md) | Sets preference level for triple slash directives versus ES6-style import declarations | :white_check_mark: | | | -| [`@typescript-eslint/type-annotation-spacing`](./docs/rules/type-annotation-spacing.md) | Require consistent spacing around type annotations | | :wrench: | | -| [`@typescript-eslint/typedef`](./docs/rules/typedef.md) | Requires type annotations to exist | | | | -| [`@typescript-eslint/unbound-method`](./docs/rules/unbound-method.md) | Enforces unbound methods are called with their expected scope | :white_check_mark: | | :thought_balloon: | -| [`@typescript-eslint/unified-signatures`](./docs/rules/unified-signatures.md) | Warns for any two overloads that could be unified into one by using a union or an optional/rest parameter | | | | +| Name | Description | :white_check_mark: | :wrench: | :thought_balloon: | +| ----------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------- | ------------------ | -------- | ----------------- | +| [`@typescript-eslint/adjacent-overload-signatures`](./docs/rules/adjacent-overload-signatures.md) | Require that member overloads be consecutive | :white_check_mark: | | | +| [`@typescript-eslint/array-type`](./docs/rules/array-type.md) | Requires using either `T[]` or `Array` for arrays | | :wrench: | | +| [`@typescript-eslint/await-thenable`](./docs/rules/await-thenable.md) | Disallows awaiting a value that is not a Thenable | :white_check_mark: | | :thought_balloon: | +| [`@typescript-eslint/ban-ts-comment`](./docs/rules/ban-ts-comment.md) | Bans `@ts-` comments from being used or requires descriptions after directive | :white_check_mark: | | | +| [`@typescript-eslint/ban-tslint-comment`](./docs/rules/ban-tslint-comment.md) | Bans `// tslint:` comments from being used | | :wrench: | | +| [`@typescript-eslint/ban-types`](./docs/rules/ban-types.md) | Bans specific types from being used | :white_check_mark: | :wrench: | | +| [`@typescript-eslint/class-literal-property-style`](./docs/rules/class-literal-property-style.md) | Ensures that literals on classes are exposed in a consistent style | | :wrench: | | +| [`@typescript-eslint/consistent-indexed-object-style`](./docs/rules/consistent-indexed-object-style.md) | Enforce or disallow the use of the record type | | :wrench: | | +| [`@typescript-eslint/consistent-type-assertions`](./docs/rules/consistent-type-assertions.md) | Enforces consistent usage of type assertions | | | | +| [`@typescript-eslint/consistent-type-definitions`](./docs/rules/consistent-type-definitions.md) | Consistent with type definition either `interface` or `type` | | :wrench: | | +| [`@typescript-eslint/consistent-type-imports`](./docs/rules/consistent-type-imports.md) | Enforces consistent usage of type imports | | :wrench: | | +| [`@typescript-eslint/explicit-function-return-type`](./docs/rules/explicit-function-return-type.md) | Require explicit return types on functions and class methods | | | | +| [`@typescript-eslint/explicit-member-accessibility`](./docs/rules/explicit-member-accessibility.md) | Require explicit accessibility modifiers on class properties and methods | | :wrench: | | +| [`@typescript-eslint/explicit-module-boundary-types`](./docs/rules/explicit-module-boundary-types.md) | Require explicit return and argument types on exported functions' and classes' public class methods | :white_check_mark: | | | +| [`@typescript-eslint/member-delimiter-style`](./docs/rules/member-delimiter-style.md) | Require a specific member delimiter style for interfaces and type literals | | :wrench: | | +| [`@typescript-eslint/member-ordering`](./docs/rules/member-ordering.md) | Require a consistent member declaration order | | | | +| [`@typescript-eslint/method-signature-style`](./docs/rules/method-signature-style.md) | Enforces using a particular method signature syntax. | | :wrench: | | +| [`@typescript-eslint/naming-convention`](./docs/rules/naming-convention.md) | Enforces naming conventions for everything across a codebase | | | :thought_balloon: | +| [`@typescript-eslint/no-base-to-string`](./docs/rules/no-base-to-string.md) | Requires that `.toString()` is only called on objects which provide useful information when stringified | | | :thought_balloon: | +| [`@typescript-eslint/no-confusing-non-null-assertion`](./docs/rules/no-confusing-non-null-assertion.md) | Disallow non-null assertion in locations that may be confusing | | :wrench: | | +| [`@typescript-eslint/no-confusing-void-expression`](./docs/rules/no-confusing-void-expression.md) | Requires expressions of type void to appear in statement position | | :wrench: | :thought_balloon: | +| [`@typescript-eslint/no-dynamic-delete`](./docs/rules/no-dynamic-delete.md) | Disallow the delete operator with computed key expressions | | :wrench: | | +| [`@typescript-eslint/no-empty-interface`](./docs/rules/no-empty-interface.md) | Disallow the declaration of empty interfaces | :white_check_mark: | :wrench: | | +| [`@typescript-eslint/no-explicit-any`](./docs/rules/no-explicit-any.md) | Disallow usage of the `any` type | :white_check_mark: | :wrench: | | +| [`@typescript-eslint/no-extra-non-null-assertion`](./docs/rules/no-extra-non-null-assertion.md) | Disallow extra non-null assertion | :white_check_mark: | :wrench: | | +| [`@typescript-eslint/no-extraneous-class`](./docs/rules/no-extraneous-class.md) | Forbids the use of classes as namespaces | | | | +| [`@typescript-eslint/no-floating-promises`](./docs/rules/no-floating-promises.md) | Requires Promise-like values to be handled appropriately | :white_check_mark: | | :thought_balloon: | +| [`@typescript-eslint/no-for-in-array`](./docs/rules/no-for-in-array.md) | Disallow iterating over an array with a for-in loop | :white_check_mark: | | :thought_balloon: | +| [`@typescript-eslint/no-implicit-any-catch`](./docs/rules/no-implicit-any-catch.md) | Disallow usage of the implicit `any` type in catch clauses | | :wrench: | | +| [`@typescript-eslint/no-inferrable-types`](./docs/rules/no-inferrable-types.md) | Disallows explicit type declarations for variables or parameters initialized to a number, string, or boolean | :white_check_mark: | :wrench: | | +| [`@typescript-eslint/no-invalid-void-type`](./docs/rules/no-invalid-void-type.md) | Disallows usage of `void` type outside of generic or return types | | | | +| [`@typescript-eslint/no-misused-new`](./docs/rules/no-misused-new.md) | Enforce valid definition of `new` and `constructor` | :white_check_mark: | | | +| [`@typescript-eslint/no-misused-promises`](./docs/rules/no-misused-promises.md) | Avoid using promises in places not designed to handle them | :white_check_mark: | | :thought_balloon: | +| [`@typescript-eslint/no-namespace`](./docs/rules/no-namespace.md) | Disallow the use of custom TypeScript modules and namespaces | :white_check_mark: | | | +| [`@typescript-eslint/no-non-null-asserted-nullish-coalescing`](./docs/rules/no-non-null-asserted-nullish-coalescing.md) | Disallows using a non-null assertion in the left operand of the nullish coalescing operator | | | | +| [`@typescript-eslint/no-non-null-asserted-optional-chain`](./docs/rules/no-non-null-asserted-optional-chain.md) | Disallows using a non-null assertion after an optional chain expression | :white_check_mark: | | | +| [`@typescript-eslint/no-non-null-assertion`](./docs/rules/no-non-null-assertion.md) | Disallows non-null assertions using the `!` postfix operator | :white_check_mark: | | | +| [`@typescript-eslint/no-parameter-properties`](./docs/rules/no-parameter-properties.md) | Disallow the use of parameter properties in class constructors | | | | +| [`@typescript-eslint/no-require-imports`](./docs/rules/no-require-imports.md) | Disallows invocation of `require()` | | | | +| [`@typescript-eslint/no-this-alias`](./docs/rules/no-this-alias.md) | Disallow aliasing `this` | :white_check_mark: | | | +| [`@typescript-eslint/no-type-alias`](./docs/rules/no-type-alias.md) | Disallow the use of type aliases | | | | +| [`@typescript-eslint/no-unnecessary-boolean-literal-compare`](./docs/rules/no-unnecessary-boolean-literal-compare.md) | Flags unnecessary equality comparisons against boolean literals | | :wrench: | :thought_balloon: | +| [`@typescript-eslint/no-unnecessary-condition`](./docs/rules/no-unnecessary-condition.md) | Prevents conditionals where the type is always truthy or always falsy | | :wrench: | :thought_balloon: | +| [`@typescript-eslint/no-unnecessary-qualifier`](./docs/rules/no-unnecessary-qualifier.md) | Warns when a namespace qualifier is unnecessary | | :wrench: | :thought_balloon: | +| [`@typescript-eslint/no-unnecessary-type-arguments`](./docs/rules/no-unnecessary-type-arguments.md) | Enforces that type arguments will not be used if not required | | :wrench: | :thought_balloon: | +| [`@typescript-eslint/no-unnecessary-type-assertion`](./docs/rules/no-unnecessary-type-assertion.md) | Warns if a type assertion does not change the type of an expression | :white_check_mark: | :wrench: | :thought_balloon: | +| [`@typescript-eslint/no-unnecessary-type-constraint`](./docs/rules/no-unnecessary-type-constraint.md) | Disallows unnecessary constraints on generic types | | :wrench: | | +| [`@typescript-eslint/no-unsafe-argument`](./docs/rules/no-unsafe-argument.md) | Disallows calling an function with an any type value | | | :thought_balloon: | +| [`@typescript-eslint/no-unsafe-assignment`](./docs/rules/no-unsafe-assignment.md) | Disallows assigning any to variables and properties | :white_check_mark: | | :thought_balloon: | +| [`@typescript-eslint/no-unsafe-call`](./docs/rules/no-unsafe-call.md) | Disallows calling an any type value | :white_check_mark: | | :thought_balloon: | +| [`@typescript-eslint/no-unsafe-member-access`](./docs/rules/no-unsafe-member-access.md) | Disallows member access on any typed variables | :white_check_mark: | | :thought_balloon: | +| [`@typescript-eslint/no-unsafe-return`](./docs/rules/no-unsafe-return.md) | Disallows returning any from a function | :white_check_mark: | | :thought_balloon: | +| [`@typescript-eslint/no-var-requires`](./docs/rules/no-var-requires.md) | Disallows the use of require statements except in import statements | :white_check_mark: | | | +| [`@typescript-eslint/non-nullable-type-assertion-style`](./docs/rules/non-nullable-type-assertion-style.md) | Prefers a non-null assertion over explicit type cast when possible | | :wrench: | :thought_balloon: | +| [`@typescript-eslint/prefer-as-const`](./docs/rules/prefer-as-const.md) | Prefer usage of `as const` over literal type | :white_check_mark: | :wrench: | | +| [`@typescript-eslint/prefer-enum-initializers`](./docs/rules/prefer-enum-initializers.md) | Prefer initializing each enums member value | | | | +| [`@typescript-eslint/prefer-for-of`](./docs/rules/prefer-for-of.md) | Prefer a ‘for-of’ loop over a standard ‘for’ loop if the index is only used to access the array being iterated | | | | +| [`@typescript-eslint/prefer-function-type`](./docs/rules/prefer-function-type.md) | Use function types instead of interfaces with call signatures | | :wrench: | | +| [`@typescript-eslint/prefer-includes`](./docs/rules/prefer-includes.md) | Enforce `includes` method over `indexOf` method | | :wrench: | :thought_balloon: | +| [`@typescript-eslint/prefer-literal-enum-member`](./docs/rules/prefer-literal-enum-member.md) | Require that all enum members be literal values to prevent unintended enum member name shadow issues | | | | +| [`@typescript-eslint/prefer-namespace-keyword`](./docs/rules/prefer-namespace-keyword.md) | Require the use of the `namespace` keyword instead of the `module` keyword to declare custom TypeScript modules | :white_check_mark: | :wrench: | | +| [`@typescript-eslint/prefer-nullish-coalescing`](./docs/rules/prefer-nullish-coalescing.md) | Enforce the usage of the nullish coalescing operator instead of logical chaining | | | :thought_balloon: | +| [`@typescript-eslint/prefer-optional-chain`](./docs/rules/prefer-optional-chain.md) | Prefer using concise optional chain expressions instead of chained logical ands | | | | +| [`@typescript-eslint/prefer-readonly`](./docs/rules/prefer-readonly.md) | Requires that private members are marked as `readonly` if they're never modified outside of the constructor | | :wrench: | :thought_balloon: | +| [`@typescript-eslint/prefer-readonly-parameter-types`](./docs/rules/prefer-readonly-parameter-types.md) | Requires that function parameters are typed as readonly to prevent accidental mutation of inputs | | | :thought_balloon: | +| [`@typescript-eslint/prefer-reduce-type-parameter`](./docs/rules/prefer-reduce-type-parameter.md) | Prefer using type parameter when calling `Array#reduce` instead of casting | | :wrench: | :thought_balloon: | +| [`@typescript-eslint/prefer-regexp-exec`](./docs/rules/prefer-regexp-exec.md) | Enforce that `RegExp#exec` is used instead of `String#match` if no global flag is provided | :white_check_mark: | :wrench: | :thought_balloon: | +| [`@typescript-eslint/prefer-string-starts-ends-with`](./docs/rules/prefer-string-starts-ends-with.md) | Enforce the use of `String#startsWith` and `String#endsWith` instead of other equivalent methods of checking substrings | | :wrench: | :thought_balloon: | +| [`@typescript-eslint/prefer-ts-expect-error`](./docs/rules/prefer-ts-expect-error.md) | Recommends using `@ts-expect-error` over `@ts-ignore` | | :wrench: | | +| [`@typescript-eslint/promise-function-async`](./docs/rules/promise-function-async.md) | Requires any function or method that returns a Promise to be marked async | | :wrench: | :thought_balloon: | +| [`@typescript-eslint/require-array-sort-compare`](./docs/rules/require-array-sort-compare.md) | Requires `Array#sort` calls to always provide a `compareFunction` | | | :thought_balloon: | +| [`@typescript-eslint/restrict-plus-operands`](./docs/rules/restrict-plus-operands.md) | When adding two variables, operands must both be of type number or of type string | :white_check_mark: | | :thought_balloon: | +| [`@typescript-eslint/restrict-template-expressions`](./docs/rules/restrict-template-expressions.md) | Enforce template literal expressions to be of string type | :white_check_mark: | | :thought_balloon: | +| [`@typescript-eslint/sort-type-union-intersection-members`](./docs/rules/sort-type-union-intersection-members.md) | Enforces that members of a type union/intersection are sorted alphabetically | | :wrench: | | +| [`@typescript-eslint/strict-boolean-expressions`](./docs/rules/strict-boolean-expressions.md) | Restricts the types allowed in boolean expressions | | :wrench: | :thought_balloon: | +| [`@typescript-eslint/switch-exhaustiveness-check`](./docs/rules/switch-exhaustiveness-check.md) | Exhaustiveness checking in switch with union type | | | :thought_balloon: | +| [`@typescript-eslint/triple-slash-reference`](./docs/rules/triple-slash-reference.md) | Sets preference level for triple slash directives versus ES6-style import declarations | :white_check_mark: | | | +| [`@typescript-eslint/type-annotation-spacing`](./docs/rules/type-annotation-spacing.md) | Require consistent spacing around type annotations | | :wrench: | | +| [`@typescript-eslint/typedef`](./docs/rules/typedef.md) | Requires type annotations to exist | | | | +| [`@typescript-eslint/unbound-method`](./docs/rules/unbound-method.md) | Enforces unbound methods are called with their expected scope | :white_check_mark: | | :thought_balloon: | +| [`@typescript-eslint/unified-signatures`](./docs/rules/unified-signatures.md) | Warns for any two overloads that could be unified into one by using a union or an optional/rest parameter | | | | diff --git a/packages/eslint-plugin/docs/rules/no-non-null-asserted-nullish-coalescing.md b/packages/eslint-plugin/docs/rules/no-non-null-asserted-nullish-coalescing.md new file mode 100644 index 000000000000..116aee4fd8ec --- /dev/null +++ b/packages/eslint-plugin/docs/rules/no-non-null-asserted-nullish-coalescing.md @@ -0,0 +1,38 @@ +# Disallows using a non-null assertion in the left operand of the nullish coalescing operator (`no-non-null-asserted-nullish-coalescing`) + +## Rule Details + +The nullish coalescing operator is designed to provide a default value when dealing with `null` or `undefined`. +Using non-null assertions in the left operand of the nullish coalescing operator is redundant. + +Examples of **incorrect** code for this rule: + +```ts +/* eslint @typescript-eslint/no-non-null-asserted-nullish-coalescing: "error" */ + +foo! ?? bar; +foo.bazz! ?? bar; +foo!.bazz! ?? bar; +foo()! ?? bar; +``` + +Examples of **correct** code for this rule: + +```ts +/* eslint @typescript-eslint/no-non-null-asserted-nullish-coalescing: "error" */ + +foo ?? bar; +foo ?? bar!; +foo!.bazz ?? bar; +foo!.bazz ?? bar!; +foo() ?? bar; +``` + +## When Not To Use It + +If you are not using TypeScript 3.7 (or greater), then you will not need to use this rule, as the operator is not supported. + +## Further Reading + +- [TypeScript 3.7 Release Notes](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-7.html) +- [Nullish Coalescing Proposal](https://github.com/tc39/proposal-nullish-coalescing) diff --git a/packages/eslint-plugin/src/configs/all.ts b/packages/eslint-plugin/src/configs/all.ts index b21d14efc9f0..fc146046f4c1 100644 --- a/packages/eslint-plugin/src/configs/all.ts +++ b/packages/eslint-plugin/src/configs/all.ts @@ -81,6 +81,7 @@ export = { '@typescript-eslint/no-misused-new': 'error', '@typescript-eslint/no-misused-promises': 'error', '@typescript-eslint/no-namespace': 'error', + '@typescript-eslint/no-non-null-asserted-nullish-coalescing': 'error', '@typescript-eslint/no-non-null-asserted-optional-chain': 'error', '@typescript-eslint/no-non-null-assertion': 'error', '@typescript-eslint/no-parameter-properties': 'error', diff --git a/packages/eslint-plugin/src/rules/index.ts b/packages/eslint-plugin/src/rules/index.ts index be78db26f806..cba927773787 100644 --- a/packages/eslint-plugin/src/rules/index.ts +++ b/packages/eslint-plugin/src/rules/index.ts @@ -53,6 +53,7 @@ import noMagicNumbers from './no-magic-numbers'; import noMisusedNew from './no-misused-new'; import noMisusedPromises from './no-misused-promises'; import noNamespace from './no-namespace'; +import noNonNullAssertedNullishCoalescing from './no-non-null-asserted-nullish-coalescing'; import noNonNullAssertedOptionalChain from './no-non-null-asserted-optional-chain'; import noNonNullAssertion from './no-non-null-assertion'; import noParameterProperties from './no-parameter-properties'; @@ -171,6 +172,7 @@ export default { 'no-misused-new': noMisusedNew, 'no-misused-promises': noMisusedPromises, 'no-namespace': noNamespace, + 'no-non-null-asserted-nullish-coalescing': noNonNullAssertedNullishCoalescing, 'no-non-null-asserted-optional-chain': noNonNullAssertedOptionalChain, 'no-non-null-assertion': noNonNullAssertion, 'no-parameter-properties': noParameterProperties, diff --git a/packages/eslint-plugin/src/rules/no-non-null-asserted-nullish-coalescing.ts b/packages/eslint-plugin/src/rules/no-non-null-asserted-nullish-coalescing.ts new file mode 100644 index 000000000000..00caf9e5882a --- /dev/null +++ b/packages/eslint-plugin/src/rules/no-non-null-asserted-nullish-coalescing.ts @@ -0,0 +1,44 @@ +import { TSESTree, TSESLint } from '@typescript-eslint/experimental-utils'; +import * as util from '../util'; + +export default util.createRule({ + name: 'no-non-null-asserted-nullish-coalescing', + meta: { + type: 'problem', + docs: { + description: + 'Disallows using a non-null assertion in the left operand of the nullish coalescing operator', + category: 'Possible Errors', + recommended: false, + suggestion: true, + }, + messages: { + noNonNullAssertedNullishCoalescing: + 'The nullish coalescing operator is designed to handle undefined and null - using a non-null assertion is not needed.', + suggestRemovingNonNull: 'You should remove the non-null assertion.', + }, + schema: [], + }, + defaultOptions: [], + create(context) { + return { + 'LogicalExpression[operator = "??"] > TSNonNullExpression.left'( + node: TSESTree.TSNonNullExpression, + ): void { + context.report({ + node, + messageId: 'noNonNullAssertedNullishCoalescing', + // use a suggestion instead of a fixer, because this can obviously break type checks + suggest: [ + { + messageId: 'suggestRemovingNonNull', + fix(fixer): TSESLint.RuleFix { + return fixer.removeRange([node.range[1] - 1, node.range[1]]); + }, + }, + ], + }); + }, + }; + }, +}); diff --git a/packages/eslint-plugin/tests/rules/no-non-null-asserted-nullish-coalescing.test.ts b/packages/eslint-plugin/tests/rules/no-non-null-asserted-nullish-coalescing.test.ts new file mode 100644 index 000000000000..5521e9f8ea03 --- /dev/null +++ b/packages/eslint-plugin/tests/rules/no-non-null-asserted-nullish-coalescing.test.ts @@ -0,0 +1,134 @@ +import rule from '../../src/rules/no-non-null-asserted-nullish-coalescing'; +import { RuleTester } from '../RuleTester'; + +const ruleTester = new RuleTester({ + parser: '@typescript-eslint/parser', +}); + +ruleTester.run('no-non-null-asserted-nullish-coalescing', rule, { + valid: [ + 'foo ?? bar;', + 'foo ?? bar!;', + 'foo.bazz ?? bar;', + 'foo.bazz ?? bar!;', + 'foo!.bazz ?? bar;', + 'foo!.bazz ?? bar!;', + 'foo() ?? bar;', + 'foo() ?? bar!;', + '(foo ?? bar)!;', + ], + invalid: [ + { + code: 'foo! ?? bar;', + errors: [ + { + messageId: 'noNonNullAssertedNullishCoalescing', + suggestions: [ + { + messageId: 'suggestRemovingNonNull', + output: 'foo ?? bar;', + }, + ], + }, + ], + }, + { + code: 'foo! ?? bar!;', + errors: [ + { + messageId: 'noNonNullAssertedNullishCoalescing', + suggestions: [ + { + messageId: 'suggestRemovingNonNull', + output: 'foo ?? bar!;', + }, + ], + }, + ], + }, + { + code: 'foo.bazz! ?? bar;', + errors: [ + { + messageId: 'noNonNullAssertedNullishCoalescing', + suggestions: [ + { + messageId: 'suggestRemovingNonNull', + output: 'foo.bazz ?? bar;', + }, + ], + }, + ], + }, + { + code: 'foo.bazz! ?? bar!;', + errors: [ + { + messageId: 'noNonNullAssertedNullishCoalescing', + suggestions: [ + { + messageId: 'suggestRemovingNonNull', + output: 'foo.bazz ?? bar!;', + }, + ], + }, + ], + }, + { + code: 'foo!.bazz! ?? bar;', + errors: [ + { + messageId: 'noNonNullAssertedNullishCoalescing', + suggestions: [ + { + messageId: 'suggestRemovingNonNull', + output: 'foo!.bazz ?? bar;', + }, + ], + }, + ], + }, + { + code: 'foo!.bazz! ?? bar!;', + errors: [ + { + messageId: 'noNonNullAssertedNullishCoalescing', + suggestions: [ + { + messageId: 'suggestRemovingNonNull', + output: 'foo!.bazz ?? bar!;', + }, + ], + }, + ], + }, + { + code: 'foo()! ?? bar;', + errors: [ + { + messageId: 'noNonNullAssertedNullishCoalescing', + suggestions: [ + { + messageId: 'suggestRemovingNonNull', + output: 'foo() ?? bar;', + }, + ], + }, + ], + }, + { + code: 'foo()! ?? bar!;', + errors: [ + { + messageId: 'noNonNullAssertedNullishCoalescing', + suggestions: [ + { + messageId: 'suggestRemovingNonNull', + output: 'foo() ?? bar!;', + }, + ], + }, + ], + }, + ], +}); From 9379caa1678c6a3508abf6bdb3124de3340beb87 Mon Sep 17 00:00:00 2001 From: sonallux <13821543+sonallux@users.noreply.github.com> Date: Sun, 16 May 2021 17:08:10 +0200 Subject: [PATCH 2/4] feat: handle use-before-assigned case --- ...no-non-null-asserted-nullish-coalescing.md | 11 ++ ...no-non-null-asserted-nullish-coalescing.ts | 52 +++++++- ...n-null-asserted-nullish-coalescing.test.ts | 118 ++++++++++++++++++ 3 files changed, 180 insertions(+), 1 deletion(-) diff --git a/packages/eslint-plugin/docs/rules/no-non-null-asserted-nullish-coalescing.md b/packages/eslint-plugin/docs/rules/no-non-null-asserted-nullish-coalescing.md index 116aee4fd8ec..9c379c6fa7d8 100644 --- a/packages/eslint-plugin/docs/rules/no-non-null-asserted-nullish-coalescing.md +++ b/packages/eslint-plugin/docs/rules/no-non-null-asserted-nullish-coalescing.md @@ -14,6 +14,13 @@ foo! ?? bar; foo.bazz! ?? bar; foo!.bazz! ?? bar; foo()! ?? bar; + +let x!: string; +x! ?? ''; + +let x: string; +x = foo(); +x! ?? ''; ``` Examples of **correct** code for this rule: @@ -26,6 +33,10 @@ foo ?? bar!; foo!.bazz ?? bar; foo!.bazz ?? bar!; foo() ?? bar; + +// This is considered correct code because because there's no way for the user to satisfy it. +let x: string; +x! ?? ''; ``` ## When Not To Use It diff --git a/packages/eslint-plugin/src/rules/no-non-null-asserted-nullish-coalescing.ts b/packages/eslint-plugin/src/rules/no-non-null-asserted-nullish-coalescing.ts index 00caf9e5882a..f7420306cd26 100644 --- a/packages/eslint-plugin/src/rules/no-non-null-asserted-nullish-coalescing.ts +++ b/packages/eslint-plugin/src/rules/no-non-null-asserted-nullish-coalescing.ts @@ -1,6 +1,35 @@ import { TSESTree, TSESLint } from '@typescript-eslint/experimental-utils'; +import { + Definition, + DefinitionType, + Variable, +} from '@typescript-eslint/scope-manager'; import * as util from '../util'; +function hasAssignmentBeforeNode( + variable: Variable, + node: TSESTree.Node, +): boolean { + return ( + variable.references.some( + ref => ref.isWrite() && ref.identifier.range[1] < node.range[1], + ) || + variable.defs.some( + def => + isDefinitionWithAssignment(def) && def.node.range[1] < node.range[1], + ) + ); +} + +function isDefinitionWithAssignment(definition: Definition): boolean { + if (definition.type !== DefinitionType.Variable) { + return false; + } + + const variableDeclarator = definition.node; + return variableDeclarator.definite ?? variableDeclarator.init !== null; +} + export default util.createRule({ name: 'no-non-null-asserted-nullish-coalescing', meta: { @@ -25,10 +54,31 @@ export default util.createRule({ 'LogicalExpression[operator = "??"] > TSNonNullExpression.left'( node: TSESTree.TSNonNullExpression, ): void { + if (node.expression.type === TSESTree.AST_NODE_TYPES.Identifier) { + const scope = context.getScope(); + const identifier = node.expression; + const variable = scope.set.get(identifier.name); + if (variable && !hasAssignmentBeforeNode(variable, node)) { + return; + } + } + context.report({ node, messageId: 'noNonNullAssertedNullishCoalescing', - // use a suggestion instead of a fixer, because this can obviously break type checks + /* + Use a suggestion instead of a fixer, because this can break type checks. + The resulting type of the nullish coalesce is only influenced by the right operand if the left operand can be `null` or `undefined`. + After removing the non-null assertion the type of the left operand might contain `null` or `undefined` and then the type of the right operand + might change the resulting type of the nullish coalesce. + See the following example: + + function test(x?: string): string { + const bar = x! ?? false; // type analysis reports `bar` has type `string` + // x ?? false; // type analysis reports `bar` has type `string | false` + return bar; + } + */ suggest: [ { messageId: 'suggestRemovingNonNull', diff --git a/packages/eslint-plugin/tests/rules/no-non-null-asserted-nullish-coalescing.test.ts b/packages/eslint-plugin/tests/rules/no-non-null-asserted-nullish-coalescing.test.ts index 5521e9f8ea03..779b31638775 100644 --- a/packages/eslint-plugin/tests/rules/no-non-null-asserted-nullish-coalescing.test.ts +++ b/packages/eslint-plugin/tests/rules/no-non-null-asserted-nullish-coalescing.test.ts @@ -16,6 +16,38 @@ ruleTester.run('no-non-null-asserted-nullish-coalescing', rule, { 'foo() ?? bar;', 'foo() ?? bar!;', '(foo ?? bar)!;', + ` + let x: string; + x! ?? ''; + `, + ` + let x: string; + x ?? ''; + `, + ` + let x!: string; + x ?? ''; + `, + ` + let x: string; + foo(x); + x! ?? ''; + `, + ` + let x: string; + x! ?? ''; + x = foo(); + `, + ` + let x: string; + foo(x); + x! ?? ''; + x = foo(); + `, + ` + let x = foo(); + x ?? ''; + `, ], invalid: [ { @@ -130,5 +162,91 @@ ruleTester.run('no-non-null-asserted-nullish-coalescing', rule, { }, ], }, + { + code: ` +let x!: string; +x! ?? ''; + `.trimRight(), + errors: [ + { + messageId: 'noNonNullAssertedNullishCoalescing', + suggestions: [ + { + messageId: 'suggestRemovingNonNull', + output: ` +let x!: string; +x ?? ''; + `.trimRight(), + }, + ], + }, + ], + }, + { + code: ` +let x: string; +x = foo(); +x! ?? ''; + `.trimRight(), + errors: [ + { + messageId: 'noNonNullAssertedNullishCoalescing', + suggestions: [ + { + messageId: 'suggestRemovingNonNull', + output: ` +let x: string; +x = foo(); +x ?? ''; + `.trimRight(), + }, + ], + }, + ], + }, + { + code: ` +let x: string; +x = foo(); +x! ?? ''; +x = foo(); + `.trimRight(), + errors: [ + { + messageId: 'noNonNullAssertedNullishCoalescing', + suggestions: [ + { + messageId: 'suggestRemovingNonNull', + output: ` +let x: string; +x = foo(); +x ?? ''; +x = foo(); + `.trimRight(), + }, + ], + }, + ], + }, + { + code: ` +let x = foo(); +x! ?? ''; + `.trimRight(), + errors: [ + { + messageId: 'noNonNullAssertedNullishCoalescing', + suggestions: [ + { + messageId: 'suggestRemovingNonNull', + output: ` +let x = foo(); +x ?? ''; + `.trimRight(), + }, + ], + }, + ], + }, ], }); From 4ad208d7fd46c4b6b08ca6f1d944714733592c4f Mon Sep 17 00:00:00 2001 From: sonallux <13821543+sonallux@users.noreply.github.com> Date: Tue, 3 Aug 2021 21:09:13 +0200 Subject: [PATCH 3/4] fix: address feedback from review --- ...no-non-null-asserted-nullish-coalescing.md | 2 +- ...no-non-null-asserted-nullish-coalescing.ts | 34 +++++--- ...n-null-asserted-nullish-coalescing.test.ts | 82 ++++++++++++++++++- 3 files changed, 106 insertions(+), 12 deletions(-) diff --git a/packages/eslint-plugin/docs/rules/no-non-null-asserted-nullish-coalescing.md b/packages/eslint-plugin/docs/rules/no-non-null-asserted-nullish-coalescing.md index 9c379c6fa7d8..799100f29939 100644 --- a/packages/eslint-plugin/docs/rules/no-non-null-asserted-nullish-coalescing.md +++ b/packages/eslint-plugin/docs/rules/no-non-null-asserted-nullish-coalescing.md @@ -41,7 +41,7 @@ x! ?? ''; ## When Not To Use It -If you are not using TypeScript 3.7 (or greater), then you will not need to use this rule, as the operator is not supported. +If you are not using TypeScript 3.7 (or greater), then you will not need to use this rule, as the nullish coalescing operator is not supported. ## Further Reading diff --git a/packages/eslint-plugin/src/rules/no-non-null-asserted-nullish-coalescing.ts b/packages/eslint-plugin/src/rules/no-non-null-asserted-nullish-coalescing.ts index f7420306cd26..b7619f1a82b5 100644 --- a/packages/eslint-plugin/src/rules/no-non-null-asserted-nullish-coalescing.ts +++ b/packages/eslint-plugin/src/rules/no-non-null-asserted-nullish-coalescing.ts @@ -1,13 +1,13 @@ -import { TSESTree, TSESLint } from '@typescript-eslint/experimental-utils'; import { - Definition, - DefinitionType, - Variable, -} from '@typescript-eslint/scope-manager'; + ASTUtils, + TSESTree, + TSESLint, +} from '@typescript-eslint/experimental-utils'; +import { Definition, DefinitionType } from '@typescript-eslint/scope-manager'; import * as util from '../util'; function hasAssignmentBeforeNode( - variable: Variable, + variable: TSESLint.Scope.Variable, node: TSESTree.Node, ): boolean { return ( @@ -27,7 +27,9 @@ function isDefinitionWithAssignment(definition: Definition): boolean { } const variableDeclarator = definition.node; - return variableDeclarator.definite ?? variableDeclarator.init !== null; + return ( + variableDeclarator.definite === true || variableDeclarator.init !== null + ); } export default util.createRule({ @@ -44,7 +46,7 @@ export default util.createRule({ messages: { noNonNullAssertedNullishCoalescing: 'The nullish coalescing operator is designed to handle undefined and null - using a non-null assertion is not needed.', - suggestRemovingNonNull: 'You should remove the non-null assertion.', + suggestRemovingNonNull: 'Remove the non-null assertion.', }, schema: [], }, @@ -57,12 +59,14 @@ export default util.createRule({ if (node.expression.type === TSESTree.AST_NODE_TYPES.Identifier) { const scope = context.getScope(); const identifier = node.expression; - const variable = scope.set.get(identifier.name); + const variable = ASTUtils.findVariable(scope, identifier.name); if (variable && !hasAssignmentBeforeNode(variable, node)) { return; } } + const sourceCode = context.getSourceCode(); + context.report({ node, messageId: 'noNonNullAssertedNullishCoalescing', @@ -83,7 +87,17 @@ export default util.createRule({ { messageId: 'suggestRemovingNonNull', fix(fixer): TSESLint.RuleFix { - return fixer.removeRange([node.range[1] - 1, node.range[1]]); + const exclamationMark = util.nullThrows( + sourceCode.getLastToken( + node, + ASTUtils.isNonNullAssertionPunctuator, + ), + util.NullThrowsReasons.MissingToken( + '!', + 'Non-null Assertion', + ), + ); + return fixer.remove(exclamationMark); }, }, ], diff --git a/packages/eslint-plugin/tests/rules/no-non-null-asserted-nullish-coalescing.test.ts b/packages/eslint-plugin/tests/rules/no-non-null-asserted-nullish-coalescing.test.ts index 779b31638775..3b47a3c2bf00 100644 --- a/packages/eslint-plugin/tests/rules/no-non-null-asserted-nullish-coalescing.test.ts +++ b/packages/eslint-plugin/tests/rules/no-non-null-asserted-nullish-coalescing.test.ts @@ -1,5 +1,5 @@ import rule from '../../src/rules/no-non-null-asserted-nullish-coalescing'; -import { RuleTester } from '../RuleTester'; +import { RuleTester, noFormat } from '../RuleTester'; const ruleTester = new RuleTester({ parser: '@typescript-eslint/parser', @@ -48,6 +48,18 @@ ruleTester.run('no-non-null-asserted-nullish-coalescing', rule, { let x = foo(); x ?? ''; `, + ` + function foo() { + let x: string; + return x ?? ''; + } + `, + ` + let x: string; + function foo() { + return x ?? ''; + } + `, ], invalid: [ { @@ -248,5 +260,73 @@ x ?? ''; }, ], }, + { + code: ` +function foo() { + let x!: string; + return x! ?? ''; +} + `.trimRight(), + errors: [ + { + messageId: 'noNonNullAssertedNullishCoalescing', + suggestions: [ + { + messageId: 'suggestRemovingNonNull', + output: ` +function foo() { + let x!: string; + return x ?? ''; +} + `.trimRight(), + }, + ], + }, + ], + }, + { + code: ` +let x!: string; +function foo() { + return x! ?? ''; +} + `.trimRight(), + errors: [ + { + messageId: 'noNonNullAssertedNullishCoalescing', + suggestions: [ + { + messageId: 'suggestRemovingNonNull', + output: ` +let x!: string; +function foo() { + return x ?? ''; +} + `.trimRight(), + }, + ], + }, + ], + }, + { + code: noFormat` +let x = foo(); +x ! ?? ''; + `.trimRight(), + errors: [ + { + messageId: 'noNonNullAssertedNullishCoalescing', + suggestions: [ + { + messageId: 'suggestRemovingNonNull', + output: noFormat` +let x = foo(); +x ?? ''; + `.trimRight(), + }, + ], + }, + ], + }, ], }); From db9d5b9a75ddcfffd3b2cb99ac8cbb76437e298a Mon Sep 17 00:00:00 2001 From: Brad Zacher Date: Mon, 20 Sep 2021 12:42:20 -0700 Subject: [PATCH 4/4] fix formatting --- .../src/rules/no-poorly-typed-ts-props.ts | 5 +- .../src/rules/plugin-test-formatting.ts | 6 +- .../eslint-plugin/src/rules/ban-ts-comment.ts | 6 +- .../src/rules/ban-tslint-comment.ts | 3 +- .../eslint-plugin/src/rules/brace-style.ts | 21 +- .../src/rules/consistent-type-imports.ts | 34 +- .../eslint-plugin/src/rules/dot-notation.ts | 4 +- .../rules/explicit-member-accessibility.ts | 5 +- .../src/rules/indent-new-do-not-use/index.ts | 15 +- packages/eslint-plugin/src/rules/indent.ts | 7 +- .../src/rules/method-signature-style.ts | 13 +- .../src/rules/no-extra-non-null-assertion.ts | 6 +- .../src/rules/no-inferrable-types.ts | 14 +- .../src/rules/no-magic-numbers.ts | 5 +- .../eslint-plugin/src/rules/no-redeclare.ts | 9 +- .../src/rules/no-unnecessary-condition.ts | 6 +- .../src/rules/no-unnecessary-qualifier.ts | 12 +- .../src/rules/no-unsafe-argument.ts | 5 +- .../src/rules/no-unsafe-member-access.ts | 3 +- .../src/rules/no-use-before-define.ts | 3 +- .../src/rules/object-curly-spacing.ts | 5 +- .../src/rules/prefer-includes.ts | 9 +- .../src/rules/prefer-optional-chain.ts | 10 +- .../src/rules/prefer-readonly.ts | 5 +- packages/eslint-plugin/src/rules/semi.ts | 3 +- .../src/rules/triple-slash-reference.ts | 3 +- .../src/util/collectUnusedVariables.ts | 6 +- packages/eslint-plugin/src/util/index.ts | 13 +- packages/eslint-plugin/src/util/misc.ts | 4 +- packages/eslint-plugin/tests/docs.test.ts | 7 +- .../tests/rules/ban-ts-comment.test.ts | 9 +- .../tests/rules/brace-style.test.ts | 15 +- .../tests/rules/indent/indent-eslint.test.ts | 3 +- .../tests/rules/member-ordering.test.ts | 516 +++--- .../tests/rules/no-explicit-any.test.ts | 1411 +++++++++-------- .../tests/rules/no-inferrable-types.test.ts | 50 +- .../tests/rules/no-invalid-void-type.test.ts | 6 +- .../tests/rules/no-loss-of-precision.test.ts | 3 +- .../tests/rules/no-type-alias.test.ts | 9 +- .../rules/no-unused-vars-experimental.test.ts | 2 +- .../tests/rules/object-curly-spacing.test.ts | 6 +- .../padding-line-between-statements.test.ts | 195 +-- .../tests/rules/prefer-optional-chain.test.ts | 18 +- .../prefer-string-starts-ends-with.test.ts | 4 +- .../eslint-plugin/tests/rules/quotes.test.ts | 9 +- .../tests/util/isUnsafeAssignment.test.ts | 4 +- .../eslint-plugin/tools/generate-configs.ts | 6 +- .../src/ast-utils/eslint-utils/predicates.ts | 81 +- .../src/ast-utils/predicates.ts | 9 +- .../src/eslint-utils/RuleCreator.ts | 2 +- .../eslint-utils/batchedSingleLineTests.ts | 4 +- .../src/eslint-utils/getParserServices.ts | 2 +- .../src/ts-eslint-scope/Definition.ts | 17 +- .../src/ts-eslint-scope/Scope.ts | 5 +- .../src/ts-eslint/CLIEngine.ts | 2 +- .../experimental-utils/src/ts-eslint/Rule.ts | 18 +- .../src/ts-eslint/RuleTester.ts | 4 +- .../experimental-utils/src/ts-eslint/Scope.ts | 6 +- .../src/ts-eslint/SourceCode.ts | 4 +- .../src/definition/DefinitionBase.ts | 2 +- packages/scope-manager/src/scope/ScopeBase.ts | 4 +- .../eslint-scope/map-ecma-version.test.ts | 2 +- .../tests/util/getSpecificNode.ts | 6 +- packages/typescript-estree/src/convert.ts | 86 +- .../src/create-program/createWatchProgram.ts | 5 +- .../typescript-estree/src/parser-options.ts | 2 +- .../typescript-estree/tests/lib/parse.test.ts | 65 +- .../tests/lib/semanticInfo-singleRun.test.ts | 8 +- .../tests/lib/semanticInfo.test.ts | 47 +- 69 files changed, 1410 insertions(+), 1484 deletions(-) diff --git a/packages/eslint-plugin-internal/src/rules/no-poorly-typed-ts-props.ts b/packages/eslint-plugin-internal/src/rules/no-poorly-typed-ts-props.ts index 1fa447080ba7..d5554ec57d54 100644 --- a/packages/eslint-plugin-internal/src/rules/no-poorly-typed-ts-props.ts +++ b/packages/eslint-plugin-internal/src/rules/no-poorly-typed-ts-props.ts @@ -53,9 +53,8 @@ export default createRule({ }, defaultOptions: [], create(context) { - const { program, esTreeNodeToTSNodeMap } = ESLintUtils.getParserServices( - context, - ); + const { program, esTreeNodeToTSNodeMap } = + ESLintUtils.getParserServices(context); const checker = program.getTypeChecker(); return { diff --git a/packages/eslint-plugin-internal/src/rules/plugin-test-formatting.ts b/packages/eslint-plugin-internal/src/rules/plugin-test-formatting.ts index 64fefc08f8ef..ed03e0fe1caf 100644 --- a/packages/eslint-plugin-internal/src/rules/plugin-test-formatting.ts +++ b/packages/eslint-plugin-internal/src/rules/plugin-test-formatting.ts @@ -490,7 +490,8 @@ export default createRule({ return { // valid - 'CallExpression > ObjectExpression > Property[key.name = "valid"] > ArrayExpression': checkValidTest, + 'CallExpression > ObjectExpression > Property[key.name = "valid"] > ArrayExpression': + checkValidTest, // invalid - errors [invalidTestsSelectorPath.join(' > ')]: checkInvalidTest, // invalid - suggestions @@ -504,7 +505,8 @@ export default createRule({ AST_NODE_TYPES.ObjectExpression, ].join(' > ')]: checkInvalidTest, // special case for our batchedSingleLineTests utility - 'CallExpression[callee.name = "batchedSingleLineTests"] > ObjectExpression': checkInvalidTest, + 'CallExpression[callee.name = "batchedSingleLineTests"] > ObjectExpression': + checkInvalidTest, }; }, }); diff --git a/packages/eslint-plugin/src/rules/ban-ts-comment.ts b/packages/eslint-plugin/src/rules/ban-ts-comment.ts index 7c2f237cd4cf..4bf17c25d95b 100644 --- a/packages/eslint-plugin/src/rules/ban-ts-comment.ts +++ b/packages/eslint-plugin/src/rules/ban-ts-comment.ts @@ -102,8 +102,10 @@ export default util.createRule<[Options], MessageIds>({ The regex used are taken from the ones used in the official TypeScript repo - https://github.com/microsoft/TypeScript/blob/master/src/compiler/scanner.ts#L281-L289 */ - const commentDirectiveRegExSingleLine = /^\/*\s*@ts-(expect-error|ignore|check|nocheck)(.*)/; - const commentDirectiveRegExMultiLine = /^\s*(?:\/|\*)*\s*@ts-(expect-error|ignore|check|nocheck)(.*)/; + const commentDirectiveRegExSingleLine = + /^\/*\s*@ts-(expect-error|ignore|check|nocheck)(.*)/; + const commentDirectiveRegExMultiLine = + /^\s*(?:\/|\*)*\s*@ts-(expect-error|ignore|check|nocheck)(.*)/; const sourceCode = context.getSourceCode(); return { diff --git a/packages/eslint-plugin/src/rules/ban-tslint-comment.ts b/packages/eslint-plugin/src/rules/ban-tslint-comment.ts index 4521fcb13c36..37dfefd380e5 100644 --- a/packages/eslint-plugin/src/rules/ban-tslint-comment.ts +++ b/packages/eslint-plugin/src/rules/ban-tslint-comment.ts @@ -3,7 +3,8 @@ import * as util from '../util'; // tslint regex // https://github.com/palantir/tslint/blob/95d9d958833fd9dc0002d18cbe34db20d0fbf437/src/enableDisableRules.ts#L32 -const ENABLE_DISABLE_REGEX = /^\s*tslint:(enable|disable)(?:-(line|next-line))?(:|\s|$)/; +const ENABLE_DISABLE_REGEX = + /^\s*tslint:(enable|disable)(?:-(line|next-line))?(:|\s|$)/; const toText = ( text: string, diff --git a/packages/eslint-plugin/src/rules/brace-style.ts b/packages/eslint-plugin/src/rules/brace-style.ts index 7107bdf4d1ba..4d981763cf48 100644 --- a/packages/eslint-plugin/src/rules/brace-style.ts +++ b/packages/eslint-plugin/src/rules/brace-style.ts @@ -26,10 +26,8 @@ export default createRule({ }, defaultOptions: ['1tbs'], create(context) { - const [ - style, - { allowSingleLine } = { allowSingleLine: false }, - ] = context.options; + const [style, { allowSingleLine } = { allowSingleLine: false }] = + context.options; const isAllmanStyle = style === 'allman'; const sourceCode = context.getSourceCode(); @@ -49,15 +47,12 @@ export default createRule({ return; } - const tokenBeforeOpeningCurly = sourceCode.getTokenBefore( - openingCurlyToken, - )!; - const tokenBeforeClosingCurly = sourceCode.getTokenBefore( - closingCurlyToken, - )!; - const tokenAfterOpeningCurly = sourceCode.getTokenAfter( - openingCurlyToken, - )!; + const tokenBeforeOpeningCurly = + sourceCode.getTokenBefore(openingCurlyToken)!; + const tokenBeforeClosingCurly = + sourceCode.getTokenBefore(closingCurlyToken)!; + const tokenAfterOpeningCurly = + sourceCode.getTokenAfter(openingCurlyToken)!; if ( !isAllmanStyle && diff --git a/packages/eslint-plugin/src/rules/consistent-type-imports.ts b/packages/eslint-plugin/src/rules/consistent-type-imports.ts index bf24bcdbc60c..34f264ff0c7d 100644 --- a/packages/eslint-plugin/src/rules/consistent-type-imports.ts +++ b/packages/eslint-plugin/src/rules/consistent-type-imports.ts @@ -255,9 +255,10 @@ export default util.createRule({ const isTypeImport = report.node.importKind === 'type'; // we have a mixed type/value import, so we need to split them out into multiple exports - const importNames = (isTypeImport - ? report.valueSpecifiers - : report.typeSpecifiers + const importNames = ( + isTypeImport + ? report.valueSpecifiers + : report.typeSpecifiers ).map(specifier => `"${specifier.local.name}"`); const message = ((): { @@ -343,9 +344,7 @@ export default util.createRule({ : {}), }; - function classifySpecifier( - node: TSESTree.ImportDeclaration, - ): { + function classifySpecifier(node: TSESTree.ImportDeclaration): { defaultSpecifier: TSESTree.ImportDefaultSpecifier | null; namespaceSpecifier: TSESTree.ImportNamespaceSpecifier | null; namedSpecifiers: TSESTree.ImportSpecifier[]; @@ -359,10 +358,11 @@ export default util.createRule({ (specifier): specifier is TSESTree.ImportNamespaceSpecifier => specifier.type === AST_NODE_TYPES.ImportNamespaceSpecifier, ) ?? null; - const namedSpecifiers: TSESTree.ImportSpecifier[] = node.specifiers.filter( - (specifier): specifier is TSESTree.ImportSpecifier => - specifier.type === AST_NODE_TYPES.ImportSpecifier, - ); + const namedSpecifiers: TSESTree.ImportSpecifier[] = + node.specifiers.filter( + (specifier): specifier is TSESTree.ImportSpecifier => + specifier.type === AST_NODE_TYPES.ImportSpecifier, + ); return { defaultSpecifier, namespaceSpecifier, @@ -527,11 +527,8 @@ export default util.createRule({ ): IterableIterator { const { node } = report; - const { - defaultSpecifier, - namespaceSpecifier, - namedSpecifiers, - } = classifySpecifier(node); + const { defaultSpecifier, namespaceSpecifier, namedSpecifiers } = + classifySpecifier(node); if (namespaceSpecifier && !defaultSpecifier) { // e.g. @@ -738,11 +735,8 @@ export default util.createRule({ ): IterableIterator { const { node } = report; - const { - defaultSpecifier, - namespaceSpecifier, - namedSpecifiers, - } = classifySpecifier(node); + const { defaultSpecifier, namespaceSpecifier, namedSpecifiers } = + classifySpecifier(node); if (namespaceSpecifier) { // e.g. diff --git a/packages/eslint-plugin/src/rules/dot-notation.ts b/packages/eslint-plugin/src/rules/dot-notation.ts index 9135dbd5c15f..becc2a92727c 100644 --- a/packages/eslint-plugin/src/rules/dot-notation.ts +++ b/packages/eslint-plugin/src/rules/dot-notation.ts @@ -93,8 +93,8 @@ export default createRule({ const propertySymbol = typeChecker.getSymbolAtLocation( esTreeNodeToTSNodeMap.get(node.property), ); - const modifierKind = propertySymbol?.getDeclarations()?.[0] - ?.modifiers?.[0].kind; + const modifierKind = + propertySymbol?.getDeclarations()?.[0]?.modifiers?.[0].kind; if ( (allowPrivateClassPropertyAccess && modifierKind == ts.SyntaxKind.PrivateKeyword) || diff --git a/packages/eslint-plugin/src/rules/explicit-member-accessibility.ts b/packages/eslint-plugin/src/rules/explicit-member-accessibility.ts index 23ac95814c06..ece09d8bc71f 100644 --- a/packages/eslint-plugin/src/rules/explicit-member-accessibility.ts +++ b/packages/eslint-plugin/src/rules/explicit-member-accessibility.ts @@ -175,9 +175,8 @@ export default util.createRule({ token.type === AST_TOKEN_TYPES.Keyword && token.value === 'public' ) { - const commensAfterPublicKeyword = sourceCode.getCommentsAfter( - token, - ); + const commensAfterPublicKeyword = + sourceCode.getCommentsAfter(token); if (commensAfterPublicKeyword.length) { // public /* Hi there! */ static foo() // ^^^^^^^ diff --git a/packages/eslint-plugin/src/rules/indent-new-do-not-use/index.ts b/packages/eslint-plugin/src/rules/indent-new-do-not-use/index.ts index 352fcd17256a..68edfe18dbb7 100644 --- a/packages/eslint-plugin/src/rules/indent-new-do-not-use/index.ts +++ b/packages/eslint-plugin/src/rules/indent-new-do-not-use/index.ts @@ -1015,9 +1015,8 @@ export default createRule({ token.type === AST_TOKEN_TYPES.Punctuator && token.value === ':', )!; - const firstConsequentToken = sourceCode.getTokenAfter( - questionMarkToken, - )!; + const firstConsequentToken = + sourceCode.getTokenAfter(questionMarkToken)!; const lastConsequentToken = sourceCode.getTokenBefore(colonToken)!; const firstAlternateToken = sourceCode.getTokenAfter(colonToken)!; @@ -1207,9 +1206,8 @@ export default createRule({ node.property, isNotClosingParenToken, )!; - const secondNonObjectToken = sourceCode.getTokenAfter( - firstNonObjectToken, - )!; + const secondNonObjectToken = + sourceCode.getTokenAfter(firstNonObjectToken)!; const objectParenCount = sourceCode.getTokensBetween( object, @@ -1677,9 +1675,8 @@ export default createRule({ return; } - const firstTokenOfLine = tokenInfo.firstTokensByLineNumber.get( - lineNumber, - )!; + const firstTokenOfLine = + tokenInfo.firstTokensByLineNumber.get(lineNumber)!; if (firstTokenOfLine.loc.start.line !== lineNumber) { // Don't check the indentation of multi-line tokens (e.g. template literals or block comments) twice. diff --git a/packages/eslint-plugin/src/rules/indent.ts b/packages/eslint-plugin/src/rules/indent.ts index a000cc0d4657..b25586a0e8b6 100644 --- a/packages/eslint-plugin/src/rules/indent.ts +++ b/packages/eslint-plugin/src/rules/indent.ts @@ -241,10 +241,9 @@ export default util.createRule({ // transform it to an ObjectExpression return rules['ObjectExpression, ObjectPattern']({ type: AST_NODE_TYPES.ObjectExpression, - properties: (node.members as ( - | TSESTree.TSEnumMember - | TSESTree.TypeElement - )[]).map( + properties: ( + node.members as (TSESTree.TSEnumMember | TSESTree.TypeElement)[] + ).map( member => TSPropertySignatureToProperty(member) as TSESTree.Property, ), diff --git a/packages/eslint-plugin/src/rules/method-signature-style.ts b/packages/eslint-plugin/src/rules/method-signature-style.ts index 54e68b2c671f..4775a1fec718 100644 --- a/packages/eslint-plugin/src/rules/method-signature-style.ts +++ b/packages/eslint-plugin/src/rules/method-signature-style.ts @@ -130,12 +130,13 @@ export default util.createRule({ ? parent.members : []; - const duplicatedKeyMethodNodes: TSESTree.TSMethodSignature[] = members.filter( - (element): element is TSESTree.TSMethodSignature => - element.type === AST_NODE_TYPES.TSMethodSignature && - element !== methodNode && - getMethodKey(element) === getMethodKey(methodNode), - ); + const duplicatedKeyMethodNodes: TSESTree.TSMethodSignature[] = + members.filter( + (element): element is TSESTree.TSMethodSignature => + element.type === AST_NODE_TYPES.TSMethodSignature && + element !== methodNode && + getMethodKey(element) === getMethodKey(methodNode), + ); const isParentModule = isNodeParentModuleDeclaration(methodNode); if (duplicatedKeyMethodNodes.length > 0) { 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 b58edd99ed6a..f507f37218f0 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,8 +32,10 @@ export default util.createRule({ return { 'TSNonNullExpression > TSNonNullExpression': checkExtraNonNullAssertion, - 'MemberExpression[optional = true] > TSNonNullExpression.object': checkExtraNonNullAssertion, - 'CallExpression[optional = true] > TSNonNullExpression.callee': checkExtraNonNullAssertion, + 'MemberExpression[optional = true] > TSNonNullExpression.object': + checkExtraNonNullAssertion, + 'CallExpression[optional = true] > TSNonNullExpression.callee': + checkExtraNonNullAssertion, }; }, }); diff --git a/packages/eslint-plugin/src/rules/no-inferrable-types.ts b/packages/eslint-plugin/src/rules/no-inferrable-types.ts index d6b6538a95d4..110bda41aea6 100644 --- a/packages/eslint-plugin/src/rules/no-inferrable-types.ts +++ b/packages/eslint-plugin/src/rules/no-inferrable-types.ts @@ -242,12 +242,14 @@ export default util.createRule({ if (ignoreParameters || !node.params) { return; } - (node.params.filter( - param => - param.type === AST_NODE_TYPES.AssignmentPattern && - param.left && - param.right, - ) as TSESTree.AssignmentPattern[]).forEach(param => { + ( + node.params.filter( + param => + param.type === AST_NODE_TYPES.AssignmentPattern && + param.left && + param.right, + ) as TSESTree.AssignmentPattern[] + ).forEach(param => { reportInferrableType(param, param.left.typeAnnotation, param.right); }); } diff --git a/packages/eslint-plugin/src/rules/no-magic-numbers.ts b/packages/eslint-plugin/src/rules/no-magic-numbers.ts index 0cb41337c1bb..1f45a489d357 100644 --- a/packages/eslint-plugin/src/rules/no-magic-numbers.ts +++ b/packages/eslint-plugin/src/rules/no-magic-numbers.ts @@ -84,9 +84,8 @@ export default util.createRule({ return; } - let fullNumberNode: - | TSESTree.Literal - | TSESTree.UnaryExpression = node; + let fullNumberNode: TSESTree.Literal | TSESTree.UnaryExpression = + node; let raw = node.raw; if ( diff --git a/packages/eslint-plugin/src/rules/no-redeclare.ts b/packages/eslint-plugin/src/rules/no-redeclare.ts index 35e40f3372d6..ae4b2e9a3f5a 100644 --- a/packages/eslint-plugin/src/rules/no-redeclare.ts +++ b/packages/eslint-plugin/src/rules/no-redeclare.ts @@ -68,9 +68,7 @@ export default util.createRule({ AST_NODE_TYPES.TSModuleDeclaration, ]); - function* iterateDeclarations( - variable: TSESLint.Scope.Variable, - ): Generator< + function* iterateDeclarations(variable: TSESLint.Scope.Variable): Generator< { type: 'builtin' | 'syntax' | 'comment'; node?: TSESTree.Identifier | TSESTree.Comment; @@ -206,9 +204,8 @@ export default util.createRule({ function findVariablesInScope(scope: TSESLint.Scope.Scope): void { for (const variable of scope.variables) { - const [declaration, ...extraDeclarations] = iterateDeclarations( - variable, - ); + const [declaration, ...extraDeclarations] = + iterateDeclarations(variable); if (extraDeclarations.length === 0) { continue; diff --git a/packages/eslint-plugin/src/rules/no-unnecessary-condition.ts b/packages/eslint-plugin/src/rules/no-unnecessary-condition.ts index 3687d99445ba..5ae3f93408a5 100644 --- a/packages/eslint-plugin/src/rules/no-unnecessary-condition.ts +++ b/packages/eslint-plugin/src/rules/no-unnecessary-condition.ts @@ -443,9 +443,9 @@ export default createRule({ // (Value to complexity ratio is dubious however) } // Otherwise just do type analysis on the function as a whole. - const returnTypes = getCallSignaturesOfType( - getNodeType(callback), - ).map(sig => sig.getReturnType()); + const returnTypes = getCallSignaturesOfType(getNodeType(callback)).map( + sig => sig.getReturnType(), + ); /* istanbul ignore if */ if (returnTypes.length === 0) { // Not a callable function return; diff --git a/packages/eslint-plugin/src/rules/no-unnecessary-qualifier.ts b/packages/eslint-plugin/src/rules/no-unnecessary-qualifier.ts index 395bbfdc4f32..014b2c220e41 100644 --- a/packages/eslint-plugin/src/rules/no-unnecessary-qualifier.ts +++ b/packages/eslint-plugin/src/rules/no-unnecessary-qualifier.ts @@ -170,12 +170,16 @@ export default util.createRule({ return { TSModuleDeclaration: enterDeclaration, TSEnumDeclaration: enterDeclaration, - 'ExportNamedDeclaration[declaration.type="TSModuleDeclaration"]': enterDeclaration, - 'ExportNamedDeclaration[declaration.type="TSEnumDeclaration"]': enterDeclaration, + 'ExportNamedDeclaration[declaration.type="TSModuleDeclaration"]': + enterDeclaration, + 'ExportNamedDeclaration[declaration.type="TSEnumDeclaration"]': + enterDeclaration, 'TSModuleDeclaration:exit': exitDeclaration, 'TSEnumDeclaration:exit': exitDeclaration, - 'ExportNamedDeclaration[declaration.type="TSModuleDeclaration"]:exit': exitDeclaration, - 'ExportNamedDeclaration[declaration.type="TSEnumDeclaration"]:exit': exitDeclaration, + 'ExportNamedDeclaration[declaration.type="TSModuleDeclaration"]:exit': + exitDeclaration, + 'ExportNamedDeclaration[declaration.type="TSEnumDeclaration"]:exit': + exitDeclaration, TSQualifiedName(node: TSESTree.TSQualifiedName): void { visitNamespaceAccess(node, node.left, node.right); }, diff --git a/packages/eslint-plugin/src/rules/no-unsafe-argument.ts b/packages/eslint-plugin/src/rules/no-unsafe-argument.ts index 84887bd8d658..aef8f927bea9 100644 --- a/packages/eslint-plugin/src/rules/no-unsafe-argument.ts +++ b/packages/eslint-plugin/src/rules/no-unsafe-argument.ts @@ -207,9 +207,8 @@ export default util.createRule<[], MessageIds>({ }); } else if (checker.isTupleType(spreadArgType)) { // foo(...[tuple1, tuple2]) - const spreadTypeArguments = checker.getTypeArguments( - spreadArgType, - ); + const spreadTypeArguments = + checker.getTypeArguments(spreadArgType); for (let j = 0; j < spreadTypeArguments.length; j += 1) { const tupleType = spreadTypeArguments[j]; const parameterType = signature.getNextParameterType(); diff --git a/packages/eslint-plugin/src/rules/no-unsafe-member-access.ts b/packages/eslint-plugin/src/rules/no-unsafe-member-access.ts index 13fd7bf0821b..121e826053e2 100644 --- a/packages/eslint-plugin/src/rules/no-unsafe-member-access.ts +++ b/packages/eslint-plugin/src/rules/no-unsafe-member-access.ts @@ -104,7 +104,8 @@ export default util.createRule({ return { // ignore MemberExpression if it's parent is TSClassImplements or TSInterfaceHeritage - ':not(TSClassImplements, TSInterfaceHeritage) > MemberExpression': checkMemberExpression, + ':not(TSClassImplements, TSInterfaceHeritage) > MemberExpression': + checkMemberExpression, 'MemberExpression[computed = true] > *.property'( node: TSESTree.Expression, ): void { diff --git a/packages/eslint-plugin/src/rules/no-use-before-define.ts b/packages/eslint-plugin/src/rules/no-use-before-define.ts index 2b0bb32ccb57..59680863c9bc 100644 --- a/packages/eslint-plugin/src/rules/no-use-before-define.ts +++ b/packages/eslint-plugin/src/rules/no-use-before-define.ts @@ -5,7 +5,8 @@ import { } from '@typescript-eslint/experimental-utils'; import * as util from '../util'; -const SENTINEL_TYPE = /^(?:(?:Function|Class)(?:Declaration|Expression)|ArrowFunctionExpression|CatchClause|ImportDeclaration|ExportNamedDeclaration)$/; +const SENTINEL_TYPE = + /^(?:(?:Function|Class)(?:Declaration|Expression)|ArrowFunctionExpression|CatchClause|ImportDeclaration|ExportNamedDeclaration)$/; /** * Parses a given value as options. diff --git a/packages/eslint-plugin/src/rules/object-curly-spacing.ts b/packages/eslint-plugin/src/rules/object-curly-spacing.ts index 256057c4fdfa..00c73820fd7c 100644 --- a/packages/eslint-plugin/src/rules/object-curly-spacing.ts +++ b/packages/eslint-plugin/src/rules/object-curly-spacing.ts @@ -170,8 +170,9 @@ export default createRule({ ): void { if (isTokenOnSameLine(first, second)) { const firstSpaced = sourceCode.isSpaceBetween!(first, second); - const secondType = sourceCode.getNodeByRangeIndex(second.range[0])! - .type; + const secondType = sourceCode.getNodeByRangeIndex( + second.range[0], + )!.type; const openingCurlyBraceMustBeSpaced = options.arraysInObjectsException && diff --git a/packages/eslint-plugin/src/rules/prefer-includes.ts b/packages/eslint-plugin/src/rules/prefer-includes.ts index 5801f9756b2f..13a6021c8069 100644 --- a/packages/eslint-plugin/src/rules/prefer-includes.ts +++ b/packages/eslint-plugin/src/rules/prefer-includes.ts @@ -132,10 +132,11 @@ export default createRule({ ): void { // Check if the comparison is equivalent to `includes()`. const callNode = node.parent as TSESTree.CallExpression; - const compareNode = (callNode.parent?.type === - AST_NODE_TYPES.ChainExpression - ? callNode.parent.parent - : callNode.parent) as TSESTree.BinaryExpression; + const compareNode = ( + callNode.parent?.type === AST_NODE_TYPES.ChainExpression + ? callNode.parent.parent + : callNode.parent + ) as TSESTree.BinaryExpression; const negative = isNegativeCheck(compareNode); if (!negative && !isPositiveCheck(compareNode)) { return; diff --git a/packages/eslint-plugin/src/rules/prefer-optional-chain.ts b/packages/eslint-plugin/src/rules/prefer-optional-chain.ts index cd886a9d9974..0e15bf8f9794 100644 --- a/packages/eslint-plugin/src/rules/prefer-optional-chain.ts +++ b/packages/eslint-plugin/src/rules/prefer-optional-chain.ts @@ -65,10 +65,12 @@ export default util.createRule({ | TSESTree.MemberExpression, ): void { // selector guarantees this cast - const initialExpression = (initialIdentifierOrNotEqualsExpr.parent - ?.type === AST_NODE_TYPES.ChainExpression - ? initialIdentifierOrNotEqualsExpr.parent.parent - : initialIdentifierOrNotEqualsExpr.parent) as TSESTree.LogicalExpression; + const initialExpression = ( + initialIdentifierOrNotEqualsExpr.parent?.type === + AST_NODE_TYPES.ChainExpression + ? initialIdentifierOrNotEqualsExpr.parent.parent + : initialIdentifierOrNotEqualsExpr.parent + ) as TSESTree.LogicalExpression; if (initialExpression.left !== initialIdentifierOrNotEqualsExpr) { // the node(identifier or member expression) is not the deepest left node diff --git a/packages/eslint-plugin/src/rules/prefer-readonly.ts b/packages/eslint-plugin/src/rules/prefer-readonly.ts index 27eb7dca97cc..56ab8265a9a0 100644 --- a/packages/eslint-plugin/src/rules/prefer-readonly.ts +++ b/packages/eslint-plugin/src/rules/prefer-readonly.ts @@ -200,9 +200,8 @@ export default util.createRule({ const sourceCode = context.getSourceCode(); for (const violatingNode of finalizedClassScope.finalizeUnmodifiedPrivateNonReadonlys()) { - const { esNode, nameNode } = getEsNodesFromViolatingNode( - violatingNode, - ); + const { esNode, nameNode } = + getEsNodesFromViolatingNode(violatingNode); context.report({ data: { name: sourceCode.getText(nameNode), diff --git a/packages/eslint-plugin/src/rules/semi.ts b/packages/eslint-plugin/src/rules/semi.ts index 9c18d0e36712..eccc264e4613 100644 --- a/packages/eslint-plugin/src/rules/semi.ts +++ b/packages/eslint-plugin/src/rules/semi.ts @@ -36,7 +36,8 @@ export default util.createRule({ ], create(context) { const rules = baseRule.create(context); - const checkForSemicolon = rules.ExpressionStatement as TSESLint.RuleFunction; + const checkForSemicolon = + rules.ExpressionStatement as TSESLint.RuleFunction; /* The following nodes are handled by the member-delimiter-style rule diff --git a/packages/eslint-plugin/src/rules/triple-slash-reference.ts b/packages/eslint-plugin/src/rules/triple-slash-reference.ts index 08c3ad6291b2..525febe2be3c 100644 --- a/packages/eslint-plugin/src/rules/triple-slash-reference.ts +++ b/packages/eslint-plugin/src/rules/triple-slash-reference.ts @@ -94,7 +94,8 @@ export default util.createRule({ return; } programNode = node; - const referenceRegExp = /^\/\s* { diff --git a/packages/eslint-plugin/src/util/collectUnusedVariables.ts b/packages/eslint-plugin/src/util/collectUnusedVariables.ts index 19aaf33565ff..b36d07e818cd 100644 --- a/packages/eslint-plugin/src/util/collectUnusedVariables.ts +++ b/packages/eslint-plugin/src/util/collectUnusedVariables.ts @@ -9,7 +9,7 @@ import * as util from '.'; class UnusedVarsVisitor< TMessageIds extends string, - TOptions extends readonly unknown[] + TOptions extends readonly unknown[], > extends Visitor { private static readonly RESULTS_CACHE = new WeakMap< TSESTree.Program, @@ -32,7 +32,7 @@ class UnusedVarsVisitor< public static collectUnusedVariables< TMessageIds extends string, - TOptions extends readonly unknown[] + TOptions extends readonly unknown[], >( context: TSESLint.RuleContext, ): ReadonlySet { @@ -747,7 +747,7 @@ function isUsedVariable(variable: TSESLint.Scope.Variable): boolean { */ function collectUnusedVariables< TMessageIds extends string, - TOptions extends readonly unknown[] + TOptions extends readonly unknown[], >( context: Readonly>, ): ReadonlySet { diff --git a/packages/eslint-plugin/src/util/index.ts b/packages/eslint-plugin/src/util/index.ts index 79e142b15fd4..4c0284895235 100644 --- a/packages/eslint-plugin/src/util/index.ts +++ b/packages/eslint-plugin/src/util/index.ts @@ -15,15 +15,10 @@ export * from './requiresQuoting'; export * from './types'; // this is done for convenience - saves migrating all of the old rules -const { - applyDefault, - deepMerge, - isObjectNotArray, - getParserServices, -} = ESLintUtils; -type InferMessageIdsTypeFromRule< - T -> = ESLintUtils.InferMessageIdsTypeFromRule; +const { applyDefault, deepMerge, isObjectNotArray, getParserServices } = + ESLintUtils; +type InferMessageIdsTypeFromRule = + ESLintUtils.InferMessageIdsTypeFromRule; type InferOptionsTypeFromRule = ESLintUtils.InferOptionsTypeFromRule; export { diff --git a/packages/eslint-plugin/src/util/misc.ts b/packages/eslint-plugin/src/util/misc.ts index 2e6c4711cb0d..e7e0991ba6a0 100644 --- a/packages/eslint-plugin/src/util/misc.ts +++ b/packages/eslint-plugin/src/util/misc.ts @@ -91,11 +91,11 @@ function getNameFromMember( type ExcludeKeys< TObj extends Record, - TKeys extends keyof TObj + TKeys extends keyof TObj, > = { [k in Exclude]: TObj[k] }; type RequireKeys< TObj extends Record, - TKeys extends keyof TObj + TKeys extends keyof TObj, > = ExcludeKeys & { [k in TKeys]-?: Exclude }; function getEnumNames(myEnum: Record): T[] { diff --git a/packages/eslint-plugin/tests/docs.test.ts b/packages/eslint-plugin/tests/docs.test.ts index 7223df50b90e..ceaf83d6680a 100644 --- a/packages/eslint-plugin/tests/docs.test.ts +++ b/packages/eslint-plugin/tests/docs.test.ts @@ -137,9 +137,10 @@ describe('Validating README.md', () => { for (const [ruleName, rule] of notDeprecated) { describe(`Checking rule ${ruleName}`, () => { - const ruleRow: string[] | undefined = (rule.meta.docs?.extendsBaseRule - ? rulesTables.extension.cells - : rulesTables.base.cells + const ruleRow: string[] | undefined = ( + rule.meta.docs?.extendsBaseRule + ? rulesTables.extension.cells + : rulesTables.base.cells ).find(row => row[0].includes(`/${ruleName}.md`)); if (!ruleRow) { // rule is in the wrong table, the first two tests will catch this, so no point in creating noise; diff --git a/packages/eslint-plugin/tests/rules/ban-ts-comment.test.ts b/packages/eslint-plugin/tests/rules/ban-ts-comment.test.ts index 994da016d5f7..b9d10b005b6f 100644 --- a/packages/eslint-plugin/tests/rules/ban-ts-comment.test.ts +++ b/packages/eslint-plugin/tests/rules/ban-ts-comment.test.ts @@ -173,8 +173,7 @@ ruleTester.run('ts-ignore', rule, { options: [{ 'ts-ignore': false }], }, { - code: - '// @ts-ignore I think that I am exempted from any need to follow the rules!', + code: '// @ts-ignore I think that I am exempted from any need to follow the rules!', options: [{ 'ts-ignore': 'allow-with-description' }], }, { @@ -340,8 +339,7 @@ ruleTester.run('ts-nocheck', rule, { options: [{ 'ts-nocheck': false }], }, { - code: - '// @ts-nocheck no doubt, people will put nonsense here from time to time just to get the rule to stop reporting, perhaps even long messages with other nonsense in them like other // @ts-nocheck or // @ts-ignore things', + code: '// @ts-nocheck no doubt, people will put nonsense here from time to time just to get the rule to stop reporting, perhaps even long messages with other nonsense in them like other // @ts-nocheck or // @ts-ignore things', options: [{ 'ts-nocheck': 'allow-with-description' }], }, { @@ -488,8 +486,7 @@ ruleTester.run('ts-check', rule, { options: [{ 'ts-check': false }], }, { - code: - '// @ts-check with a description and also with a no-op // @ts-ignore', + code: '// @ts-check with a description and also with a no-op // @ts-ignore', options: [ { 'ts-check': 'allow-with-description', minimumDescriptionLength: 3 }, ], diff --git a/packages/eslint-plugin/tests/rules/brace-style.test.ts b/packages/eslint-plugin/tests/rules/brace-style.test.ts index 28b9413795db..35bc5afe9967 100644 --- a/packages/eslint-plugin/tests/rules/brace-style.test.ts +++ b/packages/eslint-plugin/tests/rules/brace-style.test.ts @@ -721,16 +721,14 @@ if (f) { errors: [{ messageId: 'sameLineClose' }], }, { - code: - 'if (foo) {\nbaz();\n} else if (bar) {\nbaz();\n}\nelse {\nqux();\n}', + code: 'if (foo) {\nbaz();\n} else if (bar) {\nbaz();\n}\nelse {\nqux();\n}', output: 'if (foo) {\nbaz();\n}\n else if (bar) {\nbaz();\n}\nelse {\nqux();\n}', options: ['stroustrup'], errors: [{ messageId: 'sameLineClose' }], }, { - code: - 'if (foo) {\npoop();\n} \nelse if (bar) {\nbaz();\n} else if (thing) {\nboom();\n}\nelse {\nqux();\n}', + code: 'if (foo) {\npoop();\n} \nelse if (bar) {\nbaz();\n} else if (thing) {\nboom();\n}\nelse {\nqux();\n}', output: 'if (foo) {\npoop();\n} \nelse if (bar) {\nbaz();\n}\n else if (thing) {\nboom();\n}\nelse {\nqux();\n}', options: ['stroustrup'], @@ -767,8 +765,7 @@ if (f) { ], }, { - code: - 'if (foo) {\nbaz();\n} else if (bar) {\nbaz();\n}\nelse {\nqux();\n}', + code: 'if (foo) {\nbaz();\n} else if (bar) {\nbaz();\n}\nelse {\nqux();\n}', output: 'if (foo) \n{\nbaz();\n}\n else if (bar) \n{\nbaz();\n}\nelse \n{\nqux();\n}', options: ['allman'], @@ -780,8 +777,7 @@ if (f) { ], }, { - code: - 'if (foo)\n{ poop();\n} \nelse if (bar) {\nbaz();\n} else if (thing) {\nboom();\n}\nelse {\nqux();\n}', + code: 'if (foo)\n{ poop();\n} \nelse if (bar) {\nbaz();\n} else if (thing) {\nboom();\n}\nelse {\nqux();\n}', output: 'if (foo)\n{\n poop();\n} \nelse if (bar) \n{\nbaz();\n}\n else if (thing) \n{\nboom();\n}\nelse \n{\nqux();\n}', options: ['allman'], @@ -946,8 +942,7 @@ if (f) { errors: [{ messageId: 'sameLineClose' }], }, { - code: - 'if (foo)\n{ poop();\n} \nelse if (bar) {\nbaz();\n} else if (thing) {\nboom();\n}\nelse {\nqux();\n}', + code: 'if (foo)\n{ poop();\n} \nelse if (bar) {\nbaz();\n} else if (thing) {\nboom();\n}\nelse {\nqux();\n}', output: 'if (foo)\n{\n poop();\n} \nelse if (bar) \n{\nbaz();\n}\n else if (thing) \n{\nboom();\n}\nelse \n{\nqux();\n}', options: ['allman', { allowSingleLine: true }], diff --git a/packages/eslint-plugin/tests/rules/indent/indent-eslint.test.ts b/packages/eslint-plugin/tests/rules/indent/indent-eslint.test.ts index a9dfda6b127b..d03ee3ea9dc8 100644 --- a/packages/eslint-plugin/tests/rules/indent/indent-eslint.test.ts +++ b/packages/eslint-plugin/tests/rules/indent/indent-eslint.test.ts @@ -846,8 +846,7 @@ ruleTester.run('indent', rule, { options: [2, { SwitchCase: 1 }], }, { - code: - 'var geometry, box, face1, face2, colorT, colorB, sprite, padding, maxWidth;', + code: 'var geometry, box, face1, face2, colorT, colorB, sprite, padding, maxWidth;', options: [2, { SwitchCase: 1 }], }, { diff --git a/packages/eslint-plugin/tests/rules/member-ordering.test.ts b/packages/eslint-plugin/tests/rules/member-ordering.test.ts index c17aa57b90e7..b53143866b20 100644 --- a/packages/eslint-plugin/tests/rules/member-ordering.test.ts +++ b/packages/eslint-plugin/tests/rules/member-ordering.test.ts @@ -5155,14 +5155,12 @@ type Foo = { ], }; -const sortedWithGroupingDefaultOption: TSESLint.RunTests< - MessageIds, - Options -> = { - valid: [ - // default option + interface + default order + alphabetically - { - code: ` +const sortedWithGroupingDefaultOption: TSESLint.RunTests = + { + valid: [ + // default option + interface + default order + alphabetically + { + code: ` interface Foo { [a: string] : number; @@ -5179,14 +5177,14 @@ interface Foo { c() : void; } `, - options: [ - { default: { memberTypes: defaultOrder, order: 'alphabetically' } }, - ], - }, + options: [ + { default: { memberTypes: defaultOrder, order: 'alphabetically' } }, + ], + }, - // default option + interface + custom order + alphabetically - { - code: ` + // default option + interface + custom order + alphabetically + { + code: ` interface Foo { new () : Bar; @@ -5202,19 +5200,19 @@ interface Foo { () : Baz; } `, - options: [ - { - default: { - memberTypes: ['constructor', 'method', 'field'], - order: 'alphabetically', + options: [ + { + default: { + memberTypes: ['constructor', 'method', 'field'], + order: 'alphabetically', + }, }, - }, - ], - }, + ], + }, - // default option + type literal + default order + alphabetically - { - code: ` + // default option + type literal + default order + alphabetically + { + code: ` type Foo = { [a: string] : number; @@ -5231,14 +5229,14 @@ type Foo = { c() : void; } `, - options: [ - { default: { memberTypes: defaultOrder, order: 'alphabetically' } }, - ], - }, + options: [ + { default: { memberTypes: defaultOrder, order: 'alphabetically' } }, + ], + }, - // default option + type literal + custom order + alphabetically - { - code: ` + // default option + type literal + custom order + alphabetically + { + code: ` type Foo = { [a: string] : number; @@ -5255,19 +5253,19 @@ type Foo = { () : Baz; } `, - options: [ - { - default: { - memberTypes: ['constructor', 'method', 'field'], - order: 'alphabetically', + options: [ + { + default: { + memberTypes: ['constructor', 'method', 'field'], + order: 'alphabetically', + }, }, - }, - ], - }, + ], + }, - // default option + class + default order + alphabetically - { - code: ` + // default option + class + default order + alphabetically + { + code: ` class Foo { public static a: string; protected static b: string = ""; @@ -5280,13 +5278,13 @@ class Foo { constructor() {} } `, - options: [ - { default: { memberTypes: defaultOrder, order: 'alphabetically' } }, - ], - }, - // default option + class + decorators + default order + alphabetically - { - code: ` + options: [ + { default: { memberTypes: defaultOrder, order: 'alphabetically' } }, + ], + }, + // default option + class + decorators + default order + alphabetically + { + code: ` class Foo { public static a: string; protected static b: string = ""; @@ -5303,14 +5301,14 @@ class Foo { constructor() {} } `, - options: [ - { default: { memberTypes: defaultOrder, order: 'alphabetically' } }, - ], - }, + options: [ + { default: { memberTypes: defaultOrder, order: 'alphabetically' } }, + ], + }, - // default option + class + custom order + alphabetically - { - code: ` + // default option + class + custom order + alphabetically + { + code: ` class Foo { constructor() {} @@ -5323,19 +5321,19 @@ class Foo { private static c: string = ""; } `, - options: [ - { - default: { - memberTypes: ['constructor', 'instance-field', 'static-field'], - order: 'alphabetically', + options: [ + { + default: { + memberTypes: ['constructor', 'instance-field', 'static-field'], + order: 'alphabetically', + }, }, - }, - ], - }, + ], + }, - // default option + class expression + default order + alphabetically - { - code: ` + // default option + class expression + default order + alphabetically + { + code: ` const foo = class Foo { public static a: string; protected static b: string = ""; @@ -5348,14 +5346,14 @@ const foo = class Foo { constructor() {} } `, - options: [ - { default: { memberTypes: defaultOrder, order: 'alphabetically' } }, - ], - }, + options: [ + { default: { memberTypes: defaultOrder, order: 'alphabetically' } }, + ], + }, - // default option + class expression + custom order + alphabetically - { - code: ` + // default option + class expression + custom order + alphabetically + { + code: ` const foo = class Foo { constructor() {} @@ -5368,20 +5366,20 @@ const foo = class Foo { private static c: string = ""; } `, - options: [ - { - default: { - memberTypes: ['constructor', 'instance-field', 'static-field'], - order: 'alphabetically', - }, - }, - ], - }, - ], - invalid: [ - // default option + interface + wrong order within group and wrong group order + alphabetically - { - code: ` + options: [ + { + default: { + memberTypes: ['constructor', 'instance-field', 'static-field'], + order: 'alphabetically', + }, + }, + ], + }, + ], + invalid: [ + // default option + interface + wrong order within group and wrong group order + alphabetically + { + code: ` interface Foo { [a: string] : number; @@ -5398,30 +5396,30 @@ interface Foo { new () : Bar; } `, - options: [ - { default: { memberTypes: defaultOrder, order: 'alphabetically' } }, - ], - errors: [ - { - messageId: 'incorrectGroupOrder', - data: { - name: 'call', - rank: 'field', - }, - }, - { - messageId: 'incorrectGroupOrder', - data: { - name: 'new', - rank: 'method', - }, - }, - ], - }, - - // default option + type literal + wrong order within group and wrong group order + alphabetically - { - code: ` + options: [ + { default: { memberTypes: defaultOrder, order: 'alphabetically' } }, + ], + errors: [ + { + messageId: 'incorrectGroupOrder', + data: { + name: 'call', + rank: 'field', + }, + }, + { + messageId: 'incorrectGroupOrder', + data: { + name: 'new', + rank: 'method', + }, + }, + ], + }, + + // default option + type literal + wrong order within group and wrong group order + alphabetically + { + code: ` type Foo = { [a: string] : number; @@ -5438,30 +5436,30 @@ type Foo = { new () : Bar; } `, - options: [ - { default: { memberTypes: defaultOrder, order: 'alphabetically' } }, - ], - errors: [ - { - messageId: 'incorrectGroupOrder', - data: { - name: 'call', - rank: 'field', - }, - }, - { - messageId: 'incorrectGroupOrder', - data: { - name: 'new', - rank: 'method', - }, - }, - ], - }, - - // default option + class + wrong order within group and wrong group order + alphabetically - { - code: ` + options: [ + { default: { memberTypes: defaultOrder, order: 'alphabetically' } }, + ], + errors: [ + { + messageId: 'incorrectGroupOrder', + data: { + name: 'call', + rank: 'field', + }, + }, + { + messageId: 'incorrectGroupOrder', + data: { + name: 'new', + rank: 'method', + }, + }, + ], + }, + + // default option + class + wrong order within group and wrong group order + alphabetically + { + code: ` class Foo { public static c: string = ""; public static b: string = ""; @@ -5472,23 +5470,23 @@ class Foo { public d: string = ""; } `, - options: [ - { default: { memberTypes: defaultOrder, order: 'alphabetically' } }, - ], - errors: [ - { - messageId: 'incorrectGroupOrder', - data: { - name: 'd', - rank: 'public constructor', + options: [ + { default: { memberTypes: defaultOrder, order: 'alphabetically' } }, + ], + errors: [ + { + messageId: 'incorrectGroupOrder', + data: { + name: 'd', + rank: 'public constructor', + }, }, - }, - ], - }, + ], + }, - // default option + class expression + wrong order within group and wrong group order + alphabetically - { - code: ` + // default option + class expression + wrong order within group and wrong group order + alphabetically + { + code: ` const foo = class Foo { public static c: string = ""; public static b: string = ""; @@ -5499,22 +5497,22 @@ const foo = class Foo { public d: string = ""; } `, - options: [ - { default: { memberTypes: defaultOrder, order: 'alphabetically' } }, - ], - errors: [ - { - messageId: 'incorrectGroupOrder', - data: { - name: 'd', - rank: 'public constructor', - }, - }, - ], - }, - // default option + class + decorators + custom order + wrong order within group and wrong group order + alphabetically - { - code: ` + options: [ + { default: { memberTypes: defaultOrder, order: 'alphabetically' } }, + ], + errors: [ + { + messageId: 'incorrectGroupOrder', + data: { + name: 'd', + rank: 'public constructor', + }, + }, + ], + }, + // default option + class + decorators + custom order + wrong order within group and wrong group order + alphabetically + { + code: ` class Foo { @Dec() a1: string; @Dec() @@ -5531,47 +5529,45 @@ class Foo { @Dec() d(): void } `, - options: [ - { - default: { - memberTypes: [ - 'decorated-field', - 'field', - 'constructor', - 'decorated-method', - ], - order: 'alphabetically', - }, - }, - ], - errors: [ - { - messageId: 'incorrectGroupOrder', - data: { - name: 'b1', - rank: 'constructor', - }, - }, - { - messageId: 'incorrectGroupOrder', - data: { - name: 'b2', - rank: 'constructor', - }, - }, - ], - }, - ], -}; - -const sortedWithGroupingClassesOption: TSESLint.RunTests< - MessageIds, - Options -> = { - valid: [ - // classes option + interface + alphabetically --> Default order applies - { - code: ` + options: [ + { + default: { + memberTypes: [ + 'decorated-field', + 'field', + 'constructor', + 'decorated-method', + ], + order: 'alphabetically', + }, + }, + ], + errors: [ + { + messageId: 'incorrectGroupOrder', + data: { + name: 'b1', + rank: 'constructor', + }, + }, + { + messageId: 'incorrectGroupOrder', + data: { + name: 'b2', + rank: 'constructor', + }, + }, + ], + }, + ], + }; + +const sortedWithGroupingClassesOption: TSESLint.RunTests = + { + valid: [ + // classes option + interface + alphabetically --> Default order applies + { + code: ` interface Foo { [a: string] : number; @@ -5588,12 +5584,12 @@ interface Foo { a() : void; } `, - options: [{ classes: { order: 'alphabetically' } }], - }, + options: [{ classes: { order: 'alphabetically' } }], + }, - // classes option + type literal + alphabetically --> Default order applies - { - code: ` + // classes option + type literal + alphabetically --> Default order applies + { + code: ` type Foo = { [a: string] : number; @@ -5610,12 +5606,12 @@ type Foo = { a() : void; } `, - options: [{ classes: { order: 'alphabetically' } }], - }, + options: [{ classes: { order: 'alphabetically' } }], + }, - // classes option + class + default order + alphabetically - { - code: ` + // classes option + class + default order + alphabetically + { + code: ` class Foo { public static a: string; protected static b: string = ""; @@ -5628,14 +5624,14 @@ class Foo { constructor() {} } `, - options: [ - { classes: { memberTypes: defaultOrder, order: 'alphabetically' } }, - ], - }, + options: [ + { classes: { memberTypes: defaultOrder, order: 'alphabetically' } }, + ], + }, - // classes option + class + custom order + alphabetically - { - code: ` + // classes option + class + custom order + alphabetically + { + code: ` class Foo { constructor() {} @@ -5648,19 +5644,19 @@ class Foo { private static c: string = ""; } `, - options: [ - { - classes: { - memberTypes: ['constructor', 'instance-field', 'static-field'], - order: 'alphabetically', + options: [ + { + classes: { + memberTypes: ['constructor', 'instance-field', 'static-field'], + order: 'alphabetically', + }, }, - }, - ], - }, + ], + }, - // classes option + class expression + alphabetically --> Default order applies - { - code: ` + // classes option + class expression + alphabetically --> Default order applies + { + code: ` const foo = class Foo { public static a: string; protected static b: string = ""; @@ -5673,13 +5669,13 @@ const foo = class Foo { constructor() {} } `, - options: [{ classes: { order: 'alphabetically' } }], - }, - ], - invalid: [ - // default option + class + wrong order within group and wrong group order + alphabetically - { - code: ` + options: [{ classes: { order: 'alphabetically' } }], + }, + ], + invalid: [ + // default option + class + wrong order within group and wrong group order + alphabetically + { + code: ` class Foo { public static c: string = ""; public static b: string = ""; @@ -5690,21 +5686,21 @@ class Foo { public d: string = ""; } `, - options: [ - { default: { memberTypes: defaultOrder, order: 'alphabetically' } }, - ], - errors: [ - { - messageId: 'incorrectGroupOrder', - data: { - name: 'd', - rank: 'public constructor', - }, - }, - ], - }, - ], -}; + options: [ + { default: { memberTypes: defaultOrder, order: 'alphabetically' } }, + ], + errors: [ + { + messageId: 'incorrectGroupOrder', + data: { + name: 'd', + rank: 'public constructor', + }, + }, + ], + }, + ], + }; const sortedWithGroupingClassExpressionsOption: TSESLint.RunTests< MessageIds, diff --git a/packages/eslint-plugin/tests/rules/no-explicit-any.test.ts b/packages/eslint-plugin/tests/rules/no-explicit-any.test.ts index 2694fdbf1042..cb99564c943d 100644 --- a/packages/eslint-plugin/tests/rules/no-explicit-any.test.ts +++ b/packages/eslint-plugin/tests/rules/no-explicit-any.test.ts @@ -235,8 +235,7 @@ interface Qux4 { options: [{ ignoreRestArgs: true }], }, { - code: - 'function quux4(fn: (...args: ReadonlyArray) => void): void {}', + code: 'function quux4(fn: (...args: ReadonlyArray) => void): void {}', options: [{ ignoreRestArgs: true }], }, { @@ -368,831 +367,835 @@ interface Garply4 { options: [{ ignoreRestArgs: true }], }, ], - invalid: ([ - { - code: 'const number: any = 1', - errors: [ - { - messageId: 'unexpectedAny', - line: 1, - column: 15, - }, - ], - }, - { - code: 'function generic(): any {}', - errors: [ - { - messageId: 'unexpectedAny', - line: 1, - column: 21, - }, - ], - }, - { - code: 'function generic(): Array {}', - errors: [ - { - messageId: 'unexpectedAny', - line: 1, - column: 27, - }, - ], - }, - { - code: 'function generic(): any[] {}', - errors: [ - { - messageId: 'unexpectedAny', - line: 1, - column: 21, - }, - ], - }, - { - code: 'function generic(param: Array): number {}', - errors: [ - { - messageId: 'unexpectedAny', - line: 1, - column: 31, - }, - ], - }, - { - code: 'function generic(param: any[]): number {}', - errors: [ - { - messageId: 'unexpectedAny', - line: 1, - column: 25, - }, - ], - }, - { - code: 'function generic(param: Array): Array {}', - errors: [ - { - messageId: 'unexpectedAny', - line: 1, - column: 31, - suggestions: [ - { - messageId: 'suggestUnknown', - output: 'function generic(param: Array): Array {}', - }, - { - messageId: 'suggestNever', - output: 'function generic(param: Array): Array {}', - }, - ], - }, - { - messageId: 'unexpectedAny', - line: 1, - column: 44, - suggestions: [ - { - messageId: 'suggestUnknown', - output: 'function generic(param: Array): Array {}', - }, - { - messageId: 'suggestNever', - output: 'function generic(param: Array): Array {}', - }, - ], - }, - ], - }, - { - code: 'function generic(): Array> {}', - errors: [ - { - messageId: 'unexpectedAny', - line: 1, - column: 33, - }, - ], - }, - { - code: 'function generic(): Array {}', - errors: [ - { - messageId: 'unexpectedAny', - line: 1, - column: 27, - }, - ], - }, - { - code: ` + invalid: ( + [ + { + code: 'const number: any = 1', + errors: [ + { + messageId: 'unexpectedAny', + line: 1, + column: 15, + }, + ], + }, + { + code: 'function generic(): any {}', + errors: [ + { + messageId: 'unexpectedAny', + line: 1, + column: 21, + }, + ], + }, + { + code: 'function generic(): Array {}', + errors: [ + { + messageId: 'unexpectedAny', + line: 1, + column: 27, + }, + ], + }, + { + code: 'function generic(): any[] {}', + errors: [ + { + messageId: 'unexpectedAny', + line: 1, + column: 21, + }, + ], + }, + { + code: 'function generic(param: Array): number {}', + errors: [ + { + messageId: 'unexpectedAny', + line: 1, + column: 31, + }, + ], + }, + { + code: 'function generic(param: any[]): number {}', + errors: [ + { + messageId: 'unexpectedAny', + line: 1, + column: 25, + }, + ], + }, + { + code: 'function generic(param: Array): Array {}', + errors: [ + { + messageId: 'unexpectedAny', + line: 1, + column: 31, + suggestions: [ + { + messageId: 'suggestUnknown', + output: + 'function generic(param: Array): Array {}', + }, + { + messageId: 'suggestNever', + output: 'function generic(param: Array): Array {}', + }, + ], + }, + { + messageId: 'unexpectedAny', + line: 1, + column: 44, + suggestions: [ + { + messageId: 'suggestUnknown', + output: + 'function generic(param: Array): Array {}', + }, + { + messageId: 'suggestNever', + output: 'function generic(param: Array): Array {}', + }, + ], + }, + ], + }, + { + code: 'function generic(): Array> {}', + errors: [ + { + messageId: 'unexpectedAny', + line: 1, + column: 33, + }, + ], + }, + { + code: 'function generic(): Array {}', + errors: [ + { + messageId: 'unexpectedAny', + line: 1, + column: 27, + }, + ], + }, + { + code: ` class Greeter { constructor(param: Array) {} } `, - errors: [ - { - messageId: 'unexpectedAny', - line: 3, - column: 30, - }, - ], - }, - { - code: ` + errors: [ + { + messageId: 'unexpectedAny', + line: 3, + column: 30, + }, + ], + }, + { + code: ` class Greeter { message: any; } `, - errors: [ - { - messageId: 'unexpectedAny', - line: 3, - column: 14, - }, - ], - }, - { - code: ` + errors: [ + { + messageId: 'unexpectedAny', + line: 3, + column: 14, + }, + ], + }, + { + code: ` class Greeter { message: Array; } `, - errors: [ - { - messageId: 'unexpectedAny', - line: 3, - column: 20, - }, - ], - }, - { - code: ` + errors: [ + { + messageId: 'unexpectedAny', + line: 3, + column: 20, + }, + ], + }, + { + code: ` class Greeter { message: any[]; } `, - errors: [ - { - messageId: 'unexpectedAny', - line: 3, - column: 14, - }, - ], - }, - { - code: ` + errors: [ + { + messageId: 'unexpectedAny', + line: 3, + column: 14, + }, + ], + }, + { + code: ` class Greeter { message: Array>; } `, - errors: [ - { - messageId: 'unexpectedAny', - line: 3, - column: 26, - }, - ], - }, - { - code: ` + errors: [ + { + messageId: 'unexpectedAny', + line: 3, + column: 26, + }, + ], + }, + { + code: ` class Greeter { message: Array; } `, - errors: [ - { - messageId: 'unexpectedAny', - line: 3, - column: 20, - }, - ], - }, - { - code: ` + errors: [ + { + messageId: 'unexpectedAny', + line: 3, + column: 20, + }, + ], + }, + { + code: ` interface Greeter { message: any; } `, - errors: [ - { - messageId: 'unexpectedAny', - line: 3, - column: 14, - }, - ], - }, - { - code: ` + errors: [ + { + messageId: 'unexpectedAny', + line: 3, + column: 14, + }, + ], + }, + { + code: ` interface Greeter { message: Array; } `, - errors: [ - { - messageId: 'unexpectedAny', - line: 3, - column: 20, - }, - ], - }, - { - code: ` + errors: [ + { + messageId: 'unexpectedAny', + line: 3, + column: 20, + }, + ], + }, + { + code: ` interface Greeter { message: any[]; } `, - errors: [ - { - messageId: 'unexpectedAny', - line: 3, - column: 14, - }, - ], - }, - { - code: ` + errors: [ + { + messageId: 'unexpectedAny', + line: 3, + column: 14, + }, + ], + }, + { + code: ` interface Greeter { message: Array>; } `, - errors: [ - { - messageId: 'unexpectedAny', - line: 3, - column: 26, - }, - ], - }, - { - code: ` + errors: [ + { + messageId: 'unexpectedAny', + line: 3, + column: 26, + }, + ], + }, + { + code: ` interface Greeter { message: Array; } `, - errors: [ - { - messageId: 'unexpectedAny', - line: 3, - column: 20, - }, - ], - }, - { - code: ` + errors: [ + { + messageId: 'unexpectedAny', + line: 3, + column: 20, + }, + ], + }, + { + code: ` type obj = { message: any; } `, - errors: [ - { - messageId: 'unexpectedAny', - line: 3, - column: 14, - }, - ], - }, - { - code: ` + errors: [ + { + messageId: 'unexpectedAny', + line: 3, + column: 14, + }, + ], + }, + { + code: ` type obj = { message: Array; } `, - errors: [ - { - messageId: 'unexpectedAny', - line: 3, - column: 20, - }, - ], - }, - { - code: ` + errors: [ + { + messageId: 'unexpectedAny', + line: 3, + column: 20, + }, + ], + }, + { + code: ` type obj = { message: any[]; } `, - errors: [ - { - messageId: 'unexpectedAny', - line: 3, - column: 14, - }, - ], - }, - { - code: ` + errors: [ + { + messageId: 'unexpectedAny', + line: 3, + column: 14, + }, + ], + }, + { + code: ` type obj = { message: Array>; } `, - errors: [ - { - messageId: 'unexpectedAny', - line: 3, - column: 26, - }, - ], - }, - { - code: ` + errors: [ + { + messageId: 'unexpectedAny', + line: 3, + column: 26, + }, + ], + }, + { + code: ` type obj = { message: Array; } `, - errors: [ - { - messageId: 'unexpectedAny', - line: 3, - column: 20, - }, - ], - }, - { - code: ` + errors: [ + { + messageId: 'unexpectedAny', + line: 3, + column: 20, + }, + ], + }, + { + code: ` type obj = { message: string | any; } `, - errors: [ - { - messageId: 'unexpectedAny', - line: 3, - column: 23, - }, - ], - }, - { - code: ` + errors: [ + { + messageId: 'unexpectedAny', + line: 3, + column: 23, + }, + ], + }, + { + code: ` type obj = { message: string | Array; } `, - errors: [ - { - messageId: 'unexpectedAny', - line: 3, - column: 29, - }, - ], - }, - { - code: ` + errors: [ + { + messageId: 'unexpectedAny', + line: 3, + column: 29, + }, + ], + }, + { + code: ` type obj = { message: string | any[]; } `, - errors: [ - { - messageId: 'unexpectedAny', - line: 3, - column: 23, - }, - ], - }, - { - code: ` + errors: [ + { + messageId: 'unexpectedAny', + line: 3, + column: 23, + }, + ], + }, + { + code: ` type obj = { message: string | Array>; } `, - errors: [ - { - messageId: 'unexpectedAny', - line: 3, - column: 35, - }, - ], - }, - { - code: ` + errors: [ + { + messageId: 'unexpectedAny', + line: 3, + column: 35, + }, + ], + }, + { + code: ` type obj = { message: string | Array; } `, - errors: [ - { - messageId: 'unexpectedAny', - line: 3, - column: 29, - }, - ], - }, - { - code: ` + errors: [ + { + messageId: 'unexpectedAny', + line: 3, + column: 29, + }, + ], + }, + { + code: ` type obj = { message: string & any; } `, - errors: [ - { - messageId: 'unexpectedAny', - line: 3, - column: 23, - }, - ], - }, - { - code: ` + errors: [ + { + messageId: 'unexpectedAny', + line: 3, + column: 23, + }, + ], + }, + { + code: ` type obj = { message: string & Array; } `, - errors: [ - { - messageId: 'unexpectedAny', - line: 3, - column: 29, - }, - ], - }, - { - code: ` + errors: [ + { + messageId: 'unexpectedAny', + line: 3, + column: 29, + }, + ], + }, + { + code: ` type obj = { message: string & any[]; } `, - errors: [ - { - messageId: 'unexpectedAny', - line: 3, - column: 23, - }, - ], - }, - { - code: ` + errors: [ + { + messageId: 'unexpectedAny', + line: 3, + column: 23, + }, + ], + }, + { + code: ` type obj = { message: string & Array>; } `, - errors: [ - { - messageId: 'unexpectedAny', - line: 3, - column: 35, - }, - ], - }, - { - code: ` + errors: [ + { + messageId: 'unexpectedAny', + line: 3, + column: 35, + }, + ], + }, + { + code: ` type obj = { message: string & Array; } `, - errors: [ - { - messageId: 'unexpectedAny', - line: 3, - column: 29, - }, - ], - }, - { - code: 'class Foo extends Bar {}', - errors: [ - { - messageId: 'unexpectedAny', - line: 1, - column: 15, - suggestions: [ - { - messageId: 'suggestUnknown', - output: 'class Foo extends Bar {}', - }, - { - messageId: 'suggestNever', - output: 'class Foo extends Bar {}', - }, - ], - }, - { - messageId: 'unexpectedAny', - line: 1, - column: 32, - suggestions: [ - { - messageId: 'suggestUnknown', - output: 'class Foo extends Bar {}', - }, - { - messageId: 'suggestNever', - output: 'class Foo extends Bar {}', - }, - ], - }, - ], - }, - { - code: 'abstract class Foo extends Bar {}', - errors: [ - { - messageId: 'unexpectedAny', - line: 1, - column: 24, - suggestions: [ - { - messageId: 'suggestUnknown', - output: 'abstract class Foo extends Bar {}', - }, - { - messageId: 'suggestNever', - output: 'abstract class Foo extends Bar {}', - }, - ], - }, - { - messageId: 'unexpectedAny', - line: 1, - column: 41, - suggestions: [ - { - messageId: 'suggestUnknown', - output: 'abstract class Foo extends Bar {}', - }, - { - messageId: 'suggestNever', - output: 'abstract class Foo extends Bar {}', - }, - ], - }, - ], - }, - { - code: 'abstract class Foo implements Bar, Baz {}', - errors: [ - { - messageId: 'unexpectedAny', - line: 1, - column: 24, - suggestions: [ - { - messageId: 'suggestUnknown', - output: - 'abstract class Foo implements Bar, Baz {}', - }, - { - messageId: 'suggestNever', - output: - 'abstract class Foo implements Bar, Baz {}', - }, - ], - }, - { - messageId: 'unexpectedAny', - line: 1, - column: 44, - suggestions: [ - { - messageId: 'suggestUnknown', - output: - 'abstract class Foo implements Bar, Baz {}', - }, - { - messageId: 'suggestNever', - output: - 'abstract class Foo implements Bar, Baz {}', - }, - ], - }, - { - messageId: 'unexpectedAny', - line: 1, - column: 54, - suggestions: [ - { - messageId: 'suggestUnknown', - output: - 'abstract class Foo implements Bar, Baz {}', - }, - { - messageId: 'suggestNever', - output: - 'abstract class Foo implements Bar, Baz {}', - }, - ], - }, - ], - }, - { - code: 'new Foo()', - errors: [ - { - messageId: 'unexpectedAny', - line: 1, - column: 9, - }, - ], - }, - { - code: 'Foo()', - errors: [ - { - messageId: 'unexpectedAny', - line: 1, - column: 5, - }, - ], - }, - { - // https://github.com/typescript-eslint/typescript-eslint/issues/64 - code: ` + errors: [ + { + messageId: 'unexpectedAny', + line: 3, + column: 29, + }, + ], + }, + { + code: 'class Foo extends Bar {}', + errors: [ + { + messageId: 'unexpectedAny', + line: 1, + column: 15, + suggestions: [ + { + messageId: 'suggestUnknown', + output: 'class Foo extends Bar {}', + }, + { + messageId: 'suggestNever', + output: 'class Foo extends Bar {}', + }, + ], + }, + { + messageId: 'unexpectedAny', + line: 1, + column: 32, + suggestions: [ + { + messageId: 'suggestUnknown', + output: 'class Foo extends Bar {}', + }, + { + messageId: 'suggestNever', + output: 'class Foo extends Bar {}', + }, + ], + }, + ], + }, + { + code: 'abstract class Foo extends Bar {}', + errors: [ + { + messageId: 'unexpectedAny', + line: 1, + column: 24, + suggestions: [ + { + messageId: 'suggestUnknown', + output: 'abstract class Foo extends Bar {}', + }, + { + messageId: 'suggestNever', + output: 'abstract class Foo extends Bar {}', + }, + ], + }, + { + messageId: 'unexpectedAny', + line: 1, + column: 41, + suggestions: [ + { + messageId: 'suggestUnknown', + output: 'abstract class Foo extends Bar {}', + }, + { + messageId: 'suggestNever', + output: 'abstract class Foo extends Bar {}', + }, + ], + }, + ], + }, + { + code: 'abstract class Foo implements Bar, Baz {}', + errors: [ + { + messageId: 'unexpectedAny', + line: 1, + column: 24, + suggestions: [ + { + messageId: 'suggestUnknown', + output: + 'abstract class Foo implements Bar, Baz {}', + }, + { + messageId: 'suggestNever', + output: + 'abstract class Foo implements Bar, Baz {}', + }, + ], + }, + { + messageId: 'unexpectedAny', + line: 1, + column: 44, + suggestions: [ + { + messageId: 'suggestUnknown', + output: + 'abstract class Foo implements Bar, Baz {}', + }, + { + messageId: 'suggestNever', + output: + 'abstract class Foo implements Bar, Baz {}', + }, + ], + }, + { + messageId: 'unexpectedAny', + line: 1, + column: 54, + suggestions: [ + { + messageId: 'suggestUnknown', + output: + 'abstract class Foo implements Bar, Baz {}', + }, + { + messageId: 'suggestNever', + output: + 'abstract class Foo implements Bar, Baz {}', + }, + ], + }, + ], + }, + { + code: 'new Foo()', + errors: [ + { + messageId: 'unexpectedAny', + line: 1, + column: 9, + }, + ], + }, + { + code: 'Foo()', + errors: [ + { + messageId: 'unexpectedAny', + line: 1, + column: 5, + }, + ], + }, + { + // https://github.com/typescript-eslint/typescript-eslint/issues/64 + code: ` function test>() {} const test = >() => {}; `.trimRight(), - errors: [ - { - messageId: 'unexpectedAny', - line: 2, - column: 33, - suggestions: [ - { - messageId: 'suggestUnknown', - output: ` + errors: [ + { + messageId: 'unexpectedAny', + line: 2, + column: 33, + suggestions: [ + { + messageId: 'suggestUnknown', + output: ` function test>() {} const test = >() => {}; `.trimRight(), - }, - { - messageId: 'suggestNever', - output: ` + }, + { + messageId: 'suggestNever', + output: ` function test>() {} const test = >() => {}; `.trimRight(), - }, - ], - }, - { - messageId: 'unexpectedAny', - line: 3, - column: 33, - suggestions: [ - { - messageId: 'suggestUnknown', - output: ` + }, + ], + }, + { + messageId: 'unexpectedAny', + line: 3, + column: 33, + suggestions: [ + { + messageId: 'suggestUnknown', + output: ` function test>() {} const test = >() => {}; `.trimRight(), - }, - { - messageId: 'suggestNever', - output: ` + }, + { + messageId: 'suggestNever', + output: ` function test>() {} const test = >() => {}; `.trimRight(), - }, - ], - }, - ], - }, - { - // https://github.com/eslint/typescript-eslint-parser/issues/397 - code: ` + }, + ], + }, + ], + }, + { + // https://github.com/eslint/typescript-eslint-parser/issues/397 + code: ` function foo(a: number, ...rest: any[]): void { return; } `, - errors: [ - { - messageId: 'unexpectedAny', - line: 2, - column: 42, - }, - ], - }, - { - code: 'type Any = any;', - options: [{ ignoreRestArgs: true }], - errors: [ - { - messageId: 'unexpectedAny', - line: 1, - column: 12, - }, - ], - }, - { - code: 'function foo5(...args: any) {}', - options: [{ ignoreRestArgs: true }], - errors: [ - { - messageId: 'unexpectedAny', - line: 1, - column: 24, - }, - ], - }, - { - code: 'const bar5 = function (...args: any) {}', - options: [{ ignoreRestArgs: true }], - errors: [ - { - messageId: 'unexpectedAny', - line: 1, - column: 33, - }, - ], - }, - { - code: 'const baz5 = (...args: any) => {}', - options: [{ ignoreRestArgs: true }], - errors: [ - { - messageId: 'unexpectedAny', - line: 1, - column: 24, - }, - ], - }, - { - code: 'interface Qux5 { (...args: any): void; }', - options: [{ ignoreRestArgs: true }], - errors: [ - { - messageId: 'unexpectedAny', - line: 1, - column: 28, - }, - ], - }, - { - code: 'function quux5(fn: (...args: any) => void): void {}', - options: [{ ignoreRestArgs: true }], - errors: [ - { - messageId: 'unexpectedAny', - line: 1, - column: 30, - }, - ], - }, - { - code: 'function quuz5(): ((...args: any) => void) {}', - options: [{ ignoreRestArgs: true }], - errors: [ - { - messageId: 'unexpectedAny', - line: 1, - column: 30, - }, - ], - }, - { - code: 'type Fred5 = (...args: any) => void;', - options: [{ ignoreRestArgs: true }], - errors: [ - { - messageId: 'unexpectedAny', - line: 1, - column: 24, - }, - ], - }, - { - code: 'type Corge5 = new (...args: any) => void;', - options: [{ ignoreRestArgs: true }], - errors: [ - { - messageId: 'unexpectedAny', - line: 1, - column: 29, - }, - ], - }, - { - code: 'interface Grault5 { new (...args: any): void; }', - options: [{ ignoreRestArgs: true }], - errors: [ - { - messageId: 'unexpectedAny', - line: 1, - column: 35, - }, - ], - }, - { - code: 'interface Garply5 { f(...args: any): void; }', - options: [{ ignoreRestArgs: true }], - errors: [ - { - messageId: 'unexpectedAny', - line: 1, - column: 32, - }, - ], - }, - { - code: 'declare function waldo5(...args: any): void;', - options: [{ ignoreRestArgs: true }], - errors: [ - { - messageId: 'unexpectedAny', - line: 1, - column: 34, - }, - ], - }, - ] as InvalidTestCase[]).reduce((acc, testCase) => { + errors: [ + { + messageId: 'unexpectedAny', + line: 2, + column: 42, + }, + ], + }, + { + code: 'type Any = any;', + options: [{ ignoreRestArgs: true }], + errors: [ + { + messageId: 'unexpectedAny', + line: 1, + column: 12, + }, + ], + }, + { + code: 'function foo5(...args: any) {}', + options: [{ ignoreRestArgs: true }], + errors: [ + { + messageId: 'unexpectedAny', + line: 1, + column: 24, + }, + ], + }, + { + code: 'const bar5 = function (...args: any) {}', + options: [{ ignoreRestArgs: true }], + errors: [ + { + messageId: 'unexpectedAny', + line: 1, + column: 33, + }, + ], + }, + { + code: 'const baz5 = (...args: any) => {}', + options: [{ ignoreRestArgs: true }], + errors: [ + { + messageId: 'unexpectedAny', + line: 1, + column: 24, + }, + ], + }, + { + code: 'interface Qux5 { (...args: any): void; }', + options: [{ ignoreRestArgs: true }], + errors: [ + { + messageId: 'unexpectedAny', + line: 1, + column: 28, + }, + ], + }, + { + code: 'function quux5(fn: (...args: any) => void): void {}', + options: [{ ignoreRestArgs: true }], + errors: [ + { + messageId: 'unexpectedAny', + line: 1, + column: 30, + }, + ], + }, + { + code: 'function quuz5(): ((...args: any) => void) {}', + options: [{ ignoreRestArgs: true }], + errors: [ + { + messageId: 'unexpectedAny', + line: 1, + column: 30, + }, + ], + }, + { + code: 'type Fred5 = (...args: any) => void;', + options: [{ ignoreRestArgs: true }], + errors: [ + { + messageId: 'unexpectedAny', + line: 1, + column: 24, + }, + ], + }, + { + code: 'type Corge5 = new (...args: any) => void;', + options: [{ ignoreRestArgs: true }], + errors: [ + { + messageId: 'unexpectedAny', + line: 1, + column: 29, + }, + ], + }, + { + code: 'interface Grault5 { new (...args: any): void; }', + options: [{ ignoreRestArgs: true }], + errors: [ + { + messageId: 'unexpectedAny', + line: 1, + column: 35, + }, + ], + }, + { + code: 'interface Garply5 { f(...args: any): void; }', + options: [{ ignoreRestArgs: true }], + errors: [ + { + messageId: 'unexpectedAny', + line: 1, + column: 32, + }, + ], + }, + { + code: 'declare function waldo5(...args: any): void;', + options: [{ ignoreRestArgs: true }], + errors: [ + { + messageId: 'unexpectedAny', + line: 1, + column: 34, + }, + ], + }, + ] as InvalidTestCase[] + ).reduce((acc, testCase) => { const suggestions = (code: string): SuggestionOutput[] => [ { messageId: 'suggestUnknown', diff --git a/packages/eslint-plugin/tests/rules/no-inferrable-types.test.ts b/packages/eslint-plugin/tests/rules/no-inferrable-types.test.ts index 0f7bb141f1b6..fc216c6c4764 100644 --- a/packages/eslint-plugin/tests/rules/no-inferrable-types.test.ts +++ b/packages/eslint-plugin/tests/rules/no-inferrable-types.test.ts @@ -72,27 +72,25 @@ const testCases = [ const validTestCases = flatten( testCases.map(c => c.code.map(code => `const a = ${code}`)), ); -const invalidTestCases: TSESLint.InvalidTestCase< - MessageIds, - Options ->[] = flatten( - testCases.map(cas => - cas.code.map(code => ({ - code: `const a: ${cas.type} = ${code}`, - output: `const a = ${code}`, - errors: [ - { - messageId: 'noInferrableType', - data: { - type: cas.type, +const invalidTestCases: TSESLint.InvalidTestCase[] = + flatten( + testCases.map(cas => + cas.code.map(code => ({ + code: `const a: ${cas.type} = ${code}`, + output: `const a = ${code}`, + errors: [ + { + messageId: 'noInferrableType', + data: { + type: cas.type, + }, + line: 1, + column: 7, }, - line: 1, - column: 7, - }, - ], - })), - ), -); + ], + })), + ), + ); const ruleTester = new RuleTester({ parser: '@typescript-eslint/parser', @@ -124,18 +122,15 @@ class Foo { "const fn = function (a: any = 5, b: any = true, c: any = 'foo') {};", { - code: - "const fn = (a: number = 5, b: boolean = true, c: string = 'foo') => {};", + code: "const fn = (a: number = 5, b: boolean = true, c: string = 'foo') => {};", options: [{ ignoreParameters: true }], }, { - code: - "function fn(a: number = 5, b: boolean = true, c: string = 'foo') {}", + code: "function fn(a: number = 5, b: boolean = true, c: string = 'foo') {}", options: [{ ignoreParameters: true }], }, { - code: - "const fn = function (a: number = 5, b: boolean = true, c: string = 'foo') {};", + code: "const fn = function (a: number = 5, b: boolean = true, c: string = 'foo') {};", options: [{ ignoreParameters: true }], }, { @@ -163,8 +158,7 @@ class Foo { ...invalidTestCases, { - code: - "const fn = (a: number = 5, b: boolean = true, c: string = 'foo') => {};", + code: "const fn = (a: number = 5, b: boolean = true, c: string = 'foo') => {};", output: "const fn = (a = 5, b = true, c = 'foo') => {};", options: [ { diff --git a/packages/eslint-plugin/tests/rules/no-invalid-void-type.test.ts b/packages/eslint-plugin/tests/rules/no-invalid-void-type.test.ts index 56df4f47ab6f..0141da093b50 100644 --- a/packages/eslint-plugin/tests/rules/no-invalid-void-type.test.ts +++ b/packages/eslint-plugin/tests/rules/no-invalid-void-type.test.ts @@ -202,8 +202,7 @@ ruleTester.run('allowInGenericTypeArguments: true', rule, { ], }, { - code: - 'declare function functionDeclaration(arg: T): void;', + code: 'declare function functionDeclaration(arg: T): void;', errors: [ { messageId: 'invalidVoidNotReturnOrGeneric', @@ -223,8 +222,7 @@ ruleTester.run('allowInGenericTypeArguments: true', rule, { ], }, { - code: - 'declare function functionDeclaration2(arg: T): void;', + code: 'declare function functionDeclaration2(arg: T): void;', errors: [ { messageId: 'invalidVoidNotReturnOrGeneric', diff --git a/packages/eslint-plugin/tests/rules/no-loss-of-precision.test.ts b/packages/eslint-plugin/tests/rules/no-loss-of-precision.test.ts index f2405bacdb6b..cd783915b4dc 100644 --- a/packages/eslint-plugin/tests/rules/no-loss-of-precision.test.ts +++ b/packages/eslint-plugin/tests/rules/no-loss-of-precision.test.ts @@ -28,8 +28,7 @@ ruleTester.run('no-loss-of-precision', rule, { errors: [{ messageId: 'noLossOfPrecision' }], }, { - code: - 'const x = 0b100_000_000_000_000_000_000_000_000_000_000_000_000_000_000_000_000_001;', + code: 'const x = 0b100_000_000_000_000_000_000_000_000_000_000_000_000_000_000_000_000_001;', errors: [{ messageId: 'noLossOfPrecision' }], }, ], diff --git a/packages/eslint-plugin/tests/rules/no-type-alias.test.ts b/packages/eslint-plugin/tests/rules/no-type-alias.test.ts index ab4e3dd49191..1f44675a8515 100644 --- a/packages/eslint-plugin/tests/rules/no-type-alias.test.ts +++ b/packages/eslint-plugin/tests/rules/no-type-alias.test.ts @@ -430,8 +430,7 @@ type KeyNames = keyof typeof SCALARS; options: [{ allowTupleTypes: 'in-intersections' }], }, { - code: - 'type Foo = ([string] & [number, number]) | [number, number, number];', + code: 'type Foo = ([string] & [number, number]) | [number, number, number];', options: [{ allowTupleTypes: 'in-unions-and-intersections' }], }, { @@ -451,8 +450,7 @@ type KeyNames = keyof typeof SCALARS; options: [{ allowTupleTypes: 'in-intersections' }], }, { - code: - 'type Foo = ([string] & [number, number]) | readonly [number, number, number];', + code: 'type Foo = ([string] & [number, number]) | readonly [number, number, number];', options: [{ allowTupleTypes: 'in-unions-and-intersections' }], }, { @@ -472,8 +470,7 @@ type KeyNames = keyof typeof SCALARS; options: [{ allowTupleTypes: 'in-intersections' }], }, { - code: - 'type Foo = ([string] & [number, number]) | keyof [number, number, number];', + code: 'type Foo = ([string] & [number, number]) | keyof [number, number, number];', options: [{ allowTupleTypes: 'in-unions-and-intersections' }], }, { diff --git a/packages/eslint-plugin/tests/rules/no-unused-vars-experimental.test.ts b/packages/eslint-plugin/tests/rules/no-unused-vars-experimental.test.ts index c093498200cf..67b9d22c86f5 100644 --- a/packages/eslint-plugin/tests/rules/no-unused-vars-experimental.test.ts +++ b/packages/eslint-plugin/tests/rules/no-unused-vars-experimental.test.ts @@ -21,7 +21,7 @@ const ruleTester = new RuleTester({ const hasExport = /^export/m; // const hasImport = /^import .+? from ['"]/m; function makeExternalModule< - T extends ValidTestCase | InvalidTestCase + T extends ValidTestCase | InvalidTestCase, >(tests: T[]): T[] { return tests.map(t => { if (!hasExport.test(t.code)) { diff --git a/packages/eslint-plugin/tests/rules/object-curly-spacing.test.ts b/packages/eslint-plugin/tests/rules/object-curly-spacing.test.ts index ecde35b775ff..7b917a673086 100644 --- a/packages/eslint-plugin/tests/rules/object-curly-spacing.test.ts +++ b/packages/eslint-plugin/tests/rules/object-curly-spacing.test.ts @@ -581,8 +581,7 @@ ruleTester.run('object-curly-spacing', rule, { code: "const x:{// line-comment\n[k in 'union']: number\n}", }, { - code: - "const x:{/* inline-comment */[k in 'union']: number/* inline-comment */}", + code: "const x:{/* inline-comment */[k in 'union']: number/* inline-comment */}", }, { code: "const x:{\n[k in 'union']: number\n}", @@ -687,8 +686,7 @@ ruleTester.run('object-curly-spacing', rule, { options: ['always'], }, { - code: - "const x:{ /* inline-comment */ [k in 'union']: number /* inline-comment */ }", + code: "const x:{ /* inline-comment */ [k in 'union']: number /* inline-comment */ }", options: ['always'], }, { diff --git a/packages/eslint-plugin/tests/rules/padding-line-between-statements.test.ts b/packages/eslint-plugin/tests/rules/padding-line-between-statements.test.ts index 0d12ca705361..d018f189929f 100644 --- a/packages/eslint-plugin/tests/rules/padding-line-between-statements.test.ts +++ b/packages/eslint-plugin/tests/rules/padding-line-between-statements.test.ts @@ -522,15 +522,13 @@ ruleTester.run('padding-line-between-statements', rule, { ], }, { - code: - '() => {\n\tsomeArray.forEach(x => doSomething(x));\n\treturn theThing;\n}', + code: '() => {\n\tsomeArray.forEach(x => doSomething(x));\n\treturn theThing;\n}', options: [ { blankLine: 'always', prev: 'multiline-expression', next: 'return' }, ], }, { - code: - '() => {\n\tsomeArray.forEach(\n\t\tx => doSomething(x)\n\t);\n\n\treturn theThing;\n}', + code: '() => {\n\tsomeArray.forEach(\n\t\tx => doSomething(x)\n\t);\n\n\treturn theThing;\n}', options: [ { blankLine: 'always', prev: 'multiline-expression', next: 'return' }, ], @@ -1445,8 +1443,7 @@ ruleTester.run('padding-line-between-statements', rule, { ], }, { - code: - "var greet = 'hello';\n/* block comment\nblock comment */\nconsole.log(greet);", + code: "var greet = 'hello';\n/* block comment\nblock comment */\nconsole.log(greet);", options: [ { blankLine: 'never', prev: ['const', 'let', 'var'], next: '*' }, { @@ -1470,8 +1467,7 @@ ruleTester.run('padding-line-between-statements', rule, { ], }, { - code: - "var greet = 'hello';\n/* block comment\nblock comment */\n\nconsole.log(greet);", + code: "var greet = 'hello';\n/* block comment\nblock comment */\n\nconsole.log(greet);", options: [ { blankLine: 'always', prev: ['const', 'let', 'var'], next: '*' }, { @@ -1482,8 +1478,7 @@ ruleTester.run('padding-line-between-statements', rule, { ], }, { - code: - "var greet = 'hello';\n// next-line comment\n// second-line comment\n\nconsole.log(greet);", + code: "var greet = 'hello';\n// next-line comment\n// second-line comment\n\nconsole.log(greet);", options: [ { blankLine: 'always', prev: ['const', 'let', 'var'], next: '*' }, { @@ -1496,8 +1491,7 @@ ruleTester.run('padding-line-between-statements', rule, { // should allow comments on the next line followed by no blank in "never" mode { - code: - "var greet = 'hello';\n// next-line comment\n// second-line comment\nconsole.log(greet);", + code: "var greet = 'hello';\n// next-line comment\n// second-line comment\nconsole.log(greet);", options: [ { blankLine: 'never', prev: ['const', 'let', 'var'], next: '*' }, { @@ -1508,8 +1502,7 @@ ruleTester.run('padding-line-between-statements', rule, { ], }, { - code: - "var greet = 'hello';\n// next-line comment\n/* block comment\nblock comment */\nconsole.log(greet);", + code: "var greet = 'hello';\n// next-line comment\n/* block comment\nblock comment */\nconsole.log(greet);", options: [ { blankLine: 'never', prev: ['const', 'let', 'var'], next: '*' }, { @@ -1533,8 +1526,7 @@ ruleTester.run('padding-line-between-statements', rule, { ], }, { - code: - "var greet = 'hello';\nvar name = 'world';\nconsole.log(greet, name);", + code: "var greet = 'hello';\nvar name = 'world';\nconsole.log(greet, name);", options: [ { blankLine: 'never', prev: ['const', 'let', 'var'], next: '*' }, { @@ -1545,8 +1537,7 @@ ruleTester.run('padding-line-between-statements', rule, { ], }, { - code: - "var greet = 'hello';\nvar name = 'world';\n\nconsole.log(greet, name);", + code: "var greet = 'hello';\nvar name = 'world';\n\nconsole.log(greet, name);", options: [ { blankLine: 'always', prev: ['const', 'let', 'var'], next: '*' }, { @@ -1559,8 +1550,7 @@ ruleTester.run('padding-line-between-statements', rule, { // should allow a comment directly between `var` statements { - code: - "var greet = 'hello';\n// inline comment\nvar name = 'world';\n\nconsole.log(greet, name);", + code: "var greet = 'hello';\n// inline comment\nvar name = 'world';\n\nconsole.log(greet, name);", options: [ { blankLine: 'always', prev: ['const', 'let', 'var'], next: '*' }, { @@ -1571,8 +1561,7 @@ ruleTester.run('padding-line-between-statements', rule, { ], }, { - code: - "var greet = 'hello';\n/* block comment\nblock comment */\nvar name = 'world';\n\nconsole.log(greet, name);", + code: "var greet = 'hello';\n/* block comment\nblock comment */\nvar name = 'world';\n\nconsole.log(greet, name);", options: [ { blankLine: 'always', prev: ['const', 'let', 'var'], next: '*' }, { @@ -1583,8 +1572,7 @@ ruleTester.run('padding-line-between-statements', rule, { ], }, { - code: - "var greet = 'hello';\n// inline comment\nvar name = 'world';\nconsole.log(greet, name);", + code: "var greet = 'hello';\n// inline comment\nvar name = 'world';\nconsole.log(greet, name);", options: [ { blankLine: 'never', prev: ['const', 'let', 'var'], next: '*' }, { @@ -1595,8 +1583,7 @@ ruleTester.run('padding-line-between-statements', rule, { ], }, { - code: - "var greet = 'hello';\n/* block comment\nblock comment */\nvar name = 'world';\nconsole.log(greet, name);", + code: "var greet = 'hello';\n/* block comment\nblock comment */\nvar name = 'world';\nconsole.log(greet, name);", options: [ { blankLine: 'never', prev: ['const', 'let', 'var'], next: '*' }, { @@ -1644,8 +1631,7 @@ ruleTester.run('padding-line-between-statements', rule, { // should handle single `var` statement with multi-line declaration { - code: - "var greet = 'hello',\nname = 'world';\n\nconsole.log(greet, name);", + code: "var greet = 'hello',\nname = 'world';\n\nconsole.log(greet, name);", options: [ { blankLine: 'always', prev: ['const', 'let', 'var'], next: '*' }, { @@ -1667,8 +1653,7 @@ ruleTester.run('padding-line-between-statements', rule, { ], }, { - code: - "var greet = 'hello', // inline comment\nname = 'world'; // inline comment\n\nconsole.log(greet, name);", + code: "var greet = 'hello', // inline comment\nname = 'world'; // inline comment\n\nconsole.log(greet, name);", options: [ { blankLine: 'always', prev: ['const', 'let', 'var'], next: '*' }, { @@ -1679,8 +1664,7 @@ ruleTester.run('padding-line-between-statements', rule, { ], }, { - code: - "var greet = 'hello', // inline comment\nname = 'world'; // inline comment\nconsole.log(greet, name);", + code: "var greet = 'hello', // inline comment\nname = 'world'; // inline comment\nconsole.log(greet, name);", options: [ { blankLine: 'never', prev: ['const', 'let', 'var'], next: '*' }, { @@ -1691,8 +1675,7 @@ ruleTester.run('padding-line-between-statements', rule, { ], }, { - code: - "var greet = 'hello',\nname = 'world';\n// next-line comment\nconsole.log(greet);", + code: "var greet = 'hello',\nname = 'world';\n// next-line comment\nconsole.log(greet);", options: [ { blankLine: 'never', prev: ['const', 'let', 'var'], next: '*' }, { @@ -1703,8 +1686,7 @@ ruleTester.run('padding-line-between-statements', rule, { ], }, { - code: - "var greet = 'hello',\nname = 'world';\n/* block comment\nblock comment */\nconsole.log(greet);", + code: "var greet = 'hello',\nname = 'world';\n/* block comment\nblock comment */\nconsole.log(greet);", options: [ { blankLine: 'never', prev: ['const', 'let', 'var'], next: '*' }, { @@ -1765,8 +1747,7 @@ ruleTester.run('padding-line-between-statements', rule, { // should handle a mix of `var`, `let`, or `const` { - code: - "let greet = 'hello';\nvar name = 'world';\n\nconsole.log(greet, name);", + code: "let greet = 'hello';\nvar name = 'world';\n\nconsole.log(greet, name);", options: [ { blankLine: 'always', prev: ['const', 'let', 'var'], next: '*' }, { @@ -1777,8 +1758,7 @@ ruleTester.run('padding-line-between-statements', rule, { ], }, { - code: - "const greet = 'hello';\nvar name = 'world';\n\nconsole.log(greet, name);", + code: "const greet = 'hello';\nvar name = 'world';\n\nconsole.log(greet, name);", options: [ { blankLine: 'always', prev: ['const', 'let', 'var'], next: '*' }, { @@ -1789,8 +1769,7 @@ ruleTester.run('padding-line-between-statements', rule, { ], }, { - code: - "let greet = 'hello';\nconst name = 'world';\n\nconsole.log(greet, name);", + code: "let greet = 'hello';\nconst name = 'world';\n\nconsole.log(greet, name);", options: [ { blankLine: 'always', prev: ['const', 'let', 'var'], next: '*' }, { @@ -1989,8 +1968,7 @@ ruleTester.run('padding-line-between-statements', rule, { ], }, { - code: - "function example() {\nvar greet = 'hello';\nconsole.log(greet);\n}", + code: "function example() {\nvar greet = 'hello';\nconsole.log(greet);\n}", options: [ { blankLine: 'never', prev: ['const', 'let', 'var'], next: '*' }, { @@ -2023,8 +2001,7 @@ ruleTester.run('padding-line-between-statements', rule, { ], }, { - code: - "var f = function() {\nvar greet = 'hello';\nconsole.log(greet);\n};", + code: "var f = function() {\nvar greet = 'hello';\nconsole.log(greet);\n};", options: [ { blankLine: 'never', prev: ['const', 'let', 'var'], next: '*' }, { @@ -2292,33 +2269,27 @@ var a = 1 options: [{ blankLine: 'always', prev: '*', next: 'return' }], }, { - code: - 'function a() {\nif (b) {\nreturn b;\n} else if (c) {\nreturn c;\n}\n}', + code: 'function a() {\nif (b) {\nreturn b;\n} else if (c) {\nreturn c;\n}\n}', options: [{ blankLine: 'always', prev: '*', next: 'return' }], }, { - code: - 'function a() {\nif (b) {\nreturn b;\n} else if (c) {\nreturn c;\n} else {\nreturn d;\n}\n}', + code: 'function a() {\nif (b) {\nreturn b;\n} else if (c) {\nreturn c;\n} else {\nreturn d;\n}\n}', options: [{ blankLine: 'always', prev: '*', next: 'return' }], }, { - code: - 'function a() {\nif (b) {\nreturn b;\n} else if (c) {\nreturn c;\n} else {\nreturn d;\n}\n\nreturn a;\n}', + code: 'function a() {\nif (b) {\nreturn b;\n} else if (c) {\nreturn c;\n} else {\nreturn d;\n}\n\nreturn a;\n}', options: [{ blankLine: 'always', prev: '*', next: 'return' }], }, { - code: - 'function a() {\nif (b) return b;\nelse if (c) return c;\nelse return d;\n}', + code: 'function a() {\nif (b) return b;\nelse if (c) return c;\nelse return d;\n}', options: [{ blankLine: 'always', prev: '*', next: 'return' }], }, { - code: - 'function a() {\nif (b) return b;\nelse if (c) return c;\nelse {\nreturn d;\n}\n}', + code: 'function a() {\nif (b) return b;\nelse if (c) return c;\nelse {\nreturn d;\n}\n}', options: [{ blankLine: 'always', prev: '*', next: 'return' }], }, { - code: - 'function a() {\nif (b) return b;\nelse if (c) return c;\nelse {\ne();\n\nreturn d;\n}\n}', + code: 'function a() {\nif (b) return b;\nelse if (c) return c;\nelse {\ne();\n\nreturn d;\n}\n}', options: [{ blankLine: 'always', prev: '*', next: 'return' }], }, { @@ -2342,8 +2313,7 @@ var a = 1 options: [{ blankLine: 'always', prev: '*', next: 'return' }], }, { - code: - 'function a() {\nvar c;\nwhile (b) {\n c = d; //comment\n}\n\nreturn c;\n}', + code: 'function a() {\nvar c;\nwhile (b) {\n c = d; //comment\n}\n\nreturn c;\n}', options: [{ blankLine: 'always', prev: '*', next: 'return' }], }, { @@ -2387,8 +2357,7 @@ var a = 1 options: [{ blankLine: 'always', prev: '*', next: 'return' }], }, { - code: - 'function a() {\nfor (var b; b < c; b++) {\nif (d) {\nbreak; //comment\n}\n\nreturn;\n}\n}', + code: 'function a() {\nfor (var b; b < c; b++) {\nif (d) {\nbreak; //comment\n}\n\nreturn;\n}\n}', options: [{ blankLine: 'always', prev: '*', next: 'return' }], }, { @@ -2456,13 +2425,11 @@ var a = 1 options: [{ blankLine: 'always', prev: '*', next: 'return' }], }, { - code: - 'function a() {\n/*comment\ncomment*/\n//comment\nif (b) return;\n}', + code: 'function a() {\n/*comment\ncomment*/\n//comment\nif (b) return;\n}', options: [{ blankLine: 'always', prev: '*', next: 'return' }], }, { - code: - 'function a() {\n/*comment\ncomment*/\n//comment\nif (b) {\nc();\n\nreturn b;\n} else {\n//comment\nreturn d;\n}\n\n/*multi-line\ncomment*/\nreturn e;\n}', + code: 'function a() {\n/*comment\ncomment*/\n//comment\nif (b) {\nc();\n\nreturn b;\n} else {\n//comment\nreturn d;\n}\n\n/*multi-line\ncomment*/\nreturn e;\n}', options: [{ blankLine: 'always', prev: '*', next: 'return' }], }, { @@ -2474,13 +2441,11 @@ var a = 1 options: [{ blankLine: 'always', prev: '*', next: 'return' }], }, { - code: - 'function a() {\nif (b) { return; } /*multi-line\ncomment*/\n\nreturn c;\n}', + code: 'function a() {\nif (b) { return; } /*multi-line\ncomment*/\n\nreturn c;\n}', options: [{ blankLine: 'always', prev: '*', next: 'return' }], }, { - code: - 'function a() {\nif (b) { return; }\n\n/*multi-line\ncomment*/ return c;\n}', + code: 'function a() {\nif (b) { return; }\n\n/*multi-line\ncomment*/ return c;\n}', options: [{ blankLine: 'always', prev: '*', next: 'return' }], }, { @@ -2698,15 +2663,13 @@ var a = 1 parserOptions: { ecmaFeatures: { jsx: true } }, }, { - code: - 'var i = 0;\nwhile (i < 100) {\nif(i % 2 === 0) {continue;}\n++i;\n}', + code: 'var i = 0;\nwhile (i < 100) {\nif(i % 2 === 0) {continue;}\n++i;\n}', options: [ { blankLine: 'always', prev: 'multiline-block-like', next: '*' }, ], }, { - code: - 'var i = 0;\nwhile (i < 100) {\nif(i % 2 === 0) {if(i === 4) {continue;}}\n++i;\n}', + code: 'var i = 0;\nwhile (i < 100) {\nif(i % 2 === 0) {if(i === 4) {continue;}}\n++i;\n}', options: [ { blankLine: 'always', prev: 'multiline-block-like', next: '*' }, ], @@ -3293,8 +3256,7 @@ var a = 1 errors: [{ messageId: 'expectedBlankLine' }], }, { - code: - '() => {\n\tsomeArray.forEach(\n\t\tx => doSomething(x)\n\t);\n\treturn theThing;\n}', + code: '() => {\n\tsomeArray.forEach(\n\t\tx => doSomething(x)\n\t);\n\treturn theThing;\n}', output: '() => {\n\tsomeArray.forEach(\n\t\tx => doSomething(x)\n\t);\n\n\treturn theThing;\n}', options: [ @@ -4144,8 +4106,7 @@ var a = 1 errors: [{ messageId: 'expectedBlankLine' }], }, { - code: - "var greet = 'hello';\nvar name = 'world';\nconsole.log(greet, name);", + code: "var greet = 'hello';\nvar name = 'world';\nconsole.log(greet, name);", output: "var greet = 'hello';\nvar name = 'world';\n\nconsole.log(greet, name);", options: [ @@ -4213,8 +4174,7 @@ var a = 1 errors: [{ messageId: 'expectedBlankLine' }], }, { - code: - "function example() {\nvar greet = 'hello';\nconsole.log(greet);\n}", + code: "function example() {\nvar greet = 'hello';\nconsole.log(greet);\n}", output: "function example() {\nvar greet = 'hello';\n\nconsole.log(greet);\n}", options: [ @@ -4228,8 +4188,7 @@ var a = 1 errors: [{ messageId: 'expectedBlankLine' }], }, { - code: - "var f = function() {\nvar greet = 'hello';\nconsole.log(greet);\n};", + code: "var f = function() {\nvar greet = 'hello';\nconsole.log(greet);\n};", output: "var f = function() {\nvar greet = 'hello';\n\nconsole.log(greet);\n};", options: [ @@ -4323,8 +4282,7 @@ var a = 1 errors: [{ messageId: 'unexpectedBlankLine' }], }, { - code: - "var greet = 'hello';\nvar name = 'world';\n\nconsole.log(greet, name);", + code: "var greet = 'hello';\nvar name = 'world';\n\nconsole.log(greet, name);", output: "var greet = 'hello';\nvar name = 'world';\nconsole.log(greet, name);", options: [ @@ -4351,8 +4309,7 @@ var a = 1 errors: [{ messageId: 'unexpectedBlankLine' }], }, { - code: - "var greet = 'hello',\nname = 'world';\n\nconsole.log(greet, name);", + code: "var greet = 'hello',\nname = 'world';\n\nconsole.log(greet, name);", output: "var greet = 'hello',\nname = 'world';\nconsole.log(greet, name);", options: [ @@ -4366,8 +4323,7 @@ var a = 1 errors: [{ messageId: 'unexpectedBlankLine' }], }, { - code: - "var greet = 'hello', // inline comment\nname = 'world'; // inline comment\n\nconsole.log(greet, name);", + code: "var greet = 'hello', // inline comment\nname = 'world'; // inline comment\n\nconsole.log(greet, name);", output: "var greet = 'hello', // inline comment\nname = 'world'; // inline comment\nconsole.log(greet, name);", options: [ @@ -4423,8 +4379,7 @@ var a = 1 errors: [{ messageId: 'expectedBlankLine' }], }, { - code: - "var greet = 'hello';\n/* block comment\nblock comment */\nconsole.log(greet);", + code: "var greet = 'hello';\n/* block comment\nblock comment */\nconsole.log(greet);", output: "var greet = 'hello';\n\n/* block comment\nblock comment */\nconsole.log(greet);", options: [ @@ -4438,8 +4393,7 @@ var a = 1 errors: [{ messageId: 'expectedBlankLine' }], }, { - code: - "var greet = 'hello',\nname = 'world';\n// next-line comment\nconsole.log(greet);", + code: "var greet = 'hello',\nname = 'world';\n// next-line comment\nconsole.log(greet);", output: "var greet = 'hello',\nname = 'world';\n\n// next-line comment\nconsole.log(greet);", options: [ @@ -4453,8 +4407,7 @@ var a = 1 errors: [{ messageId: 'expectedBlankLine' }], }, { - code: - "var greet = 'hello',\nname = 'world';\n/* block comment\nblock comment */\nconsole.log(greet);", + code: "var greet = 'hello',\nname = 'world';\n/* block comment\nblock comment */\nconsole.log(greet);", output: "var greet = 'hello',\nname = 'world';\n\n/* block comment\nblock comment */\nconsole.log(greet);", options: [ @@ -4468,8 +4421,7 @@ var a = 1 errors: [{ messageId: 'expectedBlankLine' }], }, { - code: - "var greet = 'hello';\n// next-line comment\n// second-line comment\nconsole.log(greet);", + code: "var greet = 'hello';\n// next-line comment\n// second-line comment\nconsole.log(greet);", output: "var greet = 'hello';\n\n// next-line comment\n// second-line comment\nconsole.log(greet);", options: [ @@ -4483,8 +4435,7 @@ var a = 1 errors: [{ messageId: 'expectedBlankLine' }], }, { - code: - "var greet = 'hello';\n// next-line comment\n/* block comment\nblock comment */\nconsole.log(greet);", + code: "var greet = 'hello';\n// next-line comment\n/* block comment\nblock comment */\nconsole.log(greet);", output: "var greet = 'hello';\n\n// next-line comment\n/* block comment\nblock comment */\nconsole.log(greet);", options: [ @@ -4557,16 +4508,14 @@ var a = 1 errors: [{ messageId: 'expectedBlankLine' }], }, { - code: - 'function a() {\nif (b) return b;\nelse if (c) return c;\nelse {\ne();\nreturn d;\n}\n}', + code: 'function a() {\nif (b) return b;\nelse if (c) return c;\nelse {\ne();\nreturn d;\n}\n}', output: 'function a() {\nif (b) return b;\nelse if (c) return c;\nelse {\ne();\n\nreturn d;\n}\n}', options: [{ blankLine: 'always', prev: '*', next: 'return' }], errors: [{ messageId: 'expectedBlankLine' }], }, { - code: - 'function a() {\nif (b) return b;\nelse if (c) return c;\nelse {\ne(); return d;\n}\n}', + code: 'function a() {\nif (b) return b;\nelse if (c) return c;\nelse {\ne(); return d;\n}\n}', output: 'function a() {\nif (b) return b;\nelse if (c) return c;\nelse {\ne();\n\n return d;\n}\n}', options: [{ blankLine: 'always', prev: '*', next: 'return' }], @@ -4610,8 +4559,7 @@ var a = 1 errors: [{ messageId: 'expectedBlankLine' }], }, { - code: - 'function a() {\n/*comment\ncomment*/\nif (b) {\nc();\nreturn b;\n} else {\n//comment\n\nreturn d;\n}\n/*multi-line\ncomment*/\nreturn e;\n}', + code: 'function a() {\n/*comment\ncomment*/\nif (b) {\nc();\nreturn b;\n} else {\n//comment\n\nreturn d;\n}\n/*multi-line\ncomment*/\nreturn e;\n}', output: 'function a() {\n/*comment\ncomment*/\nif (b) {\nc();\n\nreturn b;\n} else {\n//comment\n\nreturn d;\n}\n\n/*multi-line\ncomment*/\nreturn e;\n}', options: [{ blankLine: 'always', prev: '*', next: 'return' }], @@ -4627,24 +4575,21 @@ var a = 1 errors: [{ messageId: 'expectedBlankLine' }], }, { - code: - 'function a() {\nif (b) { return; } /*multi-line\ncomment*/\nreturn c;\n}', + code: 'function a() {\nif (b) { return; } /*multi-line\ncomment*/\nreturn c;\n}', output: 'function a() {\nif (b) { return; } /*multi-line\ncomment*/\n\nreturn c;\n}', options: [{ blankLine: 'always', prev: '*', next: 'return' }], errors: [{ messageId: 'expectedBlankLine' }], }, { - code: - 'function a() {\nif (b) { return; }\n/*multi-line\ncomment*/ return c;\n}', + code: 'function a() {\nif (b) { return; }\n/*multi-line\ncomment*/ return c;\n}', output: 'function a() {\nif (b) { return; }\n\n/*multi-line\ncomment*/ return c;\n}', options: [{ blankLine: 'always', prev: '*', next: 'return' }], errors: [{ messageId: 'expectedBlankLine' }], }, { - code: - 'function a() {\nif (b) { return; } /*multi-line\ncomment*/ return c;\n}', + code: 'function a() {\nif (b) { return; } /*multi-line\ncomment*/ return c;\n}', output: 'function a() {\nif (b) { return; } /*multi-line\ncomment*/\n\n return c;\n}', options: [{ blankLine: 'always', prev: '*', next: 'return' }], @@ -4677,16 +4622,14 @@ var a = 1 errors: [{ messageId: 'expectedBlankLine' }], }, { - code: - 'function a() {\nvar c;\nwhile (b) {\n c = d; //comment\n}\nreturn c;\n}', + code: 'function a() {\nvar c;\nwhile (b) {\n c = d; //comment\n}\nreturn c;\n}', output: 'function a() {\nvar c;\nwhile (b) {\n c = d; //comment\n}\n\nreturn c;\n}', options: [{ blankLine: 'always', prev: '*', next: 'return' }], errors: [{ messageId: 'expectedBlankLine' }], }, { - code: - 'function a() {\nfor (var b; b < c; b++) {\nif (d) {\nbreak; //comment\n}\nreturn;\n}\n}', + code: 'function a() {\nfor (var b; b < c; b++) {\nif (d) {\nbreak; //comment\n}\nreturn;\n}\n}', output: 'function a() {\nfor (var b; b < c; b++) {\nif (d) {\nbreak; //comment\n}\n\nreturn;\n}\n}', options: [{ blankLine: 'always', prev: '*', next: 'return' }], @@ -4837,8 +4780,7 @@ var a = 1 errors: [{ messageId: 'unexpectedBlankLine' }], }, { - code: - 'function x() { var a = true;\n\nfor (var i = 0; i < 10; i++) { a = !a; }; }', + code: 'function x() { var a = true;\n\nfor (var i = 0; i < 10; i++) { a = !a; }; }', output: 'function x() { var a = true;\nfor (var i = 0; i < 10; i++) { a = !a; }; }', options: [ @@ -4851,8 +4793,7 @@ var a = 1 errors: [{ messageId: 'unexpectedBlankLine' }], }, { - code: - 'function x() { var y = true;\n\nswitch ("Oranges") { case "Oranges": y = !y;\n\nbreak;\n\ncase "Apples": y = !y;\n\nbreak; default: y = !y; } }', + code: 'function x() { var y = true;\n\nswitch ("Oranges") { case "Oranges": y = !y;\n\nbreak;\n\ncase "Apples": y = !y;\n\nbreak; default: y = !y; } }', output: 'function x() { var y = true;\nswitch ("Oranges") { case "Oranges": y = !y;\nbreak;\ncase "Apples": y = !y;\nbreak; default: y = !y; } }', options: [ @@ -4870,8 +4811,7 @@ var a = 1 ], }, { - code: - 'function x() {try { var a;\n\nthrow 0; } catch (e) { var b = 0;\n\nthrow e; } }', + code: 'function x() {try { var a;\n\nthrow 0; } catch (e) { var b = 0;\n\nthrow e; } }', output: 'function x() {try { var a;\nthrow 0; } catch (e) { var b = 0;\nthrow e; } }', options: [ @@ -4887,8 +4827,7 @@ var a = 1 ], }, { - code: - 'function x(a) { var b = 0;\n\nif (!a) { return false; };\n\nfor (var i = 0; i < b; i++) { if (!a[i]) return false; }\n\nreturn true; }', + code: 'function x(a) { var b = 0;\n\nif (!a) { return false; };\n\nfor (var i = 0; i < b; i++) { if (!a[i]) return false; }\n\nreturn true; }', output: 'function x(a) { var b = 0;\nif (!a) { return false; };\nfor (var i = 0; i < b; i++) { if (!a[i]) return false; }\nreturn true; }', options: [ @@ -4991,8 +4930,7 @@ var a = 1 errors: [{ messageId: 'expectedBlankLine' }], }, { - code: - 'function x() { var a = true; for (var i = 0; i < 10; i++) { a = !a; }; }', + code: 'function x() { var a = true; for (var i = 0; i < 10; i++) { a = !a; }; }', output: 'function x() { var a = true;\n\n for (var i = 0; i < 10; i++) { a = !a; }; }', options: [ @@ -5015,8 +4953,7 @@ var a = 1 errors: [{ messageId: 'expectedBlankLine' }], }, { - code: - 'function x() { var y = true; switch ("Oranges") { case "Oranges": y = !y; break; case "Apples": y = !y; break; default: y = !y; } }', + code: 'function x() { var y = true; switch ("Oranges") { case "Oranges": y = !y; break; case "Apples": y = !y; break; default: y = !y; } }', output: 'function x() { var y = true;\n\n switch ("Oranges") { case "Oranges": y = !y;\n\n break;\n\n case "Apples": y = !y;\n\n break;\n\n default: y = !y; } }', options: [ @@ -5067,8 +5004,7 @@ var a = 1 errors: [{ messageId: 'expectedBlankLine' }], }, { - code: - 'function x() {try { var a; throw 0; } catch (e) { var b = 0; throw e; } }', + code: 'function x() {try { var a; throw 0; } catch (e) { var b = 0; throw e; } }', output: 'function x() {try { var a;\n\n throw 0; } catch (e) { var b = 0;\n\n throw e; } }', options: [ @@ -5094,8 +5030,7 @@ var a = 1 ], }, { - code: - 'function x(a) { var b = 0; if (!a) { return false; }; for (var i = 0; i < b; i++) { if (!a[i]) return false; } return true; }', + code: 'function x(a) { var b = 0; if (!a) { return false; }; for (var i = 0; i < b; i++) { if (!a[i]) return false; } return true; }', output: 'function x(a) { var b = 0;\n\n if (!a) { return false; };\n\n for (var i = 0; i < b; i++) { if (!a[i]) return false; }\n\n return true; }', options: [ diff --git a/packages/eslint-plugin/tests/rules/prefer-optional-chain.test.ts b/packages/eslint-plugin/tests/rules/prefer-optional-chain.test.ts index 80340828a748..feb7f9bd524d 100644 --- a/packages/eslint-plugin/tests/rules/prefer-optional-chain.test.ts +++ b/packages/eslint-plugin/tests/rules/prefer-optional-chain.test.ts @@ -70,8 +70,7 @@ const baseCases = [ output: 'foo?.bar?.baz?.buzz()', }, { - code: - 'foo && foo.bar && foo.bar.baz && foo.bar.baz.buzz && foo.bar.baz.buzz()', + code: 'foo && foo.bar && foo.bar.baz && foo.bar.baz.buzz && foo.bar.baz.buzz()', output: 'foo?.bar?.baz?.buzz?.()', }, { @@ -94,8 +93,7 @@ const baseCases = [ }, { // case with a call expr inside the chain for some inefficient reason - code: - 'foo && foo.bar() && foo.bar().baz && foo.bar().baz.buzz && foo.bar().baz.buzz()', + code: 'foo && foo.bar() && foo.bar().baz && foo.bar().baz.buzz && foo.bar().baz.buzz()', output: 'foo?.bar()?.baz?.buzz?.()', }, // chained calls with element access @@ -104,14 +102,12 @@ const baseCases = [ output: 'foo?.bar?.baz?.[buzz]()', }, { - code: - 'foo && foo.bar && foo.bar.baz && foo.bar.baz[buzz] && foo.bar.baz[buzz]()', + code: 'foo && foo.bar && foo.bar.baz && foo.bar.baz[buzz] && foo.bar.baz[buzz]()', output: 'foo?.bar?.baz?.[buzz]?.()', }, // (partially) pre-optional chained { - code: - 'foo && foo?.bar && foo?.bar.baz && foo?.bar.baz[buzz] && foo?.bar.baz[buzz]()', + code: 'foo && foo?.bar && foo?.bar.baz && foo?.bar.baz[buzz] && foo?.bar.baz[buzz]()', output: 'foo?.bar?.baz?.[buzz]?.()', }, { @@ -254,8 +250,7 @@ ruleTester.run('prefer-optional-chain', rule, { }, // case with inconsistent checks { - code: - 'foo && foo.bar != null && foo.bar.baz !== undefined && foo.bar.baz.buzz;', + code: 'foo && foo.bar != null && foo.bar.baz !== undefined && foo.bar.baz.buzz;', output: null, errors: [ { @@ -468,8 +463,7 @@ foo?.bar(/* comment */a, }, // using suggestion instead of autofix { - code: - 'foo && foo.bar != null && foo.bar.baz !== undefined && foo.bar.baz.buzz;', + code: 'foo && foo.bar != null && foo.bar.baz !== undefined && foo.bar.baz.buzz;', output: null, errors: [ { diff --git a/packages/eslint-plugin/tests/rules/prefer-string-starts-ends-with.test.ts b/packages/eslint-plugin/tests/rules/prefer-string-starts-ends-with.test.ts index 0cef89740d56..aefb7cd8d2d9 100644 --- a/packages/eslint-plugin/tests/rules/prefer-string-starts-ends-with.test.ts +++ b/packages/eslint-plugin/tests/rules/prefer-string-starts-ends-with.test.ts @@ -1069,13 +1069,13 @@ function addOptional>( ): TSESLint.ValidTestCase[]; function addOptional< TMessageIds extends string, - TOptions extends Readonly + TOptions extends Readonly, >( cases: TSESLint.InvalidTestCase[], ): TSESLint.InvalidTestCase[]; function addOptional< TMessageIds extends string, - TOptions extends Readonly + TOptions extends Readonly, >( cases: (Case | string)[], ): Case[] { diff --git a/packages/eslint-plugin/tests/rules/quotes.test.ts b/packages/eslint-plugin/tests/rules/quotes.test.ts index 847e27e81f52..ec757dda3e54 100644 --- a/packages/eslint-plugin/tests/rules/quotes.test.ts +++ b/packages/eslint-plugin/tests/rules/quotes.test.ts @@ -290,18 +290,15 @@ ruleTester.run('quotes', rule, { options: ['backtick'], }, { - code: - 'function foo() { "use strict"; "use strong"; "use asm"; var foo = `backtick`; }', + code: 'function foo() { "use strict"; "use strong"; "use asm"; var foo = `backtick`; }', options: ['backtick'], }, { - code: - "(function() { 'use strict'; 'use strong'; 'use asm'; var foo = `backtick`; })();", + code: "(function() { 'use strict'; 'use strong'; 'use asm'; var foo = `backtick`; })();", options: ['backtick'], }, { - code: - '(() => { "use strict"; "use strong"; "use asm"; var foo = `backtick`; })();', + code: '(() => { "use strict"; "use strong"; "use asm"; var foo = `backtick`; })();', options: ['backtick'], }, diff --git a/packages/eslint-plugin/tests/util/isUnsafeAssignment.test.ts b/packages/eslint-plugin/tests/util/isUnsafeAssignment.test.ts index ece61a1c149c..1d4946a964de 100644 --- a/packages/eslint-plugin/tests/util/isUnsafeAssignment.test.ts +++ b/packages/eslint-plugin/tests/util/isUnsafeAssignment.test.ts @@ -8,9 +8,7 @@ import { isUnsafeAssignment } from '../../src/util/types'; describe('isUnsafeAssignment', () => { const rootDir = getFixturesRootDir(); - function getTypes( - code: string, - ): { + function getTypes(code: string): { sender: ts.Type; senderNode: TSESTree.Node; receiver: ts.Type; diff --git a/packages/eslint-plugin/tools/generate-configs.ts b/packages/eslint-plugin/tools/generate-configs.ts index e78808aa4b1d..ed84f286496b 100644 --- a/packages/eslint-plugin/tools/generate-configs.ts +++ b/packages/eslint-plugin/tools/generate-configs.ts @@ -49,10 +49,8 @@ const BASE_RULES_TO_BE_OVERRIDDEN = new Map( ); const EXTENDS = ['./configs/base', './configs/eslint-recommended']; -const ruleEntries: [ - string, - TSESLint.RuleModule, -][] = Object.entries(rules).sort((a, b) => a[0].localeCompare(b[0])); +const ruleEntries: [string, TSESLint.RuleModule][] = + Object.entries(rules).sort((a, b) => a[0].localeCompare(b[0])); /** * Helper function reduces records to key - value pairs. diff --git a/packages/experimental-utils/src/ast-utils/eslint-utils/predicates.ts b/packages/experimental-utils/src/ast-utils/eslint-utils/predicates.ts index 9bbd3091d994..ad89e4730fcc 100644 --- a/packages/experimental-utils/src/ast-utils/eslint-utils/predicates.ts +++ b/packages/experimental-utils/src/ast-utils/eslint-utils/predicates.ts @@ -9,48 +9,67 @@ type IsNotSpecificTokenFunction = ( token: TSESTree.Token, ) => token is Exclude; -type PunctuatorTokenWithValue< - Value extends string -> = TSESTree.PunctuatorToken & { value: Value }; -type IsPunctuatorTokenWithValueFunction< - Value extends string -> = IsSpecificTokenFunction>; -type IsNotPunctuatorTokenWithValueFunction< - Value extends string -> = IsNotSpecificTokenFunction>; +type PunctuatorTokenWithValue = + TSESTree.PunctuatorToken & { value: Value }; +type IsPunctuatorTokenWithValueFunction = + IsSpecificTokenFunction>; +type IsNotPunctuatorTokenWithValueFunction = + IsNotSpecificTokenFunction>; -const isArrowToken = eslintUtils.isArrowToken as IsPunctuatorTokenWithValueFunction<'=>'>; -const isNotArrowToken = eslintUtils.isNotArrowToken as IsNotPunctuatorTokenWithValueFunction<'=>'>; +const isArrowToken = + eslintUtils.isArrowToken as IsPunctuatorTokenWithValueFunction<'=>'>; +const isNotArrowToken = + eslintUtils.isNotArrowToken as IsNotPunctuatorTokenWithValueFunction<'=>'>; -const isClosingBraceToken = eslintUtils.isClosingBraceToken as IsPunctuatorTokenWithValueFunction<'}'>; -const isNotClosingBraceToken = eslintUtils.isNotClosingBraceToken as IsNotPunctuatorTokenWithValueFunction<'}'>; +const isClosingBraceToken = + eslintUtils.isClosingBraceToken as IsPunctuatorTokenWithValueFunction<'}'>; +const isNotClosingBraceToken = + eslintUtils.isNotClosingBraceToken as IsNotPunctuatorTokenWithValueFunction<'}'>; -const isClosingBracketToken = eslintUtils.isClosingBracketToken as IsPunctuatorTokenWithValueFunction<']'>; -const isNotClosingBracketToken = eslintUtils.isNotClosingBracketToken as IsNotPunctuatorTokenWithValueFunction<']'>; +const isClosingBracketToken = + eslintUtils.isClosingBracketToken as IsPunctuatorTokenWithValueFunction<']'>; +const isNotClosingBracketToken = + eslintUtils.isNotClosingBracketToken as IsNotPunctuatorTokenWithValueFunction<']'>; -const isClosingParenToken = eslintUtils.isClosingParenToken as IsPunctuatorTokenWithValueFunction<')'>; -const isNotClosingParenToken = eslintUtils.isNotClosingParenToken as IsNotPunctuatorTokenWithValueFunction<')'>; +const isClosingParenToken = + eslintUtils.isClosingParenToken as IsPunctuatorTokenWithValueFunction<')'>; +const isNotClosingParenToken = + eslintUtils.isNotClosingParenToken as IsNotPunctuatorTokenWithValueFunction<')'>; -const isColonToken = eslintUtils.isColonToken as IsPunctuatorTokenWithValueFunction<':'>; -const isNotColonToken = eslintUtils.isNotColonToken as IsNotPunctuatorTokenWithValueFunction<':'>; +const isColonToken = + eslintUtils.isColonToken as IsPunctuatorTokenWithValueFunction<':'>; +const isNotColonToken = + eslintUtils.isNotColonToken as IsNotPunctuatorTokenWithValueFunction<':'>; -const isCommaToken = eslintUtils.isCommaToken as IsPunctuatorTokenWithValueFunction<','>; -const isNotCommaToken = eslintUtils.isNotCommaToken as IsNotPunctuatorTokenWithValueFunction<','>; +const isCommaToken = + eslintUtils.isCommaToken as IsPunctuatorTokenWithValueFunction<','>; +const isNotCommaToken = + eslintUtils.isNotCommaToken as IsNotPunctuatorTokenWithValueFunction<','>; -const isCommentToken = eslintUtils.isCommentToken as IsSpecificTokenFunction; -const isNotCommentToken = eslintUtils.isNotCommentToken as IsNotSpecificTokenFunction; +const isCommentToken = + eslintUtils.isCommentToken as IsSpecificTokenFunction; +const isNotCommentToken = + eslintUtils.isNotCommentToken as IsNotSpecificTokenFunction; -const isOpeningBraceToken = eslintUtils.isOpeningBraceToken as IsPunctuatorTokenWithValueFunction<'{'>; -const isNotOpeningBraceToken = eslintUtils.isNotOpeningBraceToken as IsNotPunctuatorTokenWithValueFunction<'{'>; +const isOpeningBraceToken = + eslintUtils.isOpeningBraceToken as IsPunctuatorTokenWithValueFunction<'{'>; +const isNotOpeningBraceToken = + eslintUtils.isNotOpeningBraceToken as IsNotPunctuatorTokenWithValueFunction<'{'>; -const isOpeningBracketToken = eslintUtils.isOpeningBracketToken as IsPunctuatorTokenWithValueFunction<'['>; -const isNotOpeningBracketToken = eslintUtils.isNotOpeningBracketToken as IsNotPunctuatorTokenWithValueFunction<'['>; +const isOpeningBracketToken = + eslintUtils.isOpeningBracketToken as IsPunctuatorTokenWithValueFunction<'['>; +const isNotOpeningBracketToken = + eslintUtils.isNotOpeningBracketToken as IsNotPunctuatorTokenWithValueFunction<'['>; -const isOpeningParenToken = eslintUtils.isOpeningParenToken as IsPunctuatorTokenWithValueFunction<'('>; -const isNotOpeningParenToken = eslintUtils.isNotOpeningParenToken as IsNotPunctuatorTokenWithValueFunction<'('>; +const isOpeningParenToken = + eslintUtils.isOpeningParenToken as IsPunctuatorTokenWithValueFunction<'('>; +const isNotOpeningParenToken = + eslintUtils.isNotOpeningParenToken as IsNotPunctuatorTokenWithValueFunction<'('>; -const isSemicolonToken = eslintUtils.isSemicolonToken as IsPunctuatorTokenWithValueFunction<';'>; -const isNotSemicolonToken = eslintUtils.isNotSemicolonToken as IsNotPunctuatorTokenWithValueFunction<';'>; +const isSemicolonToken = + eslintUtils.isSemicolonToken as IsPunctuatorTokenWithValueFunction<';'>; +const isNotSemicolonToken = + eslintUtils.isNotSemicolonToken as IsNotPunctuatorTokenWithValueFunction<';'>; export { isArrowToken, diff --git a/packages/experimental-utils/src/ast-utils/predicates.ts b/packages/experimental-utils/src/ast-utils/predicates.ts index 03c371afd559..7a7bcf520b1a 100644 --- a/packages/experimental-utils/src/ast-utils/predicates.ts +++ b/packages/experimental-utils/src/ast-utils/predicates.ts @@ -1,8 +1,11 @@ import { AST_NODE_TYPES, AST_TOKEN_TYPES, TSESTree } from '../ts-estree'; -const isNodeOfType = (nodeType: NodeType) => ( - node: TSESTree.Node | null | undefined, -): node is TSESTree.Node & { type: NodeType } => node?.type === nodeType; +const isNodeOfType = + (nodeType: NodeType) => + ( + node: TSESTree.Node | null | undefined, + ): node is TSESTree.Node & { type: NodeType } => + node?.type === nodeType; function isOptionalChainPunctuator( token: TSESTree.Token, diff --git a/packages/experimental-utils/src/eslint-utils/RuleCreator.ts b/packages/experimental-utils/src/eslint-utils/RuleCreator.ts index ca1cfb3302e2..f02b7589862a 100644 --- a/packages/experimental-utils/src/eslint-utils/RuleCreator.ts +++ b/packages/experimental-utils/src/eslint-utils/RuleCreator.ts @@ -19,7 +19,7 @@ function RuleCreator(urlCreator: (ruleName: string) => string) { return function createRule< TOptions extends readonly unknown[], TMessageIds extends string, - TRuleListener extends RuleListener = RuleListener + TRuleListener extends RuleListener = RuleListener, >({ name, meta, diff --git a/packages/experimental-utils/src/eslint-utils/batchedSingleLineTests.ts b/packages/experimental-utils/src/eslint-utils/batchedSingleLineTests.ts index 6ed25e4a8ac4..29a56671a351 100644 --- a/packages/experimental-utils/src/eslint-utils/batchedSingleLineTests.ts +++ b/packages/experimental-utils/src/eslint-utils/batchedSingleLineTests.ts @@ -24,13 +24,13 @@ function batchedSingleLineTests>( */ function batchedSingleLineTests< TMessageIds extends string, - TOptions extends Readonly + TOptions extends Readonly, >( test: InvalidTestCase, ): InvalidTestCase[]; function batchedSingleLineTests< TMessageIds extends string, - TOptions extends Readonly + TOptions extends Readonly, >( options: ValidTestCase | InvalidTestCase, ): (ValidTestCase | InvalidTestCase)[] { diff --git a/packages/experimental-utils/src/eslint-utils/getParserServices.ts b/packages/experimental-utils/src/eslint-utils/getParserServices.ts index 925d49761522..27ad579272b9 100644 --- a/packages/experimental-utils/src/eslint-utils/getParserServices.ts +++ b/packages/experimental-utils/src/eslint-utils/getParserServices.ts @@ -9,7 +9,7 @@ const ERROR_MESSAGE = */ function getParserServices< TMessageIds extends string, - TOptions extends readonly unknown[] + TOptions extends readonly unknown[], >( context: Readonly>, allowWithoutFullTypeInformation = false, diff --git a/packages/experimental-utils/src/ts-eslint-scope/Definition.ts b/packages/experimental-utils/src/ts-eslint-scope/Definition.ts index 15c69bbf86c3..1999c4f4863e 100644 --- a/packages/experimental-utils/src/ts-eslint-scope/Definition.ts +++ b/packages/experimental-utils/src/ts-eslint-scope/Definition.ts @@ -27,13 +27,14 @@ const Definition = ESLintDefinition as DefinitionConstructor; // eslint-disable-next-line @typescript-eslint/no-empty-interface interface ParameterDefinition extends Definition {} -const ParameterDefinition = ESLintParameterDefinition as DefinitionConstructor & { - new ( - name: TSESTree.Node, - node: TSESTree.Node, - index?: number | null, - rest?: boolean, - ): ParameterDefinition; -}; +const ParameterDefinition = + ESLintParameterDefinition as DefinitionConstructor & { + new ( + name: TSESTree.Node, + node: TSESTree.Node, + index?: number | null, + rest?: boolean, + ): ParameterDefinition; + }; export { Definition, ParameterDefinition }; diff --git a/packages/experimental-utils/src/ts-eslint-scope/Scope.ts b/packages/experimental-utils/src/ts-eslint-scope/Scope.ts index 49f1e11c7955..9b2c711d2dc2 100644 --- a/packages/experimental-utils/src/ts-eslint-scope/Scope.ts +++ b/packages/experimental-utils/src/ts-eslint-scope/Scope.ts @@ -142,8 +142,9 @@ const ModuleScope = ESLintModuleScope as ScopeConstructor & ScopeChildConstructorWithUpperScope; interface FunctionExpressionNameScope extends Scope {} -const FunctionExpressionNameScope = ESLintFunctionExpressionNameScope as ScopeConstructor & - ScopeChildConstructorWithUpperScope; +const FunctionExpressionNameScope = + ESLintFunctionExpressionNameScope as ScopeConstructor & + ScopeChildConstructorWithUpperScope; interface CatchScope extends Scope {} const CatchScope = ESLintCatchScope as ScopeConstructor & diff --git a/packages/experimental-utils/src/ts-eslint/CLIEngine.ts b/packages/experimental-utils/src/ts-eslint/CLIEngine.ts index fec56c17b410..dfcc2347a5e8 100644 --- a/packages/experimental-utils/src/ts-eslint/CLIEngine.ts +++ b/packages/experimental-utils/src/ts-eslint/CLIEngine.ts @@ -71,7 +71,7 @@ declare class CLIEngineBase { TMessageIds extends string = string, TOptions extends readonly unknown[] = unknown[], // for extending base rules - TRuleListener extends RuleListener = RuleListener + TRuleListener extends RuleListener = RuleListener, >(): Map>; //////////////////// diff --git a/packages/experimental-utils/src/ts-eslint/Rule.ts b/packages/experimental-utils/src/ts-eslint/Rule.ts index a112a87c62f1..24b8fd4fa114 100644 --- a/packages/experimental-utils/src/ts-eslint/Rule.ts +++ b/packages/experimental-utils/src/ts-eslint/Rule.ts @@ -115,9 +115,8 @@ interface RuleFixer { type ReportFixFunction = ( fixer: RuleFixer, ) => null | RuleFix | readonly RuleFix[] | IterableIterator; -type ReportSuggestionArray< - TMessageIds extends string -> = ReportDescriptorBase[]; +type ReportSuggestionArray = + ReportDescriptorBase[]; interface ReportDescriptorBase { /** @@ -162,10 +161,9 @@ interface ReportDescriptorLocOnly { */ loc: Readonly | Readonly; } -type ReportDescriptor< - TMessageIds extends string -> = ReportDescriptorWithSuggestion & - (ReportDescriptorNodeOptionalLoc | ReportDescriptorLocOnly); +type ReportDescriptor = + ReportDescriptorWithSuggestion & + (ReportDescriptorNodeOptionalLoc | ReportDescriptorLocOnly); /** * Plugins can add their settings using declaration @@ -177,7 +175,7 @@ interface SharedConfigurationSettings { interface RuleContext< TMessageIds extends string, - TOptions extends readonly unknown[] + TOptions extends readonly unknown[], > { /** * The rule ID. @@ -426,7 +424,7 @@ interface RuleModule< TMessageIds extends string, TOptions extends readonly unknown[], // for extending base rules - TRuleListener extends RuleListener = RuleListener + TRuleListener extends RuleListener = RuleListener, > { /** * Metadata about the rule @@ -444,7 +442,7 @@ type RuleCreateFunction< TMessageIds extends string = never, TOptions extends readonly unknown[] = unknown[], // for extending base rules - TRuleListener extends RuleListener = RuleListener + TRuleListener extends RuleListener = RuleListener, > = (context: Readonly>) => TRuleListener; export { diff --git a/packages/experimental-utils/src/ts-eslint/RuleTester.ts b/packages/experimental-utils/src/ts-eslint/RuleTester.ts index a60de90388aa..9a255b242070 100644 --- a/packages/experimental-utils/src/ts-eslint/RuleTester.ts +++ b/packages/experimental-utils/src/ts-eslint/RuleTester.ts @@ -68,7 +68,7 @@ interface SuggestionOutput { interface InvalidTestCase< TMessageIds extends string, - TOptions extends Readonly + TOptions extends Readonly, > extends ValidTestCase { /** * Expected errors. @@ -120,7 +120,7 @@ interface TestCaseError { interface RunTests< TMessageIds extends string, - TOptions extends Readonly + TOptions extends Readonly, > { // RuleTester.run also accepts strings for valid cases readonly valid: readonly (ValidTestCase | string)[]; diff --git a/packages/experimental-utils/src/ts-eslint/Scope.ts b/packages/experimental-utils/src/ts-eslint/Scope.ts index 6907e2290fd9..bc3db012216c 100644 --- a/packages/experimental-utils/src/ts-eslint/Scope.ts +++ b/packages/experimental-utils/src/ts-eslint/Scope.ts @@ -19,7 +19,8 @@ namespace Scope { export type CatchClauseDefinition = scopeManager.CatchClauseDefinition; export type ClassNameDefinition = scopeManager.ClassNameDefinition; export type FunctionNameDefinition = scopeManager.FunctionNameDefinition; - export type ImplicitGlobalVariableDefinition = scopeManager.ImplicitGlobalVariableDefinition; + export type ImplicitGlobalVariableDefinition = + scopeManager.ImplicitGlobalVariableDefinition; export type ImportBindingDefinition = scopeManager.ImportBindingDefinition; export type ParameterDefinition = scopeManager.ParameterDefinition; export type TSEnumMemberDefinition = scopeManager.TSEnumMemberDefinition; @@ -34,7 +35,8 @@ namespace Scope { export type ClassScope = scopeManager.ClassScope; export type ConditionalTypeScope = scopeManager.ConditionalTypeScope; export type ForScope = scopeManager.ForScope; - export type FunctionExpressionNameScope = scopeManager.FunctionExpressionNameScope; + export type FunctionExpressionNameScope = + scopeManager.FunctionExpressionNameScope; export type FunctionScope = scopeManager.FunctionScope; export type FunctionTypeScope = scopeManager.FunctionTypeScope; export type GlobalScope = scopeManager.GlobalScope; diff --git a/packages/experimental-utils/src/ts-eslint/SourceCode.ts b/packages/experimental-utils/src/ts-eslint/SourceCode.ts index 7894a540ed80..582f643311ad 100644 --- a/packages/experimental-utils/src/ts-eslint/SourceCode.ts +++ b/packages/experimental-utils/src/ts-eslint/SourceCode.ts @@ -250,9 +250,7 @@ declare class SourceCodeBase extends TokenStore { * @param node The AST node to get the comments for. * @returns An object containing a leading and trailing array of comments indexed by their position. */ - getComments( - node: TSESTree.Node, - ): { + getComments(node: TSESTree.Node): { leading: TSESTree.Comment[]; trailing: TSESTree.Comment[]; }; diff --git a/packages/scope-manager/src/definition/DefinitionBase.ts b/packages/scope-manager/src/definition/DefinitionBase.ts index ed25a72293d1..7147ebc60edc 100644 --- a/packages/scope-manager/src/definition/DefinitionBase.ts +++ b/packages/scope-manager/src/definition/DefinitionBase.ts @@ -8,7 +8,7 @@ abstract class DefinitionBase< TType extends DefinitionType, TNode extends TSESTree.Node, TParent extends TSESTree.Node | null, - TName extends TSESTree.Node = TSESTree.BindingName + TName extends TSESTree.Node = TSESTree.BindingName, > { /** * A unique ID for this instance - primarily used to help debugging and testing diff --git a/packages/scope-manager/src/scope/ScopeBase.ts b/packages/scope-manager/src/scope/ScopeBase.ts index 602dd81a206a..c06a7002c48b 100644 --- a/packages/scope-manager/src/scope/ScopeBase.ts +++ b/packages/scope-manager/src/scope/ScopeBase.ts @@ -135,7 +135,7 @@ type AnyScope = ScopeBase; abstract class ScopeBase< TType extends ScopeType, TBlock extends TSESTree.Node, - TUpper extends Scope | null + TUpper extends Scope | null, > { /** * A unique ID for this instance - primarily used to help debugging and testing @@ -387,7 +387,7 @@ abstract class ScopeBase< } protected delegateToUpperScope(ref: Reference): void { - const upper = (this.upper as Scope) as AnyScope; + const upper = this.upper as Scope as AnyScope; if (upper?.leftToResolve) { upper.leftToResolve.push(ref); } diff --git a/packages/scope-manager/tests/eslint-scope/map-ecma-version.test.ts b/packages/scope-manager/tests/eslint-scope/map-ecma-version.test.ts index 3a5957b7003a..d8646fbb3539 100644 --- a/packages/scope-manager/tests/eslint-scope/map-ecma-version.test.ts +++ b/packages/scope-manager/tests/eslint-scope/map-ecma-version.test.ts @@ -33,7 +33,7 @@ describe('ecma version mapping', () => { }); }); -const fakeNode = ({} as unknown) as TSESTree.Node; +const fakeNode = {} as unknown as TSESTree.Node; function expectMapping(ecmaVersion: number | undefined, lib: Lib): void { (Referencer as jest.Mock).mockClear(); diff --git a/packages/scope-manager/tests/util/getSpecificNode.ts b/packages/scope-manager/tests/util/getSpecificNode.ts index d20ab14ff580..8f04f4a88b49 100644 --- a/packages/scope-manager/tests/util/getSpecificNode.ts +++ b/packages/scope-manager/tests/util/getSpecificNode.ts @@ -3,11 +3,11 @@ import { simpleTraverse } from '@typescript-eslint/typescript-estree'; function getSpecificNode< TSelector extends AST_NODE_TYPES, - TNode extends Extract + TNode extends Extract, >(ast: TSESTree.Node, selector: TSelector): TNode; function getSpecificNode< TSelector extends AST_NODE_TYPES, - TNode extends Extract + TNode extends Extract, >( ast: TSESTree.Node, selector: TSelector, @@ -16,7 +16,7 @@ function getSpecificNode< function getSpecificNode< TSelector extends AST_NODE_TYPES, TNode extends Extract, - TReturnType extends TSESTree.Node + TReturnType extends TSESTree.Node, >( ast: TSESTree.Node, selector: TSelector, diff --git a/packages/typescript-estree/src/convert.ts b/packages/typescript-estree/src/convert.ts index e08eabaef3ce..8170cedad3c2 100644 --- a/packages/typescript-estree/src/convert.ts +++ b/packages/typescript-estree/src/convert.ts @@ -635,9 +635,10 @@ export class Converter { } if (node.typeParameters) { - result.typeParameters = this.convertTSTypeParametersToTypeParametersDeclaration( - node.typeParameters, - ); + result.typeParameters = + this.convertTSTypeParametersToTypeParametersDeclaration( + node.typeParameters, + ); } const accessibility = getTSNodeAccessibility(node); @@ -931,9 +932,10 @@ export class Converter { // Process typeParameters if (node.typeParameters) { - result.typeParameters = this.convertTSTypeParametersToTypeParametersDeclaration( - node.typeParameters, - ); + result.typeParameters = + this.convertTSTypeParametersToTypeParametersDeclaration( + node.typeParameters, + ); } // check for exports @@ -1164,9 +1166,10 @@ export class Converter { // Process typeParameters if (node.typeParameters) { - method.typeParameters = this.convertTSTypeParametersToTypeParametersDeclaration( - node.typeParameters, - ); + method.typeParameters = + this.convertTSTypeParametersToTypeParametersDeclaration( + node.typeParameters, + ); this.fixParentLocation(method, method.typeParameters.range); } @@ -1272,9 +1275,10 @@ export class Converter { // Process typeParameters if (node.typeParameters) { - constructor.typeParameters = this.convertTSTypeParametersToTypeParametersDeclaration( - node.typeParameters, - ); + constructor.typeParameters = + this.convertTSTypeParametersToTypeParametersDeclaration( + node.typeParameters, + ); this.fixParentLocation(constructor, constructor.typeParameters.range); } @@ -1330,9 +1334,10 @@ export class Converter { // Process typeParameters if (node.typeParameters) { - result.typeParameters = this.convertTSTypeParametersToTypeParametersDeclaration( - node.typeParameters, - ); + result.typeParameters = + this.convertTSTypeParametersToTypeParametersDeclaration( + node.typeParameters, + ); } return result; } @@ -1428,9 +1433,10 @@ export class Converter { // Process typeParameters if (node.typeParameters) { - result.typeParameters = this.convertTSTypeParametersToTypeParametersDeclaration( - node.typeParameters, - ); + result.typeParameters = + this.convertTSTypeParametersToTypeParametersDeclaration( + node.typeParameters, + ); } return result; } @@ -1634,17 +1640,19 @@ export class Converter { } if (superClass.types[0]?.typeArguments) { - result.superTypeParameters = this.convertTypeArgumentsToTypeParameters( - superClass.types[0].typeArguments, - superClass.types[0], - ); + result.superTypeParameters = + this.convertTypeArgumentsToTypeParameters( + superClass.types[0].typeArguments, + superClass.types[0], + ); } } if (node.typeParameters) { - result.typeParameters = this.convertTSTypeParametersToTypeParametersDeclaration( - node.typeParameters, - ); + result.typeParameters = + this.convertTSTypeParametersToTypeParametersDeclaration( + node.typeParameters, + ); } if (implementsClause) { @@ -2406,9 +2414,10 @@ export class Converter { // Process typeParameters if (node.typeParameters) { - result.typeParameters = this.convertTSTypeParametersToTypeParametersDeclaration( - node.typeParameters, - ); + result.typeParameters = + this.convertTSTypeParametersToTypeParametersDeclaration( + node.typeParameters, + ); } // check for exports @@ -2480,9 +2489,10 @@ export class Converter { result.returnType = this.convertTypeAnnotation(node.type, node); } if (node.typeParameters) { - result.typeParameters = this.convertTSTypeParametersToTypeParametersDeclaration( - node.typeParameters, - ); + result.typeParameters = + this.convertTSTypeParametersToTypeParametersDeclaration( + node.typeParameters, + ); } return result; } @@ -2509,9 +2519,10 @@ export class Converter { } if (node.typeParameters) { - result.typeParameters = this.convertTSTypeParametersToTypeParametersDeclaration( - node.typeParameters, - ); + result.typeParameters = + this.convertTSTypeParametersToTypeParametersDeclaration( + node.typeParameters, + ); } return result; } @@ -2549,9 +2560,10 @@ export class Converter { }); if (node.typeParameters) { - result.typeParameters = this.convertTSTypeParametersToTypeParametersDeclaration( - node.typeParameters, - ); + result.typeParameters = + this.convertTSTypeParametersToTypeParametersDeclaration( + node.typeParameters, + ); } if (interfaceHeritageClauses.length > 0) { diff --git a/packages/typescript-estree/src/create-program/createWatchProgram.ts b/packages/typescript-estree/src/create-program/createWatchProgram.ts index 9081f5de9c06..2142065e47b0 100644 --- a/packages/typescript-estree/src/create-program/createWatchProgram.ts +++ b/packages/typescript-estree/src/create-program/createWatchProgram.ts @@ -395,9 +395,8 @@ function createWatchProgram( function hasTSConfigChanged(tsconfigPath: CanonicalPath): boolean { const stat = fs.statSync(tsconfigPath); const lastModifiedAt = stat.mtimeMs; - const cachedLastModifiedAt = tsconfigLastModifiedTimestampCache.get( - tsconfigPath, - ); + const cachedLastModifiedAt = + tsconfigLastModifiedTimestampCache.get(tsconfigPath); tsconfigLastModifiedTimestampCache.set(tsconfigPath, lastModifiedAt); diff --git a/packages/typescript-estree/src/parser-options.ts b/packages/typescript-estree/src/parser-options.ts index 0772edbf7adf..55f47ef9041d 100644 --- a/packages/typescript-estree/src/parser-options.ts +++ b/packages/typescript-estree/src/parser-options.ts @@ -217,7 +217,7 @@ export interface ParserWeakMap { } export interface ParserWeakMapESTreeToTSNode< - TKey extends TSESTree.Node = TSESTree.Node + TKey extends TSESTree.Node = TSESTree.Node, > { get(key: TKeyBase): TSESTreeToTSNode; has(key: unknown): boolean; diff --git a/packages/typescript-estree/tests/lib/parse.test.ts b/packages/typescript-estree/tests/lib/parse.test.ts index 3a061f6af41f..236dc6929ad0 100644 --- a/packages/typescript-estree/tests/lib/parse.test.ts +++ b/packages/typescript-estree/tests/lib/parse.test.ts @@ -93,7 +93,7 @@ describe('parseWithNodeMaps()', () => { describe('non string code', () => { // testing a non string code.. // eslint-disable-next-line @typescript-eslint/no-explicit-any - const code = (12345 as any) as string; + const code = 12345 as any as string; const config: TSESTreeOptions = { comment: true, tokens: true, @@ -495,27 +495,26 @@ describe('parseAndGenerateServices', () => { tsconfigRootDir: PROJECT_DIR, project: './tsconfig.json', }; - const testParse = ( - filePath: string, - extraFileExtensions: string[] = ['.vue'], - ) => (): void => { - try { - parser.parseAndGenerateServices(code, { - ...config, - extraFileExtensions, - filePath: join(PROJECT_DIR, filePath), - }); - } catch (error) { - /** - * Aligns paths between environments, node for windows uses `\`, for linux and mac uses `/` - */ - (error as Error).message = (error as Error).message.replace( - /\\(?!["])/gm, - '/', - ); - throw error; - } - }; + const testParse = + (filePath: string, extraFileExtensions: string[] = ['.vue']) => + (): void => { + try { + parser.parseAndGenerateServices(code, { + ...config, + extraFileExtensions, + filePath: join(PROJECT_DIR, filePath), + }); + } catch (error) { + /** + * Aligns paths between environments, node for windows uses `\`, for linux and mac uses `/` + */ + (error as Error).message = (error as Error).message.replace( + /\\(?!["])/gm, + '/', + ); + throw error; + } + }; describe('project includes', () => { it("doesn't error for matched files", () => { @@ -653,16 +652,18 @@ describe('parseAndGenerateServices', () => { project: './**/tsconfig.json', }; - const testParse = ( - filePath: 'ignoreme' | 'includeme', - projectFolderIgnoreList?: TSESTreeOptions['projectFolderIgnoreList'], - ) => (): void => { - parser.parseAndGenerateServices(code, { - ...config, - projectFolderIgnoreList, - filePath: join(PROJECT_DIR, filePath, './file.ts'), - }); - }; + const testParse = + ( + filePath: 'ignoreme' | 'includeme', + projectFolderIgnoreList?: TSESTreeOptions['projectFolderIgnoreList'], + ) => + (): void => { + parser.parseAndGenerateServices(code, { + ...config, + projectFolderIgnoreList, + filePath: join(PROJECT_DIR, filePath, './file.ts'), + }); + }; it('ignores nothing when given nothing', () => { expect(testParse('ignoreme')).not.toThrow(); diff --git a/packages/typescript-estree/tests/lib/semanticInfo-singleRun.test.ts b/packages/typescript-estree/tests/lib/semanticInfo-singleRun.test.ts index 5b94b1cbdcad..62d7c3a841c9 100644 --- a/packages/typescript-estree/tests/lib/semanticInfo-singleRun.test.ts +++ b/packages/typescript-estree/tests/lib/semanticInfo-singleRun.test.ts @@ -47,15 +47,15 @@ jest.mock('../../src/create-program/shared.ts', () => { jest.mock('../../src/create-program/useProvidedPrograms.ts', () => { return { ...jest.requireActual('../../src/create-program/useProvidedPrograms.ts'), - createProgramFromConfigFile: jest.fn().mockImplementation( - (configFile): MockProgramWithConfigFile => { + createProgramFromConfigFile: jest + .fn() + .mockImplementation((configFile): MockProgramWithConfigFile => { return { // So we can differentiate our mock return values based on which tsconfig this is __FROM_CONFIG_FILE__: configFile, ...mockProgram, }; - }, - ), + }), }; }); diff --git a/packages/typescript-estree/tests/lib/semanticInfo.test.ts b/packages/typescript-estree/tests/lib/semanticInfo.test.ts index db59636dc3a1..d099342c72e7 100644 --- a/packages/typescript-estree/tests/lib/semanticInfo.test.ts +++ b/packages/typescript-estree/tests/lib/semanticInfo.test.ts @@ -153,19 +153,19 @@ describe('semanticInfo', () => { ); expect(parseResult).toHaveProperty('services.esTreeNodeToTSNodeMap'); - const binaryExpression = (parseResult.ast - .body[0] as TSESTree.VariableDeclaration).declarations[0].init!; - const tsBinaryExpression = parseResult.services.esTreeNodeToTSNodeMap.get( - binaryExpression, - ); + const binaryExpression = ( + parseResult.ast.body[0] as TSESTree.VariableDeclaration + ).declarations[0].init!; + const tsBinaryExpression = + parseResult.services.esTreeNodeToTSNodeMap.get(binaryExpression); expect(tsBinaryExpression.kind).toEqual(ts.SyntaxKind.BinaryExpression); - const computedPropertyString = ((parseResult.ast - .body[1] as TSESTree.ClassDeclaration).body - .body[0] as TSESTree.ClassProperty).key; - const tsComputedPropertyString = parseResult.services.esTreeNodeToTSNodeMap.get( - computedPropertyString, - ); + const computedPropertyString = ( + (parseResult.ast.body[1] as TSESTree.ClassDeclaration).body + .body[0] as TSESTree.ClassProperty + ).key; + const tsComputedPropertyString = + parseResult.services.esTreeNodeToTSNodeMap.get(computedPropertyString); expect(tsComputedPropertyString.kind).toEqual(ts.SyntaxKind.StringLiteral); }); @@ -182,16 +182,17 @@ describe('semanticInfo', () => { // get array node (ast shape validated by snapshot) // node is defined in other file than the parsed one - const arrayBoundName = (((parseResult.ast - .body[1] as TSESTree.ExpressionStatement) - .expression as TSESTree.CallExpression) - .callee as TSESTree.MemberExpression).object as TSESTree.Identifier; + const arrayBoundName = ( + ( + (parseResult.ast.body[1] as TSESTree.ExpressionStatement) + .expression as TSESTree.CallExpression + ).callee as TSESTree.MemberExpression + ).object as TSESTree.Identifier; expect(arrayBoundName.name).toBe('arr'); expect(parseResult).toHaveProperty('services.esTreeNodeToTSNodeMap'); - const tsArrayBoundName = parseResult.services.esTreeNodeToTSNodeMap.get( - arrayBoundName, - ); + const tsArrayBoundName = + parseResult.services.esTreeNodeToTSNodeMap.get(arrayBoundName); expect(tsArrayBoundName).toBeDefined(); checkNumberArrayType(checker, tsArrayBoundName); @@ -217,9 +218,8 @@ describe('semanticInfo', () => { .declarations[0].id as TSESTree.Identifier; expect(boundName.name).toBe('x'); - const tsBoundName = parseResult.services.esTreeNodeToTSNodeMap.get( - boundName, - ); + const tsBoundName = + parseResult.services.esTreeNodeToTSNodeMap.get(boundName); expect(tsBoundName).toBeDefined(); expect(parseResult.services.tsNodeToESTreeNodeMap.get(tsBoundName)).toBe( @@ -369,9 +369,8 @@ function testIsolatedFile( expect(parseResult).toHaveProperty('services.esTreeNodeToTSNodeMap'); // get corresponding TS node - const tsArrayMember = parseResult.services.esTreeNodeToTSNodeMap.get( - arrayMember, - ); + const tsArrayMember = + parseResult.services.esTreeNodeToTSNodeMap.get(arrayMember); expect(tsArrayMember).toBeDefined(); expect(tsArrayMember.kind).toBe(ts.SyntaxKind.NumericLiteral); expect((tsArrayMember as ts.NumericLiteral).text).toBe('3');