From b4e39fbd06b9591506a61f1135d3b6370c57f949 Mon Sep 17 00:00:00 2001 From: auvred Date: Sat, 17 Feb 2024 20:16:04 +0300 Subject: [PATCH 01/19] test(eslint-plugin): render snapshots of ESLint output for each code example --- .../docs/rules/class-methods-use-this.md | 4 +- .../docs/rules/consistent-type-exports.md | 15 - .../docs/rules/default-param-last.md | 4 - .../rules/explicit-module-boundary-types.md | 36 +- .../docs/rules/member-ordering.md | 12 +- .../docs/rules/no-extraneous-class.md | 2 +- .../docs/rules/no-implied-eval.md | 4 - .../rules/no-meaningless-void-operator.md | 2 +- .../docs/rules/no-require-imports.md | 4 +- .../docs/rules/no-throw-literal.md | 20 +- .../rules/no-unnecessary-type-assertion.md | 10 +- .../docs/rules/no-var-requires.md | 4 +- .../non-nullable-type-assertion-style.md | 4 +- .../docs/rules/prefer-destructuring.md | 4 +- .../docs/rules/promise-function-async.md | 4 +- .../docs/rules/restrict-plus-operands.md | 20 +- .../docs/rules/strict-boolean-expressions.md | 6 - .../docs/rules/type-annotation-spacing.md | 2 +- .../adjacent-overload-signatures.shot | 78 +++ .../array-type.shot | 55 ++ .../await-thenable.shot | 19 + .../ban-ts-comment.shot | 85 +++ .../ban-tslint-comment.shot | 26 + .../ban-types.shot | 68 +++ .../class-literal-property-style.shot | 63 ++ .../class-methods-use-this.shot | 43 ++ .../consistent-generic-constructors.shot | 34 ++ .../consistent-indexed-object-style.shot | 40 ++ .../consistent-type-assertions.shot | 47 ++ .../consistent-type-definitions.shot | 30 + .../consistent-type-exports.shot | 29 + .../consistent-type-imports.shot | 53 ++ .../default-param-last.shot | 46 ++ .../dot-notation.shot | 31 + .../explicit-function-return-type.shot | 216 +++++++ .../explicit-member-accessibility.shot | 273 +++++++++ .../explicit-module-boundary-types.shot | 170 ++++++ .../lines-between-class-members.shot | 29 + .../member-delimiter-style.shot | 54 ++ .../member-ordering.shot | 549 ++++++++++++++++++ .../method-signature-style.shot | 59 ++ .../no-array-constructor.shot | 18 + .../no-array-delete.shot | 16 + .../no-base-to-string.shot | 52 ++ .../no-confusing-non-null-assertion.shot | 27 + .../no-confusing-void-expression.shot | 74 +++ .../no-duplicate-enum-values.shot | 35 ++ .../no-duplicate-type-constituents.shot | 36 ++ .../no-dynamic-delete.shot | 31 + .../no-empty-function.shot | 36 ++ .../no-empty-interface.shot | 33 ++ .../no-explicit-any.shot | 139 +++++ .../no-extra-non-null-assertion.shot | 46 ++ .../no-extraneous-class.shot | 192 ++++++ .../no-floating-promises.shot | 64 ++ .../no-for-in-array.shot | 41 ++ .../no-implied-eval.shot | 69 +++ .../no-import-type-side-effects.shot | 37 ++ .../no-inferrable-types.shot | 89 +++ .../no-invalid-void-type.shot | 84 +++ .../no-magic-numbers.shot | 69 +++ .../no-meaningless-void-operator.shot | 25 + .../no-misused-new.shot | 27 + .../no-misused-promises.shot | 129 ++++ .../no-mixed-enums.shot | 38 ++ .../no-namespace.shot | 87 +++ ...-non-null-asserted-nullish-coalescing.shot | 35 ++ .../no-non-null-asserted-optional-chain.shot | 15 + .../no-non-null-assertion.shot | 22 + .../no-redeclare.shot | 33 ++ .../no-redundant-type-constituents.shot | 51 ++ .../no-require-imports.shot | 29 + .../no-restricted-imports.shot | 25 + .../no-shadow.shot | 20 + .../no-this-alias.shot | 66 +++ .../no-throw-literal.shot | 74 +++ .../no-type-alias.shot | 489 ++++++++++++++++ ...o-unnecessary-boolean-literal-compare.shot | 72 +++ .../no-unnecessary-condition.shot | 62 ++ .../no-unnecessary-qualifier.shot | 35 ++ .../no-unnecessary-type-arguments.shot | 62 ++ .../no-unnecessary-type-assertion.shot | 64 ++ .../no-unnecessary-type-constraint.shot | 43 ++ .../no-unsafe-argument.shot | 56 ++ .../no-unsafe-assignment.shot | 67 +++ .../no-unsafe-call.shot | 42 ++ .../no-unsafe-declaration-merging.shot | 23 + .../no-unsafe-enum-comparison.shot | 47 ++ .../no-unsafe-member-access.shot | 49 ++ .../no-unsafe-return.shot | 84 +++ .../no-use-before-define.shot | 37 ++ .../no-useless-empty-export.shot | 25 + .../no-useless-template-literals.shot | 42 ++ .../no-var-requires.shot | 29 + .../non-nullable-type-assertion-style.shot | 19 + .../parameter-properties.shot | 406 +++++++++++++ .../prefer-as-const.shot | 21 + .../prefer-destructuring.shot | 36 ++ .../prefer-enum-initializers.shot | 43 ++ .../prefer-find.shot | 15 + .../prefer-for-of.shot | 27 + .../prefer-function-type.shot | 72 +++ .../prefer-includes.shot | 58 ++ .../prefer-literal-enum-member.shot | 62 ++ .../prefer-namespace-keyword.shot | 14 + .../prefer-nullish-coalescing.shot | 122 ++++ .../prefer-promise-reject-errors.shot | 39 ++ .../prefer-readonly.shot | 67 +++ .../prefer-reduce-type-parameter.shot | 29 + .../prefer-regexp-exec.shot | 26 + .../prefer-return-this-type.shot | 43 ++ .../prefer-string-starts-ends-with.shot | 49 ++ .../prefer-ts-expect-error.shot | 48 ++ .../promise-function-async.shot | 63 ++ .../require-array-sort-compare.shot | 41 ++ .../restrict-plus-operands.shot | 108 ++++ .../restrict-template-expressions.shot | 67 +++ .../return-await.shot | 169 ++++++ .../sort-type-constituents.shot | 113 ++++ .../space-before-blocks.shot | 29 + .../strict-boolean-expressions.shot | 59 ++ .../switch-exhaustiveness-check.shot | 162 ++++++ .../triple-slash-reference.shot | 55 ++ .../type-annotation-spacing.shot | 283 +++++++++ .../docs-eslint-output-snapshots/typedef.shot | 191 ++++++ .../unbound-method.shot | 76 +++ .../unified-signatures.shot | 46 ++ packages/eslint-plugin/tests/docs.test.ts | 184 ++++++ 128 files changed, 8195 insertions(+), 93 deletions(-) create mode 100644 packages/eslint-plugin/tests/docs-eslint-output-snapshots/adjacent-overload-signatures.shot create mode 100644 packages/eslint-plugin/tests/docs-eslint-output-snapshots/array-type.shot create mode 100644 packages/eslint-plugin/tests/docs-eslint-output-snapshots/await-thenable.shot create mode 100644 packages/eslint-plugin/tests/docs-eslint-output-snapshots/ban-ts-comment.shot create mode 100644 packages/eslint-plugin/tests/docs-eslint-output-snapshots/ban-tslint-comment.shot create mode 100644 packages/eslint-plugin/tests/docs-eslint-output-snapshots/ban-types.shot create mode 100644 packages/eslint-plugin/tests/docs-eslint-output-snapshots/class-literal-property-style.shot create mode 100644 packages/eslint-plugin/tests/docs-eslint-output-snapshots/class-methods-use-this.shot create mode 100644 packages/eslint-plugin/tests/docs-eslint-output-snapshots/consistent-generic-constructors.shot create mode 100644 packages/eslint-plugin/tests/docs-eslint-output-snapshots/consistent-indexed-object-style.shot create mode 100644 packages/eslint-plugin/tests/docs-eslint-output-snapshots/consistent-type-assertions.shot create mode 100644 packages/eslint-plugin/tests/docs-eslint-output-snapshots/consistent-type-definitions.shot create mode 100644 packages/eslint-plugin/tests/docs-eslint-output-snapshots/consistent-type-exports.shot create mode 100644 packages/eslint-plugin/tests/docs-eslint-output-snapshots/consistent-type-imports.shot create mode 100644 packages/eslint-plugin/tests/docs-eslint-output-snapshots/default-param-last.shot create mode 100644 packages/eslint-plugin/tests/docs-eslint-output-snapshots/dot-notation.shot create mode 100644 packages/eslint-plugin/tests/docs-eslint-output-snapshots/explicit-function-return-type.shot create mode 100644 packages/eslint-plugin/tests/docs-eslint-output-snapshots/explicit-member-accessibility.shot create mode 100644 packages/eslint-plugin/tests/docs-eslint-output-snapshots/explicit-module-boundary-types.shot create mode 100644 packages/eslint-plugin/tests/docs-eslint-output-snapshots/lines-between-class-members.shot create mode 100644 packages/eslint-plugin/tests/docs-eslint-output-snapshots/member-delimiter-style.shot create mode 100644 packages/eslint-plugin/tests/docs-eslint-output-snapshots/member-ordering.shot create mode 100644 packages/eslint-plugin/tests/docs-eslint-output-snapshots/method-signature-style.shot create mode 100644 packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-array-constructor.shot create mode 100644 packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-array-delete.shot create mode 100644 packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-base-to-string.shot create mode 100644 packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-confusing-non-null-assertion.shot create mode 100644 packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-confusing-void-expression.shot create mode 100644 packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-duplicate-enum-values.shot create mode 100644 packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-duplicate-type-constituents.shot create mode 100644 packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-dynamic-delete.shot create mode 100644 packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-empty-function.shot create mode 100644 packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-empty-interface.shot create mode 100644 packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-explicit-any.shot create mode 100644 packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-extra-non-null-assertion.shot create mode 100644 packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-extraneous-class.shot create mode 100644 packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-floating-promises.shot create mode 100644 packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-for-in-array.shot create mode 100644 packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-implied-eval.shot create mode 100644 packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-import-type-side-effects.shot create mode 100644 packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-inferrable-types.shot create mode 100644 packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-invalid-void-type.shot create mode 100644 packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-magic-numbers.shot create mode 100644 packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-meaningless-void-operator.shot create mode 100644 packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-misused-new.shot create mode 100644 packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-misused-promises.shot create mode 100644 packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-mixed-enums.shot create mode 100644 packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-namespace.shot create mode 100644 packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-non-null-asserted-nullish-coalescing.shot create mode 100644 packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-non-null-asserted-optional-chain.shot create mode 100644 packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-non-null-assertion.shot create mode 100644 packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-redeclare.shot create mode 100644 packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-redundant-type-constituents.shot create mode 100644 packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-require-imports.shot create mode 100644 packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-restricted-imports.shot create mode 100644 packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-shadow.shot create mode 100644 packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-this-alias.shot create mode 100644 packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-throw-literal.shot create mode 100644 packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-type-alias.shot create mode 100644 packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-unnecessary-boolean-literal-compare.shot create mode 100644 packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-unnecessary-condition.shot create mode 100644 packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-unnecessary-qualifier.shot create mode 100644 packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-unnecessary-type-arguments.shot create mode 100644 packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-unnecessary-type-assertion.shot create mode 100644 packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-unnecessary-type-constraint.shot create mode 100644 packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-unsafe-argument.shot create mode 100644 packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-unsafe-assignment.shot create mode 100644 packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-unsafe-call.shot create mode 100644 packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-unsafe-declaration-merging.shot create mode 100644 packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-unsafe-enum-comparison.shot create mode 100644 packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-unsafe-member-access.shot create mode 100644 packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-unsafe-return.shot create mode 100644 packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-use-before-define.shot create mode 100644 packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-useless-empty-export.shot create mode 100644 packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-useless-template-literals.shot create mode 100644 packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-var-requires.shot create mode 100644 packages/eslint-plugin/tests/docs-eslint-output-snapshots/non-nullable-type-assertion-style.shot create mode 100644 packages/eslint-plugin/tests/docs-eslint-output-snapshots/parameter-properties.shot create mode 100644 packages/eslint-plugin/tests/docs-eslint-output-snapshots/prefer-as-const.shot create mode 100644 packages/eslint-plugin/tests/docs-eslint-output-snapshots/prefer-destructuring.shot create mode 100644 packages/eslint-plugin/tests/docs-eslint-output-snapshots/prefer-enum-initializers.shot create mode 100644 packages/eslint-plugin/tests/docs-eslint-output-snapshots/prefer-find.shot create mode 100644 packages/eslint-plugin/tests/docs-eslint-output-snapshots/prefer-for-of.shot create mode 100644 packages/eslint-plugin/tests/docs-eslint-output-snapshots/prefer-function-type.shot create mode 100644 packages/eslint-plugin/tests/docs-eslint-output-snapshots/prefer-includes.shot create mode 100644 packages/eslint-plugin/tests/docs-eslint-output-snapshots/prefer-literal-enum-member.shot create mode 100644 packages/eslint-plugin/tests/docs-eslint-output-snapshots/prefer-namespace-keyword.shot create mode 100644 packages/eslint-plugin/tests/docs-eslint-output-snapshots/prefer-nullish-coalescing.shot create mode 100644 packages/eslint-plugin/tests/docs-eslint-output-snapshots/prefer-promise-reject-errors.shot create mode 100644 packages/eslint-plugin/tests/docs-eslint-output-snapshots/prefer-readonly.shot create mode 100644 packages/eslint-plugin/tests/docs-eslint-output-snapshots/prefer-reduce-type-parameter.shot create mode 100644 packages/eslint-plugin/tests/docs-eslint-output-snapshots/prefer-regexp-exec.shot create mode 100644 packages/eslint-plugin/tests/docs-eslint-output-snapshots/prefer-return-this-type.shot create mode 100644 packages/eslint-plugin/tests/docs-eslint-output-snapshots/prefer-string-starts-ends-with.shot create mode 100644 packages/eslint-plugin/tests/docs-eslint-output-snapshots/prefer-ts-expect-error.shot create mode 100644 packages/eslint-plugin/tests/docs-eslint-output-snapshots/promise-function-async.shot create mode 100644 packages/eslint-plugin/tests/docs-eslint-output-snapshots/require-array-sort-compare.shot create mode 100644 packages/eslint-plugin/tests/docs-eslint-output-snapshots/restrict-plus-operands.shot create mode 100644 packages/eslint-plugin/tests/docs-eslint-output-snapshots/restrict-template-expressions.shot create mode 100644 packages/eslint-plugin/tests/docs-eslint-output-snapshots/return-await.shot create mode 100644 packages/eslint-plugin/tests/docs-eslint-output-snapshots/sort-type-constituents.shot create mode 100644 packages/eslint-plugin/tests/docs-eslint-output-snapshots/space-before-blocks.shot create mode 100644 packages/eslint-plugin/tests/docs-eslint-output-snapshots/strict-boolean-expressions.shot create mode 100644 packages/eslint-plugin/tests/docs-eslint-output-snapshots/switch-exhaustiveness-check.shot create mode 100644 packages/eslint-plugin/tests/docs-eslint-output-snapshots/triple-slash-reference.shot create mode 100644 packages/eslint-plugin/tests/docs-eslint-output-snapshots/type-annotation-spacing.shot create mode 100644 packages/eslint-plugin/tests/docs-eslint-output-snapshots/typedef.shot create mode 100644 packages/eslint-plugin/tests/docs-eslint-output-snapshots/unbound-method.shot create mode 100644 packages/eslint-plugin/tests/docs-eslint-output-snapshots/unified-signatures.shot diff --git a/packages/eslint-plugin/docs/rules/class-methods-use-this.md b/packages/eslint-plugin/docs/rules/class-methods-use-this.md index 8864b44cf3aa..9a3a2189876c 100644 --- a/packages/eslint-plugin/docs/rules/class-methods-use-this.md +++ b/packages/eslint-plugin/docs/rules/class-methods-use-this.md @@ -68,7 +68,7 @@ Example of a incorrect code when `ignoreClassesThatImplementAnInterface` is set ##### ❌ Incorrect -```ts +```ts option='{ "ignoreClassesThatImplementAnInterface": "public-fields" }' class X implements Y { method() {} property = () => {}; @@ -83,7 +83,7 @@ class X implements Y { ##### ✅ Correct -```ts +```ts option='{ "ignoreClassesThatImplementAnInterface": "public-fields" }' class X implements Y { method() {} property = () => {}; diff --git a/packages/eslint-plugin/docs/rules/consistent-type-exports.md b/packages/eslint-plugin/docs/rules/consistent-type-exports.md index 61f520845c5f..c649e54a3537 100644 --- a/packages/eslint-plugin/docs/rules/consistent-type-exports.md +++ b/packages/eslint-plugin/docs/rules/consistent-type-exports.md @@ -79,21 +79,6 @@ export type { T }; export { x }; ``` - - -### ❌ Incorrect - -```ts option='{ "fixMixedExportsWithInlineTypeSpecifier": true }' -export { Button } from 'some-library'; -export type { ButtonProps } from 'some-library'; -``` - -### ✅ Correct - -```ts option='{ "fixMixedExportsWithInlineTypeSpecifier": true }' -export { Button, type ButtonProps } from 'some-library'; -``` - ## When Not To Use It If you use `--isolatedModules` the compiler would error if a type is not re-exported using `export type`. diff --git a/packages/eslint-plugin/docs/rules/default-param-last.md b/packages/eslint-plugin/docs/rules/default-param-last.md index 909f9ac10d0f..31c70652f0e5 100644 --- a/packages/eslint-plugin/docs/rules/default-param-last.md +++ b/packages/eslint-plugin/docs/rules/default-param-last.md @@ -14,8 +14,6 @@ It adds support for optional parameters. ### ❌ Incorrect ```ts -/* eslint @typescript-eslint/default-param-last: "error" */ - function f(a = 0, b: number) {} function f(a: number, b = 0, c: number) {} function f(a: number, b?: number, c: number) {} @@ -36,8 +34,6 @@ class Foo { ### ✅ Correct ```ts -/* eslint @typescript-eslint/default-param-last: "error" */ - function f(a = 0) {} function f(a: number, b = 0) {} function f(a: number, b?: number) {} diff --git a/packages/eslint-plugin/docs/rules/explicit-module-boundary-types.md b/packages/eslint-plugin/docs/rules/explicit-module-boundary-types.md index 879e30638114..12c01a96a9e5 100644 --- a/packages/eslint-plugin/docs/rules/explicit-module-boundary-types.md +++ b/packages/eslint-plugin/docs/rules/explicit-module-boundary-types.md @@ -91,31 +91,31 @@ If you are working on a codebase within which you lint non-TypeScript code (i.e. ### `allowArgumentsExplicitlyTypedAsAny` -Examples of code for this rule with `{ allowArgumentsExplicitlyTypedAsAny: false }`: +When this option is `true` the rule ignores arguments that are explicitly typed as any. -#### ❌ Incorrect +#### ❌ Incorrect for `allowArgumentsExplicitlyTypedAsAny: false` ```ts option='{ "allowArgumentsExplicitlyTypedAsAny": false }' export const func = (value: any): number => value + 1; ``` -#### ✅ Correct +#### ✅ Correct for `allowArgumentsExplicitlyTypedAsAny: true` -```ts option='{ "allowArgumentsExplicitlyTypedAsAny": false }' -export const func = (value: number): number => value + 1; +```ts option='{ "allowArgumentsExplicitlyTypedAsAny": true }' +export const func = (value: any): number => value + 1; ``` ### `allowDirectConstAssertionInArrowFunctions` -Examples of code for this rule with `{ allowDirectConstAssertionInArrowFunctions: false }`: +When this option is `true` the rule ignores return type annotations on body-less arrow functions that return an `as const` type assertion. -#### ❌ Incorrect +#### ❌ Incorrect for `allowDirectConstAssertionInArrowFunctions: false` -```ts option='{ "allowArgumentsExplicitlyTypedAsAny": false }' +```ts option='{ "allowDirectConstAssertionInArrowFunctions": false }' export const func = (value: number) => ({ type: 'X', value }); export const foo = () => ({ bar: true, @@ -123,9 +123,9 @@ export const foo = () => ({ export const bar = () => 1; ``` -#### ✅ Correct +#### ✅ Correct for `allowDirectConstAssertionInArrowFunctions: true` -```ts option='{ "allowArgumentsExplicitlyTypedAsAny": false }' +```ts option='{ "allowDirectConstAssertionInArrowFunctions": true }' export const func = (value: number) => ({ type: 'X', value }) as const; export const foo = () => ({ @@ -151,11 +151,11 @@ You may pass function/method names you would like this rule to ignore, like so: ### `allowHigherOrderFunctions` -Examples of code for this rule with `{ allowHigherOrderFunctions: false }`: +When this option is `true` the rule ignores return type annotations on function immediately returning another function expression. -#### ❌ Incorrect +#### ❌ Incorrect for `allowHigherOrderFunctions: false` ```ts option='{ "allowHigherOrderFunctions": false }' export const arrowFn = () => () => {}; @@ -169,9 +169,9 @@ export function foo(outer: string) { } ``` -#### ✅ Correct +#### ✅ Correct for `allowHigherOrderFunctions: true` -```ts option='{ "allowHigherOrderFunctions": false }' +```ts option='{ "allowHigherOrderFunctions": true }' export const arrowFn = () => (): void => {}; export function fn() { @@ -185,11 +185,11 @@ export function foo(outer: string) { ### `allowTypedFunctionExpressions` -Examples of code for this rule with `{ allowTypedFunctionExpressions: false }`: +When this option is `true` the rule ignores type annotations on the variable of a function expression. -#### ❌ Incorrect +#### ❌ Incorrect for `allowTypedFunctionExpressions: false` ```ts option='{ "allowTypedFunctionExpressions": false }' export let arrowFn = () => 'test'; @@ -205,9 +205,9 @@ export let objectProp = { export const foo = bar => {}; ``` -#### ✅ Correct +#### ✅ Correct for `allowTypedFunctionExpressions: true` -```ts option='{ "allowTypedFunctionExpressions": false }' +```ts option='{ "allowTypedFunctionExpressions": true }' type FuncType = () => string; export let arrowFn: FuncType = () => 'test'; diff --git a/packages/eslint-plugin/docs/rules/member-ordering.md b/packages/eslint-plugin/docs/rules/member-ordering.md index fc505ff9d276..35e51168da63 100644 --- a/packages/eslint-plugin/docs/rules/member-ordering.md +++ b/packages/eslint-plugin/docs/rules/member-ordering.md @@ -972,9 +972,9 @@ interface Foo { b(): void; a: boolean; - [a: string]: number; // Order doesn't matter (no sortable identifier) - new (): Bar; // Order doesn't matter (no sortable identifier) - (): Baz; // Order doesn't matter (no sortable identifier) + [a: string]: number; + new (): Bar; + (): Baz; } ``` @@ -982,12 +982,12 @@ interface Foo { ```ts option='{ "default": { "memberTypes": "never", "order": "alphabetically" } }' interface Foo { + [a: string]: number; a: boolean; b(): void; - [a: string]: number; // Order doesn't matter (no sortable identifier) - new (): Bar; // Order doesn't matter (no sortable identifier) - (): Baz; // Order doesn't matter (no sortable identifier) + (): Baz; + new (): Bar; } ``` diff --git a/packages/eslint-plugin/docs/rules/no-extraneous-class.md b/packages/eslint-plugin/docs/rules/no-extraneous-class.md index 451b01ae4a5d..0d41c99583fe 100644 --- a/packages/eslint-plugin/docs/rules/no-extraneous-class.md +++ b/packages/eslint-plugin/docs/rules/no-extraneous-class.md @@ -283,8 +283,8 @@ class Constants { #### ✅ Correct ```ts option='{ "allowWithDecorator": true }' +@logOnRead() class Constants { - @logOnRead() static readonly version = 42; } ``` diff --git a/packages/eslint-plugin/docs/rules/no-implied-eval.md b/packages/eslint-plugin/docs/rules/no-implied-eval.md index 10f787d6d43f..a81ef1004de8 100644 --- a/packages/eslint-plugin/docs/rules/no-implied-eval.md +++ b/packages/eslint-plugin/docs/rules/no-implied-eval.md @@ -34,8 +34,6 @@ This rule aims to eliminate implied `eval()` through the use of `new Function()` ### ❌ Incorrect ```ts -/* eslint @typescript-eslint/no-implied-eval: "error" */ - setTimeout('alert(`Hi!`);', 100); setInterval('alert(`Hi!`);', 100); @@ -62,8 +60,6 @@ const fn = new Function('a', 'b', 'return a + b'); ### ✅ Correct ```ts -/* eslint @typescript-eslint/no-implied-eval: "error" */ - setTimeout(function () { alert('Hi!'); }, 100); diff --git a/packages/eslint-plugin/docs/rules/no-meaningless-void-operator.md b/packages/eslint-plugin/docs/rules/no-meaningless-void-operator.md index e57606d5ec9d..302bc77f1a16 100644 --- a/packages/eslint-plugin/docs/rules/no-meaningless-void-operator.md +++ b/packages/eslint-plugin/docs/rules/no-meaningless-void-operator.md @@ -39,7 +39,7 @@ function bar(x: number) { void x; // discarding a number return 2; } -void bar(); // discarding a number +void bar(1); // discarding a number ``` ## Options diff --git a/packages/eslint-plugin/docs/rules/no-require-imports.md b/packages/eslint-plugin/docs/rules/no-require-imports.md index d67d639b9cb8..4a893d005b0c 100644 --- a/packages/eslint-plugin/docs/rules/no-require-imports.md +++ b/packages/eslint-plugin/docs/rules/no-require-imports.md @@ -40,13 +40,13 @@ With `{allow: ['/package\\.json$']}`: ### ❌ Incorrect -```ts +```ts option='{ "allow": ["/package.json$"] }' console.log(require('../data.json').version); ``` ### ✅ Correct -```ts +```ts option='{ "allow": ["/package.json$"] }' console.log(require('../package.json').version); ``` diff --git a/packages/eslint-plugin/docs/rules/no-throw-literal.md b/packages/eslint-plugin/docs/rules/no-throw-literal.md index 91bb246ce52e..a6e2c4c5c84f 100644 --- a/packages/eslint-plugin/docs/rules/no-throw-literal.md +++ b/packages/eslint-plugin/docs/rules/no-throw-literal.md @@ -28,19 +28,19 @@ throw undefined; throw null; -const err = new Error(); -throw 'an ' + err; +const err1 = new Error(); +throw 'an ' + err1; -const err = new Error(); -throw `${err}`; +const err2 = new Error(); +throw `${err2}`; -const err = ''; -throw err; +const err3 = ''; +throw err3; -function err() { +function getErr() { return ''; } -throw err(); +throw getErr(); const foo = { bar: '', @@ -67,10 +67,10 @@ try { const err = new Error(); throw err; -function err() { +function getErr() { return new Error(); } -throw err(); +throw getErr(); const foo = { bar: new Error(), diff --git a/packages/eslint-plugin/docs/rules/no-unnecessary-type-assertion.md b/packages/eslint-plugin/docs/rules/no-unnecessary-type-assertion.md index 7f428c056243..6ec4393a9dea 100644 --- a/packages/eslint-plugin/docs/rules/no-unnecessary-type-assertion.md +++ b/packages/eslint-plugin/docs/rules/no-unnecessary-type-assertion.md @@ -22,17 +22,17 @@ const bar = foo!; ``` ```ts -const foo = <3>3; +const foo = (3 + 5); ``` ```ts -type Foo = 3; -const foo = 3; +type Foo = number; +const foo = (3 + 5); ``` ```ts -type Foo = 3; -const foo = 3 as Foo; +type Foo = number; +const foo = (3 + 5) as Foo; ``` ```ts diff --git a/packages/eslint-plugin/docs/rules/no-var-requires.md b/packages/eslint-plugin/docs/rules/no-var-requires.md index 0bd0b2b564b9..db48d2e01b1f 100644 --- a/packages/eslint-plugin/docs/rules/no-var-requires.md +++ b/packages/eslint-plugin/docs/rules/no-var-requires.md @@ -40,13 +40,13 @@ With `{allow: ['/package\\.json$']}`: ### ❌ Incorrect -```ts +```ts option='{ "allow": ["/package.json$"] }' const foo = require('../data.json'); ``` ### ✅ Correct -```ts +```ts option='{ "allow": ["/package.json$"] }' const foo = require('../package.json'); ``` diff --git a/packages/eslint-plugin/docs/rules/non-nullable-type-assertion-style.md b/packages/eslint-plugin/docs/rules/non-nullable-type-assertion-style.md index 0dc6527ff0d3..9729f696e1a1 100644 --- a/packages/eslint-plugin/docs/rules/non-nullable-type-assertion-style.md +++ b/packages/eslint-plugin/docs/rules/non-nullable-type-assertion-style.md @@ -21,7 +21,7 @@ This rule reports when an `as` cast is doing the same job as a `!` would, and su ### ❌ Incorrect ```ts -const maybe = Math.random() > 0.5 ? '' : undefined; +const maybe: string | undefined = Math.random() > 0.5 ? '' : undefined; const definitely = maybe as string; const alsoDefinitely = maybe; @@ -30,7 +30,7 @@ const alsoDefinitely = maybe; ### ✅ Correct ```ts -const maybe = Math.random() > 0.5 ? '' : undefined; +const maybe: string | undefined = Math.random() > 0.5 ? '' : undefined; const definitely = maybe!; const alsoDefinitely = maybe!; diff --git a/packages/eslint-plugin/docs/rules/prefer-destructuring.md b/packages/eslint-plugin/docs/rules/prefer-destructuring.md index 5980b81dbae8..7d6f93e69420 100644 --- a/packages/eslint-plugin/docs/rules/prefer-destructuring.md +++ b/packages/eslint-plugin/docs/rules/prefer-destructuring.md @@ -80,12 +80,12 @@ Examples with `{ enforceForDeclarationWithTypeAnnotation: true }`: ### ❌ Incorrect -```ts +```ts option='{ "object": true }, { "enforceForDeclarationWithTypeAnnotation": true }' const x: string = obj.x; ``` ### ✅ Correct -```ts +```ts option='{ "object": true }, { "enforceForDeclarationWithTypeAnnotation": true }' const { x }: { x: string } = obj; ``` diff --git a/packages/eslint-plugin/docs/rules/promise-function-async.md b/packages/eslint-plugin/docs/rules/promise-function-async.md index c85c00af40fc..5f2ddb98a267 100644 --- a/packages/eslint-plugin/docs/rules/promise-function-async.md +++ b/packages/eslint-plugin/docs/rules/promise-function-async.md @@ -93,7 +93,7 @@ Examples of code with `{ "allowedPromiseNames": ["Bluebird"] }`: #### ❌ Incorrect ```ts option='{ "allowedPromiseNames": ["Bluebird"] }' -import { Bluebird } from 'bluebird'; +class Bluebird {} const returnsBluebird = () => new Bluebird(() => {}); ``` @@ -101,7 +101,7 @@ const returnsBluebird = () => new Bluebird(() => {}); #### ✅ Correct ```ts option='{ "allowedPromiseNames": ["Bluebird"] }' -import { Bluebird } from 'bluebird'; +class Bluebird {} const returnsBluebird = async () => new Bluebird(() => {}); ``` diff --git a/packages/eslint-plugin/docs/rules/restrict-plus-operands.md b/packages/eslint-plugin/docs/rules/restrict-plus-operands.md index 868d1bdefc01..836924989bb1 100644 --- a/packages/eslint-plugin/docs/rules/restrict-plus-operands.md +++ b/packages/eslint-plugin/docs/rules/restrict-plus-operands.md @@ -176,22 +176,22 @@ Examples of code for this rule with `{ skipCompoundAssignments: false }`: #### ❌ Incorrect -```ts option='{ "skipCompoundAssignments": true }' -let foo: string | undefined; -foo += 'some data'; +```ts option='{ "skipCompoundAssignments": false }' +let foo: bigint = 0n; +foo += 1; -let bar: string = ''; -bar += 0; +let bar: number[] = [1]; +bar += 1; ``` #### ✅ Correct -```ts option='{ "skipCompoundAssignments": true }' -let foo: number = 0; -foo += 1; +```ts option='{ "skipCompoundAssignments": false }' +let foo: bigint = 0n; +foo += 1n; -let bar = ''; -bar += 'test'; +let bar: number = 1; +bar += 1; ``` ## When Not To Use It diff --git a/packages/eslint-plugin/docs/rules/strict-boolean-expressions.md b/packages/eslint-plugin/docs/rules/strict-boolean-expressions.md index f0f702d03d51..b83710bfd997 100644 --- a/packages/eslint-plugin/docs/rules/strict-boolean-expressions.md +++ b/packages/eslint-plugin/docs/rules/strict-boolean-expressions.md @@ -58,12 +58,6 @@ while (obj) { ### ✅ Correct ```tsx -// Using logical operator short-circuiting is allowed -const Component = () => { - const entry = map.get('foo') || {}; - return entry &&

