diff --git a/packages/eslint-plugin/docs/rules/ban-ts-comment.mdx b/packages/eslint-plugin/docs/rules/ban-ts-comment.mdx index 91d9a9051b8a..ca36964e28cb 100644 --- a/packages/eslint-plugin/docs/rules/ban-ts-comment.mdx +++ b/packages/eslint-plugin/docs/rules/ban-ts-comment.mdx @@ -41,9 +41,7 @@ if (false) { console.log('hello'); } if (false) { - /* - @ts-ignore: Unreachable code error - */ + /* @ts-ignore: Unreachable code error */ console.log('hello'); } ``` @@ -90,9 +88,7 @@ if (false) { console.log('hello'); } if (false) { - /* - @ts-expect-error: Unreachable code error - */ + /* @ts-expect-error: Unreachable code error */ console.log('hello'); } ``` diff --git a/packages/eslint-plugin/docs/rules/class-methods-use-this.mdx b/packages/eslint-plugin/docs/rules/class-methods-use-this.mdx index 3b4cb7cf138d..8e580a8b24a7 100644 --- a/packages/eslint-plugin/docs/rules/class-methods-use-this.mdx +++ b/packages/eslint-plugin/docs/rules/class-methods-use-this.mdx @@ -70,7 +70,7 @@ Example of incorrect code when `ignoreClassesThatImplementAnInterface` is set to -```ts +```ts option='{ "ignoreClassesThatImplementAnInterface": "public-fields" }' class X implements Y { method() {} property = () => {}; @@ -86,7 +86,7 @@ class X implements Y { -```ts +```ts option='{ "ignoreClassesThatImplementAnInterface": "public-fields" }' class X implements Y { method() {} property = () => {}; diff --git a/packages/eslint-plugin/docs/rules/consistent-type-exports.mdx b/packages/eslint-plugin/docs/rules/consistent-type-exports.mdx index be1ab45c2b7e..7c699d1096aa 100644 --- a/packages/eslint-plugin/docs/rules/consistent-type-exports.mdx +++ b/packages/eslint-plugin/docs/rules/consistent-type-exports.mdx @@ -85,24 +85,6 @@ export type { T }; export { x }; ``` - - - -```ts option='{ "fixMixedExportsWithInlineTypeSpecifier": true }' -export { Button } from 'some-library'; -export type { ButtonProps } from 'some-library'; -``` - - - - -```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.mdx b/packages/eslint-plugin/docs/rules/default-param-last.mdx index bc50cad62136..38527abf7681 100644 --- a/packages/eslint-plugin/docs/rules/default-param-last.mdx +++ b/packages/eslint-plugin/docs/rules/default-param-last.mdx @@ -16,8 +16,6 @@ It adds support for optional parameters. ```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) {} @@ -39,8 +37,6 @@ class Foo { ```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.mdx b/packages/eslint-plugin/docs/rules/explicit-module-boundary-types.mdx index e73e12c97d85..7a19ab87c726 100644 --- a/packages/eslint-plugin/docs/rules/explicit-module-boundary-types.mdx +++ b/packages/eslint-plugin/docs/rules/explicit-module-boundary-types.mdx @@ -97,20 +97,20 @@ 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. - + ```ts option='{ "allowArgumentsExplicitlyTypedAsAny": false }' export const func = (value: any): number => value + 1; ``` - + -```ts option='{ "allowArgumentsExplicitlyTypedAsAny": false }' -export const func = (value: number): number => value + 1; +```ts option='{ "allowArgumentsExplicitlyTypedAsAny": true }' +export const func = (value: any): number => value + 1; ``` @@ -118,12 +118,12 @@ export const func = (value: number): 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. - + -```ts option='{ "allowArgumentsExplicitlyTypedAsAny": false }' +```ts option='{ "allowDirectConstAssertionInArrowFunctions": false }' export const func = (value: number) => ({ type: 'X', value }); export const foo = () => ({ bar: true, @@ -132,9 +132,9 @@ export const bar = () => 1; ``` - + -```ts option='{ "allowArgumentsExplicitlyTypedAsAny": false }' +```ts option='{ "allowDirectConstAssertionInArrowFunctions": true }' export const func = (value: number) => ({ type: 'X', value }) as const; export const foo = () => ({ @@ -163,10 +163,10 @@ 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, which is immediately returning another function expression. - + ```ts option='{ "allowHigherOrderFunctions": false }' export const arrowFn = () => () => {}; @@ -181,9 +181,9 @@ export function foo(outer: string) { ``` - + -```ts option='{ "allowHigherOrderFunctions": false }' +```ts option='{ "allowHigherOrderFunctions": true }' export const arrowFn = () => (): void => {}; export function fn() { @@ -200,10 +200,10 @@ 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. - + ```ts option='{ "allowTypedFunctionExpressions": false }' export let arrowFn = () => 'test'; @@ -220,9 +220,9 @@ export const foo = bar => {}; ``` - + -```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.mdx b/packages/eslint-plugin/docs/rules/member-ordering.mdx index b32c2e03c24a..82f8f84f904b 100644 --- a/packages/eslint-plugin/docs/rules/member-ordering.mdx +++ b/packages/eslint-plugin/docs/rules/member-ordering.mdx @@ -1011,9 +1011,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; } ``` @@ -1022,12 +1022,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.mdx b/packages/eslint-plugin/docs/rules/no-extraneous-class.mdx index a457ccf962b0..f368d5420e8f 100644 --- a/packages/eslint-plugin/docs/rules/no-extraneous-class.mdx +++ b/packages/eslint-plugin/docs/rules/no-extraneous-class.mdx @@ -293,7 +293,7 @@ class NotEmptyClass { ### `allowWithDecorator` -The `allowWithDecorator` option adds an exemption for classes that contain a member decorated with a `@` decorator. +The `allowWithDecorator` option adds an exemption for classes decorated with a `@` decorator. @@ -308,8 +308,8 @@ class Constants { ```ts option='{ "allowWithDecorator": true }' +@logOnRead() class Constants { - @logOnRead() static readonly version = 42; } ``` diff --git a/packages/eslint-plugin/docs/rules/no-floating-promises.mdx b/packages/eslint-plugin/docs/rules/no-floating-promises.mdx index 939eccae62f7..6b42594dae63 100644 --- a/packages/eslint-plugin/docs/rules/no-floating-promises.mdx +++ b/packages/eslint-plugin/docs/rules/no-floating-promises.mdx @@ -104,7 +104,7 @@ This allows you to skip checking of async IIFEs (Immediately Invoked function Ex Examples of **correct** code for this rule with `{ ignoreIIFE: true }`: - +{/* prettier-ignore */} ```ts option='{ "ignoreIIFE": true }' showPlaygroundButton await (async function () { await res(1); diff --git a/packages/eslint-plugin/docs/rules/no-implied-eval.mdx b/packages/eslint-plugin/docs/rules/no-implied-eval.mdx index 8e7050d200b4..5019008cb561 100644 --- a/packages/eslint-plugin/docs/rules/no-implied-eval.mdx +++ b/packages/eslint-plugin/docs/rules/no-implied-eval.mdx @@ -36,8 +36,6 @@ This rule aims to eliminate implied `eval()` through the use of `new Function()` ```ts -/* eslint @typescript-eslint/no-implied-eval: "error" */ - setTimeout('alert(`Hi!`);', 100); setInterval('alert(`Hi!`);', 100); @@ -65,8 +63,6 @@ const fn = new Function('a', 'b', 'return a + b'); ```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.mdx b/packages/eslint-plugin/docs/rules/no-meaningless-void-operator.mdx index 9df265bc987c..905c70618710 100644 --- a/packages/eslint-plugin/docs/rules/no-meaningless-void-operator.mdx +++ b/packages/eslint-plugin/docs/rules/no-meaningless-void-operator.mdx @@ -44,7 +44,7 @@ function bar(x: number) { void x; // discarding a number return 2; } -void bar(); // discarding a number +void bar(1); // discarding a number ``` diff --git a/packages/eslint-plugin/docs/rules/no-require-imports.mdx b/packages/eslint-plugin/docs/rules/no-require-imports.mdx index b5cc06dbd432..5af39f233cf5 100644 --- a/packages/eslint-plugin/docs/rules/no-require-imports.mdx +++ b/packages/eslint-plugin/docs/rules/no-require-imports.mdx @@ -45,14 +45,14 @@ With `{allow: ['/package\\.json$']}`: -```ts +```ts option='{ "allow": ["/package.json$"] }' console.log(require('../data.json').version); ``` -```ts +```ts option='{ "allow": ["/package.json$"] }' console.log(require('../package.json').version); ``` diff --git a/packages/eslint-plugin/docs/rules/no-unnecessary-type-assertion.mdx b/packages/eslint-plugin/docs/rules/no-unnecessary-type-assertion.mdx index 3182474d9b6a..4c34f32cae8f 100644 --- a/packages/eslint-plugin/docs/rules/no-unnecessary-type-assertion.mdx +++ b/packages/eslint-plugin/docs/rules/no-unnecessary-type-assertion.mdx @@ -24,17 +24,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.mdx b/packages/eslint-plugin/docs/rules/no-var-requires.mdx index 725cb0f7a835..e71c2e17c712 100644 --- a/packages/eslint-plugin/docs/rules/no-var-requires.mdx +++ b/packages/eslint-plugin/docs/rules/no-var-requires.mdx @@ -45,14 +45,14 @@ With `{allow: ['/package\\.json$']}`: -```ts +```ts option='{ "allow": ["/package.json$"] }' const foo = require('../data.json'); ``` -```ts +```ts option='{ "allow": ["/package.json$"] }' const foo = require('../package.json'); ``` diff --git a/packages/eslint-plugin/docs/rules/non-nullable-type-assertion-style.mdx b/packages/eslint-plugin/docs/rules/non-nullable-type-assertion-style.mdx index 05185e692893..cbb1dc0fa11e 100644 --- a/packages/eslint-plugin/docs/rules/non-nullable-type-assertion-style.mdx +++ b/packages/eslint-plugin/docs/rules/non-nullable-type-assertion-style.mdx @@ -23,7 +23,7 @@ This rule reports when an `as` cast is doing the same job as a `!` would, and su ```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; @@ -33,7 +33,7 @@ const alsoDefinitely = maybe; ```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/only-throw-error.mdx b/packages/eslint-plugin/docs/rules/only-throw-error.mdx index fd9d8f2c4d25..cd27f8cc4387 100644 --- a/packages/eslint-plugin/docs/rules/only-throw-error.mdx +++ b/packages/eslint-plugin/docs/rules/only-throw-error.mdx @@ -39,10 +39,10 @@ throw `${err}`; const err = ''; throw err; -function err() { +function getError() { return ''; } -throw err(); +throw getError(); const foo = { bar: '', @@ -70,10 +70,10 @@ try { const err = new Error(); throw err; -function err() { +function getError() { return new Error(); } -throw err(); +throw getError(); const foo = { bar: new Error(), diff --git a/packages/eslint-plugin/docs/rules/prefer-destructuring.mdx b/packages/eslint-plugin/docs/rules/prefer-destructuring.mdx index 9e3d43b2229a..411e376b7243 100644 --- a/packages/eslint-plugin/docs/rules/prefer-destructuring.mdx +++ b/packages/eslint-plugin/docs/rules/prefer-destructuring.mdx @@ -87,14 +87,14 @@ Examples with `{ enforceForDeclarationWithTypeAnnotation: true }`: -```ts +```ts option='{ "object": true }, { "enforceForDeclarationWithTypeAnnotation": true }' const x: string = obj.x; ``` -```ts +```ts option='{ "object": true }, { "enforceForDeclarationWithTypeAnnotation": true }' const { x }: { x: string } = obj; ``` diff --git a/packages/eslint-plugin/docs/rules/prefer-optional-chain.mdx b/packages/eslint-plugin/docs/rules/prefer-optional-chain.mdx index c9a63b6dc8d1..a93fad38daf3 100644 --- a/packages/eslint-plugin/docs/rules/prefer-optional-chain.mdx +++ b/packages/eslint-plugin/docs/rules/prefer-optional-chain.mdx @@ -199,12 +199,26 @@ thing && thing.toString(); When this option is `true` the rule will check operands that are typed as `boolean` when inspecting "loose boolean" operands. +:::note + +This rule intentionally ignores the following case: + +```ts +declare const x: false | { a: string }; +x && x.a; +!x || x.a; +``` + +The boolean expression narrows out the non-nullish falsy cases - so converting the chain to `x?.a` would introduce a type error. + +::: + ```ts option='{ "checkBoolean": true }' -declare const thing: boolean; +declare const thing: true; thing && thing.toString(); ``` @@ -214,7 +228,7 @@ thing && thing.toString(); for `checkBoolean: false` ```ts option='{ "checkBoolean": false }' -declare const thing: boolean; +declare const thing: true; thing && thing.toString(); ``` @@ -257,7 +271,7 @@ When this option is `true` the rule will skip operands that are not typed with ` -```ts option='{ "requireNullish": true }' +```ts option='{ "requireNullish": true }' skipValidation declare const thing1: string | null; thing1 && thing1.toString(); ``` diff --git a/packages/eslint-plugin/docs/rules/prefer-readonly-parameter-types.mdx b/packages/eslint-plugin/docs/rules/prefer-readonly-parameter-types.mdx index 322fb804b366..196b63ba9dab 100644 --- a/packages/eslint-plugin/docs/rules/prefer-readonly-parameter-types.mdx +++ b/packages/eslint-plugin/docs/rules/prefer-readonly-parameter-types.mdx @@ -303,7 +303,7 @@ Examples of code for this rule with `{ignoreInferredTypes: true}`: -```ts option='{ "ignoreInferredTypes": true }' +```ts option='{ "ignoreInferredTypes": true }' skipValidation import { acceptsCallback, CallbackOptions } from 'external-dependency'; acceptsCallback((options: CallbackOptions) => {}); @@ -336,7 +336,7 @@ acceptsCallback(options => {});
external-dependency.d.ts -```ts option='{ "ignoreInferredTypes": true }' +```ts option='{ "ignoreInferredTypes": true }' skipValidation export interface CallbackOptions { prop: string; } diff --git a/packages/eslint-plugin/docs/rules/promise-function-async.mdx b/packages/eslint-plugin/docs/rules/promise-function-async.mdx index 7a2a39559e4d..bb506ad08bfc 100644 --- a/packages/eslint-plugin/docs/rules/promise-function-async.mdx +++ b/packages/eslint-plugin/docs/rules/promise-function-async.mdx @@ -101,7 +101,7 @@ Examples of code with `{ "allowedPromiseNames": ["Bluebird"] }`: ```ts option='{ "allowedPromiseNames": ["Bluebird"] }' -import { Bluebird } from 'bluebird'; +class Bluebird {} const returnsBluebird = () => new Bluebird(() => {}); ``` @@ -110,7 +110,7 @@ const returnsBluebird = () => new Bluebird(() => {}); ```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.mdx b/packages/eslint-plugin/docs/rules/restrict-plus-operands.mdx index 228ac7785094..c96c8aa12ede 100644 --- a/packages/eslint-plugin/docs/rules/restrict-plus-operands.mdx +++ b/packages/eslint-plugin/docs/rules/restrict-plus-operands.mdx @@ -196,23 +196,23 @@ Examples of code for this rule with `{ skipCompoundAssignments: false }`: -```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; ``` -```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; ``` diff --git a/packages/eslint-plugin/docs/rules/space-before-blocks.mdx b/packages/eslint-plugin/docs/rules/space-before-blocks.mdx index ef48550d16d7..84f6cf93e336 100644 --- a/packages/eslint-plugin/docs/rules/space-before-blocks.mdx +++ b/packages/eslint-plugin/docs/rules/space-before-blocks.mdx @@ -15,7 +15,7 @@ It adds support for interfaces and enums. - +{/* prettier-ignore */} ```ts enum Breakpoint{ Large, diff --git a/packages/eslint-plugin/docs/rules/strict-boolean-expressions.mdx b/packages/eslint-plugin/docs/rules/strict-boolean-expressions.mdx index 7b7afb2793db..ab7653a5c0db 100644 --- a/packages/eslint-plugin/docs/rules/strict-boolean-expressions.mdx +++ b/packages/eslint-plugin/docs/rules/strict-boolean-expressions.mdx @@ -61,12 +61,6 @@ while (obj) { ```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.mdx b/packages/eslint-plugin/docs/rules/type-annotation-spacing.mdx index f2d884b837a5..423dc90da83d 100644 --- a/packages/eslint-plugin/docs/rules/type-annotation-spacing.mdx +++ b/packages/eslint-plugin/docs/rules/type-annotation-spacing.mdx @@ -257,7 +257,7 @@ class Foo { } type Foo = { - name: (name : string)=>string; + name : (name : string)=>string; } type Foo = ()=>{}; diff --git a/packages/eslint-plugin/jest.config.js b/packages/eslint-plugin/jest.config.js index 72e29aa600b9..94ed72687afa 100644 --- a/packages/eslint-plugin/jest.config.js +++ b/packages/eslint-plugin/jest.config.js @@ -5,4 +5,6 @@ module.exports = { ...require('../../jest.config.base.js'), coveragePathIgnorePatterns: ['src/index.ts$', 'src/configs/.*.ts$'], + // intentionally empty, to exclude node_modules from ignore (we need to transform ESM dependencies) + transformIgnorePatterns: [], }; diff --git a/packages/eslint-plugin/package.json b/packages/eslint-plugin/package.json index c189fdad6252..40c51565cc73 100644 --- a/packages/eslint-plugin/package.json +++ b/packages/eslint-plugin/package.json @@ -76,6 +76,7 @@ "devDependencies": { "@types/debug": "*", "@types/marked": "*", + "@types/mdast": "^4.0.3", "@types/natural-compare": "*", "@typescript-eslint/rule-schema-to-typescript-types": "7.5.0", "@typescript-eslint/rule-tester": "7.5.0", @@ -90,11 +91,15 @@ "json-schema": "*", "markdown-table": "^3.0.3", "marked": "^5.1.1", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-mdx": "^3.0.0", + "micromark-extension-mdxjs": "^3.0.0", "prettier": "^3.0.3", "rimraf": "*", "title-case": "^3.0.3", "tsx": "*", - "typescript": "*" + "typescript": "*", + "unist-util-visit": "^5.0.0" }, "peerDependencies": { "@typescript-eslint/parser": "^7.0.0", 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..5d728abf25be --- /dev/null +++ b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/adjacent-overload-signatures.shot @@ -0,0 +1,82 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Validating rule docs adjacent-overload-signatures.mdx code examples ESLint output 1`] = ` +"Incorrect + +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[`Validating rule docs adjacent-overload-signatures.mdx code examples ESLint output 2`] = ` +"Correct + +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..0241304b22e8 --- /dev/null +++ b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/array-type.shot @@ -0,0 +1,73 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Validating rule docs array-type.mdx code examples ESLint output 1`] = ` +"Incorrect +Options: { "default": "array" } + +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[`Validating rule docs array-type.mdx code examples ESLint output 2`] = ` +"Correct +Options: { "default": "array" } + +const x: string[] = ['a', 'b']; +const y: readonly string[] = ['a', 'b']; +" +`; + +exports[`Validating rule docs array-type.mdx code examples ESLint output 3`] = ` +"Incorrect +Options: { "default": "generic" } + +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[`Validating rule docs array-type.mdx code examples ESLint output 4`] = ` +"Correct +Options: { "default": "generic" } + +const x: Array = ['a', 'b']; +const y: ReadonlyArray = ['a', 'b']; +" +`; + +exports[`Validating rule docs array-type.mdx code examples ESLint output 5`] = ` +"Incorrect +Options: { "default": "array-simple" } + +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[`Validating rule docs array-type.mdx code examples ESLint output 6`] = ` +"Correct +Options: { "default": "array-simple" } + +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..10fdfdb9d0e2 --- /dev/null +++ b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/await-thenable.shot @@ -0,0 +1,23 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Validating rule docs await-thenable.mdx code examples ESLint output 1`] = ` +"Incorrect + +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[`Validating rule docs await-thenable.mdx code examples ESLint output 2`] = ` +"Correct + +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..0b65d400fb1b --- /dev/null +++ b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/ban-ts-comment.shot @@ -0,0 +1,103 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Validating rule docs ban-ts-comment.mdx code examples ESLint output 1`] = ` +"Incorrect +Options: { "ts-ignore": true } + +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) { + /* @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'); +} +" +`; + +exports[`Validating rule docs ban-ts-comment.mdx code examples ESLint output 2`] = ` +"Correct +Options: { "ts-ignore": true } + +if (false) { + // Compiler warns about unreachable code error + console.log('hello'); +} +" +`; + +exports[`Validating rule docs ban-ts-comment.mdx code examples ESLint output 3`] = ` +"Incorrect +Options: { "ts-expect-error": "allow-with-description" } + +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[`Validating rule docs ban-ts-comment.mdx code examples ESLint output 4`] = ` +"Correct +Options: { "ts-expect-error": "allow-with-description" } + +if (false) { + // @ts-expect-error: Unreachable code error + console.log('hello'); +} +if (false) { + /* @ts-expect-error: Unreachable code error */ + console.log('hello'); +} +" +`; + +exports[`Validating rule docs ban-ts-comment.mdx code examples ESLint output 5`] = ` +"Incorrect +Options: { "ts-expect-error": { "descriptionFormat": "^: TS\\\\d+ because .+$" } } + +// @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[`Validating rule docs ban-ts-comment.mdx code examples ESLint output 6`] = ` +"Correct +Options: { "ts-expect-error": { "descriptionFormat": "^: TS\\\\d+ because .+$" } } + +// @ts-expect-error: TS1234 because the library definition is wrong +const a = doSomething('hello'); +" +`; + +exports[`Validating rule docs ban-ts-comment.mdx code examples ESLint output 7`] = ` +"Incorrect +Options: { "ts-expect-error": "allow-with-description", "minimumDescriptionLength": 10 } + +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[`Validating rule docs ban-ts-comment.mdx code examples ESLint output 8`] = ` +"Correct +Options: { "ts-expect-error": "allow-with-description", "minimumDescriptionLength": 10 } + +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..27aacf7ece65 --- /dev/null +++ b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/ban-tslint-comment.shot @@ -0,0 +1,30 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Validating rule docs ban-tslint-comment.mdx code examples ESLint output 1`] = ` +"Incorrect + +/* 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[`Validating rule docs ban-tslint-comment.mdx code examples ESLint output 2`] = ` +"Correct + +// 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..f96ac650ffa5 --- /dev/null +++ b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/ban-types.shot @@ -0,0 +1,72 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Validating rule docs ban-types.mdx code examples ESLint output 1`] = ` +"Incorrect + +// 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[`Validating rule docs ban-types.mdx code examples ESLint output 2`] = ` +"Correct + +// 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..1eb987f499bf --- /dev/null +++ b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/class-literal-property-style.shot @@ -0,0 +1,75 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Validating rule docs class-literal-property-style.mdx code examples ESLint output 1`] = ` +"Incorrect +Options: "fields" + +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[`Validating rule docs class-literal-property-style.mdx code examples ESLint output 2`] = ` +"Correct +Options: "fields" + +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[`Validating rule docs class-literal-property-style.mdx code examples ESLint output 3`] = ` +"Incorrect +Options: "getters" + +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[`Validating rule docs class-literal-property-style.mdx code examples ESLint output 4`] = ` +"Correct +Options: "getters" + +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..3406f16d9ea3 --- /dev/null +++ b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/class-methods-use-this.shot @@ -0,0 +1,53 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Validating rule docs class-methods-use-this.mdx code examples ESLint output 1`] = ` +"Options: { "ignoreOverrideMethods": true } + +class X { + override method() {} + override property = () => {}; +} +" +`; + +exports[`Validating rule docs class-methods-use-this.mdx code examples ESLint output 2`] = ` +"Options: { "ignoreClassesThatImplementAnInterface": true } + +class X implements Y { + method() {} + property = () => {}; +} +" +`; + +exports[`Validating rule docs class-methods-use-this.mdx code examples ESLint output 3`] = ` +"Incorrect +Options: { "ignoreClassesThatImplementAnInterface": "public-fields" } + +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[`Validating rule docs class-methods-use-this.mdx code examples ESLint output 4`] = ` +"Correct +Options: { "ignoreClassesThatImplementAnInterface": "public-fields" } + +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..1e63291e5fae --- /dev/null +++ b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/consistent-generic-constructors.shot @@ -0,0 +1,46 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Validating rule docs consistent-generic-constructors.mdx code examples ESLint output 1`] = ` +"Incorrect +Options: "constructor" + +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[`Validating rule docs consistent-generic-constructors.mdx code examples ESLint output 2`] = ` +"Correct +Options: "constructor" + +const map = new Map(); +const map: Map = new MyMap(); +const set = new Set(); +const set = new Set(); +const set: Set = new Set(); +" +`; + +exports[`Validating rule docs consistent-generic-constructors.mdx code examples ESLint output 3`] = ` +"Incorrect +Options: "type-annotation" + +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[`Validating rule docs consistent-generic-constructors.mdx code examples ESLint output 4`] = ` +"Correct +Options: "type-annotation" + +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..3acf9ee188aa --- /dev/null +++ b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/consistent-indexed-object-style.shot @@ -0,0 +1,52 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Validating rule docs consistent-indexed-object-style.mdx code examples ESLint output 1`] = ` +"Incorrect +Options: "record" + +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[`Validating rule docs consistent-indexed-object-style.mdx code examples ESLint output 2`] = ` +"Correct +Options: "record" + +type Foo = Record; +" +`; + +exports[`Validating rule docs consistent-indexed-object-style.mdx code examples ESLint output 3`] = ` +"Incorrect +Options: "index-signature" + +type Foo = Record; + ~~~~~~~~~~~~~~~~~~~~~~~ An index signature is preferred over a record. +" +`; + +exports[`Validating rule docs consistent-indexed-object-style.mdx code examples ESLint output 4`] = ` +"Correct +Options: "index-signature" + +interface Foo { + [key: string]: unknown; +} + +type Foo = { + [key: string]: unknown; +}; +" +`; diff --git a/packages/eslint-plugin/tests/docs-eslint-output-snapshots/consistent-return.shot b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/consistent-return.shot new file mode 100644 index 000000000000..da3f0be81891 --- /dev/null +++ b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/consistent-return.shot @@ -0,0 +1,35 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Validating rule docs consistent-return.mdx code examples ESLint output 1`] = ` +"Incorrect + +function foo(): undefined {} +function bar(flag: boolean): undefined { + if (flag) return foo(); + return; + ~~~~~~~ Function 'bar' expected a return value. +} + +async function baz(flag: boolean): Promise { + if (flag) return; + return foo(); + ~~~~~~~~~~~~~ Async function 'baz' expected no return value. +} +" +`; + +exports[`Validating rule docs consistent-return.mdx code examples ESLint output 2`] = ` +"Correct + +function foo(): void {} +function bar(flag: boolean): void { + if (flag) return foo(); + return; +} + +async function baz(flag: boolean): Promise { + if (flag) return 42; + return; +} +" +`; 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..755dc6eb472d --- /dev/null +++ b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/consistent-type-assertions.shot @@ -0,0 +1,59 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Validating rule docs consistent-type-assertions.mdx code examples ESLint output 1`] = ` +"Incorrect +Options: { "assertionStyle": "as", "objectLiteralTypeAssertions": "never" } + +const x = { foo: 1 } as T; + ~~~~~~~~~~~~~~~ Always prefer const x: T = { ... }. + +function bar() { + return { foo: 1 } as T; + ~~~~~~~~~~~~~~~ Always prefer const x: T = { ... }. +} +" +`; + +exports[`Validating rule docs consistent-type-assertions.mdx code examples ESLint output 2`] = ` +"Correct +Options: { "assertionStyle": "as", "objectLiteralTypeAssertions": "never" } + +const x: T = { foo: 1 }; +const y = { foo: 1 } as any; +const z = { foo: 1 } as unknown; + +function bar(): T { + return { foo: 1 }; +} +" +`; + +exports[`Validating rule docs consistent-type-assertions.mdx code examples ESLint output 3`] = ` +"Incorrect +Options: { "assertionStyle": "as", "objectLiteralTypeAssertions": "allow-as-parameter" } + +const x = { foo: 1 } as T; + ~~~~~~~~~~~~~~~ Always prefer const x: T = { ... }. + +function bar() { + return { foo: 1 } as T; + ~~~~~~~~~~~~~~~ Always prefer const x: T = { ... }. +} +" +`; + +exports[`Validating rule docs consistent-type-assertions.mdx code examples ESLint output 4`] = ` +"Correct +Options: { "assertionStyle": "as", "objectLiteralTypeAssertions": "allow-as-parameter" } + +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..85bd090663a6 --- /dev/null +++ b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/consistent-type-definitions.shot @@ -0,0 +1,42 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Validating rule docs consistent-type-definitions.mdx code examples ESLint output 1`] = ` +"Incorrect +Options: "interface" + +type T = { x: number }; + ~ Use an \`interface\` instead of a \`type\`. +" +`; + +exports[`Validating rule docs consistent-type-definitions.mdx code examples ESLint output 2`] = ` +"Correct +Options: "interface" + +type T = string; +type Foo = string | {}; + +interface T { + x: number; +} +" +`; + +exports[`Validating rule docs consistent-type-definitions.mdx code examples ESLint output 3`] = ` +"Incorrect +Options: "type" + +interface T { + ~ Use a \`type\` instead of an \`interface\`. + x: number; +} +" +`; + +exports[`Validating rule docs consistent-type-definitions.mdx code examples ESLint output 4`] = ` +"Correct +Options: "type" + +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..97f0114047ba --- /dev/null +++ b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/consistent-type-exports.shot @@ -0,0 +1,33 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Validating rule docs consistent-type-exports.mdx code examples ESLint output 1`] = ` +"Incorrect + +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[`Validating rule docs consistent-type-exports.mdx code examples ESLint output 2`] = ` +"Correct + +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..76afd59000fd --- /dev/null +++ b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/consistent-type-imports.shot @@ -0,0 +1,65 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Validating rule docs consistent-type-imports.mdx code examples ESLint output 1`] = ` +"Options: { "prefer": "type-imports" } + +import type { Foo } from 'Foo'; +import type Bar from 'Bar'; +type T = Foo; +const x: Bar = 1; +" +`; + +exports[`Validating rule docs consistent-type-imports.mdx code examples ESLint output 2`] = ` +"Options: { "prefer": "type-imports" } + +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[`Validating rule docs consistent-type-imports.mdx code examples ESLint output 3`] = ` +"Incorrect + +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[`Validating rule docs consistent-type-imports.mdx code examples ESLint output 4`] = ` +"Options: { "fixStyle": "separate-type-imports" } + +import type { Foo } from 'Foo'; +import type Bar from 'Bar'; +type T = Foo; +const x: Bar = 1; +" +`; + +exports[`Validating rule docs consistent-type-imports.mdx code examples ESLint output 5`] = ` +"Options: { "fixStyle": "inline-type-imports" } + +import { type Foo } from 'Foo'; +import type Bar from 'Bar'; +type T = Foo; +const x: Bar = 1; +" +`; + +exports[`Validating rule docs consistent-type-imports.mdx code examples ESLint output 6`] = ` +"Options: { "disallowTypeAnnotations": true } + +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..0944932f2e58 --- /dev/null +++ b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/default-param-last.shot @@ -0,0 +1,50 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Validating rule docs default-param-last.mdx code examples ESLint output 1`] = ` +"Incorrect + +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[`Validating rule docs default-param-last.mdx code examples ESLint output 2`] = ` +"Correct + +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..31abaa77cb29 --- /dev/null +++ b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/dot-notation.shot @@ -0,0 +1,37 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Validating rule docs dot-notation.mdx code examples ESLint output 1`] = ` +"Options: { "allowPrivateClassPropertyAccess": true } + +class X { + private priv_prop = 123; +} + +const x = new X(); +x['priv_prop'] = 123; +" +`; + +exports[`Validating rule docs dot-notation.mdx code examples ESLint output 2`] = ` +"Options: { "allowProtectedClassPropertyAccess": true } + +class X { + protected protected_prop = 123; +} + +const x = new X(); +x['protected_prop'] = 123; +" +`; + +exports[`Validating rule docs dot-notation.mdx code examples ESLint output 3`] = ` +"Options: { "allowIndexSignaturePropertyAccess": true } + +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..1bce8870ade7 --- /dev/null +++ b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/explicit-function-return-type.shot @@ -0,0 +1,262 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Validating rule docs explicit-function-return-type.mdx code examples ESLint output 1`] = ` +"Incorrect + +// 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[`Validating rule docs explicit-function-return-type.mdx code examples ESLint output 2`] = ` +"Correct + +// 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[`Validating rule docs explicit-function-return-type.mdx code examples ESLint output 3`] = ` +"Incorrect +Options: { "allowExpressions": true } + +function test() {} +~~~~~~~~~~~~~ Missing return type on function. + +const fn = () => {}; + ~~ Missing return type on function. + +export default () => {}; + ~~ Missing return type on function. +" +`; + +exports[`Validating rule docs explicit-function-return-type.mdx code examples ESLint output 4`] = ` +"Correct +Options: { "allowExpressions": true } + +node.addEventListener('click', () => {}); + +node.addEventListener('click', function () {}); + +const foo = arr.map(i => i * i); +" +`; + +exports[`Validating rule docs explicit-function-return-type.mdx code examples ESLint output 5`] = ` +"Incorrect +Options: { "allowTypedFunctionExpressions": true } + +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[`Validating rule docs explicit-function-return-type.mdx code examples ESLint output 6`] = ` +"Correct +Options: { "allowTypedFunctionExpressions": true } + +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[`Validating rule docs explicit-function-return-type.mdx code examples ESLint output 7`] = ` +"Incorrect +Options: { "allowHigherOrderFunctions": true } + +var arrowFn = () => () => {}; + ~~ Missing return type on function. + +function fn() { + return function () {}; + ~~~~~~~~~ Missing return type on function. +} +" +`; + +exports[`Validating rule docs explicit-function-return-type.mdx code examples ESLint output 8`] = ` +"Correct +Options: { "allowHigherOrderFunctions": true } + +var arrowFn = () => (): void => {}; + +function fn() { + return function (): void {}; +} +" +`; + +exports[`Validating rule docs explicit-function-return-type.mdx code examples ESLint output 9`] = ` +"Incorrect +Options: { "allowDirectConstAssertionInArrowFunctions": true } + +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[`Validating rule docs explicit-function-return-type.mdx code examples ESLint output 10`] = ` +"Correct +Options: { "allowDirectConstAssertionInArrowFunctions": true } + +const func = (value: number) => ({ foo: 'bar', value }) as const; +const func = () => x as const; +" +`; + +exports[`Validating rule docs explicit-function-return-type.mdx code examples ESLint output 11`] = ` +"Incorrect +Options: { "allowConciseArrowFunctionExpressionsStartingWithVoid": true } + +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[`Validating rule docs explicit-function-return-type.mdx code examples ESLint output 12`] = ` +"Correct +Options: { "allowConciseArrowFunctionExpressionsStartingWithVoid": true } + +var log = (message: string) => void console.log(message); +" +`; + +exports[`Validating rule docs explicit-function-return-type.mdx code examples ESLint output 13`] = ` +"Incorrect +Options: { "allowFunctionsWithoutTypeParameters": true } + +function foo(t: T) { +~~~~~~~~~~~~~~~ Missing return type on function. + return t; +} + +const bar = (t: T) => t; + ~~ Missing return type on function. +" +`; + +exports[`Validating rule docs explicit-function-return-type.mdx code examples ESLint output 14`] = ` +"Correct +Options: { "allowFunctionsWithoutTypeParameters": true } + +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[`Validating rule docs explicit-function-return-type.mdx code examples ESLint output 15`] = ` +"Incorrect +Options: { "allowIIFEs": true } + +var func = () => 'foo'; + ~~ Missing return type on function. +" +`; + +exports[`Validating rule docs explicit-function-return-type.mdx code examples ESLint output 16`] = ` +"Correct +Options: { "allowIIFEs": true } + +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..ee066bed4686 --- /dev/null +++ b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/explicit-member-accessibility.shot @@ -0,0 +1,303 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Validating rule docs explicit-member-accessibility.mdx code examples ESLint output 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[`Validating rule docs explicit-member-accessibility.mdx code examples ESLint output 2`] = ` +"Options: { "accessibility": "explicit" } + +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[`Validating rule docs explicit-member-accessibility.mdx code examples ESLint output 3`] = ` +"Options: { "accessibility": "no-public" } + +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[`Validating rule docs explicit-member-accessibility.mdx code examples ESLint output 4`] = ` +"Options: { "accessibility": "no-public" } + +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[`Validating rule docs explicit-member-accessibility.mdx code examples ESLint output 5`] = ` +"Options: { "overrides": { "constructors": "no-public" } } + +class Animal { + public constructor(protected animalName) {} + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Public accessibility modifier on method definition constructor. + public get name() { + return this.animalName; + } +} +" +`; + +exports[`Validating rule docs explicit-member-accessibility.mdx code examples ESLint output 6`] = ` +"Options: { "overrides": { "constructors": "no-public" } } + +class Animal { + constructor(protected animalName) {} + public get name() { + return this.animalName; + } +} +" +`; + +exports[`Validating rule docs explicit-member-accessibility.mdx code examples ESLint output 7`] = ` +"Options: { "accessibility": "no-public", "overrides": { "properties": "explicit" } } + +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[`Validating rule docs explicit-member-accessibility.mdx code examples ESLint output 8`] = ` +"Options: { "accessibility": "no-public", "overrides": { "properties": "explicit" } } + +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[`Validating rule docs explicit-member-accessibility.mdx code examples ESLint output 9`] = ` +"Options: { "accessibility": "off", "overrides": { "parameterProperties": "explicit" } } + +class Animal { + constructor(readonly animalName: string) {} + ~~~~~~~~~~~~~~~~~~~~~~~~~~~ Missing accessibility modifier on parameter property animalName. +} +" +`; + +exports[`Validating rule docs explicit-member-accessibility.mdx code examples ESLint output 10`] = ` +"Options: { "accessibility": "off", "overrides": { "parameterProperties": "explicit" } } + +class Animal { + constructor(public readonly animalName: string) {} +} + +class Animal { + constructor(public animalName: string) {} +} + +class Animal { + constructor(animalName: string) {} +} +" +`; + +exports[`Validating rule docs explicit-member-accessibility.mdx code examples ESLint output 11`] = ` +"Options: { "accessibility": "off", "overrides": { "parameterProperties": "no-public" } } + +class Animal { + constructor(public readonly animalName: string) {} + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Public accessibility modifier on parameter property animalName. +} +" +`; + +exports[`Validating rule docs explicit-member-accessibility.mdx code examples ESLint output 12`] = ` +"Options: { "accessibility": "off", "overrides": { "parameterProperties": "no-public" } } + +class Animal { + constructor(public animalName: string) {} +} +" +`; + +exports[`Validating rule docs explicit-member-accessibility.mdx code examples ESLint output 13`] = ` +"Options: { "overrides": { "accessors" : "off" } } + +class Animal { + constructor(protected animalName) {} + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Missing accessibility modifier on method definition constructor. + public get name() { + return this.animalName; + } + get legs() { + return this.legCount; + } +} +" +`; + +exports[`Validating rule docs explicit-member-accessibility.mdx code examples ESLint output 14`] = ` +"Options: { "overrides": { "accessors" : "off" } } + +class Animal { + public constructor(protected animalName) {} + public get name() { + return this.animalName; + } + get legs() { + return this.legCount; + } +} +" +`; + +exports[`Validating rule docs explicit-member-accessibility.mdx code examples ESLint output 15`] = ` +"Options: { "ignoredMethodNames": ["specificMethod", "whateverMethod"] } + +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..707536a970d6 --- /dev/null +++ b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/explicit-module-boundary-types.shot @@ -0,0 +1,198 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Validating rule docs explicit-module-boundary-types.mdx code examples ESLint output 1`] = ` +"Incorrect + +// 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[`Validating rule docs explicit-module-boundary-types.mdx code examples ESLint output 2`] = ` +"Correct + +// 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[`Validating rule docs explicit-module-boundary-types.mdx code examples ESLint output 3`] = ` +"Incorrect +Options: { "allowArgumentsExplicitlyTypedAsAny": false } + +export const func = (value: any): number => value + 1; + ~~~~~~~~~~ Argument 'value' should be typed with a non-any type. +" +`; + +exports[`Validating rule docs explicit-module-boundary-types.mdx code examples ESLint output 4`] = ` +"Correct +Options: { "allowArgumentsExplicitlyTypedAsAny": true } + +export const func = (value: any): number => value + 1; +" +`; + +exports[`Validating rule docs explicit-module-boundary-types.mdx code examples ESLint output 5`] = ` +"Incorrect +Options: { "allowDirectConstAssertionInArrowFunctions": false } + +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[`Validating rule docs explicit-module-boundary-types.mdx code examples ESLint output 6`] = ` +"Correct +Options: { "allowDirectConstAssertionInArrowFunctions": true } + +export const func = (value: number) => ({ type: 'X', value }) as const; +export const foo = () => + ({ + bar: true, + }) as const; +export const bar = () => 1 as const; +" +`; + +exports[`Validating rule docs explicit-module-boundary-types.mdx code examples ESLint output 7`] = ` +"Incorrect +Options: { "allowHigherOrderFunctions": false } + +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[`Validating rule docs explicit-module-boundary-types.mdx code examples ESLint output 8`] = ` +"Correct +Options: { "allowHigherOrderFunctions": true } + +export const arrowFn = () => (): void => {}; + +export function fn() { + return function (): void {}; +} + +export function foo(outer: string) { + return function (inner: string): void {}; +} +" +`; + +exports[`Validating rule docs explicit-module-boundary-types.mdx code examples ESLint output 9`] = ` +"Incorrect +Options: { "allowTypedFunctionExpressions": false } + +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[`Validating rule docs explicit-module-boundary-types.mdx code examples ESLint output 10`] = ` +"Correct +Options: { "allowTypedFunctionExpressions": true } + +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..551df7110d76 --- /dev/null +++ b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/lines-between-class-members.shot @@ -0,0 +1,33 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Validating rule docs lines-between-class-members.mdx code examples ESLint output 1`] = ` +"Options: "always", { "exceptAfterOverload": true } + +class foo { + bar(a: string): void; + bar(a: string, b: string): void; + bar(a: string, b: string) {} + + baz() {} + + qux() {} +} +" +`; + +exports[`Validating rule docs lines-between-class-members.mdx code examples ESLint output 2`] = ` +"Options: "always", { "exceptAfterOverload": false } + +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..b1b5eb48f627 --- /dev/null +++ b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/member-delimiter-style.shot @@ -0,0 +1,58 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Validating rule docs member-delimiter-style.mdx code examples ESLint output 1`] = ` +"Incorrect + +// 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[`Validating rule docs member-delimiter-style.mdx code examples ESLint output 2`] = ` +"Correct + +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..d03a0730b13e --- /dev/null +++ b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/member-ordering.shot @@ -0,0 +1,660 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Validating rule docs member-ordering.mdx code examples ESLint output 1`] = ` +"Incorrect +Options: { "default": ["signature", "method", "constructor", "field"] } + +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[`Validating rule docs member-ordering.mdx code examples ESLint output 2`] = ` +"Incorrect +Options: { "default": ["signature", "method", "constructor", "field"] } + +type Foo = { + B: string; // -> field + + // no constructor + + A(): void; // -> method + ~~~~~~~~~~ Member A should be declared before all field definitions. + + // no signature +}; +" +`; + +exports[`Validating rule docs member-ordering.mdx code examples ESLint output 3`] = ` +"Incorrect +Options: { "default": ["signature", "method", "constructor", "field"] } + +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[`Validating rule docs member-ordering.mdx code examples ESLint output 4`] = ` +"Incorrect +Options: { "default": ["signature", "method", "constructor", "field"] } + +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[`Validating rule docs member-ordering.mdx code examples ESLint output 5`] = ` +"Correct +Options: { "default": ["signature", "method", "constructor", "field"] } + +interface Foo { + [Z: string]: any; // -> signature + + A(): void; // -> method + + new (); // -> constructor + + B: string; // -> field +} +" +`; + +exports[`Validating rule docs member-ordering.mdx code examples ESLint output 6`] = ` +"Correct +Options: { "default": ["signature", "method", "constructor", "field"] } + +type Foo = { + // no signature + + A(): void; // -> method + + // no constructor + + B: string; // -> field +}; +" +`; + +exports[`Validating rule docs member-ordering.mdx code examples ESLint output 7`] = ` +"Correct +Options: { "default": ["signature", "method", "constructor", "field"] } + +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[`Validating rule docs member-ordering.mdx code examples ESLint output 8`] = ` +"Correct +Options: { "default": ["signature", "method", "constructor", "field"] } + +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[`Validating rule docs member-ordering.mdx code examples ESLint output 9`] = ` +"Incorrect +Options: { "default": ["public-instance-method", "public-static-field"] } + +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[`Validating rule docs member-ordering.mdx code examples ESLint output 10`] = ` +"Incorrect +Options: { "default": ["public-instance-method", "public-static-field"] } + +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[`Validating rule docs member-ordering.mdx code examples ESLint output 11`] = ` +"Correct +Options: { "default": ["public-instance-method", "public-static-field"] } + +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[`Validating rule docs member-ordering.mdx code examples ESLint output 12`] = ` +"Correct +Options: { "default": ["public-instance-method", "public-static-field"] } + +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[`Validating rule docs member-ordering.mdx code examples ESLint output 13`] = ` +"Incorrect +Options: { "default": ["public-static-field", "static-field", "instance-field"] } + +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[`Validating rule docs member-ordering.mdx code examples ESLint output 14`] = ` +"Incorrect +Options: { "default": ["public-static-field", "static-field", "instance-field"] } + +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[`Validating rule docs member-ordering.mdx code examples ESLint output 15`] = ` +"Correct +Options: { "default": ["public-static-field", "static-field", "instance-field"] } + +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[`Validating rule docs member-ordering.mdx code examples ESLint output 16`] = ` +"Correct +Options: { "default": ["public-static-field", "static-field", "instance-field"] } + +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[`Validating rule docs member-ordering.mdx code examples ESLint output 17`] = ` +"Incorrect +Options: { "classes": ["method", "constructor", "field"] } + +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[`Validating rule docs member-ordering.mdx code examples ESLint output 18`] = ` +"Correct +Options: { "classes": ["method", "constructor", "field"] } + +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[`Validating rule docs member-ordering.mdx code examples ESLint output 19`] = ` +"Incorrect +Options: { "classExpressions": ["method", "constructor", "field"] } + +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[`Validating rule docs member-ordering.mdx code examples ESLint output 20`] = ` +"Correct +Options: { "classExpressions": ["method", "constructor", "field"] } + +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[`Validating rule docs member-ordering.mdx code examples ESLint output 21`] = ` +"Incorrect +Options: { "interfaces": ["signature", "method", "constructor", "field"] } + +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[`Validating rule docs member-ordering.mdx code examples ESLint output 22`] = ` +"Correct +Options: { "interfaces": ["signature", "method", "constructor", "field"] } + +interface Foo { + [Z: string]: any; // -> signature + + A(): void; // -> method + + new (); // -> constructor + + B: string; // -> field +} +" +`; + +exports[`Validating rule docs member-ordering.mdx code examples ESLint output 23`] = ` +"Incorrect +Options: { "typeLiterals": ["signature", "method", "constructor", "field"] } + +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[`Validating rule docs member-ordering.mdx code examples ESLint output 24`] = ` +"Correct +Options: { "typeLiterals": ["signature", "method", "constructor", "field"] } + +type Foo = { + [Z: string]: any; // -> signature + + A(): void; // -> method + + new (); // -> constructor + + B: string; // -> field +}; +" +`; + +exports[`Validating rule docs member-ordering.mdx code examples ESLint output 25`] = ` +"Incorrect +Options: {"default":{"order":"alphabetically"}} + +interface Foo { + a: x; + B: x; + ~~~~~ Member B should be declared before member a. + c: x; + + B(): void; + c(): void; + a(): void; + ~~~~~~~~~~ Member a should be declared before member c. +} +" +`; + +exports[`Validating rule docs member-ordering.mdx code examples ESLint output 26`] = ` +"Correct +Options: {"default":{"order":"alphabetically"}} + +interface Foo { + B: x; + a: x; + c: x; + + B(): void; + a(): void; + c(): void; +} +" +`; + +exports[`Validating rule docs member-ordering.mdx code examples ESLint output 27`] = ` +"Incorrect +Options: {"default":{"memberTypes":["method","field"],"order":"alphabetically"}} + +interface Foo { + B(): void; + c(): void; + a(): void; + ~~~~~~~~~~ Member a should be declared before member c. + + a: x; + B: x; + ~~~~~ Member B should be declared before member a. + c: x; +} +" +`; + +exports[`Validating rule docs member-ordering.mdx code examples ESLint output 28`] = ` +"Correct +Options: {"default":{"memberTypes":["method","field"],"order":"alphabetically"}} + +interface Foo { + B(): void; + a(): void; + c(): void; + + B: x; + a: x; + c: x; +} +" +`; + +exports[`Validating rule docs member-ordering.mdx code examples ESLint output 29`] = ` +"Incorrect +Options: {"default":{"order":"alphabetically-case-insensitive"}} + +interface Foo { + B: x; + a: x; + ~~~~~ Member a should be declared before member B. + c: x; + + B(): void; + c(): void; + a(): void; + ~~~~~~~~~~ Member a should be declared before member c. +} +" +`; + +exports[`Validating rule docs member-ordering.mdx code examples ESLint output 30`] = ` +"Correct +Options: {"default":{"order":"alphabetically-case-insensitive"}} + +interface Foo { + a: x; + B: x; + c: x; + + a(): void; + B(): void; + c(): void; +} +" +`; + +exports[`Validating rule docs member-ordering.mdx code examples ESLint output 31`] = ` +"Incorrect +Options: { "default": { "memberTypes": "never", "order": "alphabetically" } } + +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[`Validating rule docs member-ordering.mdx code examples ESLint output 32`] = ` +"Correct +Options: { "default": { "memberTypes": "never", "order": "alphabetically" } } + +interface Foo { + [a: string]: number; + a: boolean; + b(): void; + + (): Baz; + new (): Bar; +} +" +`; + +exports[`Validating rule docs member-ordering.mdx code examples ESLint output 33`] = ` +"Incorrect +Options: { "default": { "optionalityOrder": "optional-first", "order": "alphabetically" } } + +interface Foo { + a: boolean; + ~~~~~~~~~~~ Member a should be declared after all optional members. + b?: number; + c: string; +} +" +`; + +exports[`Validating rule docs member-ordering.mdx code examples ESLint output 34`] = ` +"Correct +Options: { "default": { "optionalityOrder": "optional-first", "order": "alphabetically" } } + +interface Foo { + b?: number; + a: boolean; + c: string; +} +" +`; + +exports[`Validating rule docs member-ordering.mdx code examples ESLint output 35`] = ` +"Incorrect +Options: { "default": { "optionalityOrder": "required-first", "order": "alphabetically" } } + +interface Foo { + a: boolean; + b?: number; + ~~~~~~~~~~~ Member b should be declared after all required members. + c: string; +} +" +`; + +exports[`Validating rule docs member-ordering.mdx code examples ESLint output 36`] = ` +"Correct +Options: { "default": { "optionalityOrder": "required-first", "order": "alphabetically" } } + +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..d1be5427205d --- /dev/null +++ b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/method-signature-style.shot @@ -0,0 +1,71 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Validating rule docs method-signature-style.mdx code examples ESLint output 1`] = ` +"Incorrect +Options: "property" + +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[`Validating rule docs method-signature-style.mdx code examples ESLint output 2`] = ` +"Correct +Options: "property" + +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[`Validating rule docs method-signature-style.mdx code examples ESLint output 3`] = ` +"Incorrect +Options: "method" + +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[`Validating rule docs method-signature-style.mdx code examples ESLint output 4`] = ` +"Correct +Options: "method" + +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..3967eeeecdca --- /dev/null +++ b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-array-constructor.shot @@ -0,0 +1,22 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Validating rule docs no-array-constructor.mdx code examples ESLint output 1`] = ` +"Incorrect + +Array(0, 1, 2); +~~~~~~~~~~~~~~ The array literal notation [] is preferable. +new Array(0, 1, 2); +~~~~~~~~~~~~~~~~~~ The array literal notation [] is preferable. +" +`; + +exports[`Validating rule docs no-array-constructor.mdx code examples ESLint output 2`] = ` +"Correct + +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..a61316eb73fe --- /dev/null +++ b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-array-delete.shot @@ -0,0 +1,20 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Validating rule docs no-array-delete.mdx code examples ESLint output 1`] = ` +"Incorrect + +declare const arr: number[]; + +delete arr[0]; +~~~~~~~~~~~~~ Using the \`delete\` operator with an array expression is unsafe. +" +`; + +exports[`Validating rule docs no-array-delete.mdx code examples ESLint output 2`] = ` +"Correct + +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..21750093fe9a --- /dev/null +++ b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-base-to-string.shot @@ -0,0 +1,58 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Validating rule docs no-base-to-string.mdx code examples ESLint output 1`] = ` +"Incorrect + +// 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[`Validating rule docs no-base-to-string.mdx code examples ESLint output 2`] = ` +"Correct + +// 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[`Validating rule docs no-base-to-string.mdx code examples ESLint output 3`] = ` +"Options: { "ignoredTypeNames": ["RegExp"] } + +\`\${/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..074f8f721db5 --- /dev/null +++ b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-confusing-non-null-assertion.shot @@ -0,0 +1,31 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Validating rule docs no-confusing-non-null-assertion.mdx code examples ESLint output 1`] = ` +"Incorrect + +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[`Validating rule docs no-confusing-non-null-assertion.mdx code examples ESLint output 2`] = ` +"Correct + +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..bf20e61945c3 --- /dev/null +++ b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-confusing-void-expression.shot @@ -0,0 +1,82 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Validating rule docs no-confusing-void-expression.mdx code examples ESLint output 1`] = ` +"Incorrect + +// 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[`Validating rule docs no-confusing-void-expression.mdx code examples ESLint output 2`] = ` +"Correct + +// 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[`Validating rule docs no-confusing-void-expression.mdx code examples ESLint output 3`] = ` +"Options: { "ignoreArrowShorthand": true } + +promise.then(value => window.postMessage(value)); +" +`; + +exports[`Validating rule docs no-confusing-void-expression.mdx code examples ESLint output 4`] = ` +"Options: { "ignoreVoidOperator": true } + +// 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..33ac7b3e3444 --- /dev/null +++ b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-duplicate-enum-values.shot @@ -0,0 +1,43 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Validating rule docs no-duplicate-enum-values.mdx code examples ESLint output 1`] = ` +"Incorrect + +enum E { + A = 0, + B = 0, + ~~~~~ Duplicate enum member value 0. +} +" +`; + +exports[`Validating rule docs no-duplicate-enum-values.mdx code examples ESLint output 2`] = ` +"Incorrect + +enum E { + A = 'A', + B = 'A', + ~~~~~~~ Duplicate enum member value A. +} +" +`; + +exports[`Validating rule docs no-duplicate-enum-values.mdx code examples ESLint output 3`] = ` +"Correct + +enum E { + A = 0, + B = 1, +} +" +`; + +exports[`Validating rule docs no-duplicate-enum-values.mdx code examples ESLint output 4`] = ` +"Correct + +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..be96eb01aa3e --- /dev/null +++ b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-duplicate-type-constituents.shot @@ -0,0 +1,40 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Validating rule docs no-duplicate-type-constituents.mdx code examples ESLint output 1`] = ` +"Incorrect + +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[`Validating rule docs no-duplicate-type-constituents.mdx code examples ESLint output 2`] = ` +"Correct + +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..4f132983f1b5 --- /dev/null +++ b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-dynamic-delete.shot @@ -0,0 +1,35 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Validating rule docs no-dynamic-delete.mdx code examples ESLint output 1`] = ` +"Incorrect + +// 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[`Validating rule docs no-dynamic-delete.mdx code examples ESLint output 2`] = ` +"Correct + +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..7d7349e908b4 --- /dev/null +++ b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-empty-function.shot @@ -0,0 +1,44 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Validating rule docs no-empty-function.mdx code examples ESLint output 1`] = ` +"Options: { "allow": ["private-constructors"] } + +class Foo { + private constructor() {} +} +" +`; + +exports[`Validating rule docs no-empty-function.mdx code examples ESLint output 2`] = ` +"Options: { "allow": ["protected-constructors"] } + +class Foo { + protected constructor() {} +} +" +`; + +exports[`Validating rule docs no-empty-function.mdx code examples ESLint output 3`] = ` +"Options: { "allow": ["decoratedFunctions"] } + +class Foo { + @decorator() + foo() {} +} +" +`; + +exports[`Validating rule docs no-empty-function.mdx code examples ESLint output 4`] = ` +"Options: { "allow": ["overrideMethods"] } + +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..f6aa9a05b458 --- /dev/null +++ b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-empty-interface.shot @@ -0,0 +1,37 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Validating rule docs no-empty-interface.mdx code examples ESLint output 1`] = ` +"Incorrect + +// 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[`Validating rule docs no-empty-interface.mdx code examples ESLint output 2`] = ` +"Correct + +// 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..3867e5a4ff74 --- /dev/null +++ b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-explicit-any.shot @@ -0,0 +1,177 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Validating rule docs no-explicit-any.mdx code examples ESLint output 1`] = ` +"Incorrect + +const age: any = 'seventeen'; + ~~~ Unexpected any. Specify a different type. +" +`; + +exports[`Validating rule docs no-explicit-any.mdx code examples ESLint output 2`] = ` +"Incorrect + +const ages: any[] = ['seventeen']; + ~~~ Unexpected any. Specify a different type. +" +`; + +exports[`Validating rule docs no-explicit-any.mdx code examples ESLint output 3`] = ` +"Incorrect + +const ages: Array = ['seventeen']; + ~~~ Unexpected any. Specify a different type. +" +`; + +exports[`Validating rule docs no-explicit-any.mdx code examples ESLint output 4`] = ` +"Incorrect + +function greet(): any {} + ~~~ Unexpected any. Specify a different type. +" +`; + +exports[`Validating rule docs no-explicit-any.mdx code examples ESLint output 5`] = ` +"Incorrect + +function greet(): any[] {} + ~~~ Unexpected any. Specify a different type. +" +`; + +exports[`Validating rule docs no-explicit-any.mdx code examples ESLint output 6`] = ` +"Incorrect + +function greet(): Array {} + ~~~ Unexpected any. Specify a different type. +" +`; + +exports[`Validating rule docs no-explicit-any.mdx code examples ESLint output 7`] = ` +"Incorrect + +function greet(): Array> {} + ~~~ Unexpected any. Specify a different type. +" +`; + +exports[`Validating rule docs no-explicit-any.mdx code examples ESLint output 8`] = ` +"Incorrect + +function greet(param: Array): string {} + ~~~ Unexpected any. Specify a different type. +" +`; + +exports[`Validating rule docs no-explicit-any.mdx code examples ESLint output 9`] = ` +"Incorrect + +function greet(param: Array): Array {} + ~~~ Unexpected any. Specify a different type. + ~~~ Unexpected any. Specify a different type. +" +`; + +exports[`Validating rule docs no-explicit-any.mdx code examples ESLint output 10`] = ` +"Correct + +const age: number = 17; +" +`; + +exports[`Validating rule docs no-explicit-any.mdx code examples ESLint output 11`] = ` +"Correct + +const ages: number[] = [17]; +" +`; + +exports[`Validating rule docs no-explicit-any.mdx code examples ESLint output 12`] = ` +"Correct + +const ages: Array = [17]; +" +`; + +exports[`Validating rule docs no-explicit-any.mdx code examples ESLint output 13`] = ` +"Correct + +function greet(): string {} +" +`; + +exports[`Validating rule docs no-explicit-any.mdx code examples ESLint output 14`] = ` +"Correct + +function greet(): string[] {} +" +`; + +exports[`Validating rule docs no-explicit-any.mdx code examples ESLint output 15`] = ` +"Correct + +function greet(): Array {} +" +`; + +exports[`Validating rule docs no-explicit-any.mdx code examples ESLint output 16`] = ` +"Correct + +function greet(): Array> {} +" +`; + +exports[`Validating rule docs no-explicit-any.mdx code examples ESLint output 17`] = ` +"Correct + +function greet(param: Array): string {} +" +`; + +exports[`Validating rule docs no-explicit-any.mdx code examples ESLint output 18`] = ` +"Correct + +function greet(param: Array): Array {} +" +`; + +exports[`Validating rule docs no-explicit-any.mdx code examples ESLint output 19`] = ` +"Options: { "ignoreRestArgs": false } + +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..48301d1622a4 --- /dev/null +++ b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-extra-non-null-assertion.shot @@ -0,0 +1,58 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Validating rule docs no-extra-non-null-assertion.mdx code examples ESLint output 1`] = ` +"Incorrect + +const foo: { bar: number } | null = null; +const bar = foo!!!.bar; + ~~~~~ Forbidden extra non-null assertion. + ~~~~ Forbidden extra non-null assertion. +" +`; + +exports[`Validating rule docs no-extra-non-null-assertion.mdx code examples ESLint output 2`] = ` +"Incorrect + +function foo(bar: number | undefined) { + const bar: number = bar!!!; + ~~~~~ Forbidden extra non-null assertion. + ~~~~ Forbidden extra non-null assertion. +} +" +`; + +exports[`Validating rule docs no-extra-non-null-assertion.mdx code examples ESLint output 3`] = ` +"Incorrect + +function foo(bar?: { n: number }) { + return bar!?.n; + ~~~~ Forbidden extra non-null assertion. +} +" +`; + +exports[`Validating rule docs no-extra-non-null-assertion.mdx code examples ESLint output 4`] = ` +"Correct + +const foo: { bar: number } | null = null; +const bar = foo!.bar; +" +`; + +exports[`Validating rule docs no-extra-non-null-assertion.mdx code examples ESLint output 5`] = ` +"Correct + +function foo(bar: number | undefined) { + const bar: number = bar!; +} +" +`; + +exports[`Validating rule docs no-extra-non-null-assertion.mdx code examples ESLint output 6`] = ` +"Correct + +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..a7f12598ec21 --- /dev/null +++ b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-extraneous-class.shot @@ -0,0 +1,234 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Validating rule docs no-extraneous-class.mdx code examples ESLint output 1`] = ` +"Incorrect + +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[`Validating rule docs no-extraneous-class.mdx code examples ESLint output 2`] = ` +"Correct + +export const version = 42; + +export function isProduction() { + return process.env.NODE_ENV === 'production'; +} + +function logHelloWorld() { + console.log('Hello, world!'); +} +" +`; + +exports[`Validating rule docs no-extraneous-class.mdx code examples ESLint output 3`] = ` +"Incorrect + +export class Utilities { + ~~~~~~~~~ Unexpected class with only static properties. + static util1() { + return Utilities.util3(); + } + + static util2() { + /* ... */ + } + + static util3() { + /* ... */ + } +} +" +`; + +exports[`Validating rule docs no-extraneous-class.mdx code examples ESLint output 4`] = ` +"Correct + +export function util1() { + return util3(); +} + +export function util2() { + /* ... */ +} + +export function util3() { + /* ... */ +} +" +`; + +exports[`Validating rule docs no-extraneous-class.mdx code examples ESLint output 5`] = ` +"Incorrect + +// 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[`Validating rule docs no-extraneous-class.mdx code examples ESLint output 6`] = ` +" + +// utilities.ts +export function sayHello() { + console.log('Hello, world!'); +} + +// consumers.ts +import * as utilities from './utilities'; + +utilities.sayHello(); +" +`; + +exports[`Validating rule docs no-extraneous-class.mdx code examples ESLint output 7`] = ` +" + +// utilities.ts +export function sayHello() { + console.log('Hello, world!'); +} + +// consumers.ts +import { sayHello } from './utilities'; + +sayHello(); +" +`; + +exports[`Validating rule docs no-extraneous-class.mdx code examples ESLint output 8`] = ` +"Incorrect + +export class Utilities { + ~~~~~~~~~ Unexpected class with only static properties. + static mutableCount = 1; + + static incrementCount() { + Utilities.mutableCount += 1; + } +} +" +`; + +exports[`Validating rule docs no-extraneous-class.mdx code examples ESLint output 9`] = ` +"Correct + +let mutableCount = 1; + +export function getMutableCount() { + return mutableField; +} + +export function incrementCount() { + mutableField += 1; +} +" +`; + +exports[`Validating rule docs no-extraneous-class.mdx code examples ESLint output 10`] = ` +"Incorrect +Options: { "allowConstructorOnly": true } + +class NoFields {} + ~~~~~~~~ Unexpected empty class. +" +`; + +exports[`Validating rule docs no-extraneous-class.mdx code examples ESLint output 11`] = ` +"Correct +Options: { "allowConstructorOnly": true } + +class NoFields { + constructor() { + console.log('Hello, world!'); + } +} +" +`; + +exports[`Validating rule docs no-extraneous-class.mdx code examples ESLint output 12`] = ` +"Incorrect +Options: { "allowEmpty": true } + +class NoFields { + ~~~~~~~~ Unexpected class with only a constructor. + constructor() { + console.log('Hello, world!'); + } +} +" +`; + +exports[`Validating rule docs no-extraneous-class.mdx code examples ESLint output 13`] = ` +"Correct +Options: { "allowEmpty": true } + +class NoFields {} +" +`; + +exports[`Validating rule docs no-extraneous-class.mdx code examples ESLint output 14`] = ` +"Incorrect +Options: { "allowStaticOnly": true } + +class EmptyClass {} + ~~~~~~~~~~ Unexpected empty class. +" +`; + +exports[`Validating rule docs no-extraneous-class.mdx code examples ESLint output 15`] = ` +"Correct +Options: { "allowStaticOnly": true } + +class NotEmptyClass { + static version = 42; +} +" +`; + +exports[`Validating rule docs no-extraneous-class.mdx code examples ESLint output 16`] = ` +"Incorrect +Options: { "allowWithDecorator": true } + +class Constants { + ~~~~~~~~~ Unexpected class with only static properties. + static readonly version = 42; +} +" +`; + +exports[`Validating rule docs no-extraneous-class.mdx code examples ESLint output 17`] = ` +"Correct +Options: { "allowWithDecorator": true } + +@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..0dc935b52782 --- /dev/null +++ b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-floating-promises.shot @@ -0,0 +1,72 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Validating rule docs no-floating-promises.mdx code examples ESLint output 1`] = ` +"Incorrect + +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[`Validating rule docs no-floating-promises.mdx code examples ESLint output 2`] = ` +"Correct + +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[`Validating rule docs no-floating-promises.mdx code examples ESLint output 3`] = ` +"Options: { "ignoreVoid": true } + +async function returnsPromise() { + return 'value'; +} +void returnsPromise(); + +void Promise.reject('value'); +" +`; + +exports[`Validating rule docs no-floating-promises.mdx code examples ESLint output 4`] = ` +"Options: { "ignoreIIFE": true } + +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..e5f4312e8cf0 --- /dev/null +++ b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-for-in-array.shot @@ -0,0 +1,45 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Validating rule docs no-for-in-array.mdx code examples ESLint output 1`] = ` +"Incorrect + +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[`Validating rule docs no-for-in-array.mdx code examples ESLint output 2`] = ` +"Correct + +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..5f53ef702589 --- /dev/null +++ b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-implied-eval.shot @@ -0,0 +1,73 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Validating rule docs no-implied-eval.mdx code examples ESLint output 1`] = ` +"Incorrect + +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[`Validating rule docs no-implied-eval.mdx code examples ESLint output 2`] = ` +"Correct + +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..a97dde69584c --- /dev/null +++ b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-import-type-side-effects.shot @@ -0,0 +1,41 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Validating rule docs no-import-type-side-effects.mdx code examples ESLint output 1`] = ` +"Incorrect + +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[`Validating rule docs no-import-type-side-effects.mdx code examples ESLint output 2`] = ` +"Correct + +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..5e1c9f54e71f --- /dev/null +++ b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-inferrable-types.shot @@ -0,0 +1,97 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Validating rule docs no-inferrable-types.mdx code examples ESLint output 1`] = ` +"Incorrect + +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[`Validating rule docs no-inferrable-types.mdx code examples ESLint output 2`] = ` +"Correct + +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[`Validating rule docs no-inferrable-types.mdx code examples ESLint output 3`] = ` +"Options: { "ignoreParameters": true } + +function foo(a: number = 5, b: boolean = true) { + // ... +} +" +`; + +exports[`Validating rule docs no-inferrable-types.mdx code examples ESLint output 4`] = ` +"Options: { "ignoreProperties": true } + +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..bcfb2596c811 --- /dev/null +++ b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-invalid-void-type.shot @@ -0,0 +1,96 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Validating rule docs no-invalid-void-type.mdx code examples ESLint output 1`] = ` +"Incorrect + +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[`Validating rule docs no-invalid-void-type.mdx code examples ESLint output 2`] = ` +"Correct + +type NoOp = () => void; + +function noop(): void {} + +let trulyUndefined = void 0; + +async function promiseMeSomething(): Promise {} + +type stillVoid = void | never; +" +`; + +exports[`Validating rule docs no-invalid-void-type.mdx code examples ESLint output 3`] = ` +"Options: { "allowInGenericTypeArguments": false } + +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[`Validating rule docs no-invalid-void-type.mdx code examples ESLint output 4`] = ` +"Options: { "allowInGenericTypeArguments": ["Ex.Mx.Tx"] } + +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[`Validating rule docs no-invalid-void-type.mdx code examples ESLint output 5`] = ` +"Options: { "allowInGenericTypeArguments": ["Ex.Mx.Tx"] } + +type AllowedVoid = Ex.Mx.Tx; +type AllowedVoidUnion = void | Ex.Mx.Tx; +" +`; + +exports[`Validating rule docs no-invalid-void-type.mdx code examples ESLint output 6`] = ` +"Options: { "allowAsThisParameter": false } + +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..5d37a25cb7d2 --- /dev/null +++ b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-magic-numbers.shot @@ -0,0 +1,85 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Validating rule docs no-magic-numbers.mdx code examples ESLint output 1`] = ` +"Options: { "ignoreEnums": false } + +enum foo { + SECOND = 1000, + ~~~~ No magic number: 1000. +} +" +`; + +exports[`Validating rule docs no-magic-numbers.mdx code examples ESLint output 2`] = ` +"Options: { "ignoreEnums": true } + +enum foo { + SECOND = 1000, +} +" +`; + +exports[`Validating rule docs no-magic-numbers.mdx code examples ESLint output 3`] = ` +"Options: { "ignoreNumericLiteralTypes": false } + +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[`Validating rule docs no-magic-numbers.mdx code examples ESLint output 4`] = ` +"Options: { "ignoreNumericLiteralTypes": true } + +type SmallPrimes = 2 | 3 | 5 | 7 | 11; +" +`; + +exports[`Validating rule docs no-magic-numbers.mdx code examples ESLint output 5`] = ` +"Options: { "ignoreReadonlyClassProperties": false } + +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[`Validating rule docs no-magic-numbers.mdx code examples ESLint output 6`] = ` +"Options: { "ignoreReadonlyClassProperties": true } + +class Foo { + readonly A = 1; + readonly B = 2; + public static readonly C = 1; + static readonly D = 1; +} +" +`; + +exports[`Validating rule docs no-magic-numbers.mdx code examples ESLint output 7`] = ` +"Options: { "ignoreTypeIndexes": false } + +type Foo = Bar[0]; + ~ No magic number: 0. +type Baz = Parameters[2]; + ~ No magic number: 2. +" +`; + +exports[`Validating rule docs no-magic-numbers.mdx code examples ESLint output 8`] = ` +"Options: { "ignoreTypeIndexes": true } + +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..828f8a407bf6 --- /dev/null +++ b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-meaningless-void-operator.shot @@ -0,0 +1,29 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Validating rule docs no-meaningless-void-operator.mdx code examples ESLint output 1`] = ` +"Incorrect + +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[`Validating rule docs no-meaningless-void-operator.mdx code examples ESLint output 2`] = ` +"Correct + +(() => {})(); + +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..3610d01286b4 --- /dev/null +++ b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-misused-new.shot @@ -0,0 +1,31 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Validating rule docs no-misused-new.mdx code examples ESLint output 1`] = ` +"Incorrect + +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[`Validating rule docs no-misused-new.mdx code examples ESLint output 2`] = ` +"Correct + +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..3c1170e888c0 --- /dev/null +++ b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-misused-promises.shot @@ -0,0 +1,147 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Validating rule docs no-misused-promises.mdx code examples ESLint output 1`] = ` +"Incorrect +Options: { "checksConditionals": true } + +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[`Validating rule docs no-misused-promises.mdx code examples ESLint output 2`] = ` +"Correct +Options: { "checksConditionals": true } + +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[`Validating rule docs no-misused-promises.mdx code examples ESLint output 3`] = ` +"Incorrect +Options: { "checksVoidReturn": true } + +[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[`Validating rule docs no-misused-promises.mdx code examples ESLint output 4`] = ` +"Correct +Options: { "checksVoidReturn": true } + +// 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[`Validating rule docs no-misused-promises.mdx code examples ESLint output 5`] = ` +"Incorrect +Options: { "checksSpreads": true } + +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[`Validating rule docs no-misused-promises.mdx code examples ESLint output 6`] = ` +"Correct +Options: { "checksSpreads": true } + +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..66399740f725 --- /dev/null +++ b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-mixed-enums.shot @@ -0,0 +1,46 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Validating rule docs no-mixed-enums.mdx code examples ESLint output 1`] = ` +"Incorrect + +enum Status { + Unknown, + Closed = 1, + Open = 'open', + ~~~~~~ Mixing number and string enums can be confusing. +} +" +`; + +exports[`Validating rule docs no-mixed-enums.mdx code examples ESLint output 2`] = ` +"Correct + +enum Status { + Unknown = 0, + Closed = 1, + Open = 2, +} +" +`; + +exports[`Validating rule docs no-mixed-enums.mdx code examples ESLint output 3`] = ` +"Correct + +enum Status { + Unknown, + Closed, + Open, +} +" +`; + +exports[`Validating rule docs no-mixed-enums.mdx code examples ESLint output 4`] = ` +"Correct + +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..5e35be91c013 --- /dev/null +++ b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-namespace.shot @@ -0,0 +1,109 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Validating rule docs no-namespace.mdx code examples ESLint output 1`] = ` +"Incorrect + +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[`Validating rule docs no-namespace.mdx code examples ESLint output 2`] = ` +"Correct + +declare module 'foo' {} + +// anything inside a d.ts file +" +`; + +exports[`Validating rule docs no-namespace.mdx code examples ESLint output 3`] = ` +"Incorrect +Options: { "allowDeclarations": true } + +module foo {} +~~~~~~~~~~~~~ ES2015 module syntax is preferred over namespaces. +namespace foo {} +~~~~~~~~~~~~~~~~ ES2015 module syntax is preferred over namespaces. +" +`; + +exports[`Validating rule docs no-namespace.mdx code examples ESLint output 4`] = ` +"Correct +Options: { "allowDeclarations": true } + +declare module 'foo' {} +declare module foo {} +declare namespace foo {} + +declare global { + namespace foo {} +} + +declare module foo { + namespace foo {} +} +" +`; + +exports[`Validating rule docs no-namespace.mdx code examples ESLint output 5`] = ` +"Incorrect +Options: { "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[`Validating rule docs no-namespace.mdx code examples ESLint output 6`] = ` +"Correct +Options: { "allowDeclarations": false } + +declare module 'foo' {} +" +`; + +exports[`Validating rule docs no-namespace.mdx code examples ESLint output 7`] = ` +"Incorrect +Options: { "allowDefinitionFiles": true } + +// 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[`Validating rule docs no-namespace.mdx code examples ESLint output 8`] = ` +"Correct +Options: { "allowDefinitionFiles": true } + +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..c7cc504de64c --- /dev/null +++ b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-non-null-asserted-nullish-coalescing.shot @@ -0,0 +1,39 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Validating rule docs no-non-null-asserted-nullish-coalescing.mdx code examples ESLint output 1`] = ` +"Incorrect + +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[`Validating rule docs no-non-null-asserted-nullish-coalescing.mdx code examples ESLint output 2`] = ` +"Correct + +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..9baeb2235730 --- /dev/null +++ b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-non-null-asserted-optional-chain.shot @@ -0,0 +1,19 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Validating rule docs no-non-null-asserted-optional-chain.mdx code examples ESLint output 1`] = ` +"Incorrect + +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[`Validating rule docs no-non-null-asserted-optional-chain.mdx code examples ESLint output 2`] = ` +"Correct + +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..f9e86b9577f1 --- /dev/null +++ b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-non-null-assertion.shot @@ -0,0 +1,26 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Validating rule docs no-non-null-assertion.mdx code examples ESLint output 1`] = ` +"Incorrect + +interface Example { + property?: string; +} + +declare const example: Example; +const includesBaz = example.property!.includes('baz'); + ~~~~~~~~~~~~~~~~~ Forbidden non-null assertion. +" +`; + +exports[`Validating rule docs no-non-null-assertion.mdx code examples ESLint output 2`] = ` +"Correct + +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..11d7834f6664 --- /dev/null +++ b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-redeclare.shot @@ -0,0 +1,37 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Validating rule docs no-redeclare.mdx code examples ESLint output 1`] = ` +"Options: { "ignoreDeclarationMerge": true } + +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[`Validating rule docs no-redeclare.mdx code examples ESLint output 2`] = ` +"Options: { "ignoreDeclarationMerge": true } + +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..6e9d59111d4a --- /dev/null +++ b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-redundant-type-constituents.shot @@ -0,0 +1,55 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Validating rule docs no-redundant-type-constituents.mdx code examples ESLint output 1`] = ` +"Incorrect + +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[`Validating rule docs no-redundant-type-constituents.mdx code examples ESLint output 2`] = ` +"Correct + +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..027cb637f45c --- /dev/null +++ b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-require-imports.shot @@ -0,0 +1,39 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Validating rule docs no-require-imports.mdx code examples ESLint output 1`] = ` +"Incorrect + +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[`Validating rule docs no-require-imports.mdx code examples ESLint output 2`] = ` +"Correct + +import * as lib1 from 'lib1'; +import { lib2 } from 'lib2'; +import * as lib3 from 'lib3'; +" +`; + +exports[`Validating rule docs no-require-imports.mdx code examples ESLint output 3`] = ` +"Incorrect +Options: { "allow": ["/package.json$"] } + +console.log(require('../data.json').version); + ~~~~~~~~~~~~~~~~~~~~~~~ A \`require()\` style import is forbidden. +" +`; + +exports[`Validating rule docs no-require-imports.mdx code examples ESLint output 4`] = ` +"Correct +Options: { "allow": ["/package.json$"] } + +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..bb0ceec3541a --- /dev/null +++ b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-restricted-imports.shot @@ -0,0 +1,31 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Validating rule docs no-restricted-imports.mdx code examples ESLint output 1`] = ` +"Incorrect +Options: {"paths":[{"name":"import-foo","message":"Please use import-bar instead.","allowTypeImports":true},{"name":"import-baz","message":"Please use import-quux instead.","allowTypeImports":true}]} + +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[`Validating rule docs no-restricted-imports.mdx code examples ESLint output 2`] = ` +"Correct +Options: {"paths":[{"name":"import-foo","message":"Please use import-bar instead.","allowTypeImports":true},{"name":"import-baz","message":"Please use import-quux instead.","allowTypeImports":true}]} + +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..46c8fe00fb7d --- /dev/null +++ b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-shadow.shot @@ -0,0 +1,24 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Validating rule docs no-shadow.mdx code examples ESLint output 1`] = ` +"Options: { "ignoreTypeValueShadow": true } + +type Foo = number; +interface Bar { + prop: number; +} + +function f() { + const Foo = 1; + const Bar = 'test'; +} +" +`; + +exports[`Validating rule docs no-shadow.mdx code examples ESLint output 2`] = ` +"Options: { "ignoreFunctionTypeParameterNameValueShadow": true } + +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..a4893cd22e7f --- /dev/null +++ b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-this-alias.shot @@ -0,0 +1,82 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Validating rule docs no-this-alias.mdx code examples ESLint output 1`] = ` +"Incorrect + +const self = this; + ~~~~ Unexpected aliasing of 'this' to local variable. + +setTimeout(function () { + self.doWork(); +}); +" +`; + +exports[`Validating rule docs no-this-alias.mdx code examples ESLint output 2`] = ` +"Correct + +setTimeout(() => { + this.doWork(); +}); +" +`; + +exports[`Validating rule docs no-this-alias.mdx code examples ESLint output 3`] = ` +"Incorrect +Options: { "allowDestructuring": false } + +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[`Validating rule docs no-this-alias.mdx code examples ESLint output 4`] = ` +"Correct +Options: { "allowDestructuring": false } + +class ComponentLike { + props: unknown; + state: unknown; + + render() { + console.log(this.props); + console.log(this.state); + } +} +" +`; + +exports[`Validating rule docs no-this-alias.mdx code examples ESLint output 5`] = ` +"Incorrect +Options: { "allowedNames": ["self"] } + +class Example { + method() { + const that = this; + ~~~~ Unexpected aliasing of 'this' to local variable. + } +} +" +`; + +exports[`Validating rule docs no-this-alias.mdx code examples ESLint output 6`] = ` +"Correct +Options: { "allowedNames": ["self"] } + +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..71c60ea2ec68 --- /dev/null +++ b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-throw-literal.shot @@ -0,0 +1,78 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Validating rule docs no-throw-literal.md code examples ESLint output snapshot 1`] = ` +"Incorrect + +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[`Validating rule docs no-throw-literal.md code examples ESLint output snapshot 2`] = ` +"Correct + +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..395801423b91 --- /dev/null +++ b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-type-alias.shot @@ -0,0 +1,553 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Validating rule docs no-type-alias.mdx code examples ESLint output 1`] = ` +"Options: { "allowAliases": "always" } + +// 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[`Validating rule docs no-type-alias.mdx code examples ESLint output 2`] = ` +"Options: { "allowAliases": "in-unions" } + +// 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[`Validating rule docs no-type-alias.mdx code examples ESLint output 3`] = ` +"Options: { "allowAliases": "in-unions" } + +// 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[`Validating rule docs no-type-alias.mdx code examples ESLint output 4`] = ` +"Options: { "allowAliases": "in-intersections" } + +// 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[`Validating rule docs no-type-alias.mdx code examples ESLint output 5`] = ` +"Options: { "allowAliases": "in-intersections" } + +// primitives +type Foo = string & string[]; + +type Foo = \`a-\${number}\` & \`b-\${number}\`; + +// reference types +interface Bar {} +class Baz implements Bar {} + +type Foo = Bar & Baz; +" +`; + +exports[`Validating rule docs no-type-alias.mdx code examples ESLint output 6`] = ` +"Options: { "allowAliases": "in-unions-and-intersections" } + +// 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[`Validating rule docs no-type-alias.mdx code examples ESLint output 7`] = ` +"Options: { "allowAliases": "in-unions-and-intersections" } + +// 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[`Validating rule docs no-type-alias.mdx code examples ESLint output 8`] = ` +"Options: { "allowCallbacks": "always" } + +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[`Validating rule docs no-type-alias.mdx code examples ESLint output 9`] = ` +"Options: { "allowConditionalTypes": "always" } + +type Foo = T extends number ? number : null; +" +`; + +exports[`Validating rule docs no-type-alias.mdx code examples ESLint output 10`] = ` +"Options: { "allowConstructors": "always" } + +type Foo = new () => void; +" +`; + +exports[`Validating rule docs no-type-alias.mdx code examples ESLint output 11`] = ` +"Options: { "allowLiterals": "always" } + +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[`Validating rule docs no-type-alias.mdx code examples ESLint output 12`] = ` +"Options: { "allowLiterals": "in-unions" } + +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[`Validating rule docs no-type-alias.mdx code examples ESLint output 13`] = ` +"Options: { "allowLiterals": "in-unions" } + +type Foo = { name: string } | { age: number }; +" +`; + +exports[`Validating rule docs no-type-alias.mdx code examples ESLint output 14`] = ` +"Options: { "allowLiterals": "in-intersections" } + +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[`Validating rule docs no-type-alias.mdx code examples ESLint output 15`] = ` +"Options: { "allowLiterals": "in-intersections" } + +type Foo = { name: string } & { age: number }; +" +`; + +exports[`Validating rule docs no-type-alias.mdx code examples ESLint output 16`] = ` +"Options: { "allowLiterals": "in-unions-and-intersections" } + +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[`Validating rule docs no-type-alias.mdx code examples ESLint output 17`] = ` +"Options: { "allowLiterals": "in-unions-and-intersections" } + +type Foo = { name: string } | { age: number }; + +type Foo = { name: string } & { age: number }; +" +`; + +exports[`Validating rule docs no-type-alias.mdx code examples ESLint output 18`] = ` +"Options: { "allowMappedTypes": "always" } + +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[`Validating rule docs no-type-alias.mdx code examples ESLint output 19`] = ` +"Options: { "allowMappedTypes": "in-unions" } + +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[`Validating rule docs no-type-alias.mdx code examples ESLint output 20`] = ` +"Options: { "allowMappedTypes": "in-unions" } + +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[`Validating rule docs no-type-alias.mdx code examples ESLint output 21`] = ` +"Options: { "allowMappedTypes": "in-intersections" } + +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[`Validating rule docs no-type-alias.mdx code examples ESLint output 22`] = ` +"Options: { "allowMappedTypes": "in-intersections" } + +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[`Validating rule docs no-type-alias.mdx code examples ESLint output 23`] = ` +"Options: { "allowMappedTypes": "in-unions-and-intersections" } + +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[`Validating rule docs no-type-alias.mdx code examples ESLint output 24`] = ` +"Options: { "allowMappedTypes": "in-unions-and-intersections" } + +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[`Validating rule docs no-type-alias.mdx code examples ESLint output 25`] = ` +"Options: { "allowTupleTypes": "always" } + +type Foo = [number]; + +type Foo = [number] | [number, number]; + +type Foo = [number] & [number, number]; + +type Foo = [number] | ([number, number] & [string, string]); +" +`; + +exports[`Validating rule docs no-type-alias.mdx code examples ESLint output 26`] = ` +"Options: { "allowTupleTypes": "in-unions" } + +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[`Validating rule docs no-type-alias.mdx code examples ESLint output 27`] = ` +"Options: { "allowTupleTypes": "in-unions" } + +type Foo = [number] | [number, number]; + +type Foo = [string] | [number]; +" +`; + +exports[`Validating rule docs no-type-alias.mdx code examples ESLint output 28`] = ` +"Options: { "allowTupleTypes": "in-intersections" } + +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[`Validating rule docs no-type-alias.mdx code examples ESLint output 29`] = ` +"Options: { "allowTupleTypes": "in-intersections" } + +type Foo = [number] & [number, number]; + +type Foo = [string] & [number]; +" +`; + +exports[`Validating rule docs no-type-alias.mdx code examples ESLint output 30`] = ` +"Options: { "allowTupleTypes": "in-unions-and-intersections" } + +type Foo = [number]; + ~~~~~~~~ Type tuple types are not allowed. + +type Foo = [string]; + ~~~~~~~~ Type tuple types are not allowed. +" +`; + +exports[`Validating rule docs no-type-alias.mdx code examples ESLint output 31`] = ` +"Options: { "allowTupleTypes": "in-unions-and-intersections" } + +type Foo = [number] & [number, number]; + +type Foo = [string] | [number]; +" +`; + +exports[`Validating rule docs no-type-alias.mdx code examples ESLint output 32`] = ` +"Options: { "allowGenerics": "always" } + +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..3397a172781a --- /dev/null +++ b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-unnecessary-boolean-literal-compare.shot @@ -0,0 +1,88 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Validating rule docs no-unnecessary-boolean-literal-compare.mdx code examples ESLint output 1`] = ` +"Incorrect + +declare const someCondition: boolean; +if (someCondition === true) { + ~~~~~~~~~~~~~~~~~~~~~~ This expression unnecessarily compares a boolean value to a boolean instead of using it directly. +} +" +`; + +exports[`Validating rule docs no-unnecessary-boolean-literal-compare.mdx code examples ESLint output 2`] = ` +"Correct + +declare const someCondition: boolean; +if (someCondition) { +} + +declare const someObjectBoolean: boolean | Record; +if (someObjectBoolean === true) { +} + +declare const someStringBoolean: boolean | string; +if (someStringBoolean === true) { +} +" +`; + +exports[`Validating rule docs no-unnecessary-boolean-literal-compare.mdx code examples ESLint output 3`] = ` +"Incorrect +Options: { "allowComparingNullableBooleansToTrue": false } + +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[`Validating rule docs no-unnecessary-boolean-literal-compare.mdx code examples ESLint output 4`] = ` +"Correct +Options: { "allowComparingNullableBooleansToTrue": false } + +declare const someUndefinedCondition: boolean | undefined; +if (someUndefinedCondition) { +} + +declare const someNullCondition: boolean | null; +if (!someNullCondition) { +} +" +`; + +exports[`Validating rule docs no-unnecessary-boolean-literal-compare.mdx code examples ESLint output 5`] = ` +"Incorrect +Options: { "allowComparingNullableBooleansToFalse": false } + +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[`Validating rule docs no-unnecessary-boolean-literal-compare.mdx code examples ESLint output 6`] = ` +"Correct +Options: { "allowComparingNullableBooleansToFalse": false } + +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..508ffbe028f6 --- /dev/null +++ b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-unnecessary-condition.shot @@ -0,0 +1,68 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Validating rule docs no-unnecessary-condition.mdx code examples ESLint output 1`] = ` +"Incorrect + +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[`Validating rule docs no-unnecessary-condition.mdx code examples ESLint output 2`] = ` +"Correct + +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[`Validating rule docs no-unnecessary-condition.mdx code examples ESLint output 3`] = ` +"Options: { "allowConstantLoopConditions": true } + +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..df1f421b2b20 --- /dev/null +++ b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-unnecessary-qualifier.shot @@ -0,0 +1,43 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Validating rule docs no-unnecessary-qualifier.mdx code examples ESLint output 1`] = ` +"Incorrect + +enum A { + B, + C = A.B, + ~ Qualifier is unnecessary since 'B' is in scope. +} +" +`; + +exports[`Validating rule docs no-unnecessary-qualifier.mdx code examples ESLint output 2`] = ` +"Incorrect + +namespace A { + export type B = number; + const x: A.B = 3; + ~ Qualifier is unnecessary since 'B' is in scope. +} +" +`; + +exports[`Validating rule docs no-unnecessary-qualifier.mdx code examples ESLint output 3`] = ` +"Correct + +enum A { + B, + C = B, +} +" +`; + +exports[`Validating rule docs no-unnecessary-qualifier.mdx code examples ESLint output 4`] = ` +"Correct + +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..5f564985f373 --- /dev/null +++ b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-unnecessary-type-arguments.shot @@ -0,0 +1,78 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Validating rule docs no-unnecessary-type-arguments.mdx code examples ESLint output 1`] = ` +"Incorrect + +function f() {} +f(); + ~~~~~~ This is the default value for this type parameter, so it can be omitted. +" +`; + +exports[`Validating rule docs no-unnecessary-type-arguments.mdx code examples ESLint output 2`] = ` +"Incorrect + +function g() {} +g(); + ~~~~~~ This is the default value for this type parameter, so it can be omitted. +" +`; + +exports[`Validating rule docs no-unnecessary-type-arguments.mdx code examples ESLint output 3`] = ` +"Incorrect + +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[`Validating rule docs no-unnecessary-type-arguments.mdx code examples ESLint output 4`] = ` +"Incorrect + +interface I {} +class Impl implements I {} + ~~~~~~ This is the default value for this type parameter, so it can be omitted. +" +`; + +exports[`Validating rule docs no-unnecessary-type-arguments.mdx code examples ESLint output 5`] = ` +"Correct + +function f() {} +f(); +f(); +" +`; + +exports[`Validating rule docs no-unnecessary-type-arguments.mdx code examples ESLint output 6`] = ` +"Correct + +function g() {} +g(); +g(); +" +`; + +exports[`Validating rule docs no-unnecessary-type-arguments.mdx code examples ESLint output 7`] = ` +"Correct + +class C {} +new C(); +new C(); + +class D extends C {} +class D extends C {} +" +`; + +exports[`Validating rule docs no-unnecessary-type-arguments.mdx code examples ESLint output 8`] = ` +"Correct + +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..707826df3e1b --- /dev/null +++ b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-unnecessary-type-assertion.shot @@ -0,0 +1,92 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Validating rule docs no-unnecessary-type-assertion.mdx code examples ESLint output 1`] = ` +"Incorrect + +const foo = 3; +const bar = foo!; + ~~~~ This assertion is unnecessary since it does not change the type of the expression. +" +`; + +exports[`Validating rule docs no-unnecessary-type-assertion.mdx code examples ESLint output 2`] = ` +"Incorrect + +const foo = (3 + 5); + ~~~~~~~~~~~~~~~ This assertion is unnecessary since it does not change the type of the expression. +" +`; + +exports[`Validating rule docs no-unnecessary-type-assertion.mdx code examples ESLint output 3`] = ` +"Incorrect + +type Foo = number; +const foo = (3 + 5); + ~~~~~~~~~~~~ This assertion is unnecessary since it does not change the type of the expression. +" +`; + +exports[`Validating rule docs no-unnecessary-type-assertion.mdx code examples ESLint output 4`] = ` +"Incorrect + +type Foo = number; +const foo = (3 + 5) as Foo; + ~~~~~~~~~~~~~~ This assertion is unnecessary since it does not change the type of the expression. +" +`; + +exports[`Validating rule docs no-unnecessary-type-assertion.mdx code examples ESLint output 5`] = ` +"Incorrect + +const foo = 'foo' as const; + ~~~~~~~~~~~~~~ This assertion is unnecessary since it does not change the type of the expression. +" +`; + +exports[`Validating rule docs no-unnecessary-type-assertion.mdx code examples ESLint output 6`] = ` +"Incorrect + +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[`Validating rule docs no-unnecessary-type-assertion.mdx code examples ESLint output 7`] = ` +"Correct + +const foo = 3; +" +`; + +exports[`Validating rule docs no-unnecessary-type-assertion.mdx code examples ESLint output 8`] = ` +"Correct + +const foo = 3 as number; +" +`; + +exports[`Validating rule docs no-unnecessary-type-assertion.mdx code examples ESLint output 9`] = ` +"Correct + +let foo = 'foo' as const; +" +`; + +exports[`Validating rule docs no-unnecessary-type-assertion.mdx code examples ESLint output 10`] = ` +"Correct + +function foo(x: number | undefined): number { + return x!; +} +" +`; + +exports[`Validating rule docs no-unnecessary-type-assertion.mdx code examples ESLint output 11`] = ` +"Options: { "typesToIgnore": ["Foo"] } + +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..aee6e71498d7 --- /dev/null +++ b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-unnecessary-type-constraint.shot @@ -0,0 +1,47 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Validating rule docs no-unnecessary-type-constraint.mdx code examples ESLint output 1`] = ` +"Incorrect + +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[`Validating rule docs no-unnecessary-type-constraint.mdx code examples ESLint output 2`] = ` +"Correct + +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..5faa832727bc --- /dev/null +++ b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-unsafe-argument.shot @@ -0,0 +1,62 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Validating rule docs no-unsafe-argument.mdx code examples ESLint output 1`] = ` +"Incorrect + +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[`Validating rule docs no-unsafe-argument.mdx code examples ESLint output 2`] = ` +"Correct + +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[`Validating rule docs no-unsafe-argument.mdx code examples ESLint output 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..2e1b94899b68 --- /dev/null +++ b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-unsafe-assignment.shot @@ -0,0 +1,73 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Validating rule docs no-unsafe-assignment.mdx code examples ESLint output 1`] = ` +"Incorrect + +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[`Validating rule docs no-unsafe-assignment.mdx code examples ESLint output 2`] = ` +"Correct + +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[`Validating rule docs no-unsafe-assignment.mdx code examples ESLint output 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..bfc1388d6cf9 --- /dev/null +++ b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-unsafe-call.shot @@ -0,0 +1,46 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Validating rule docs no-unsafe-call.mdx code examples ESLint output 1`] = ` +"Incorrect + +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[`Validating rule docs no-unsafe-call.mdx code examples ESLint output 2`] = ` +"Correct + +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..839899b7bfce --- /dev/null +++ b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-unsafe-declaration-merging.shot @@ -0,0 +1,27 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Validating rule docs no-unsafe-declaration-merging.mdx code examples ESLint output 1`] = ` +"Incorrect + +interface Foo {} + ~~~ Unsafe declaration merging between classes and interfaces. + +class Foo {} + ~~~ Unsafe declaration merging between classes and interfaces. +" +`; + +exports[`Validating rule docs no-unsafe-declaration-merging.mdx code examples ESLint output 2`] = ` +"Correct + +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..2d883379f083 --- /dev/null +++ b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-unsafe-enum-comparison.shot @@ -0,0 +1,55 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Validating rule docs no-unsafe-enum-comparison.mdx code examples ESLint output 1`] = ` +"Incorrect + +enum Fruit { + Apple, +} + +declare let fruit: Fruit; + +fruit === 0; +~~~~~~~~~~~ The two values in this comparison do not have a shared enum type. +" +`; + +exports[`Validating rule docs no-unsafe-enum-comparison.mdx code examples ESLint output 2`] = ` +"Incorrect + +enum Vegetable { + Asparagus = 'asparagus', +} + +declare let vegetable: Vegetable; + +vegetable === 'asparagus'; +~~~~~~~~~~~~~~~~~~~~~~~~~ The two values in this comparison do not have a shared enum type. +" +`; + +exports[`Validating rule docs no-unsafe-enum-comparison.mdx code examples ESLint output 3`] = ` +"Correct + +enum Fruit { + Apple, +} + +declare let fruit: Fruit; + +fruit === Fruit.Apple; +" +`; + +exports[`Validating rule docs no-unsafe-enum-comparison.mdx code examples ESLint output 4`] = ` +"Correct + +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..33b46a7e5921 --- /dev/null +++ b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-unsafe-member-access.shot @@ -0,0 +1,53 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Validating rule docs no-unsafe-member-access.mdx code examples ESLint output 1`] = ` +"Incorrect + +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[`Validating rule docs no-unsafe-member-access.mdx code examples ESLint output 2`] = ` +"Correct + +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..e645fdcbb568 --- /dev/null +++ b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-unsafe-return.shot @@ -0,0 +1,90 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Validating rule docs no-unsafe-return.mdx code examples ESLint output 1`] = ` +"Incorrect + +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[`Validating rule docs no-unsafe-return.mdx code examples ESLint output 2`] = ` +"Correct + +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[`Validating rule docs no-unsafe-return.mdx code examples ESLint output 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-unsafe-unary-minus.shot b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-unsafe-unary-minus.shot new file mode 100644 index 000000000000..da02e428b2c1 --- /dev/null +++ b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-unsafe-unary-minus.shot @@ -0,0 +1,37 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Validating rule docs no-unsafe-unary-minus.mdx code examples ESLint output 1`] = ` +"Incorrect + +declare const a: string; +-a; +~~ Argument of unary negation should be assignable to number | bigint but is string instead. + +declare const b: {}; +-b; +~~ Argument of unary negation should be assignable to number | bigint but is {} instead. +" +`; + +exports[`Validating rule docs no-unsafe-unary-minus.mdx code examples ESLint output 2`] = ` +"Correct + +-42; +-42n; + +declare const a: number; +-a; + +declare const b: number; +-b; + +declare const c: number | bigint; +-c; + +declare const d: any; +-d; + +declare const e: 1 | 2; +-e; +" +`; 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..1efd72d47170 --- /dev/null +++ b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-use-before-define.shot @@ -0,0 +1,47 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Validating rule docs no-use-before-define.mdx code examples ESLint output 1`] = ` +"Incorrect +Options: { "enums": true } + +const x = Foo.FOO; + ~~~ 'Foo' was used before it was defined. + +enum Foo { + FOO, +} +" +`; + +exports[`Validating rule docs no-use-before-define.mdx code examples ESLint output 2`] = ` +"Correct +Options: { "enums": false } + +function foo() { + return Foo.FOO; +} + +enum Foo { + FOO, +} +" +`; + +exports[`Validating rule docs no-use-before-define.mdx code examples ESLint output 3`] = ` +"Options: { "typedefs": false } + +let myVar: StringOrNumber; +type StringOrNumber = string | number; +" +`; + +exports[`Validating rule docs no-use-before-define.mdx code examples ESLint output 4`] = ` +"Options: { "ignoreTypeReferences": true } + +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..d495e2a1c2c9 --- /dev/null +++ b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-useless-empty-export.shot @@ -0,0 +1,33 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Validating rule docs no-useless-empty-export.mdx code examples ESLint output 1`] = ` +"Incorrect + +export const value = 'Hello, world!'; +export {}; +~~~~~~~~~~ Empty export does nothing and can be removed. +" +`; + +exports[`Validating rule docs no-useless-empty-export.mdx code examples ESLint output 2`] = ` +"Incorrect + +import 'some-other-module'; +export {}; +~~~~~~~~~~ Empty export does nothing and can be removed. +" +`; + +exports[`Validating rule docs no-useless-empty-export.mdx code examples ESLint output 3`] = ` +"Correct + +export const value = 'Hello, world!'; +" +`; + +exports[`Validating rule docs no-useless-empty-export.mdx code examples ESLint output 4`] = ` +"Correct + +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..3cc841703a98 --- /dev/null +++ b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-useless-template-literals.shot @@ -0,0 +1,46 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Validating rule docs no-useless-template-literals.mdx code examples ESLint output 1`] = ` +"Incorrect + +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[`Validating rule docs no-useless-template-literals.mdx code examples ESLint output 2`] = ` +"Correct + +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..8acb5b5d8a8c --- /dev/null +++ b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-var-requires.shot @@ -0,0 +1,39 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Validating rule docs no-var-requires.mdx code examples ESLint output 1`] = ` +"Incorrect + +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[`Validating rule docs no-var-requires.mdx code examples ESLint output 2`] = ` +"Correct + +import foo = require('foo'); +require('foo'); +import foo from 'foo'; +" +`; + +exports[`Validating rule docs no-var-requires.mdx code examples ESLint output 3`] = ` +"Incorrect +Options: { "allow": ["/package.json$"] } + +const foo = require('../data.json'); + ~~~~~~~~~~~~~~~~~~~~~~~ Require statement not part of import statement. +" +`; + +exports[`Validating rule docs no-var-requires.mdx code examples ESLint output 4`] = ` +"Correct +Options: { "allow": ["/package.json$"] } + +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..ee2425e935bd --- /dev/null +++ b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/non-nullable-type-assertion-style.shot @@ -0,0 +1,23 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Validating rule docs non-nullable-type-assertion-style.mdx code examples ESLint output 1`] = ` +"Incorrect + +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[`Validating rule docs non-nullable-type-assertion-style.mdx code examples ESLint output 2`] = ` +"Correct + +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/only-throw-error.shot b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/only-throw-error.shot new file mode 100644 index 000000000000..ad4deada2a9b --- /dev/null +++ b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/only-throw-error.shot @@ -0,0 +1,77 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Validating rule docs only-throw-error.mdx code examples ESLint output 1`] = ` +"Incorrect + +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 err = new Error(); +throw 'an ' + err; + ~~~~~~~~~~~ Expected an error object to be thrown. + +const err = new Error(); +throw \`\${err}\`; + ~~~~~~~~ Expected an error object to be thrown. + +const err = ''; +throw err; + +function getError() { + return ''; +} +throw getError(); + ~~~~~~~~~~ Expected an error object to be thrown. + +const foo = { + bar: '', +}; +throw foo.bar; + ~~~~~~~ Expected an error object to be thrown. +" +`; + +exports[`Validating rule docs only-throw-error.mdx code examples ESLint output 2`] = ` +"Correct + +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 getError() { + return new Error(); +} +throw getError(); + +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/parameter-properties.shot b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/parameter-properties.shot new file mode 100644 index 000000000000..0f7b87e16c60 --- /dev/null +++ b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/parameter-properties.shot @@ -0,0 +1,458 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Validating rule docs parameter-properties.mdx code examples ESLint output 1`] = ` +"Incorrect + +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[`Validating rule docs parameter-properties.mdx code examples ESLint output 2`] = ` +"Correct + +class Foo { + constructor(name: string) {} +} +" +`; + +exports[`Validating rule docs parameter-properties.mdx code examples ESLint output 3`] = ` +"Incorrect +Options: { "allow": ["readonly"] } + +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[`Validating rule docs parameter-properties.mdx code examples ESLint output 4`] = ` +"Correct +Options: { "allow": ["readonly"] } + +class Foo { + constructor(name: string) {} +} + +class Foo { + constructor(readonly name: string) {} +} +" +`; + +exports[`Validating rule docs parameter-properties.mdx code examples ESLint output 5`] = ` +"Incorrect +Options: { "allow": ["private"] } + +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[`Validating rule docs parameter-properties.mdx code examples ESLint output 6`] = ` +"Correct +Options: { "allow": ["private"] } + +class Foo { + constructor(name: string) {} +} + +class Foo { + constructor(private name: string) {} +} +" +`; + +exports[`Validating rule docs parameter-properties.mdx code examples ESLint output 7`] = ` +"Incorrect +Options: { "allow": ["protected"] } + +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[`Validating rule docs parameter-properties.mdx code examples ESLint output 8`] = ` +"Correct +Options: { "allow": ["protected"] } + +class Foo { + constructor(name: string) {} +} + +class Foo { + constructor(protected name: string) {} +} +" +`; + +exports[`Validating rule docs parameter-properties.mdx code examples ESLint output 9`] = ` +"Incorrect +Options: { "allow": ["public"] } + +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[`Validating rule docs parameter-properties.mdx code examples ESLint output 10`] = ` +"Correct +Options: { "allow": ["public"] } + +class Foo { + constructor(name: string) {} +} + +class Foo { + constructor(public name: string) {} +} +" +`; + +exports[`Validating rule docs parameter-properties.mdx code examples ESLint output 11`] = ` +"Incorrect +Options: { "allow": ["private readonly"] } + +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[`Validating rule docs parameter-properties.mdx code examples ESLint output 12`] = ` +"Correct +Options: { "allow": ["private readonly"] } + +class Foo { + constructor(name: string) {} +} + +class Foo { + constructor(private readonly name: string) {} +} +" +`; + +exports[`Validating rule docs parameter-properties.mdx code examples ESLint output 13`] = ` +"Incorrect +Options: { "allow": ["protected readonly"] } + +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[`Validating rule docs parameter-properties.mdx code examples ESLint output 14`] = ` +"Correct +Options: { "allow": ["protected readonly"] } + +class Foo { + constructor(name: string) {} +} + +class Foo { + constructor(protected readonly name: string) {} +} +" +`; + +exports[`Validating rule docs parameter-properties.mdx code examples ESLint output 15`] = ` +"Incorrect +Options: { "allow": ["public readonly"] } + +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[`Validating rule docs parameter-properties.mdx code examples ESLint output 16`] = ` +"Correct +Options: { "allow": ["public readonly"] } + +class Foo { + constructor(name: string) {} +} + +class Foo { + constructor(public readonly name: string) {} +} +" +`; + +exports[`Validating rule docs parameter-properties.mdx code examples ESLint output 17`] = ` +"Incorrect +Options: { "prefer": "parameter-property" } + +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[`Validating rule docs parameter-properties.mdx code examples ESLint output 18`] = ` +"Correct +Options: { "prefer": "parameter-property" } + +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..77a86c948cab --- /dev/null +++ b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/prefer-as-const.shot @@ -0,0 +1,25 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Validating rule docs prefer-as-const.mdx code examples ESLint output 1`] = ` +"Incorrect + +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[`Validating rule docs prefer-as-const.mdx code examples ESLint output 2`] = ` +"Correct + +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..1bfbe107afa2 --- /dev/null +++ b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/prefer-destructuring.shot @@ -0,0 +1,50 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Validating rule docs prefer-destructuring.mdx code examples ESLint output 1`] = ` +" + +const x: string = obj.x; // This is incorrect and the auto fixer provides following untyped fix. +// const { x } = obj; +" +`; + +exports[`Validating rule docs prefer-destructuring.mdx code examples ESLint output 2`] = ` +" + +const x: string = obj.x; // This is correct by default. You can also forbid this by an option. +" +`; + +exports[`Validating rule docs prefer-destructuring.mdx code examples ESLint output 3`] = ` +"Incorrect + +const x = ['a']; +const y = x[0]; + ~~~~~~~~ Use array destructuring. +" +`; + +exports[`Validating rule docs prefer-destructuring.mdx code examples ESLint output 4`] = ` +"Correct + +const x = { 0: 'a' }; +const y = x[0]; +" +`; + +exports[`Validating rule docs prefer-destructuring.mdx code examples ESLint output 5`] = ` +"Incorrect +Options: { "object": true }, { "enforceForDeclarationWithTypeAnnotation": true } + +const x: string = obj.x; + ~~~~~~~~~~~~~~~~~ Use object destructuring. +" +`; + +exports[`Validating rule docs prefer-destructuring.mdx code examples ESLint output 6`] = ` +"Correct +Options: { "object": true }, { "enforceForDeclarationWithTypeAnnotation": true } + +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..38bd92861600 --- /dev/null +++ b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/prefer-enum-initializers.shot @@ -0,0 +1,47 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Validating rule docs prefer-enum-initializers.mdx code examples ESLint output 1`] = ` +"Incorrect + +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[`Validating rule docs prefer-enum-initializers.mdx code examples ESLint output 2`] = ` +"Correct + +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..2e759cc12ef1 --- /dev/null +++ b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/prefer-find.shot @@ -0,0 +1,19 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Validating rule docs prefer-find.mdx code examples ESLint output 1`] = ` +"Incorrect + +[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[`Validating rule docs prefer-find.mdx code examples ESLint output 2`] = ` +"Correct + +[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..b717c78c985a --- /dev/null +++ b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/prefer-for-of.shot @@ -0,0 +1,31 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Validating rule docs prefer-for-of.mdx code examples ESLint output 1`] = ` +"Incorrect + +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[`Validating rule docs prefer-for-of.mdx code examples ESLint output 2`] = ` +"Correct + +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..6c667353e44b --- /dev/null +++ b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/prefer-function-type.shot @@ -0,0 +1,90 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Validating rule docs prefer-function-type.mdx code examples ESLint output 1`] = ` +"Incorrect + +interface Example { + (): string; + ~~~~~~~~~~~ Interface only has a call signature, you should use a function type instead. +} +" +`; + +exports[`Validating rule docs prefer-function-type.mdx code examples ESLint output 2`] = ` +"Incorrect + +function foo(example: { (): number }): number { + ~~~~~~~~~~ Type literal only has a call signature, you should use a function type instead. + return example(); +} +" +`; + +exports[`Validating rule docs prefer-function-type.mdx code examples ESLint output 3`] = ` +"Incorrect + +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[`Validating rule docs prefer-function-type.mdx code examples ESLint output 4`] = ` +"Correct + +type Example = () => string; +" +`; + +exports[`Validating rule docs prefer-function-type.mdx code examples ESLint output 5`] = ` +"Correct + +function foo(example: () => number): number { + return bar(); +} +" +`; + +exports[`Validating rule docs prefer-function-type.mdx code examples ESLint output 6`] = ` +"Correct + +// returns the function itself, not the \`this\` argument. +type ReturnsSelf = (arg: string) => ReturnsSelf; +" +`; + +exports[`Validating rule docs prefer-function-type.mdx code examples ESLint output 7`] = ` +"Correct + +function foo(bar: { (): string; baz: number }): string { + return bar(); +} +" +`; + +exports[`Validating rule docs prefer-function-type.mdx code examples ESLint output 8`] = ` +"Correct + +interface Foo { + bar: string; +} +interface Bar extends Foo { + (): void; +} +" +`; + +exports[`Validating rule docs prefer-function-type.mdx code examples ESLint output 9`] = ` +"Correct + +// 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..bcf38889434b --- /dev/null +++ b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/prefer-includes.shot @@ -0,0 +1,62 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Validating rule docs prefer-includes.mdx code examples ESLint output 1`] = ` +"Incorrect + +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[`Validating rule docs prefer-includes.mdx code examples ESLint output 2`] = ` +"Correct + +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..c9938b4bbb47 --- /dev/null +++ b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/prefer-literal-enum-member.shot @@ -0,0 +1,72 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Validating rule docs prefer-literal-enum-member.mdx code examples ESLint output 1`] = ` +"Incorrect + +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[`Validating rule docs prefer-literal-enum-member.mdx code examples ESLint output 2`] = ` +"Correct + +enum Valid { + A, + B = 'TestStr', // A regular string + C = 4, // A number + D = null, + E = /some_regex/, +} +" +`; + +exports[`Validating rule docs prefer-literal-enum-member.mdx code examples ESLint output 3`] = ` +"Incorrect +Options: { "allowBitwiseExpressions": true } + +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[`Validating rule docs prefer-literal-enum-member.mdx code examples ESLint output 4`] = ` +"Correct +Options: { "allowBitwiseExpressions": true } + +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..5ee0588681aa --- /dev/null +++ b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/prefer-namespace-keyword.shot @@ -0,0 +1,18 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Validating rule docs prefer-namespace-keyword.mdx code examples ESLint output 1`] = ` +"Incorrect + +module Example {} +~~~~~~~~~~~~~~~~~ Use 'namespace' instead of 'module' to declare custom TypeScript modules. +" +`; + +exports[`Validating rule docs prefer-namespace-keyword.mdx code examples ESLint output 2`] = ` +"Correct + +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..d2c8afaf5096 --- /dev/null +++ b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/prefer-nullish-coalescing.shot @@ -0,0 +1,138 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Validating rule docs prefer-nullish-coalescing.mdx code examples ESLint output 1`] = ` +"Options: { "ignoreTernaryTests": false } + +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[`Validating rule docs prefer-nullish-coalescing.mdx code examples ESLint output 2`] = ` +"Options: { "ignoreTernaryTests": false } + +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[`Validating rule docs prefer-nullish-coalescing.mdx code examples ESLint output 3`] = ` +"Options: { "ignoreConditionalTests": false } + +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[`Validating rule docs prefer-nullish-coalescing.mdx code examples ESLint output 4`] = ` +"Options: { "ignoreConditionalTests": false } + +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[`Validating rule docs prefer-nullish-coalescing.mdx code examples ESLint output 5`] = ` +"Options: { "ignoreMixedLogicalExpressions": false } + +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[`Validating rule docs prefer-nullish-coalescing.mdx code examples ESLint output 6`] = ` +"Options: { "ignoreMixedLogicalExpressions": false } + +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[`Validating rule docs prefer-nullish-coalescing.mdx code examples ESLint output 7`] = ` +"Options: { "ignorePrimitives": { "string": true } } + +const foo: string | undefined = 'bar'; +foo || 'a string'; +" +`; + +exports[`Validating rule docs prefer-nullish-coalescing.mdx code examples ESLint output 8`] = ` +"Options: { "ignorePrimitives": { "string": true } } + +const foo: string | undefined = 'bar'; +foo ?? 'a string'; +" +`; diff --git a/packages/eslint-plugin/tests/docs-eslint-output-snapshots/prefer-optional-chain.shot b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/prefer-optional-chain.shot new file mode 100644 index 000000000000..36130171307f --- /dev/null +++ b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/prefer-optional-chain.shot @@ -0,0 +1,218 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Validating rule docs prefer-optional-chain.mdx code examples ESLint output 1`] = ` +"Incorrect + +foo && foo.a && foo.a.b && foo.a.b.c; +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Prefer using an optional chain expression instead, as it's more concise and easier to read. +foo && foo['a'] && foo['a'].b && foo['a'].b.c; +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Prefer using an optional chain expression instead, as it's more concise and easier to read. +foo && foo.a && foo.a.b && foo.a.b.method && foo.a.b.method(); +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Prefer using an optional chain expression instead, as it's more concise and easier to read. + +// With empty objects +(((foo || {}).a || {}).b || {}).c; +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Prefer using an optional chain expression instead, as it's more concise and easier to read. + ~~~~~~~~~~~~~~~~~~~~~~~ Prefer using an optional chain expression instead, as it's more concise and easier to read. + ~~~~~~~~~~~~~ Prefer using an optional chain expression instead, as it's more concise and easier to read. +(((foo || {})['a'] || {}).b || {}).c; +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Prefer using an optional chain expression instead, as it's more concise and easier to read. + ~~~~~~~~~~~~~~~~~~~~~~~~~~ Prefer using an optional chain expression instead, as it's more concise and easier to read. + ~~~~~~~~~~~~~~~~ Prefer using an optional chain expression instead, as it's more concise and easier to read. + +// With negated \`or\`s +!foo || !foo.bar; +~~~~~~~~~~~~~~~~ Prefer using an optional chain expression instead, as it's more concise and easier to read. +!foo || !foo[bar]; +~~~~~~~~~~~~~~~~~ Prefer using an optional chain expression instead, as it's more concise and easier to read. +!foo || !foo.bar || !foo.bar.baz || !foo.bar.baz(); +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Prefer using an optional chain expression instead, as it's more concise and easier to read. + +// this rule also supports converting chained strict nullish checks: +foo && +~~~~~~ Prefer using an optional chain expression instead, as it's more concise and easier to read. + foo.a != null && +~~~~~~~~~~~~~~~ + foo.a.b !== null && + foo.a.b.c != undefined && + foo.a.b.c.d !== undefined && + foo.a.b.c.d.e; +" +`; + +exports[`Validating rule docs prefer-optional-chain.mdx code examples ESLint output 2`] = ` +"Correct + +foo?.a?.b?.c; +foo?.['a']?.b?.c; +foo?.a?.b?.method?.(); + +foo?.a?.b?.c?.d?.e; + +!foo?.bar; +!foo?.[bar]; +!foo?.bar?.baz?.(); +" +`; + +exports[`Validating rule docs prefer-optional-chain.mdx code examples ESLint output 3`] = ` +"Options: { "allowPotentiallyUnsafeFixesThatModifyTheReturnTypeIKnowWhatImDoing": true } + +declare const foo: { bar: boolean } | null | undefined; +declare function acceptsBoolean(arg: boolean): void; + +// ✅ typechecks succesfully as the expression only returns \`boolean\` +acceptsBoolean(foo != null && foo.bar); + ~~~~~~~~~~~~~~~~~~~~~~ Prefer using an optional chain expression instead, as it's more concise and easier to read. + +// ❌ typechecks UNSUCCESSFULLY as the expression returns \`boolean | undefined\` +acceptsBoolean(foo?.bar); +" +`; + +exports[`Validating rule docs prefer-optional-chain.mdx code examples ESLint output 4`] = ` +"Incorrect +Options: { "checkAny": true } + +declare const thing: any; + +thing && thing.toString(); +~~~~~~~~~~~~~~~~~~~~~~~~~ Prefer using an optional chain expression instead, as it's more concise and easier to read. +" +`; + +exports[`Validating rule docs prefer-optional-chain.mdx code examples ESLint output 5`] = ` +"Correct +Options: { "checkAny": false } + +declare const thing: any; + +thing && thing.toString(); +" +`; + +exports[`Validating rule docs prefer-optional-chain.mdx code examples ESLint output 6`] = ` +"Incorrect +Options: { "checkUnknown": true } + +declare const thing: unknown; + +thing && thing.toString(); +~~~~~~~~~~~~~~~~~~~~~~~~~ Prefer using an optional chain expression instead, as it's more concise and easier to read. +" +`; + +exports[`Validating rule docs prefer-optional-chain.mdx code examples ESLint output 7`] = ` +"Correct +Options: { "checkUnknown": false } + +declare const thing: unknown; + +thing && thing.toString(); +" +`; + +exports[`Validating rule docs prefer-optional-chain.mdx code examples ESLint output 8`] = ` +"Incorrect +Options: { "checkString": true } + +declare const thing: string; + +thing && thing.toString(); +~~~~~~~~~~~~~~~~~~~~~~~~~ Prefer using an optional chain expression instead, as it's more concise and easier to read. +" +`; + +exports[`Validating rule docs prefer-optional-chain.mdx code examples ESLint output 9`] = ` +"Correct +Options: { "checkString": false } + +declare const thing: string; + +thing && thing.toString(); +" +`; + +exports[`Validating rule docs prefer-optional-chain.mdx code examples ESLint output 10`] = ` +"Incorrect +Options: { "checkNumber": true } + +declare const thing: number; + +thing && thing.toString(); +~~~~~~~~~~~~~~~~~~~~~~~~~ Prefer using an optional chain expression instead, as it's more concise and easier to read. +" +`; + +exports[`Validating rule docs prefer-optional-chain.mdx code examples ESLint output 11`] = ` +"Correct +Options: { "checkNumber": false } + +declare const thing: number; + +thing && thing.toString(); +" +`; + +exports[`Validating rule docs prefer-optional-chain.mdx code examples ESLint output 12`] = ` +"Incorrect +Options: { "checkBoolean": true } + +declare const thing: true; + +thing && thing.toString(); +~~~~~~~~~~~~~~~~~~~~~~~~~ Prefer using an optional chain expression instead, as it's more concise and easier to read. +" +`; + +exports[`Validating rule docs prefer-optional-chain.mdx code examples ESLint output 13`] = ` +"Correct +Options: { "checkBoolean": false } + +declare const thing: true; + +thing && thing.toString(); +" +`; + +exports[`Validating rule docs prefer-optional-chain.mdx code examples ESLint output 14`] = ` +"Incorrect +Options: { "checkBigInt": true } + +declare const thing: bigint; + +thing && thing.toString(); +~~~~~~~~~~~~~~~~~~~~~~~~~ Prefer using an optional chain expression instead, as it's more concise and easier to read. +" +`; + +exports[`Validating rule docs prefer-optional-chain.mdx code examples ESLint output 15`] = ` +"Correct +Options: { "checkBigInt": false } + +declare const thing: bigint; + +thing && thing.toString(); +" +`; + +exports[`Validating rule docs prefer-optional-chain.mdx code examples ESLint output 16`] = ` +"Incorrect +Options: { "requireNullish": true } + +declare const thing1: string | null; +thing1 && thing1.toString(); +" +`; + +exports[`Validating rule docs prefer-optional-chain.mdx code examples ESLint output 17`] = ` +"Correct +Options: { "requireNullish": true } + +declare const thing1: string | null; +thing1?.toString(); + +declare const thing2: string; +thing2 && thing2.toString(); +" +`; 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..70508e175842 --- /dev/null +++ b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/prefer-promise-reject-errors.shot @@ -0,0 +1,43 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Validating rule docs prefer-promise-reject-errors.mdx code examples ESLint output 1`] = ` +"Incorrect + +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[`Validating rule docs prefer-promise-reject-errors.mdx code examples ESLint output 2`] = ` +"Correct + +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-parameter-types.shot b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/prefer-readonly-parameter-types.shot new file mode 100644 index 000000000000..606039e2e781 --- /dev/null +++ b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/prefer-readonly-parameter-types.shot @@ -0,0 +1,358 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Validating rule docs prefer-readonly-parameter-types.mdx code examples ESLint output 1`] = ` +"Incorrect + +function array1(arg: string[]) {} // array is not readonly + ~~~~~~~~~~~~~ Parameter should be a read only type. +function array2(arg: readonly string[][]) {} // array element is not readonly + ~~~~~~~~~~~~~~~~~~~~~~~~ Parameter should be a read only type. +function array3(arg: [string, number]) {} // tuple is not readonly + ~~~~~~~~~~~~~~~~~~~~~ Parameter should be a read only type. +function array4(arg: readonly [string[], number]) {} // tuple element is not readonly + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Parameter should be a read only type. +// the above examples work the same if you use ReadonlyArray instead + +function object1(arg: { prop: string }) {} // property is not readonly + ~~~~~~~~~~~~~~~~~~~~~ Parameter should be a read only type. +function object2(arg: { readonly prop: string; prop2: string }) {} // not all properties are readonly + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Parameter should be a read only type. +function object3(arg: { readonly prop: { prop2: string } }) {} // nested property is not readonly + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Parameter should be a read only type. +// the above examples work the same if you use Readonly instead + +interface CustomArrayType extends ReadonlyArray { + prop: string; // note: this property is mutable +} +function custom1(arg: CustomArrayType) {} + ~~~~~~~~~~~~~~~~~~~~ Parameter should be a read only type. + +interface CustomFunction { + (): void; + prop: string; // note: this property is mutable +} +function custom2(arg: CustomFunction) {} + ~~~~~~~~~~~~~~~~~~~ Parameter should be a read only type. + +function union(arg: string[] | ReadonlyArray) {} // not all types are readonly + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Parameter should be a read only type. + +// rule also checks function types +interface Foo { + (arg: string[]): void; + ~~~~~~~~~~~~~ Parameter should be a read only type. +} +interface Foo { + new (arg: string[]): void; + ~~~~~~~~~~~~~ Parameter should be a read only type. +} +const x = { foo(arg: string[]): void {} }; + ~~~~~~~~~~~~~ Parameter should be a read only type. +function foo(arg: string[]); + ~~~~~~~~~~~~~ Parameter should be a read only type. +type Foo = (arg: string[]) => void; + ~~~~~~~~~~~~~ Parameter should be a read only type. +interface Foo { + foo(arg: string[]): void; + ~~~~~~~~~~~~~ Parameter should be a read only type. +} +" +`; + +exports[`Validating rule docs prefer-readonly-parameter-types.mdx code examples ESLint output 2`] = ` +"Correct + +function array1(arg: readonly string[]) {} +function array2(arg: readonly (readonly string[])[]) {} +function array3(arg: readonly [string, number]) {} +function array4(arg: readonly [readonly string[], number]) {} +// the above examples work the same if you use ReadonlyArray instead + +function object1(arg: { readonly prop: string }) {} +function object2(arg: { readonly prop: string; readonly prop2: string }) {} +function object3(arg: { readonly prop: { readonly prop2: string } }) {} +// the above examples work the same if you use Readonly instead + +interface CustomArrayType extends ReadonlyArray { + readonly prop: string; +} +function custom1(arg: Readonly) {} +// interfaces that extend the array types are not considered arrays, and thus must be made readonly. + +interface CustomFunction { + (): void; + readonly prop: string; +} +function custom2(arg: CustomFunction) {} + +function union(arg: readonly string[] | ReadonlyArray) {} + +function primitive1(arg: string) {} +function primitive2(arg: number) {} +function primitive3(arg: boolean) {} +function primitive4(arg: unknown) {} +function primitive5(arg: null) {} +function primitive6(arg: undefined) {} +function primitive7(arg: any) {} +function primitive8(arg: never) {} +function primitive9(arg: string | number | undefined) {} + +function fnSig(arg: () => void) {} + +enum Foo { + a, + b, +} +function enumArg(arg: Foo) {} + +function symb1(arg: symbol) {} +const customSymbol = Symbol('a'); +function symb2(arg: typeof customSymbol) {} + +// function types +interface Foo { + (arg: readonly string[]): void; +} +interface Foo { + new (arg: readonly string[]): void; +} +const x = { foo(arg: readonly string[]): void {} }; +function foo(arg: readonly string[]); +type Foo = (arg: readonly string[]) => void; +interface Foo { + foo(arg: readonly string[]): void; +} +" +`; + +exports[`Validating rule docs prefer-readonly-parameter-types.mdx code examples ESLint output 3`] = ` +"Incorrect +Options: {"allow":["$",{"from":"file","name":"Foo"},{"from":"lib","name":"HTMLElement"},{"from":"package","name":"Bar","package":"bar-lib"}]} + +interface ThisIsMutable { + prop: string; +} + +interface Wrapper { + sub: ThisIsMutable; +} + +interface WrapperWithOther { + readonly sub: Foo; + otherProp: string; +} + +// Incorrect because ThisIsMutable is not readonly +function fn1(arg: ThisIsMutable) {} + ~~~~~~~~~~~~~~~~~~ Parameter should be a read only type. + +// Incorrect because Wrapper.sub is not readonly +function fn2(arg: Wrapper) {} + ~~~~~~~~~~~~ Parameter should be a read only type. + +// Incorrect because WrapperWithOther.otherProp is not readonly and not in the allowlist +function fn3(arg: WrapperWithOther) {} + ~~~~~~~~~~~~~~~~~~~~~ Parameter should be a read only type. +" +`; + +exports[`Validating rule docs prefer-readonly-parameter-types.mdx code examples ESLint output 4`] = ` +"Incorrect +Options: {"allow":["$",{"from":"file","name":"Foo"},{"from":"lib","name":"HTMLElement"},{"from":"package","name":"Bar","package":"bar-lib"}]} + +import { Foo } from 'some-lib'; +import { Bar } from 'incorrect-lib'; + +interface HTMLElement { + prop: string; +} + +// Incorrect because Foo is not a local type +function fn1(arg: Foo) {} + +// Incorrect because HTMLElement is not from the default library +function fn2(arg: HTMLElement) {} + ~~~~~~~~~~~~~~~~ Parameter should be a read only type. + +// Incorrect because Bar is not from "bar-lib" +function fn3(arg: Bar) {} +" +`; + +exports[`Validating rule docs prefer-readonly-parameter-types.mdx code examples ESLint output 5`] = ` +"Correct +Options: {"allow":["$",{"from":"file","name":"Foo"},{"from":"lib","name":"HTMLElement"},{"from":"package","name":"Bar","package":"bar-lib"}]} + +interface Foo { + prop: string; +} + +interface Wrapper { + readonly sub: Foo; + readonly otherProp: string; +} + +// Works because Foo is allowed +function fn1(arg: Foo) {} + +// Works even when Foo is nested somewhere in the type, with other properties still being checked +function fn2(arg: Wrapper) {} +" +`; + +exports[`Validating rule docs prefer-readonly-parameter-types.mdx code examples ESLint output 6`] = ` +"Correct +Options: {"allow":["$",{"from":"file","name":"Foo"},{"from":"lib","name":"HTMLElement"},{"from":"package","name":"Bar","package":"bar-lib"}]} + +import { Bar } from 'bar-lib'; + +interface Foo { + prop: string; +} + +// Works because Foo is a local type +function fn1(arg: Foo) {} + +// Works because HTMLElement is from the default library +function fn2(arg: HTMLElement) {} + +// Works because Bar is from "bar-lib" +function fn3(arg: Bar) {} +" +`; + +exports[`Validating rule docs prefer-readonly-parameter-types.mdx code examples ESLint output 7`] = ` +"Correct +Options: {"allow":["$",{"from":"file","name":"Foo"},{"from":"lib","name":"HTMLElement"},{"from":"package","name":"Bar","package":"bar-lib"}]} + +import { Foo } from './foo'; + +// Works because Foo is still a local type - it has to be in the same package +function fn(arg: Foo) {} +" +`; + +exports[`Validating rule docs prefer-readonly-parameter-types.mdx code examples ESLint output 8`] = ` +"Incorrect +Options: { "checkParameterProperties": true } + +class Foo { + constructor(private paramProp: string[]) {} + ~~~~~~~~~~~~~~~~~~~ Parameter should be a read only type. +} +" +`; + +exports[`Validating rule docs prefer-readonly-parameter-types.mdx code examples ESLint output 9`] = ` +"Correct +Options: { "checkParameterProperties": true } + +class Foo { + constructor(private paramProp: readonly string[]) {} +} +" +`; + +exports[`Validating rule docs prefer-readonly-parameter-types.mdx code examples ESLint output 10`] = ` +"Options: { "checkParameterProperties": false } + +class Foo { + constructor( + private paramProp1: string[], + private paramProp2: readonly string[], + ) {} +} +" +`; + +exports[`Validating rule docs prefer-readonly-parameter-types.mdx code examples ESLint output 11`] = ` +"Incorrect +Options: { "ignoreInferredTypes": true } + +import { acceptsCallback, CallbackOptions } from 'external-dependency'; + +acceptsCallback((options: CallbackOptions) => {}); +" +`; + +exports[`Validating rule docs prefer-readonly-parameter-types.mdx code examples ESLint output 12`] = ` +"Incorrect +Options: { "ignoreInferredTypes": true } + +export interface CallbackOptions { + prop: string; +} +type Callback = (options: CallbackOptions) => void; + ~~~~~~~~~~~~~~~~~~~~~~~~ Parameter should be a read only type. +type AcceptsCallback = (callback: Callback) => void; + +export const acceptsCallback: AcceptsCallback; +" +`; + +exports[`Validating rule docs prefer-readonly-parameter-types.mdx code examples ESLint output 13`] = ` +"Correct +Options: { "ignoreInferredTypes": true } + +import { acceptsCallback } from 'external-dependency'; + +acceptsCallback(options => {}); +" +`; + +exports[`Validating rule docs prefer-readonly-parameter-types.mdx code examples ESLint output 14`] = ` +"Correct +Options: { "ignoreInferredTypes": true } + +export interface CallbackOptions { + prop: string; +} +type Callback = (options: CallbackOptions) => void; + ~~~~~~~~~~~~~~~~~~~~~~~~ Parameter should be a read only type. +type AcceptsCallback = (callback: Callback) => void; + +export const acceptsCallback: AcceptsCallback; +" +`; + +exports[`Validating rule docs prefer-readonly-parameter-types.mdx code examples ESLint output 15`] = ` +"Incorrect +Options: { "treatMethodsAsReadonly": false } + +type MyType = { + readonly prop: string; + method(): string; // note: this method is mutable +}; +function foo(arg: MyType) {} + ~~~~~~~~~~~ Parameter should be a read only type. +" +`; + +exports[`Validating rule docs prefer-readonly-parameter-types.mdx code examples ESLint output 16`] = ` +"Correct +Options: { "treatMethodsAsReadonly": false } + +type MyType = Readonly<{ + prop: string; + method(): string; +}>; +function foo(arg: MyType) {} + +type MyOtherType = { + readonly prop: string; + readonly method: () => string; +}; +function bar(arg: MyOtherType) {} +" +`; + +exports[`Validating rule docs prefer-readonly-parameter-types.mdx code examples ESLint output 17`] = ` +"Options: { "treatMethodsAsReadonly": true } + +type MyType = { + readonly prop: string; + method(): string; // note: this method is mutable +}; +function foo(arg: MyType) {} +" +`; 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..375126979792 --- /dev/null +++ b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/prefer-readonly.shot @@ -0,0 +1,77 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Validating rule docs prefer-readonly.mdx code examples ESLint output 1`] = ` +"Incorrect + +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[`Validating rule docs prefer-readonly.mdx code examples ESLint output 2`] = ` +"Correct + +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[`Validating rule docs prefer-readonly.mdx code examples ESLint output 3`] = ` +"Incorrect +Options: { "onlyInlineLambdas": true } + +class Container { + private onClick = () => { + ~~~~~~~~~~~~~~~~~~~~~~~~~ Member 'onClick' is never reassigned; mark it as \`readonly\`. + /* ... */ +~~~~~~~~~~~~~ + }; +~~~~ +} +" +`; + +exports[`Validating rule docs prefer-readonly.mdx code examples ESLint output 4`] = ` +"Correct +Options: { "onlyInlineLambdas": true } + +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..5babf0ea8978 --- /dev/null +++ b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/prefer-reduce-type-parameter.shot @@ -0,0 +1,33 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Validating rule docs prefer-reduce-type-parameter.mdx code examples ESLint output 1`] = ` +"Incorrect + +[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[`Validating rule docs prefer-reduce-type-parameter.mdx code examples ESLint output 2`] = ` +"Correct + +[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..c9f37ea12f90 --- /dev/null +++ b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/prefer-regexp-exec.shot @@ -0,0 +1,30 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Validating rule docs prefer-regexp-exec.mdx code examples ESLint output 1`] = ` +"Incorrect + +'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[`Validating rule docs prefer-regexp-exec.mdx code examples ESLint output 2`] = ` +"Correct + +/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..a8341c971317 --- /dev/null +++ b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/prefer-return-this-type.shot @@ -0,0 +1,47 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Validating rule docs prefer-return-this-type.mdx code examples ESLint output 1`] = ` +"Incorrect + +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[`Validating rule docs prefer-return-this-type.mdx code examples ESLint output 2`] = ` +"Correct + +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..f6b0142f5c9c --- /dev/null +++ b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/prefer-string-starts-ends-with.shot @@ -0,0 +1,65 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Validating rule docs prefer-string-starts-ends-with.mdx code examples ESLint output 1`] = ` +"Incorrect + +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[`Validating rule docs prefer-string-starts-ends-with.mdx code examples ESLint output 2`] = ` +"Correct + +declare const foo: string; + +// starts with +foo.startsWith('bar'); + +// ends with +foo.endsWith('bar'); +" +`; + +exports[`Validating rule docs prefer-string-starts-ends-with.mdx code examples ESLint output 3`] = ` +"Options: { "allowSingleElementEquality": "always" } + +declare const text: string; + +text[0] === 'a'; +text[0] === text[0].toUpperCase(); +text[0] === text[1]; +text[text.length - 1] === 'b'; +" +`; 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..c5d83ea67289 --- /dev/null +++ b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/prefer-ts-expect-error.shot @@ -0,0 +1,52 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Validating rule docs prefer-ts-expect-error.mdx code examples ESLint output 1`] = ` +"Incorrect + +// @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[`Validating rule docs prefer-ts-expect-error.mdx code examples ESLint output 2`] = ` +"Correct + +// @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..0c91850303e9 --- /dev/null +++ b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/promise-function-async.shot @@ -0,0 +1,79 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Validating rule docs promise-function-async.mdx code examples ESLint output 1`] = ` +"Incorrect + +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[`Validating rule docs promise-function-async.mdx code examples ESLint output 2`] = ` +"Correct + +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[`Validating rule docs promise-function-async.mdx code examples ESLint output 3`] = ` +"Incorrect +Options: { "allowAny": false } + +const returnsAny = () => ({}) as any; + ~~ Functions that return promises must be async. +" +`; + +exports[`Validating rule docs promise-function-async.mdx code examples ESLint output 4`] = ` +"Correct +Options: { "allowAny": false } + +const returnsAny = async () => ({}) as any; +" +`; + +exports[`Validating rule docs promise-function-async.mdx code examples ESLint output 5`] = ` +"Incorrect +Options: { "allowedPromiseNames": ["Bluebird"] } + +class Bluebird {} + +const returnsBluebird = () => new Bluebird(() => {}); + ~~ Functions that return promises must be async. +" +`; + +exports[`Validating rule docs promise-function-async.mdx code examples ESLint output 6`] = ` +"Correct +Options: { "allowedPromiseNames": ["Bluebird"] } + +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..2b5225cc362f --- /dev/null +++ b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/require-array-sort-compare.shot @@ -0,0 +1,51 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Validating rule docs require-array-sort-compare.mdx code examples ESLint output 1`] = ` +"Incorrect + +const array: any[]; +const stringArray: string[]; + +array.sort(); +~~~~~~~~~~~~ Require 'compare' argument. + +// String arrays should be sorted using \`String#localeCompare\`. +stringArray.sort(); +" +`; + +exports[`Validating rule docs require-array-sort-compare.mdx code examples ESLint output 2`] = ` +"Correct + +const array: any[]; +const userDefinedType: { sort(): void }; + +array.sort((a, b) => a - b); +array.sort((a, b) => a.localeCompare(b)); + +userDefinedType.sort(); +" +`; + +exports[`Validating rule docs require-array-sort-compare.mdx code examples ESLint output 3`] = ` +"Incorrect +Options: { "ignoreStringArrays": true } + +const one = 1; +const two = 2; +const three = 3; +[one, two, three].sort(); +~~~~~~~~~~~~~~~~~~~~~~~~ Require 'compare' argument. +" +`; + +exports[`Validating rule docs require-array-sort-compare.mdx code examples ESLint output 4`] = ` +"Correct +Options: { "ignoreStringArrays": true } + +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..ca837d02b8c9 --- /dev/null +++ b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/restrict-plus-operands.shot @@ -0,0 +1,148 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Validating rule docs restrict-plus-operands.mdx code examples ESLint output 1`] = ` +"Incorrect + +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[`Validating rule docs restrict-plus-operands.mdx code examples ESLint output 2`] = ` +"Correct + +let foo = 1n + 1n; +let fn = (a: string, b: string) => a + b; +" +`; + +exports[`Validating rule docs restrict-plus-operands.mdx code examples ESLint output 3`] = ` +"Incorrect +Options: { "allowAny": true } + +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[`Validating rule docs restrict-plus-operands.mdx code examples ESLint output 4`] = ` +"Correct +Options: { "allowAny": true } + +let fn = (a: number, b: any) => a + b; +let fn = (a: string, b: any) => a + b; +" +`; + +exports[`Validating rule docs restrict-plus-operands.mdx code examples ESLint output 5`] = ` +"Incorrect +Options: { "allowBoolean": true } + +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[`Validating rule docs restrict-plus-operands.mdx code examples ESLint output 6`] = ` +"Correct +Options: { "allowBoolean": true } + +let fn = (a: number, b: boolean) => a + b; +let fn = (a: string, b: boolean) => a + b; +" +`; + +exports[`Validating rule docs restrict-plus-operands.mdx code examples ESLint output 7`] = ` +"Incorrect +Options: { "allowNullish": true } + +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[`Validating rule docs restrict-plus-operands.mdx code examples ESLint output 8`] = ` +"Correct +Options: { "allowNullish": true } + +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[`Validating rule docs restrict-plus-operands.mdx code examples ESLint output 9`] = ` +"Incorrect +Options: { "allowNumberAndString": true } + +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[`Validating rule docs restrict-plus-operands.mdx code examples ESLint output 10`] = ` +"Correct +Options: { "allowNumberAndString": true } + +let fn = (a: number, b: string) => a + b; +let fn = (a: number, b: number | string) => a + b; +" +`; + +exports[`Validating rule docs restrict-plus-operands.mdx code examples ESLint output 11`] = ` +"Incorrect +Options: { "allowRegExp": true } + +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[`Validating rule docs restrict-plus-operands.mdx code examples ESLint output 12`] = ` +"Correct +Options: { "allowRegExp": true } + +let fn = (a: string, b: RegExp) => a + b; +" +`; + +exports[`Validating rule docs restrict-plus-operands.mdx code examples ESLint output 13`] = ` +"Incorrect +Options: { "skipCompoundAssignments": false } + +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[`Validating rule docs restrict-plus-operands.mdx code examples ESLint output 14`] = ` +"Correct +Options: { "skipCompoundAssignments": false } + +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..06f982288ebc --- /dev/null +++ b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/restrict-template-expressions.shot @@ -0,0 +1,93 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Validating rule docs restrict-template-expressions.mdx code examples ESLint output 1`] = ` +"Incorrect + +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[`Validating rule docs restrict-template-expressions.mdx code examples ESLint output 2`] = ` +"Correct + +const arg = 'foo'; +const msg1 = \`arg = \${arg}\`; +const msg2 = \`arg = \${arg || 'default'}\`; + +const stringWithKindProp: string & { _kind?: 'MyString' } = 'foo'; +const msg3 = \`stringWithKindProp = \${stringWithKindProp}\`; +" +`; + +exports[`Validating rule docs restrict-template-expressions.mdx code examples ESLint output 3`] = ` +"Options: { "allowNumber": true } + +const arg = 123; +const msg1 = \`arg = \${arg}\`; +const msg2 = \`arg = \${arg || 'zero'}\`; +" +`; + +exports[`Validating rule docs restrict-template-expressions.mdx code examples ESLint output 4`] = ` +"Options: { "allowBoolean": true } + +const arg = true; +const msg1 = \`arg = \${arg}\`; +const msg2 = \`arg = \${arg || 'not truthy'}\`; +" +`; + +exports[`Validating rule docs restrict-template-expressions.mdx code examples ESLint output 5`] = ` +"Options: { "allowAny": true } + +const user = JSON.parse('{ "name": "foo" }'); +const msg1 = \`arg = \${user.name}\`; +const msg2 = \`arg = \${user.name || 'the user with no name'}\`; +" +`; + +exports[`Validating rule docs restrict-template-expressions.mdx code examples ESLint output 6`] = ` +"Options: { "allowNullish": true } + +const arg = condition ? 'ok' : null; +const msg1 = \`arg = \${arg}\`; +" +`; + +exports[`Validating rule docs restrict-template-expressions.mdx code examples ESLint output 7`] = ` +"Options: { "allowRegExp": true } + +const arg = new RegExp('foo'); +const msg1 = \`arg = \${arg}\`; +" +`; + +exports[`Validating rule docs restrict-template-expressions.mdx code examples ESLint output 8`] = ` +"Options: { "allowRegExp": true } + +const arg = /foo/; +const msg1 = \`arg = \${arg}\`; +" +`; + +exports[`Validating rule docs restrict-template-expressions.mdx code examples ESLint output 9`] = ` +"Options: { "allowNever": true } + +const arg = 'something'; +const msg1 = typeof arg === 'string' ? arg : \`arg = \${arg}\`; +" +`; + +exports[`Validating rule docs restrict-template-expressions.mdx code examples ESLint output 10`] = ` +"Options: { "allowArray": true } + +const arg = ['foo', 'bar']; +const msg1 = \`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..bc0d087ad505 --- /dev/null +++ b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/return-await.shot @@ -0,0 +1,187 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Validating rule docs return-await.mdx code examples ESLint output 1`] = ` +"Incorrect +Options: "in-try-catch" + +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[`Validating rule docs return-await.mdx code examples ESLint output 2`] = ` +"Correct +Options: "in-try-catch" + +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[`Validating rule docs return-await.mdx code examples ESLint output 3`] = ` +"Incorrect +Options: "always" + +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[`Validating rule docs return-await.mdx code examples ESLint output 4`] = ` +"Correct +Options: "always" + +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[`Validating rule docs return-await.mdx code examples ESLint output 5`] = ` +"Incorrect +Options: "never" + +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[`Validating rule docs return-await.mdx code examples ESLint output 6`] = ` +"Correct +Options: "never" + +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..5f814b118459 --- /dev/null +++ b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/sort-type-constituents.shot @@ -0,0 +1,135 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Validating rule docs sort-type-constituents.mdx code examples ESLint output 1`] = ` +"Incorrect + +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[`Validating rule docs sort-type-constituents.mdx code examples ESLint output 2`] = ` +"Correct + +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[`Validating rule docs sort-type-constituents.mdx code examples ESLint output 3`] = ` +"Incorrect +Options: { "checkIntersections": true } + +type ExampleIntersection = B & A; + ~~~~~ Intersection type ExampleIntersection constituents must be sorted. +" +`; + +exports[`Validating rule docs sort-type-constituents.mdx code examples ESLint output 4`] = ` +"Correct +Options: { "checkIntersections": true } + +type ExampleIntersection = A & B; +" +`; + +exports[`Validating rule docs sort-type-constituents.mdx code examples ESLint output 5`] = ` +"Incorrect +Options: { "checkUnions": true } + +type ExampleUnion = B | A; + ~~~~~ Union type ExampleUnion constituents must be sorted. +" +`; + +exports[`Validating rule docs sort-type-constituents.mdx code examples ESLint output 6`] = ` +"Correct +Options: { "checkUnions": true } + +type ExampleUnion = A | B; +" +`; + +exports[`Validating rule docs sort-type-constituents.mdx code examples ESLint output 7`] = ` +"Incorrect +Options: { "groupOrder": ["literal", "nullish" ]} + +type ExampleGroup = null | 123; + ~~~~~~~~~~ Union type ExampleGroup constituents must be sorted. +" +`; + +exports[`Validating rule docs sort-type-constituents.mdx code examples ESLint output 8`] = ` +"Correct +Options: { "groupOrder": ["literal", "nullish" ]} + +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..74158461fac1 --- /dev/null +++ b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/space-before-blocks.shot @@ -0,0 +1,33 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Validating rule docs space-before-blocks.mdx code examples ESLint output 1`] = ` +"Incorrect + +enum Breakpoint{ + ~ Missing space before opening brace. + Large, + Medium, +} + +interface State{ + ~ Missing space before opening brace. + currentBreakpoint: Breakpoint; +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +} +~ +" +`; + +exports[`Validating rule docs space-before-blocks.mdx code examples ESLint output 2`] = ` +"Correct + +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..b547a7e6e0c5 --- /dev/null +++ b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/strict-boolean-expressions.shot @@ -0,0 +1,63 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Validating rule docs strict-boolean-expressions.mdx code examples ESLint output 1`] = ` +"Incorrect + +// 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[`Validating rule docs strict-boolean-expressions.mdx code examples ESLint output 2`] = ` +"Correct + +// 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..1b2fd682199f --- /dev/null +++ b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/switch-exhaustiveness-check.shot @@ -0,0 +1,176 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Validating rule docs switch-exhaustiveness-check.mdx code examples ESLint output 1`] = ` +"Options: { "requireDefaultForNonUnion": true } + +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[`Validating rule docs switch-exhaustiveness-check.mdx code examples ESLint output 2`] = ` +"Incorrect + +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[`Validating rule docs switch-exhaustiveness-check.mdx code examples ESLint output 3`] = ` +"Correct + +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[`Validating rule docs switch-exhaustiveness-check.mdx code examples ESLint output 4`] = ` +"Correct + +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[`Validating rule docs switch-exhaustiveness-check.mdx code examples ESLint output 5`] = ` +"Incorrect + +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[`Validating rule docs switch-exhaustiveness-check.mdx code examples ESLint output 6`] = ` +"Correct + +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[`Validating rule docs switch-exhaustiveness-check.mdx code examples ESLint output 7`] = ` +"Correct + +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..96e59374e116 --- /dev/null +++ b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/triple-slash-reference.shot @@ -0,0 +1,79 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Validating rule docs triple-slash-reference.mdx code examples ESLint output 1`] = ` +"Incorrect +Options: { "lib": "never" } + +/// +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Do not use a triple slash reference for code, use \`import\` style instead. + +globalThis.value; +" +`; + +exports[`Validating rule docs triple-slash-reference.mdx code examples ESLint output 2`] = ` +"Correct +Options: { "lib": "never" } + +import { value } from 'code'; +" +`; + +exports[`Validating rule docs triple-slash-reference.mdx code examples ESLint output 3`] = ` +"Incorrect +Options: { "path": "never" } + +/// +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Do not use a triple slash reference for code, use \`import\` style instead. + +globalThis.value; +" +`; + +exports[`Validating rule docs triple-slash-reference.mdx code examples ESLint output 4`] = ` +"Correct +Options: { "path": "never" } + +import { value } from 'code'; +" +`; + +exports[`Validating rule docs triple-slash-reference.mdx code examples ESLint output 5`] = ` +"Incorrect +Options: { "types": "never" } + +/// +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Do not use a triple slash reference for code, use \`import\` style instead. + +globalThis.value; +" +`; + +exports[`Validating rule docs triple-slash-reference.mdx code examples ESLint output 6`] = ` +"Correct +Options: { "types": "never" } + +import { value } from 'code'; +" +`; + +exports[`Validating rule docs triple-slash-reference.mdx code examples ESLint output 7`] = ` +"Incorrect +Options: { "types": "prefer-import" } + +/// +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Do not use a triple slash reference for code, use \`import\` style instead. + +import { valueA } from 'code'; + +globalThis.valueB; +" +`; + +exports[`Validating rule docs triple-slash-reference.mdx code examples ESLint output 8`] = ` +"Correct +Options: { "types": "prefer-import" } + +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..765805e9bbab --- /dev/null +++ b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/type-annotation-spacing.shot @@ -0,0 +1,311 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Validating rule docs type-annotation-spacing.mdx code examples ESLint output 1`] = ` +"Incorrect + +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[`Validating rule docs type-annotation-spacing.mdx code examples ESLint output 2`] = ` +"Correct + +let foo: string = "bar"; + +function foo(): string {} + +class Foo { + name: string; +} + +type Foo = () => {}; +" +`; + +exports[`Validating rule docs type-annotation-spacing.mdx code examples ESLint output 3`] = ` +"Incorrect +Options: { "before": false, "after": true } + +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[`Validating rule docs type-annotation-spacing.mdx code examples ESLint output 4`] = ` +"Correct +Options: { "before": false, "after": true } + +let foo: string = "bar"; + +function foo(): string {} + +class Foo { + name: string; +} + +type Foo = ()=> {}; +" +`; + +exports[`Validating rule docs type-annotation-spacing.mdx code examples ESLint output 5`] = ` +"Incorrect +Options: { "before": true, "after": true } + +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[`Validating rule docs type-annotation-spacing.mdx code examples ESLint output 6`] = ` +"Correct +Options: { "before": true, "after": true } + +let foo : string = "bar"; + +function foo() : string {} + +class Foo { + name : string; +} + +type Foo = () => {}; +" +`; + +exports[`Validating rule docs type-annotation-spacing.mdx code examples ESLint output 7`] = ` +"Incorrect +Options: {"before":false,"after":false,"overrides":{"colon":{"before":true,"after":true}}} + +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[`Validating rule docs type-annotation-spacing.mdx code examples ESLint output 8`] = ` +"Correct +Options: {"before":false,"after":false,"overrides":{"colon":{"before":true,"after":true}}} + +let foo : string = "bar"; + +function foo() : string {} + +class Foo { + name : string; +} + +type Foo = { + name : (name : string)=>string; +} + +type Foo = ()=>{}; +" +`; + +exports[`Validating rule docs type-annotation-spacing.mdx code examples ESLint output 9`] = ` +"Incorrect +Options: {"before":false,"after":false,"overrides":{"arrow":{"before":true,"after":true}}} + +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[`Validating rule docs type-annotation-spacing.mdx code examples ESLint output 10`] = ` +"Correct +Options: {"before":false,"after":false,"overrides":{"arrow":{"before":true,"after":true}}} + +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..aee201a17000 --- /dev/null +++ b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/typedef.shot @@ -0,0 +1,239 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Validating rule docs typedef.mdx code examples ESLint output 1`] = ` +"Incorrect +Options: { "arrayDestructuring": true } + +const [a] = [1]; + ~~~ Expected a type annotation. +const [b, c] = [1, 2]; + ~~~~~~ Expected a type annotation. +" +`; + +exports[`Validating rule docs typedef.mdx code examples ESLint output 2`] = ` +"Correct +Options: { "arrayDestructuring": true } + +const [a]: number[] = [1]; +const [b]: [number] = [2]; +const [c, d]: [boolean, string] = [true, 'text']; + +for (const [key, val] of new Map([['key', 1]])) { +} +" +`; + +exports[`Validating rule docs typedef.mdx code examples ESLint output 3`] = ` +"Incorrect +Options: { "arrowParameter": true } + +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[`Validating rule docs typedef.mdx code examples ESLint output 4`] = ` +"Correct +Options: { "arrowParameter": true } + +const logsSize = (size: number) => console.log(size); + +['hello', 'world'].map((text: string) => text.length); + +const mapper = { + map: (text: string) => text + '...', +}; +" +`; + +exports[`Validating rule docs typedef.mdx code examples ESLint output 5`] = ` +"Incorrect +Options: { "memberVariableDeclaration": true } + +class ContainsText { + delayedText; + ~~~~~~~~~~~~ Expected delayedText to have a type annotation. + immediateTextImplicit = 'text'; + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Expected immediateTextImplicit to have a type annotation. +} +" +`; + +exports[`Validating rule docs typedef.mdx code examples ESLint output 6`] = ` +"Correct +Options: { "memberVariableDeclaration": true } + +class ContainsText { + delayedText: string; + immediateTextImplicit: string = 'text'; +} +" +`; + +exports[`Validating rule docs typedef.mdx code examples ESLint output 7`] = ` +"Incorrect +Options: { "objectDestructuring": true } + +const { length } = 'text'; + ~~~~~~~~~~ Expected a type annotation. +const [b, c] = Math.random() ? [1, 2] : [3, 4]; +" +`; + +exports[`Validating rule docs typedef.mdx code examples ESLint output 8`] = ` +"Correct +Options: { "objectDestructuring": true } + +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[`Validating rule docs typedef.mdx code examples ESLint output 9`] = ` +"Incorrect +Options: { "parameter": true } + +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[`Validating rule docs typedef.mdx code examples ESLint output 10`] = ` +"Correct +Options: { "parameter": true } + +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[`Validating rule docs typedef.mdx code examples ESLint output 11`] = ` +"Incorrect +Options: { "propertyDeclaration": true } + +type Members = { + member; + ~~~~~~~ Expected member to have a type annotation. + otherMember; + ~~~~~~~~~~~~ Expected otherMember to have a type annotation. +}; +" +`; + +exports[`Validating rule docs typedef.mdx code examples ESLint output 12`] = ` +"Correct +Options: { "propertyDeclaration": true } + +type Members = { + member: boolean; + otherMember: string; +}; +" +`; + +exports[`Validating rule docs typedef.mdx code examples ESLint output 13`] = ` +"Incorrect +Options: { "variableDeclaration": true } + +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[`Validating rule docs typedef.mdx code examples ESLint output 14`] = ` +"Correct +Options: { "variableDeclaration": true } + +const text: string = 'text'; +let initialText: string = 'text'; +let delayedText: string; +" +`; + +exports[`Validating rule docs typedef.mdx code examples ESLint output 15`] = ` +"Incorrect +Options: { "variableDeclaration": true, "variableDeclarationIgnoreFunction": true } + +const text = 'text'; + ~~~~~~~~~~~~~ Expected text to have a type annotation. +" +`; + +exports[`Validating rule docs typedef.mdx code examples ESLint output 16`] = ` +"Correct +Options: { "variableDeclaration": true, "variableDeclarationIgnoreFunction": true } + +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..e19e03867533 --- /dev/null +++ b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/unbound-method.shot @@ -0,0 +1,82 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Validating rule docs unbound-method.mdx code examples ESLint output 1`] = ` +"Incorrect + +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[`Validating rule docs unbound-method.mdx code examples ESLint output 2`] = ` +"Correct + +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.logUnbound.bind(instance); +const innerLog = () => instance.logUnbound(); + +// 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[`Validating rule docs unbound-method.mdx code examples ESLint output 3`] = ` +"Options: { "ignoreStatic": true } + +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..c35fb2cc7545 --- /dev/null +++ b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/unified-signatures.shot @@ -0,0 +1,62 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Validating rule docs unified-signatures.mdx code examples ESLint output 1`] = ` +"Incorrect + +function x(x: number): void; +function x(x: string): void; + ~~~~~~~~~ These overloads can be combined into one signature taking \`number | string\`. +" +`; + +exports[`Validating rule docs unified-signatures.mdx code examples ESLint output 2`] = ` +"Incorrect + +function y(): void; +function y(...x: number[]): void; + ~~~~~~~~~~~~~~ These overloads can be combined into one signature with a rest parameter. +" +`; + +exports[`Validating rule docs unified-signatures.mdx code examples ESLint output 3`] = ` +"Correct + +function x(x: number | string): void; +" +`; + +exports[`Validating rule docs unified-signatures.mdx code examples ESLint output 4`] = ` +"Correct + +function y(...x: number[]): void; +" +`; + +exports[`Validating rule docs unified-signatures.mdx code examples ESLint output 5`] = ` +"Correct + +// 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[`Validating rule docs unified-signatures.mdx code examples ESLint output 6`] = ` +"Incorrect +Options: { "ignoreDifferentlyNamedParameters": true } + +function f(a: number): void; +function f(a: string): void; + ~~~~~~~~~ These overloads can be combined into one signature taking \`number | string\`. +" +`; + +exports[`Validating rule docs unified-signatures.mdx code examples ESLint output 7`] = ` +"Correct +Options: { "ignoreDifferentlyNamedParameters": true } + +function f(a: number): void; +function f(b: string): void; +" +`; diff --git a/packages/eslint-plugin/tests/docs-eslint-output-snapshots/use-unknown-in-catch-callback-variable.shot b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/use-unknown-in-catch-callback-variable.shot new file mode 100644 index 000000000000..464a4760c246 --- /dev/null +++ b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/use-unknown-in-catch-callback-variable.shot @@ -0,0 +1,30 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Validating rule docs use-unknown-in-catch-callback-variable.mdx code examples ESLint output 1`] = ` +"Incorrect + +Promise.reject(new Error('I will reject!')).catch(err => { + ~~~ Prefer the safe \`: unknown\` for a catch callback variable. + console.log(err); +}); + +Promise.reject(new Error('I will reject!')).catch((err: any) => { + ~~~~~~~~ Prefer the safe \`: unknown\` for a catch callback variable. + console.log(err); +}); + +Promise.reject(new Error('I will reject!')).catch((err: Error) => { + ~~~~~~~~~~ Prefer the safe \`: unknown\` for a catch callback variable. + console.log(err); +}); +" +`; + +exports[`Validating rule docs use-unknown-in-catch-callback-variable.mdx code examples ESLint output 2`] = ` +"Correct + +Promise.reject(new Error('I will reject!')).catch((err: unknown) => { + console.log(err); +}); +" +`; diff --git a/packages/eslint-plugin/tests/docs.test.ts b/packages/eslint-plugin/tests/docs.test.ts index b3000aa3a721..049c0d168e4f 100644 --- a/packages/eslint-plugin/tests/docs.test.ts +++ b/packages/eslint-plugin/tests/docs.test.ts @@ -1,10 +1,23 @@ +import 'jest-specific-snapshot'; + +import assert from 'node:assert/strict'; + 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 type * as mdast from 'mdast'; +import type { fromMarkdown as FromMarkdown } from 'mdast-util-from-markdown' with { 'resolution-mode': 'import' }; +import type { mdxFromMarkdown as MdxFromMarkdown } from 'mdast-util-mdx' with { 'resolution-mode': 'import' }; +import type { mdxjs as Mdxjs } from 'micromark-extension-mdxjs' with { 'resolution-mode': 'import' }; import path from 'path'; import { titleCase } from 'title-case'; +import type * as UnistUtilVisit from 'unist-util-visit' with { 'resolution-mode': 'import' }; import rules from '../src/rules'; +import { areOptionsValid } from './areOptionsValid'; +import { getFixturesRootDir } from './RuleTester'; const docsRoot = path.resolve(__dirname, '../docs/rules'); const rulesData = Object.entries(rules); @@ -46,7 +59,72 @@ function tokenIsH2( ); } +function renderLintResults(code: string, errors: Linter.LintMessage[]): string { + const output: string[] = []; + const lines = code.split(/\r?\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( + startLine === endLine + ? Math.max(1, endColumn - startColumn) + : line.length - startColumn, + ); + const squiggleWithIndent = ' '.repeat(startColumn) + squiggle + ' '; + const errorMessageIndent = ' '.repeat(squiggleWithIndent.length); + output.push( + squiggleWithIndent + + error.message.split('\n').join('\n' + errorMessageIndent), + ); + } else if (i === endLine) { + output.push('~'.repeat(endColumn)); + } else { + output.push('~'.repeat(line.length)); + } + } + } + + 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', () => { + let fromMarkdown: typeof FromMarkdown; + let mdxjs: typeof Mdxjs; + let mdxFromMarkdown: typeof MdxFromMarkdown; + let unistUtilVisit: typeof UnistUtilVisit; + beforeAll(async () => { + // dynamic import('...') is transpiled to the require('...') call, + // but all modules imported below are ESM only, so we cannot require() them + // eslint-disable-next-line @typescript-eslint/no-implied-eval + const dynamicImport = new Function('module', 'return import(module)'); + ({ fromMarkdown } = await dynamicImport('mdast-util-from-markdown')); + ({ mdxjs } = await dynamicImport('micromark-extension-mdxjs')); + ({ mdxFromMarkdown } = await dynamicImport('mdast-util-mdx')); + unistUtilVisit = await dynamicImport('unist-util-visit'); + }); + const ignoredFiles = new Set([ 'README.md', 'TEMPLATE.md', @@ -207,10 +285,156 @@ describe('Validating rule docs', () => { } } }); + + test('code examples ESLint output', () => { + // TypeScript can't infer type arguments unless we provide them explicitly + linter.defineRule< + keyof (typeof rule)['meta']['messages'], + (typeof rule)['defaultOptions'] + >(ruleName, rule); + + const tree = fromMarkdown(fullText, { + extensions: [mdxjs()], + mdastExtensions: [mdxFromMarkdown()], + }); + + unistUtilVisit.visit(tree, node => { + if (node.type === 'mdxJsxFlowElement') { + if (node.name !== 'TabItem') { + return unistUtilVisit.CONTINUE; + } + + unistUtilVisit.visit(node, 'code', code => { + const valueAttr = node.attributes.find( + attr => + attr.type === 'mdxJsxAttribute' && attr.name === 'value', + ); + lintCodeBlock( + code, + valueAttr && typeof valueAttr.value === 'string' + ? valueAttr.value.startsWith('❌ Incorrect') || + (valueAttr.value.startsWith('✅ Correct') + ? false + : 'skip-check') + : 'skip-check', + ); + }); + + return unistUtilVisit.SKIP; + } + + if (node.type === 'code') { + if (node.meta?.includes('showPlaygroundButton')) { + lintCodeBlock(node, 'skip-check'); + } + + return unistUtilVisit.SKIP; + } + + return unistUtilVisit.CONTINUE; + }); + + function lintCodeBlock( + token: mdast.Code, + shouldContainLintErrors: boolean | 'skip-check', + ): void { + const lang = token.lang?.trim(); + if (!lang || !/^tsx?\b/i.test(lang)) { + return; + } + + const optionRegex = /option='(?