diff --git a/docs/rules/prefer-immutable-types.md b/docs/rules/prefer-immutable-types.md index 18be71d56..1c02fc0ac 100644 --- a/docs/rules/prefer-immutable-types.md +++ b/docs/rules/prefer-immutable-types.md @@ -244,6 +244,37 @@ type Options = { ReadonlyDeep?: Array>; Immutable?: Array>; }; + + overrides?: Array<{ + match: Array< + | { + from: "file"; + path?: string; + name?: string | string[]; + pattern?: RegExp | RegExp[]; + ignoreName?: string | string[]; + ignorePattern?: RegExp | RegExp[]; + } + | { + from: "lib"; + name?: string | string[]; + pattern?: RegExp | RegExp[]; + ignoreName?: string | string[]; + ignorePattern?: RegExp | RegExp[]; + } + | { + from: "package"; + package?: string; + name?: string | string[]; + pattern?: RegExp | RegExp[]; + ignoreName?: string | string[]; + ignorePattern?: RegExp | RegExp[]; + } + >; + options: Omit; + inherit?: boolean; + disable: boolean; + }>; }; ``` @@ -475,3 +506,29 @@ It allows for the ability to ignore violations based on the identifier (name) of This option takes a `RegExp` string or an array of `RegExp` strings. It allows for the ability to ignore violations based on the type (as written, with whitespace removed) of the node in question. + +### `overrides` + +Allows for applying overrides to the options based on the type's declaration. +This can be used to override the settings for types coming from 3rd party libraries. + +Note: Only the first matching override will be used. + +#### `overrides[n].specifiers` + +A specifier, or an array of specifiers to match the function type against. + +In the case of reference types, both the type and its generics will be recursively checked. +If any of them match, the specifier will be considered a match. + +#### `overrides[n].options` + +The options to use when a specifiers matches. + +#### `overrides[n].inherit` + +Inherit the root options? Default is `true`. + +#### `overrides[n].disable` + +If true, when a specifier matches, this rule will not be applied to the matching node. diff --git a/src/rules/prefer-immutable-types.ts b/src/rules/prefer-immutable-types.ts index c5199e5a2..cec620fcf 100644 --- a/src/rules/prefer-immutable-types.ts +++ b/src/rules/prefer-immutable-types.ts @@ -9,13 +9,19 @@ import { } from "@typescript-eslint/utils/ts-eslint"; import { deepmerge } from "deepmerge-ts"; import { Immutability } from "is-immutable-type"; +import { type Type, type TypeNode } from "typescript"; import { type IgnoreClassesOption, + type OverridableOptions, + type RawOverridableOptions, + getCoreOptions, + getCoreOptionsForType, ignoreClassesOptionSchema, shouldIgnoreClasses, shouldIgnoreInFunction, shouldIgnorePattern, + upgradeRawOverridableOptions, } from "#eslint-plugin-functional/options"; import { ruleNameScope } from "#eslint-plugin-functional/utils/misc"; import { type ESFunctionType } from "#eslint-plugin-functional/utils/node-types"; @@ -24,6 +30,7 @@ import { type RuleResult, createRule, getReturnTypesOfFunction, + getTypeDataOfNode, getTypeImmutabilityOfNode, getTypeImmutabilityOfType, isImplementationOfOverload, @@ -42,6 +49,8 @@ import { isTSTypePredicate, } from "#eslint-plugin-functional/utils/type-guards"; +import { overridableOptionsSchema } from "../utils/schemas"; + /** * The name of this rule. */ @@ -55,7 +64,8 @@ export const fullName = `${ruleNameScope}/${name}`; type RawEnforcement = | Exclude | "None" - | false; + | false + | undefined; type Option = IgnoreClassesOption & { enforcement: RawEnforcement; @@ -64,6 +74,20 @@ type Option = IgnoreClassesOption & { ignoreTypePattern?: string[] | string; }; +type CoreOptions = Option & { + parameters?: Partial