From 5124835af4381f660269f82b43223bd743eef437 Mon Sep 17 00:00:00 2001 From: Josh Goldberg Date: Mon, 15 Apr 2024 07:38:44 -0400 Subject: [PATCH 01/10] feat(typescript-estree): disallowAutomaticSingleRunInference, off (fast) by default --- docs/packages/Parser.mdx | 19 ++--- docs/packages/TypeScript_ESTree.mdx | 41 ++++++----- eslint.config.mjs | 1 - .../src/parseSettings/inferSingleRun.ts | 4 +- .../typescript-estree/src/parser-options.ts | 41 ++++++----- .../tests/lib/inferSingleRun.test.ts | 73 +++++++++++++++++++ 6 files changed, 131 insertions(+), 48 deletions(-) create mode 100644 packages/typescript-estree/tests/lib/inferSingleRun.test.ts diff --git a/docs/packages/Parser.mdx b/docs/packages/Parser.mdx index 3ea0d996cfc6..0c7eb9946ab9 100644 --- a/docs/packages/Parser.mdx +++ b/docs/packages/Parser.mdx @@ -30,10 +30,10 @@ The following additional configuration options are available by specifying them ```ts interface ParserOptions { - allowAutomaticSingleRunInference?: boolean; cacheLifetime?: { glob?: number | 'Infinity'; }; + disallowAutomaticSingleRunInference?: boolean; ecmaFeatures?: { jsx?: boolean; globalReturn?: boolean; @@ -55,22 +55,23 @@ interface ParserOptions { } ``` -### `allowAutomaticSingleRunInference` +### `disallowAutomaticSingleRunInference` -> Default `process.env.TSESTREE_SINGLE_RUN` or `false`. +> Default `process.env.TSESTREE_SINGLE_RUN` or `true`. -Whether to use common heuristics to infer whether ESLint is being used as part of a single run (as opposed to `--fix` mode or in a persistent session such as an editor extension). +Whether to stop using common heuristics to infer whether ESLint is being used as part of a single run (as opposed to `--fix` mode or in a persistent session such as an editor extension). +In other words, typescript-eslint is faster by default, and this option disables an automatic performance optimization. When typescript-eslint handles TypeScript Program management behind the scenes for [linting with type information](../getting-started/Typed_Linting.mdx), this distinction is important for performance. There is significant overhead to managing TypeScript "Watch" Programs needed for the long-running use-case. Being able to assume the single run case allows typescript-eslint to faster immutable Programs instead. This setting's default value can be specified by setting a `TSESTREE_SINGLE_RUN` environment variable to `"false"` or `"true"`. -For example, `TSESTREE_SINGLE_RUN=true npx eslint .` will enable it. +For example, `TSESTREE_SINGLE_RUN=false npx eslint .` will disable it. -:::tip -We've seen `allowAutomaticSingleRunInference` improve linting speed in CI by up to 10-20%. -Our plan is to [enable `allowAutomaticSingleRunInference` by default in an upcoming major version](https://github.com/typescript-eslint/typescript-eslint/issues/8121). +:::note +We recommend leaving this option off if possible. +We've seen allowing automatic single run inference improve linting speed in CI by up to 10-20%. ::: ### `cacheLifetime` @@ -79,7 +80,7 @@ This option allows you to granularly control our internal cache expiry lengths. You can specify the number of seconds as an integer number, or the string 'Infinity' if you never want the cache to expire. -By default cache entries will be evicted after 30 seconds, or will persist indefinitely if the parser infers that it is a single run (see [`allowAutomaticSingleRunInference`](#allowAutomaticSingleRunInference)). +By default cache entries will be evicted after 30 seconds, or will persist indefinitely if the parser infers that it is a single run (see [`disallowAutomaticSingleRunInference`](#disallowAutomaticSingleRunInference)). ### `ecmaFeatures` diff --git a/docs/packages/TypeScript_ESTree.mdx b/docs/packages/TypeScript_ESTree.mdx index 7269942e84d3..505a8c040847 100644 --- a/docs/packages/TypeScript_ESTree.mdx +++ b/docs/packages/TypeScript_ESTree.mdx @@ -241,30 +241,13 @@ interface ParseAndGenerateServicesOptions extends ParseOptions { */ DEPRECATED__createDefaultProgram?: boolean; - /** - * ESLint (and therefore typescript-eslint) is used in both "single run"/one-time contexts, - * such as an ESLint CLI invocation, and long-running sessions (such as continuous feedback - * on a file in an IDE). - * - * When typescript-eslint handles TypeScript Program management behind the scenes, this distinction - * is important because there is significant overhead to managing the so called Watch Programs - * needed for the long-running use-case. - * - * When allowAutomaticSingleRunInference is enabled, we will use common heuristics to infer - * whether or not ESLint is being used as part of a single run. - * - * This setting's default value can be specified by setting a `TSESTREE_SINGLE_RUN` - * environment variable to `"false"` or `"true"`. - */ - allowAutomaticSingleRunInference?: boolean; - /** * Granular control of the expiry lifetime of our internal caches. * You can specify the number of seconds as an integer number, or the string * 'Infinity' if you never want the cache to expire. * * By default cache entries will be evicted after 30 seconds, or will persist - * indefinitely if `allowAutomaticSingleRunInference = true` AND the parser + * indefinitely if `disallowAutomaticSingleRunInference = false` AND the parser * infers that it is a single run. */ cacheLifetime?: { @@ -273,6 +256,28 @@ interface ParseAndGenerateServicesOptions extends ParseOptions { */ glob?: number | 'Infinity'; }; + + /** + * ESLint (and therefore typescript-eslint) is used in both "single run"/one-time contexts, + * such as an ESLint CLI invocation, and long-running sessions (such as continuous feedback + * on a file in an IDE). + * + * When typescript-eslint handles TypeScript Program management behind the scenes, this distinction + * is important because there is significant overhead to managing the so called Watch Programs + * needed for the long-running use-case. + * + * By default, we will use common heuristics to infer whether ESLint is being + * used as part of a single run. This option disables those heuristics, and + * therefore the performance optimizations gained by them. + * + * In other words, typescript-eslint is faster by default, and this option + * disables an automatic performance optimization. + * + * This setting's default value can be specified by setting a `TSESTREE_SINGLE_RUN` + * environment variable to `"false"` or `"true"`. + * Otherwise, the default value is `false`. + */ + disallowAutomaticSingleRunInference?: boolean; } /** diff --git a/eslint.config.mjs b/eslint.config.mjs index bb2c0c491044..c7956f27f439 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -76,7 +76,6 @@ export default tseslint.config( ...globals.node, }, parserOptions: { - allowAutomaticSingleRunInference: true, cacheLifetime: { // we pretty well never create/change tsconfig structure - so no need to ever evict the cache // in the rare case that we do - just need to manually restart their IDE. diff --git a/packages/typescript-estree/src/parseSettings/inferSingleRun.ts b/packages/typescript-estree/src/parseSettings/inferSingleRun.ts index db64bc21435f..a86e25f9b7a7 100644 --- a/packages/typescript-estree/src/parseSettings/inferSingleRun.ts +++ b/packages/typescript-estree/src/parseSettings/inferSingleRun.ts @@ -33,8 +33,8 @@ export function inferSingleRun(options: TSESTreeOptions | undefined): boolean { return true; } - // Currently behind a flag while we gather real-world feedback - if (options.allowAutomaticSingleRunInference) { + // Ideally, we'd like to try to auto-detect CI or CLI usage that lets us infer a single CLI run. + if (!options.disallowAutomaticSingleRunInference) { const possibleEslintBinPaths = [ 'node_modules/.bin/eslint', // npm or yarn repo 'node_modules/eslint/bin/eslint.js', // pnpm repo diff --git a/packages/typescript-estree/src/parser-options.ts b/packages/typescript-estree/src/parser-options.ts index 4347ee29e47e..5fa2b9f8f9ec 100644 --- a/packages/typescript-estree/src/parser-options.ts +++ b/packages/typescript-estree/src/parser-options.ts @@ -198,30 +198,13 @@ interface ParseAndGenerateServicesOptions extends ParseOptions { */ DEPRECATED__createDefaultProgram?: boolean; - /** - * ESLint (and therefore typescript-eslint) is used in both "single run"/one-time contexts, - * such as an ESLint CLI invocation, and long-running sessions (such as continuous feedback - * on a file in an IDE). - * - * When typescript-eslint handles TypeScript Program management behind the scenes, this distinction - * is important because there is significant overhead to managing the so called Watch Programs - * needed for the long-running use-case. - * - * When allowAutomaticSingleRunInference is enabled, we will use common heuristics to infer - * whether or not ESLint is being used as part of a single run. - * - * This setting's default value can be specified by setting a `TSESTREE_SINGLE_RUN` - * environment variable to `"false"` or `"true"`. - */ - allowAutomaticSingleRunInference?: boolean; - /** * Granular control of the expiry lifetime of our internal caches. * You can specify the number of seconds as an integer number, or the string * 'Infinity' if you never want the cache to expire. * * By default cache entries will be evicted after 30 seconds, or will persist - * indefinitely if `allowAutomaticSingleRunInference = true` AND the parser + * indefinitely if `disallowAutomaticSingleRunInference = false` AND the parser * infers that it is a single run. */ cacheLifetime?: { @@ -230,6 +213,28 @@ interface ParseAndGenerateServicesOptions extends ParseOptions { */ glob?: CacheDurationSeconds; }; + + /** + * ESLint (and therefore typescript-eslint) is used in both "single run"/one-time contexts, + * such as an ESLint CLI invocation, and long-running sessions (such as continuous feedback + * on a file in an IDE). + * + * When typescript-eslint handles TypeScript Program management behind the scenes, this distinction + * is important because there is significant overhead to managing the so called Watch Programs + * needed for the long-running use-case. + * + * By default, we will use common heuristics to infer whether ESLint is being + * used as part of a single run. This option disables those heuristics, and + * therefore the performance optimizations gained by them. + * + * In other words, typescript-eslint is faster by default, and this option + * disables an automatic performance optimization. + * + * This setting's default value can be specified by setting a `TSESTREE_SINGLE_RUN` + * environment variable to `"false"` or `"true"`. + * Otherwise, the default value is `false`. + */ + disallowAutomaticSingleRunInference?: boolean; } export type TSESTreeOptions = ParseAndGenerateServicesOptions; diff --git a/packages/typescript-estree/tests/lib/inferSingleRun.test.ts b/packages/typescript-estree/tests/lib/inferSingleRun.test.ts new file mode 100644 index 000000000000..cc380a8200df --- /dev/null +++ b/packages/typescript-estree/tests/lib/inferSingleRun.test.ts @@ -0,0 +1,73 @@ +import { inferSingleRun } from '../../src/parseSettings/inferSingleRun'; + +describe('inferSingleRun', () => { + beforeEach(() => { + process.argv = ['node', 'eslint']; + process.env.CI = undefined; + process.env.TSESTREE_SINGLE_RUN = undefined; + }); + + it('returns false when options is undefined', () => { + const actual = inferSingleRun(undefined); + + expect(actual).toBe(false); + }); + + it('returns false when options.project is null', () => { + const actual = inferSingleRun({ project: null }); + + expect(actual).toBe(false); + }); + + it('returns false when options.program is defined', () => { + const actual = inferSingleRun({ programs: [], project: true }); + + expect(actual).toBe(false); + }); + + it("returns false when TSESTREE_SINGLE_RUN is 'false'", () => { + process.env.TSESTREE_SINGLE_RUN = 'false'; + + const actual = inferSingleRun({ project: true }); + + expect(actual).toBe(false); + }); + + it("returns true when TSESTREE_SINGLE_RUN is 'true'", () => { + process.env.TSESTREE_SINGLE_RUN = 'true'; + + const actual = inferSingleRun({ project: true }); + + expect(actual).toBe(true); + }); + + it("returns true when CI is 'true'", () => { + process.env.CI = 'true'; + + const actual = inferSingleRun({ project: true }); + + expect(actual).toBe(true); + }); + + it('returns true when run by the ESLint CLI in npm/yarn', () => { + process.argv = ['node', 'node_modules/.bin/eslint']; + + const actual = inferSingleRun({ project: true }); + + expect(actual).toBe(true); + }); + + it('returns true when run by the ESLint CLI in pnpm', () => { + process.argv = ['node', 'node_modules/eslint/bin/eslint.js']; + + const actual = inferSingleRun({ project: true }); + + expect(actual).toBe(true); + }); + + it('returns false when none of the known cases are true', () => { + const actual = inferSingleRun({ project: true }); + + expect(actual).toBe(false); + }); +}); From 400a6b09c802c2236f3d51508b83567b5bade516 Mon Sep 17 00:00:00 2001 From: Josh Goldberg Date: Mon, 15 Apr 2024 08:30:52 -0400 Subject: [PATCH 02/10] Unnecessary Infinity cache lifetime too --- eslint.config.mjs | 5 ----- 1 file changed, 5 deletions(-) diff --git a/eslint.config.mjs b/eslint.config.mjs index c7956f27f439..bde1e5edd589 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -76,11 +76,6 @@ export default tseslint.config( ...globals.node, }, parserOptions: { - cacheLifetime: { - // we pretty well never create/change tsconfig structure - so no need to ever evict the cache - // in the rare case that we do - just need to manually restart their IDE. - glob: 'Infinity', - }, project: [ 'tsconfig.json', 'packages/*/tsconfig.json', From 09306203203468a94dc57744357c2a270df280d4 Mon Sep 17 00:00:00 2001 From: Josh Goldberg Date: Mon, 15 Apr 2024 08:40:59 -0400 Subject: [PATCH 03/10] disallowAutomaticSingleRunInference in RuleTester --- packages/rule-tester/src/RuleTester.ts | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/packages/rule-tester/src/RuleTester.ts b/packages/rule-tester/src/RuleTester.ts index f0ac7ca3dcac..8a408f4a9ece 100644 --- a/packages/rule-tester/src/RuleTester.ts +++ b/packages/rule-tester/src/RuleTester.ts @@ -214,13 +214,16 @@ export class RuleTester extends TestFramework { if (test.parser === TYPESCRIPT_ESLINT_PARSER) { throw new Error(DUPLICATE_PARSER_ERROR_MESSAGE); } - if (!test.filename) { - return { - ...test, - filename: getFilename(test.parserOptions), - }; - } - return test; + return { + ...test, + filename: test.filename || getFilename(test.parserOptions), + parserOptions: { + // Re-running simulates --fix mode, which implies an isolated program + // (i.e. parseAndGenerateServicesCalls[test.filename] > 1). + disallowAutomaticSingleRunInference: true, + ...test.parserOptions, + }, + }; }; const normalizedTests = { From 8f398e3e7116ff55e0dbdfb4a5ee78fe4d3d4efc Mon Sep 17 00:00:00 2001 From: Josh Goldberg Date: Mon, 15 Apr 2024 10:39:32 -0400 Subject: [PATCH 04/10] Add more explicit disallowAutomaticSingleRunInference: true,s --- .../no-duplicate-enum-values.shot | 30 +- .../no-magic-numbers.shot | 7 +- .../no-mixed-enums.shot | 39 +-- .../no-unnecessary-qualifier.shot | 25 +- .../no-unsafe-declaration-merging.shot | 15 - .../no-unsafe-enum-comparison.shot | 42 +-- .../no-use-before-define.shot | 37 +-- .../prefer-enum-initializers.shot | 40 +-- .../prefer-literal-enum-member.shot | 65 +--- .../prefer-readonly-parameter-types.shot | 298 ------------------ .../space-before-blocks.shot | 22 +- .../switch-exhaustiveness-check.shot | 60 +--- .../tests/TypeOrValueSpecifier.test.ts | 1 + .../type-utils/tests/isTypeReadonly.test.ts | 1 + .../tests/isUnsafeAssignment.test.ts | 1 + 15 files changed, 84 insertions(+), 599 deletions(-) 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 index 33ac7b3e3444..a680fc081a13 100644 --- 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 @@ -4,10 +4,13 @@ exports[`Validating rule docs no-duplicate-enum-values.mdx code examples ESLint "Incorrect enum E { +~~~~~~~~ A = 0, +~~~~~~~~ B = 0, - ~~~~~ Duplicate enum member value 0. +~~~~~~~~ } +~ " `; @@ -15,29 +18,12 @@ exports[`Validating rule docs no-duplicate-enum-values.mdx code examples ESLint "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-magic-numbers.shot b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-magic-numbers.shot index 5d37a25cb7d2..5af5191cd2e5 100644 --- 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 @@ -4,9 +4,11 @@ exports[`Validating rule docs no-magic-numbers.mdx code examples ESLint output 1 "Options: { "ignoreEnums": false } enum foo { +~~~~~~~~~~ SECOND = 1000, - ~~~~ No magic number: 1000. +~~~~~~~~~~~~~~~~ } +~ " `; @@ -14,8 +16,11 @@ exports[`Validating rule docs no-magic-numbers.mdx code examples ESLint output 2 "Options: { "ignoreEnums": true } enum foo { +~~~~~~~~~~ SECOND = 1000, +~~~~~~~~~~~~~~~~ } +~ " `; 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 index 66399740f725..d22a242af183 100644 --- 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 @@ -4,43 +4,14 @@ 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-unnecessary-qualifier.shot b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-unnecessary-qualifier.shot index df1f421b2b20..d88c70158043 100644 --- 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 @@ -4,10 +4,13 @@ exports[`Validating rule docs no-unnecessary-qualifier.mdx code examples ESLint "Incorrect enum A { +~~~~~~~~ B, +~~~~ C = A.B, - ~ Qualifier is unnecessary since 'B' is in scope. +~~~~~~~~~~ } +~ " `; @@ -21,23 +24,3 @@ namespace A { } " `; - -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-unsafe-declaration-merging.shot b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-unsafe-declaration-merging.shot index 839899b7bfce..b1331758506c 100644 --- 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 @@ -10,18 +10,3 @@ 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 index 2d883379f083..351b577cebe6 100644 --- 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 @@ -4,13 +4,19 @@ exports[`Validating rule docs no-unsafe-enum-comparison.mdx code examples ESLint "Incorrect enum Fruit { +~~~~~~~~~~~~ Apple, +~~~~~~~~ } +~ + declare let fruit: Fruit; +~~~~~~~~~~~~~~~~~~~~~~~~~ + fruit === 0; -~~~~~~~~~~~ The two values in this comparison do not have a shared enum type. +~~~~~~~~~~~~ " `; @@ -18,38 +24,18 @@ exports[`Validating rule docs no-unsafe-enum-comparison.mdx code examples ESLint "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; +vegetable === 'asparagus'; +~~~~~~~~~~~~~~~~~~~~~~~~~~ " `; 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 index 1efd72d47170..d3920b46874b 100644 --- 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 @@ -5,43 +5,14 @@ exports[`Validating rule docs no-use-before-define.mdx code examples ESLint outp 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/prefer-enum-initializers.shot b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/prefer-enum-initializers.shot index 38bd92861600..07cbdc8b6714 100644 --- 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 @@ -4,44 +4,34 @@ exports[`Validating rule docs prefer-enum-initializers.mdx code examples ESLint "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', +~~~~~~~~~~~~ + Red, +~~~~~~ Green = 'Green', +~~~~~~~~~~~~~~~~~~ Blue = 'Blue', +~~~~~~~~~~~~~~~~ } +~ " `; 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 index c9938b4bbb47..e76ab73c8869 100644 --- 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 @@ -4,69 +4,20 @@ exports[`Validating rule docs prefer-literal-enum-member.mdx code examples ESLin "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-readonly-parameter-types.shot b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/prefer-readonly-parameter-types.shot index 606039e2e781..e7b558ecb1e4 100644 --- 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 @@ -58,301 +58,3 @@ interface Foo { } " `; - -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/space-before-blocks.shot b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/space-before-blocks.shot index 74158461fac1..e2c174055b1d 100644 --- 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 @@ -4,30 +4,20 @@ exports[`Validating rule docs space-before-blocks.mdx code examples ESLint outpu "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/switch-exhaustiveness-check.shot b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/switch-exhaustiveness-check.shot index 1b2fd682199f..f2272066c660 100644 --- 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 @@ -109,68 +109,30 @@ exports[`Validating rule docs switch-exhaustiveness-check.mdx code examples ESLi "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/type-utils/tests/TypeOrValueSpecifier.test.ts b/packages/type-utils/tests/TypeOrValueSpecifier.test.ts index 8ddca54d3b34..b0be9a7a6e66 100644 --- a/packages/type-utils/tests/TypeOrValueSpecifier.test.ts +++ b/packages/type-utils/tests/TypeOrValueSpecifier.test.ts @@ -131,6 +131,7 @@ describe('TypeOrValueSpecifier', () => { ): void { const rootDir = path.join(__dirname, 'fixtures'); const { ast, services } = parseForESLint(code, { + disallowAutomaticSingleRunInference: true, project: './tsconfig.json', filePath: path.join(rootDir, 'file.ts'), tsconfigRootDir: rootDir, diff --git a/packages/type-utils/tests/isTypeReadonly.test.ts b/packages/type-utils/tests/isTypeReadonly.test.ts index c171417e5d32..903c92e5b003 100644 --- a/packages/type-utils/tests/isTypeReadonly.test.ts +++ b/packages/type-utils/tests/isTypeReadonly.test.ts @@ -16,6 +16,7 @@ describe('isTypeReadonly', () => { program: ts.Program; } { const { ast, services } = parseForESLint(code, { + disallowAutomaticSingleRunInference: true, project: './tsconfig.json', filePath: path.join(rootDir, 'file.ts'), tsconfigRootDir: rootDir, diff --git a/packages/type-utils/tests/isUnsafeAssignment.test.ts b/packages/type-utils/tests/isUnsafeAssignment.test.ts index 733682b5a559..69fc0e12c8b9 100644 --- a/packages/type-utils/tests/isUnsafeAssignment.test.ts +++ b/packages/type-utils/tests/isUnsafeAssignment.test.ts @@ -19,6 +19,7 @@ describe('isUnsafeAssignment', () => { checker: ts.TypeChecker; } { const { ast, services } = parseForESLint(code, { + disallowAutomaticSingleRunInference: true, project: './tsconfig.json', filePath: path.join(rootDir, 'file.ts'), tsconfigRootDir: rootDir, From 1ed1c52650e1f65d4527726392afad76115a9369 Mon Sep 17 00:00:00 2001 From: Josh Goldberg Date: Mon, 15 Apr 2024 11:39:28 -0400 Subject: [PATCH 05/10] Fixed for parse.test.ts --- packages/typescript-estree/tests/lib/parse.test.ts | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/packages/typescript-estree/tests/lib/parse.test.ts b/packages/typescript-estree/tests/lib/parse.test.ts index f973358d85a1..de6fc6936dc3 100644 --- a/packages/typescript-estree/tests/lib/parse.test.ts +++ b/packages/typescript-estree/tests/lib/parse.test.ts @@ -168,6 +168,7 @@ describe('parseAndGenerateServices', () => { const config: TSESTreeOptions = { EXPERIMENTAL_useProjectService: false, comment: true, + disallowAutomaticSingleRunInference: true, tokens: true, range: true, loc: true, @@ -346,6 +347,7 @@ describe('parseAndGenerateServices', () => { const code = 'var a = true'; const config: TSESTreeOptions = { comment: true, + disallowAutomaticSingleRunInference: true, tokens: true, range: true, loc: true, @@ -486,6 +488,7 @@ describe('parseAndGenerateServices', () => { const code = 'var a = true'; const config: TSESTreeOptions = { comment: true, + disallowAutomaticSingleRunInference: true, tokens: true, range: true, loc: true, @@ -530,6 +533,7 @@ describe('parseAndGenerateServices', () => { it("shouldn't turn on debugger if no options were provided", () => { parser.parseAndGenerateServices('const x = 1;', { debugLevel: [], + disallowAutomaticSingleRunInference: true, }); expect(debugEnable).not.toHaveBeenCalled(); }); @@ -537,6 +541,7 @@ describe('parseAndGenerateServices', () => { it('should turn on eslint debugger', () => { parser.parseAndGenerateServices('const x = 1;', { debugLevel: ['eslint'], + disallowAutomaticSingleRunInference: true, }); expect(debugEnable).toHaveBeenCalledTimes(1); expect(debugEnable).toHaveBeenCalledWith('eslint:*,-eslint:code-path'); @@ -545,6 +550,7 @@ describe('parseAndGenerateServices', () => { it('should turn on typescript-eslint debugger', () => { parser.parseAndGenerateServices('const x = 1;', { debugLevel: ['typescript-eslint'], + disallowAutomaticSingleRunInference: true, }); expect(debugEnable).toHaveBeenCalledTimes(1); expect(debugEnable).toHaveBeenCalledWith('typescript-eslint:*'); @@ -553,6 +559,7 @@ describe('parseAndGenerateServices', () => { it('should turn on both eslint and typescript-eslint debugger', () => { parser.parseAndGenerateServices('const x = 1;', { debugLevel: ['typescript-eslint', 'eslint'], + disallowAutomaticSingleRunInference: true, }); expect(debugEnable).toHaveBeenCalledTimes(1); expect(debugEnable).toHaveBeenCalledWith( @@ -565,6 +572,7 @@ describe('parseAndGenerateServices', () => { expect(() => parser.parseAndGenerateServices('const x = 1;', { debugLevel: ['typescript'], + disallowAutomaticSingleRunInference: true, filePath: './path-that-doesnt-exist.ts', project: ['./tsconfig-that-doesnt-exist.json'], }), @@ -590,6 +598,7 @@ describe('parseAndGenerateServices', () => { const code = 'var a = true'; const config: TSESTreeOptions = { comment: true, + disallowAutomaticSingleRunInference: true, tokens: true, range: true, loc: true, @@ -631,6 +640,7 @@ describe('parseAndGenerateServices', () => { cacheLifetime: { glob: lifetime, }, + disallowAutomaticSingleRunInference: true, filePath: join(FIXTURES_DIR, 'file.ts'), tsconfigRootDir: FIXTURES_DIR, project: ['./**/tsconfig.json', './**/tsconfig.extra.json'], From 2fb418b3eb48c516d0306f32ddc601202242a933 Mon Sep 17 00:00:00 2001 From: Josh Goldberg Date: Mon, 15 Apr 2024 11:58:38 -0400 Subject: [PATCH 06/10] Fixed persistentParse.test.ts and semanticInfo.test.ts --- packages/typescript-estree/tests/lib/persistentParse.test.ts | 1 + packages/typescript-estree/tests/lib/semanticInfo.test.ts | 1 + 2 files changed, 2 insertions(+) diff --git a/packages/typescript-estree/tests/lib/persistentParse.test.ts b/packages/typescript-estree/tests/lib/persistentParse.test.ts index dbfd2831dea5..0d66694a5b75 100644 --- a/packages/typescript-estree/tests/lib/persistentParse.test.ts +++ b/packages/typescript-estree/tests/lib/persistentParse.test.ts @@ -71,6 +71,7 @@ function parseFile( ignoreTsconfigRootDir?: boolean, ): void { parseAndGenerateServices(CONTENTS[filename], { + disallowAutomaticSingleRunInference: true, project: './tsconfig.json', tsconfigRootDir: ignoreTsconfigRootDir ? undefined : tmpDir, filePath: relative diff --git a/packages/typescript-estree/tests/lib/semanticInfo.test.ts b/packages/typescript-estree/tests/lib/semanticInfo.test.ts index f5f78934a880..8777bc4d2c32 100644 --- a/packages/typescript-estree/tests/lib/semanticInfo.test.ts +++ b/packages/typescript-estree/tests/lib/semanticInfo.test.ts @@ -23,6 +23,7 @@ const testFiles = glob.sync(`**/*.src.ts`, { function createOptions(fileName: string): TSESTreeOptions & { cwd?: string } { return { + disallowAutomaticSingleRunInference: true, loc: true, range: true, tokens: true, From 568489fa55ff84d7fb08ef20945d13289177c075 Mon Sep 17 00:00:00 2001 From: Josh Goldberg Date: Mon, 15 Apr 2024 18:04:22 -0400 Subject: [PATCH 07/10] disallowAutomaticSingleRunInference in docs.test.ts --- packages/eslint-plugin/tests/docs.test.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/eslint-plugin/tests/docs.test.ts b/packages/eslint-plugin/tests/docs.test.ts index 049c0d168e4f..7c7f142a4f46 100644 --- a/packages/eslint-plugin/tests/docs.test.ts +++ b/packages/eslint-plugin/tests/docs.test.ts @@ -367,6 +367,7 @@ describe('Validating rule docs', () => { { parser: '@typescript-eslint/parser', parserOptions: { + disallowAutomaticSingleRunInference: true, tsconfigRootDir: rootPath, project: './tsconfig.json', }, From dd20f36bbc73e536412a9eab00562585b49b17cd Mon Sep 17 00:00:00 2001 From: Josh Goldberg Date: Mon, 15 Apr 2024 18:05:51 -0400 Subject: [PATCH 08/10] Reset plugin .shot files --- .../no-duplicate-enum-values.shot | 30 +- .../no-magic-numbers.shot | 7 +- .../no-mixed-enums.shot | 39 ++- .../no-unnecessary-qualifier.shot | 25 +- .../no-unsafe-declaration-merging.shot | 15 + .../no-unsafe-enum-comparison.shot | 42 ++- .../no-use-before-define.shot | 37 ++- .../prefer-enum-initializers.shot | 40 ++- .../prefer-literal-enum-member.shot | 65 +++- .../prefer-readonly-parameter-types.shot | 298 ++++++++++++++++++ .../space-before-blocks.shot | 22 +- .../switch-exhaustiveness-check.shot | 60 +++- 12 files changed, 599 insertions(+), 81 deletions(-) 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 index a680fc081a13..33ac7b3e3444 100644 --- 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 @@ -4,13 +4,10 @@ exports[`Validating rule docs no-duplicate-enum-values.mdx code examples ESLint "Incorrect enum E { -~~~~~~~~ A = 0, -~~~~~~~~ B = 0, -~~~~~~~~ + ~~~~~ Duplicate enum member value 0. } -~ " `; @@ -18,12 +15,29 @@ exports[`Validating rule docs no-duplicate-enum-values.mdx code examples ESLint "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-magic-numbers.shot b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-magic-numbers.shot index 5af5191cd2e5..5d37a25cb7d2 100644 --- 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 @@ -4,11 +4,9 @@ exports[`Validating rule docs no-magic-numbers.mdx code examples ESLint output 1 "Options: { "ignoreEnums": false } enum foo { -~~~~~~~~~~ SECOND = 1000, -~~~~~~~~~~~~~~~~ + ~~~~ No magic number: 1000. } -~ " `; @@ -16,11 +14,8 @@ exports[`Validating rule docs no-magic-numbers.mdx code examples ESLint output 2 "Options: { "ignoreEnums": true } enum foo { -~~~~~~~~~~ SECOND = 1000, -~~~~~~~~~~~~~~~~ } -~ " `; 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 index d22a242af183..66399740f725 100644 --- 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 @@ -4,14 +4,43 @@ 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-unnecessary-qualifier.shot b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-unnecessary-qualifier.shot index d88c70158043..df1f421b2b20 100644 --- 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 @@ -4,13 +4,10 @@ exports[`Validating rule docs no-unnecessary-qualifier.mdx code examples ESLint "Incorrect enum A { -~~~~~~~~ B, -~~~~ C = A.B, -~~~~~~~~~~ + ~ Qualifier is unnecessary since 'B' is in scope. } -~ " `; @@ -24,3 +21,23 @@ namespace A { } " `; + +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-unsafe-declaration-merging.shot b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-unsafe-declaration-merging.shot index b1331758506c..839899b7bfce 100644 --- 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 @@ -10,3 +10,18 @@ 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 index 351b577cebe6..2d883379f083 100644 --- 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 @@ -4,19 +4,13 @@ exports[`Validating rule docs no-unsafe-enum-comparison.mdx code examples ESLint "Incorrect enum Fruit { -~~~~~~~~~~~~ Apple, -~~~~~~~~ } -~ - declare let fruit: Fruit; -~~~~~~~~~~~~~~~~~~~~~~~~~ - fruit === 0; -~~~~~~~~~~~~ +~~~~~~~~~~~ The two values in this comparison do not have a shared enum type. " `; @@ -24,18 +18,38 @@ exports[`Validating rule docs no-unsafe-enum-comparison.mdx code examples ESLint "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-use-before-define.shot b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-use-before-define.shot index d3920b46874b..1efd72d47170 100644 --- 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 @@ -5,14 +5,43 @@ exports[`Validating rule docs no-use-before-define.mdx code examples ESLint outp 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/prefer-enum-initializers.shot b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/prefer-enum-initializers.shot index 07cbdc8b6714..38bd92861600 100644 --- 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 @@ -4,34 +4,44 @@ exports[`Validating rule docs prefer-enum-initializers.mdx code examples ESLint "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-literal-enum-member.shot b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/prefer-literal-enum-member.shot index e76ab73c8869..c9938b4bbb47 100644 --- 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 @@ -4,20 +4,69 @@ exports[`Validating rule docs prefer-literal-enum-member.mdx code examples ESLin "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-readonly-parameter-types.shot b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/prefer-readonly-parameter-types.shot index e7b558ecb1e4..606039e2e781 100644 --- 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 @@ -58,3 +58,301 @@ interface Foo { } " `; + +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/space-before-blocks.shot b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/space-before-blocks.shot index e2c174055b1d..74158461fac1 100644 --- 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 @@ -4,20 +4,30 @@ exports[`Validating rule docs space-before-blocks.mdx code examples ESLint outpu "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/switch-exhaustiveness-check.shot b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/switch-exhaustiveness-check.shot index f2272066c660..1b2fd682199f 100644 --- 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 @@ -109,30 +109,68 @@ exports[`Validating rule docs switch-exhaustiveness-check.mdx code examples ESLi "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; } -~ " `; From 86f1a867e9e24ad3b3f5bf2302228fd8bf6caa21 Mon Sep 17 00:00:00 2001 From: Josh Goldberg Date: Mon, 22 Apr 2024 16:46:33 -0400 Subject: [PATCH 09/10] Fix unit tests for Windows --- packages/typescript-estree/tests/lib/inferSingleRun.test.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/typescript-estree/tests/lib/inferSingleRun.test.ts b/packages/typescript-estree/tests/lib/inferSingleRun.test.ts index 769fb62df4a1..e91087de0cb4 100644 --- a/packages/typescript-estree/tests/lib/inferSingleRun.test.ts +++ b/packages/typescript-estree/tests/lib/inferSingleRun.test.ts @@ -1,5 +1,4 @@ import path from 'path'; - import { inferSingleRun } from '../../src/parseSettings/inferSingleRun'; describe('inferSingleRun', () => { From fa48c8846d0e1b6b13fca54923197600b0826023 Mon Sep 17 00:00:00 2001 From: Josh Goldberg Date: Mon, 22 Apr 2024 16:46:51 -0400 Subject: [PATCH 10/10] lint --- packages/typescript-estree/tests/lib/inferSingleRun.test.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/typescript-estree/tests/lib/inferSingleRun.test.ts b/packages/typescript-estree/tests/lib/inferSingleRun.test.ts index e91087de0cb4..769fb62df4a1 100644 --- a/packages/typescript-estree/tests/lib/inferSingleRun.test.ts +++ b/packages/typescript-estree/tests/lib/inferSingleRun.test.ts @@ -1,4 +1,5 @@ import path from 'path'; + import { inferSingleRun } from '../../src/parseSettings/inferSingleRun'; describe('inferSingleRun', () => { pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy