From d3cf5d8eaf5e9095e67a0743004e1f5e4effa5ed Mon Sep 17 00:00:00 2001 From: RebeccaStevens Date: Thu, 19 Dec 2024 03:07:32 +0000 Subject: [PATCH] feat(no-conditional-statements): add option `ignoreCodePattern` for ignoring if conditions (#909) --- docs/rules/no-conditional-statements.md | 9 +++++++++ src/rules/no-conditional-statements.ts | 19 ++++++++++++++----- tests/rules/no-conditional-statements.test.ts | 13 +++++++++++++ 3 files changed, 36 insertions(+), 5 deletions(-) diff --git a/docs/rules/no-conditional-statements.md b/docs/rules/no-conditional-statements.md index 12ef79a5d..607cc3d98 100644 --- a/docs/rules/no-conditional-statements.md +++ b/docs/rules/no-conditional-statements.md @@ -65,6 +65,7 @@ This rule accepts an options object of the following type: ```ts type Options = { allowReturningBranches: boolean | "ifExhaustive"; + ignoreCodePattern?: ReadonlyArray | string; }; ``` @@ -124,3 +125,11 @@ const x = (() => { Note: Currently this option is not useable with the [no-else-return](https://eslint.org/docs/rules/no-else-return) rule; `else` statements must contain a return statement. + +### `ignoreCodePattern` + +This option takes a RegExp string or an array of RegExp strings. +It allows for the ability to ignore violations based on the test condition of the `if` +statement. + +Note: This option has no effect on `switch` statements. diff --git a/src/rules/no-conditional-statements.ts b/src/rules/no-conditional-statements.ts index ff88b9f20..1c1479cae 100644 --- a/src/rules/no-conditional-statements.ts +++ b/src/rules/no-conditional-statements.ts @@ -1,9 +1,11 @@ import type { TSESTree } from "@typescript-eslint/utils"; -import type { JSONSchema4 } from "@typescript-eslint/utils/json-schema"; +import type { JSONSchema4, JSONSchema4ObjectSchema } from "@typescript-eslint/utils/json-schema"; import type { RuleContext } from "@typescript-eslint/utils/ts-eslint"; +import { deepmerge } from "deepmerge-ts"; import type { Type } from "typescript"; import tsApiUtils from "#/conditional-imports/ts-api-utils"; +import { type IgnoreCodePatternOption, ignoreCodePatternOptionSchema, shouldIgnorePattern } from "#/options"; import { ruleNameScope } from "#/utils/misc"; import { type NamedCreateRuleCustomMeta, type Rule, type RuleResult, createRule, getTypeOfNode } from "#/utils/rule"; import { @@ -32,7 +34,7 @@ export const fullName: `${typeof ruleNameScope}/${typeof name}` = `${ruleNameSco * The options this rule can take. */ type Options = [ - { + IgnoreCodePatternOption & { allowReturningBranches: boolean | "ifExhaustive"; }, ]; @@ -43,7 +45,7 @@ type Options = [ const schema: JSONSchema4[] = [ { type: "object", - properties: { + properties: deepmerge(ignoreCodePatternOptionSchema, { allowReturningBranches: { oneOf: [ { @@ -55,7 +57,7 @@ const schema: JSONSchema4[] = [ }, ], }, - }, + } satisfies JSONSchema4ObjectSchema["properties"]), additionalProperties: false, }, ]; @@ -273,7 +275,14 @@ function checkIfStatement( context: Readonly>, options: Readonly, ): RuleResult { - const [{ allowReturningBranches }] = options; + const [{ allowReturningBranches, ignoreCodePattern }] = options; + + if (shouldIgnorePattern(node.test, context, undefined, undefined, ignoreCodePattern)) { + return { + context, + descriptors: [], + }; + } return { context, diff --git a/tests/rules/no-conditional-statements.test.ts b/tests/rules/no-conditional-statements.test.ts index 10d84c1b7..04a2d24ef 100644 --- a/tests/rules/no-conditional-statements.test.ts +++ b/tests/rules/no-conditional-statements.test.ts @@ -132,6 +132,19 @@ describe(name, () => { }); }); }); + + describe("ignoreCodePattern", () => { + it("ignores matching conditionals", () => { + valid({ + code: dedent` + if (import.meta.vitest) { + const { it, expect } = import.meta.vitest; + } + `, + options: [{ ignoreCodePattern: ["import\\.meta\\.vitest"] }], + }); + }); + }); }); });