Name: {entry.name}

; -}; - // nullable values should be checked explicitly against null or undefined let num: number | undefined = 0; if (num != null) { diff --git a/packages/eslint-plugin/docs/rules/type-annotation-spacing.md b/packages/eslint-plugin/docs/rules/type-annotation-spacing.md index d7017c7c5d5d..7e9b8f6b3f21 100644 --- a/packages/eslint-plugin/docs/rules/type-annotation-spacing.md +++ b/packages/eslint-plugin/docs/rules/type-annotation-spacing.md @@ -245,7 +245,7 @@ class Foo { } type Foo = { - name: (name : string)=>string; + name : (name : string)=>string; } type Foo = ()=>{}; diff --git a/packages/eslint-plugin/tests/docs-eslint-output-snapshots/adjacent-overload-signatures.shot b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/adjacent-overload-signatures.shot new file mode 100644 index 000000000000..22ecedeb3cd7 --- /dev/null +++ b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/adjacent-overload-signatures.shot @@ -0,0 +1,78 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[` 1`] = ` +"declare namespace Foo { + export function foo(s: string): void; + export function foo(n: number): void; + export function bar(): void; + export function foo(sn: string | number): void; + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ All foo signatures should be adjacent. +} + +type Foo = { + foo(s: string): void; + foo(n: number): void; + bar(): void; + foo(sn: string | number): void; + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ All foo signatures should be adjacent. +}; + +interface Foo { + foo(s: string): void; + foo(n: number): void; + bar(): void; + foo(sn: string | number): void; + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ All foo signatures should be adjacent. +} + +class Foo { + foo(s: string): void; + foo(n: number): void; + bar(): void {} + foo(sn: string | number): void {} + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ All foo signatures should be adjacent. +} + +export function foo(s: string): void; +export function foo(n: number): void; +export function bar(): void; +export function foo(sn: string | number): void; +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ All foo signatures should be adjacent. +" +`; + +exports[` 2`] = ` +"declare namespace Foo { + export function foo(s: string): void; + export function foo(n: number): void; + export function foo(sn: string | number): void; + export function bar(): void; +} + +type Foo = { + foo(s: string): void; + foo(n: number): void; + foo(sn: string | number): void; + bar(): void; +}; + +interface Foo { + foo(s: string): void; + foo(n: number): void; + foo(sn: string | number): void; + bar(): void; +} + +class Foo { + foo(s: string): void; + foo(n: number): void; + foo(sn: string | number): void {} + bar(): void {} +} + +export function bar(): void; +export function foo(s: string): void; +export function foo(n: number): void; +export function foo(sn: string | number): void; +" +`; diff --git a/packages/eslint-plugin/tests/docs-eslint-output-snapshots/array-type.shot b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/array-type.shot new file mode 100644 index 000000000000..641e1f8051b7 --- /dev/null +++ b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/array-type.shot @@ -0,0 +1,55 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[` 1`] = ` +"const x: Array = ['a', 'b']; + ~~~~~~~~~~~~~ Array type using 'Array' is forbidden. Use 'string[]' instead. +const y: ReadonlyArray = ['a', 'b']; + ~~~~~~~~~~~~~~~~~~~~~ Array type using 'ReadonlyArray' is forbidden. Use 'readonly string[]' instead. +" +`; + +exports[` 2`] = ` +"const x: string[] = ['a', 'b']; +const y: readonly string[] = ['a', 'b']; +" +`; + +exports[` 3`] = ` +"const x: string[] = ['a', 'b']; + ~~~~~~~~ Array type using 'string[]' is forbidden. Use 'Array' instead. +const y: readonly string[] = ['a', 'b']; + ~~~~~~~~~~~~~~~~~ Array type using 'readonly string[]' is forbidden. Use 'ReadonlyArray' instead. +" +`; + +exports[` 4`] = ` +"const x: Array = ['a', 'b']; +const y: ReadonlyArray = ['a', 'b']; +" +`; + +exports[` 5`] = ` +"const a: (string | number)[] = ['a', 'b']; + ~~~~~~~~~~~~~~~~~~~ Array type using 'T[]' is forbidden for non-simple types. Use 'Array' instead. +const b: { prop: string }[] = [{ prop: 'a' }]; + ~~~~~~~~~~~~~~~~~~ Array type using 'T[]' is forbidden for non-simple types. Use 'Array' instead. +const c: (() => void)[] = [() => {}]; + ~~~~~~~~~~~~~~ Array type using 'T[]' is forbidden for non-simple types. Use 'Array' instead. +const d: Array = ['a', 'b']; + ~~~~~~~~~~~~~ Array type using 'Array' is forbidden for simple types. Use 'MyType[]' instead. +const e: Array = ['a', 'b']; + ~~~~~~~~~~~~~ Array type using 'Array' is forbidden for simple types. Use 'string[]' instead. +const f: ReadonlyArray = ['a', 'b']; + ~~~~~~~~~~~~~~~~~~~~~ Array type using 'ReadonlyArray' is forbidden for simple types. Use 'readonly string[]' instead. +" +`; + +exports[` 6`] = ` +"const a: Array = ['a', 'b']; +const b: Array<{ prop: string }> = [{ prop: 'a' }]; +const c: Array<() => void> = [() => {}]; +const d: MyType[] = ['a', 'b']; +const e: string[] = ['a', 'b']; +const f: readonly string[] = ['a', 'b']; +" +`; diff --git a/packages/eslint-plugin/tests/docs-eslint-output-snapshots/await-thenable.shot b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/await-thenable.shot new file mode 100644 index 000000000000..bd9ee905df06 --- /dev/null +++ b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/await-thenable.shot @@ -0,0 +1,19 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[` 1`] = ` +"await 'value'; +~~~~~~~~~~~~~ Unexpected \`await\` of a non-Promise (non-"Thenable") value. + +const createValue = () => 'value'; +await createValue(); +~~~~~~~~~~~~~~~~~~~ Unexpected \`await\` of a non-Promise (non-"Thenable") value. +" +`; + +exports[` 2`] = ` +"await Promise.resolve('value'); + +const createValue = async () => 'value'; +await createValue(); +" +`; diff --git a/packages/eslint-plugin/tests/docs-eslint-output-snapshots/ban-ts-comment.shot b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/ban-ts-comment.shot new file mode 100644 index 000000000000..50efd775b7c1 --- /dev/null +++ b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/ban-ts-comment.shot @@ -0,0 +1,85 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[` 1`] = ` +"if (false) { + // @ts-ignore: Unreachable code error + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Use "@ts-expect-error" instead of "@ts-ignore", as "@ts-ignore" will do nothing if the following line is error-free. + console.log('hello'); +} +if (false) { + /* + ~~ Use "@ts-expect-error" instead of "@ts-ignore", as "@ts-ignore" will do nothing if the following line is error-free. + @ts-ignore: Unreachable code error +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + */ +~~ + console.log('hello'); +} +" +`; + +exports[` 2`] = ` +"if (false) { + // Compiler warns about unreachable code error + console.log('hello'); +} +" +`; + +exports[` 3`] = ` +"if (false) { + // @ts-expect-error + ~~~~~~~~~~~~~~~~~~~ Include a description after the "@ts-expect-error" directive to explain why the @ts-expect-error is necessary. The description must be 3 characters or longer. + console.log('hello'); +} +if (false) { + /* @ts-expect-error */ + ~~~~~~~~~~~~~~~~~~~~~~ Include a description after the "@ts-expect-error" directive to explain why the @ts-expect-error is necessary. The description must be 3 characters or longer. + console.log('hello'); +} +" +`; + +exports[` 4`] = ` +"if (false) { + // @ts-expect-error: Unreachable code error + console.log('hello'); +} +if (false) { + /* + @ts-expect-error: Unreachable code error + */ + console.log('hello'); +} +" +`; + +exports[` 5`] = ` +"// @ts-expect-error: the library definition is wrong +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ The description for the "@ts-expect-error" directive must match the ^: TS\\d+ because .+$ format. +const a = doSomething('hello'); +" +`; + +exports[` 6`] = ` +"// @ts-expect-error: TS1234 because the library definition is wrong +const a = doSomething('hello'); +" +`; + +exports[` 7`] = ` +"if (false) { + // @ts-expect-error: TODO + ~~~~~~~~~~~~~~~~~~~~~~~~~ Include a description after the "@ts-expect-error" directive to explain why the @ts-expect-error is necessary. The description must be 10 characters or longer. + console.log('hello'); +} +" +`; + +exports[` 8`] = ` +"if (false) { + // @ts-expect-error The rationale for this override is described in issue #1337 on GitLab + console.log('hello'); +} +" +`; diff --git a/packages/eslint-plugin/tests/docs-eslint-output-snapshots/ban-tslint-comment.shot b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/ban-tslint-comment.shot new file mode 100644 index 000000000000..fdd2af913adc --- /dev/null +++ b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/ban-tslint-comment.shot @@ -0,0 +1,26 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[` 1`] = ` +"/* tslint:disable */ +~~~~~~~~~~~~~~~~~~~~ tslint comment detected: "/* tslint:disable */" +/* tslint:enable */ +~~~~~~~~~~~~~~~~~~~ tslint comment detected: "/* tslint:enable */" +/* tslint:disable:rule1 rule2 rule3... */ +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ tslint comment detected: "/* tslint:disable:rule1 rule2 rule3... */" +/* tslint:enable:rule1 rule2 rule3... */ +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ tslint comment detected: "/* tslint:enable:rule1 rule2 rule3... */" +// tslint:disable-next-line +~~~~~~~~~~~~~~~~~~~~~~~~~~~ tslint comment detected: "// tslint:disable-next-line" +someCode(); // tslint:disable-line + ~~~~~~~~~~~~~~~~~~~~~~ tslint comment detected: "// tslint:disable-line" +// tslint:disable-next-line:rule1 rule2 rule3... +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ tslint comment detected: "// tslint:disable-next-line:rule1 rule2 rule3..." +" +`; + +exports[` 2`] = ` +"// This is a comment that just happens to mention tslint +/* This is a multiline comment that just happens to mention tslint */ +someCode(); // This is a comment that just happens to mention tslint +" +`; diff --git a/packages/eslint-plugin/tests/docs-eslint-output-snapshots/ban-types.shot b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/ban-types.shot new file mode 100644 index 000000000000..ef6a4125f26b --- /dev/null +++ b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/ban-types.shot @@ -0,0 +1,68 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[` 1`] = ` +"// use lower-case primitives for consistency +const str: String = 'foo'; + ~~~~~~ Don't use \`String\` as a type. Use string instead +const bool: Boolean = true; + ~~~~~~~ Don't use \`Boolean\` as a type. Use boolean instead +const num: Number = 1; + ~~~~~~ Don't use \`Number\` as a type. Use number instead +const symb: Symbol = Symbol('foo'); + ~~~~~~ Don't use \`Symbol\` as a type. Use symbol instead +const bigInt: BigInt = 1n; + ~~~~~~ Don't use \`BigInt\` as a type. Use bigint instead + +// use a proper function type +const func: Function = () => 1; + ~~~~~~~~ Don't use \`Function\` as a type. The \`Function\` type accepts any function-like value. + It provides no type safety when calling the function, which can be a common source of bugs. + It also accepts things like class declarations, which will throw at runtime as they will not be called with \`new\`. + If you are expecting the function to accept certain arguments, you should explicitly define the function shape. + +// use safer object types +const lowerObj: Object = {}; + ~~~~~~ Don't use \`Object\` as a type. The \`Object\` type actually means "any non-nullish value", so it is marginally better than \`unknown\`. + - If you want a type meaning "any object", you probably want \`object\` instead. + - If you want a type meaning "any value", you probably want \`unknown\` instead. + - If you really want a type meaning "any non-nullish value", you probably want \`NonNullable\` instead. +const capitalObj: Object = { a: 'string' }; + ~~~~~~ Don't use \`Object\` as a type. The \`Object\` type actually means "any non-nullish value", so it is marginally better than \`unknown\`. + - If you want a type meaning "any object", you probably want \`object\` instead. + - If you want a type meaning "any value", you probably want \`unknown\` instead. + - If you really want a type meaning "any non-nullish value", you probably want \`NonNullable\` instead. + +const curly1: {} = 1; + ~~ Don't use \`{}\` as a type. \`{}\` actually means "any non-nullish value". + - If you want a type meaning "any object", you probably want \`object\` instead. + - If you want a type meaning "any value", you probably want \`unknown\` instead. + - If you want a type meaning "empty object", you probably want \`Record\` instead. + - If you really want a type meaning "any non-nullish value", you probably want \`NonNullable\` instead. +const curly2: {} = { a: 'string' }; + ~~ Don't use \`{}\` as a type. \`{}\` actually means "any non-nullish value". + - If you want a type meaning "any object", you probably want \`object\` instead. + - If you want a type meaning "any value", you probably want \`unknown\` instead. + - If you want a type meaning "empty object", you probably want \`Record\` instead. + - If you really want a type meaning "any non-nullish value", you probably want \`NonNullable\` instead. +" +`; + +exports[` 2`] = ` +"// use lower-case primitives for consistency +const str: string = 'foo'; +const bool: boolean = true; +const num: number = 1; +const symb: symbol = Symbol('foo'); +const bigInt: bigint = 1n; + +// use a proper function type +const func: () => number = () => 1; + +// use safer object types +const lowerObj: object = {}; +const capitalObj: { a: string } = { a: 'string' }; + +const curly1: number = 1; +const curly2: Record<'a', string> = { a: 'string' }; +" +`; diff --git a/packages/eslint-plugin/tests/docs-eslint-output-snapshots/class-literal-property-style.shot b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/class-literal-property-style.shot new file mode 100644 index 000000000000..743ed68dd08e --- /dev/null +++ b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/class-literal-property-style.shot @@ -0,0 +1,63 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[` 1`] = ` +"class Mx { + public static get myField1() { + ~~~~~~~~ Literals should be exposed using readonly fields. + return 1; + } + + private get ['myField2']() { + ~~~~~~~~~~ Literals should be exposed using readonly fields. + return 'hello world'; + } +} +" +`; + +exports[` 2`] = ` +"class Mx { + public readonly myField1 = 1; + + // not a literal + public readonly myField2 = [1, 2, 3]; + + private readonly ['myField3'] = 'hello world'; + + public get myField4() { + return \`hello from \${window.location.href}\`; + } +} +" +`; + +exports[` 3`] = ` +"class Mx { + readonly myField1 = 1; + ~~~~~~~~ Literals should be exposed using getters. + readonly myField2 = \`hello world\`; + ~~~~~~~~ Literals should be exposed using getters. + private readonly myField3 = 'hello world'; + ~~~~~~~~ Literals should be exposed using getters. +} +" +`; + +exports[` 4`] = ` +"class Mx { + // no readonly modifier + public myField1 = 'hello'; + + // not a literal + public readonly myField2 = [1, 2, 3]; + + public static get myField3() { + return 1; + } + + private get ['myField4']() { + return 'hello world'; + } +} +" +`; diff --git a/packages/eslint-plugin/tests/docs-eslint-output-snapshots/class-methods-use-this.shot b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/class-methods-use-this.shot new file mode 100644 index 000000000000..6d1fecfc13fe --- /dev/null +++ b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/class-methods-use-this.shot @@ -0,0 +1,43 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[` 1`] = ` +"class X { + override method() {} + override property = () => {}; +} +" +`; + +exports[` 2`] = ` +"class X implements Y { + method() {} + property = () => {}; +} +" +`; + +exports[` 3`] = ` +"class X implements Y { + method() {} + property = () => {}; + + private privateMethod() {} + ~~~~~~~~~~~~~~~~~~~~~ Expected 'this' to be used by class method 'privateMethod'. + private privateProperty = () => {}; + ~~~~~~~~~~~~~~~~~~~~~~~~~~ Expected 'this' to be used by class method 'privateProperty'. + + protected privateMethod() {} + ~~~~~~~~~~~~~~~~~~~~~~~ Expected 'this' to be used by class method 'privateMethod'. + protected privateProperty = () => {}; + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Expected 'this' to be used by class method 'privateProperty'. +} +" +`; + +exports[` 4`] = ` +"class X implements Y { + method() {} + property = () => {}; +} +" +`; diff --git a/packages/eslint-plugin/tests/docs-eslint-output-snapshots/consistent-generic-constructors.shot b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/consistent-generic-constructors.shot new file mode 100644 index 000000000000..98c8adbc1e60 --- /dev/null +++ b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/consistent-generic-constructors.shot @@ -0,0 +1,34 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[` 1`] = ` +"const map: Map = new Map(); + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ The generic type arguments should be specified as part of the constructor type arguments. +const set: Set = new Set(); + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ The generic type arguments should be specified as part of the constructor type arguments. +" +`; + +exports[` 2`] = ` +"const map = new Map(); +const map: Map = new MyMap(); +const set = new Set(); +const set = new Set(); +const set: Set = new Set(); +" +`; + +exports[` 3`] = ` +"const map = new Map(); + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ The generic type arguments should be specified as part of the type annotation. +const set = new Set(); + ~~~~~~~~~~~~~~~~~~~~~~~ The generic type arguments should be specified as part of the type annotation. +" +`; + +exports[` 4`] = ` +"const map: Map = new Map(); +const set: Set = new Set(); +const set = new Set(); +const set: Set = new Set(); +" +`; diff --git a/packages/eslint-plugin/tests/docs-eslint-output-snapshots/consistent-indexed-object-style.shot b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/consistent-indexed-object-style.shot new file mode 100644 index 000000000000..c68e2217ea4f --- /dev/null +++ b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/consistent-indexed-object-style.shot @@ -0,0 +1,40 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[` 1`] = ` +"interface Foo { +~ A record is preferred over an index signature. + [key: string]: unknown; +~~~~~~~~~~~~~~~~~~~~~~~~~ +} +~ + +type Foo = { + ~ A record is preferred over an index signature. + [key: string]: unknown; +~~~~~~~~~~~~~~ +}; +~ +" +`; + +exports[` 2`] = ` +"type Foo = Record; +" +`; + +exports[` 3`] = ` +"type Foo = Record; + ~~~~~~~~~~~~~~~~~~~~~~~ An index signature is preferred over a record. +" +`; + +exports[` 4`] = ` +"interface Foo { + [key: string]: unknown; +} + +type Foo = { + [key: string]: unknown; +}; +" +`; diff --git a/packages/eslint-plugin/tests/docs-eslint-output-snapshots/consistent-type-assertions.shot b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/consistent-type-assertions.shot new file mode 100644 index 000000000000..bff2df808b89 --- /dev/null +++ b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/consistent-type-assertions.shot @@ -0,0 +1,47 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[` 1`] = ` +"const x = { foo: 1 } as T; + ~~~~~~~~~~~~~~~ Always prefer const x: T = { ... }. + +function bar() { + return { foo: 1 } as T; + ~~~~~~~~~~~~~~~ Always prefer const x: T = { ... }. +} +" +`; + +exports[` 2`] = ` +"const x: T = { foo: 1 }; +const y = { foo: 1 } as any; +const z = { foo: 1 } as unknown; + +function bar(): T { + return { foo: 1 }; +} +" +`; + +exports[` 3`] = ` +"const x = { foo: 1 } as T; + ~~~~~~~~~~~~~~~ Always prefer const x: T = { ... }. + +function bar() { + return { foo: 1 } as T; + ~~~~~~~~~~~~~~~ Always prefer const x: T = { ... }. +} +" +`; + +exports[` 4`] = ` +"const x: T = { foo: 1 }; +const y = { foo: 1 } as any; +const z = { foo: 1 } as unknown; +bar({ foo: 1 } as T); +new Clazz({ foo: 1 } as T); +function bar() { + throw { foo: 1 } as Foo; +} +const foo = ; +" +`; diff --git a/packages/eslint-plugin/tests/docs-eslint-output-snapshots/consistent-type-definitions.shot b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/consistent-type-definitions.shot new file mode 100644 index 000000000000..c78d36814e73 --- /dev/null +++ b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/consistent-type-definitions.shot @@ -0,0 +1,30 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[` 1`] = ` +"type T = { x: number }; + ~ Use an \`interface\` instead of a \`type\`. +" +`; + +exports[` 2`] = ` +"type T = string; +type Foo = string | {}; + +interface T { + x: number; +} +" +`; + +exports[` 3`] = ` +"interface T { + ~ Use a \`type\` instead of an \`interface\`. + x: number; +} +" +`; + +exports[` 4`] = ` +"type T = { x: number }; +" +`; diff --git a/packages/eslint-plugin/tests/docs-eslint-output-snapshots/consistent-type-exports.shot b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/consistent-type-exports.shot new file mode 100644 index 000000000000..b0abb58dcafd --- /dev/null +++ b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/consistent-type-exports.shot @@ -0,0 +1,29 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[` 1`] = ` +"interface ButtonProps { + onClick: () => void; +} + +class Button implements ButtonProps { + onClick = () => console.log('button!'); +} + +export { Button, ButtonProps }; +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Type export ButtonProps is not a value and should be exported using \`export type\`. +" +`; + +exports[` 2`] = ` +"interface ButtonProps { + onClick: () => void; +} + +class Button implements ButtonProps { + onClick = () => console.log('button!'); +} + +export { Button }; +export type { ButtonProps }; +" +`; diff --git a/packages/eslint-plugin/tests/docs-eslint-output-snapshots/consistent-type-imports.shot b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/consistent-type-imports.shot new file mode 100644 index 000000000000..9a9b7141419f --- /dev/null +++ b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/consistent-type-imports.shot @@ -0,0 +1,53 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[` 1`] = ` +"import type { Foo } from 'Foo'; +import type Bar from 'Bar'; +type T = Foo; +const x: Bar = 1; +" +`; + +exports[` 2`] = ` +"import { Foo } from 'Foo'; +~~~~~~~~~~~~~~~~~~~~~~~~~~ All imports in the declaration are only used as types. Use \`import type\`. +import Bar from 'Bar'; +~~~~~~~~~~~~~~~~~~~~~~ All imports in the declaration are only used as types. Use \`import type\`. +type T = Foo; +const x: Bar = 1; +" +`; + +exports[` 3`] = ` +"import { Foo } from 'Foo'; +~~~~~~~~~~~~~~~~~~~~~~~~~~ All imports in the declaration are only used as types. Use \`import type\`. +import Bar from 'Bar'; +~~~~~~~~~~~~~~~~~~~~~~ All imports in the declaration are only used as types. Use \`import type\`. +type T = Foo; +const x: Bar = 1; +" +`; + +exports[` 4`] = ` +"import type { Foo } from 'Foo'; +import type Bar from 'Bar'; +type T = Foo; +const x: Bar = 1; +" +`; + +exports[` 5`] = ` +"import { type Foo } from 'Foo'; +import type Bar from 'Bar'; +type T = Foo; +const x: Bar = 1; +" +`; + +exports[` 6`] = ` +"type T = import('Foo').Foo; + ~~~~~~~~~~~~~~~~~ \`import()\` type annotations are forbidden. +const x: import('Bar') = 1; + ~~~~~~~~~~~~~ \`import()\` type annotations are forbidden. +" +`; diff --git a/packages/eslint-plugin/tests/docs-eslint-output-snapshots/default-param-last.shot b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/default-param-last.shot new file mode 100644 index 000000000000..24e12e0a9d45 --- /dev/null +++ b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/default-param-last.shot @@ -0,0 +1,46 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[` 1`] = ` +"function f(a = 0, b: number) {} + ~~~~~ Default parameters should be last. +function f(a: number, b = 0, c: number) {} + ~~~~~ Default parameters should be last. +function f(a: number, b?: number, c: number) {} + ~~~~~~~~~~ Default parameters should be last. +class Foo { + constructor( + public a = 10, + ~~~~~~~~~~~~~ Default parameters should be last. + private b: number, + ) {} +} +class Foo { + constructor( + public a?: number, + ~~~~~~~~~~~~~~~~~ Default parameters should be last. + private b: number, + ) {} +} +" +`; + +exports[` 2`] = ` +"function f(a = 0) {} +function f(a: number, b = 0) {} +function f(a: number, b?: number) {} +function f(a: number, b?: number, c = 0) {} +function f(a: number, b = 0, c?: number) {} +class Foo { + constructor( + public a, + private b = 0, + ) {} +} +class Foo { + constructor( + public a, + private b?: number, + ) {} +} +" +`; diff --git a/packages/eslint-plugin/tests/docs-eslint-output-snapshots/dot-notation.shot b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/dot-notation.shot new file mode 100644 index 000000000000..2bf4ca2eaa82 --- /dev/null +++ b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/dot-notation.shot @@ -0,0 +1,31 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[` 1`] = ` +"class X { + private priv_prop = 123; +} + +const x = new X(); +x['priv_prop'] = 123; +" +`; + +exports[` 2`] = ` +"class X { + protected protected_prop = 123; +} + +const x = new X(); +x['protected_prop'] = 123; +" +`; + +exports[` 3`] = ` +"class X { + [key: string]: number; +} + +const x = new X(); +x['hello'] = 123; +" +`; diff --git a/packages/eslint-plugin/tests/docs-eslint-output-snapshots/explicit-function-return-type.shot b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/explicit-function-return-type.shot new file mode 100644 index 000000000000..5d8f74003d40 --- /dev/null +++ b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/explicit-function-return-type.shot @@ -0,0 +1,216 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[` 1`] = ` +"// Should indicate that no value is returned (void) +function test() { +~~~~~~~~~~~~~ Missing return type on function. + return; +} + +// Should indicate that a number is returned +var fn = function () { + ~~~~~~~~~ Missing return type on function. + return 1; +}; + +// Should indicate that a string is returned +var arrowFn = () => 'test'; + ~~ Missing return type on function. + +class Test { + // Should indicate that no value is returned (void) + method() { + ~~~~~~ Missing return type on function. + return; + } +} +" +`; + +exports[` 2`] = ` +"// No return value should be expected (void) +function test(): void { + return; +} + +// A return value of type number +var fn = function (): number { + return 1; +}; + +// A return value of type string +var arrowFn = (): string => 'test'; + +class Test { + // No return value should be expected (void) + method(): void { + return; + } +} +" +`; + +exports[` 3`] = ` +"function test() {} +~~~~~~~~~~~~~ Missing return type on function. + +const fn = () => {}; + ~~ Missing return type on function. + +export default () => {}; + ~~ Missing return type on function. +" +`; + +exports[` 4`] = ` +"node.addEventListener('click', () => {}); + +node.addEventListener('click', function () {}); + +const foo = arr.map(i => i * i); +" +`; + +exports[` 5`] = ` +"let arrowFn = () => 'test'; + ~~ Missing return type on function. + +let funcExpr = function () { + ~~~~~~~~~ Missing return type on function. + return 'test'; +}; + +let objectProp = { + foo: () => 1, + ~~~~~ Missing return type on function. +}; +" +`; + +exports[` 6`] = ` +"type FuncType = () => string; + +let arrowFn: FuncType = () => 'test'; + +let funcExpr: FuncType = function () { + return 'test'; +}; + +let asTyped = (() => '') as () => string; +let castTyped = <() => string>(() => ''); + +interface ObjectType { + foo(): number; +} +let objectProp: ObjectType = { + foo: () => 1, +}; +let objectPropAs = { + foo: () => 1, +} as ObjectType; +let objectPropCast = { + foo: () => 1, +}; + +declare function functionWithArg(arg: () => number); +functionWithArg(() => 1); + +declare function functionWithObjectArg(arg: { method: () => number }); +functionWithObjectArg({ + method() { + return 1; + }, +}); +" +`; + +exports[` 7`] = ` +"var arrowFn = () => () => {}; + ~~ Missing return type on function. + +function fn() { + return function () {}; + ~~~~~~~~~ Missing return type on function. +} +" +`; + +exports[` 8`] = ` +"var arrowFn = () => (): void => {}; + +function fn() { + return function (): void {}; +} +" +`; + +exports[` 9`] = ` +"const func = (value: number) => ({ type: 'X', value }) as any; + ~~ Missing return type on function. +const func = (value: number) => ({ type: 'X', value }) as Action; + ~~ Missing return type on function. +" +`; + +exports[` 10`] = ` +"const func = (value: number) => ({ foo: 'bar', value }) as const; +const func = () => x as const; +" +`; + +exports[` 11`] = ` +"var join = (a: string, b: string) => \`\${a}\${b}\`; + ~~ Missing return type on function. + +const log = (message: string) => { + ~~ Missing return type on function. + console.log(message); +}; +" +`; + +exports[` 12`] = ` +"var log = (message: string) => void console.log(message); +" +`; + +exports[` 13`] = ` +"function foo(t: T) { +~~~~~~~~~~~~~~~ Missing return type on function. + return t; +} + +const bar = (t: T) => t; + ~~ Missing return type on function. +" +`; + +exports[` 14`] = ` +"function foo(t: T): T { + return t; +} + +const bar = (t: T): T => t; + +function allowedFunction(x: string) { + return x; +} + +const allowedArrow = (x: string) => x; +" +`; + +exports[` 15`] = ` +"var func = () => 'foo'; + ~~ Missing return type on function. +" +`; + +exports[` 16`] = ` +"var foo = (() => 'foo')(); + +var bar = (function () { + return 'bar'; +})(); +" +`; diff --git a/packages/eslint-plugin/tests/docs-eslint-output-snapshots/explicit-member-accessibility.shot b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/explicit-member-accessibility.shot new file mode 100644 index 000000000000..add13b35172b --- /dev/null +++ b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/explicit-member-accessibility.shot @@ -0,0 +1,273 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[` 1`] = ` +"class Animal { + constructor(name) { + ~ Missing accessibility modifier on method definition constructor. + // No accessibility modifier +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + this.animalName = name; +~~~~~~~~~~~~~~~~~~~~~~~~~ + } +~ + animalName: string; // No accessibility modifier + ~~~~~~~~~~~~~~~~~~~ Missing accessibility modifier on class property animalName. + get name(): string { + ~ Missing accessibility modifier on get property accessor name. + // No accessibility modifier +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + return this.animalName; +~~~~~~~~~~~~~~~~~~~~~~~~~ + } +~ + set name(value: string) { + ~ Missing accessibility modifier on set property accessor name. + // No accessibility modifier +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + this.animalName = value; +~~~~~~~~~~~~~~~~~~~~~~~~~~ + } +~ + walk() { + ~ Missing accessibility modifier on method definition walk. + // method +~~~~~~~~~~~ + } +~ +} +" +`; + +exports[` 2`] = ` +"class Animal { + public constructor( + public breed, + name, + ) { + // Parameter property and constructor + this.animalName = name; + } + private animalName: string; // Property + get name(): string { + ~ Missing accessibility modifier on get property accessor name. + // get accessor +~~~~~~~~~~~~~~~~~ + return this.animalName; +~~~~~~~~~~~~~~~~~~~~~~~~~ + } +~ + set name(value: string) { + ~ Missing accessibility modifier on set property accessor name. + // set accessor +~~~~~~~~~~~~~~~~~ + this.animalName = value; +~~~~~~~~~~~~~~~~~~~~~~~~~~ + } +~ + public walk() { + // method + } +} +" +`; + +exports[` 3`] = ` +"class Animal { + public constructor( + ~ Public accessibility modifier on method definition constructor. + public breed, +~~~~~~~~~~~~~~~ + name, +~~~~~~~ + ) { +~~~ + // Parameter property and constructor +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + this.animalName = name; +~~~~~~~~~~~~~~~~~~~~~~~~~ + } +~ + public animalName: string; // Property + ~~~~~~~~~~~~~~~~~~~~~~~~~~ Public accessibility modifier on class property animalName. + public get name(): string { + ~ Public accessibility modifier on get property accessor name. + // get accessor +~~~~~~~~~~~~~~~~~ + return this.animalName; +~~~~~~~~~~~~~~~~~~~~~~~~~ + } +~ + public set name(value: string) { + ~ Public accessibility modifier on set property accessor name. + // set accessor +~~~~~~~~~~~~~~~~~ + this.animalName = value; +~~~~~~~~~~~~~~~~~~~~~~~~~~ + } +~ + public walk() { + ~ Public accessibility modifier on method definition walk. + // method +~~~~~~~~~~~ + } +~ +} +" +`; + +exports[` 4`] = ` +"class Animal { + constructor( + protected breed, + name, + ) { + // Parameter property and constructor + this.name = name; + } + private animalName: string; // Property + get name(): string { + // get accessor + return this.animalName; + } + private set name(value: string) { + // set accessor + this.animalName = value; + } + protected walk() { + // method + } +} +" +`; + +exports[` 5`] = ` +"class Animal { + public constructor(protected animalName) {} + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Public accessibility modifier on method definition constructor. + public get name() { + return this.animalName; + } +} +" +`; + +exports[` 6`] = ` +"class Animal { + constructor(protected animalName) {} + public get name() { + return this.animalName; + } +} +" +`; + +exports[` 7`] = ` +"class Animal { + constructor(protected animalName) {} + get name() { + return this.animalName; + } + protected set name(value: string) { + this.animalName = value; + } + legs: number; + ~~~~~~~~~~~~~ Missing accessibility modifier on class property legs. + private hasFleas: boolean; +} +" +`; + +exports[` 8`] = ` +"class Animal { + constructor(protected animalName) {} + get name() { + return this.animalName; + } + protected set name(value: string) { + this.animalName = value; + } + public legs: number; + private hasFleas: boolean; +} +" +`; + +exports[` 9`] = ` +"class Animal { + constructor(readonly animalName: string) {} + ~~~~~~~~~~~~~~~~~~~~~~~~~~~ Missing accessibility modifier on parameter property animalName. +} +" +`; + +exports[` 10`] = ` +"class Animal { + constructor(public readonly animalName: string) {} +} + +class Animal { + constructor(public animalName: string) {} +} + +class Animal { + constructor(animalName: string) {} +} +" +`; + +exports[` 11`] = ` +"class Animal { + constructor(public readonly animalName: string) {} + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Public accessibility modifier on parameter property animalName. +} +" +`; + +exports[` 12`] = ` +"class Animal { + constructor(public animalName: string) {} +} +" +`; + +exports[` 13`] = ` +"class Animal { + constructor(protected animalName) {} + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Missing accessibility modifier on method definition constructor. + public get name() { + return this.animalName; + } + get legs() { + return this.legCount; + } +} +" +`; + +exports[` 14`] = ` +"class Animal { + public constructor(protected animalName) {} + public get name() { + return this.animalName; + } + get legs() { + return this.legCount; + } +} +" +`; + +exports[` 15`] = ` +"class Animal { + get specificMethod() { + console.log('No error because you specified this method on option'); + } + get whateverMethod() { + console.log('No error because you specified this method on option'); + } + public get otherMethod() { + console.log('This method comply with this rule'); + } +} +" +`; diff --git a/packages/eslint-plugin/tests/docs-eslint-output-snapshots/explicit-module-boundary-types.shot b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/explicit-module-boundary-types.shot new file mode 100644 index 000000000000..81e1e7eb2686 --- /dev/null +++ b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/explicit-module-boundary-types.shot @@ -0,0 +1,170 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[` 1`] = ` +"// Should indicate that no value is returned (void) +export function test() { + ~~~~~~~~~~~~~ Missing return type on function. + return; +} + +// Should indicate that a string is returned +export var arrowFn = () => 'test'; + ~~ Missing return type on function. + +// All arguments should be typed +export var arrowFn = (arg): string => \`test \${arg}\`; + ~~~ Argument 'arg' should be typed. +export var arrowFn = (arg: any): string => \`test \${arg}\`; + ~~~~~~~~ Argument 'arg' should be typed with a non-any type. + +export class Test { + // Should indicate that no value is returned (void) + method() { + ~~~~~~ Missing return type on function. + return; + } +} +" +`; + +exports[` 2`] = ` +"// A function with no return value (void) +export function test(): void { + return; +} + +// A return value of type string +export var arrowFn = (): string => 'test'; + +// All arguments should be typed +export var arrowFn = (arg: string): string => \`test \${arg}\`; +export var arrowFn = (arg: unknown): string => \`test \${arg}\`; + +export class Test { + // A class method with no return value (void) + method(): void { + return; + } +} + +// The function does not apply because it is not an exported function. +function test() { + return; +} +" +`; + +exports[` 3`] = ` +"export const func = (value: any): number => value + 1; + ~~~~~~~~~~ Argument 'value' should be typed with a non-any type. +" +`; + +exports[` 4`] = ` +"export const func = (value: any): number => value + 1; +" +`; + +exports[` 5`] = ` +"export const func = (value: number) => ({ type: 'X', value }); + ~~ Missing return type on function. +export const foo = () => ({ + ~~ Missing return type on function. + bar: true, +}); +export const bar = () => 1; + ~~ Missing return type on function. +" +`; + +exports[` 6`] = ` +"export const func = (value: number) => ({ type: 'X', value }) as const; +export const foo = () => + ({ + bar: true, + }) as const; +export const bar = () => 1 as const; +" +`; + +exports[` 7`] = ` +"export const arrowFn = () => () => {}; + ~~ Missing return type on function. + ~~ Missing return type on function. + +export function fn() { + ~~~~~~~~~~~ Missing return type on function. + return function () {}; + ~~~~~~~~~ Missing return type on function. +} + +export function foo(outer: string) { + ~~~~~~~~~~~~ Missing return type on function. + return function (inner: string) {}; + ~~~~~~~~~ Missing return type on function. +} +" +`; + +exports[` 8`] = ` +"export const arrowFn = () => (): void => {}; + +export function fn() { + return function (): void {}; +} + +export function foo(outer: string) { + return function (inner: string): void {}; +} +" +`; + +exports[` 9`] = ` +"export let arrowFn = () => 'test'; + ~~ Missing return type on function. + +export let funcExpr = function () { + ~~~~~~~~~ Missing return type on function. + return 'test'; +}; + +export let objectProp = { + foo: () => 1, + ~~~~~ Missing return type on function. +}; + +export const foo = bar => {}; + ~~~ Argument 'bar' should be typed. + ~~ Missing return type on function. +" +`; + +exports[` 10`] = ` +"type FuncType = () => string; + +export let arrowFn: FuncType = () => 'test'; + +export let funcExpr: FuncType = function () { + return 'test'; +}; + +export let asTyped = (() => '') as () => string; +export let castTyped = <() => string>(() => ''); + +interface ObjectType { + foo(): number; +} +export let objectProp: ObjectType = { + foo: () => 1, +}; +export let objectPropAs = { + foo: () => 1, +} as ObjectType; +export let objectPropCast = { + foo: () => 1, +}; + +type FooType = (bar: string) => void; +export const foo: FooType = bar => {}; +" +`; diff --git a/packages/eslint-plugin/tests/docs-eslint-output-snapshots/lines-between-class-members.shot b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/lines-between-class-members.shot new file mode 100644 index 000000000000..b3fe1f11d8c7 --- /dev/null +++ b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/lines-between-class-members.shot @@ -0,0 +1,29 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[` 1`] = ` +"class foo { + bar(a: string): void; + bar(a: string, b: string): void; + bar(a: string, b: string) {} + + baz() {} + + qux() {} +} +" +`; + +exports[` 2`] = ` +"class foo { + bar(a: string): void; + + bar(a: string, b: string): void; + + bar(a: string, b: string) {} + + baz() {} + + qux() {} +} +" +`; diff --git a/packages/eslint-plugin/tests/docs-eslint-output-snapshots/member-delimiter-style.shot b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/member-delimiter-style.shot new file mode 100644 index 000000000000..6789ba907f61 --- /dev/null +++ b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/member-delimiter-style.shot @@ -0,0 +1,54 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[` 1`] = ` +"// missing semicolon delimiter +interface Foo { + name: string + ~ Expected a semicolon. + greet(): string + ~ Expected a semicolon. +} + +// using incorrect delimiter +interface Bar { + name: string, + ~ Expected a semicolon. + greet(): string, + ~ Expected a semicolon. +} + +// missing last member delimiter +interface Baz { + name: string; + greet(): string + ~ Expected a semicolon. +} + +// incorrect delimiter +type FooBar = { name: string, greet(): string } + ~ Expected a semicolon. + +// last member should not have delimiter +type FooBar = { name: string; greet(): string; } + ~ Unexpected separator (;). +" +`; + +exports[` 2`] = ` +"interface Foo { + name: string; + greet(): string; +} + +interface Foo { name: string } + +type Bar = { + name: string; + greet(): string; +} + +type Bar = { name: string } + +type FooBar = { name: string; greet(): string } +" +`; diff --git a/packages/eslint-plugin/tests/docs-eslint-output-snapshots/member-ordering.shot b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/member-ordering.shot new file mode 100644 index 000000000000..4b970c3bf474 --- /dev/null +++ b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/member-ordering.shot @@ -0,0 +1,549 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[` 1`] = ` +"interface Foo { + B: string; // -> field + + new (); // -> constructor + ~~~~~~~ Member new should be declared before all field definitions. + + A(): void; // -> method + ~~~~~~~~~~ Member A should be declared before all field definitions. + + [Z: string]: any; // -> signature + ~~~~~~~~~~~~~~~~~ Member Z should be declared before all field definitions. +} +" +`; + +exports[` 2`] = ` +"type Foo = { + B: string; // -> field + + // no constructor + + A(): void; // -> method + ~~~~~~~~~~ Member A should be declared before all field definitions. + + // no signature +}; +" +`; + +exports[` 3`] = ` +"class Foo { + private C: string; // -> field + public D: string; // -> field + protected static E: string; // -> field + + constructor() {} // -> constructor + ~~~~~~~~~~~~~~~~ Member constructor should be declared before all field definitions. + + public static A(): void {} // -> method + ~~~~~~~~~~~~~~~~~~~~~~~~~~ Member A should be declared before all field definitions. + public B(): void {} // -> method + ~~~~~~~~~~~~~~~~~~~ Member B should be declared before all field definitions. + + [Z: string]: any; // -> signature + ~~~~~~~~~~~~~~~~~ Member Z should be declared before all field definitions. +} +" +`; + +exports[` 4`] = ` +"const Foo = class { + private C: string; // -> field + public D: string; // -> field + + constructor() {} // -> constructor + ~~~~~~~~~~~~~~~~ Member constructor should be declared before all field definitions. + + public static A(): void {} // -> method + ~~~~~~~~~~~~~~~~~~~~~~~~~~ Member A should be declared before all field definitions. + public B(): void {} // -> method + ~~~~~~~~~~~~~~~~~~~ Member B should be declared before all field definitions. + + [Z: string]: any; // -> signature + ~~~~~~~~~~~~~~~~~ Member Z should be declared before all field definitions. + + protected static E: string; // -> field +}; +" +`; + +exports[` 5`] = ` +"interface Foo { + [Z: string]: any; // -> signature + + A(): void; // -> method + + new (); // -> constructor + + B: string; // -> field +} +" +`; + +exports[` 6`] = ` +"type Foo = { + // no signature + + A(): void; // -> method + + // no constructor + + B: string; // -> field +}; +" +`; + +exports[` 7`] = ` +"class Foo { + [Z: string]: any; // -> signature + + public static A(): void {} // -> method + public B(): void {} // -> method + + constructor() {} // -> constructor + + private C: string; // -> field + public D: string; // -> field + protected static E: string; // -> field +} +" +`; + +exports[` 8`] = ` +"const Foo = class { + [Z: string]: any; // -> signature + + public static A(): void {} // -> method + public B(): void {} // -> method + + constructor() {} // -> constructor + + private C: string; // -> field + public D: string; // -> field + protected static E: string; // -> field +}; +" +`; + +exports[` 9`] = ` +"class Foo { + private C: string; // (irrelevant) + + public D: string; // (irrelevant) + + public static E: string; // -> public static field + + constructor() {} // (irrelevant) + + public static A(): void {} // (irrelevant) + + [Z: string]: any; // (irrelevant) + + public B(): void {} // -> public instance method + ~~~~~~~~~~~~~~~~~~~ Member B should be declared before all public static field definitions. +} +" +`; + +exports[` 10`] = ` +"const Foo = class { + private C: string; // (irrelevant) + + [Z: string]: any; // (irrelevant) + + public static E: string; // -> public static field + + public D: string; // (irrelevant) + + constructor() {} // (irrelevant) + + public static A(): void {} // (irrelevant) + + public B(): void {} // -> public instance method + ~~~~~~~~~~~~~~~~~~~ Member B should be declared before all public static field definitions. +}; +" +`; + +exports[` 11`] = ` +"class Foo { + public B(): void {} // -> public instance method + + private C: string; // (irrelevant) + + public D: string; // (irrelevant) + + public static E: string; // -> public static field + + constructor() {} // (irrelevant) + + public static A(): void {} // (irrelevant) + + [Z: string]: any; // (irrelevant) +} +" +`; + +exports[` 12`] = ` +"const Foo = class { + public B(): void {} // -> public instance method + + private C: string; // (irrelevant) + + [Z: string]: any; // (irrelevant) + + public D: string; // (irrelevant) + + constructor() {} // (irrelevant) + + public static A(): void {} // (irrelevant) + + public static E: string; // -> public static field +}; +" +`; + +exports[` 13`] = ` +"class Foo { + private E: string; // -> instance field + + private static B: string; // -> static field + ~~~~~~~~~~~~~~~~~~~~~~~~~ Member B should be declared before all instance field definitions. + protected static C: string; // -> static field + ~~~~~~~~~~~~~~~~~~~~~~~~~~~ Member C should be declared before all instance field definitions. + private static D: string; // -> static field + ~~~~~~~~~~~~~~~~~~~~~~~~~ Member D should be declared before all instance field definitions. + + public static A: string; // -> public static field + ~~~~~~~~~~~~~~~~~~~~~~~~ Member A should be declared before all instance field definitions. + + [Z: string]: any; // (irrelevant) +} +" +`; + +exports[` 14`] = ` +"const foo = class { + public T(): void {} // method (irrelevant) + + private static B: string; // -> static field + + constructor() {} // constructor (irrelevant) + + private E: string; // -> instance field + + protected static C: string; // -> static field + ~~~~~~~~~~~~~~~~~~~~~~~~~~~ Member C should be declared before all instance field definitions. + private static D: string; // -> static field + ~~~~~~~~~~~~~~~~~~~~~~~~~ Member D should be declared before all instance field definitions. + + [Z: string]: any; // signature (irrelevant) + + public static A: string; // -> public static field + ~~~~~~~~~~~~~~~~~~~~~~~~ Member A should be declared before all static field definitions. +}; +" +`; + +exports[` 15`] = ` +"class Foo { + public static A: string; // -> public static field + + private static B: string; // -> static field + protected static C: string; // -> static field + private static D: string; // -> static field + + private E: string; // -> instance field + + [Z: string]: any; // (irrelevant) +} +" +`; + +exports[` 16`] = ` +"const foo = class { + [Z: string]: any; // -> signature (irrelevant) + + public static A: string; // -> public static field + + constructor() {} // -> constructor (irrelevant) + + private static B: string; // -> static field + protected static C: string; // -> static field + private static D: string; // -> static field + + private E: string; // -> instance field + + public T(): void {} // -> method (irrelevant) +}; +" +`; + +exports[` 17`] = ` +"class Foo { + private C: string; // -> field + public D: string; // -> field + protected static E: string; // -> field + + constructor() {} // -> constructor + ~~~~~~~~~~~~~~~~ Member constructor should be declared before all field definitions. + + public static A(): void {} // -> method + ~~~~~~~~~~~~~~~~~~~~~~~~~~ Member A should be declared before all field definitions. + public B(): void {} // -> method + ~~~~~~~~~~~~~~~~~~~ Member B should be declared before all field definitions. +} +" +`; + +exports[` 18`] = ` +"class Foo { + public static A(): void {} // -> method + public B(): void {} // -> method + + constructor() {} // -> constructor + + private C: string; // -> field + public D: string; // -> field + protected static E: string; // -> field +} +" +`; + +exports[` 19`] = ` +"const foo = class { + private C: string; // -> field + public D: string; // -> field + protected static E: string; // -> field + + constructor() {} // -> constructor + ~~~~~~~~~~~~~~~~ Member constructor should be declared before all field definitions. + + public static A(): void {} // -> method + ~~~~~~~~~~~~~~~~~~~~~~~~~~ Member A should be declared before all field definitions. + public B(): void {} // -> method + ~~~~~~~~~~~~~~~~~~~ Member B should be declared before all field definitions. +}; +" +`; + +exports[` 20`] = ` +"const foo = class { + public static A(): void {} // -> method + public B(): void {} // -> method + + constructor() {} // -> constructor + + private C: string; // -> field + public D: string; // -> field + protected static E: string; // -> field +}; +" +`; + +exports[` 21`] = ` +"interface Foo { + B: string; // -> field + + new (); // -> constructor + ~~~~~~~ Member new should be declared before all field definitions. + + A(): void; // -> method + ~~~~~~~~~~ Member A should be declared before all field definitions. + + [Z: string]: any; // -> signature + ~~~~~~~~~~~~~~~~~ Member Z should be declared before all field definitions. +} +" +`; + +exports[` 22`] = ` +"interface Foo { + [Z: string]: any; // -> signature + + A(): void; // -> method + + new (); // -> constructor + + B: string; // -> field +} +" +`; + +exports[` 23`] = ` +"type Foo = { + B: string; // -> field + + A(): void; // -> method + ~~~~~~~~~~ Member A should be declared before all field definitions. + + new (); // -> constructor + ~~~~~~~ Member new should be declared before all field definitions. + + [Z: string]: any; // -> signature + ~~~~~~~~~~~~~~~~~ Member Z should be declared before all field definitions. +}; +" +`; + +exports[` 24`] = ` +"type Foo = { + [Z: string]: any; // -> signature + + A(): void; // -> method + + new (); // -> constructor + + B: string; // -> field +}; +" +`; + +exports[` 25`] = ` +"interface Foo { + a: x; + B: x; + ~~~~~ Member B should be declared before member a. + c: x; + + B(): void; + c(): void; + a(): void; +} +" +`; + +exports[` 26`] = ` +"interface Foo { + B: x; + a: x; + c: x; + + B(): void; + a(): void; + c(): void; +} +" +`; + +exports[` 27`] = ` +"interface Foo { + B(): void; + c(): void; + a(): void; + ~~~~~~~~~~ Member a should be declared before member c. + + a: x; + B: x; + c: x; +} +" +`; + +exports[` 28`] = ` +"interface Foo { + B(): void; + a(): void; + c(): void; + + B: x; + a: x; + c: x; +} +" +`; + +exports[` 29`] = ` +"interface Foo { + B: x; + a: x; + ~~~~~ Member a should be declared before member B. + c: x; + + B(): void; + c(): void; + a(): void; +} +" +`; + +exports[` 30`] = ` +"interface Foo { + a: x; + B: x; + c: x; + + a(): void; + B(): void; + c(): void; +} +" +`; + +exports[` 31`] = ` +"interface Foo { + b(): void; + a: boolean; + ~~~~~~~~~~~ Member a should be declared before member b. + + [a: string]: number; + new (): Bar; + (): Baz; + ~~~~~~~~ Member call should be declared before member new. +} +" +`; + +exports[` 32`] = ` +"interface Foo { + [a: string]: number; + a: boolean; + b(): void; + + (): Baz; + new (): Bar; +} +" +`; + +exports[` 33`] = ` +"interface Foo { + a: boolean; + ~~~~~~~~~~~ Member a should be declared after all optional members. + b?: number; + c: string; +} +" +`; + +exports[` 34`] = ` +"interface Foo { + b?: number; + a: boolean; + c: string; +} +" +`; + +exports[` 35`] = ` +"interface Foo { + a: boolean; + b?: number; + ~~~~~~~~~~~ Member b should be declared after all required members. + c: string; +} +" +`; + +exports[` 36`] = ` +"interface Foo { + a: boolean; + c: string; + b?: number; +} +" +`; diff --git a/packages/eslint-plugin/tests/docs-eslint-output-snapshots/method-signature-style.shot b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/method-signature-style.shot new file mode 100644 index 000000000000..a061a3651a61 --- /dev/null +++ b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/method-signature-style.shot @@ -0,0 +1,59 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[` 1`] = ` +"interface T1 { + func(arg: string): number; + ~~~~~~~~~~~~~~~~~~~~~~~~~~ Shorthand method signature is forbidden. Use a function property instead. +} +type T2 = { + func(arg: boolean): void; + ~~~~~~~~~~~~~~~~~~~~~~~~~ Shorthand method signature is forbidden. Use a function property instead. +}; +interface T3 { + func(arg: number): void; + ~~~~~~~~~~~~~~~~~~~~~~~~ Shorthand method signature is forbidden. Use a function property instead. + func(arg: string): void; + ~~~~~~~~~~~~~~~~~~~~~~~~ Shorthand method signature is forbidden. Use a function property instead. + func(arg: boolean): void; + ~~~~~~~~~~~~~~~~~~~~~~~~~ Shorthand method signature is forbidden. Use a function property instead. +} +" +`; + +exports[` 2`] = ` +"interface T1 { + func: (arg: string) => number; +} +type T2 = { + func: (arg: boolean) => void; +}; +// this is equivalent to the overload +interface T3 { + func: ((arg: number) => void) & + ((arg: string) => void) & + ((arg: boolean) => void); +} +" +`; + +exports[` 3`] = ` +"interface T1 { + func: (arg: string) => number; + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Function property signature is forbidden. Use a method shorthand instead. +} +type T2 = { + func: (arg: boolean) => void; + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Function property signature is forbidden. Use a method shorthand instead. +}; +" +`; + +exports[` 4`] = ` +"interface T1 { + func(arg: string): number; +} +type T2 = { + func(arg: boolean): void; +}; +" +`; diff --git a/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-array-constructor.shot b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-array-constructor.shot new file mode 100644 index 000000000000..e4482f404076 --- /dev/null +++ b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-array-constructor.shot @@ -0,0 +1,18 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[` 1`] = ` +"Array(0, 1, 2); +~~~~~~~~~~~~~~ The array literal notation [] is preferable. +new Array(0, 1, 2); +~~~~~~~~~~~~~~~~~~ The array literal notation [] is preferable. +" +`; + +exports[` 2`] = ` +"Array(0, 1, 2); +new Array(x, y, z); + +Array(500); +new Array(someOtherArray.length); +" +`; diff --git a/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-array-delete.shot b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-array-delete.shot new file mode 100644 index 000000000000..2880709bda7c --- /dev/null +++ b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-array-delete.shot @@ -0,0 +1,16 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[` 1`] = ` +"declare const arr: number[]; + +delete arr[0]; +~~~~~~~~~~~~~ Using the \`delete\` operator with an array expression is unsafe. +" +`; + +exports[` 2`] = ` +"declare const arr: number[]; + +arr.splice(0, 1); +" +`; diff --git a/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-base-to-string.shot b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-base-to-string.shot new file mode 100644 index 000000000000..04570507341c --- /dev/null +++ b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-base-to-string.shot @@ -0,0 +1,52 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[` 1`] = ` +"// Passing an object or class instance to string concatenation: +'' + {}; + ~~ '{}' will evaluate to '[object Object]' when stringified. + +class MyClass {} +const value = new MyClass(); +value + ''; +~~~~~ 'value' will evaluate to '[object Object]' when stringified. + +// Interpolation and manual .toString() calls too: +\`Value: \${value}\`; + ~~~~~ 'value' will evaluate to '[object Object]' when stringified. +({}).toString(); + ~~ '{}' will evaluate to '[object Object]' when stringified. +" +`; + +exports[` 2`] = ` +"// These types all have useful .toString()s +'Text' + true; +\`Value: \${123}\`; +\`Arrays too: \${[1, 2, 3]}\`; +(() => {}).toString(); + +// Defining a custom .toString class is considered acceptable +class CustomToString { + toString() { + return 'Hello, world!'; + } +} +\`Value: \${new CustomToString()}\`; + +const literalWithToString = { + toString: () => 'Hello, world!', +}; + +\`Value: \${literalWithToString}\`; +" +`; + +exports[` 3`] = ` +"\`\${/regex/}\`; +'' + /regex/; +/regex/.toString(); +let value = /regex/; +value.toString(); +let text = \`\${value}\`; +" +`; diff --git a/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-confusing-non-null-assertion.shot b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-confusing-non-null-assertion.shot new file mode 100644 index 000000000000..4aac73ddf0b9 --- /dev/null +++ b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-confusing-non-null-assertion.shot @@ -0,0 +1,27 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[` 1`] = ` +"interface Foo { + bar?: string; + num?: number; +} + +const foo: Foo = getFoo(); +const isEqualsBar = foo.bar! == 'hello'; + ~~~~~~~~~~~~~~~~~~~ Confusing combinations of non-null assertion and equal test like "a! == b", which looks very similar to not equal "a !== b". +const isEqualsNum = 1 + foo.num! == 2; + ~~~~~~~~~~~~~~~~~ Confusing combinations of non-null assertion and equal test like "a! == b", which looks very similar to not equal "a !== b". +" +`; + +exports[` 2`] = ` +"interface Foo { + bar?: string; + num?: number; +} + +const foo: Foo = getFoo(); +const isEqualsBar = foo.bar == 'hello'; +const isEqualsNum = (1 + foo.num!) == 2; +" +`; diff --git a/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-confusing-void-expression.shot b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-confusing-void-expression.shot new file mode 100644 index 000000000000..cb7c2f4e63eb --- /dev/null +++ b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-confusing-void-expression.shot @@ -0,0 +1,74 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[` 1`] = ` +"// somebody forgot that \`alert\` doesn't return anything +const response = alert('Are you sure?'); +console.log(alert('Are you sure?')); + +// it's not obvious whether the chained promise will contain the response (fixable) +promise.then(value => window.postMessage(value)); + +// it looks like we are returning the result of \`console.error\` (fixable) +function doSomething() { + if (!somethingToDo) { + return console.error('Nothing to do!'); + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Returning a void expression from a function is forbidden. Please move it before the \`return\` statement. + } + + console.log('Doing a thing...'); +} +" +`; + +exports[` 2`] = ` +"// just a regular void function in a statement position +alert('Hello, world!'); + +// this function returns a boolean value so it's ok +const response = confirm('Are you sure?'); +console.log(confirm('Are you sure?')); + +// now it's obvious that \`postMessage\` doesn't return any response +promise.then(value => { + window.postMessage(value); +}); + +// now it's explicit that we want to log the error and return early +function doSomething() { + if (!somethingToDo) { + console.error('Nothing to do!'); + return; + } + + console.log('Doing a thing...'); +} + +// using logical expressions for their side effects is fine +cond && console.log('true'); +cond || console.error('false'); +cond ? console.log('true') : console.error('false'); +" +`; + +exports[` 3`] = ` +"promise.then(value => window.postMessage(value)); +" +`; + +exports[` 4`] = ` +"// now it's obvious that we don't expect any response +promise.then(value => void window.postMessage(value)); + +// now it's explicit that we don't want to return anything +function doSomething() { + if (!somethingToDo) { + return void console.error('Nothing to do!'); + } + + console.log('Doing a thing...'); +} + +// we are sure that we want to always log \`undefined\` +console.log(void alert('Hello, world!')); +" +`; diff --git a/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-duplicate-enum-values.shot b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-duplicate-enum-values.shot new file mode 100644 index 000000000000..7c893c000f5e --- /dev/null +++ b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-duplicate-enum-values.shot @@ -0,0 +1,35 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[` 1`] = ` +"enum E { + A = 0, + B = 0, + ~~~~~ Duplicate enum member value 0. +} +" +`; + +exports[` 2`] = ` +"enum E { + A = 'A', + B = 'A', + ~~~~~~~ Duplicate enum member value A. +} +" +`; + +exports[` 3`] = ` +"enum E { + A = 0, + B = 1, +} +" +`; + +exports[` 4`] = ` +"enum E { + A = 'A', + B = 'B', +} +" +`; diff --git a/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-duplicate-type-constituents.shot b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-duplicate-type-constituents.shot new file mode 100644 index 000000000000..3f63277e8984 --- /dev/null +++ b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-duplicate-type-constituents.shot @@ -0,0 +1,36 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[` 1`] = ` +"type T1 = 'A' | 'A'; + ~~~ Union type constituent is duplicated with 'A'. + +type T2 = A | A | B; + ~ Union type constituent is duplicated with A. + +type T3 = { a: string } & { a: string }; + ~~~~~~~~~~~~~ Intersection type constituent is duplicated with { a: string }. + +type T4 = [1, 2, 3] | [1, 2, 3]; + ~~~~~~~~~ Union type constituent is duplicated with [1, 2, 3]. + +type StringA = string; +type StringB = string; +type T5 = StringA | StringB; + ~~~~~~~ Union type constituent is duplicated with StringA. +" +`; + +exports[` 2`] = ` +"type T1 = 'A' | 'B'; + +type T2 = A | B | C; + +type T3 = { a: string } & { b: string }; + +type T4 = [1, 2, 3] | [1, 2, 3, 4]; + +type StringA = string; +type NumberB = number; +type T5 = StringA | NumberB; +" +`; diff --git a/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-dynamic-delete.shot b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-dynamic-delete.shot new file mode 100644 index 000000000000..c01d0d12c37e --- /dev/null +++ b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-dynamic-delete.shot @@ -0,0 +1,31 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[` 1`] = ` +"// Can be replaced with the constant equivalents, such as container.aaa +delete container['aaa']; + ~~~~~ Do not delete dynamically computed property keys. +delete container['Infinity']; + ~~~~~~~~~~ Do not delete dynamically computed property keys. + +// Dynamic, difficult-to-reason-about lookups +const name = 'name'; +delete container[name]; + ~~~~ Do not delete dynamically computed property keys. +delete container[name.toUpperCase()]; + ~~~~~~~~~~~~~~~~~~ Do not delete dynamically computed property keys. +" +`; + +exports[` 2`] = ` +"const container: { [i: string]: number } = { + /* ... */ +}; + +// Constant runtime lookups by string index +delete container.aaa; + +// Constants that must be accessed by [] +delete container[7]; +delete container['-Infinity']; +" +`; diff --git a/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-empty-function.shot b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-empty-function.shot new file mode 100644 index 000000000000..631169b1217e --- /dev/null +++ b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-empty-function.shot @@ -0,0 +1,36 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[` 1`] = ` +"class Foo { + private constructor() {} +} +" +`; + +exports[` 2`] = ` +"class Foo { + protected constructor() {} +} +" +`; + +exports[` 3`] = ` +"class Foo { + @decorator() + foo() {} +} +" +`; + +exports[` 4`] = ` +"abstract class Base { + protected greet(): void { + console.log('Hello!'); + } +} + +class Foo extends Base { + protected override greet(): void {} +} +" +`; diff --git a/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-empty-interface.shot b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-empty-interface.shot new file mode 100644 index 000000000000..febb7a6ee3f6 --- /dev/null +++ b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-empty-interface.shot @@ -0,0 +1,33 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[` 1`] = ` +"// an empty interface +interface Foo {} + ~~~ An empty interface is equivalent to \`{}\`. + +// an interface with only one supertype (Bar === Foo) +interface Bar extends Foo {} + ~~~ An interface declaring no members is equivalent to its supertype. + +// an interface with an empty list of supertypes +interface Baz {} + ~~~ An empty interface is equivalent to \`{}\`. +" +`; + +exports[` 2`] = ` +"// an interface with any number of members +interface Foo { + name: string; +} + +// same as above +interface Bar { + age: number; +} + +// an interface with more than one supertype +// in this case the interface can be used as a replacement of an intersection type. +interface Baz extends Foo, Bar {} +" +`; diff --git a/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-explicit-any.shot b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-explicit-any.shot new file mode 100644 index 000000000000..508781cf4edf --- /dev/null +++ b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-explicit-any.shot @@ -0,0 +1,139 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[` 1`] = ` +"const age: any = 'seventeen'; + ~~~ Unexpected any. Specify a different type. +" +`; + +exports[` 2`] = ` +"const ages: any[] = ['seventeen']; + ~~~ Unexpected any. Specify a different type. +" +`; + +exports[` 3`] = ` +"const ages: Array = ['seventeen']; + ~~~ Unexpected any. Specify a different type. +" +`; + +exports[` 4`] = ` +"function greet(): any {} + ~~~ Unexpected any. Specify a different type. +" +`; + +exports[` 5`] = ` +"function greet(): any[] {} + ~~~ Unexpected any. Specify a different type. +" +`; + +exports[` 6`] = ` +"function greet(): Array {} + ~~~ Unexpected any. Specify a different type. +" +`; + +exports[` 7`] = ` +"function greet(): Array> {} + ~~~ Unexpected any. Specify a different type. +" +`; + +exports[` 8`] = ` +"function greet(param: Array): string {} + ~~~ Unexpected any. Specify a different type. +" +`; + +exports[` 9`] = ` +"function greet(param: Array): Array {} + ~~~ Unexpected any. Specify a different type. + ~~~ Unexpected any. Specify a different type. +" +`; + +exports[` 10`] = ` +"const age: number = 17; +" +`; + +exports[` 11`] = ` +"const ages: number[] = [17]; +" +`; + +exports[` 12`] = ` +"const ages: Array = [17]; +" +`; + +exports[` 13`] = ` +"function greet(): string {} +" +`; + +exports[` 14`] = ` +"function greet(): string[] {} +" +`; + +exports[` 15`] = ` +"function greet(): Array {} +" +`; + +exports[` 16`] = ` +"function greet(): Array> {} +" +`; + +exports[` 17`] = ` +"function greet(param: Array): string {} +" +`; + +exports[` 18`] = ` +"function greet(param: Array): Array {} +" +`; + +exports[` 19`] = ` +"function foo1(...args: any[]): void {} + ~~~ Unexpected any. Specify a different type. +function foo2(...args: readonly any[]): void {} + ~~~ Unexpected any. Specify a different type. +function foo3(...args: Array): void {} + ~~~ Unexpected any. Specify a different type. +function foo4(...args: ReadonlyArray): void {} + ~~~ Unexpected any. Specify a different type. + +declare function bar(...args: any[]): void; + ~~~ Unexpected any. Specify a different type. + +const baz = (...args: any[]) => {}; + ~~~ Unexpected any. Specify a different type. +const qux = function (...args: any[]) {}; + ~~~ Unexpected any. Specify a different type. + +type Quux = (...args: any[]) => void; + ~~~ Unexpected any. Specify a different type. +type Quuz = new (...args: any[]) => void; + ~~~ Unexpected any. Specify a different type. + +interface Grault { + (...args: any[]): void; + ~~~ Unexpected any. Specify a different type. +} +interface Corge { + new (...args: any[]): void; + ~~~ Unexpected any. Specify a different type. +} +interface Garply { + f(...args: any[]): void; + ~~~ Unexpected any. Specify a different type. +} +" +`; diff --git a/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-extra-non-null-assertion.shot b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-extra-non-null-assertion.shot new file mode 100644 index 000000000000..648c09322657 --- /dev/null +++ b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-extra-non-null-assertion.shot @@ -0,0 +1,46 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[` 1`] = ` +"const foo: { bar: number } | null = null; +const bar = foo!!!.bar; + ~~~~~ Forbidden extra non-null assertion. + ~~~~ Forbidden extra non-null assertion. +" +`; + +exports[` 2`] = ` +"function foo(bar: number | undefined) { + const bar: number = bar!!!; + ~~~~~ Forbidden extra non-null assertion. + ~~~~ Forbidden extra non-null assertion. +} +" +`; + +exports[` 3`] = ` +"function foo(bar?: { n: number }) { + return bar!?.n; + ~~~~ Forbidden extra non-null assertion. +} +" +`; + +exports[` 4`] = ` +"const foo: { bar: number } | null = null; +const bar = foo!.bar; +" +`; + +exports[` 5`] = ` +"function foo(bar: number | undefined) { + const bar: number = bar!; +} +" +`; + +exports[` 6`] = ` +"function foo(bar?: { n: number }) { + return bar?.n; +} +" +`; diff --git a/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-extraneous-class.shot b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-extraneous-class.shot new file mode 100644 index 000000000000..451fdf44bbc7 --- /dev/null +++ b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-extraneous-class.shot @@ -0,0 +1,192 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[` 1`] = ` +"class StaticConstants { + ~~~~~~~~~~~~~~~ Unexpected class with only static properties. + static readonly version = 42; + + static isProduction() { + return process.env.NODE_ENV === 'production'; + } +} + +class HelloWorldLogger { + ~~~~~~~~~~~~~~~~ Unexpected class with only a constructor. + constructor() { + console.log('Hello, world!'); + } +} +" +`; + +exports[` 2`] = ` +"export const version = 42; + +export function isProduction() { + return process.env.NODE_ENV === 'production'; +} + +function logHelloWorld() { + console.log('Hello, world!'); +} +" +`; + +exports[` 3`] = ` +"export class Utilities { + ~~~~~~~~~ Unexpected class with only static properties. + static util1() { + return Utilities.util3(); + } + + static util2() { + /* ... */ + } + + static util3() { + /* ... */ + } +} +" +`; + +exports[` 4`] = ` +"export function util1() { + return util3(); +} + +export function util2() { + /* ... */ +} + +export function util3() { + /* ... */ +} +" +`; + +exports[` 5`] = ` +"// utilities.ts +export class Utilities { + ~~~~~~~~~ Unexpected class with only static properties. + static sayHello() { + console.log('Hello, world!'); + } +} + +// consumers.ts +import { Utilities } from './utilities'; + +Utilities.sayHello(); +" +`; + +exports[` 6`] = ` +"// utilities.ts +export function sayHello() { + console.log('Hello, world!'); +} + +// consumers.ts +import * as utilities from './utilities'; + +utilities.sayHello(); +" +`; + +exports[` 7`] = ` +"// utilities.ts +export function sayHello() { + console.log('Hello, world!'); +} + +// consumers.ts +import { sayHello } from './utilities'; + +sayHello(); +" +`; + +exports[` 8`] = ` +"export class Utilities { + ~~~~~~~~~ Unexpected class with only static properties. + static mutableCount = 1; + + static incrementCount() { + Utilities.mutableCount += 1; + } +} +" +`; + +exports[` 9`] = ` +"let mutableCount = 1; + +export function getMutableCount() { + return mutableField; +} + +export function incrementCount() { + mutableField += 1; +} +" +`; + +exports[` 10`] = ` +"class NoFields {} + ~~~~~~~~ Unexpected empty class. +" +`; + +exports[` 11`] = ` +"class NoFields { + constructor() { + console.log('Hello, world!'); + } +} +" +`; + +exports[` 12`] = ` +"class NoFields { + ~~~~~~~~ Unexpected class with only a constructor. + constructor() { + console.log('Hello, world!'); + } +} +" +`; + +exports[` 13`] = ` +"class NoFields {} +" +`; + +exports[` 14`] = ` +"class EmptyClass {} + ~~~~~~~~~~ Unexpected empty class. +" +`; + +exports[` 15`] = ` +"class NotEmptyClass { + static version = 42; +} +" +`; + +exports[` 16`] = ` +"class Constants { + ~~~~~~~~~ Unexpected class with only static properties. + static readonly version = 42; +} +" +`; + +exports[` 17`] = ` +"@logOnRead() +class Constants { + static readonly version = 42; +} +" +`; diff --git a/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-floating-promises.shot b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-floating-promises.shot new file mode 100644 index 000000000000..94586a86264b --- /dev/null +++ b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-floating-promises.shot @@ -0,0 +1,64 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[` 1`] = ` +"const promise = new Promise((resolve, reject) => resolve('value')); +promise; +~~~~~~~~ Promises must be awaited, end with a call to .catch, end with a call to .then with a rejection handler or be explicitly marked as ignored with the \`void\` operator. + +async function returnsPromise() { + return 'value'; +} +returnsPromise().then(() => {}); +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Promises must be awaited, end with a call to .catch, end with a call to .then with a rejection handler or be explicitly marked as ignored with the \`void\` operator. + +Promise.reject('value').catch(); +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Promises must be awaited, end with a call to .catch, end with a call to .then with a rejection handler or be explicitly marked as ignored with the \`void\` operator. + +Promise.reject('value').finally(); +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Promises must be awaited, end with a call to .catch, end with a call to .then with a rejection handler or be explicitly marked as ignored with the \`void\` operator. + +[1, 2, 3].map(async x => x + 1); +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ An array of Promises may be unintentional. Consider handling the promises' fulfillment or rejection with Promise.all or similar, or explicitly marking the expression as ignored with the \`void\` operator. +" +`; + +exports[` 2`] = ` +"const promise = new Promise((resolve, reject) => resolve('value')); +await promise; + +async function returnsPromise() { + return 'value'; +} +returnsPromise().then( + () => {}, + () => {}, +); + +Promise.reject('value').catch(() => {}); + +await Promise.reject('value').finally(() => {}); + +await Promise.all([1, 2, 3].map(async x => x + 1)); +" +`; + +exports[` 3`] = ` +"async function returnsPromise() { + return 'value'; +} +void returnsPromise(); + +void Promise.reject('value'); +" +`; + +exports[` 4`] = ` +"await (async function () { + await res(1); +})(); + +(async function () { + await res(1); +})(); +" +`; diff --git a/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-for-in-array.shot b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-for-in-array.shot new file mode 100644 index 000000000000..a47cedc24c02 --- /dev/null +++ b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-for-in-array.shot @@ -0,0 +1,41 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[` 1`] = ` +"declare const array: string[]; + +for (const i in array) { +~ For-in loops over arrays skips holes, returns indices as strings, and may visit the prototype chain or other enumerable properties. Use a more robust iteration method such as for-of or array.forEach instead. + console.log(array[i]); +~~~~~~~~~~~~~~~~~~~~~~~~ +} +~ + +for (const i in array) { +~ For-in loops over arrays skips holes, returns indices as strings, and may visit the prototype chain or other enumerable properties. Use a more robust iteration method such as for-of or array.forEach instead. + console.log(i, array[i]); +~~~~~~~~~~~~~~~~~~~~~~~~~~~ +} +~ +" +`; + +exports[` 2`] = ` +"declare const array: string[]; + +for (const value of array) { + console.log(value); +} + +for (let i = 0; i < array.length; i += 1) { + console.log(i, array[i]); +} + +array.forEach((value, i) => { + console.log(i, value); +}); + +for (const [i, value] of array.entries()) { + console.log(i, value); +} +" +`; diff --git a/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-implied-eval.shot b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-implied-eval.shot new file mode 100644 index 000000000000..5ab22d601880 --- /dev/null +++ b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-implied-eval.shot @@ -0,0 +1,69 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[` 1`] = ` +"setTimeout('alert(\`Hi!\`);', 100); + ~~~~~~~~~~~~~~~ Implied eval. Consider passing a function. + +setInterval('alert(\`Hi!\`);', 100); + ~~~~~~~~~~~~~~~ Implied eval. Consider passing a function. + +setImmediate('alert(\`Hi!\`)'); + ~~~~~~~~~~~~~~ Implied eval. Consider passing a function. + +execScript('alert(\`Hi!\`)'); + ~~~~~~~~~~~~~~ Implied eval. Consider passing a function. + +window.setTimeout('count = 5', 10); + ~~~~~~~~~~~ Implied eval. Consider passing a function. + +window.setInterval('foo = bar', 10); + ~~~~~~~~~~~ Implied eval. Consider passing a function. + +const fn = '() = {}'; +setTimeout(fn, 100); + ~~ Implied eval. Consider passing a function. + +const fn = () => { + return 'x = 10'; +}; +setTimeout(fn(), 100); + ~~~~ Implied eval. Consider passing a function. + +const fn = new Function('a', 'b', 'return a + b'); + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Implied eval. Do not use the Function constructor to create functions. +" +`; + +exports[` 2`] = ` +"setTimeout(function () { + alert('Hi!'); +}, 100); + +setInterval(function () { + alert('Hi!'); +}, 100); + +setImmediate(function () { + alert('Hi!'); +}); + +execScript(function () { + alert('Hi!'); +}); + +const fn = () => {}; +setTimeout(fn, 100); + +const foo = { + fn: function () {}, +}; +setTimeout(foo.fn, 100); +setTimeout(foo.fn.bind(this), 100); + +class Foo { + static fn = () => {}; +} + +setTimeout(Foo.fn, 100); +" +`; diff --git a/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-import-type-side-effects.shot b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-import-type-side-effects.shot new file mode 100644 index 000000000000..6c05aedf0587 --- /dev/null +++ b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-import-type-side-effects.shot @@ -0,0 +1,37 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[` 1`] = ` +"import { type A } from 'mod'; +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ TypeScript will only remove the inline type specifiers which will leave behind a side effect import at runtime. Convert this to a top-level type qualifier to properly remove the entire import. +import { type A as AA } from 'mod'; +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ TypeScript will only remove the inline type specifiers which will leave behind a side effect import at runtime. Convert this to a top-level type qualifier to properly remove the entire import. +import { type A, type B } from 'mod'; +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ TypeScript will only remove the inline type specifiers which will leave behind a side effect import at runtime. Convert this to a top-level type qualifier to properly remove the entire import. +import { type A as AA, type B as BB } from 'mod'; +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ TypeScript will only remove the inline type specifiers which will leave behind a side effect import at runtime. Convert this to a top-level type qualifier to properly remove the entire import. +" +`; + +exports[` 2`] = ` +"import type { A } from 'mod'; +import type { A as AA } from 'mod'; +import type { A, B } from 'mod'; +import type { A as AA, B as BB } from 'mod'; + +import T from 'mod'; +import type T from 'mod'; + +import * as T from 'mod'; +import type * as T from 'mod'; + +import { T } from 'mod'; +import type { T } from 'mod'; +import { T, U } from 'mod'; +import type { T, U } from 'mod'; +import { type T, U } from 'mod'; +import { T, type U } from 'mod'; + +import type T, { U } from 'mod'; +import T, { type U } from 'mod'; +" +`; diff --git a/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-inferrable-types.shot b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-inferrable-types.shot new file mode 100644 index 000000000000..17e22fec61b4 --- /dev/null +++ b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-inferrable-types.shot @@ -0,0 +1,89 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[` 1`] = ` +"const a: bigint = 10n; + ~~~~~~~~~~~~~~~ Type bigint trivially inferred from a bigint literal, remove type annotation. +const a: bigint = BigInt(10); + ~~~~~~~~~~~~~~~~~~~~~~ Type bigint trivially inferred from a bigint literal, remove type annotation. +const a: boolean = !0; + ~~~~~~~~~~~~~~~ Type boolean trivially inferred from a boolean literal, remove type annotation. +const a: boolean = Boolean(null); + ~~~~~~~~~~~~~~~~~~~~~~~~~~ Type boolean trivially inferred from a boolean literal, remove type annotation. +const a: boolean = true; + ~~~~~~~~~~~~~~~~~ Type boolean trivially inferred from a boolean literal, remove type annotation. +const a: null = null; + ~~~~~~~~~~~~~~ Type null trivially inferred from a null literal, remove type annotation. +const a: number = 10; + ~~~~~~~~~~~~~~ Type number trivially inferred from a number literal, remove type annotation. +const a: number = Infinity; + ~~~~~~~~~~~~~~~~~~~~ Type number trivially inferred from a number literal, remove type annotation. +const a: number = NaN; + ~~~~~~~~~~~~~~~ Type number trivially inferred from a number literal, remove type annotation. +const a: number = Number('1'); + ~~~~~~~~~~~~~~~~~~~~~~~ Type number trivially inferred from a number literal, remove type annotation. +const a: RegExp = /a/; + ~~~~~~~~~~~~~~~ Type RegExp trivially inferred from a RegExp literal, remove type annotation. +const a: RegExp = new RegExp('a'); + ~~~~~~~~~~~~~~~~~~~~~~~~~~~ Type RegExp trivially inferred from a RegExp literal, remove type annotation. +const a: string = \`str\`; + ~~~~~~~~~~~~~~~~~ Type string trivially inferred from a string literal, remove type annotation. +const a: string = String(1); + ~~~~~~~~~~~~~~~~~~~~~ Type string trivially inferred from a string literal, remove type annotation. +const a: symbol = Symbol('a'); + ~~~~~~~~~~~~~~~~~~~~~~~ Type symbol trivially inferred from a symbol literal, remove type annotation. +const a: undefined = undefined; + ~~~~~~~~~~~~~~~~~~~~~~~~ Type undefined trivially inferred from a undefined literal, remove type annotation. +const a: undefined = void someValue; + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Type undefined trivially inferred from a undefined literal, remove type annotation. + +class Foo { + prop: number = 5; + ~~~~~~~~~~~~~~~~~ Type number trivially inferred from a number literal, remove type annotation. +} + +function fn(a: number = 5, b: boolean = true) {} + ~~~~~~~~~~~~~ Type number trivially inferred from a number literal, remove type annotation. + ~~~~~~~~~~~~~~~~~ Type boolean trivially inferred from a boolean literal, remove type annotation. +" +`; + +exports[` 2`] = ` +"const a = 10n; +const a = BigInt(10); +const a = !0; +const a = Boolean(null); +const a = true; +const a = null; +const a = 10; +const a = Infinity; +const a = NaN; +const a = Number('1'); +const a = /a/; +const a = new RegExp('a'); +const a = \`str\`; +const a = String(1); +const a = Symbol('a'); +const a = undefined; +const a = void someValue; + +class Foo { + prop = 5; +} + +function fn(a = 5, b = true) {} +" +`; + +exports[` 3`] = ` +"function foo(a: number = 5, b: boolean = true) { + // ... +} +" +`; + +exports[` 4`] = ` +"class Foo { + prop: number = 5; +} +" +`; diff --git a/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-invalid-void-type.shot b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-invalid-void-type.shot new file mode 100644 index 000000000000..92d33465d52d --- /dev/null +++ b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-invalid-void-type.shot @@ -0,0 +1,84 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[` 1`] = ` +"type PossibleValues = string | number | void; + ~~~~ void is not valid as a constituent in a union type +type MorePossibleValues = string | ((number & any) | (string | void)); + ~~~~ void is not valid as a constituent in a union type + +function logSomething(thing: void) {} + ~~~~ void is only valid as a return type or generic type argument. +function printArg(arg: T) {} + +logAndReturn(undefined); + ~~~~ void is only valid as a return type or generic type argument. + +interface Interface { + lambda: () => void; + prop: void; + ~~~~ void is only valid as a return type or generic type argument. +} + +class MyClass { + private readonly propName: void; + ~~~~ void is only valid as a return type or generic type argument. +} +" +`; + +exports[` 2`] = ` +"type NoOp = () => void; + +function noop(): void {} + +let trulyUndefined = void 0; + +async function promiseMeSomething(): Promise {} + +type stillVoid = void | never; +" +`; + +exports[` 3`] = ` +"logAndReturn(undefined); + ~~~~ void is only valid as a return type. + +let voidPromise: Promise = new Promise(() => {}); + ~~~~ void is only valid as a return type. + ~~~~ void is only valid as a return type. +let voidMap: Map = new Map(); + ~~~~ void is only valid as a return type. + ~~~~ void is only valid as a return type. +" +`; + +exports[` 4`] = ` +"logAndReturn(undefined); + ~~~~ void is only valid as a return type or generic type argument. + +type NotAllowedVoid1 = Mx.Tx; + ~~~~ Mx.Tx may not have void as a type argument. +type NotAllowedVoid2 = Tx; + ~~~~ Tx may not have void as a type argument. +type NotAllowedVoid3 = Promise; + ~~~~ Promise may not have void as a type argument. +" +`; + +exports[` 5`] = ` +"type AllowedVoid = Ex.Mx.Tx; +type AllowedVoidUnion = void | Ex.Mx.Tx; +" +`; + +exports[` 6`] = ` +"function doThing(this: void) {} + ~~~~ void is only valid as a return type or generic type argument. +class Example { + static helper(this: void) {} + ~~~~ void is only valid as a return type or generic type argument. + callback(this: void) {} + ~~~~ void is only valid as a return type or generic type argument. +} +" +`; diff --git a/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-magic-numbers.shot b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-magic-numbers.shot new file mode 100644 index 000000000000..80d7ebd59085 --- /dev/null +++ b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-magic-numbers.shot @@ -0,0 +1,69 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[` 1`] = ` +"enum foo { + SECOND = 1000, + ~~~~ No magic number: 1000. +} +" +`; + +exports[` 2`] = ` +"enum foo { + SECOND = 1000, +} +" +`; + +exports[` 3`] = ` +"type SmallPrimes = 2 | 3 | 5 | 7 | 11; + ~ No magic number: 2. + ~ No magic number: 3. + ~ No magic number: 5. + ~ No magic number: 7. + ~~ No magic number: 11. +" +`; + +exports[` 4`] = ` +"type SmallPrimes = 2 | 3 | 5 | 7 | 11; +" +`; + +exports[` 5`] = ` +"class Foo { + readonly A = 1; + ~ No magic number: 1. + readonly B = 2; + ~ No magic number: 2. + public static readonly C = 1; + ~ No magic number: 1. + static readonly D = 1; + ~ No magic number: 1. +} +" +`; + +exports[` 6`] = ` +"class Foo { + readonly A = 1; + readonly B = 2; + public static readonly C = 1; + static readonly D = 1; +} +" +`; + +exports[` 7`] = ` +"type Foo = Bar[0]; + ~ No magic number: 0. +type Baz = Parameters[2]; + ~ No magic number: 2. +" +`; + +exports[` 8`] = ` +"type Foo = Bar[0]; +type Baz = Parameters[2]; +" +`; diff --git a/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-meaningless-void-operator.shot b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-meaningless-void-operator.shot new file mode 100644 index 000000000000..e4a003bc91ee --- /dev/null +++ b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-meaningless-void-operator.shot @@ -0,0 +1,25 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[` 1`] = ` +"void (() => {})(); +~~~~~~~~~~~~~~~~~ void operator shouldn't be used on void; it should convey that a return value is being ignored + +function foo() {} +void foo(); +~~~~~~~~~~ void operator shouldn't be used on void; it should convey that a return value is being ignored +" +`; + +exports[` 2`] = ` +"(() => {})(); + +function foo() {} +foo(); // nothing to discard + +function bar(x: number) { + void x; // discarding a number + return 2; +} +void bar(1); // discarding a number +" +`; diff --git a/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-misused-new.shot b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-misused-new.shot new file mode 100644 index 000000000000..e4161a9beba4 --- /dev/null +++ b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-misused-new.shot @@ -0,0 +1,27 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[` 1`] = ` +"declare class C { + new(): C; + ~~~~~~~~~ Class cannot have method named \`new\`. +} + +interface I { + new (): I; + ~~~~~~~~~~ Interfaces cannot be constructed, only classes. + constructor(): void; + ~~~~~~~~~~~~~~~~~~~~ Interfaces cannot be constructed, only classes. +} +" +`; + +exports[` 2`] = ` +"declare class C { + constructor(); +} + +interface I { + new (): C; +} +" +`; diff --git a/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-misused-promises.shot b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-misused-promises.shot new file mode 100644 index 000000000000..2a33c1af2533 --- /dev/null +++ b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-misused-promises.shot @@ -0,0 +1,129 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[` 1`] = ` +"const promise = Promise.resolve('value'); + +if (promise) { + ~~~~~~~ Expected non-Promise value in a boolean conditional. + // Do something +} + +const val = promise ? 123 : 456; + ~~~~~~~ Expected non-Promise value in a boolean conditional. + +while (promise) { + ~~~~~~~ Expected non-Promise value in a boolean conditional. + // Do something +} +" +`; + +exports[` 2`] = ` +"const promise = Promise.resolve('value'); + +// Always \`await\` the Promise in a conditional +if (await promise) { + // Do something +} + +const val = (await promise) ? 123 : 456; + +while (await promise) { + // Do something +} +" +`; + +exports[` 3`] = ` +"[1, 2, 3].forEach(async value => { + ~ Promise returned in function argument where a void return was expected. + await doSomething(value); +~~~~~~~~~ +}); +~ + +new Promise(async (resolve, reject) => { + ~ Promise returned in function argument where a void return was expected. + await doSomething(); +~~~~~~~~~~ + resolve(); +~ +}); +~ + +const eventEmitter = new EventEmitter(); +eventEmitter.on('some-event', async () => { + synchronousCall(); + await doSomething(); + otherSynchronousCall(); +}); +" +`; + +exports[` 4`] = ` +"// for-of puts \`await\` in outer context +for (const value of [1, 2, 3]) { + await doSomething(value); +} + +// If outer context is not \`async\`, handle error explicitly +Promise.all( + [1, 2, 3].map(async value => { + await doSomething(value); + }), +).catch(handleError); + +// Use an async IIFE wrapper +new Promise((resolve, reject) => { + // combine with \`void\` keyword to tell \`no-floating-promises\` rule to ignore unhandled rejection + void (async () => { + await doSomething(); + resolve(); + })(); +}); + +// Name the async wrapper to call it later +const eventEmitter = new EventEmitter(); +eventEmitter.on('some-event', () => { + const handler = async () => { + await doSomething(); + otherSynchronousCall(); + }; + + try { + synchronousCall(); + } catch (err) { + handleSpecificError(err); + } + + handler().catch(handleError); +}); +" +`; + +exports[` 5`] = ` +"const getData = () => someAsyncOperation({ myArg: 'foo' }); + +return { foo: 42, ...getData() }; + +const getData2 = async () => { + await someAsyncOperation({ myArg: 'foo' }); +}; + +return { foo: 42, ...getData2() }; + ~~~~~~~~~~ Expected a non-Promise value to be spreaded in an object. +" +`; + +exports[` 6`] = ` +"const getData = () => someAsyncOperation({ myArg: 'foo' }); + +return { foo: 42, ...(await getData()) }; + +const getData2 = async () => { + await someAsyncOperation({ myArg: 'foo' }); +}; + +return { foo: 42, ...(await getData2()) }; +" +`; diff --git a/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-mixed-enums.shot b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-mixed-enums.shot new file mode 100644 index 000000000000..6a4c7c6c2e54 --- /dev/null +++ b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-mixed-enums.shot @@ -0,0 +1,38 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[` 1`] = ` +"enum Status { + Unknown, + Closed = 1, + Open = 'open', + ~~~~~~ Mixing number and string enums can be confusing. +} +" +`; + +exports[` 2`] = ` +"enum Status { + Unknown = 0, + Closed = 1, + Open = 2, +} +" +`; + +exports[` 3`] = ` +"enum Status { + Unknown, + Closed, + Open, +} +" +`; + +exports[` 4`] = ` +"enum Status { + Unknown = 'unknown', + Closed = 'closed', + Open = 'open', +} +" +`; diff --git a/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-namespace.shot b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-namespace.shot new file mode 100644 index 000000000000..3e1a94cc1856 --- /dev/null +++ b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-namespace.shot @@ -0,0 +1,87 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[` 1`] = ` +"module foo {} +~~~~~~~~~~~~~ ES2015 module syntax is preferred over namespaces. +namespace foo {} +~~~~~~~~~~~~~~~~ ES2015 module syntax is preferred over namespaces. + +declare module foo {} +~~~~~~~~~~~~~~~~~~~~~ ES2015 module syntax is preferred over namespaces. +declare namespace foo {} +~~~~~~~~~~~~~~~~~~~~~~~~ ES2015 module syntax is preferred over namespaces. +" +`; + +exports[` 2`] = ` +"declare module 'foo' {} + +// anything inside a d.ts file +" +`; + +exports[` 3`] = ` +"module foo {} +~~~~~~~~~~~~~ ES2015 module syntax is preferred over namespaces. +namespace foo {} +~~~~~~~~~~~~~~~~ ES2015 module syntax is preferred over namespaces. +" +`; + +exports[` 4`] = ` +"declare module 'foo' {} +declare module foo {} +declare namespace foo {} + +declare global { + namespace foo {} +} + +declare module foo { + namespace foo {} +} +" +`; + +exports[` 5`] = ` +"module foo {} +~~~~~~~~~~~~~ ES2015 module syntax is preferred over namespaces. +namespace foo {} +~~~~~~~~~~~~~~~~ ES2015 module syntax is preferred over namespaces. +declare module foo {} +~~~~~~~~~~~~~~~~~~~~~ ES2015 module syntax is preferred over namespaces. +declare namespace foo {} +~~~~~~~~~~~~~~~~~~~~~~~~ ES2015 module syntax is preferred over namespaces. +" +`; + +exports[` 6`] = ` +"declare module 'foo' {} +" +`; + +exports[` 7`] = ` +"// if outside a d.ts file +module foo {} +~~~~~~~~~~~~~ ES2015 module syntax is preferred over namespaces. +namespace foo {} +~~~~~~~~~~~~~~~~ ES2015 module syntax is preferred over namespaces. + +// if outside a d.ts file and allowDeclarations = false +module foo {} +~~~~~~~~~~~~~ ES2015 module syntax is preferred over namespaces. +namespace foo {} +~~~~~~~~~~~~~~~~ ES2015 module syntax is preferred over namespaces. +declare module foo {} +~~~~~~~~~~~~~~~~~~~~~ ES2015 module syntax is preferred over namespaces. +declare namespace foo {} +~~~~~~~~~~~~~~~~~~~~~~~~ ES2015 module syntax is preferred over namespaces. +" +`; + +exports[` 8`] = ` +"declare module 'foo' {} + +// anything inside a d.ts file +" +`; diff --git a/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-non-null-asserted-nullish-coalescing.shot b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-non-null-asserted-nullish-coalescing.shot new file mode 100644 index 000000000000..b2676745c3ab --- /dev/null +++ b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-non-null-asserted-nullish-coalescing.shot @@ -0,0 +1,35 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[` 1`] = ` +"foo! ?? bar; +~~~~ The nullish coalescing operator is designed to handle undefined and null - using a non-null assertion is not needed. +foo.bazz! ?? bar; +~~~~~~~~~ The nullish coalescing operator is designed to handle undefined and null - using a non-null assertion is not needed. +foo!.bazz! ?? bar; +~~~~~~~~~~ The nullish coalescing operator is designed to handle undefined and null - using a non-null assertion is not needed. +foo()! ?? bar; +~~~~~~ The nullish coalescing operator is designed to handle undefined and null - using a non-null assertion is not needed. + +let x!: string; +x! ?? ''; +~~ The nullish coalescing operator is designed to handle undefined and null - using a non-null assertion is not needed. + +let x: string; +x = foo(); +x! ?? ''; +~~ The nullish coalescing operator is designed to handle undefined and null - using a non-null assertion is not needed. +" +`; + +exports[` 2`] = ` +"foo ?? bar; +foo ?? bar!; +foo!.bazz ?? bar; +foo!.bazz ?? bar!; +foo() ?? bar; + +// This is considered correct code because there's no way for the user to satisfy it. +let x: string; +x! ?? ''; +" +`; diff --git a/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-non-null-asserted-optional-chain.shot b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-non-null-asserted-optional-chain.shot new file mode 100644 index 000000000000..b688933bb7c2 --- /dev/null +++ b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-non-null-asserted-optional-chain.shot @@ -0,0 +1,15 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[` 1`] = ` +"foo?.bar!; +~~~~~~~~~ Optional chain expressions can return undefined by design - using a non-null assertion is unsafe and wrong. +foo?.bar()!; +~~~~~~~~~~~ Optional chain expressions can return undefined by design - using a non-null assertion is unsafe and wrong. +" +`; + +exports[` 2`] = ` +"foo?.bar; +foo?.bar(); +" +`; diff --git a/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-non-null-assertion.shot b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-non-null-assertion.shot new file mode 100644 index 000000000000..0d95d434a273 --- /dev/null +++ b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-non-null-assertion.shot @@ -0,0 +1,22 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[` 1`] = ` +"interface Example { + property?: string; +} + +declare const example: Example; +const includesBaz = example.property!.includes('baz'); + ~~~~~~~~~~~~~~~~~ Forbidden non-null assertion. +" +`; + +exports[` 2`] = ` +"interface Example { + property?: string; +} + +declare const example: Example; +const includesBaz = example.property?.includes('baz') ?? false; +" +`; diff --git a/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-redeclare.shot b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-redeclare.shot new file mode 100644 index 000000000000..9f2cd110910f --- /dev/null +++ b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-redeclare.shot @@ -0,0 +1,33 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[` 1`] = ` +"interface A { + prop1: 1; +} +interface A { + prop2: 2; +} + +namespace Foo { + export const a = 1; +} +namespace Foo { + export const b = 2; +} + +class Bar {} +namespace Bar {} + +function Baz() {} +namespace Baz {} +" +`; + +exports[` 2`] = ` +"type something = string; +// eslint-disable-next-line @typescript-eslint/no-redeclare -- intentionally naming the variable the same as the type +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Definition for rule '@typescript-eslint/no-redeclare' was not found. +const something = 2; + ~~~~~~~~~ 'something' is already defined. +" +`; diff --git a/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-redundant-type-constituents.shot b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-redundant-type-constituents.shot new file mode 100644 index 000000000000..27b2209a9069 --- /dev/null +++ b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-redundant-type-constituents.shot @@ -0,0 +1,51 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[` 1`] = ` +"type UnionAny = any | 'foo'; + ~~~ 'any' overrides all other types in this union type. +type UnionUnknown = unknown | 'foo'; + ~~~~~~~ 'unknown' overrides all other types in this union type. +type UnionNever = never | 'foo'; + ~~~~~ 'never' is overridden by other types in this union type. + +type UnionBooleanLiteral = boolean | false; + ~~~~~ false is overridden by boolean in this union type. +type UnionNumberLiteral = number | 1; + ~ 1 is overridden by number in this union type. +type UnionStringLiteral = string | 'foo'; + ~~~~~ "foo" is overridden by string in this union type. + +type IntersectionAny = any & 'foo'; + ~~~ 'any' overrides all other types in this intersection type. +type IntersectionUnknown = string & unknown; + ~~~~~~~ 'unknown' is overridden by other types in this intersection type. +type IntersectionNever = string | never; + ~~~~~ 'never' is overridden by other types in this union type. + +type IntersectionBooleanLiteral = boolean & false; + ~~~~~~~ boolean is overridden by the false in this intersection type. +type IntersectionNumberLiteral = number & 1; + ~~~~~~ number is overridden by the 1 in this intersection type. +type IntersectionStringLiteral = string & 'foo'; + ~~~~~~ string is overridden by the "foo" in this intersection type. +" +`; + +exports[` 2`] = ` +"type UnionAny = any; +type UnionUnknown = unknown; +type UnionNever = never; + +type UnionBooleanLiteral = boolean; +type UnionNumberLiteral = number; +type UnionStringLiteral = string; + +type IntersectionAny = any; +type IntersectionUnknown = string; +type IntersectionNever = string; + +type IntersectionBooleanLiteral = false; +type IntersectionNumberLiteral = 1; +type IntersectionStringLiteral = 'foo'; +" +`; diff --git a/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-require-imports.shot b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-require-imports.shot new file mode 100644 index 000000000000..3b8dc4f0e617 --- /dev/null +++ b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-require-imports.shot @@ -0,0 +1,29 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[` 1`] = ` +"const lib1 = require('lib1'); + ~~~~~~~~~~~~~~~ A \`require()\` style import is forbidden. +const { lib2 } = require('lib2'); + ~~~~~~~~~~~~~~~ A \`require()\` style import is forbidden. +import lib3 = require('lib3'); + ~~~~~~~~~~~~~~~ A \`require()\` style import is forbidden. +" +`; + +exports[` 2`] = ` +"import * as lib1 from 'lib1'; +import { lib2 } from 'lib2'; +import * as lib3 from 'lib3'; +" +`; + +exports[` 3`] = ` +"console.log(require('../data.json').version); + ~~~~~~~~~~~~~~~~~~~~~~~ A \`require()\` style import is forbidden. +" +`; + +exports[` 4`] = ` +"console.log(require('../package.json').version); +" +`; diff --git a/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-restricted-imports.shot b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-restricted-imports.shot new file mode 100644 index 000000000000..fcccec7f6b97 --- /dev/null +++ b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-restricted-imports.shot @@ -0,0 +1,25 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[` 1`] = ` +"import foo from 'import-foo'; +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 'import-foo' import is restricted from being used. Please use import-bar instead. +export { Foo } from 'import-foo'; +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 'import-foo' import is restricted from being used. Please use import-bar instead. + +import baz from 'import-baz'; +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 'import-baz' import is restricted from being used. Please use import-quux instead. +export { Baz } from 'import-baz'; +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 'import-baz' import is restricted from being used. Please use import-quux instead. +" +`; + +exports[` 2`] = ` +"import { foo } from 'other-module'; + +import type foo from 'import-foo'; +export type { Foo } from 'import-foo'; + +import type baz from 'import-baz'; +export type { Baz } from 'import-baz'; +" +`; diff --git a/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-shadow.shot b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-shadow.shot new file mode 100644 index 000000000000..09e859cfc7fb --- /dev/null +++ b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-shadow.shot @@ -0,0 +1,20 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[` 1`] = ` +"type Foo = number; +interface Bar { + prop: number; +} + +function f() { + const Foo = 1; + const Bar = 'test'; +} +" +`; + +exports[` 2`] = ` +"const test = 1; +type Func = (test: string) => typeof test; +" +`; diff --git a/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-this-alias.shot b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-this-alias.shot new file mode 100644 index 000000000000..2cf3b997330f --- /dev/null +++ b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-this-alias.shot @@ -0,0 +1,66 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[` 1`] = ` +"const self = this; + ~~~~ Unexpected aliasing of 'this' to local variable. + +setTimeout(function () { + self.doWork(); +}); +" +`; + +exports[` 2`] = ` +"setTimeout(() => { + this.doWork(); +}); +" +`; + +exports[` 3`] = ` +"class ComponentLike { + props: unknown; + state: unknown; + + render() { + const { props, state } = this; + ~~~~~~~~~~~~~~~~ Unexpected aliasing of members of 'this' to local variables. + + console.log(props); + console.log(state); + } +} +" +`; + +exports[` 4`] = ` +"class ComponentLike { + props: unknown; + state: unknown; + + render() { + console.log(this.props); + console.log(this.state); + } +} +" +`; + +exports[` 5`] = ` +"class Example { + method() { + const that = this; + ~~~~ Unexpected aliasing of 'this' to local variable. + } +} +" +`; + +exports[` 6`] = ` +"class Example { + method() { + const self = this; + } +} +" +`; diff --git a/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-throw-literal.shot b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-throw-literal.shot new file mode 100644 index 000000000000..47f904d5ed4d --- /dev/null +++ b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-throw-literal.shot @@ -0,0 +1,74 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[` 1`] = ` +"throw 'error'; + ~~~~~~~ Expected an error object to be thrown. + +throw 0; + ~ Expected an error object to be thrown. + +throw undefined; + ~~~~~~~~~ Do not throw undefined. + +throw null; + ~~~~ Expected an error object to be thrown. + +const err1 = new Error(); +throw 'an ' + err1; + ~~~~~~~~~~~~ Expected an error object to be thrown. + +const err2 = new Error(); +throw \`\${err2}\`; + ~~~~~~~~~ Expected an error object to be thrown. + +const err3 = ''; +throw err3; + ~~~~ Expected an error object to be thrown. + +function getErr() { + return ''; +} +throw getErr(); + ~~~~~~~~ Expected an error object to be thrown. + +const foo = { + bar: '', +}; +throw foo.bar; + ~~~~~~~ Expected an error object to be thrown. +" +`; + +exports[` 2`] = ` +"throw new Error(); + +throw new Error('error'); + +const e = new Error('error'); +throw e; + +try { + throw new Error('error'); +} catch (e) { + throw e; +} + +const err = new Error(); +throw err; + +function getErr() { + return new Error(); +} +throw getErr(); + +const foo = { + bar: new Error(), +}; +throw foo.bar; + +class CustomError extends Error { + // ... +} +throw new CustomError(); +" +`; diff --git a/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-type-alias.shot b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-type-alias.shot new file mode 100644 index 000000000000..83db0c4becee --- /dev/null +++ b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-type-alias.shot @@ -0,0 +1,489 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[` 1`] = ` +"// primitives +type Foo = 'a'; + +type Foo = 'a' | 'b'; + +type Foo = string; + +type Foo = string | string[]; + +type Foo = string & string[]; + +type Foo = \`foo-\${number}\`; + +// reference types +interface Bar {} +class Baz implements Bar {} + +type Foo = Bar; + +type Foo = Bar | Baz; + +type Foo = Bar & Baz; +" +`; + +exports[` 2`] = ` +"// primitives +type Foo = 'a'; + ~~~ Type aliases are not allowed. + +type Foo = string; + ~~~~~~ Type aliases are not allowed. + +type Foo = string & string[]; + ~~~~~~ Aliases in intersection types are not allowed. + ~~~~~~~~ Aliases in intersection types are not allowed. + +type Foo = \`foo-\${number}\`; + ~~~~~~~~~~~~~~~ Type aliases are not allowed. + +// reference types +interface Bar {} +class Baz implements Bar {} + +type Foo = Bar; + ~~~ Type aliases are not allowed. + +type Foo = Bar & Baz; + ~~~ Aliases in intersection types are not allowed. + ~~~ Aliases in intersection types are not allowed. +" +`; + +exports[` 3`] = ` +"// primitives +type Foo = 'a' | 'b'; + +type Foo = string | string[]; + +type Foo = \`a-\${number}\` | \`b-\${number}\`; + +// reference types +interface Bar {} +class Baz implements Bar {} + +type Foo = Bar | Baz; +" +`; + +exports[` 4`] = ` +"// primitives +type Foo = 'a'; + ~~~ Type aliases are not allowed. + +type Foo = 'a' | 'b'; + ~~~ Aliases in union types are not allowed. + ~~~ Aliases in union types are not allowed. + +type Foo = string; + ~~~~~~ Type aliases are not allowed. + +type Foo = string | string[]; + ~~~~~~ Aliases in union types are not allowed. + ~~~~~~~~ Aliases in union types are not allowed. + +type Foo = \`a-\${number}\` | \`b-\${number}\`; + ~~~~~~~~~~~~~ Aliases in union types are not allowed. + ~~~~~~~~~~~~~ Aliases in union types are not allowed. + +// reference types +interface Bar {} +class Baz implements Bar {} + +type Foo = Bar; + ~~~ Type aliases are not allowed. + +type Foo = Bar | Baz; + ~~~ Aliases in union types are not allowed. + ~~~ Aliases in union types are not allowed. +" +`; + +exports[` 5`] = ` +"// primitives +type Foo = string & string[]; + +type Foo = \`a-\${number}\` & \`b-\${number}\`; + +// reference types +interface Bar {} +class Baz implements Bar {} + +type Foo = Bar & Baz; +" +`; + +exports[` 6`] = ` +"// primitives +type Foo = 'a'; + ~~~ Type aliases are not allowed. + +type Foo = string; + ~~~~~~ Type aliases are not allowed. + +type Foo = \`foo-\${number}\`; + ~~~~~~~~~~~~~~~ Type aliases are not allowed. + +// reference types +interface Bar {} +class Baz implements Bar {} + +type Foo = Bar; + ~~~ Type aliases are not allowed. +" +`; + +exports[` 7`] = ` +"// primitives +type Foo = 'a' | 'b'; + +type Foo = string | string[]; + +type Foo = string & string[]; + +type Foo = \`a-\${number}\` & \`b-\${number}\`; + +type Foo = \`a-\${number}\` | \`b-\${number}\`; + +// reference types +interface Bar {} +class Baz implements Bar {} + +type Foo = Bar | Baz; + +type Foo = Bar & Baz; +" +`; + +exports[` 8`] = ` +"type Foo = () => void; + +type Foo = (name: string) => string; + +class Person {} + +type Foo = (name: string, age: number) => string | Person; + +type Foo = (name: string, age: number) => string & Person; +" +`; + +exports[` 9`] = ` +"type Foo = T extends number ? number : null; +" +`; + +exports[` 10`] = ` +"type Foo = new () => void; +" +`; + +exports[` 11`] = ` +"type Foo = {}; + +type Foo = { + name: string; + age: number; +}; + +type Foo = { + name: string; + age: number; + walk: (miles: number) => void; +}; + +type Foo = { name: string } | { age: number }; + +type Foo = { name: string } & { age: number }; +" +`; + +exports[` 12`] = ` +"type Foo = {}; + ~~ Type literals are not allowed. + +type Foo = { + ~ Type literals are not allowed. + name: string; +~~~~ + age: number; +~~~ +}; +~ + +type Foo = { + ~ Type literals are not allowed. + name: string; +~~~~ + age: number; +~~~ + walk: (miles: number) => void; +~~~~~~~~~~~~~~~~~~~~~ +}; +~ + +type Foo = { name: string } & { age: number }; + ~~~~~~~~~~~~~~~~ Literals in intersection types are not allowed. + ~~~~~~~~~~~~~~~ Literals in intersection types are not allowed. +" +`; + +exports[` 13`] = ` +"type Foo = { name: string } | { age: number }; +" +`; + +exports[` 14`] = ` +"type Foo = {}; + ~~ Type literals are not allowed. + +type Foo = { + ~ Type literals are not allowed. + name: string; +~~~~ + age: number; +~~~ +}; +~ + +type Foo = { + ~ Type literals are not allowed. + name: string; +~~~~ + age: number; +~~~ + walk: (miles: number) => void; +~~~~~~~~~~~~~~~~~~~~~ +}; +~ + +type Foo = { name: string } | { age: number }; + ~~~~~~~~~~~~~~~~ Literals in union types are not allowed. + ~~~~~~~~~~~~~~~ Literals in union types are not allowed. +" +`; + +exports[` 15`] = ` +"type Foo = { name: string } & { age: number }; +" +`; + +exports[` 16`] = ` +"type Foo = {}; + ~~ Type literals are not allowed. + +type Foo = { + ~ Type literals are not allowed. + name: string; +~~~~ + age: number; +~~~ +}; +~ + +type Foo = { + ~ Type literals are not allowed. + name: string; +~~~~ + age: number; +~~~ + walk: (miles: number) => void; +~~~~~~~~~~~~~~~~~~~~~ +}; +~ +" +`; + +exports[` 17`] = ` +"type Foo = { name: string } | { age: number }; + +type Foo = { name: string } & { age: number }; +" +`; + +exports[` 18`] = ` +"type Foo = { readonly [P in keyof T]: T[P] }; + +type Foo = { [P in keyof T]?: T[P] }; + +type Foo = + | { readonly [P in keyof T]: T[P] } + | { readonly [P in keyof U]: U[P] }; + +type Foo = { [P in keyof T]?: T[P] } | { [P in keyof U]?: U[P] }; + +type Foo = { readonly [P in keyof T]: T[P] } & { + readonly [P in keyof U]: U[P]; +}; + +type Foo = { [P in keyof T]?: T[P] } & { [P in keyof U]?: U[P] }; +" +`; + +exports[` 19`] = ` +"type Foo = { readonly [P in keyof T]: T[P] }; + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Type mapped types are not allowed. + +type Foo = { [P in keyof T]?: T[P] }; + ~~~~~~~~~~~~~~~~~~~~~~~~~ Type mapped types are not allowed. + +type Foo = { readonly [P in keyof T]: T[P] } & { + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Mapped types in intersection types are not allowed. + ~ Mapped types in intersection types are not allowed. + readonly [P in keyof U]: U[P]; +~ +}; +~ + +type Foo = { [P in keyof T]?: T[P] } & { [P in keyof U]?: U[P] }; + ~~~~~~~~~~~~~~~~~~~~~~~~~ Mapped types in intersection types are not allowed. + ~~~~~~~~~~~~~~~~~~~~~~~~~ Mapped types in intersection types are not allowed. +" +`; + +exports[` 20`] = ` +"type Foo = + | { readonly [P in keyof T]: T[P] } + | { readonly [P in keyof U]: U[P] }; + +type Foo = { [P in keyof T]?: T[P] } | { [P in keyof U]?: U[P] }; +" +`; + +exports[` 21`] = ` +"type Foo = { readonly [P in keyof T]: T[P] }; + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Type mapped types are not allowed. + +type Foo = { [P in keyof T]?: T[P] }; + ~~~~~~~~~~~~~~~~~~~~~~~~~ Type mapped types are not allowed. + +type Foo = + | { readonly [P in keyof T]: T[P] } + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Mapped types in union types are not allowed. + | { readonly [P in keyof U]: U[P] }; + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Mapped types in union types are not allowed. + +type Foo = { [P in keyof T]?: T[P] } | { [P in keyof U]?: U[P] }; + ~~~~~~~~~~~~~~~~~~~~~~~~~ Mapped types in union types are not allowed. + ~~~~~~~~~~~~~~~~~~~~~~~~~ Mapped types in union types are not allowed. +" +`; + +exports[` 22`] = ` +"type Foo = { readonly [P in keyof T]: T[P] } & { + readonly [P in keyof U]: U[P]; +}; + +type Foo = { [P in keyof T]?: T[P] } & { [P in keyof U]?: U[P] }; +" +`; + +exports[` 23`] = ` +"type Foo = { readonly [P in keyof T]: T[P] }; + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Type mapped types are not allowed. + +type Foo = { [P in keyof T]?: T[P] }; + ~~~~~~~~~~~~~~~~~~~~~~~~~ Type mapped types are not allowed. +" +`; + +exports[` 24`] = ` +"type Foo = + | { readonly [P in keyof T]: T[P] } + | { readonly [P in keyof U]: U[P] }; + +type Foo = { [P in keyof T]?: T[P] } | { [P in keyof U]?: U[P] }; + +type Foo = { readonly [P in keyof T]: T[P] } & { + readonly [P in keyof U]: U[P]; +}; + +type Foo = { [P in keyof T]?: T[P] } & { [P in keyof U]?: U[P] }; +" +`; + +exports[` 25`] = ` +"type Foo = [number]; + +type Foo = [number] | [number, number]; + +type Foo = [number] & [number, number]; + +type Foo = [number] | ([number, number] & [string, string]); +" +`; + +exports[` 26`] = ` +"type Foo = [number]; + ~~~~~~~~ Type tuple types are not allowed. + +type Foo = [number] & [number, number]; + ~~~~~~~~ Tuple Types in intersection types are not allowed. + ~~~~~~~~~~~~~~~~ Tuple Types in intersection types are not allowed. + +type Foo = [string] & [number]; + ~~~~~~~~ Tuple Types in intersection types are not allowed. + ~~~~~~~~ Tuple Types in intersection types are not allowed. +" +`; + +exports[` 27`] = ` +"type Foo = [number] | [number, number]; + +type Foo = [string] | [number]; +" +`; + +exports[` 28`] = ` +"type Foo = [number]; + ~~~~~~~~ Type tuple types are not allowed. + +type Foo = [number] | [number, number]; + ~~~~~~~~ Tuple Types in union types are not allowed. + ~~~~~~~~~~~~~~~~ Tuple Types in union types are not allowed. + +type Foo = [string] | [number]; + ~~~~~~~~ Tuple Types in union types are not allowed. + ~~~~~~~~ Tuple Types in union types are not allowed. +" +`; + +exports[` 29`] = ` +"type Foo = [number] & [number, number]; + +type Foo = [string] & [number]; +" +`; + +exports[` 30`] = ` +"type Foo = [number]; + ~~~~~~~~ Type tuple types are not allowed. + +type Foo = [string]; + ~~~~~~~~ Type tuple types are not allowed. +" +`; + +exports[` 31`] = ` +"type Foo = [number] & [number, number]; + +type Foo = [string] | [number]; +" +`; + +exports[` 32`] = ` +"type Foo = Bar; + +type Foo = Record; + +type Foo = Readonly; + +type Foo = Partial; + +type Foo = Omit; +" +`; diff --git a/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-unnecessary-boolean-literal-compare.shot b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-unnecessary-boolean-literal-compare.shot new file mode 100644 index 000000000000..d1aa3a7d02ca --- /dev/null +++ b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-unnecessary-boolean-literal-compare.shot @@ -0,0 +1,72 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[` 1`] = ` +"declare const someCondition: boolean; +if (someCondition === true) { + ~~~~~~~~~~~~~~~~~~~~~~ This expression unnecessarily compares a boolean value to a boolean instead of using it directly. +} +" +`; + +exports[` 2`] = ` +"declare const someCondition: boolean; +if (someCondition) { +} + +declare const someObjectBoolean: boolean | Record; +if (someObjectBoolean === true) { +} + +declare const someStringBoolean: boolean | string; +if (someStringBoolean === true) { +} +" +`; + +exports[` 3`] = ` +"declare const someUndefinedCondition: boolean | undefined; +if (someUndefinedCondition === true) { + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ This expression unnecessarily compares a nullable boolean value to true instead of using it directly. +} + +declare const someNullCondition: boolean | null; +if (someNullCondition !== true) { + ~~~~~~~~~~~~~~~~~~~~~~~~~~ This expression unnecessarily compares a nullable boolean value to true instead of negating it. +} +" +`; + +exports[` 4`] = ` +"declare const someUndefinedCondition: boolean | undefined; +if (someUndefinedCondition) { +} + +declare const someNullCondition: boolean | null; +if (!someNullCondition) { +} +" +`; + +exports[` 5`] = ` +"declare const someUndefinedCondition: boolean | undefined; +if (someUndefinedCondition === false) { + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ This expression unnecessarily compares a nullable boolean value to false instead of using the ?? operator to provide a default. +} + +declare const someNullCondition: boolean | null; +if (someNullCondition !== false) { + ~~~~~~~~~~~~~~~~~~~~~~~~~~~ This expression unnecessarily compares a nullable boolean value to false instead of using the ?? operator to provide a default. +} +" +`; + +exports[` 6`] = ` +"declare const someUndefinedCondition: boolean | undefined; +if (someUndefinedCondition ?? true) { +} + +declare const someNullCondition: boolean | null; +if (!(someNullCondition ?? true)) { +} +" +`; diff --git a/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-unnecessary-condition.shot b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-unnecessary-condition.shot new file mode 100644 index 000000000000..f20d185b9896 --- /dev/null +++ b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-unnecessary-condition.shot @@ -0,0 +1,62 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[` 1`] = ` +"function head(items: T[]) { + // items can never be nullable, so this is unnecessary + if (items) { + ~~~~~ Unnecessary conditional, value is always truthy. + return items[0].toUpperCase(); + } +} + +function foo(arg: 'bar' | 'baz') { + // arg is never nullable or empty string, so this is unnecessary + if (arg) { + ~~~ Unnecessary conditional, value is always truthy. + } +} + +function bar(arg: string) { + // arg can never be nullish, so ?. is unnecessary + return arg?.length; + ~~ Unnecessary optional chain on a non-nullish value. +} + +// Checks array predicate return types, where possible +[ + [1, 2], + [3, 4], +].filter(t => t); // number[] is always truthy + ~ Unnecessary conditional, value is always truthy. +" +`; + +exports[` 2`] = ` +"function head(items: T[]) { + // Necessary, since items.length might be 0 + if (items.length) { + return items[0].toUpperCase(); + } +} + +function foo(arg: string) { + // Necessary, since foo might be ''. + if (arg) { + } +} + +function bar(arg?: string | null) { + // Necessary, since arg might be nullish + return arg?.length; +} + +[0, 1, 2, 3].filter(t => t); // number can be truthy or falsy +" +`; + +exports[` 3`] = ` +"while (true) {} +for (; true; ) {} +do {} while (true); +" +`; diff --git a/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-unnecessary-qualifier.shot b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-unnecessary-qualifier.shot new file mode 100644 index 000000000000..62653858b8ba --- /dev/null +++ b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-unnecessary-qualifier.shot @@ -0,0 +1,35 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[` 1`] = ` +"enum A { + B, + C = A.B, + ~ Qualifier is unnecessary since 'B' is in scope. +} +" +`; + +exports[` 2`] = ` +"namespace A { + export type B = number; + const x: A.B = 3; + ~ Qualifier is unnecessary since 'B' is in scope. +} +" +`; + +exports[` 3`] = ` +"enum A { + B, + C = B, +} +" +`; + +exports[` 4`] = ` +"namespace A { + export type B = number; + const x: B = 3; +} +" +`; diff --git a/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-unnecessary-type-arguments.shot b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-unnecessary-type-arguments.shot new file mode 100644 index 000000000000..b6d1c59fbbb2 --- /dev/null +++ b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-unnecessary-type-arguments.shot @@ -0,0 +1,62 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[` 1`] = ` +"function f() {} +f(); + ~~~~~~ This is the default value for this type parameter, so it can be omitted. +" +`; + +exports[` 2`] = ` +"function g() {} +g(); + ~~~~~~ This is the default value for this type parameter, so it can be omitted. +" +`; + +exports[` 3`] = ` +"class C {} +new C(); + ~~~~~~ This is the default value for this type parameter, so it can be omitted. + +class D extends C {} + ~~~~~~ This is the default value for this type parameter, so it can be omitted. +" +`; + +exports[` 4`] = ` +"interface I {} +class Impl implements I {} + ~~~~~~ This is the default value for this type parameter, so it can be omitted. +" +`; + +exports[` 5`] = ` +"function f() {} +f(); +f(); +" +`; + +exports[` 6`] = ` +"function g() {} +g(); +g(); +" +`; + +exports[` 7`] = ` +"class C {} +new C(); +new C(); + +class D extends C {} +class D extends C {} +" +`; + +exports[` 8`] = ` +"interface I {} +class Impl implements I {} +" +`; diff --git a/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-unnecessary-type-assertion.shot b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-unnecessary-type-assertion.shot new file mode 100644 index 000000000000..9e88e96b8016 --- /dev/null +++ b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-unnecessary-type-assertion.shot @@ -0,0 +1,64 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[` 1`] = ` +"const foo = 3; +const bar = foo!; + ~~~~ This assertion is unnecessary since it does not change the type of the expression. +" +`; + +exports[` 2`] = ` +"const foo = (3 + 5); + ~~~~~~~~~~~~~~~ This assertion is unnecessary since it does not change the type of the expression. +" +`; + +exports[` 3`] = ` +"type Foo = number; +const foo = (3 + 5); + ~~~~~~~~~~~~ This assertion is unnecessary since it does not change the type of the expression. +" +`; + +exports[` 4`] = ` +"type Foo = number; +const foo = (3 + 5) as Foo; + ~~~~~~~~~~~~~~ This assertion is unnecessary since it does not change the type of the expression. +" +`; + +exports[` 5`] = ` +"function foo(x: number): number { + return x!; // unnecessary non-null + ~~ This assertion is unnecessary since it does not change the type of the expression. +} +" +`; + +exports[` 6`] = ` +"const foo = 3; +" +`; + +exports[` 7`] = ` +"const foo = 3 as number; +" +`; + +exports[` 8`] = ` +"const foo = 'foo' as const; +" +`; + +exports[` 9`] = ` +"function foo(x: number | undefined): number { + return x!; +} +" +`; + +exports[` 10`] = ` +"type Foo = 3; +const foo: Foo = 3; +" +`; diff --git a/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-unnecessary-type-constraint.shot b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-unnecessary-type-constraint.shot new file mode 100644 index 000000000000..ba70aeeb288a --- /dev/null +++ b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-unnecessary-type-constraint.shot @@ -0,0 +1,43 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[` 1`] = ` +"interface FooAny {} + ~~~~~~~~~~~~~ Constraining the generic type \`T\` to \`any\` does nothing and is unnecessary. + +interface FooUnknown {} + ~~~~~~~~~~~~~~~~~ Constraining the generic type \`T\` to \`unknown\` does nothing and is unnecessary. + +type BarAny = {}; + ~~~~~~~~~~~~~ Constraining the generic type \`T\` to \`any\` does nothing and is unnecessary. + +type BarUnknown = {}; + ~~~~~~~~~~~~~~~~~ Constraining the generic type \`T\` to \`unknown\` does nothing and is unnecessary. + +class BazAny { + ~~~~~~~~~~~~~ Constraining the generic type \`T\` to \`any\` does nothing and is unnecessary. + quxAny() {} + ~~~~~~~~~~~~~ Constraining the generic type \`U\` to \`any\` does nothing and is unnecessary. +} + +const QuuxAny = () => {}; + ~~~~~~~~~~~~~ Constraining the generic type \`T\` to \`any\` does nothing and is unnecessary. + +function QuuzAny() {} + ~~~~~~~~~~~~~ Constraining the generic type \`T\` to \`any\` does nothing and is unnecessary. +" +`; + +exports[` 2`] = ` +"interface Foo {} + +type Bar = {}; + +class Baz { + qux() {} +} + +const Quux = () => {}; + +function Quuz() {} +" +`; diff --git a/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-unsafe-argument.shot b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-unsafe-argument.shot new file mode 100644 index 000000000000..70ac42f52505 --- /dev/null +++ b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-unsafe-argument.shot @@ -0,0 +1,56 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[` 1`] = ` +"declare function foo(arg1: string, arg2: number, arg3: string): void; + +const anyTyped = 1 as any; + +foo(...anyTyped); + ~~~~~~~~~~~ Unsafe spread of an \`any\` type. +foo(anyTyped, 1, 'a'); + ~~~~~~~~ Unsafe argument of type \`any\` assigned to a parameter of type \`string\`. + +const anyArray: any[] = []; +foo(...anyArray); + ~~~~~~~~~~~ Unsafe spread of an \`any\` array type. + +const tuple1 = ['a', anyTyped, 'b'] as const; +foo(...tuple1); + ~~~~~~~~~ Unsafe spread of a tuple type. The argument is of type \`any\` and is assigned to a parameter of type \`number\`. + +const tuple2 = [1] as const; +foo('a', ...tuple, anyTyped); + ~~~~~~~~ Unsafe spread of an \`any\` type. + ~~~~~~~~ Unsafe argument of type \`any\` assigned to a parameter of type \`number\`. + +declare function bar(arg1: string, arg2: number, ...rest: string[]): void; +const x = [1, 2] as [number, ...number[]]; +foo('a', ...x, anyTyped); + +declare function baz(arg1: Set, arg2: Map): void; +foo(new Set(), new Map()); +" +`; + +exports[` 2`] = ` +"declare function foo(arg1: string, arg2: number, arg3: string): void; + +foo('a', 1, 'b'); + +const tuple1 = ['a', 1, 'b'] as const; +foo(...tuple1); + +declare function bar(arg1: string, arg2: number, ...rest: string[]): void; +const array: string[] = ['a']; +bar('a', 1, ...array); + +declare function baz(arg1: Set, arg2: Map): void; +foo(new Set(), new Map()); +" +`; + +exports[` 3`] = ` +"declare function foo(arg1: unknown, arg2: Set, arg3: unknown[]): void; +foo(1 as any, new Set(), [] as any[]); +" +`; diff --git a/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-unsafe-assignment.shot b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-unsafe-assignment.shot new file mode 100644 index 000000000000..ccb42ef82c12 --- /dev/null +++ b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-unsafe-assignment.shot @@ -0,0 +1,67 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[` 1`] = ` +"const x = 1 as any, + ~~~~~~~~~~~~ Unsafe assignment of an \`any\` value. + y = 1 as any; + ~~~~~~~~~~~~ Unsafe assignment of an \`any\` value. +const [x] = 1 as any; + ~~~~~~~~~~~~~~ Unsafe assignment of an \`any\` value. +const [x] = [] as any[]; + ~~~ Unsafe array destructuring of an \`any\` array value. +const [x] = [1 as any]; + ~ Unsafe array destructuring of a tuple element with an \`any\` value. +[x] = [1] as [any]; + ~ Unsafe array destructuring of a tuple element with an \`any\` value. + +function foo(a = 1 as any) {} + ~~~~~~~~~~~~ Unsafe assignment of an \`any\` value. +class Foo { + constructor(private a = 1 as any) {} + ~~~~~~~~~~~~ Unsafe assignment of an \`any\` value. +} +class Foo { + private a = 1 as any; + ~~~~~~~~~~~~~~~~~~~~~ Unsafe assignment of an \`any\` value. +} + +// generic position examples +const x: Set = new Set(); + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Unsafe assignment of type Set to a variable of type Set. +const x: Map = new Map(); + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Unsafe assignment of type Map to a variable of type Map. +const x: Set = new Set(); + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Unsafe assignment of type Set to a variable of type Set. +const x: Set>> = new Set>>(); + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Unsafe assignment of type Set>> to a variable of type Set>>. +" +`; + +exports[` 2`] = ` +"const x = 1, + y = 1; +const [x] = [1]; +[x] = [1] as [number]; + +function foo(a = 1) {} +class Foo { + constructor(private a = 1) {} +} +class Foo { + private a = 1; +} + +// generic position examples +const x: Set = new Set(); +const x: Map = new Map(); +const x: Set = new Set(); +const x: Set>> = new Set>>(); +" +`; + +exports[` 3`] = ` +"const x: unknown = y as any; +const x: unknown[] = y as any[]; +const x: Set = y as Set; +" +`; diff --git a/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-unsafe-call.shot b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-unsafe-call.shot new file mode 100644 index 000000000000..9e360be9998f --- /dev/null +++ b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-unsafe-call.shot @@ -0,0 +1,42 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[` 1`] = ` +"declare const anyVar: any; +declare const nestedAny: { prop: any }; + +anyVar(); +~~~~~~ Unsafe call of an \`any\` typed value. +anyVar.a.b(); +~~~~~~~~~~ Unsafe call of an \`any\` typed value. + +nestedAny.prop(); +~~~~~~~~~~~~~~ Unsafe call of an \`any\` typed value. +nestedAny.prop['a'](); +~~~~~~~~~~~~~~~~~~~ Unsafe call of an \`any\` typed value. + +new anyVar(); +~~~~~~~~~~~~ Unsafe construction of an any type value. +new nestedAny.prop(); +~~~~~~~~~~~~~~~~~~~~ Unsafe construction of an any type value. + +anyVar\`foo\`; +~~~~~~ Unsafe any typed template tag. +nestedAny.prop\`foo\`; +~~~~~~~~~~~~~~ Unsafe any typed template tag. +" +`; + +exports[` 2`] = ` +"declare const typedVar: () => void; +declare const typedNested: { prop: { a: () => void } }; + +typedVar(); +typedNested.prop.a(); + +(() => {})(); + +new Map(); + +String.raw\`foo\`; +" +`; diff --git a/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-unsafe-declaration-merging.shot b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-unsafe-declaration-merging.shot new file mode 100644 index 000000000000..4d40546ae264 --- /dev/null +++ b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-unsafe-declaration-merging.shot @@ -0,0 +1,23 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[` 1`] = ` +"interface Foo {} + ~~~ Unsafe declaration merging between classes and interfaces. + +class Foo {} + ~~~ Unsafe declaration merging between classes and interfaces. +" +`; + +exports[` 2`] = ` +"interface Foo {} +class Bar implements Foo {} + +namespace Baz {} +namespace Baz {} +enum Baz {} + +namespace Qux {} +function Qux() {} +" +`; diff --git a/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-unsafe-enum-comparison.shot b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-unsafe-enum-comparison.shot new file mode 100644 index 000000000000..e74d7d0c2e2c --- /dev/null +++ b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-unsafe-enum-comparison.shot @@ -0,0 +1,47 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[` 1`] = ` +"enum Fruit { + Apple, +} + +declare let fruit: Fruit; + +fruit === 0; +~~~~~~~~~~~ The two values in this comparison do not have a shared enum type. +" +`; + +exports[` 2`] = ` +"enum Vegetable { + Asparagus = 'asparagus', +} + +declare let vegetable: Vegetable; + +vegetable === 'asparagus'; +~~~~~~~~~~~~~~~~~~~~~~~~~ The two values in this comparison do not have a shared enum type. +" +`; + +exports[` 3`] = ` +"enum Fruit { + Apple, +} + +declare let fruit: Fruit; + +fruit === Fruit.Apple; +" +`; + +exports[` 4`] = ` +"enum Vegetable { + Asparagus = 'asparagus', +} + +declare let vegetable: Vegetable; + +vegetable === Vegetable.Asparagus; +" +`; diff --git a/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-unsafe-member-access.shot b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-unsafe-member-access.shot new file mode 100644 index 000000000000..b826748c49d8 --- /dev/null +++ b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-unsafe-member-access.shot @@ -0,0 +1,49 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[` 1`] = ` +"declare const anyVar: any; +declare const nestedAny: { prop: any }; + +anyVar.a; + ~ Unsafe member access .a on an \`any\` value. +anyVar.a.b; + ~ Unsafe member access .a on an \`any\` value. +anyVar['a']; + ~~~ Unsafe member access ['a'] on an \`any\` value. +anyVar['a']['b']; + ~~~ Unsafe member access ['a'] on an \`any\` value. + +nestedAny.prop.a; + ~ Unsafe member access .a on an \`any\` value. +nestedAny.prop['a']; + ~~~ Unsafe member access ['a'] on an \`any\` value. + +const key = 'a'; +nestedAny.prop[key]; + ~~~ Unsafe member access [key] on an \`any\` value. + +// Using an any to access a member is unsafe +const arr = [1, 2, 3]; +arr[anyVar]; + ~~~~~~ Computed name [anyVar] resolves to an any value. +nestedAny[anyVar]; + ~~~~~~ Computed name [anyVar] resolves to an any value. +" +`; + +exports[` 2`] = ` +"declare const properlyTyped: { prop: { a: string } }; + +properlyTyped.prop.a; +properlyTyped.prop['a']; + +const key = 'a'; +properlyTyped.prop[key]; + +const arr = [1, 2, 3]; +arr[1]; +let idx = 1; +arr[idx]; +arr[idx++]; +" +`; diff --git a/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-unsafe-return.shot b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-unsafe-return.shot new file mode 100644 index 000000000000..88a32d25c8f5 --- /dev/null +++ b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-unsafe-return.shot @@ -0,0 +1,84 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[` 1`] = ` +"function foo1() { + return 1 as any; + ~~~~~~~~~~~~~~~~ Unsafe return of an \`any\` typed value. +} +function foo2() { + return Object.create(null); + ~~~~~~~~~~~~~~~~~~~~~~~~~~~ Unsafe return of an \`any\` typed value. +} +const foo3 = () => { + return 1 as any; + ~~~~~~~~~~~~~~~~ Unsafe return of an \`any\` typed value. +}; +const foo4 = () => Object.create(null); + ~~~~~~~~~~~~~~~~~~~ Unsafe return of an \`any\` typed value. + +function foo5() { + return [] as any[]; + ~~~~~~~~~~~~~~~~~~~ Unsafe return of an \`any[]\` typed value. +} +function foo6() { + return [] as Array; + ~~~~~~~~~~~~~~~~~~~~~~~~ Unsafe return of an \`any[]\` typed value. +} +function foo7() { + return [] as readonly any[]; + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Unsafe return of an \`any[]\` typed value. +} +function foo8() { + return [] as Readonly; + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Unsafe return of an \`any[]\` typed value. +} +const foo9 = () => { + return [] as any[]; + ~~~~~~~~~~~~~~~~~~~ Unsafe return of an \`any[]\` typed value. +}; +const foo10 = () => [] as any[]; + ~~~~~~~~~~~ Unsafe return of an \`any[]\` typed value. + +const foo11 = (): string[] => [1, 2, 3] as any[]; + ~~~~~~~~~~~~~~~~~~ Unsafe return of an \`any[]\` typed value. + +// generic position examples +function assignability1(): Set { + return new Set([1]); + ~~~~~~~~~~~~~~~~~~~~~~~~~ Unsafe return of type \`Set\` from function with return type \`Set\`. +} +type TAssign = () => Set; +const assignability2: TAssign = () => new Set([true]); + ~~~~~~~~~~~~~~~~~~~~ Unsafe return of type \`Set\` from function with return type \`Set\`. +" +`; + +exports[` 2`] = ` +"function foo1() { + return 1; +} +function foo2() { + return Object.create(null) as Record; +} + +const foo3 = () => []; +const foo4 = () => ['a']; + +function assignability1(): Set { + return new Set(['foo']); +} +type TAssign = () => Set; +const assignability2: TAssign = () => new Set(['foo']); +" +`; + +exports[` 3`] = ` +"function foo1(): unknown { + return JSON.parse(singleObjString); // Return type for JSON.parse is any. +} + +function foo2(): unknown[] { + return [] as any[]; +} +" +`; diff --git a/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-use-before-define.shot b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-use-before-define.shot new file mode 100644 index 000000000000..3f47d8e0921b --- /dev/null +++ b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-use-before-define.shot @@ -0,0 +1,37 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[` 1`] = ` +"const x = Foo.FOO; + ~~~ 'Foo' was used before it was defined. + +enum Foo { + FOO, +} +" +`; + +exports[` 2`] = ` +"function foo() { + return Foo.FOO; +} + +enum Foo { + FOO, +} +" +`; + +exports[` 3`] = ` +"let myVar: StringOrNumber; +type StringOrNumber = string | number; +" +`; + +exports[` 4`] = ` +"let var1: StringOrNumber; +type StringOrNumber = string | number; + +let var2: Enum; +enum Enum {} +" +`; diff --git a/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-useless-empty-export.shot b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-useless-empty-export.shot new file mode 100644 index 000000000000..5f550e823246 --- /dev/null +++ b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-useless-empty-export.shot @@ -0,0 +1,25 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[` 1`] = ` +"export const value = 'Hello, world!'; +export {}; +~~~~~~~~~~ Empty export does nothing and can be removed. +" +`; + +exports[` 2`] = ` +"import 'some-other-module'; +export {}; +~~~~~~~~~~ Empty export does nothing and can be removed. +" +`; + +exports[` 3`] = ` +"export const value = 'Hello, world!'; +" +`; + +exports[` 4`] = ` +"import 'some-other-module'; +" +`; diff --git a/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-useless-template-literals.shot b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-useless-template-literals.shot new file mode 100644 index 000000000000..01b854c49a75 --- /dev/null +++ b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-useless-template-literals.shot @@ -0,0 +1,42 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[` 1`] = ` +"const ab1 = \`\${'a'}\${'b'}\`; + ~~~ Template literal expression is unnecessary and can be simplified. + ~~~ Template literal expression is unnecessary and can be simplified. +const ab2 = \`a\${'b'}\`; + ~~~ Template literal expression is unnecessary and can be simplified. + +const stringWithNumber = \`\${'1 + 1 = '}\${2}\`; + ~~~~~~~~~~ Template literal expression is unnecessary and can be simplified. + ~ Template literal expression is unnecessary and can be simplified. + +const stringWithBoolean = \`\${'true is '}\${true}\`; + ~~~~~~~~~~ Template literal expression is unnecessary and can be simplified. + ~~~~ Template literal expression is unnecessary and can be simplified. + +const text = 'a'; +const wrappedText = \`\${text}\`; + ~~~~ Template literal expression is unnecessary and can be simplified. + +declare const intersectionWithString: string & { _brand: 'test-brand' }; +const wrappedIntersection = \`\${intersectionWithString}\`; + ~~~~~~~~~~~~~~~~~~~~~~ Template literal expression is unnecessary and can be simplified. +" +`; + +exports[` 2`] = ` +"const ab1 = 'ab'; +const ab2 = 'ab'; + +const stringWithNumber = \`1 + 1 = 2\`; + +const stringWithBoolean = \`true is true\`; + +const text = 'a'; +const wrappedText = text; + +declare const intersectionWithString: string & { _brand: 'test-brand' }; +const wrappedIntersection = intersectionWithString; +" +`; diff --git a/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-var-requires.shot b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-var-requires.shot new file mode 100644 index 000000000000..643832c52ba3 --- /dev/null +++ b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-var-requires.shot @@ -0,0 +1,29 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[` 1`] = ` +"var foo = require('foo'); + ~~~~~~~~~~~~~~ Require statement not part of import statement. +const foo = require('foo'); + ~~~~~~~~~~~~~~ Require statement not part of import statement. +let foo = require('foo'); + ~~~~~~~~~~~~~~ Require statement not part of import statement. +" +`; + +exports[` 2`] = ` +"import foo = require('foo'); +require('foo'); +import foo from 'foo'; +" +`; + +exports[` 3`] = ` +"const foo = require('../data.json'); + ~~~~~~~~~~~~~~~~~~~~~~~ Require statement not part of import statement. +" +`; + +exports[` 4`] = ` +"const foo = require('../package.json'); +" +`; diff --git a/packages/eslint-plugin/tests/docs-eslint-output-snapshots/non-nullable-type-assertion-style.shot b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/non-nullable-type-assertion-style.shot new file mode 100644 index 000000000000..114d8c7d1c45 --- /dev/null +++ b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/non-nullable-type-assertion-style.shot @@ -0,0 +1,19 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[` 1`] = ` +"const maybe: string | undefined = Math.random() > 0.5 ? '' : undefined; + +const definitely = maybe as string; + ~~~~~~~~~~~~~~~ Use a ! assertion to more succinctly remove null and undefined from the type. +const alsoDefinitely = maybe; + ~~~~~~~~~~~~~ Use a ! assertion to more succinctly remove null and undefined from the type. +" +`; + +exports[` 2`] = ` +"const maybe: string | undefined = Math.random() > 0.5 ? '' : undefined; + +const definitely = maybe!; +const alsoDefinitely = maybe!; +" +`; diff --git a/packages/eslint-plugin/tests/docs-eslint-output-snapshots/parameter-properties.shot b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/parameter-properties.shot new file mode 100644 index 000000000000..66cb073e6ffb --- /dev/null +++ b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/parameter-properties.shot @@ -0,0 +1,406 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[` 1`] = ` +"class Foo { + constructor(readonly name: string) {} + ~~~~~~~~~~~~~~~~~~~~~ Property name should be declared as a class property. +} + +class Foo { + constructor(private name: string) {} + ~~~~~~~~~~~~~~~~~~~~ Property name should be declared as a class property. +} + +class Foo { + constructor(protected name: string) {} + ~~~~~~~~~~~~~~~~~~~~~~ Property name should be declared as a class property. +} + +class Foo { + constructor(public name: string) {} + ~~~~~~~~~~~~~~~~~~~ Property name should be declared as a class property. +} + +class Foo { + constructor(private readonly name: string) {} + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Property name should be declared as a class property. +} + +class Foo { + constructor(protected readonly name: string) {} + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Property name should be declared as a class property. +} + +class Foo { + constructor(public readonly name: string) {} + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Property name should be declared as a class property. +} +" +`; + +exports[` 2`] = ` +"class Foo { + constructor(name: string) {} +} +" +`; + +exports[` 3`] = ` +"class Foo { + constructor(private name: string) {} + ~~~~~~~~~~~~~~~~~~~~ Property name should be declared as a class property. +} + +class Foo { + constructor(protected name: string) {} + ~~~~~~~~~~~~~~~~~~~~~~ Property name should be declared as a class property. +} + +class Foo { + constructor(public name: string) {} + ~~~~~~~~~~~~~~~~~~~ Property name should be declared as a class property. +} + +class Foo { + constructor(private readonly name: string) {} + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Property name should be declared as a class property. +} + +class Foo { + constructor(protected readonly name: string) {} + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Property name should be declared as a class property. +} + +class Foo { + constructor(public readonly name: string) {} + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Property name should be declared as a class property. +} +" +`; + +exports[` 4`] = ` +"class Foo { + constructor(name: string) {} +} + +class Foo { + constructor(readonly name: string) {} +} +" +`; + +exports[` 5`] = ` +"class Foo { + constructor(readonly name: string) {} + ~~~~~~~~~~~~~~~~~~~~~ Property name should be declared as a class property. +} + +class Foo { + constructor(protected name: string) {} + ~~~~~~~~~~~~~~~~~~~~~~ Property name should be declared as a class property. +} + +class Foo { + constructor(public name: string) {} + ~~~~~~~~~~~~~~~~~~~ Property name should be declared as a class property. +} + +class Foo { + constructor(private readonly name: string) {} + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Property name should be declared as a class property. +} + +class Foo { + constructor(protected readonly name: string) {} + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Property name should be declared as a class property. +} + +class Foo { + constructor(public readonly name: string) {} + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Property name should be declared as a class property. +} +" +`; + +exports[` 6`] = ` +"class Foo { + constructor(name: string) {} +} + +class Foo { + constructor(private name: string) {} +} +" +`; + +exports[` 7`] = ` +"class Foo { + constructor(readonly name: string) {} + ~~~~~~~~~~~~~~~~~~~~~ Property name should be declared as a class property. +} + +class Foo { + constructor(private name: string) {} + ~~~~~~~~~~~~~~~~~~~~ Property name should be declared as a class property. +} + +class Foo { + constructor(public name: string) {} + ~~~~~~~~~~~~~~~~~~~ Property name should be declared as a class property. +} + +class Foo { + constructor(private readonly name: string) {} + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Property name should be declared as a class property. +} + +class Foo { + constructor(protected readonly name: string) {} + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Property name should be declared as a class property. +} + +class Foo { + constructor(public readonly name: string) {} + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Property name should be declared as a class property. +} +" +`; + +exports[` 8`] = ` +"class Foo { + constructor(name: string) {} +} + +class Foo { + constructor(protected name: string) {} +} +" +`; + +exports[` 9`] = ` +"class Foo { + constructor(readonly name: string) {} + ~~~~~~~~~~~~~~~~~~~~~ Property name should be declared as a class property. +} + +class Foo { + constructor(private name: string) {} + ~~~~~~~~~~~~~~~~~~~~ Property name should be declared as a class property. +} + +class Foo { + constructor(protected name: string) {} + ~~~~~~~~~~~~~~~~~~~~~~ Property name should be declared as a class property. +} + +class Foo { + constructor(private readonly name: string) {} + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Property name should be declared as a class property. +} + +class Foo { + constructor(protected readonly name: string) {} + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Property name should be declared as a class property. +} + +class Foo { + constructor(public readonly name: string) {} + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Property name should be declared as a class property. +} +" +`; + +exports[` 10`] = ` +"class Foo { + constructor(name: string) {} +} + +class Foo { + constructor(public name: string) {} +} +" +`; + +exports[` 11`] = ` +"class Foo { + constructor(readonly name: string) {} + ~~~~~~~~~~~~~~~~~~~~~ Property name should be declared as a class property. +} + +class Foo { + constructor(private name: string) {} + ~~~~~~~~~~~~~~~~~~~~ Property name should be declared as a class property. +} + +class Foo { + constructor(protected name: string) {} + ~~~~~~~~~~~~~~~~~~~~~~ Property name should be declared as a class property. +} + +class Foo { + constructor(public name: string) {} + ~~~~~~~~~~~~~~~~~~~ Property name should be declared as a class property. +} + +class Foo { + constructor(protected readonly name: string) {} + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Property name should be declared as a class property. +} + +class Foo { + constructor(public readonly name: string) {} + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Property name should be declared as a class property. +} +" +`; + +exports[` 12`] = ` +"class Foo { + constructor(name: string) {} +} + +class Foo { + constructor(private readonly name: string) {} +} +" +`; + +exports[` 13`] = ` +"class Foo { + constructor(readonly name: string) {} + ~~~~~~~~~~~~~~~~~~~~~ Property name should be declared as a class property. +} + +class Foo { + constructor(private name: string) {} + ~~~~~~~~~~~~~~~~~~~~ Property name should be declared as a class property. +} + +class Foo { + constructor(protected name: string) {} + ~~~~~~~~~~~~~~~~~~~~~~ Property name should be declared as a class property. +} + +class Foo { + constructor(public name: string) {} + ~~~~~~~~~~~~~~~~~~~ Property name should be declared as a class property. +} + +class Foo { + constructor(private readonly name: string) {} + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Property name should be declared as a class property. +} + +class Foo { + constructor(public readonly name: string) {} + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Property name should be declared as a class property. +} +" +`; + +exports[` 14`] = ` +"class Foo { + constructor(name: string) {} +} + +class Foo { + constructor(protected readonly name: string) {} +} +" +`; + +exports[` 15`] = ` +"class Foo { + constructor(readonly name: string) {} + ~~~~~~~~~~~~~~~~~~~~~ Property name should be declared as a class property. +} + +class Foo { + constructor(private name: string) {} + ~~~~~~~~~~~~~~~~~~~~ Property name should be declared as a class property. +} + +class Foo { + constructor(protected name: string) {} + ~~~~~~~~~~~~~~~~~~~~~~ Property name should be declared as a class property. +} + +class Foo { + constructor(public name: string) {} + ~~~~~~~~~~~~~~~~~~~ Property name should be declared as a class property. +} + +class Foo { + constructor(private readonly name: string) {} + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Property name should be declared as a class property. +} + +class Foo { + constructor(protected readonly name: string) {} + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Property name should be declared as a class property. +} +" +`; + +exports[` 16`] = ` +"class Foo { + constructor(name: string) {} +} + +class Foo { + constructor(public readonly name: string) {} +} +" +`; + +exports[` 17`] = ` +"class Foo { + private name: string; + ~~~~~~~~~~~~~~~~~~~~~ Property name should be declared as a parameter property. + constructor(name: string) { + this.name = name; + } +} + +class Foo { + public readonly name: string; + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Property name should be declared as a parameter property. + constructor(name: string) { + this.name = name; + } +} + +class Foo { + constructor(name: string) { + this.name = name; + } + name: string; + ~~~~~~~~~~~~~ Property name should be declared as a parameter property. +} +" +`; + +exports[` 18`] = ` +"class Foo { + private differentName: string; + constructor(name: string) { + this.differentName = name; + } +} + +class Foo { + private differentType: number | undefined; + constructor(differentType: number) { + this.differentType = differentType; + } +} + +class Foo { + protected logicInConstructor: string; + constructor(logicInConstructor: string) { + console.log('Hello, world!'); + this.logicInConstructor = logicInConstructor; + } +} +" +`; diff --git a/packages/eslint-plugin/tests/docs-eslint-output-snapshots/prefer-as-const.shot b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/prefer-as-const.shot new file mode 100644 index 000000000000..5de1bdb65c03 --- /dev/null +++ b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/prefer-as-const.shot @@ -0,0 +1,21 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[` 1`] = ` +"let bar: 2 = 2; + ~ Expected a \`const\` assertion instead of a literal type annotation. +let foo = <'bar'>'bar'; + ~~~~~ Expected a \`const\` instead of a literal type assertion. +let foo = { bar: 'baz' as 'baz' }; + ~~~~~ Expected a \`const\` instead of a literal type assertion. +" +`; + +exports[` 2`] = ` +"let foo = 'bar'; +let foo = 'bar' as const; +let foo: 'bar' = 'bar' as const; +let bar = 'bar' as string; +let foo = 'bar'; +let foo = { bar: 'baz' }; +" +`; diff --git a/packages/eslint-plugin/tests/docs-eslint-output-snapshots/prefer-destructuring.shot b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/prefer-destructuring.shot new file mode 100644 index 000000000000..0e07875747ce --- /dev/null +++ b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/prefer-destructuring.shot @@ -0,0 +1,36 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[` 1`] = ` +"const x: string = obj.x; // This is incorrect and the auto fixer provides following untyped fix. +// const { x } = obj; +" +`; + +exports[` 2`] = ` +"const x: string = obj.x; // This is correct by default. You can also forbid this by an option. +" +`; + +exports[` 3`] = ` +"const x = ['a']; +const y = x[0]; + ~~~~~~~~ Use array destructuring. +" +`; + +exports[` 4`] = ` +"const x = { 0: 'a' }; +const y = x[0]; +" +`; + +exports[` 5`] = ` +"const x: string = obj.x; + ~~~~~~~~~~~~~~~~~ Use object destructuring. +" +`; + +exports[` 6`] = ` +"const { x }: { x: string } = obj; +" +`; diff --git a/packages/eslint-plugin/tests/docs-eslint-output-snapshots/prefer-enum-initializers.shot b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/prefer-enum-initializers.shot new file mode 100644 index 000000000000..47709c000979 --- /dev/null +++ b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/prefer-enum-initializers.shot @@ -0,0 +1,43 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[` 1`] = ` +"enum Status { + Open = 1, + Close, + ~~~~~ The value of the member 'Close' should be explicitly defined. +} + +enum Direction { + Up, + ~~ The value of the member 'Up' should be explicitly defined. + Down, + ~~~~ The value of the member 'Down' should be explicitly defined. +} + +enum Color { + Red, + ~~~ The value of the member 'Red' should be explicitly defined. + Green = 'Green', + Blue = 'Blue', +} +" +`; + +exports[` 2`] = ` +"enum Status { + Open = 'Open', + Close = 'Close', +} + +enum Direction { + Up = 1, + Down = 2, +} + +enum Color { + Red = 'Red', + Green = 'Green', + Blue = 'Blue', +} +" +`; diff --git a/packages/eslint-plugin/tests/docs-eslint-output-snapshots/prefer-find.shot b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/prefer-find.shot new file mode 100644 index 000000000000..3be12cafc1cf --- /dev/null +++ b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/prefer-find.shot @@ -0,0 +1,15 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[` 1`] = ` +"[1, 2, 3].filter(x => x > 1)[0]; +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Prefer .find(...) instead of .filter(...)[0]. + +[1, 2, 3].filter(x => x > 1).at(0); +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Prefer .find(...) instead of .filter(...)[0]. +" +`; + +exports[` 2`] = ` +"[1, 2, 3].find(x => x > 1); +" +`; diff --git a/packages/eslint-plugin/tests/docs-eslint-output-snapshots/prefer-for-of.shot b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/prefer-for-of.shot new file mode 100644 index 000000000000..4ae30861b4bd --- /dev/null +++ b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/prefer-for-of.shot @@ -0,0 +1,27 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[` 1`] = ` +"declare const array: string[]; + +for (let i = 0; i < array.length; i++) { +~ Expected a \`for-of\` loop instead of a \`for\` loop with this simple iteration. + console.log(array[i]); +~~~~~~~~~~~~~~~~~~~~~~~~ +} +~ +" +`; + +exports[` 2`] = ` +"declare const array: string[]; + +for (const x of array) { + console.log(x); +} + +for (let i = 0; i < array.length; i++) { + // i is used, so for-of could not be used. + console.log(i, array[i]); +} +" +`; diff --git a/packages/eslint-plugin/tests/docs-eslint-output-snapshots/prefer-function-type.shot b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/prefer-function-type.shot new file mode 100644 index 000000000000..ff02ff4573fc --- /dev/null +++ b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/prefer-function-type.shot @@ -0,0 +1,72 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[` 1`] = ` +"interface Example { + (): string; + ~~~~~~~~~~~ Interface only has a call signature, you should use a function type instead. +} +" +`; + +exports[` 2`] = ` +"function foo(example: { (): number }): number { + ~~~~~~~~~~ Type literal only has a call signature, you should use a function type instead. + return example(); +} +" +`; + +exports[` 3`] = ` +"interface ReturnsSelf { + // returns the function itself, not the \`this\` argument. + (arg: string): this; + ~~~~ \`this\` refers to the function type 'ReturnsSelf', did you intend to use a generic \`this\` parameter like \`(this: Self, ...) => Self\` instead? +} +" +`; + +exports[` 4`] = ` +"type Example = () => string; +" +`; + +exports[` 5`] = ` +"function foo(example: () => number): number { + return bar(); +} +" +`; + +exports[` 6`] = ` +"// returns the function itself, not the \`this\` argument. +type ReturnsSelf = (arg: string) => ReturnsSelf; +" +`; + +exports[` 7`] = ` +"function foo(bar: { (): string; baz: number }): string { + return bar(); +} +" +`; + +exports[` 8`] = ` +"interface Foo { + bar: string; +} +interface Bar extends Foo { + (): void; +} +" +`; + +exports[` 9`] = ` +"// multiple call signatures (overloads) is allowed: +interface Overloaded { + (data: string): number; + (id: number): string; +} +// this is equivelent to Overloaded interface. +type Intersection = ((data: string) => number) & ((id: number) => string); +" +`; diff --git a/packages/eslint-plugin/tests/docs-eslint-output-snapshots/prefer-includes.shot b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/prefer-includes.shot new file mode 100644 index 000000000000..52168ee538d2 --- /dev/null +++ b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/prefer-includes.shot @@ -0,0 +1,58 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[` 1`] = ` +"const str: string; +const array: any[]; +const readonlyArray: ReadonlyArray; +const typedArray: UInt8Array; +const maybe: string; +const userDefined: { + indexOf(x: any): number; + includes(x: any): boolean; +}; + +str.indexOf(value) !== -1; +~~~~~~~~~~~~~~~~~~~~~~~~~ Use 'includes()' method instead. +array.indexOf(value) !== -1; +~~~~~~~~~~~~~~~~~~~~~~~~~~~ Use 'includes()' method instead. +readonlyArray.indexOf(value) === -1; +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Use 'includes()' method instead. +typedArray.indexOf(value) > -1; +maybe?.indexOf('') !== -1; +~~~~~~~~~~~~~~~~~~~~~~~~~ Use 'includes()' method instead. +userDefined.indexOf(value) >= 0; +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Use 'includes()' method instead. + +/example/.test(str); +~~~~~~~~~~~~~~~~~~~ Use \`String#includes()\` method with a string instead. +" +`; + +exports[` 2`] = ` +"const str: string; +const array: any[]; +const readonlyArray: ReadonlyArray; +const typedArray: UInt8Array; +const maybe: string; +const userDefined: { + indexOf(x: any): number; + includes(x: any): boolean; +}; + +str.includes(value); +array.includes(value); +!readonlyArray.includes(value); +typedArray.includes(value); +maybe?.includes(''); +userDefined.includes(value); + +str.includes('example'); + +// The two methods have different parameters. +declare const mismatchExample: { + indexOf(x: unknown, fromIndex?: number): number; + includes(x: unknown): boolean; +}; +mismatchExample.indexOf(value) >= 0; +" +`; diff --git a/packages/eslint-plugin/tests/docs-eslint-output-snapshots/prefer-literal-enum-member.shot b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/prefer-literal-enum-member.shot new file mode 100644 index 000000000000..1d59870e05ff --- /dev/null +++ b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/prefer-literal-enum-member.shot @@ -0,0 +1,62 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[` 1`] = ` +"const str = 'Test'; +enum Invalid { + A = str, // Variable assignment + ~ Explicit enum value must only be a literal value (string, number, boolean, etc). + B = {}, // Object assignment + ~ Explicit enum value must only be a literal value (string, number, boolean, etc). + C = \`A template literal string\`, // Template literal + D = new Set(1, 2, 3), // Constructor in assignment + ~ Explicit enum value must only be a literal value (string, number, boolean, etc). + E = 2 + 2, // Expression assignment + ~ Explicit enum value must only be a literal value (string, number, boolean, etc). +} +" +`; + +exports[` 2`] = ` +"enum Valid { + A, + B = 'TestStr', // A regular string + C = 4, // A number + D = null, + E = /some_regex/, +} +" +`; + +exports[` 3`] = ` +"const x = 1; +enum Foo { + A = x << 0, + ~ Explicit enum value must only be a literal value (string, number, boolean, etc). + B = x >> 0, + ~ Explicit enum value must only be a literal value (string, number, boolean, etc). + C = x >>> 0, + ~ Explicit enum value must only be a literal value (string, number, boolean, etc). + D = x | 0, + ~ Explicit enum value must only be a literal value (string, number, boolean, etc). + E = x & 0, + ~ Explicit enum value must only be a literal value (string, number, boolean, etc). + F = x ^ 0, + ~ Explicit enum value must only be a literal value (string, number, boolean, etc). + G = ~x, + ~ Explicit enum value must only be a literal value (string, number, boolean, etc). +} +" +`; + +exports[` 4`] = ` +"enum Foo { + A = 1 << 0, + B = 1 >> 0, + C = 1 >>> 0, + D = 1 | 0, + E = 1 & 0, + F = 1 ^ 0, + G = ~1, +} +" +`; diff --git a/packages/eslint-plugin/tests/docs-eslint-output-snapshots/prefer-namespace-keyword.shot b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/prefer-namespace-keyword.shot new file mode 100644 index 000000000000..f345448a88c2 --- /dev/null +++ b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/prefer-namespace-keyword.shot @@ -0,0 +1,14 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[` 1`] = ` +"module Example {} +~~~~~~~~~~~~~~~~~ Use 'namespace' instead of 'module' to declare custom TypeScript modules. +" +`; + +exports[` 2`] = ` +"namespace Example {} + +declare module 'foo' {} +" +`; diff --git a/packages/eslint-plugin/tests/docs-eslint-output-snapshots/prefer-nullish-coalescing.shot b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/prefer-nullish-coalescing.shot new file mode 100644 index 000000000000..644cc3e23dbe --- /dev/null +++ b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/prefer-nullish-coalescing.shot @@ -0,0 +1,122 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[` 1`] = ` +"const foo: any = 'bar'; +foo !== undefined && foo !== null ? foo : 'a string'; +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Prefer using nullish coalescing operator (\`??\`) instead of a ternary expression, as it is simpler to read. +foo === undefined || foo === null ? 'a string' : foo; +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Prefer using nullish coalescing operator (\`??\`) instead of a ternary expression, as it is simpler to read. +foo == undefined ? 'a string' : foo; +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Prefer using nullish coalescing operator (\`??\`) instead of a ternary expression, as it is simpler to read. +foo == null ? 'a string' : foo; +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Prefer using nullish coalescing operator (\`??\`) instead of a ternary expression, as it is simpler to read. + +const foo: string | undefined = 'bar'; +foo !== undefined ? foo : 'a string'; +foo === undefined ? 'a string' : foo; + +const foo: string | null = 'bar'; +foo !== null ? foo : 'a string'; +foo === null ? 'a string' : foo; +" +`; + +exports[` 2`] = ` +"const foo: any = 'bar'; +foo ?? 'a string'; +foo ?? 'a string'; +foo ?? 'a string'; +foo ?? 'a string'; + +const foo: string | undefined = 'bar'; +foo ?? 'a string'; +foo ?? 'a string'; + +const foo: string | null = 'bar'; +foo ?? 'a string'; +foo ?? 'a string'; +" +`; + +exports[` 3`] = ` +"declare const a: string | null; +declare const b: string | null; + +if (a || b) { + ~~ Prefer using nullish coalescing operator (\`??\`) instead of a logical or (\`||\`), as it is a safer operator. +} +if ((a ||= b)) { +} +while (a || b) {} + ~~ Prefer using nullish coalescing operator (\`??\`) instead of a logical or (\`||\`), as it is a safer operator. +while ((a ||= b)) {} +do {} while (a || b); + ~~ Prefer using nullish coalescing operator (\`??\`) instead of a logical or (\`||\`), as it is a safer operator. +for (let i = 0; a || b; i += 1) {} + ~~ Prefer using nullish coalescing operator (\`??\`) instead of a logical or (\`||\`), as it is a safer operator. +a || b ? true : false; + ~~ Prefer using nullish coalescing operator (\`??\`) instead of a logical or (\`||\`), as it is a safer operator. +" +`; + +exports[` 4`] = ` +"declare const a: string | null; +declare const b: string | null; + +if (a ?? b) { +} +if ((a ??= b)) { +} +while (a ?? b) {} +while ((a ??= b)) {} +do {} while (a ?? b); +for (let i = 0; a ?? b; i += 1) {} +a ?? b ? true : false; +" +`; + +exports[` 5`] = ` +"declare const a: string | null; +declare const b: string | null; +declare const c: string | null; +declare const d: string | null; + +a || (b && c); + ~~ Prefer using nullish coalescing operator (\`??\`) instead of a logical or (\`||\`), as it is a safer operator. +a ||= b && c; +(a && b) || c || d; + ~~ Prefer using nullish coalescing operator (\`??\`) instead of a logical or (\`||\`), as it is a safer operator. + ~~ Prefer using nullish coalescing operator (\`??\`) instead of a logical or (\`||\`), as it is a safer operator. +a || (b && c) || d; + ~~ Prefer using nullish coalescing operator (\`??\`) instead of a logical or (\`||\`), as it is a safer operator. + ~~ Prefer using nullish coalescing operator (\`??\`) instead of a logical or (\`||\`), as it is a safer operator. +a || (b && c && d); + ~~ Prefer using nullish coalescing operator (\`??\`) instead of a logical or (\`||\`), as it is a safer operator. +" +`; + +exports[` 6`] = ` +"declare const a: string | null; +declare const b: string | null; +declare const c: string | null; +declare const d: string | null; + +a ?? (b && c); +a ??= b && c; +(a && b) ?? c ?? d; +a ?? (b && c) ?? d; +a ?? (b && c && d); +" +`; + +exports[` 7`] = ` +"const foo: string | undefined = 'bar'; +foo || 'a string'; +" +`; + +exports[` 8`] = ` +"const foo: string | undefined = 'bar'; +foo ?? 'a string'; +" +`; diff --git a/packages/eslint-plugin/tests/docs-eslint-output-snapshots/prefer-promise-reject-errors.shot b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/prefer-promise-reject-errors.shot new file mode 100644 index 000000000000..bbd354eb2bd4 --- /dev/null +++ b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/prefer-promise-reject-errors.shot @@ -0,0 +1,39 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[` 1`] = ` +"Promise.reject('error'); +~~~~~~~~~~~~~~~~~~~~~~~ Expected the Promise rejection reason to be an Error. + +const err = new Error(); +Promise.reject('an ' + err); +~~~~~~~~~~~~~~~~~~~~~~~~~~~ Expected the Promise rejection reason to be an Error. + +new Promise((resolve, reject) => reject('error')); + ~~~~~~~~~~~~~~~ Expected the Promise rejection reason to be an Error. + +new Promise((resolve, reject) => { + const err = new Error(); + reject('an ' + err); + ~~~~~~~~~~~~~~~~~~~ Expected the Promise rejection reason to be an Error. +}); +" +`; + +exports[` 2`] = ` +"Promise.reject(new Error()); + +class CustomError extends Error { + // ... +} +Promise.reject(new CustomError()); + +new Promise((resolve, reject) => reject(new Error())); + +new Promise((resolve, reject) => { + class CustomError extends Error { + // ... + } + return reject(new CustomError()); +}); +" +`; diff --git a/packages/eslint-plugin/tests/docs-eslint-output-snapshots/prefer-readonly.shot b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/prefer-readonly.shot new file mode 100644 index 000000000000..ad2244806a78 --- /dev/null +++ b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/prefer-readonly.shot @@ -0,0 +1,67 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[` 1`] = ` +"class Container { + // These member variables could be marked as readonly + private neverModifiedMember = true; + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Member 'neverModifiedMember' is never reassigned; mark it as \`readonly\`. + private onlyModifiedInConstructor: number; + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Member 'onlyModifiedInConstructor' is never reassigned; mark it as \`readonly\`. + #neverModifiedPrivateField = 3; + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Member '#neverModifiedPrivateField' is never reassigned; mark it as \`readonly\`. + + public constructor( + onlyModifiedInConstructor: number, + // Private parameter properties can also be marked as readonly + private neverModifiedParameter: string, + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Member 'neverModifiedParameter: string' is never reassigned; mark it as \`readonly\`. + ) { + this.onlyModifiedInConstructor = onlyModifiedInConstructor; + } +} +" +`; + +exports[` 2`] = ` +"class Container { + // Public members might be modified externally + public publicMember: boolean; + + // Protected members might be modified by child classes + protected protectedMember: number; + + // This is modified later on by the class + private modifiedLater = 'unchanged'; + + public mutate() { + this.modifiedLater = 'mutated'; + } + + // This is modified later on by the class + #modifiedLaterPrivateField = 'unchanged'; + + public mutatePrivateField() { + this.#modifiedLaterPrivateField = 'mutated'; + } +} +" +`; + +exports[` 3`] = ` +"class Container { + private onClick = () => { + ~~ Member 'onClick' is never reassigned; mark it as \`readonly\`. + /* ... */ +~~~~~~~~~~~ + }; +~~ +} +" +`; + +exports[` 4`] = ` +"class Container { + private neverModifiedPrivate = 'unchanged'; +} +" +`; diff --git a/packages/eslint-plugin/tests/docs-eslint-output-snapshots/prefer-reduce-type-parameter.shot b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/prefer-reduce-type-parameter.shot new file mode 100644 index 000000000000..360c0c45649c --- /dev/null +++ b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/prefer-reduce-type-parameter.shot @@ -0,0 +1,29 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[` 1`] = ` +"[1, 2, 3].reduce((arr, num) => arr.concat(num * 2), [] as number[]); + ~~~~~~~~~~~~~~ Unnecessary cast: Array#reduce accepts a type parameter for the default value. + +['a', 'b'].reduce( + (accum, name) => ({ + ...accum, + [name]: true, + }), + {} as Record, + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Unnecessary cast: Array#reduce accepts a type parameter for the default value. +); +" +`; + +exports[` 2`] = ` +"[1, 2, 3].reduce((arr, num) => arr.concat(num * 2), []); + +['a', 'b'].reduce>( + (accum, name) => ({ + ...accum, + [name]: true, + }), + {}, +); +" +`; diff --git a/packages/eslint-plugin/tests/docs-eslint-output-snapshots/prefer-regexp-exec.shot b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/prefer-regexp-exec.shot new file mode 100644 index 000000000000..c956192cdaa5 --- /dev/null +++ b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/prefer-regexp-exec.shot @@ -0,0 +1,26 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[` 1`] = ` +"'something'.match(/thing/); + ~~~~~ Use the \`RegExp#exec()\` method instead. + +'some things are just things'.match(/thing/); + ~~~~~ Use the \`RegExp#exec()\` method instead. + +const text = 'something'; +const search = /thing/; +text.match(search); + ~~~~~ Use the \`RegExp#exec()\` method instead. +" +`; + +exports[` 2`] = ` +"/thing/.exec('something'); + +'some things are just things'.match(/thing/g); + +const text = 'something'; +const search = /thing/; +search.exec(text); +" +`; diff --git a/packages/eslint-plugin/tests/docs-eslint-output-snapshots/prefer-return-this-type.shot b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/prefer-return-this-type.shot new file mode 100644 index 000000000000..46e56d0da8eb --- /dev/null +++ b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/prefer-return-this-type.shot @@ -0,0 +1,43 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[` 1`] = ` +"class Foo { + f1(): Foo { + ~~~ Use \`this\` type instead. + return this; + } + f2 = (): Foo => { + ~~~ Use \`this\` type instead. + return this; + }; + f3(): Foo | undefined { + return Math.random() > 0.5 ? this : undefined; + } +} +" +`; + +exports[` 2`] = ` +"class Foo { + f1(): this { + return this; + } + f2() { + return this; + } + f3 = (): this => { + return this; + }; + f4 = () => { + return this; + }; +} + +class Base {} +class Derived extends Base { + f(): Base { + return this; + } +} +" +`; diff --git a/packages/eslint-plugin/tests/docs-eslint-output-snapshots/prefer-string-starts-ends-with.shot b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/prefer-string-starts-ends-with.shot new file mode 100644 index 000000000000..c497edb05137 --- /dev/null +++ b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/prefer-string-starts-ends-with.shot @@ -0,0 +1,49 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[` 1`] = ` +"declare const foo: string; + +// starts with +foo[0] === 'b'; +~~~~~~~~~~~~~~ Use 'String#startsWith' method instead. +foo.charAt(0) === 'b'; +~~~~~~~~~~~~~~~~~~~~~ Use 'String#startsWith' method instead. +foo.indexOf('bar') === 0; +~~~~~~~~~~~~~~~~~~~~~~~~ Use 'String#startsWith' method instead. +foo.slice(0, 3) === 'bar'; +~~~~~~~~~~~~~~~~~~~~~~~~~ Use 'String#startsWith' method instead. +foo.substring(0, 3) === 'bar'; +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Use 'String#startsWith' method instead. +foo.match(/^bar/) != null; +~~~~~~~~~~~~~~~~~ Use 'String#startsWith' method instead. +/^bar/.test(foo); +~~~~~~~~~~~~~~~~ Use 'String#startsWith' method instead. + +// ends with +foo[foo.length - 1] === 'b'; +~~~~~~~~~~~~~~~~~~~~~~~~~~~ Use the 'String#endsWith' method instead. +foo.charAt(foo.length - 1) === 'b'; +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Use the 'String#endsWith' method instead. +foo.lastIndexOf('bar') === foo.length - 3; +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Use the 'String#endsWith' method instead. +foo.slice(-3) === 'bar'; +~~~~~~~~~~~~~~~~~~~~~~~ Use the 'String#endsWith' method instead. +foo.substring(foo.length - 3) === 'bar'; +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Use the 'String#endsWith' method instead. +foo.match(/bar$/) != null; +~~~~~~~~~~~~~~~~~ Use the 'String#endsWith' method instead. +/bar$/.test(foo); +~~~~~~~~~~~~~~~~ Use the 'String#endsWith' method instead. +" +`; + +exports[` 2`] = ` +"declare const foo: string; + +// starts with +foo.startsWith('bar'); + +// ends with +foo.endsWith('bar'); +" +`; diff --git a/packages/eslint-plugin/tests/docs-eslint-output-snapshots/prefer-ts-expect-error.shot b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/prefer-ts-expect-error.shot new file mode 100644 index 000000000000..f1c79e437427 --- /dev/null +++ b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/prefer-ts-expect-error.shot @@ -0,0 +1,48 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[` 1`] = ` +"// @ts-ignore +~~~~~~~~~~~~~ Use "@ts-expect-error" to ensure an error is actually being suppressed. +const str: string = 1; + +/** +~~~~~~~~~~~~~~~~ Use "@ts-expect-error" to ensure an error is actually being suppressed. + * Explaining comment +~~~~~~~~~~~~~~~~~~~~~ + * +~~ + * @ts-ignore */ +~~~~~~~~~~~~~~~~ +const multiLine: number = 'value'; + +/** @ts-ignore */ +~~~~~~~~~~~~~~~~~ Use "@ts-expect-error" to ensure an error is actually being suppressed. +const block: string = 1; + +const isOptionEnabled = (key: string): boolean => { + // @ts-ignore: if key isn't in globalOptions it'll be undefined which is false + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Use "@ts-expect-error" to ensure an error is actually being suppressed. + return !!globalOptions[key]; +}; +" +`; + +exports[` 2`] = ` +"// @ts-expect-error +const str: string = 1; + +/** + * Explaining comment + * + * @ts-expect-error */ +const multiLine: number = 'value'; + +/** @ts-expect-error */ +const block: string = 1; + +const isOptionEnabled = (key: string): boolean => { + // @ts-expect-error: if key isn't in globalOptions it'll be undefined which is false + return !!globalOptions[key]; +}; +" +`; diff --git a/packages/eslint-plugin/tests/docs-eslint-output-snapshots/promise-function-async.shot b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/promise-function-async.shot new file mode 100644 index 000000000000..e0d560e73e5c --- /dev/null +++ b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/promise-function-async.shot @@ -0,0 +1,63 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[` 1`] = ` +"const arrowFunctionReturnsPromise = () => Promise.resolve('value'); + ~~ Functions that return promises must be async. + +function functionReturnsPromise() { +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Functions that return promises must be async. + return Promise.resolve('value'); +} + +function functionReturnsUnionWithPromiseImplicitly(p: boolean) { +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Functions that return promises must be async. + return p ? 'value' : Promise.resolve('value'); +} +" +`; + +exports[` 2`] = ` +"const arrowFunctionReturnsPromise = async () => Promise.resolve('value'); + +async function functionReturnsPromise() { + return Promise.resolve('value'); +} + +// An explicit return type that is not Promise means this function cannot be made async, so it is ignored by the rule +function functionReturnsUnionWithPromiseExplicitly( + p: boolean, +): string | Promise { + return p ? 'value' : Promise.resolve('value'); +} + +async function functionReturnsUnionWithPromiseImplicitly(p: boolean) { + return p ? 'value' : Promise.resolve('value'); +} +" +`; + +exports[` 3`] = ` +"const returnsAny = () => ({}) as any; + ~~ Functions that return promises must be async. +" +`; + +exports[` 4`] = ` +"const returnsAny = async () => ({}) as any; +" +`; + +exports[` 5`] = ` +"class Bluebird {} + +const returnsBluebird = () => new Bluebird(() => {}); + ~~ Functions that return promises must be async. +" +`; + +exports[` 6`] = ` +"class Bluebird {} + +const returnsBluebird = async () => new Bluebird(() => {}); +" +`; diff --git a/packages/eslint-plugin/tests/docs-eslint-output-snapshots/require-array-sort-compare.shot b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/require-array-sort-compare.shot new file mode 100644 index 000000000000..48791d14182a --- /dev/null +++ b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/require-array-sort-compare.shot @@ -0,0 +1,41 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[` 1`] = ` +"const array: any[]; +const stringArray: string[]; + +array.sort(); +~~~~~~~~~~~~ Require 'compare' argument. + +// String arrays should be sorted using \`String#localeCompare\`. +stringArray.sort(); +" +`; + +exports[` 2`] = ` +"const array: any[]; +const userDefinedType: { sort(): void }; + +array.sort((a, b) => a - b); +array.sort((a, b) => a.localeCompare(b)); + +userDefinedType.sort(); +" +`; + +exports[` 3`] = ` +"const one = 1; +const two = 2; +const three = 3; +[one, two, three].sort(); +~~~~~~~~~~~~~~~~~~~~~~~~ Require 'compare' argument. +" +`; + +exports[` 4`] = ` +"const one = '1'; +const two = '2'; +const three = '3'; +[one, two, three].sort(); +" +`; diff --git a/packages/eslint-plugin/tests/docs-eslint-output-snapshots/restrict-plus-operands.shot b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/restrict-plus-operands.shot new file mode 100644 index 000000000000..3f077141be67 --- /dev/null +++ b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/restrict-plus-operands.shot @@ -0,0 +1,108 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[` 1`] = ` +"let foo = 1n + 1; + ~~~~~~ Numeric '+' operations must either be both bigints or both numbers. Got \`bigint\` + \`number\`. +let fn = (a: string, b: never) => a + b; + ~ Invalid operand for a '+' operation. Operands must each be a number or string, allowing a string + any of: \`any\`, \`boolean\`, \`null\`, \`RegExp\`, \`undefined\`. Got \`never\`. +" +`; + +exports[` 2`] = ` +"let foo = 1n + 1n; +let fn = (a: string, b: string) => a + b; +" +`; + +exports[` 3`] = ` +"let fn = (a: number, b: []) => a + b; + ~ Invalid operand for a '+' operation. Operands must each be a number or string, allowing a string + any of: \`any\`, \`boolean\`, \`null\`, \`RegExp\`, \`undefined\`. Got \`[]\`. +let fn = (a: string, b: []) => a + b; + ~ Invalid operand for a '+' operation. Operands must each be a number or string, allowing a string + any of: \`any\`, \`boolean\`, \`null\`, \`RegExp\`, \`undefined\`. Got \`[]\`. +" +`; + +exports[` 4`] = ` +"let fn = (a: number, b: any) => a + b; +let fn = (a: string, b: any) => a + b; +" +`; + +exports[` 5`] = ` +"let fn = (a: number, b: unknown) => a + b; + ~ Invalid operand for a '+' operation. Operands must each be a number or string, allowing a string + any of: \`any\`, \`boolean\`, \`null\`, \`RegExp\`, \`undefined\`. Got \`unknown\`. +let fn = (a: string, b: unknown) => a + b; + ~ Invalid operand for a '+' operation. Operands must each be a number or string, allowing a string + any of: \`any\`, \`boolean\`, \`null\`, \`RegExp\`, \`undefined\`. Got \`unknown\`. +" +`; + +exports[` 6`] = ` +"let fn = (a: number, b: boolean) => a + b; +let fn = (a: string, b: boolean) => a + b; +" +`; + +exports[` 7`] = ` +"let fn = (a: number, b: unknown) => a + b; + ~ Invalid operand for a '+' operation. Operands must each be a number or string, allowing a string + any of: \`any\`, \`boolean\`, \`null\`, \`RegExp\`, \`undefined\`. Got \`unknown\`. +let fn = (a: number, b: never) => a + b; + ~ Invalid operand for a '+' operation. Operands must each be a number or string, allowing a string + any of: \`any\`, \`boolean\`, \`null\`, \`RegExp\`, \`undefined\`. Got \`never\`. +let fn = (a: string, b: unknown) => a + b; + ~ Invalid operand for a '+' operation. Operands must each be a number or string, allowing a string + any of: \`any\`, \`boolean\`, \`null\`, \`RegExp\`, \`undefined\`. Got \`unknown\`. +let fn = (a: string, b: never) => a + b; + ~ Invalid operand for a '+' operation. Operands must each be a number or string, allowing a string + any of: \`any\`, \`boolean\`, \`null\`, \`RegExp\`, \`undefined\`. Got \`never\`. +" +`; + +exports[` 8`] = ` +"let fn = (a: number, b: undefined) => a + b; +let fn = (a: number, b: null) => a + b; +let fn = (a: string, b: undefined) => a + b; +let fn = (a: string, b: null) => a + b; +" +`; + +exports[` 9`] = ` +"let fn = (a: number, b: unknown) => a + b; + ~ Invalid operand for a '+' operation. Operands must each be a number or string, allowing a string + any of: \`any\`, \`boolean\`, \`null\`, \`RegExp\`, \`undefined\`. Got \`unknown\`. +let fn = (a: number, b: never) => a + b; + ~ Invalid operand for a '+' operation. Operands must each be a number or string, allowing a string + any of: \`any\`, \`boolean\`, \`null\`, \`RegExp\`, \`undefined\`. Got \`never\`. +" +`; + +exports[` 10`] = ` +"let fn = (a: number, b: string) => a + b; +let fn = (a: number, b: number | string) => a + b; +" +`; + +exports[` 11`] = ` +"let fn = (a: number, b: RegExp) => a + b; + ~ Invalid operand for a '+' operation. Operands must each be a number or string, allowing a string + any of: \`any\`, \`boolean\`, \`null\`, \`RegExp\`, \`undefined\`. Got \`RegExp\`. +" +`; + +exports[` 12`] = ` +"let fn = (a: string, b: RegExp) => a + b; +" +`; + +exports[` 13`] = ` +"let foo: bigint = 0n; +foo += 1; +~~~~~~~~ Numeric '+' operations must either be both bigints or both numbers. Got \`bigint\` + \`number\`. + +let bar: number[] = [1]; +bar += 1; +~~~ Invalid operand for a '+' operation. Operands must each be a number or string, allowing a string + any of: \`any\`, \`boolean\`, \`null\`, \`RegExp\`, \`undefined\`. Got \`number[]\`. +" +`; + +exports[` 14`] = ` +"let foo: bigint = 0n; +foo += 1n; + +let bar: number = 1; +bar += 1; +" +`; diff --git a/packages/eslint-plugin/tests/docs-eslint-output-snapshots/restrict-template-expressions.shot b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/restrict-template-expressions.shot new file mode 100644 index 000000000000..8bb577a2efd3 --- /dev/null +++ b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/restrict-template-expressions.shot @@ -0,0 +1,67 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[` 1`] = ` +"const arg1 = [1, 2]; +const msg1 = \`arg1 = \${arg1}\`; + ~~~~ Invalid type "number[]" of template literal expression. + +const arg2 = { name: 'Foo' }; +const msg2 = \`arg2 = \${arg2 || null}\`; + ~~~~~~~~~~~~ Invalid type "{ name: string; }" of template literal expression. +" +`; + +exports[` 2`] = ` +"const arg = 'foo'; +const msg1 = \`arg = \${arg}\`; +const msg2 = \`arg = \${arg || 'default'}\`; + +const stringWithKindProp: string & { _kind?: 'MyString' } = 'foo'; +const msg3 = \`stringWithKindProp = \${stringWithKindProp}\`; +" +`; + +exports[` 3`] = ` +"const arg = 123; +const msg1 = \`arg = \${arg}\`; +const msg2 = \`arg = \${arg || 'zero'}\`; +" +`; + +exports[` 4`] = ` +"const arg = true; +const msg1 = \`arg = \${arg}\`; +const msg2 = \`arg = \${arg || 'not truthy'}\`; +" +`; + +exports[` 5`] = ` +"const user = JSON.parse('{ "name": "foo" }'); +const msg1 = \`arg = \${user.name}\`; +const msg2 = \`arg = \${user.name || 'the user with no name'}\`; +" +`; + +exports[` 6`] = ` +"const arg = condition ? 'ok' : null; +const msg1 = \`arg = \${arg}\`; +" +`; + +exports[` 7`] = ` +"const arg = new RegExp('foo'); +const msg1 = \`arg = \${arg}\`; +" +`; + +exports[` 8`] = ` +"const arg = /foo/; +const msg1 = \`arg = \${arg}\`; +" +`; + +exports[` 9`] = ` +"const arg = 'something'; +const msg1 = typeof arg === 'string' ? arg : \`arg = \${arg}\`; +" +`; diff --git a/packages/eslint-plugin/tests/docs-eslint-output-snapshots/return-await.shot b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/return-await.shot new file mode 100644 index 000000000000..33083b72d1a0 --- /dev/null +++ b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/return-await.shot @@ -0,0 +1,169 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[` 1`] = ` +"async function invalidInTryCatch1() { + try { + return Promise.resolve('try'); + ~~~~~~~~~~~~~~~~~~~~~~ Returning an awaited promise is required in this context. + } catch (e) {} +} + +async function invalidInTryCatch2() { + try { + throw new Error('error'); + } catch (e) { + return await Promise.resolve('catch'); + } +} + +async function invalidInTryCatch3() { + try { + throw new Error('error'); + } catch (e) { + return Promise.resolve('catch'); + ~~~~~~~~~~~~~~~~~~~~~~~~ Returning an awaited promise is required in this context. + } finally { + console.log('cleanup'); + } +} + +async function invalidInTryCatch4() { + try { + throw new Error('error'); + } catch (e) { + throw new Error('error2'); + } finally { + return await Promise.resolve('finally'); + } +} + +async function invalidInTryCatch5() { + return await Promise.resolve('try'); + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Returning an awaited promise is not allowed in this context. +} + +async function invalidInTryCatch6() { + return await 'value'; + ~~~~~~~~~~~~~ Returning an awaited value that is not a promise is not allowed. +} +" +`; + +exports[` 2`] = ` +"async function validInTryCatch1() { + try { + return await Promise.resolve('try'); + } catch (e) {} +} + +async function validInTryCatch2() { + try { + throw new Error('error'); + } catch (e) { + return Promise.resolve('catch'); + } +} + +async function validInTryCatch3() { + try { + throw new Error('error'); + } catch (e) { + return await Promise.resolve('catch'); + } finally { + console.log('cleanup'); + } +} + +async function validInTryCatch4() { + try { + throw new Error('error'); + } catch (e) { + throw new Error('error2'); + } finally { + return Promise.resolve('finally'); + } +} + +async function validInTryCatch5() { + return Promise.resolve('try'); +} + +async function validInTryCatch6() { + return 'value'; +} +" +`; + +exports[` 3`] = ` +"async function invalidAlways1() { + try { + return Promise.resolve('try'); + ~~~~~~~~~~~~~~~~~~~~~~ Returning an awaited promise is required in this context. + } catch (e) {} +} + +async function invalidAlways2() { + return Promise.resolve('try'); + ~~~~~~~~~~~~~~~~~~~~~~ Returning an awaited promise is required in this context. +} + +async function invalidAlways3() { + return await 'value'; + ~~~~~~~~~~~~~ Returning an awaited value that is not a promise is not allowed. +} +" +`; + +exports[` 4`] = ` +"async function validAlways1() { + try { + return await Promise.resolve('try'); + } catch (e) {} +} + +async function validAlways2() { + return await Promise.resolve('try'); +} + +async function validAlways3() { + return 'value'; +} +" +`; + +exports[` 5`] = ` +"async function invalidNever1() { + try { + return await Promise.resolve('try'); + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Returning an awaited promise is not allowed in this context. + } catch (e) {} +} + +async function invalidNever2() { + return await Promise.resolve('try'); + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Returning an awaited promise is not allowed in this context. +} + +async function invalidNever3() { + return await 'value'; + ~~~~~~~~~~~~~ Returning an awaited value that is not a promise is not allowed. +} +" +`; + +exports[` 6`] = ` +"async function validNever1() { + try { + return Promise.resolve('try'); + } catch (e) {} +} + +async function validNever2() { + return Promise.resolve('try'); +} + +async function validNever3() { + return 'value'; +} +" +`; diff --git a/packages/eslint-plugin/tests/docs-eslint-output-snapshots/sort-type-constituents.shot b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/sort-type-constituents.shot new file mode 100644 index 000000000000..5c4a569f85fa --- /dev/null +++ b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/sort-type-constituents.shot @@ -0,0 +1,113 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[` 1`] = ` +"type T1 = B | A; + ~~~~~ Union type T1 constituents must be sorted. + +type T2 = { b: string } & { a: string }; + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Intersection type T2 constituents must be sorted. + +type T3 = [1, 2, 4] & [1, 2, 3]; + ~~~~~~~~~~~~~~~~~~~~~ Intersection type T3 constituents must be sorted. + +type T4 = + | [1, 2, 4] + ~~~~~ Union type T4 constituents must be sorted. + | [1, 2, 3] +~~~~~~~~~~~ + | { b: string } +~~~~~~~~~~~~~~~ + | { a: string } +~~~~~~~~~~~~~~~ + | (() => void) +~~~~~~~~~~~~~~ + | (() => string) +~~~~~~~~~~~~~~~~ + | 'b' +~~~~~ + | 'a' +~~~~~ + | 'b' +~~~~~ + | 'a' +~~~~~ + | readonly string[] +~~~~~~~~~~~~~~~~~~~ + | readonly number[] +~~~~~~~~~~~~~~~~~~~ + | string[] +~~~~~~~~~~ + | number[] +~~~~~~~~~~ + | B +~~~ + | A +~~~ + | string +~~~~~~~~ + | any; +~~~~~~ +" +`; + +exports[` 2`] = ` +"type T1 = A | B; + +type T2 = { a: string } & { b: string }; + +type T3 = [1, 2, 3] & [1, 2, 4]; + +type T4 = + | A + | B + | number[] + | string[] + | any + | string + | readonly number[] + | readonly string[] + | 'a' + | 'a' + | 'b' + | 'b' + | (() => string) + | (() => void) + | { a: string } + | { b: string } + | [1, 2, 3] + | [1, 2, 4]; +" +`; + +exports[` 3`] = ` +"type ExampleIntersection = B & A; + ~~~~~ Intersection type ExampleIntersection constituents must be sorted. +" +`; + +exports[` 4`] = ` +"type ExampleIntersection = A & B; +" +`; + +exports[` 5`] = ` +"type ExampleUnion = B | A; + ~~~~~ Union type ExampleUnion constituents must be sorted. +" +`; + +exports[` 6`] = ` +"type ExampleUnion = A | B; +" +`; + +exports[` 7`] = ` +"type ExampleGroup = null | 123; + ~~~~~~~~~~ Union type ExampleGroup constituents must be sorted. +" +`; + +exports[` 8`] = ` +"type ExampleGroup = 123 | null; +" +`; diff --git a/packages/eslint-plugin/tests/docs-eslint-output-snapshots/space-before-blocks.shot b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/space-before-blocks.shot new file mode 100644 index 000000000000..48255ef86182 --- /dev/null +++ b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/space-before-blocks.shot @@ -0,0 +1,29 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[` 1`] = ` +"enum Breakpoint{ + ~ Missing space before opening brace. + Large, + Medium, +} + +interface State{ + ~ Missing space before opening brace. + currentBreakpoint: Breakpoint; +~~~~~~~~~~~~~~~~~ +} +~ +" +`; + +exports[` 2`] = ` +"enum Breakpoint { + Large, + Medium, +} + +interface State { + currentBreakpoint: Breakpoint; +} +" +`; diff --git a/packages/eslint-plugin/tests/docs-eslint-output-snapshots/strict-boolean-expressions.shot b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/strict-boolean-expressions.shot new file mode 100644 index 000000000000..d872874b65b6 --- /dev/null +++ b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/strict-boolean-expressions.shot @@ -0,0 +1,59 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[` 1`] = ` +"// nullable numbers are considered unsafe by default +let num: number | undefined = 0; +if (num) { + console.log('num is defined'); +} + +// nullable strings are considered unsafe by default +let str: string | null = null; +if (!str) { + ~~~ Unexpected nullish value in conditional. The condition is always false. + console.log('str is empty'); +} + +// nullable booleans are considered unsafe by default +function foo(bool?: boolean) { + if (bool) { + ~~~~ Unexpected nullable boolean value in conditional. Please handle the nullish case explicitly. + bar(); + } +} + +// \`any\`, unconstrained generics and unions of more than one primitive type are disallowed +const foo = (arg: T) => (arg ? 1 : 0); + ~~~ Unexpected any value in conditional. An explicit comparison or type cast is required. + +// always-truthy and always-falsy types are disallowed +let obj = {}; +while (obj) { + ~~~ Unexpected object value in conditional. The condition is always true. + obj = getObj(); +} +" +`; + +exports[` 2`] = ` +"// nullable values should be checked explicitly against null or undefined +let num: number | undefined = 0; +if (num != null) { + console.log('num is defined'); +} + +let str: string | null = null; +if (str != null && !str) { + console.log('str is empty'); +} + +function foo(bool?: boolean) { + if (bool ?? false) { + bar(); + } +} + +// \`any\` types should be cast to boolean explicitly +const foo = (arg: any) => (Boolean(arg) ? 1 : 0); +" +`; diff --git a/packages/eslint-plugin/tests/docs-eslint-output-snapshots/switch-exhaustiveness-check.shot b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/switch-exhaustiveness-check.shot new file mode 100644 index 000000000000..e46dc7dbe813 --- /dev/null +++ b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/switch-exhaustiveness-check.shot @@ -0,0 +1,162 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[` 1`] = ` +"const value: number = Math.floor(Math.random() * 3); + +switch (value) { + ~~~~~ Switch is not exhaustive. Cases not matched: default + case 0: + return 0; + case 1: + return 1; +} +" +`; + +exports[` 2`] = ` +"type Day = + | 'Monday' + | 'Tuesday' + | 'Wednesday' + | 'Thursday' + | 'Friday' + | 'Saturday' + | 'Sunday'; + +declare const day: Day; +let result = 0; + +switch (day) { + ~~~ Switch is not exhaustive. Cases not matched: "Tuesday" | "Wednesday" | "Thursday" | "Friday" | "Saturday" | "Sunday" + case 'Monday': + result = 1; + break; +} +" +`; + +exports[` 3`] = ` +"type Day = + | 'Monday' + | 'Tuesday' + | 'Wednesday' + | 'Thursday' + | 'Friday' + | 'Saturday' + | 'Sunday'; + +declare const day: Day; +let result = 0; + +switch (day) { + case 'Monday': + result = 1; + break; + case 'Tuesday': + result = 2; + break; + case 'Wednesday': + result = 3; + break; + case 'Thursday': + result = 4; + break; + case 'Friday': + result = 5; + break; + case 'Saturday': + result = 6; + break; + case 'Sunday': + result = 7; + break; +} +" +`; + +exports[` 4`] = ` +"type Day = + | 'Monday' + | 'Tuesday' + | 'Wednesday' + | 'Thursday' + | 'Friday' + | 'Saturday' + | 'Sunday'; + +declare const day: Day; +let result = 0; + +switch (day) { + case 'Monday': + result = 1; + break; + default: + result = 42; +} +" +`; + +exports[` 5`] = ` +"enum Fruit { + Apple, + Banana, + Cherry, +} + +declare const fruit: Fruit; + +switch (fruit) { + ~~~~~ Switch is not exhaustive. Cases not matched: Fruit.Banana | Fruit.Cherry + case Fruit.Apple: + console.log('an apple'); + break; +} +" +`; + +exports[` 6`] = ` +"enum Fruit { + Apple, + Banana, + Cherry, +} + +declare const fruit: Fruit; + +switch (fruit) { + case Fruit.Apple: + console.log('an apple'); + break; + + case Fruit.Banana: + console.log('a banana'); + break; + + case Fruit.Cherry: + console.log('a cherry'); + break; +} +" +`; + +exports[` 7`] = ` +"enum Fruit { + Apple, + Banana, + Cherry, +} + +declare const fruit: Fruit; + +switch (fruit) { + case Fruit.Apple: + console.log('an apple'); + break; + + default: + console.log('a fruit'); + break; +} +" +`; diff --git a/packages/eslint-plugin/tests/docs-eslint-output-snapshots/triple-slash-reference.shot b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/triple-slash-reference.shot new file mode 100644 index 000000000000..2e848e1bdea7 --- /dev/null +++ b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/triple-slash-reference.shot @@ -0,0 +1,55 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[` 1`] = ` +"/// +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Do not use a triple slash reference for code, use \`import\` style instead. + +globalThis.value; +" +`; + +exports[` 2`] = ` +"import { value } from 'code'; +" +`; + +exports[` 3`] = ` +"/// +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Do not use a triple slash reference for code, use \`import\` style instead. + +globalThis.value; +" +`; + +exports[` 4`] = ` +"import { value } from 'code'; +" +`; + +exports[` 5`] = ` +"/// +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Do not use a triple slash reference for code, use \`import\` style instead. + +globalThis.value; +" +`; + +exports[` 6`] = ` +"import { value } from 'code'; +" +`; + +exports[` 7`] = ` +"/// +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Do not use a triple slash reference for code, use \`import\` style instead. + +import { valueA } from 'code'; + +globalThis.valueB; +" +`; + +exports[` 8`] = ` +"import { valueA, valueB } from 'code'; +" +`; diff --git a/packages/eslint-plugin/tests/docs-eslint-output-snapshots/type-annotation-spacing.shot b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/type-annotation-spacing.shot new file mode 100644 index 000000000000..ed7fb0137d23 --- /dev/null +++ b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/type-annotation-spacing.shot @@ -0,0 +1,283 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[` 1`] = ` +"let foo:string = "bar"; + ~ Expected a space after the ':'. +let foo :string = "bar"; + ~ Expected a space after the ':'. + ~ Unexpected space before the ':'. +let foo : string = "bar"; + ~ Unexpected space before the ':'. + +function foo():string {} + ~ Expected a space after the ':'. +function foo() :string {} + ~ Expected a space after the ':'. + ~ Unexpected space before the ':'. +function foo() : string {} + ~ Unexpected space before the ':'. + +class Foo { + name:string; + ~ Expected a space after the ':'. +} + +class Foo { + name :string; + ~ Expected a space after the ':'. + ~ Unexpected space before the ':'. +} + +class Foo { + name : string; + ~ Unexpected space before the ':'. +} + +type Foo = ()=>{}; + ~~ Expected a space after the '=>'. + ~~ Expected a space before the '=>'. +type Foo = () =>{}; + ~~ Expected a space after the '=>'. +type Foo = ()=> {}; + ~~ Expected a space before the '=>'. +" +`; + +exports[` 2`] = ` +"let foo: string = "bar"; + +function foo(): string {} + +class Foo { + name: string; +} + +type Foo = () => {}; +" +`; + +exports[` 3`] = ` +"let foo:string = "bar"; + ~ Expected a space after the ':'. +let foo :string = "bar"; + ~ Expected a space after the ':'. + ~ Unexpected space before the ':'. +let foo : string = "bar"; + ~ Unexpected space before the ':'. + +function foo():string {} + ~ Expected a space after the ':'. +function foo() :string {} + ~ Expected a space after the ':'. + ~ Unexpected space before the ':'. +function foo() : string {} + ~ Unexpected space before the ':'. + +class Foo { + name:string; + ~ Expected a space after the ':'. +} + +class Foo { + name :string; + ~ Expected a space after the ':'. + ~ Unexpected space before the ':'. +} + +class Foo { + name : string; + ~ Unexpected space before the ':'. +} + +type Foo = ()=>{}; + ~~ Expected a space after the '=>'. +type Foo = () =>{}; + ~~ Expected a space after the '=>'. + ~~ Unexpected space before the '=>'. +type Foo = () => {}; + ~~ Unexpected space before the '=>'. +" +`; + +exports[` 4`] = ` +"let foo: string = "bar"; + +function foo(): string {} + +class Foo { + name: string; +} + +type Foo = ()=> {}; +" +`; + +exports[` 5`] = ` +"let foo: string = "bar"; + ~ Expected a space before the ':'. +let foo:string = "bar"; + ~ Expected a space after the ':'. + ~ Expected a space before the ':'. +let foo :string = "bar"; + ~ Expected a space after the ':'. + +function foo(): string {} + ~ Expected a space before the ':'. +function foo():string {} + ~ Expected a space after the ':'. + ~ Expected a space before the ':'. +function foo() :string {} + ~ Expected a space after the ':'. + +class Foo { + name: string; + ~ Expected a space before the ':'. +} + +class Foo { + name:string; + ~ Expected a space after the ':'. + ~ Expected a space before the ':'. +} + +class Foo { + name :string; + ~ Expected a space after the ':'. +} + +type Foo = ()=>{}; + ~~ Expected a space after the '=>'. + ~~ Expected a space before the '=>'. +type Foo = () =>{}; + ~~ Expected a space after the '=>'. +type Foo = ()=> {}; + ~~ Expected a space before the '=>'. +" +`; + +exports[` 6`] = ` +"let foo : string = "bar"; + +function foo() : string {} + +class Foo { + name : string; +} + +type Foo = () => {}; +" +`; + +exports[` 7`] = ` +"let foo: string = "bar"; + ~ Expected a space before the ':'. +let foo:string = "bar"; + ~ Expected a space after the ':'. + ~ Expected a space before the ':'. +let foo :string = "bar"; + ~ Expected a space after the ':'. + +function foo(): string {} + ~ Expected a space before the ':'. +function foo():string {} + ~ Expected a space after the ':'. + ~ Expected a space before the ':'. +function foo() :string {} + ~ Expected a space after the ':'. + +class Foo { + name: string; + ~ Expected a space before the ':'. +} + +class Foo { + name:string; + ~ Expected a space after the ':'. + ~ Expected a space before the ':'. +} + +class Foo { + name :string; + ~ Expected a space after the ':'. +} + +type Foo = () =>{}; + ~~ Unexpected space before the '=>'. +type Foo = ()=> {}; + ~~ Unexpected space after the '=>'. +type Foo = () => {}; + ~~ Unexpected space after the '=>'. + ~~ Unexpected space before the '=>'. +" +`; + +exports[` 8`] = ` +"let foo : string = "bar"; + +function foo() : string {} + +class Foo { + name : string; +} + +type Foo = { + name : (name : string)=>string; +} + +type Foo = ()=>{}; +" +`; + +exports[` 9`] = ` +"let foo: string = "bar"; + ~ Unexpected space after the ':'. +let foo : string = "bar"; + ~ Unexpected space after the ':'. + ~ Unexpected space before the ':'. +let foo :string = "bar"; + ~ Unexpected space before the ':'. + +function foo(): string {} + ~ Unexpected space after the ':'. +function foo():string {} +function foo() :string {} + ~ Unexpected space before the ':'. + +class Foo { + name: string; + ~ Unexpected space after the ':'. +} + +class Foo { + name : string; + ~ Unexpected space after the ':'. + ~ Unexpected space before the ':'. +} + +class Foo { + name :string; + ~ Unexpected space before the ':'. +} + +type Foo = ()=>{}; + ~~ Expected a space after the '=>'. + ~~ Expected a space before the '=>'. +type Foo = () =>{}; + ~~ Expected a space after the '=>'. +type Foo = ()=> {}; + ~~ Expected a space before the '=>'. +" +`; + +exports[` 10`] = ` +"let foo:string = "bar"; + +function foo():string {} + +class Foo { + name:string; +} + +type Foo = () => {}; +" +`; diff --git a/packages/eslint-plugin/tests/docs-eslint-output-snapshots/typedef.shot b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/typedef.shot new file mode 100644 index 000000000000..c5449289bf6e --- /dev/null +++ b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/typedef.shot @@ -0,0 +1,191 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[` 1`] = ` +"const [a] = [1]; + ~~~ Expected a type annotation. +const [b, c] = [1, 2]; + ~~~~~~ Expected a type annotation. +" +`; + +exports[` 2`] = ` +"const [a]: number[] = [1]; +const [b]: [number] = [2]; +const [c, d]: [boolean, string] = [true, 'text']; + +for (const [key, val] of new Map([['key', 1]])) { +} +" +`; + +exports[` 3`] = ` +"const logsSize = size => console.log(size); + ~~~~ Expected size to have a type annotation. + +['hello', 'world'].map(text => text.length); + ~~~~ Expected text to have a type annotation. + +const mapper = { + map: text => text + '...', + ~~~~ Expected text to have a type annotation. +}; +" +`; + +exports[` 4`] = ` +"const logsSize = (size: number) => console.log(size); + +['hello', 'world'].map((text: string) => text.length); + +const mapper = { + map: (text: string) => text + '...', +}; +" +`; + +exports[` 5`] = ` +"class ContainsText { + delayedText; + ~~~~~~~~~~~~ Expected delayedText to have a type annotation. + immediateTextImplicit = 'text'; + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Expected immediateTextImplicit to have a type annotation. +} +" +`; + +exports[` 6`] = ` +"class ContainsText { + delayedText: string; + immediateTextImplicit: string = 'text'; +} +" +`; + +exports[` 7`] = ` +"const { length } = 'text'; + ~~~~~~~~~~ Expected a type annotation. +const [b, c] = Math.random() ? [1, 2] : [3, 4]; +" +`; + +exports[` 8`] = ` +"const { length }: { length: number } = 'text'; +const [b, c]: [number, number] = Math.random() ? [1, 2] : [3, 4]; + +for (const { key, val } of [{ key: 'key', val: 1 }]) { +} +" +`; + +exports[` 9`] = ` +"function logsSize(size): void { + ~~~~ Expected size to have a type annotation. + console.log(size); +} + +const doublesSize = function (size): number { + ~~~~ Expected size to have a type annotation. + return size * 2; +}; + +const divider = { + curriesSize(size): number { + ~~~~ Expected size to have a type annotation. + return size; + }, + dividesSize: function (size): number { + ~~~~ Expected size to have a type annotation. + return size / 2; + }, +}; + +class Logger { + log(text): boolean { + ~~~~ Expected text to have a type annotation. + console.log('>', text); + return true; + } +} +" +`; + +exports[` 10`] = ` +"function logsSize(size: number): void { + console.log(size); +} + +const doublesSize = function (size: number): number { + return size * 2; +}; + +const divider = { + curriesSize(size: number): number { + return size; + }, + dividesSize: function (size: number): number { + return size / 2; + }, +}; + +class Logger { + log(text: boolean): boolean { + console.log('>', text); + return true; + } +} +" +`; + +exports[` 11`] = ` +"type Members = { + member; + ~~~~~~~ Expected member to have a type annotation. + otherMember; + ~~~~~~~~~~~~ Expected otherMember to have a type annotation. +}; +" +`; + +exports[` 12`] = ` +"type Members = { + member: boolean; + otherMember: string; +}; +" +`; + +exports[` 13`] = ` +"const text = 'text'; + ~~~~~~~~~~~~~ Expected text to have a type annotation. +let initialText = 'text'; + ~~~~~~~~~~~~~~~~~~~~ Expected initialText to have a type annotation. +let delayedText; + ~~~~~~~~~~~ Expected delayedText to have a type annotation. +" +`; + +exports[` 14`] = ` +"const text: string = 'text'; +let initialText: string = 'text'; +let delayedText: string; +" +`; + +exports[` 15`] = ` +"const text = 'text'; + ~~~~~~~~~~~~~ Expected text to have a type annotation. +" +`; + +exports[` 16`] = ` +"const a = (): void => {}; +const b = function (): void {}; +const c: () => void = (): void => {}; + +class Foo { + a = (): void => {}; + b = function (): void {}; + c: () => void = (): void => {}; +} +" +`; diff --git a/packages/eslint-plugin/tests/docs-eslint-output-snapshots/unbound-method.shot b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/unbound-method.shot new file mode 100644 index 000000000000..b869f055121e --- /dev/null +++ b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/unbound-method.shot @@ -0,0 +1,76 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[` 1`] = ` +"class MyClass { + public log(): void { + console.log(this); + } +} + +const instance = new MyClass(); + +// This logs the global scope (\`window\`/\`global\`), not the class instance +const myLog = instance.log; + ~~~~~~~~~~~~ Avoid referencing unbound methods which may cause unintentional scoping of \`this\`. + If your function does not access \`this\`, you can annotate it with \`this: void\`, or consider using an arrow function instead. +myLog(); + +// This log might later be called with an incorrect scope +const { log } = instance; + ~~~ Avoid referencing unbound methods which may cause unintentional scoping of \`this\`. + If your function does not access \`this\`, you can annotate it with \`this: void\`, or consider using an arrow function instead. + +// arith.double may refer to \`this\` internally +const arith = { + double(x: number): number { + return x * 2; + }, +}; +const { double } = arith; + ~~~~~~ Avoid referencing unbound methods which may cause unintentional scoping of \`this\`. + If your function does not access \`this\`, you can annotate it with \`this: void\`, or consider using an arrow function instead. +" +`; + +exports[` 2`] = ` +"class MyClass { + public logUnbound(): void { + console.log(this); + } + + public logBound = () => console.log(this); +} + +const instance = new MyClass(); + +// logBound will always be bound with the correct scope +const { logBound } = instance; +logBound(); + +// .bind and lambdas will also add a correct scope +const dotBindLog = instance.logBound.bind(instance); +const innerLog = () => instance.logBound(); + +// arith.double explicitly declares that it does not refer to \`this\` internally +const arith = { + double(this: void, x: number): number { + return x * 2; + }, +}; +const { double } = arith; +" +`; + +exports[` 3`] = ` +"class OtherClass { + static log() { + console.log(OtherClass); + } +} + +// With \`ignoreStatic\`, statics are assumed to not rely on a particular scope +const { log } = OtherClass; + +log(); +" +`; diff --git a/packages/eslint-plugin/tests/docs-eslint-output-snapshots/unified-signatures.shot b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/unified-signatures.shot new file mode 100644 index 000000000000..cdfe0c6d7a76 --- /dev/null +++ b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/unified-signatures.shot @@ -0,0 +1,46 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[` 1`] = ` +"function x(x: number): void; +function x(x: string): void; + ~~~~~~~~~ These overloads can be combined into one signature taking \`number | string\`. +" +`; + +exports[` 2`] = ` +"function y(): void; +function y(...x: number[]): void; + ~~~~~~~~~~~~~~ These overloads can be combined into one signature with a rest parameter. +" +`; + +exports[` 3`] = ` +"function x(x: number | string): void; +" +`; + +exports[` 4`] = ` +"function y(...x: number[]): void; +" +`; + +exports[` 5`] = ` +"// This rule won't check overload signatures with different rest parameter types. +// See https://github.com/microsoft/TypeScript/issues/5077 +function f(...a: number[]): void; +function f(...a: string[]): void; +" +`; + +exports[` 6`] = ` +"function f(a: number): void; +function f(a: string): void; + ~~~~~~~~~ These overloads can be combined into one signature taking \`number | string\`. +" +`; + +exports[` 7`] = ` +"function f(a: number): void; +function f(b: string): void; +" +`; diff --git a/packages/eslint-plugin/tests/docs.test.ts b/packages/eslint-plugin/tests/docs.test.ts index 9d99ca159103..7ae2c1c2aec0 100644 --- a/packages/eslint-plugin/tests/docs.test.ts +++ b/packages/eslint-plugin/tests/docs.test.ts @@ -1,10 +1,15 @@ +import 'jest-specific-snapshot'; + import { parseForESLint } from '@typescript-eslint/parser'; +import * as tseslintParser from '@typescript-eslint/parser'; +import { Linter } from '@typescript-eslint/utils/ts-eslint'; import fs from 'fs'; import { marked } from 'marked'; import path from 'path'; import { titleCase } from 'title-case'; import rules from '../src/rules'; +import { getFixturesRootDir } from './RuleTester'; const docsRoot = path.resolve(__dirname, '../docs/rules'); const rulesData = Object.entries(rules); @@ -46,6 +51,51 @@ function tokenIsH2( ); } +function renderLintResults(code: string, errors: Linter.LintMessage[]): string { + const output: string[] = []; + const lines = code.split('\n'); + + for (let i = 0; i < lines.length; i++) { + const line = lines[i]; + output.push(line); + + for (const error of errors) { + const startLine = error.line - 1; + const endLine = + error.endLine === undefined ? startLine : error.endLine - 1; + const startColumn = error.column - 1; + const endColumn = + error.endColumn === undefined ? startColumn : error.endColumn - 1; + if (i < startLine || i > endLine) { + continue; + } + if (i === startLine) { + const squiggle = '~'.repeat(Math.max(1, endColumn - startColumn)); + const squiggleWithIndent = ' '.repeat(startColumn) + squiggle + ' '; + const errorMessageIndent = ' '.repeat(squiggleWithIndent.length); + output.push( + squiggleWithIndent + + error.message.split('\n').join('\n' + errorMessageIndent), + ); + } else { + const squiggle = '~'.repeat(Math.max(1, line.length - startColumn)); + output.push(squiggle); + } + } + } + + return output.join('\n').trim() + '\n'; +} + +const linter = new Linter(); +linter.defineParser('@typescript-eslint/parser', tseslintParser); + +const eslintOutputSnapshotFolder = path.resolve( + __dirname, + 'docs-eslint-output-snapshots', +); +fs.mkdirSync(eslintOutputSnapshotFolder, { recursive: true }); + describe('Validating rule docs', () => { const ignoredFiles = new Set([ 'README.md', @@ -71,6 +121,9 @@ describe('Validating rule docs', () => { }); for (const [ruleName, rule] of rulesData) { + if (ruleName !== 'consistent-type-assertions') { + // continue; + } const { description } = rule.meta.docs!; describe(`${ruleName}.md`, () => { @@ -207,10 +260,141 @@ describe('Validating rule docs', () => { } } }); + + describe('code examples ESLint output', () => { + if ( + [ + 'prefer-readonly-parameter-types', // https://github.com/typescript-eslint/typescript-eslint/pull/8461 + 'prefer-optional-chain', // https://github.com/typescript-eslint/typescript-eslint/issues/8487 + ].includes(ruleName) + ) { + return; + } + + // TypeScript can't infer type arguments unless we provide them explicitly + linter.defineRule< + keyof (typeof rule)['meta']['messages'], + (typeof rule)['defaultOptions'] + >(ruleName, rule); + + type Context = + | { + type: 'outside-the-tabs'; + } + | { + type: 'entered-tabs'; + } + | { + type: 'under-tab-heading'; + headingsDepth: number; + sectionType: 'incorrect' | 'correct' | 'unknown'; + }; + let currentContext: Context = { + type: 'outside-the-tabs', + }; + + for (const token of tokens) { + if (token.type === 'html') { + const isOpeningTabsComment = /^$/.test( + token.text.trim(), + ); + const isClosingTabsComment = /^$/.test( + token.text.trim(), + ); + + if (isOpeningTabsComment) { + currentContext = { type: 'entered-tabs' }; + } else if (isClosingTabsComment) { + currentContext = { type: 'outside-the-tabs' }; + } + } else if (token.type === 'heading') { + if ( + currentContext.type === 'under-tab-heading' && + token.depth < currentContext.headingsDepth + ) { + currentContext = { type: 'outside-the-tabs' }; + } else if ( + currentContext.type === 'entered-tabs' || + (currentContext.type === 'under-tab-heading' && + token.depth === currentContext.headingsDepth) + ) { + const heading = token.text.trim(); + currentContext = { + type: 'under-tab-heading', + headingsDepth: token.depth, + sectionType: heading.startsWith('❌ Incorrect') + ? 'incorrect' + : heading.startsWith('✅ Correct') + ? 'correct' + : 'unknown', + }; + } + } + + if ( + token.type !== 'code' || + (currentContext.type !== 'under-tab-heading' && + !token.lang?.includes('showPlaygroundButton')) + ) { + continue; + } + + const lang = token.lang?.trim(); + if (!lang || !/^tsx?\b/i.test(lang)) { + continue; + } + + const optionRegex = /option='(?