Repository: eslint-functional/eslint-plugin-functional
Pull request #909 (2024-12-19 03:05:30)

feat(no-conditional-statements): add option `ignoreCodePattern` for ignoring if conditions

graphite-app[bot]: ## How to use the Graphite Merge Queue

Add either label to this PR to merge it via the merge queue:
- <kbd>Status: Merge Queue</kbd> - adds this PR to the back of the merge queue
- <kbd>Status: Hotfix</kbd> - for urgent hot fixes, skip the queue and merge this PR next

You must have a Graphite account in order to use the merge queue. Sign up using [this link](https://app.graphite.dev/invite/github/eslint-functional?ref=merge-queue-instructions-comment&prId=5719759746).

<h2></h2>
<sub>

An organization admin has enabled the [Graphite Merge Queue](https://graphite.dev/docs/graphite-merge-queue) in this repository.

</sub>

<sub>

Please do not merge from GitHub as this will restart CI on PRs being processed by the merge queue.

</sub>
RebeccaStevens: ### Merge activity

* **Dec 18, 10:07 PM EST**: The merge label 'Status: Merge Queue' was detected. This PR will be added to the [Graphite merge queue](https://app.graphite.dev/merges?org=eslint-functional&repo=eslint-plugin-functional) once it meets the requirements.


Patch:
diff --git a/docs/rules/no-conditional-statements.md b/docs/rules/no-conditional-statements.md
index 12ef79a..607cc3d 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> | 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 ff88b9f..1c1479c 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<RuleContext<keyof typeof errorMessages, Options>>,
   options: Readonly<Options>,
 ): RuleResult<keyof typeof errorMessages, Options> {
-  const [{ allowReturningBranches }] = options;
+  const [{ allowReturningBranches, ignoreCodePattern }] = options;
+
+  if (shouldIgnorePattern(node.test, context, undefined, undefined, ignoreCodePattern)) {
+    return {
+      context,
+      descriptors: [],
+    };
+  }
 
   return {
     context,


Test patch:
diff --git a/tests/rules/no-conditional-statements.test.ts b/tests/rules/no-conditional-statements.test.ts
index 10d84c1..04a2d24 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"] }],
+            });
+          });
+        });
       });
     });