UNPKG

eslint-plugin-functional

Version:
4,328 lines 139 kB
'use strict';

var deepmergeTs = require('deepmerge-ts');
var utils = require('@typescript-eslint/utils');
var eslintUtils = require('@typescript-eslint/utils/eslint-utils');
var isImmutableType = require('is-immutable-type');
var escapeRegExp = require('escape-string-regexp');
var semver = require('semver');

function _interopNamespaceDefault(e) {
  var n = Object.create(null);
  if (e) {
    Object.keys(e).forEach(function (k) {
      if (k !== 'default') {
        var d = Object.getOwnPropertyDescriptor(e, k);
        Object.defineProperty(n, k, d.get ? d : {
          enumerable: true,
          get: function () { return e[k]; }
        });
      }
    });
  }
  n.default = e;
  return Object.freeze(n);
}

var semver__namespace = /*#__PURE__*/_interopNamespaceDefault(semver);

var ts = (() => {
    try {
        return require("typescript");
    }
    catch {
        return undefined;
    }
})();

/**
 * @file Functions that type guard the given node/type.
 */
/*
 * Node type guards.
 */
function isArrayExpression(node) {
    return node.type === utils.AST_NODE_TYPES.ArrayExpression;
}
function isArrayPattern(node) {
    return node.type === utils.AST_NODE_TYPES.ArrayPattern;
}
function isAssignmentExpression(node) {
    return node.type === utils.AST_NODE_TYPES.AssignmentExpression;
}
function isAssignmentPattern(node) {
    return node.type === utils.AST_NODE_TYPES.AssignmentPattern;
}
function isBlockStatement(node) {
    return node.type === utils.AST_NODE_TYPES.BlockStatement;
}
function isBreakStatement(node) {
    return node.type === utils.AST_NODE_TYPES.BreakStatement;
}
function isCallExpression(node) {
    return node.type === utils.AST_NODE_TYPES.CallExpression;
}
function isPropertyDefinition(node) {
    return node.type === utils.AST_NODE_TYPES.PropertyDefinition;
}
/**
 * Is the given node a class node?
 *
 * It doesn't matter what type of class.
 */
function isClassLike(node) {
    return (node.type === utils.AST_NODE_TYPES.ClassDeclaration ||
        node.type === utils.AST_NODE_TYPES.ClassExpression);
}
function isContinueStatement(node) {
    return node.type === utils.AST_NODE_TYPES.ContinueStatement;
}
function isExpressionStatement(node) {
    return node.type === utils.AST_NODE_TYPES.ExpressionStatement;
}
function isForStatement(node) {
    return node.type === utils.AST_NODE_TYPES.ForStatement;
}
function isFunctionDeclaration(node) {
    return node.type === utils.AST_NODE_TYPES.FunctionDeclaration;
}
/**
 * Is the given node a function expression node?
 *
 * It doesn't matter what type of function expression.
 */
function isFunctionExpressionLike(node) {
    return (node.type === utils.AST_NODE_TYPES.FunctionExpression ||
        node.type === utils.AST_NODE_TYPES.ArrowFunctionExpression);
}
/**
 * Is the given node a function node?
 *
 * It doesn't matter what type of function.
 */
function isFunctionLike(node) {
    return isFunctionDeclaration(node) || isFunctionExpressionLike(node);
}
function isIdentifier(node) {
    return node.type === utils.AST_NODE_TYPES.Identifier;
}
function isIfStatement(node) {
    return node.type === utils.AST_NODE_TYPES.IfStatement;
}
function isMemberExpression(node) {
    return node.type === utils.AST_NODE_TYPES.MemberExpression;
}
function isMethodDefinition(node) {
    return node.type === utils.AST_NODE_TYPES.MethodDefinition;
}
function isNewExpression(node) {
    return node.type === utils.AST_NODE_TYPES.NewExpression;
}
function isObjectExpression(node) {
    return node.type === utils.AST_NODE_TYPES.ObjectExpression;
}
function isObjectPattern(node) {
    return node.type === utils.AST_NODE_TYPES.ObjectPattern;
}
function isPrivateIdentifier(node) {
    return node.type === utils.AST_NODE_TYPES.PrivateIdentifier;
}
function isProgram(node) {
    return node.type === utils.AST_NODE_TYPES.Program;
}
function isProperty(node) {
    return node.type === utils.AST_NODE_TYPES.Property;
}
function isRestElement(node) {
    return node.type === utils.AST_NODE_TYPES.RestElement;
}
function isReturnStatement(node) {
    return node.type === utils.AST_NODE_TYPES.ReturnStatement;
}
function isSwitchStatement(node) {
    return node.type === utils.AST_NODE_TYPES.SwitchStatement;
}
function isThisExpression(node) {
    return node.type === utils.AST_NODE_TYPES.ThisExpression;
}
function isThrowStatement(node) {
    return node.type === utils.AST_NODE_TYPES.ThrowStatement;
}
function isTSArrayType(node) {
    return node.type === utils.AST_NODE_TYPES.TSArrayType;
}
function isTSAsExpression(node) {
    return node.type === utils.AST_NODE_TYPES.TSAsExpression;
}
function isTSFunctionType(node) {
    return node.type === utils.AST_NODE_TYPES.TSFunctionType;
}
function isTSIndexSignature(node) {
    return node.type === utils.AST_NODE_TYPES.TSIndexSignature;
}
function isTSMethodSignature(node) {
    return node.type === utils.AST_NODE_TYPES.TSMethodSignature;
}
function isTSCallSignatureDeclaration(node) {
    return node.type === utils.AST_NODE_TYPES.TSCallSignatureDeclaration;
}
function isTSConstructSignatureDeclaration(node) {
    return node.type === utils.AST_NODE_TYPES.TSConstructSignatureDeclaration;
}
function isTSInterfaceBody(node) {
    return node.type === utils.AST_NODE_TYPES.TSInterfaceBody;
}
function isTSInterfaceDeclaration(node) {
    return node.type === utils.AST_NODE_TYPES.TSInterfaceDeclaration;
}
function isTSInterfaceHeritage(node) {
    return node.type === utils.AST_NODE_TYPES.TSInterfaceHeritage;
}
function isTSNullKeyword(node) {
    return node.type === utils.AST_NODE_TYPES.TSNullKeyword;
}
function isTSParameterProperty(node) {
    return node.type === utils.AST_NODE_TYPES.TSParameterProperty;
}
function isTSPropertySignature(node) {
    return node.type === utils.AST_NODE_TYPES.TSPropertySignature;
}
function isTSTupleType(node) {
    return node.type === utils.AST_NODE_TYPES.TSTupleType;
}
function isTSTypeAnnotation(node) {
    return node.type === utils.AST_NODE_TYPES.TSTypeAnnotation;
}
function isTSTypeLiteral(node) {
    return node.type === utils.AST_NODE_TYPES.TSTypeLiteral;
}
function isTSTypeOperator(node) {
    return node.type === utils.AST_NODE_TYPES.TSTypeOperator;
}
function isTSTypePredicate(node) {
    return node.type === utils.AST_NODE_TYPES.TSTypePredicate;
}
function isTSTypeReference(node) {
    return node.type === utils.AST_NODE_TYPES.TSTypeReference;
}
function isTSUndefinedKeyword(node) {
    return node.type === utils.AST_NODE_TYPES.TSUndefinedKeyword;
}
function isTSVoidKeyword(node) {
    return node.type === utils.AST_NODE_TYPES.TSVoidKeyword;
}
function isUnaryExpression(node) {
    return node.type === utils.AST_NODE_TYPES.UnaryExpression;
}
function isVariableDeclaration(node) {
    return node.type === utils.AST_NODE_TYPES.VariableDeclaration;
}
function isYieldExpression(node) {
    return node.type === utils.AST_NODE_TYPES.YieldExpression;
}
function hasID(node) {
    return Object.hasOwn(node, "id");
}
function hasKey(node) {
    return Object.hasOwn(node, "key");
}
function isDefined(value) {
    return value !== null && value !== undefined;
}
/*
 * TS types type guards.
 */
function isUnionType(type) {
    return ts !== undefined && type.flags === ts.TypeFlags.Union;
}
function isArrayType(type) {
    return (type !== null &&
        ((type.symbol !== undefined && type.symbol.name === "Array") ||
            (isUnionType(type) && type.types.some(isArrayType))));
}
function isArrayConstructorType(type) {
    return (type !== null &&
        ((type.symbol !== undefined &&
            type.symbol.name === "ArrayConstructor") ||
            (isUnionType(type) && type.types.some(isArrayConstructorType))));
}
function isObjectConstructorType(type) {
    return (type !== null &&
        ((type.symbol !== undefined &&
            type.symbol.name === "ObjectConstructor") ||
            (isUnionType(type) && type.types.some(isObjectConstructorType))));
}
function isFunctionLikeType(type) {
    return type !== null && type.getCallSignatures().length > 0;
}

/**
 * Return the first ancestor that meets the given check criteria.
 */
function getAncestorOfType(checker, node, child = null) {
    return checker(node, child)
        ? node
        : isDefined(node.parent)
            ? getAncestorOfType(checker, node.parent, node)
            : null;
}
/**
 * Test if the given node is in a function's body.
 *
 * @param node - The node to test.
 * @param async - Whether the function must be async or sync. Use `undefined` for either.
 */
function isInFunctionBody(node, async) {
    const functionNode = getAncestorOfType((n, c) => isFunctionLike(n) && n.body === c, node);
    return (functionNode !== null &&
        (async === undefined || functionNode.async === async));
}
/**
 * Test if the given node is in a class.
 */
function isInClass(node) {
    return getAncestorOfType(isClassLike, node) !== null;
}
/**
 * Test if the given node is in a for loop initializer.
 */
function isInForLoopInitializer(node) {
    return (getAncestorOfType((n, c) => isForStatement(n) && n.init === c, node) !== null);
}
/**
 * Test if the given node is shallowly inside a `Readonly<{...}>`.
 */
function isInReadonly(node) {
    return getReadonly(node) !== null;
}
/**
 * Test if the given node is shallowly inside a `Readonly<{...}>`.
 */
function getReadonly(node) {
    // For nested cases, we shouldn't look for any parent, but the immediate parent.
    if (isDefined(node.parent) &&
        isTSTypeLiteral(node.parent) &&
        isDefined(node.parent.parent) &&
        isTSTypeAnnotation(node.parent.parent)) {
        return null;
    }
    const typeRef = getAncestorOfType(isTSTypeReference, node);
    const intHeritage = getAncestorOfType(isTSInterfaceHeritage, node);
    const expressionOrTypeName = typeRef?.typeName ?? intHeritage?.expression;
    return expressionOrTypeName !== undefined &&
        isIdentifier(expressionOrTypeName) &&
        expressionOrTypeName.name === "Readonly"
        ? typeRef ?? intHeritage
        : null;
}
/**
 * Test if the given node is in a TS Property Signature.
 */
function isInInterface(node) {
    return getAncestorOfType(isTSInterfaceBody, node) !== null;
}
/**
 * Test if the given node is in a Constructor.
 */
function isInConstructor(node) {
    const methodDefinition = getAncestorOfType(isMethodDefinition, node);
    return (methodDefinition !== null &&
        isIdentifier(methodDefinition.key) &&
        methodDefinition.key.name === "constructor");
}
/**
 * Is the given node in the return type.
 */
function isInReturnType(node) {
    return (getAncestorOfType((n) => isDefined(n.parent) &&
        isFunctionLike(n.parent) &&
        n.parent.returnType === n, node) !== null);
}
/**
 * Test if the given node is nested inside another statement.
 */
function isNested(node) {
    return (node.parent !== undefined &&
        !(isProgram(node.parent) || isBlockStatement(node.parent)));
}
/**
 * Is the given identifier a property of an object?
 */
function isPropertyAccess(node) {
    return (node.parent !== undefined &&
        isMemberExpression(node.parent) &&
        node.parent.property === node);
}
/**
 * Is the given identifier a property name?
 */
function isPropertyName(node) {
    return (node.parent !== undefined &&
        isProperty(node.parent) &&
        node.parent.key === node);
}
/**
 * Is the given function an IIFE?
 */
function isIIFE(node) {
    return (isFunctionExpressionLike(node) &&
        node.parent !== undefined &&
        isCallExpression(node.parent) &&
        node.parent.callee === node);
}
/**
 * Is the given node being passed as an argument?
 */
function isArgument(node) {
    return (node.parent !== undefined &&
        isCallExpression(node.parent) &&
        // eslint-disable-next-line @typescript-eslint/no-unsafe-argument
        node.parent.arguments.includes(node));
}
/**
 * Is the given node a parameter?
 */
function isParameter(node) {
    return (node.parent !== undefined &&
        isFunctionLike(node.parent) &&
        // eslint-disable-next-line @typescript-eslint/no-unsafe-argument
        node.parent.params.includes(node));
}
/**
 * Is the given node a getter function?
 */
function isGetter(node) {
    return (node.parent !== undefined &&
        isProperty(node.parent) &&
        node.parent.kind === "get");
}
/**
 * Is the given node a setter function?
 */
function isSetter(node) {
    return (node.parent !== undefined &&
        isProperty(node.parent) &&
        node.parent.kind === "set");
}
/**
 * Get the key the given node is assigned to in its parent ObjectExpression.
 */
function getKeyOfValueInObjectExpression(node) {
    if (!isDefined(node.parent)) {
        return null;
    }
    const objectExpression = getAncestorOfType(isObjectExpression, node);
    if (objectExpression === null) {
        return null;
    }
    const objectExpressionProps = objectExpression.properties.filter((prop) => isProperty(prop) && prop.value === node);
    if (objectExpressionProps.length !== 1) {
        return null;
    }
    const objectExpressionProp = objectExpressionProps[0];
    if (!isProperty(objectExpressionProp) ||
        !isIdentifier(objectExpressionProp.key)) {
        return null;
    }
    return objectExpressionProp.key.name;
}
/**
 * Is the given identifier defined by a mutable variable (let or var)?
 */
function isDefinedByMutableVariable(node, context, treatParametersAsMutable) {
    const services = eslintUtils.getParserServices(context);
    const symbol = services.getSymbolAtLocation(node);
    const variableDeclaration = symbol?.valueDeclaration;
    if (variableDeclaration === undefined) {
        return true;
    }
    const variableDeclarationNode = services.tsNodeToESTreeNodeMap.get(variableDeclaration);
    if (variableDeclarationNode !== undefined &&
        isParameter(variableDeclarationNode)) {
        return treatParametersAsMutable(variableDeclarationNode);
    }
    if (!ts.isVariableDeclaration(variableDeclaration)) {
        return true;
    }
    const variableDeclarator = context.parserServices?.tsNodeToESTreeNodeMap.get(variableDeclaration);
    if (variableDeclarator?.parent === undefined ||
        !isVariableDeclaration(variableDeclarator.parent)) {
        return true;
    }
    return variableDeclarator.parent.kind !== "const";
}
/**
 * Get the root identifier of an expression.
 */
function findRootIdentifier(node) {
    if (isIdentifier(node)) {
        return node;
    }
    if (isMemberExpression(node)) {
        return findRootIdentifier(node.object);
    }
    return undefined;
}

const ruleNameScope = "functional";
/**
 * Higher order function to check if the two given values are the same.
 */
function isExpected(expected) {
    return (actual) => actual === expected;
}
/**
 * Does the given ExpressionStatement specify directive prologues.
 */
function isDirectivePrologue(node) {
    return (node.expression.type === utils.AST_NODE_TYPES.Literal &&
        typeof node.expression.value === "string" &&
        node.expression.value.startsWith("use "));
}
/**
 * Get the identifier text of the given node.
 */
function getNodeIdentifierText(node, context) {
    if (!isDefined(node)) {
        return undefined;
    }
    const identifierText = isIdentifier(node) || isPrivateIdentifier(node)
        ? node.name
        : hasID(node) && isDefined(node.id)
            ? getNodeIdentifierText(node.id, context)
            : hasKey(node) && isDefined(node.key)
                ? getNodeIdentifierText(node.key, context)
                : isAssignmentExpression(node)
                    ? getNodeIdentifierText(node.left, context)
                    : isMemberExpression(node)
                        ? `${getNodeIdentifierText(node.object, context)}.${getNodeIdentifierText(node.property, context)}`
                        : isThisExpression(node)
                            ? "this"
                            : isUnaryExpression(node)
                                ? getNodeIdentifierText(node.argument, context)
                                : isTSTypeAnnotation(node)
                                    ? context.sourceCode
                                        .getText(node.typeAnnotation)
                                        .replaceAll(/\s+/gmu, "")
                                    : isTSAsExpression(node)
                                        ? getNodeIdentifierText(node.expression, context)
                                        : null;
    if (identifierText !== null) {
        return identifierText;
    }
    const keyInObjectExpression = getKeyOfValueInObjectExpression(node);
    if (keyInObjectExpression !== null) {
        return keyInObjectExpression;
    }
    return undefined;
}
/**
 * Get the code of the given node.
 */
function getNodeCode(node, context) {
    return context.sourceCode.getText(node);
}
/**
 * Get all the identifier texts of the given node.
 */
function getNodeIdentifierTexts(node, context) {
    return (isVariableDeclaration(node)
        ? node.declarations.flatMap((declarator) => getNodeIdentifierText(declarator, context))
        : [getNodeIdentifierText(node, context)]).filter((text) => text !== undefined);
}

/**
 * The schema for the option to ignore patterns.
 */
const ignoreIdentifierPatternOptionSchema = {
    ignoreIdentifierPattern: {
        type: ["string", "array"],
        items: {
            type: "string",
        },
    },
};
/**
 * The schema for the option to ignore patterns.
 */
const ignoreCodePatternOptionSchema = {
    ignoreCodePattern: {
        type: ["string", "array"],
        items: {
            type: "string",
        },
    },
};
/**
 * The schema for the option to ignore accessor patterns.
 */
const ignoreAccessorPatternOptionSchema = {
    ignoreAccessorPattern: {
        type: ["string", "array"],
        items: {
            type: "string",
        },
    },
};
/**
 * The schema for the option to ignore classes.
 */
const ignoreClassesOptionSchema = {
    ignoreClasses: {
        oneOf: [
            {
                type: "boolean",
            },
            {
                type: "string",
                enum: ["fieldsOnly"],
            },
        ],
    },
};
/**
 * The schema for the option to ignore prefix selector.
 */
const ignorePrefixSelectorOptionSchema = {
    ignorePrefixSelector: {
        type: ["string", "array"],
        items: {
            type: "string",
        },
    },
};
/**
 * Should the given text be allowed?
 *
 * Test using the given pattern(s).
 */
function shouldIgnoreViaPattern(text, pattern) {
    const patterns = Array.isArray(pattern) ? pattern : [pattern];
    // One or more patterns match?
    return patterns.some((p) => new RegExp(p, "u").test(text));
}
/**
 * Recursive callback of `shouldIgnoreViaAccessorPattern`.
 *
 * This function not be called from anywhere else.
 *
 * Does the given text match the given pattern.
 */
function accessorPatternMatch([pattern, ...remainingPatternParts], textParts, allowExtra = false) {
    return pattern === undefined
        ? allowExtra || textParts.length === 0
        : // Match any depth (including 0)?
            pattern === "**"
                ? textParts.length === 0
                    ? accessorPatternMatch(remainingPatternParts, [], allowExtra)
                    : Array.from({ length: textParts.length })
                        .map((element, index) => index)
                        .some((offset) => accessorPatternMatch(remainingPatternParts, textParts.slice(offset), true))
                : // Match anything?
                    pattern === "*"
                        ? textParts.length > 0 &&
                            accessorPatternMatch(remainingPatternParts, textParts.slice(1), allowExtra)
                        : // Text matches pattern?
                            new RegExp(`^${escapeRegExp(pattern).replaceAll("\\*", ".*")}$`, "u").test(textParts[0]) &&
                                accessorPatternMatch(remainingPatternParts, textParts.slice(1), allowExtra);
}
/**
 * Should the given text be allowed?
 *
 * Test using the given accessor pattern(s).
 */
function shouldIgnoreViaAccessorPattern(text, pattern) {
    const patterns = Array.isArray(pattern) ? pattern : [pattern];
    // One or more patterns match?
    return patterns.some((p) => accessorPatternMatch(p.split("."), text.split(".")));
}
/**
 * Should the given node be allowed base off the following rule options?
 *
 * - AllowInFunctionOption.
 */
function shouldIgnoreInFunction(node, context, allowInFunction) {
    return allowInFunction === true && isInFunctionBody(node);
}
/**
 * Should the given node be allowed base off the following rule options?
 *
 * - IgnoreClassesOption.
 */
function shouldIgnoreClasses(node, context, ignoreClasses) {
    return ((ignoreClasses === true && (isClassLike(node) || isInClass(node))) ||
        (ignoreClasses === "fieldsOnly" &&
            (isPropertyDefinition(node) ||
                (isAssignmentExpression(node) &&
                    isInClass(node) &&
                    isMemberExpression(node.left) &&
                    isThisExpression(node.left.object)))));
}
/**
 * Should the given node be allowed base off the following rule options?
 *
 * - IgnoreAccessorPatternOption.
 * - IgnoreIdentifierPatternOption.
 */
function shouldIgnorePattern(node, context, ignoreIdentifierPattern, ignoreAccessorPattern, ignoreCodePattern) {
    const texts = getNodeIdentifierTexts(node, context);
    if (texts.length === 0) {
        return (ignoreCodePattern !== undefined &&
            shouldIgnoreViaPattern(getNodeCode(node, context), ignoreCodePattern));
    }
    return (
    // Ignore if ignoreIdentifierPattern is set and a pattern matches.
    (ignoreIdentifierPattern !== undefined &&
        texts.every((text) => shouldIgnoreViaPattern(text, ignoreIdentifierPattern))) ||
        // Ignore if ignoreAccessorPattern is set and an accessor pattern matches.
        (ignoreAccessorPattern !== undefined &&
            texts.every((text) => shouldIgnoreViaAccessorPattern(text, ignoreAccessorPattern))) ||
        // Ignore if ignoreCodePattern is set and a code pattern matches.
        (ignoreCodePattern !== undefined &&
            shouldIgnoreViaPattern(getNodeCode(node, context), ignoreCodePattern)));
}

/**
 * The settings that have been loaded - so we don't have to reload them.
 */
const cachedSettings = new WeakMap();
/**
 * Get the immutability overrides defined in the settings.
 */
function getImmutabilityOverrides({ immutability, }) {
    if (immutability === undefined) {
        return undefined;
    }
    if (!cachedSettings.has(immutability)) {
        const overrides = loadImmutabilityOverrides(immutability);
        // eslint-disable-next-line functional/no-expression-statements
        cachedSettings.set(immutability, overrides);
        return overrides;
    }
    return cachedSettings.get(immutability);
}
/**
 * Get all the overrides and upgrade them.
 */
function loadImmutabilityOverrides(immutabilitySettings) {
    const overridesSetting = immutabilitySettings?.overrides;
    if (overridesSetting === undefined) {
        return undefined;
    }
    const raw = Array.isArray(overridesSetting)
        ? overridesSetting
        : overridesSetting.values ?? [];
    const upgraded = raw.map((rawValue) => {
        const { type, to, from, ...rest } = rawValue;
        const value = {
            type,
            to: typeof to === "string" ? isImmutableType.Immutability[to] : to,
            from: from === undefined
                ? undefined
                : typeof from === "string"
                    ? isImmutableType.Immutability[from]
                    : from,
        };
        /* c8 ignore start */
        if (value.type === undefined) {
            // eslint-disable-next-line functional/no-throw-statements
            throw new Error(`Override is missing required "type" property. Value: "${JSON.stringify(rawValue)}"`);
        }
        if (value.to === undefined) {
            // eslint-disable-next-line functional/no-throw-statements
            throw new Error(`Override is missing required "to" property. Value: "${JSON.stringify(rawValue)}"`);
        }
        const restKeys = Object.keys(rest);
        if (restKeys.length > 0) {
            // eslint-disable-next-line functional/no-throw-statements
            throw new Error(`Override is contains unknown property(s) "${restKeys.join(", ")}". Value: "${JSON.stringify(rawValue)}"`);
        }
        /* c8 ignore stop */
        return value;
    });
    const keepDefault = Array.isArray(overridesSetting) || overridesSetting.keepDefault !== false;
    return keepDefault
        ? [...isImmutableType.getDefaultOverrides(), ...upgraded]
        : upgraded;
}

// eslint-disable-next-line @typescript-eslint/naming-convention -- This is a special var.
const __VERSION__ = "0.0.0-development";

// This function can't be functional as it needs to interact with 3rd-party
// libraries that aren't functional.
/* eslint-disable functional/no-return-void, functional/no-expression-statements */
/**
 * Create a function that processes common options and then runs the given
 * check.
 */
function checkNode(check, context, options) {
    return (node) => {
        const result = check(node, context, options);
        // eslint-disable-next-line functional/no-loop-statements -- can't really be avoided.
        for (const descriptor of result.descriptors) {
            result.context.report(descriptor);
        }
    };
}
/* eslint-enable functional/no-return-void, functional/no-expression-statements */
/**
 * Create a rule.
 */
function createRule(name, meta, defaultOptions, ruleFunctionsMap) {
    return createRuleUsingFunction(name, meta, defaultOptions, () => ruleFunctionsMap);
}
/**
 * Create a rule.
 */
function createRuleUsingFunction(name, meta, defaultOptions, createFunction) {
    const ruleCreator = eslintUtils.RuleCreator((ruleName) => `https://github.com/eslint-functional/eslint-plugin-functional/blob/v6.5.1/docs/rules/${ruleName}.md`);
    return ruleCreator({
        name,
        meta: meta,
        defaultOptions,
        create: (context, options) => {
            const ruleFunctionsMap = createFunction(context, options);
            return Object.fromEntries(Object.entries(ruleFunctionsMap).map(([nodeSelector, ruleFunction]) => [
                nodeSelector,
                // prettier-ignore
                checkNode(ruleFunction, context, options),
            ]));
        },
    });
}
/**
 * Get the type of the the given node.
 */
function getTypeOfNode(node, context) {
    const { esTreeNodeToTSNodeMap } = eslintUtils.getParserServices(context);
    const tsNode = esTreeNodeToTSNodeMap.get(node);
    return getTypeOfTSNode(tsNode, context);
}
/**
 * Get the type of the the given ts node.
 */
function getTypeOfTSNode(node, context) {
    const { program } = eslintUtils.getParserServices(context);
    const checker = program.getTypeChecker();
    const nodeType = checker.getTypeAtLocation(node);
    const constrained = checker.getBaseConstraintOfType(nodeType);
    return constrained ?? nodeType;
}
/**
 * Get the return type of the the given function node.
 */
function getReturnTypesOfFunction(node, context) {
    if (ts === undefined) {
        return null;
    }
    const parserServices = eslintUtils.getParserServices(context);
    const checker = parserServices.program.getTypeChecker();
    const type = getTypeOfNode(node, context);
    const signatures = checker.getSignaturesOfType(type, ts.SignatureKind.Call);
    return signatures.map((signature) => checker.getReturnTypeOfSignature(signature));
}
/**
 * Does the given function have overloads?
 */
function isImplementationOfOverload(func, context) {
    if (ts === undefined) {
        return false;
    }
    const parserServices = eslintUtils.getParserServices(context);
    const checker = parserServices.program.getTypeChecker();
    const signature = parserServices.esTreeNodeToTSNodeMap.get(func);
    return checker.isImplementationOfOverload(signature) === true;
}
/**
 * Get the type immutability of the the given node or type.
 */
function getTypeImmutabilityOfNode(node, context, maxImmutability, explicitOverrides) {
    if (ts === undefined) {
        return isImmutableType.Immutability.Unknown;
    }
    const parserServices = eslintUtils.getParserServices(context);
    const overrides = explicitOverrides ?? getImmutabilityOverrides(context.settings);
    const tsNode = parserServices.esTreeNodeToTSNodeMap.get(node);
    const typedNode = ts.isIdentifier(tsNode) ? tsNode.parent : tsNode;
    const typeLike = typedNode.type ??
        getTypeOfNode(parserServices.tsNodeToESTreeNodeMap.get(typedNode), context);
    return isImmutableType.getTypeImmutability(parserServices.program, typeLike, overrides, 
    // Don't use the global cache in testing environments as it may cause errors when switching between different config options.
    process.env["NODE_ENV"] !== "test", maxImmutability);
}
/**
 * Get the type immutability of the the given type.
 */
function getTypeImmutabilityOfType(typeOrTypeNode, context, maxImmutability, explicitOverrides) {
    const parserServices = eslintUtils.getParserServices(context);
    const overrides = explicitOverrides ?? getImmutabilityOverrides(context.settings);
    return isImmutableType.getTypeImmutability(parserServices.program, typeOrTypeNode, overrides, 
    // Don't use the global cache in testing environments as it may cause errors when switching between different config options.
    process.env["NODE_ENV"] !== "test", maxImmutability);
}

/**
 * The name of this rule.
 */
const name$i = "functional-parameters";
/**
 * The full name of this rule.
 */
const fullName$9 = `${ruleNameScope}/${name$i}`;
/**
 * The schema for the rule options.
 */
const schema$i = [
    {
        type: "object",
        properties: deepmergeTs.deepmerge(ignoreIdentifierPatternOptionSchema, ignorePrefixSelectorOptionSchema, {
            allowRestParameter: {
                type: "boolean",
            },
            allowArgumentsKeyword: {
                type: "boolean",
            },
            enforceParameterCount: {
                oneOf: [
                    {
                        type: "boolean",
                        enum: [false],
                    },
                    {
                        type: "string",
                        enum: ["atLeastOne", "exactlyOne"],
                    },
                    {
                        type: "object",
                        properties: {
                            count: {
                                type: "string",
                                enum: ["atLeastOne", "exactlyOne"],
                            },
                            ignoreGettersAndSetters: {
                                type: "boolean",
                            },
                            ignoreLambdaExpression: {
                                type: "boolean",
                            },
                            ignoreIIFE: {
                                type: "boolean",
                            },
                        },
                        additionalProperties: false,
                    },
                ],
            },
        }),
        additionalProperties: false,
    },
];
/**
 * The default options for the rule.
 */
const defaultOptions$i = [
    {
        allowRestParameter: false,
        allowArgumentsKeyword: false,
        enforceParameterCount: {
            count: "atLeastOne",
            ignoreLambdaExpression: false,
            ignoreIIFE: true,
            ignoreGettersAndSetters: true,
        },
    },
];
/**
 * The possible error messages.
 */
const errorMessages$i = {
    restParam: "Unexpected rest parameter. Use a regular parameter of type array instead.",
    arguments: "Unexpected use of `arguments`. Use regular function arguments instead.",
    paramCountAtLeastOne: "Functions must have at least one parameter.",
    paramCountExactlyOne: "Functions must have exactly one parameter.",
};
/**
 * The meta data for this rule.
 */
const meta$j = {
    type: "suggestion",
    docs: {
        category: "Currying",
        description: "Enforce functional parameters.",
        recommended: "recommended",
        recommendedSeverity: "error",
    },
    messages: errorMessages$i,
    schema: schema$i,
};
/**
 * Get the rest parameter violations.
 */
function getRestParamViolations([{ allowRestParameter }], node) {
    return !allowRestParameter &&
        node.params.length > 0 &&
        isRestElement(node.params.at(-1))
        ? [
            {
                node: node.params.at(-1),
                messageId: "restParam",
            },
        ]
        : [];
}
/**
 * Get the parameter count violations.
 */
function getParamCountViolations([{ enforceParameterCount }], node) {
    if (enforceParameterCount === false ||
        (node.params.length === 0 &&
            typeof enforceParameterCount === "object" &&
            ((enforceParameterCount.ignoreIIFE && isIIFE(node)) ||
                (enforceParameterCount.ignoreLambdaExpression && isArgument(node)) ||
                (enforceParameterCount.ignoreGettersAndSetters &&
                    (isGetter(node) || isSetter(node)))))) {
        return [];
    }
    if (node.params.length === 0 &&
        (enforceParameterCount === "atLeastOne" ||
            (typeof enforceParameterCount === "object" &&
                enforceParameterCount.count === "atLeastOne"))) {
        return [
            {
                node,
                messageId: "paramCountAtLeastOne",
            },
        ];
    }
    if (node.params.length !== 1 &&
        (enforceParameterCount === "exactlyOne" ||
            (typeof enforceParameterCount === "object" &&
                enforceParameterCount.count === "exactlyOne"))) {
        return [
            {
                node,
                messageId: "paramCountExactlyOne",
            },
        ];
    }
    return [];
}
/**
 * Check if the given function node has a reset parameter this rule.
 */
function checkFunction$3(node, context, options) {
    const [optionsObject] = options;
    const { ignoreIdentifierPattern } = optionsObject;
    if (shouldIgnorePattern(node, context, ignoreIdentifierPattern)) {
        return {
            context,
            descriptors: [],
        };
    }
    return {
        context,
        descriptors: [
            ...getRestParamViolations(options, node),
            ...getParamCountViolations(options, node),
        ],
    };
}
/**
 * Check if the given identifier is for the "arguments" keyword.
 */
function checkIdentifier(node, context, options) {
    const [optionsObject] = options;
    const { ignoreIdentifierPattern } = optionsObject;
    if (shouldIgnorePattern(node, context, ignoreIdentifierPattern)) {
        return {
            context,
            descriptors: [],
        };
    }
    const { allowArgumentsKeyword } = optionsObject;
    return {
        context,
        descriptors: !allowArgumentsKeyword &&
            node.name === "arguments" &&
            !isPropertyName(node) &&
            !isPropertyAccess(node)
            ? [
                {
                    node,
                    messageId: "arguments",
                },
            ]
            : [],
    };
}
// Create the rule.
const rule$i = createRuleUsingFunction(name$i, meta$j, defaultOptions$i, (context, options) => {
    const [optionsObject] = options;
    const { ignorePrefixSelector } = optionsObject;
    const baseFunctionSelectors = [
        "ArrowFunctionExpression",
        "FunctionDeclaration",
        "FunctionExpression",
    ];
    const ignoreSelectors = ignorePrefixSelector === undefined
        ? undefined
        : Array.isArray(ignorePrefixSelector)
            ? ignorePrefixSelector
            : [ignorePrefixSelector];
    const fullFunctionSelectors = baseFunctionSelectors.flatMap((baseSelector) => ignoreSelectors === undefined
        ? [baseSelector]
        : `:not(:matches(${ignoreSelectors.join(",")})) > ${baseSelector}`);
    return {
        ...Object.fromEntries(fullFunctionSelectors.map((selector) => [selector, checkFunction$3])),
        Identifier: checkIdentifier,
    };
});

/**
 * The name of this rule.
 */
const name$h = "immutable-data";
/**
 * The full name of this rule.
 */
const fullName$8 = `${ruleNameScope}/${name$h}`;
/**
 * The schema for the rule options.
 */
const schema$h = [
    {
        type: "object",
        properties: deepmergeTs.deepmerge(ignoreIdentifierPatternOptionSchema, ignoreAccessorPatternOptionSchema, ignoreClassesOptionSchema, {
            ignoreImmediateMutation: {
                type: "boolean",
            },
            ignoreNonConstDeclarations: {
                oneOf: [
                    {
                        type: "boolean",
                    },
                    {
                        type: "object",
                        properties: {
                            treatParametersAsConst: {
                                type: "boolean",
                            },
                        },
                        additionalProperties: false,
                    },
                ],
            },
        }),
        additionalProperties: false,
    },
];
/**
 * The default options for the rule.
 */
const defaultOptions$h = [
    {
        ignoreClasses: false,
        ignoreImmediateMutation: true,
        ignoreNonConstDeclarations: false,
    },
];
/**
 * The possible error messages.
 */
const errorMessages$h = {
    generic: "Modifying an existing object/array is not allowed.",
    object: "Modifying properties of existing object not allowed.",
    array: "Modifying an array is not allowed.",
};
/**
 * The meta data for this rule.
 */
const meta$i = {
    type: "suggestion",
    docs: {
        category: "No Mutations",
        description: "Enforce treating data as immutable.",
        recommended: "recommended",
        recommendedSeverity: "error",
        requiresTypeChecking: true,
    },
    messages: errorMessages$h,
    schema: schema$h,
};
/**
 * Array methods that mutate an array.
 *
 * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/prototype#Methods#Mutator_methods
 */
const arrayMutatorMethods = new Set([
    "copyWithin",
    "fill",
    "pop",
    "push",
    "reverse",
    "shift",
    "sort",
    "splice",
    "unshift",
]);
/**
 * Array methods that return a new object (or array) without mutating the original.
 *
 * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/prototype#Methods#Accessor_methods
 * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/prototype#Iteration_methods
 */
const arrayNewObjectReturningMethods = [
    "concat",
    "slice",
    "filter",
    "map",
    "reduce",
    "reduceRight",
];
/**
 * Array constructor functions that create a new array.
 *
 * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array#Methods
 */
const arrayConstructorFunctions = ["from", "of"];
/**
 * Object constructor functions that mutate an object.
 *
 * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object#Methods_of_the_Object_constructor
 */
const objectConstructorMutatorFunctions = new Set([
    "assign",
    "defineProperties",
    "defineProperty",
    "setPrototypeOf",
]);
/**
 * Object constructor functions that return new objects.
 */
const objectConstructorNewObjectReturningMethods = [
    "create",
    "entries",
    "fromEntries",
    "getOwnPropertyDescriptor",
    "getOwnPropertyDescriptors",
    "getOwnPropertyNames",
    "getOwnPropertySymbols",
    "groupBy",
    "keys",
    "values",
];
/**
 * String constructor functions that return new objects.
 *
 * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String#Methods
 */
const stringConstructorNewObjectReturningMethods = ["split"];
/**
 * Check if the given assignment expression violates this rule.
 */
function checkAssignmentExpression(node, context, options) {
    const [optionsObject] = options;
    const { ignoreIdentifierPattern, ignoreAccessorPattern, ignoreNonConstDeclarations, ignoreClasses, } = optionsObject;
    if (!isMemberExpression(node.left) ||
        shouldIgnoreClasses(node, context, ignoreClasses) ||
        shouldIgnorePattern(node, context, ignoreIdentifierPattern, ignoreAccessorPattern)) {
        return {
            context,
            descriptors: [],
        };
    }
    if (ignoreNonConstDeclarations !== false) {
        const rootIdentifier = findRootIdentifier(node.left.object);
        if (rootIdentifier !== undefined &&
            isDefinedByMutableVariable(rootIdentifier, context, (variableNode) => ignoreNonConstDeclarations === true ||
                !ignoreNonConstDeclarations.treatParametersAsConst ||
                shouldIgnorePattern(variableNode, context, ignoreIdentifierPattern, ignoreAccessorPattern))) {
            return {
                context,
                descriptors: [],
            };
        }
    }
    return {
        context,
        descriptors: 
        // Allow if in a constructor - allow for field initialization.
        isInConstructor(node) ? [] : [{ node, messageId: "generic" }],
    };
}
/**
 * Check if the given node violates this rule.
 */
function checkUnaryExpression(node, context, options) {
    const [optionsObject] = options;
    const { ignoreIdentifierPattern, ignoreAccessorPattern, ignoreNonConstDeclarations, ignoreClasses, } = optionsObject;
    if (!isMemberExpression(node.argument) ||
        shouldIgnoreClasses(node, context, ignoreClasses) ||
        shouldIgnorePattern(node, context, ignoreIdentifierPattern, ignoreAccessorPattern)) {
        return {
            context,
            descriptors: [],
        };
    }
    if (ignoreNonConstDeclarations !== false) {
        const rootIdentifier = findRootIdentifier(node.argument.object);
        if (rootIdentifier !== undefined &&
            isDefinedByMutableVariable(rootIdentifier, context, (variableNode) => ignoreNonConstDeclarations === true ||
                !ignoreNonConstDeclarations.treatParametersAsConst ||
                shouldIgnorePattern(variableNode, context, ignoreIdentifierPattern, ignoreAccessorPattern))) {
            return {
                context,
                descriptors: [],
            };
        }
    }
    return {
        context,
        descriptors: node.operator === "delete" ? [{ node, messageId: "generic" }] : [],
    };
}
/**
 * Check if the given node violates this rule.
 */
function checkUpdateExpression(node, context, options) {
    const [optionsObject] = options;
    const { ignoreIdentifierPattern, ignoreAccessorPattern, ignoreNonConstDeclarations, ignoreClasses, } = optionsObject;
    if (!isMemberExpression(node.argument) ||
        shouldIgnoreClasses(node.argument, context, ignoreClasses) ||
        shouldIgnorePattern(node.argument, context, ignoreIdentifierPattern, ignoreAccessorPattern)) {
        return {
            context,
            descriptors: [],
        };
    }
    if (ignoreNonConstDeclarations !== false) {
        const rootIdentifier = findRootIdentifier(node.argument.object);
        if (rootIdentifier !== undefined &&
            isDefinedByMutableVariable(rootIdentifier, context, (variableNode) => ignoreNonConstDeclarations === true ||
                !ignoreNonConstDeclarations.treatParametersAsConst ||
                shouldIgnorePattern(variableNode, context, ignoreIdentifierPattern, ignoreAccessorPattern))) {
            return {
                context,
                descriptors: [],
            };
        }
    }
    return {
        context,
        descriptors: [{ node, messageId: "generic" }],
    };
}
/**
 * Check if the given the given MemberExpression is part of a chain and
 * immediately follows a method/function call that returns a new array.
 *
 * If this is the case, then the given MemberExpression is allowed to be
 * a mutator method call.
 */
function isInChainCallAndFollowsNew(node, context) {
    if (isMemberExpression(node)) {
        return isInChainCallAndFollowsNew(node.object, context);
    }
    if (isTSAsExpression(node)) {
        return isInChainCallAndFollowsNew(node.expression, context);
    }
    // Check for: [0, 1, 2]
    if (isArrayExpression(node)) {
        return true;
    }
    // Check for: new Array()
    if (isNewExpression(node) &&
        isArrayConstructorType(getTypeOfNode(node.callee, context))) {
        return true;
    }
    if (isCallExpression(node) &&
        isMemberExpression(node.callee) &&
        isIdentifier(node.callee.property)) {
        // Check for: Array.from(iterable)
        if (arrayConstructorFunctions.some(isExpected(node.callee.property.name)) &&
            isArrayConstructorType(getTypeOfNode(node.callee.object, context))) {
            return true;
        }
        // Check for: array.slice(0)
        if (arrayNewObjectReturningMethods.some(isExpected(node.callee.property.name))) {
            return true;
        }
        // Check for: Object.entries(object)
        if (objectConstructorNewObjectReturningMethods.some(isExpected(node.callee.property.name)) &&
            isObjectConstructorType(getTypeOfNode(node.callee.object, context))) {
            return true;
        }
        // Check for: "".split("")
        if (stringConstructorNewObjectReturningMethods.some(isExpected(node.callee.property.name)) &&
            getTypeOfNode(node.callee.object, context).isStringLiteral()) {
            return true;
        }
    }
    return false;
}
/**
 * Check if the given node violates this rule.
 */
function checkCallExpression$1(node, context, options) {
    const [optionsObject] = options;
    const { ignoreIdentifierPattern, ignoreAccessorPattern, ignoreNonConstDeclarations, ignoreClasses, } = optionsObject;
    // Not potential object mutation?
    if (!isMemberExpression(node.callee) ||
        !isIdentifier(node.callee.property) ||
        shouldIgnoreClasses(node.callee.object, context, ignoreClasses) ||
        shouldIgnorePattern(node.callee.object, context, ignoreIdentifierPattern, ignoreAccessorPattern)) {
        return {
            context,
            descriptors: [],
        };
    }
    const { ignoreImmediateMutation } = optionsObject;
    // Array mutation?
    if (arrayMutatorMethods.has(node.callee.property.name) &&
        (!ignoreImmediateMutation ||
            !isInChainCallAndFollowsNew(node.callee, context)) &&
        isArrayType(getTypeOfNode(node.callee.object, context))) {
        if (ignoreNonConstDeclarations === false) {
            return {
                context,
                descriptors: [{ node, messageId: "array" }],
            };
        }
        const rootIdentifier = findRootIdentifier(node.callee.object);
        if (rootIdentifier === undefined ||
            !isDefinedByMutableVariable(rootIdentifier, context, (variableNode) => ignoreNonConstDeclarations === true ||
                !ignoreNonConstDeclarations.treatParametersAsConst ||
                shouldIgnorePattern(variableNode, context, ignoreIdentifierPattern, ignoreAccessorPattern))) {
            return {
                context,
                descriptors: [{ node, messageId: "array" }],
            };
        }
    }
    // Non-array object mutation (ex. Object.assign on identifier)?
    if (objectConstructorMutatorFunctions.has(node.callee.property.name) &&
        node.arguments.length >= 2 &&
        (isIdentifier(node.arguments[0]) ||
            isMemberExpression(node.arguments[0])) &&
        !shouldIgnoreClasses(node.arguments[0], context, ignoreClasses) &&
        !shouldIgnorePattern(node.arguments[0], context, ignoreIdentifierPattern, ignoreAccessorPattern) &&
        isObjectConstructorType(getTypeOfNode(node.callee.object, context))) {
        if (ignoreNonConstDeclarations === false) {
            return {
                context,
                descriptors: [{ node, messageId: "object" }],
            };
        }
        const rootIdentifier = findRootIdentifier(node.callee.object);
        if (rootIdentifier === undefined ||
            !isDefinedByMutableVariable(rootIdentifier, context, (variableNode) => ignoreNonConstDeclarations === true ||
                !ignoreNonConstDeclarations.treatParametersAsConst ||
                shouldIgnorePattern(variableNode, context, ignoreIdentifierPattern, ignoreAccessorPattern))) {
            return {
                context,
                descriptors: [{ node, messageId: "object" }],
            };
        }
    }
    return {
        context,
        descriptors: [],
    };
}
// Create the rule.
const rule$h = createRule(name$h, meta$i, defaultOptions$h, {
    AssignmentExpression: checkAssignmentExpression,
    UnaryExpression: checkUnaryExpression,
    UpdateExpression: checkUpdateExpression,
    CallExpression: checkCallExpression$1,
});

/**
 * The name of this rule.
 */
const name$g = "no-classes";
/**
 * The schema for the rule options.
 */
const schema$g = [];
/**
 * The default options for the rule.
 */
const defaultOptions$g = [{}];
/**
 * The possible error messages.
 */
const errorMessages$g = {
    generic: "Unexpected class, use functions not classes.",
};
/**
 * The meta data for this rule.
 */
const meta$h = {
    type: "suggestion",
    docs: {
        category: "No Other Paradigms",
        description: "Disallow classes.",
        recommended: "recommended",
        recommendedSeverity: "error",
    },
    messages: errorMessages$g,
    schema: schema$g,
};
/**
 * Check if the given class node violates this rule.
 */
function checkClass(node, context) {
    // All class nodes violate this rule.
    return { context, descriptors: [{ node, messageId: "generic" }] };
}
// Create the rule.
const rule$g = createRule(name$g, meta$h, defaultOptions$g, { ClassDeclaration: checkClass, ClassExpression: checkClass });

var tsApiUtils = (() => {
    if (ts !== undefined) {
        return require("ts-api-utils");
    }
    return undefined;
})();

/**
 * The name of this rule.
 */
const name$f = "no-conditional-statements";
/**
 * The full name of this rule.
 */
const fullName$7 = `${ruleNameScope}/${name$f}`;
/**
 * The schema for the rule options.
 */
const schema$f = [
    {
        type: "object",
        properties: {
            allowReturningBranches: {
                oneOf: [
                    {
                        type: "boolean",
                    },
                    {
                        type: "string",
                        enum: ["ifExhaustive"],
                    },
                ],
            },
        },
        additionalProperties: false,
    },
];
/**
 * The default options for the rule.
 */
const defaultOptions$f = [{ allowReturningBranches: false }];
/**
 * The possible error messages.
 */
const errorMessages$f = {
    incompleteBranch: "Incomplete branch, every branch in a conditional statement must contain a return statement.",
    incompleteIf: "Incomplete if, it must have an else statement and every branch must contain a return statement.",
    incompleteSwitch: "Incomplete switch, it must be exhaustive or have an default case and every case must contain a return statement.",
    unexpectedIf: "Unexpected if, use a conditional expression (ternary operator) instead.",
    unexpectedSwitch: "Unexpected switch, use a conditional expression (ternary operator) instead.",
};
/**
 * The meta data for this rule.
 */
const meta$g = {
    type: "suggestion",
    docs: {
        category: "No Statements",
        description: "Disallow conditional statements.",
        recommended: "recommended",
        recommendedSeverity: "error",
        requiresTypeChecking: true,
    },
    messages: errorMessages$f,
    schema: schema$f,
};
/**
 * Report the given node as an incomplete branch violation.
 *
 * @param node - The node to report.
 * @returns A violation rule result.
 */
function incompleteBranchViolation(node) {
    return [{ node, messageId: "incompleteBranch" }];
}
/**
 * Get a function that tests if the given statement is never returning.
 */
function getIsNeverExpressions(context) {
    return (statement) => {
        if (isExpressionStatement(statement)) {
            const expressionStatementType = getTypeOfNode(statement.expression, context);
            return (expressionStatementType !== null &&
                tsApiUtils?.isIntrinsicNeverType(expressionStatementType) === true);
        }
        return false;
    };
}
/**
 * Is the given statement, when inside an if statement, a returning branch?
 */
function isIfReturningBranch(statement) {
    return (
    // Another instance of this rule will check nested if statements.
    isIfStatement(statement) ||
        isReturnStatement(statement) ||
        isThrowStatement(statement) ||
        isBreakStatement(statement) ||
        isContinueStatement(statement));
}
/**
 * Get all of the violations in the given if statement assuming if statements
 * are allowed.
 */
function getIfBranchViolations(node, context) {
    const branches = [node.consequent, node.alternate];
    const violations = branches.filter((branch) => {
        if (branch === null || isIfReturningBranch(branch)) {
            return false;
        }
        if (isExpressionStatement(branch)) {
            const expressionStatementType = getTypeOfNode(branch.expression, context);
            if (expressionStatementType !== null &&
                tsApiUtils?.isIntrinsicNeverType(expressionStatementType) === true) {
                return false;
            }
        }
        if (isBlockStatement(branch)) {
            if (branch.body.some(isIfReturningBranch)) {
                return false;
            }
            const isNeverExpressions = getIsNeverExpressions(context);
            if (branch.body.some(isNeverExpressions)) {
                return false;
            }
        }
        return true;
    });
    return violations.flatMap(incompleteBranchViolation);
}
/**
 * Is the given statement, when inside a switch statement, a returning branch?
 */
function isSwitchReturningBranch(statement) {
    return (
    // Another instance of this rule will check nested switch statements.
    isSwitchStatement(statement) ||
        isReturnStatement(statement) ||
        isThrowStatement(statement));
}
/**
 * Get all of the violations in the given switch statement assuming switch
 * statements are allowed.
 */
function getSwitchViolations(node, context) {
    const isNeverExpressions = getIsNeverExpressions(context);
    const violations = node.cases.filter((branch) => {
        if (branch.consequent.length === 0) {
            return false;
        }
        if (branch.consequent.some(isSwitchReturningBranch)) {
            return false;
        }
        if (branch.consequent.every(isBlockStatement)) {
            const lastBlock = branch.consequent.at(-1);
            if (lastBlock.body.some(isSwitchReturningBranch)) {
                return false;
            }
            if (lastBlock.body.some(isNeverExpressions)) {
                return false;
            }
        }
        return !branch.consequent.some(isNeverExpressions);
    });
    return violations.flatMap(incompleteBranchViolation);
}
/**
 * Does the given if statement violate this rule if it must be exhaustive.
 */
function isExhaustiveIfViolation(node) {
    return node.alternate === null;
}
/**
 * Does the given typed switch statement violate this rule if it must be exhaustive.
 */
function isExhaustiveTypeSwitchViolation(node, context) {
    const discriminantType = getTypeOfNode(node.discriminant, context);
    if (!discriminantType?.isUnion()) {
        return true;
    }
    const caseTypes = node.cases.reduce((types, c) => new Set([...types, getTypeOfNode(c.test, context)]), new Set());
    return discriminantType.types.some((unionType) => !caseTypes.has(unionType));
}
/**
 * Does the given switch statement violate this rule if it must be exhaustive.
 */
function isExhaustiveSwitchViolation(node, context) {
    return (
    // No cases defined.
    node.cases.every((c) => c.test !== null)
        ? isExhaustiveTypeSwitchViolation(node, context)
        : false);
}
/**
 * Check if the given IfStatement violates this rule.
 */
function checkIfStatement(node, context, options) {
    const [{ allowReturningBranches }] = options;
    return {
        context,
        descriptors: allowReturningBranches === false
            ? [{ node, messageId: "unexpectedIf" }]
            : allowReturningBranches === "ifExhaustive"
                ? isExhaustiveIfViolation(node)
                    ? [{ node, messageId: "incompleteIf" }]
                    : getIfBranchViolations(node, context)
                : getIfBranchViolations(node, context),
    };
}
/**
 * Check if the given SwitchStatement violates this rule.
 */
function checkSwitchStatement(node, context, options) {
    const [{ allowReturningBranches }] = options;
    return {
        context,
        descriptors: allowReturningBranches === false
            ? [{ node, messageId: "unexpectedSwitch" }]
            : allowReturningBranches === "ifExhaustive"
                ? isExhaustiveSwitchViolation(node, context)
                    ? [{ node, messageId: "incompleteSwitch" }]
                    : getSwitchViolations(node, context)
                : getSwitchViolations(node, context),
    };
}
// Create the rule.
const rule$f = createRule(name$f, meta$g, defaultOptions$f, {
    IfStatement: checkIfStatement,
    SwitchStatement: checkSwitchStatement,
});

/**
 * The name of this rule.
 */
const name$e = "no-expression-statements";
/**
 * The full name of this rule.
 */
const fullName$6 = `${ruleNameScope}/${name$e}`;
/**
 * The schema for the rule options.
 */
const schema$e = [
    {
        type: "object",
        properties: deepmergeTs.deepmerge(ignoreCodePatternOptionSchema, {
            ignoreVoid: {
                type: "boolean",
            },
            ignoreSelfReturning: {
                type: "boolean",
            },
        }),
        additionalProperties: false,
    },
];
/**
 * The default options for the rule.
 */
const defaultOptions$e = [
    {
        ignoreVoid: false,
        ignoreSelfReturning: false,
    },
];
/**
 * The possible error messages.
 */
const errorMessages$e = {
    generic: "Using expressions to cause side-effects not allowed.",
};
/**
 * The meta data for this rule.
 */
const meta$f = {
    type: "suggestion",
    docs: {
        category: "No Statements",
        description: "Disallow expression statements.",
        recommended: "recommended",
        recommendedSeverity: "error",
        requiresTypeChecking: true,
    },
    messages: errorMessages$e,
    schema: schema$e,
};
/**
 * Check if the given ExpressionStatement violates this rule.
 */
function checkExpressionStatement(node, context, options) {
    const [optionsObject] = options;
    const { ignoreCodePattern } = optionsObject;
    if (shouldIgnorePattern(node, context, undefined, undefined, ignoreCodePattern)) {
        return {
            context,
            descriptors: [],
        };
    }
    // Allow specifying directive prologues and using yield expressions.
    if (isDirectivePrologue(node) || isYieldExpression(node.expression)) {
        return {
            context,
            descriptors: [],
        };
    }
    const { ignoreVoid, ignoreSelfReturning } = optionsObject;
    if ((ignoreVoid || ignoreSelfReturning) &&
        isCallExpression(node.expression)) {
        const returnType = getTypeOfNode(node.expression, context);
        if (returnType === null) {
            return {
                context,
                descriptors: [{ node, messageId: "generic" }],
            };
        }
        if (ignoreVoid && tsApiUtils?.isIntrinsicVoidType(returnType) === true) {
            return {
                context,
                descriptors: [],
            };
        }
        if (ignoreSelfReturning) {
            const type = getTypeOfNode(node.expression.callee, context);
            if (type !== null) {
                const declaration = type.getSymbol()?.valueDeclaration;
                if (ts !== undefined &&
                    declaration !== undefined &&
                    ts.isFunctionLike(declaration) &&
                    "body" in declaration &&
                    declaration.body !== undefined &&
                    ts.isBlock(declaration.body)) {
                    const returnStatements = declaration.body.statements.filter(ts.isReturnStatement);
                    if (returnStatements.every((statement) => statement.expression !== undefined &&
                        tsApiUtils?.isThisKeyword(statement.expression))) {
                        return {
                            context,
                            descriptors: [],
                        };
                    }
                }
            }
        }
    }
    return {
        context,
        descriptors: [{ node, messageId: "generic" }],
    };
}
// Create the rule.
const rule$e = createRule(name$e, meta$f, defaultOptions$e, {
    ExpressionStatement: checkExpressionStatement,
});

/**
 * The name of this rule.
 */
const name$d = "no-let";
/**
 * The full name of this rule.
 */
const fullName$5 = `${ruleNameScope}/${name$d}`;
/**
 * The schema for the rule options.
 */
const schema$d = [
    {
        type: "object",
        properties: deepmergeTs.deepmerge(ignoreIdentifierPatternOptionSchema, {
            allowInForLoopInit: {
                type: "boolean",
            },
            allowInFunctions: {
                type: "boolean",
            },
        }),
        additionalProperties: false,
    },
];
/**
 * The default options for the rule.
 */
const defaultOptions$d = [
    {
        allowInForLoopInit: false,
        allowInFunctions: false,
    },
];
/**
 * The possible error messages.
 */
const errorMessages$d = {
    generic: "Unexpected let, use const instead.",
};
/**
 * The meta data for this rule.
 */
const meta$e = {
    type: "suggestion",
    docs: {
        category: "No Mutations",
        description: "Disallow mutable variables.",
        recommended: "recommended",
        recommendedSeverity: "error",
    },
    messages: errorMessages$d,
    schema: schema$d,
};
/**
 * Check if the given VariableDeclaration violates this rule.
 */
function checkVariableDeclaration(node, context, options) {
    const [optionsObject] = options;
    const { allowInForLoopInit, ignoreIdentifierPattern, allowInFunctions } = optionsObject;
    if (node.kind !== "let" ||
        shouldIgnoreInFunction(node, context, allowInFunctions) ||
        shouldIgnorePattern(node, context, ignoreIdentifierPattern) ||
        (allowInForLoopInit && isInForLoopInitializer(node))) {
        return {
            context,
            descriptors: [],
        };
    }
    return {
        context,
        descriptors: [{ node, messageId: "generic" }],
    };
}
// Create the rule.
const rule$d = createRule(name$d, meta$e, defaultOptions$d, {
    VariableDeclaration: checkVariableDeclaration,
});

/**
 * The name of this rule.
 */
const name$c = "no-loop-statements";
/**
 * The schema for the rule options.
 */
const schema$c = [];
/**
 * The default options for the rule.
 */
const defaultOptions$c = [{}];
/**
 * The possible error messages.
 */
const errorMessages$c = {
    generic: "Unexpected loop, use map or reduce instead.",
};
/**
 * The meta data for this rule.
 */
const meta$d = {
    type: "suggestion",
    docs: {
        category: "No Statements",
        description: "Disallow imperative loops.",
        recommended: "recommended",
        recommendedSeverity: "error",
    },
    messages: errorMessages$c,
    schema: schema$c,
};
/**
 * Check if the given loop violates this rule.
 */
function checkLoop(node, context) {
    // All loops violate this rule.
    return { context, descriptors: [{ node, messageId: "generic" }] };
}
// Create the rule.
const rule$c = createRule(name$c, meta$d, defaultOptions$c, {
    ForStatement: checkLoop,
    ForInStatement: checkLoop,
    ForOfStatement: checkLoop,
    WhileStatement: checkLoop,
    DoWhileStatement: checkLoop,
});

/**
 * The name of this rule.
 */
const name$b = "no-mixed-types";
/**
 * The schema for the rule options.
 */
const schema$b = [
    {
        type: "object",
        properties: {
            checkInterfaces: {
                type: "boolean",
            },
            checkTypeLiterals: {
                type: "boolean",
            },
        },
        additionalProperties: false,
    },
];
/**
 * The default options for the rule.
 */
const defaultOptions$b = [
    {
        checkInterfaces: true,
        checkTypeLiterals: true,
    },
];
/**
 * The possible error messages.
 */
const errorMessages$b = {
    generic: "Only the same kind of members allowed in types.",
};
/**
 * The meta data for this rule.
 */
const meta$c = {
    type: "suggestion",
    docs: {
        category: "No Other Paradigms",
        description: "Restrict types so that only members of the same kind are allowed in them.",
        requiresTypeChecking: true,
        recommended: "recommended",
        recommendedSeverity: "error",
    },
    messages: errorMessages$b,
    schema: schema$b,
};
/**
 * Does the given type elements violate the rule.
 */
function hasTypeElementViolations(typeElements, context) {
    return !typeElements
        .map((member) => {
        return (isTSMethodSignature(member) ||
            isTSCallSignatureDeclaration(member) ||
            isTSConstructSignatureDeclaration(member) ||
            ((isTSPropertySignature(member) || isTSIndexSignature(member)) &&
                member.typeAnnotation !== undefined &&
                (isTSFunctionType(member.typeAnnotation.typeAnnotation) ||
                    isFunctionLikeType(getTypeOfNode(member, context)))));
    })
        .every((isFunction, _, array) => array[0] === isFunction);
}
/**
 * Check if the given TSInterfaceDeclaration violates this rule.
 */
function checkTSInterfaceDeclaration(node, context, options) {
    return {
        context,
        descriptors: hasTypeElementViolations(node.body.body, context)
            ? [{ node, messageId: "generic" }]
            : [],
    };
}
/**
 * Check if the given TSTypeAliasDeclaration violates this rule.
 */
function checkTSTypeAliasDeclaration(node, context, options) {
    return {
        context,
        descriptors: 
        // TypeLiteral.
        (isTSTypeLiteral(node.typeAnnotation) &&
            hasTypeElementViolations(node.typeAnnotation.members, context)) ||
            // TypeLiteral inside `Readonly<>`.
            (isTSTypeReference(node.typeAnnotation) &&
                isIdentifier(node.typeAnnotation.typeName) &&
                node.typeAnnotation.typeArguments !== undefined &&
                node.typeAnnotation.typeArguments.params.length === 1 &&
                isTSTypeLiteral(node.typeAnnotation.typeArguments.params[0]) &&
                hasTypeElementViolations(node.typeAnnotation.typeArguments.params[0].members, context))
            ? [{ node, messageId: "generic" }]
            : [],
    };
}
// Create the rule.
const rule$b = createRuleUsingFunction(name$b, meta$c, defaultOptions$b, (context, options) => {
    const [{ checkInterfaces, checkTypeLiterals }] = options;
    return Object.fromEntries([
        [
            "TSInterfaceDeclaration",
            checkInterfaces ? checkTSInterfaceDeclaration : undefined,
        ],
        [
            "TSTypeAliasDeclaration",
            checkTypeLiterals ? checkTSTypeAliasDeclaration : undefined,
        ],
    ].filter(([sel, fn]) => fn !== undefined));
});

/**
 * The name of this rule.
 */
const name$a = "no-promise-reject";
/**
 * The schema for the rule options.
 */
const schema$a = [];
/**
 * The default options for the rule.
 */
const defaultOptions$a = [{}];
/**
 * The possible error messages.
 */
const errorMessages$a = {
    generic: "Unexpected reject, return an error instead.",
};
/**
 * The meta data for this rule.
 */
const meta$b = {
    type: "suggestion",
    docs: {
        category: "No Exceptions",
        description: "Disallow rejecting promises.",
        recommended: false,
        recommendedSeverity: "error",
    },
    messages: errorMessages$a,
    schema: schema$a,
};
/**
 * Check if the given CallExpression violates this rule.
 */
function checkCallExpression(node, context) {
    return {
        context,
        descriptors: isMemberExpression(node.callee) &&
            isIdentifier(node.callee.object) &&
            isIdentifier(node.callee.property) &&
            node.callee.object.name === "Promise" &&
            node.callee.property.name === "reject"
            ? [{ node, messageId: "generic" }]
            : [],
    };
}
// Create the rule.
const rule$a = createRule(name$a, meta$b, defaultOptions$a, {
    CallExpression: checkCallExpression,
});

/**
 * The name of this rule.
 */
const name$9 = "no-return-void";
/**
 * The schema for the rule options.
 */
const schema$9 = [
    {
        type: "object",
        properties: {
            allowNull: {
                type: "boolean",
            },
            allowUndefined: {
                type: "boolean",
            },
            ignoreInferredTypes: {
                type: "boolean",
            },
        },
        additionalProperties: false,
    },
];
/**
 * The default options for the rule.
 */
const defaultOptions$9 = [
    {
        allowNull: true,
        allowUndefined: true,
        ignoreInferredTypes: false,
    },
];
/**
 * The possible error messages.
 */
const errorMessages$9 = {
    generic: "Function must return a value.",
};
/**
 * The meta data for this rule.
 */
const meta$a = {
    type: "suggestion",
    docs: {
        category: "No Statements",
        description: "Disallow functions that don't return anything.",
        requiresTypeChecking: true,
        recommended: "recommended",
        recommendedSeverity: "error",
    },
    messages: errorMessages$9,
    schema: schema$9,
};
/**
 * Check if the given function node violates this rule.
 */
function checkFunction$2(node, context, options) {
    const [{ ignoreInferredTypes, allowNull, allowUndefined }] = options;
    if (node.returnType === undefined) {
        if (!ignoreInferredTypes && isFunctionLike(node)) {
            const functionType = getTypeOfNode(node, context);
            const returnType = functionType
                ?.getCallSignatures()?.[0]
                ?.getReturnType();
            if (returnType !== undefined &&
                tsApiUtils !== undefined &&
                (tsApiUtils.isIntrinsicVoidType(returnType) ||
                    (!allowNull && tsApiUtils.isIntrinsicNullType(returnType)) ||
                    (!allowUndefined && tsApiUtils.isIntrinsicUndefinedType(returnType)))) {
                return {
                    context,
                    descriptors: [{ node, messageId: "generic" }],
                };
            }
        }
    }
    else if (isTSVoidKeyword(node.returnType.typeAnnotation) ||
        (!allowNull && isTSNullKeyword(node.returnType.typeAnnotation)) ||
        (!allowUndefined && isTSUndefinedKeyword(node.returnType.typeAnnotation))) {
        return {
            context,
            descriptors: [{ node: node.returnType, messageId: "generic" }],
        };
    }
    return {
        context,
        descriptors: [],
    };
}
// Create the rule.
const rule$9 = createRule(name$9, meta$a, defaultOptions$9, {
    ArrowFunctionExpression: checkFunction$2,
    FunctionDeclaration: checkFunction$2,
    FunctionExpression: checkFunction$2,
    TSCallSignatureDeclaration: checkFunction$2,
    TSConstructSignatureDeclaration: checkFunction$2,
    TSDeclareFunction: checkFunction$2,
    TSEmptyBodyFunctionExpression: checkFunction$2,
    TSFunctionType: checkFunction$2,
    TSMethodSignature: checkFunction$2,
});

/**
 * The name of this rule.
 */
const name$8 = "no-this-expressions";
/**
 * The full name of this rule.
 */
const fullName$4 = `${ruleNameScope}/${name$8}`;
/**
 * The schema for the rule options.
 */
const schema$8 = [];
/**
 * The default options for the rule.
 */
const defaultOptions$8 = [{}];
/**
 * The possible error messages.
 */
const errorMessages$8 = {
    generic: "Unexpected this, use functions not classes.",
};
/**
 * The meta data for this rule.
 */
const meta$9 = {
    type: "suggestion",
    docs: {
        category: "No Other Paradigms",
        description: "Disallow this access.",
        recommended: "recommended",
        recommendedSeverity: "error",
    },
    messages: errorMessages$8,
    schema: schema$8,
};
/**
 * Check if the given ThisExpression violates this rule.
 */
function checkThisExpression(node, context) {
    // All throw statements violate this rule.
    return { context, descriptors: [{ node, messageId: "generic" }] };
}
// Create the rule.
const rule$8 = createRule(name$8, meta$9, defaultOptions$8, {
    ThisExpression: checkThisExpression,
});

/**
 * The name of this rule.
 */
const name$7 = "no-throw-statements";
/**
 * The full name of this rule.
 */
const fullName$3 = `${ruleNameScope}/${name$7}`;
/**
 * The schema for the rule options.
 */
const schema$7 = [
    {
        type: "object",
        properties: {
            allowInAsyncFunctions: {
                type: "boolean",
            },
        },
        additionalProperties: false,
    },
];
/**
 * The default options for the rule.
 */
const defaultOptions$7 = [
    {
        allowInAsyncFunctions: false,
    },
];
/**
 * The possible error messages.
 */
const errorMessages$7 = {
    generic: "Unexpected throw, throwing exceptions is not functional.",
};
/**
 * The meta data for this rule.
 */
const meta$8 = {
    type: "suggestion",
    docs: {
        category: "No Exceptions",
        description: "Disallow throwing exceptions.",
        recommended: "recommended",
        recommendedSeverity: "error",
    },
    messages: errorMessages$7,
    schema: schema$7,
};
/**
 * Check if the given ThrowStatement violates this rule.
 */
function checkThrowStatement(node, context, options) {
    const [{ allowInAsyncFunctions }] = options;
    if (!allowInAsyncFunctions || !isInFunctionBody(node, true)) {
        return { context, descriptors: [{ node, messageId: "generic" }] };
    }
    return {
        context,
        descriptors: [],
    };
}
// Create the rule.
const rule$7 = createRule(name$7, meta$8, defaultOptions$7, {
    ThrowStatement: checkThrowStatement,
});

/**
 * The name of this rule.
 */
const name$6 = "no-try-statements";
/**
 * The full name of this rule.
 */
const fullName$2 = `${ruleNameScope}/${name$6}`;
/**
 * The schema for the rule options.
 */
const schema$6 = [
    {
        type: "object",
        properties: {
            allowCatch: {
                type: "boolean",
            },
            allowFinally: {
                type: "boolean",
            },
        },
        additionalProperties: false,
    },
];
/**
 * The default options for the rule.
 */
const defaultOptions$6 = [
    {
        allowCatch: false,
        allowFinally: false,
    },
];
/**
 * The possible error messages.
 */
const errorMessages$6 = {
    catch: "Unexpected try-catch, this pattern is not functional.",
    finally: "Unexpected try-finally, this pattern is not functional.",
};
/**
 * The meta data for this rule.
 */
const meta$7 = {
    type: "suggestion",
    docs: {
        category: "No Exceptions",
        description: "Disallow try-catch[-finally] and try-finally patterns.",
        recommended: "recommended",
        recommendedSeverity: "error",
    },
    messages: errorMessages$6,
    schema: schema$6,
};
/**
 * Check if the given TryStatement violates this rule.
 */
function checkTryStatement(node, context, options) {
    const [{ allowCatch, allowFinally }] = options;
    return {
        context,
        descriptors: !allowCatch && node.handler !== null
            ? [{ node, messageId: "catch" }]
            : !allowFinally && node.finalizer !== null
                ? [{ node, messageId: "finally" }]
                : [],
    };
}
// Create the rule.
const rule$6 = createRule(name$6, meta$7, defaultOptions$6, {
    TryStatement: checkTryStatement,
});

/**
 * The name of this rule.
 */
const name$5 = "prefer-immutable-types";
/**
 * The full name of this rule.
 */
const fullName$1 = `${ruleNameScope}/${name$5}`;
/**
 * The enum options for the level of enforcement.
 */
const enforcementEnumOptions = [
    ...Object.values(isImmutableType.Immutability).filter((i) => i !== isImmutableType.Immutability.Unknown &&
        i !== isImmutableType.Immutability[isImmutableType.Immutability.Unknown] &&
        i !== isImmutableType.Immutability.Mutable &&
        i !== isImmutableType.Immutability[isImmutableType.Immutability.Mutable]),
    "None",
    false,
];
/**
 * The non-shorthand schema for each option.
 */
const optionExpandedSchema = deepmergeTs.deepmerge(ignoreClassesOptionSchema, {
    enforcement: {
        type: ["string", "number", "boolean"],
        enum: enforcementEnumOptions,
    },
    ignoreInferredTypes: {
        type: "boolean",
    },
    ignoreNamePattern: {
        type: ["string", "array"],
        items: {
            type: "string",
        },
    },
    ignoreTypePattern: {
        type: ["string", "array"],
        items: {
            type: "string",
        },
    },
});
/**
 * The schema for each option.
 */
const optionSchema = {
    oneOf: [
        {
            type: "object",
            properties: optionExpandedSchema,
            additionalProperties: false,
        },
        {
            type: ["string", "number", "boolean"],
            enum: enforcementEnumOptions,
        },
    ],
};
/**
 * The schema for each fixer config.
 */
const fixerSchema$1 = {
    oneOf: [
        {
            type: "object",
            properties: {
                pattern: { type: "string" },
                replace: { type: "string" },
            },
            additionalProperties: false,
        },
        {
            type: "array",
            items: {
                type: "object",
                properties: {
                    pattern: { type: "string" },
                    replace: { type: "string" },
                },
                additionalProperties: false,
            },
        },
    ],
};
const suggestionsSchema$1 = {
    type: "array",
    items: {
        type: "array",
        items: {
            type: "object",
            properties: {
                pattern: { type: "string" },
                replace: { type: "string" },
            },
            additionalProperties: false,
        },
    },
};
/**
 * The schema for the rule options.
 */
const schema$5 = [
    {
        type: "object",
        properties: deepmergeTs.deepmerge(optionExpandedSchema, {
            parameters: optionSchema,
            returnTypes: optionSchema,
            variables: {
                oneOf: [
                    {
                        type: "object",
                        properties: deepmergeTs.deepmerge(optionExpandedSchema, {
                            ignoreInFunctions: {
                                type: "boolean",
                            },
                        }),
                        additionalProperties: false,
                    },
                    {
                        type: ["string", "number", "boolean"],
                        enum: enforcementEnumOptions,
                    },
                ],
            },
            fixer: {
                type: "object",
                properties: {
                    ReadonlyShallow: fixerSchema$1,
                    ReadonlyDeep: fixerSchema$1,
                    Immutable: fixerSchema$1,
                },
                additionalProperties: false,
            },
            suggestions: {
                type: "object",
                properties: {
                    ReadonlyShallow: suggestionsSchema$1,
                    ReadonlyDeep: suggestionsSchema$1,
                    Immutable: suggestionsSchema$1,
                },
                additionalProperties: false,
            },
        }),
        additionalProperties: false,
    },
];
/**
 * The default options for the rule.
 */
const defaultOptions$5 = [
    {
        enforcement: isImmutableType.Immutability.Immutable,
        ignoreInferredTypes: false,
        ignoreClasses: false,
        suggestions: {
            ReadonlyShallow: [
                [
                    {
                        pattern: "^([_$a-zA-Z\\xA0-\\uFFFF][_$a-zA-Z0-9\\xA0-\\uFFFF]*\\[\\])$",
                        replace: "readonly $1",
                    },
                    {
                        pattern: "^(Array|Map|Set)<(.+)>$",
                        replace: "Readonly$1<$2>",
                    },
                    {
                        pattern: "^(.+)$",
                        replace: "Readonly<$1>",
                    },
                ],
            ],
        },
    },
];
/**
 * The possible error messages.
 */
const errorMessages$5 = {
    parameter: 'Parameter should have an immutability of at least "{{ expected }}" (actual: "{{ actual }}").',
    returnType: 'Return type should have an immutability of at least "{{ expected }}" (actual: "{{ actual }}").',
    variable: 'Variable should have an immutability of at least "{{ expected }}" (actual: "{{ actual }}").',
    propertyImmutability: 'Property should have an immutability of at least "{{ expected }}" (actual: "{{ actual }}").',
    propertyModifier: "Property should have a readonly modifier.",
};
/**
 * The meta data for this rule.
 */
const meta$6 = {
    type: "suggestion",
    docs: {
        category: "No Mutations",
        description: "Require function parameters to be typed as certain immutability",
        recommended: "recommended",
        recommendedSeverity: "error",
        requiresTypeChecking: true,
    },
    fixable: "code",
    hasSuggestions: true,
    messages: errorMessages$5,
    schema: schema$5,
};
/**
 * Get the fixer and the suggestions' fixers.
 */
function getAllFixers(node, context, fixerConfigs, suggestionsConfigs) {
    const nodeText = context.sourceCode.getText(node).replaceAll(/\s+/gmu, " ");
    const fix = fixerConfigs === false
        ? null
        : getConfiguredFixer$1(node, nodeText, fixerConfigs);
    const suggestionFixers = suggestionsConfigs === false
        ? null
        : getConfiguredSuggestionFixers(node, nodeText, suggestionsConfigs);
    return { fix, suggestionFixers };
}
/**
 * Get a fixer that uses the user config.
 */
function getConfiguredFixer$1(node, text, configs) {
    const config = configs.find((c) => c.pattern.test(text));
    if (config === undefined) {
        return null;
    }
    return (fixer) => fixer.replaceText(node, text.replace(config.pattern, config.replace));
}
/**
 * Get a fixer that uses the user config.
 */
function getConfiguredSuggestionFixers(node, text, suggestionsConfigs) {
    return suggestionsConfigs
        .map((configs) => {
        const config = configs.find((c) => c.pattern.test(text));
        if (config === undefined) {
            return null;
        }
        return (fixer) => fixer.replaceText(node, text.replace(config.pattern, config.replace));
    })
        .filter(isDefined);
}
/**
 * Get the level of enforcement from the raw value given.
 */
function parseEnforcement(rawEnforcement) {
    return rawEnforcement === "None"
        ? false
        : typeof rawEnforcement === "string"
            ? isImmutableType.Immutability[rawEnforcement]
            : rawEnforcement;
}
/**
 * Get the fixer config for the the given enforcement level from the raw config given.
 */
function parseFixerConfigs(allRawConfigs, enforcement) {
    const key = isImmutableType.Immutability[enforcement];
    const rawConfigs = allRawConfigs?.[key];
    if (rawConfigs === undefined) {
        return false;
    }
    const raws = Array.isArray(rawConfigs) ? rawConfigs : [rawConfigs];
    return raws.map((r) => ({
        ...r,
        pattern: new RegExp(r.pattern, "u"),
    }));
}
/**
 * Get the suggestions config for the the given enforcement level from the raw config given.
 */
function parseSuggestionsConfigs(rawSuggestions, enforcement) {
    const key = isImmutableType.Immutability[enforcement];
    const rawConfigsSet = rawSuggestions?.[key];
    if (rawConfigsSet === undefined) {
        return false;
    }
    return rawConfigsSet.map((rawConfigs) => rawConfigs.map((rawConfig) => ({
        ...rawConfig,
        pattern: new RegExp(rawConfig.pattern, "u"),
    })));
}
/**
 * Get the parameter type violations.
 */
function getParameterTypeViolations(node, context, options) {
    const [optionsObject] = options;
    const { parameters: rawOption, fixer: rawFixerConfig, suggestions: rawSuggestionsConfigs, } = optionsObject;
    const { enforcement: rawEnforcement, ignoreInferredTypes, ignoreClasses, ignoreNamePattern, ignoreTypePattern, } = {
        ignoreInferredTypes: optionsObject.ignoreInferredTypes,
        ignoreClasses: optionsObject.ignoreClasses,
        ignoreNamePattern: optionsObject.ignoreNamePattern,
        ignoreTypePattern: optionsObject.ignoreTypePattern,
        ...(typeof rawOption === "object"
            ? rawOption
            : {
                enforcement: rawOption,
            }),
    };
    const enforcement = parseEnforcement(rawEnforcement ?? optionsObject.enforcement);
    if (enforcement === false ||
        shouldIgnoreClasses(node, context, ignoreClasses)) {
        return [];
    }
    const fixerConfigs = parseFixerConfigs(rawFixerConfig, enforcement);
    const suggestionsConfigs = parseSuggestionsConfigs(rawSuggestionsConfigs, enforcement);
    return node.params
        .map((param) => {
        if (shouldIgnorePattern(param, context, ignoreNamePattern)) {
            return undefined;
        }
        const parameterProperty = isTSParameterProperty(param);
        if (parameterProperty && !param.readonly) {
            const messageId = "propertyModifier";
            const fix = (fixer) => fixer.insertTextBefore(param.parameter, "readonly ");
            return {
                node: param,
                messageId,
                fix: fixerConfigs === false ? null : fix,
                suggest: [
                    {
                        messageId,
                        fix,
                    },
                ],
            };
        }
        const actualParam = parameterProperty ? param.parameter : param;
        if (
        // inferred types
        (ignoreInferredTypes && actualParam.typeAnnotation === undefined) ||
            // ignored
            (actualParam.typeAnnotation !== undefined &&
                shouldIgnorePattern(actualParam.typeAnnotation, context, ignoreTypePattern)) ||
            // type guard
            (node.returnType !== undefined &&
                isTSTypePredicate(node.returnType.typeAnnotation) &&
                isIdentifier(node.returnType.typeAnnotation.parameterName) &&
                isIdentifier(actualParam) &&
                actualParam.name ===
                    node.returnType.typeAnnotation.parameterName.name)) {
            return undefined;
        }
        const immutability = getTypeImmutabilityOfNode(actualParam, context, enforcement);
        if (immutability >= enforcement) {
            return undefined;
        }
        const { fix, suggestionFixers } = actualParam.typeAnnotation === undefined
            ? {}
            : getAllFixers(actualParam.typeAnnotation.typeAnnotation, context, fixerConfigs, suggestionsConfigs);
        const messageId = "parameter";
        const data = {
            actual: isImmutableType.Immutability[immutability],
            expected: isImmutableType.Immutability[enforcement],
        };
        return {
            node: actualParam,
            messageId,
            data,
            fix,
            suggest: suggestionFixers?.map((fix) => ({
                messageId,
                data,
                fix,
            })) ?? null,
        };
    })
        .filter(isDefined);
}
/**
 * Get the return type violations.
 */
function getReturnTypeViolations(node, context, options) {
    const [optionsObject] = options;
    const { returnTypes: rawOption, fixer: rawFixerConfig, suggestions: rawSuggestionsConfigs, } = optionsObject;
    const { enforcement: rawEnforcement, ignoreInferredTypes, ignoreClasses, ignoreNamePattern, ignoreTypePattern, } = {
        ignoreInferredTypes: optionsObject.ignoreInferredTypes,
        ignoreClasses: optionsObject.ignoreClasses,
        ignoreNamePattern: optionsObject.ignoreNamePattern,
        ignoreTypePattern: optionsObject.ignoreTypePattern,
        ...(typeof rawOption === "object" ? rawOption : { enforcement: rawOption }),
    };
    const enforcement = parseEnforcement(rawEnforcement ?? optionsObject.enforcement);
    if (enforcement === false ||
        (ignoreInferredTypes && node.returnType?.typeAnnotation === undefined) ||
        shouldIgnoreClasses(node, context, ignoreClasses) ||
        shouldIgnorePattern(node, context, ignoreNamePattern)) {
        return [];
    }
    const fixerConfigs = parseFixerConfigs(rawFixerConfig, enforcement);
    const suggestionsConfigs = parseSuggestionsConfigs(rawSuggestionsConfigs, enforcement);
    if (node.returnType?.typeAnnotation !== undefined &&
        !isTSTypePredicate(node.returnType.typeAnnotation)) {
        if (shouldIgnorePattern(node.returnType, context, ignoreTypePattern)) {
            return [];
        }
        const immutability = getTypeImmutabilityOfNode(node.returnType.typeAnnotation, context, enforcement);
        if (immutability >= enforcement) {
            return [];
        }
        const { fix, suggestionFixers } = getAllFixers(node.returnType.typeAnnotation, context, fixerConfigs, suggestionsConfigs);
        const messageId = "returnType";
        const data = {
            actual: isImmutableType.Immutability[immutability],
            expected: isImmutableType.Immutability[enforcement],
        };
        return [
            {
                node: node.returnType,
                messageId,
                data,
                fix,
                suggest: suggestionFixers?.map((fix) => ({
                    messageId,
                    data,
                    fix,
                })) ?? null,
            },
        ];
    }
    if (!isFunctionLike(node)) {
        return [];
    }
    const returnTypes = getReturnTypesOfFunction(node, context);
    if (returnTypes === null ||
        returnTypes.length !== 1 ||
        isImplementationOfOverload(node, context)) {
        return [];
    }
    const immutability = getTypeImmutabilityOfType(returnTypes[0], context, enforcement);
    if (immutability >= enforcement) {
        return [];
    }
    const { fix, suggestionFixers } = node.returnType?.typeAnnotation === undefined
        ? {}
        : getAllFixers(node.returnType.typeAnnotation, context, fixerConfigs, suggestionsConfigs);
    const messageId = "returnType";
    const data = {
        actual: isImmutableType.Immutability[immutability],
        expected: isImmutableType.Immutability[enforcement],
    };
    return [
        {
            node: hasID(node) && node.id !== null ? node.id : node,
            messageId,
            data,
            fix,
            suggest: suggestionFixers?.map((fix) => ({
                messageId,
                data,
                fix,
            })) ?? null,
        },
    ];
}
/**
 * Check if the given function node violates this rule.
 */
function checkFunction$1(node, context, options) {
    const descriptors = [
        ...getParameterTypeViolations(node, context, options),
        ...getReturnTypeViolations(node, context, options),
    ];
    return {
        context,
        descriptors,
    };
}
/**
 * Check if the given function node violates this rule.
 */
function checkVariable(node, context, options) {
    const [optionsObject] = options;
    const { variables: rawOption, fixer: rawFixerConfig, suggestions: rawSuggestionsConfigs, } = optionsObject;
    const { enforcement: rawEnforcement, ignoreInferredTypes, ignoreClasses, ignoreNamePattern, ignoreTypePattern, ignoreInFunctions, } = {
        ignoreInferredTypes: optionsObject.ignoreInferredTypes,
        ignoreClasses: optionsObject.ignoreClasses,
        ignoreNamePattern: optionsObject.ignoreNamePattern,
        ignoreTypePattern: optionsObject.ignoreTypePattern,
        ignoreInFunctions: false,
        ...(typeof rawOption === "object" ? rawOption : { enforcement: rawOption }),
    };
    const enforcement = parseEnforcement(rawEnforcement ?? optionsObject.enforcement);
    if (enforcement === false ||
        shouldIgnoreClasses(node, context, ignoreClasses) ||
        shouldIgnoreInFunction(node, context, ignoreInFunctions) ||
        shouldIgnorePattern(node, context, ignoreNamePattern)) {
        return {
            context,
            descriptors: [],
        };
    }
    const propertyDefinition = isPropertyDefinition(node);
    if (propertyDefinition && !node.readonly) {
        const fix = (fixer) => fixer.insertTextBefore(node.key, "readonly ");
        const messageId = "propertyModifier";
        return {
            context,
            descriptors: [
                {
                    node,
                    messageId,
                    fix: rawFixerConfig === undefined ? null : fix,
                    suggest: [
                        {
                            messageId,
                            fix,
                        },
                    ],
                },
            ],
        };
    }
    const nodeWithTypeAnnotation = propertyDefinition ? node : node.id;
    if (ignoreInferredTypes &&
        nodeWithTypeAnnotation.typeAnnotation === undefined) {
        return {
            context,
            descriptors: [],
        };
    }
    if (nodeWithTypeAnnotation.typeAnnotation !== undefined &&
        shouldIgnorePattern(nodeWithTypeAnnotation.typeAnnotation, context, ignoreTypePattern)) {
        return {
            context,
            descriptors: [],
        };
    }
    const elements = isArrayPattern(nodeWithTypeAnnotation)
        ? nodeWithTypeAnnotation.elements
        : isObjectPattern(nodeWithTypeAnnotation)
            ? nodeWithTypeAnnotation.properties
            : [nodeWithTypeAnnotation];
    const elementResults = elements.map((element) => {
        if (!isDefined(element)) {
            return null;
        }
        const immutability = getTypeImmutabilityOfNode(element, context, enforcement);
        if (immutability >= enforcement) {
            return null;
        }
        const fixerConfigs = parseFixerConfigs(rawFixerConfig, enforcement);
        const suggestionsConfigs = parseSuggestionsConfigs(rawSuggestionsConfigs, enforcement);
        const { fix, suggestionFixers } = isMemberExpression(element) ||
            isProperty(element) ||
            element.typeAnnotation === undefined
            ? {}
            : getAllFixers(element.typeAnnotation.typeAnnotation, context, fixerConfigs, suggestionsConfigs);
        return { element, immutability, fix, suggestionFixers };
    });
    const messageId = propertyDefinition ? "propertyImmutability" : "variable";
    return {
        context,
        descriptors: elementResults
            .filter(isDefined)
            .map(({ element, immutability, fix, suggestionFixers }) => {
            const data = {
                actual: isImmutableType.Immutability[immutability],
                expected: isImmutableType.Immutability[enforcement],
            };
            return {
                node: element,
                messageId,
                data,
                fix,
                suggest: suggestionFixers?.map((fix) => ({
                    messageId,
                    data,
                    fix,
                })) ?? null,
            };
        }),
    };
}
// Create the rule.
const rule$5 = createRule(name$5, meta$6, defaultOptions$5, {
    ArrowFunctionExpression: checkFunction$1,
    FunctionDeclaration: checkFunction$1,
    FunctionExpression: checkFunction$1,
    TSCallSignatureDeclaration: checkFunction$1,
    TSConstructSignatureDeclaration: checkFunction$1,
    TSDeclareFunction: checkFunction$1,
    TSEmptyBodyFunctionExpression: checkFunction$1,
    TSFunctionType: checkFunction$1,
    TSMethodSignature: checkFunction$1,
    PropertyDefinition: checkVariable,
    VariableDeclarator: checkVariable,
});

/**
 * The name of this rule.
 */
const name$4 = "prefer-property-signatures";
/**
 * The schema for the rule options.
 */
const schema$4 = [
    {
        type: "object",
        properties: {
            ignoreIfReadonlyWrapped: {
                type: "boolean",
                default: false,
            },
        },
        additionalProperties: false,
    },
];
/**
 * The default options for the rule.
 */
const defaultOptions$4 = [
    {
        ignoreIfReadonlyWrapped: false,
    },
];
/**
 * The possible error messages.
 */
const errorMessages$4 = {
    generic: "Use a property signature instead of a method signature",
};
/**
 * The meta data for this rule.
 */
const meta$5 = {
    type: "suggestion",
    docs: {
        category: "Stylistic",
        description: "Prefer property signatures over method signatures.",
        recommended: "recommended",
        recommendedSeverity: "error",
        requiresTypeChecking: true,
    },
    messages: errorMessages$4,
    schema: schema$4,
};
/**
 * Check if the given TSMethodSignature violates this rule.
 */
function checkTSMethodSignature(node, context, options) {
    const [{ ignoreIfReadonlyWrapped }] = options;
    if (ignoreIfReadonlyWrapped && isInReadonly(node)) {
        return { context, descriptors: [] };
    }
    // All TS method signatures violate this rule.
    return { context, descriptors: [{ node, messageId: "generic" }] };
}
// Create the rule.
const rule$4 = createRule(name$4, meta$5, defaultOptions$4, {
    TSMethodSignature: checkTSMethodSignature,
});

/**
 * The name of this rule.
 */
const name$3 = "prefer-readonly-type";
/**
 * The schema for the rule options.
 */
const schema$3 = [
    {
        type: "object",
        properties: {
            allowLocalMutation: {
                type: "boolean",
            },
            ignorePattern: {
                type: ["string", "array"],
                items: {
                    type: "string",
                },
            },
            ignoreClass: {
                oneOf: [
                    {
                        type: "boolean",
                    },
                    {
                        type: "string",
                        enum: ["fieldsOnly"],
                    },
                ],
            },
            ignoreInterface: {
                type: "boolean",
            },
            allowMutableReturnType: {
                type: "boolean",
            },
            checkImplicit: {
                type: "boolean",
            },
            ignoreCollections: {
                type: "boolean",
            },
        },
        additionalProperties: false,
    },
];
/**
 * The default options for the rule.
 */
const defaultOptions$3 = [
    {
        checkImplicit: false,
        ignoreClass: false,
        ignoreInterface: false,
        ignoreCollections: false,
        allowLocalMutation: false,
        allowMutableReturnType: false,
    },
];
/**
 * The possible error messages.
 */
const errorMessages$3 = {
    array: "Only readonly arrays allowed.",
    implicit: "Implicitly a mutable array. Only readonly arrays allowed.",
    property: "A readonly modifier is required.",
    tuple: "Only readonly tuples allowed.",
    type: "Only readonly types allowed.",
};
/**
 * The meta data for this rule.
 */
const meta$4 = {
    deprecated: true,
    replacedBy: [
        "functional/prefer-immutable-types",
        "functional/type-declaration-immutability",
    ],
    type: "suggestion",
    docs: {
        category: "No Mutations",
        description: "Prefer readonly types over mutable types.",
        recommended: "recommended",
        recommendedSeverity: "error",
        requiresTypeChecking: true,
    },
    messages: errorMessages$3,
    fixable: "code",
    schema: schema$3,
};
const mutableToImmutableTypes = new Map([
    ["Array", "ReadonlyArray"],
    ["Map", "ReadonlyMap"],
    ["Set", "ReadonlySet"],
]);
const mutableTypeRegex = new RegExp(`^${[...mutableToImmutableTypes.keys()].join("|")}$`, "u");
/**
 * For backwards compatibility.
 */
function shouldIgnorePattern2(node, context, ignorePattern, ignoreAccessorPattern) {
    const isTypeNode = isTSArrayType(node) ||
        isTSIndexSignature(node) ||
        isTSTupleType(node) ||
        isTSTypeAnnotation(node) ||
        isTSTypeLiteral(node) ||
        isTSTypeReference(node);
    if (isTypeNode) {
        return shouldIgnorePattern2(node.parent, context, ignorePattern, ignoreAccessorPattern);
    }
    return shouldIgnorePattern(node, context, ignorePattern, ignoreAccessorPattern);
}
/**
 * Check if the given ArrayType or TupleType violates this rule.
 */
function checkArrayOrTupleType(node, context, options) {
    const [optionsObject] = options;
    const { allowLocalMutation, allowMutableReturnType, ignoreClass, ignoreCollections, ignoreInterface, ignorePattern, } = optionsObject;
    if (shouldIgnoreClasses(node, context, ignoreClass) ||
        (ignoreInterface && isInInterface(node)) ||
        shouldIgnoreInFunction(node, context, allowLocalMutation) ||
        shouldIgnorePattern2(node, context, ignorePattern) ||
        ignoreCollections) {
        return {
            context,
            descriptors: [],
        };
    }
    return {
        context,
        descriptors: (node.parent === undefined ||
            !isTSTypeOperator(node.parent) ||
            node.parent.operator !== "readonly") &&
            (!allowMutableReturnType || !isInReturnType(node))
            ? [
                {
                    node,
                    messageId: isTSTupleType(node) ? "tuple" : "array",
                    fix: node.parent !== undefined && isTSArrayType(node.parent)
                        ? (fixer) => [
                            fixer.insertTextBefore(node, "(readonly "),
                            fixer.insertTextAfter(node, ")"),
                        ]
                        : (fixer) => fixer.insertTextBefore(node, "readonly "),
                },
            ]
            : [],
    };
}
/**
 * Check if the given TSMappedType violates this rule.
 */
function checkMappedType(node, context, options) {
    const [optionsObject] = options;
    const { allowLocalMutation, ignoreClass, ignoreInterface, ignorePattern } = optionsObject;
    if (shouldIgnoreClasses(node, context, ignoreClass) ||
        (ignoreInterface && isInInterface(node)) ||
        shouldIgnoreInFunction(node, context, allowLocalMutation) ||
        shouldIgnorePattern2(node, context, ignorePattern)) {
        return {
            context,
            descriptors: [],
        };
    }
    return {
        context,
        descriptors: node.readonly === true || node.readonly === "+"
            ? []
            : [
                {
                    node,
                    messageId: "property",
                    fix: (fixer) => fixer.insertTextBeforeRange([node.range[0] + 1, node.range[1]], " readonly"),
                },
            ],
    };
}
/**
 * Check if the given TypeReference violates this rule.
 */
function checkTypeReference(node, context, options) {
    const [optionsObject] = options;
    const { allowLocalMutation, ignoreClass, ignoreInterface, ignorePattern, allowMutableReturnType, ignoreCollections, } = optionsObject;
    if (shouldIgnoreClasses(node, context, ignoreClass) ||
        (ignoreInterface && isInInterface(node)) ||
        shouldIgnoreInFunction(node, context, allowLocalMutation) ||
        shouldIgnorePattern2(node, context, ignorePattern)) {
        return {
            context,
            descriptors: [],
        };
    }
    if (isIdentifier(node.typeName)) {
        if (ignoreCollections && mutableTypeRegex.test(node.typeName.name)) {
            return {
                context,
                descriptors: [],
            };
        }
        const immutableType = mutableToImmutableTypes.get(node.typeName.name);
        return {
            context,
            descriptors: immutableType !== undefined &&
                immutableType.length > 0 &&
                (!allowMutableReturnType || !isInReturnType(node))
                ? [
                    {
                        node,
                        messageId: "type",
                        fix: (fixer) => fixer.replaceText(node.typeName, immutableType),
                    },
                ]
                : [],
        };
    }
    return {
        context,
        descriptors: [],
    };
}
/**
 * Check if the given property/signature node violates this rule.
 */
function checkProperty(node, context, options) {
    const [optionsObject] = options;
    const { allowLocalMutation, ignoreClass, ignoreInterface, ignorePattern, allowMutableReturnType, } = optionsObject;
    if (shouldIgnoreClasses(node, context, ignoreClass) ||
        (ignoreInterface && isInInterface(node)) ||
        shouldIgnoreInFunction(node, context, allowLocalMutation) ||
        shouldIgnorePattern2(node, context, ignorePattern)) {
        return {
            context,
            descriptors: [],
        };
    }
    return {
        context,
        descriptors: !node.readonly && (!allowMutableReturnType || !isInReturnType(node))
            ? [
                {
                    node,
                    messageId: "property",
                    fix: isTSIndexSignature(node) || isTSPropertySignature(node)
                        ? (fixer) => fixer.insertTextBefore(node, "readonly ")
                        : isTSParameterProperty(node)
                            ? (fixer) => fixer.insertTextBefore(node.parameter, "readonly ")
                            : (fixer) => fixer.insertTextBefore(node.key, "readonly "),
                },
            ]
            : [],
    };
}
/**
 * Check if the given TypeReference violates this rule.
 */
function checkImplicitType(node, context, options) {
    const [optionsObject] = options;
    const { allowLocalMutation, ignoreClass, ignoreInterface, ignorePattern, checkImplicit, ignoreCollections, } = optionsObject;
    if (!checkImplicit ||
        shouldIgnoreClasses(node, context, ignoreClass) ||
        (ignoreInterface && isInInterface(node)) ||
        shouldIgnoreInFunction(node, context, allowLocalMutation) ||
        shouldIgnorePattern2(node, context, ignorePattern)) {
        return {
            context,
            descriptors: [],
        };
    }
    const declarators = isFunctionLike(node)
        ? node.params
            .map((param) => isAssignmentPattern(param)
            ? {
                id: param.left,
                init: param.right,
                node: param,
            }
            : undefined)
            .filter((param) => param !== undefined)
        : node.declarations.map((declaration) => ({
            id: declaration.id,
            init: declaration.init,
            node: declaration,
        }));
    return {
        context,
        descriptors: declarators.flatMap((declarator) => isIdentifier(declarator.id) &&
            declarator.id.typeAnnotation === undefined &&
            declarator.init !== null &&
            isArrayType(getTypeOfNode(declarator.init, context)) &&
            !ignoreCollections
            ? [
                {
                    node: declarator.node,
                    messageId: "implicit",
                    fix: (fixer) => fixer.insertTextAfter(declarator.id, ": readonly unknown[]"),
                },
            ]
            : []),
    };
}
// Create the rule.
const rule$3 = createRule(name$3, meta$4, defaultOptions$3, {
    ArrowFunctionExpression: checkImplicitType,
    PropertyDefinition: checkProperty,
    FunctionDeclaration: checkImplicitType,
    FunctionExpression: checkImplicitType,
    TSArrayType: checkArrayOrTupleType,
    TSIndexSignature: checkProperty,
    TSParameterProperty: checkProperty,
    TSPropertySignature: checkProperty,
    TSTupleType: checkArrayOrTupleType,
    TSMappedType: checkMappedType,
    TSTypeReference: checkTypeReference,
    VariableDeclaration: checkImplicitType,
});

/**
 * The name of this rule.
 */
const name$2 = "prefer-tacit";
/**
 * The schema for the rule options.
 */
const schema$2 = [
    {
        type: "object",
        properties: {
            checkMemberExpressions: {
                type: "boolean",
            },
        },
        additionalProperties: false,
    },
];
/**
 * The default options for the rule.
 */
const defaultOptions$2 = [
    {
        checkMemberExpressions: false,
    },
];
/**
 * The possible error messages.
 */
const errorMessages$2 = {
    generic: "Potentially unnecessary function wrapper.",
};
/**
 * The meta data for this rule.
 */
const meta$3 = {
    type: "suggestion",
    docs: {
        category: "Stylistic",
        description: "Replaces `x => f(x)` with just `f`.",
        recommended: "recommended",
        recommendedSeverity: "warn",
        requiresTypeChecking: true,
    },
    messages: errorMessages$2,
    hasSuggestions: true,
    schema: schema$2,
};
/**
 * Is the version of TypeScript being used 4.7 or newer?
 */
const isTS4dot7 = ts !== undefined &&
    semver__namespace.satisfies(ts.version, `>= 4.7.0 || >= 4.7.1-rc || >= 4.7.0-beta`, {
        includePrerelease: true,
    });
/**
 * From the callee's type, does it follow that the caller violates this rule.
 */
function isCallerViolation(caller, calleeType, context) {
    if (calleeType.symbol === undefined) {
        return false;
    }
    const tsDeclaration = calleeType.symbol.valueDeclaration ?? calleeType.symbol.declarations?.[0];
    if (tsDeclaration === undefined) {
        return false;
    }
    return getTypeOfTSNode(tsDeclaration, context)
        .getCallSignatures()
        .some((signature) => signature.parameters.length === caller.arguments.length);
}
/**
 * Get the fixes for a call to a reference violation.
 */
function fixFunctionCallToReference(context, fixer, node, caller) {
    // Fix to Instantiation Expression.
    if (caller.typeParameters !== undefined &&
        caller.typeParameters.params.length > 0) {
        return isTS4dot7
            ? [
                fixer.removeRange([node.range[0], caller.callee.range[0]]),
                fixer.removeRange([caller.typeParameters.range[1], node.range[1]]),
            ]
            : null;
    }
    return [
        fixer.replaceText(node, isMemberExpression(caller.callee)
            ? `${context.sourceCode.getText(caller.callee)}.bind(${context.sourceCode.getText(caller.callee.object)})`
            : context.sourceCode.getText(caller.callee)),
    ];
}
/**
 * Creates the suggestions.
 */
function buildSuggestions(context, node, caller) {
    return [
        {
            messageId: "generic",
            fix: (fixer) => {
                const functionCallToReference = fixFunctionCallToReference(context, fixer, node, caller);
                if (functionCallToReference === null) {
                    return null;
                }
                if (node.type === utils.TSESTree.AST_NODE_TYPES.FunctionDeclaration &&
                    !isNested(node)) {
                    if (node.id === null) {
                        return null;
                    }
                    return [
                        fixer.insertTextBefore(node, `const ${node.id.name} = `),
                        fixer.insertTextAfter(node, `;`),
                        ...functionCallToReference,
                    ];
                }
                return functionCallToReference;
            },
        },
    ];
}
/**
 * Check for violations based on the given caller.
 */
function getCallDescriptors(node, context, options, caller) {
    const [{ checkMemberExpressions }] = options;
    if (!isIdentifier(caller.callee) &&
        !(checkMemberExpressions && isMemberExpression(caller.callee))) {
        return [];
    }
    if (node.params.length === caller.arguments.length &&
        node.params.every((param, index) => {
            const callArg = caller.arguments[index];
            return (isIdentifier(callArg) &&
                isIdentifier(param) &&
                callArg.name === param.name);
        })) {
        const calleeType = getTypeOfNode(caller.callee, context);
        if (calleeType !== null && isCallerViolation(caller, calleeType, context)) {
            return [
                {
                    node,
                    messageId: "generic",
                    suggest: buildSuggestions(context, node, caller),
                },
            ];
        }
        return [];
    }
    return [];
}
/**
 * Check for violations in the form: `x => f(x)`.
 */
function getDirectCallDescriptors(node, context, options) {
    if (isCallExpression(node.body)) {
        return getCallDescriptors(node, context, options, node.body);
    }
    return [];
}
/**
 * Check for violations in the form: `x => { return f(x); }`.
 */
function getNestedCallDescriptors(node, context, options) {
    if (isBlockStatement(node.body) &&
        node.body.body.length === 1 &&
        isReturnStatement(node.body.body[0]) &&
        node.body.body[0].argument !== null &&
        isCallExpression(node.body.body[0].argument)) {
        return getCallDescriptors(node, context, options, node.body.body[0].argument);
    }
    return [];
}
/**
 * Check if the given function node violates this rule.
 */
function checkFunction(node, context, options) {
    return {
        context,
        descriptors: [
            ...getDirectCallDescriptors(node, context, options),
            ...getNestedCallDescriptors(node, context, options),
        ],
    };
}
// Create the rule.
const rule$2 = createRule(name$2, meta$3, defaultOptions$2, {
    FunctionDeclaration: checkFunction,
    FunctionExpression: checkFunction,
    ArrowFunctionExpression: checkFunction,
});

/**
 * The name of this rule.
 */
const name$1 = "readonly-type";
/**
 * The schema for the rule options.
 */
const schema$1 = [
    {
        type: "string",
        enum: ["generic", "keyword"],
    },
];
/**
 * The default options for the rule.
 */
const defaultOptions$1 = ["generic"];
/**
 * The possible error messages.
 */
const errorMessages$1 = {
    generic: "Readonly type using 'readonly' keyword is forbidden. Use 'Readonly<T>' instead.",
    keyword: "Readonly type using 'Readonly<T>' is forbidden. Use 'readonly' keyword instead.",
};
/**
 * The meta data for this rule.
 */
const meta$2 = {
    type: "suggestion",
    docs: {
        category: "Stylistic",
        description: "Require consistently using either `readonly` keywords or `Readonly<T>`",
        recommended: "recommended",
        recommendedSeverity: "error",
        requiresTypeChecking: true,
    },
    fixable: "code",
    messages: errorMessages$1,
    schema: schema$1,
};
/**
 * Check for violations with a type literal.
 */
function checkTypeLiteral(node, context, options) {
    const [mode] = options;
    const readonlyWrapper = getReadonly(node);
    const { sourceCode } = context;
    if (readonlyWrapper !== null) {
        if (mode === "generic") {
            return {
                context,
                descriptors: node.members
                    .map((member) => {
                    if ((isPropertyDefinition(member) ||
                        isTSParameterProperty(member) ||
                        isTSPropertySignature(member)) &&
                        member.readonly) {
                        return {
                            node: member.key,
                            messageId: "generic",
                            fix: (fixer) => fixer.replaceText(member, sourceCode.getText(member).replace(/readonly /u, "")),
                        };
                    }
                    return undefined;
                })
                    .filter(isDefined),
            };
        }
        return {
            context,
            descriptors: [
                {
                    node: isTSTypeReference(readonlyWrapper)
                        ? readonlyWrapper.typeName
                        : readonlyWrapper,
                    messageId: "keyword",
                    fix: (fixer) => {
                        const text = sourceCode.getText(readonlyWrapper);
                        const wrapperStartPattern = /^Readonly\s*</gu;
                        const wrapperEndPattern = /\s*>$/gu;
                        // eslint-disable-next-line functional/no-expression-statements -- Sets `wrapperStartPattern.lastIndex`.
                        wrapperStartPattern.exec(text);
                        const end = wrapperEndPattern.exec(text);
                        const startCutPoint = wrapperStartPattern.lastIndex;
                        const endCutPoint = end.index;
                        return [
                            fixer.removeRange([
                                readonlyWrapper.range[0],
                                readonlyWrapper.range[0] + startCutPoint,
                            ]),
                            fixer.removeRange([
                                readonlyWrapper.range[1] - text.length + endCutPoint,
                                readonlyWrapper.range[1],
                            ]),
                            ...node.members
                                .map((member) => {
                                if (!(isPropertyDefinition(member) ||
                                    isTSIndexSignature(member) ||
                                    isTSParameterProperty(member) ||
                                    isTSPropertySignature(member)) ||
                                    member.readonly) {
                                    return undefined;
                                }
                                return fixer.insertTextBefore(member, "readonly ");
                            })
                                .filter(isDefined),
                        ];
                    },
                },
            ],
        };
    }
    if (mode === "generic") {
        const needsWrapping = node.members.length > 0 &&
            node.members.every((member) => (isPropertyDefinition(member) ||
                isTSIndexSignature(member) ||
                isTSParameterProperty(member) ||
                isTSPropertySignature(member)) &&
                member.readonly);
        if (needsWrapping) {
            return {
                context,
                descriptors: [
                    {
                        node,
                        messageId: "generic",
                        fix: (fixer) => [
                            fixer.insertTextBefore(node, "Readonly<"),
                            fixer.insertTextAfter(node, ">"),
                            ...node.members.map((member) => fixer.replaceText(member, sourceCode.getText(member).replace(/readonly /u, ""))),
                        ],
                    },
                ],
            };
        }
    }
    return {
        context,
        descriptors: [],
    };
}
// Create the rule.
const rule$1 = createRule(name$1, meta$2, defaultOptions$1, {
    TSTypeLiteral: checkTypeLiteral,
});

/**
 * The name of this rule.
 */
const name = "type-declaration-immutability";
/**
 * The full name of this rule.
 */
const fullName = `${ruleNameScope}/${name}`;
/**
 * How the actual immutability should be compared to the given immutability.
 */
var RuleEnforcementComparator;
(function (RuleEnforcementComparator) {
    RuleEnforcementComparator[RuleEnforcementComparator["Less"] = -2] = "Less";
    RuleEnforcementComparator[RuleEnforcementComparator["AtMost"] = -1] = "AtMost";
    RuleEnforcementComparator[RuleEnforcementComparator["Exactly"] = 0] = "Exactly";
    RuleEnforcementComparator[RuleEnforcementComparator["AtLeast"] = 1] = "AtLeast";
    RuleEnforcementComparator[RuleEnforcementComparator["More"] = 2] = "More";
})(RuleEnforcementComparator || (RuleEnforcementComparator = {}));
/**
 * The schema for each fixer config.
 */
const fixerSchema = {
    oneOf: [
        {
            type: "boolean",
            enum: [false],
        },
        {
            type: "object",
            properties: {
                pattern: { type: "string" },
                replace: { type: "string" },
            },
            additionalProperties: false,
        },
        {
            type: "array",
            items: {
                type: "object",
                properties: {
                    pattern: { type: "string" },
                    replace: { type: "string" },
                },
                additionalProperties: false,
            },
        },
    ],
};
const suggestionsSchema = {
    oneOf: [
        {
            type: "boolean",
            enum: [false],
        },
        {
            type: "array",
            items: {
                type: "object",
                properties: {
                    pattern: { type: "string" },
                    replace: { type: "string" },
                },
                additionalProperties: false,
            },
        },
    ],
};
/**
 * The schema for the rule options.
 */
const schema = [
    {
        type: "object",
        properties: deepmergeTs.deepmerge(ignoreIdentifierPatternOptionSchema, {
            rules: {
                type: "array",
                items: {
                    type: "object",
                    properties: {
                        identifiers: {
                            type: ["string", "array"],
                            items: {
                                type: ["string"],
                            },
                        },
                        immutability: {
                            type: ["string", "number"],
                            enum: Object.values(isImmutableType.Immutability).filter((i) => i !== isImmutableType.Immutability.Unknown &&
                                i !== isImmutableType.Immutability[isImmutableType.Immutability.Unknown]),
                        },
                        comparator: {
                            type: ["string", "number"],
                            enum: Object.values(RuleEnforcementComparator),
                        },
                        fixer: fixerSchema,
                        suggestions: suggestionsSchema,
                    },
                    required: ["identifiers", "immutability"],
                    additionalProperties: false,
                },
            },
            ignoreInterfaces: {
                type: "boolean",
            },
        }),
        additionalProperties: false,
    },
];
/**
 * The default options for the rule.
 */
const defaultOptions = [
    {
        rules: [
            {
                identifiers: ["^(?!I?Mutable).+"],
                immutability: isImmutableType.Immutability.Immutable,
                comparator: RuleEnforcementComparator.AtLeast,
            },
        ],
        ignoreInterfaces: false,
    },
];
/**
 * The possible error messages.
 */
const errorMessages = {
    Less: 'This type is declare to have an immutability less than "{{ expected }}" (actual: "{{ actual }}").',
    AtLeast: 'This type is declare to have an immutability of at least "{{ expected }}" (actual: "{{ actual }}").',
    Exactly: 'This type is declare to have an immutability of exactly "{{ expected }}" (actual: "{{ actual }}").',
    AtMost: 'This type is declare to have an immutability of at most "{{ expected }}" (actual: "{{ actual }}").',
    More: 'This type is declare to have an immutability more than "{{ expected }}" (actual: "{{ actual }}").',
};
/**
 * The meta data for this rule.
 */
const meta$1 = {
    type: "suggestion",
    docs: {
        category: "No Mutations",
        description: "Enforce the immutability of types based on patterns.",
        recommended: "recommended",
        recommendedSeverity: "error",
        requiresTypeChecking: true,
    },
    messages: errorMessages,
    fixable: "code",
    hasSuggestions: true,
    schema,
};
/**
 * Get all the rules that were given and upgrade them.
 */
function getRules(options) {
    const [optionsObject] = options;
    const { rules: rulesOptions } = optionsObject;
    return rulesOptions.map((rule) => {
        const identifiers = Array.isArray(rule.identifiers)
            ? rule.identifiers.map((id) => new RegExp(id, "u"))
            : [new RegExp(rule.identifiers, "u")];
        const immutability = typeof rule.immutability === "string"
            ? isImmutableType.Immutability[rule.immutability]
            : rule.immutability;
        const comparator = rule.comparator === undefined
            ? RuleEnforcementComparator.AtLeast
            : typeof rule.comparator === "string"
                ? RuleEnforcementComparator[rule.comparator]
                : rule.comparator;
        const fixers = rule.fixer === undefined || rule.fixer === false
            ? false
            : (Array.isArray(rule.fixer) ? rule.fixer : [rule.fixer]).map((r) => ({
                ...r,
                pattern: new RegExp(r.pattern, "us"),
            }));
        const suggestions = rule.suggestions === undefined || rule.suggestions === false
            ? false
            : rule.suggestions.map((r) => ({
                ...r,
                pattern: new RegExp(r.pattern, "us"),
            }));
        return {
            identifiers,
            immutability,
            comparator,
            fixers,
            suggestions,
        };
    });
}
/**
 * Find the first rule to apply to the given node.
 */
function getRuleToApply(node, context, options) {
    const rules = getRules(options);
    if (rules.length === 0) {
        return undefined;
    }
    const texts = getNodeIdentifierTexts(node, context);
    if (texts.length === 0) {
        return undefined;
    }
    return rules.find((rule) => rule.identifiers.some((pattern) => texts.some((text) => pattern.test(text))));
}
/**
 * Get a fixer that uses the user config.
 */
function getConfiguredFixer(node, context, configs) {
    const text = context.sourceCode.getText(node);
    const config = configs.find((c) => c.pattern.test(text));
    if (config === undefined) {
        return null;
    }
    return (fixer) => fixer.replaceText(node, text.replace(config.pattern, config.replace));
}
/**
 * Get the suggestions that uses the user config.
 */
function getConfiguredSuggestions(node, context, configs, messageId) {
    const text = context.sourceCode.getText(node);
    const matchingConfig = configs.filter((c) => c.pattern.test(text));
    if (matchingConfig.length === 0) {
        return null;
    }
    return matchingConfig.map((config) => ({
        fix: (fixer) => fixer.replaceText(node, text.replace(config.pattern, config.replace)),
        messageId,
    }));
}
/**
 * Compare the actual immutability to the expected immutability.
 */
function compareImmutability(rule, actual) {
    switch (rule.comparator) {
        case RuleEnforcementComparator.Less: {
            return actual < rule.immutability;
        }
        case RuleEnforcementComparator.AtMost: {
            return actual <= rule.immutability;
        }
        case RuleEnforcementComparator.Exactly: {
            return actual === rule.immutability;
        }
        case RuleEnforcementComparator.AtLeast: {
            return actual >= rule.immutability;
        }
        case RuleEnforcementComparator.More: {
            return actual > rule.immutability;
        }
    }
}
/**
 * Get the results.
 */
function getResults(node, context, rule, immutability) {
    const valid = compareImmutability(rule, immutability);
    if (valid) {
        return {
            context,
            descriptors: [],
        };
    }
    const messageId = RuleEnforcementComparator[rule.comparator];
    const fix = rule.fixers === false || isTSInterfaceDeclaration(node)
        ? null
        : getConfiguredFixer(node.typeAnnotation, context, rule.fixers);
    const suggest = rule.suggestions === false || isTSInterfaceDeclaration(node)
        ? null
        : getConfiguredSuggestions(node.typeAnnotation, context, rule.suggestions, messageId);
    return {
        context,
        descriptors: [
            {
                node: node.id,
                messageId,
                data: {
                    actual: isImmutableType.Immutability[immutability],
                    expected: isImmutableType.Immutability[rule.immutability],
                },
                fix,
                suggest,
            },
        ],
    };
}
/**
 * Check if the given Interface or Type Alias violates this rule.
 */
function checkTypeDeclaration(node, context, options) {
    const [optionsObject] = options;
    const { ignoreInterfaces, ignoreIdentifierPattern } = optionsObject;
    if (shouldIgnorePattern(node, context, ignoreIdentifierPattern) ||
        (ignoreInterfaces && isTSInterfaceDeclaration(node))) {
        return {
            context,
            descriptors: [],
        };
    }
    const rule = getRuleToApply(node, context, options);
    if (rule === undefined) {
        return {
            context,
            descriptors: [],
        };
    }
    const maxImmutability = rule.comparator === RuleEnforcementComparator.AtLeast
        ? rule.immutability
        : rule.comparator === RuleEnforcementComparator.More
            ? rule.immutability + 1
            : undefined;
    const immutability = getTypeImmutabilityOfNode(node, context, maxImmutability);
    return getResults(node, context, rule, immutability);
}
// Create the rule.
const rule = createRule(name, meta$1, defaultOptions, {
    TSTypeAliasDeclaration: checkTypeDeclaration,
    TSInterfaceDeclaration: checkTypeDeclaration,
});

/**
 * All of the custom rules.
 */
const rules = {
    [name$i]: rule$i,
    [name$h]: rule$h,
    [name$g]: rule$g,
    [name$f]: rule$f,
    [name$e]: rule$e,
    [name$d]: rule$d,
    [name$c]: rule$c,
    [name$b]: rule$b,
    [name$a]: rule$a,
    [name$9]: rule$9,
    [name$8]: rule$8,
    [name$7]: rule$7,
    [name$6]: rule$6,
    [name$5]: rule$5,
    [name$4]: rule$4,
    [name$3]: rule$3,
    [name$2]: rule$2,
    [name$1]: rule$1,
    [name]: rule,
};

var all = {
    ...Object.fromEntries(Object.entries(rules)
        .filter(([, rule]) => rule.meta.deprecated !== true)
        .map(([name, rule]) => [
        `${ruleNameScope}/${name}`,
        rule.meta.docs.recommendedSeverity,
    ])),
};

var currying = Object.fromEntries(Object.entries(rules)
    .filter(([, rule]) => rule.meta.deprecated !== true &&
    rule.meta.docs.category === "Currying" &&
    rule.meta.docs.recommended !== false)
    .map(([name, rule]) => [
    `${ruleNameScope}/${name}`,
    rule.meta.docs.recommendedSeverity,
]));

var disableTypeChecked = Object.fromEntries(Object.entries(rules)
    .filter(([, rule]) => rule.meta.docs?.requiresTypeChecking === true)
    .map(([name]) => [`${ruleNameScope}/${name}`, "off"]));

var externalVanillaRecommended = {
    "prefer-const": "error",
    "no-param-reassign": "error",
    "no-var": "error",
};

const tsConfig = {
    "@typescript-eslint/prefer-readonly": "error",
    "@typescript-eslint/switch-exhaustiveness-check": "error",
};
var externalTypeScriptRecommended = {
    ...externalVanillaRecommended,
    ...tsConfig,
};

const recommended = Object.fromEntries(Object.entries(rules)
    .filter(([, rule]) => rule.meta.deprecated !== true &&
    rule.meta.docs.recommended === "recommended" &&
    rule.meta.docs.category !== "Stylistic")
    .map(([name, rule]) => [
    `${ruleNameScope}/${name}`,
    rule.meta.docs.recommendedSeverity,
]));
const overrides$1 = {
    [fullName$9]: [
        "error",
        {
            enforceParameterCount: {
                ignoreLambdaExpression: true,
                ignoreIIFE: true,
                ignoreGettersAndSetters: true,
            },
        },
    ],
    [fullName$7]: [
        "error",
        {
            allowReturningBranches: true,
        },
    ],
    [fullName$5]: [
        "error",
        {
            allowInForLoopInit: true,
        },
    ],
    [fullName$4]: "off",
    [fullName$3]: [
        "error",
        {
            allowInAsyncFunctions: true,
        },
    ],
    [fullName$2]: "off",
    [fullName$1]: [
        "error",
        {
            enforcement: "None",
            ignoreInferredTypes: true,
            parameters: {
                enforcement: "ReadonlyDeep",
            },
        },
    ],
    [fullName]: [
        "error",
        {
            rules: [
                {
                    identifiers: ["^I?Immutable.+"],
                    immutability: isImmutableType.Immutability.Immutable,
                    comparator: RuleEnforcementComparator.AtLeast,
                },
                {
                    identifiers: ["^I?ReadonlyDeep.+"],
                    immutability: isImmutableType.Immutability.ReadonlyDeep,
                    comparator: RuleEnforcementComparator.AtLeast,
                },
                {
                    identifiers: ["^I?Readonly.+"],
                    immutability: isImmutableType.Immutability.ReadonlyShallow,
                    comparator: RuleEnforcementComparator.AtLeast,
                    suggestions: [
                        {
                            pattern: "^(Array|Map|Set)<(.+)>$",
                            replace: "Readonly$1<$2>",
                        },
                        {
                            pattern: "^(.+)$",
                            replace: "Readonly<$1>",
                        },
                    ],
                },
                {
                    identifiers: ["^I?Mutable.+"],
                    immutability: isImmutableType.Immutability.Mutable,
                    comparator: RuleEnforcementComparator.AtMost,
                    suggestions: [
                        {
                            pattern: "^Readonly(Array|Map|Set)<(.+)>$",
                            replace: "$1<$2>",
                        },
                        {
                            pattern: "^Readonly<(.+)>$",
                            replace: "$1",
                        },
                    ],
                },
            ],
        },
    ],
};
var recommended$1 = {
    ...recommended,
    ...overrides$1,
};

const overrides = {
    [fullName$9]: [
        "error",
        {
            enforceParameterCount: false,
        },
    ],
    [fullName$8]: ["error", { ignoreClasses: "fieldsOnly" }],
    [fullName$7]: "off",
    [fullName$6]: "off",
    [fullName$1]: [
        "error",
        {
            enforcement: "None",
            ignoreInferredTypes: true,
            parameters: {
                enforcement: "ReadonlyShallow",
            },
        },
    ],
};
var lite = {
    ...recommended$1,
    ...overrides,
};

var noExceptions = Object.fromEntries(Object.entries(rules)
    .filter(([, rule]) => rule.meta.deprecated !== true &&
    rule.meta.docs.category === "No Exceptions" &&
    rule.meta.docs.recommended !== false)
    .map(([name, rule]) => [
    `${ruleNameScope}/${name}`,
    rule.meta.docs.recommendedSeverity,
]));

var noMutations = Object.fromEntries(Object.entries(rules)
    .filter(([, rule]) => rule.meta.deprecated !== true &&
    rule.meta.docs.category === "No Mutations" &&
    rule.meta.docs.recommended !== false)
    .map(([name, rule]) => [
    `${ruleNameScope}/${name}`,
    rule.meta.docs.recommendedSeverity,
]));

var noOtherParadigms = Object.fromEntries(Object.entries(rules)
    .filter(([, rule]) => rule.meta.deprecated !== true &&
    rule.meta.docs.category === "No Other Paradigms" &&
    rule.meta.docs.recommended !== false)
    .map(([name, rule]) => [
    `${ruleNameScope}/${name}`,
    rule.meta.docs.recommendedSeverity,
]));

var noStatements = Object.fromEntries(Object.entries(rules)
    .filter(([, rule]) => rule.meta.deprecated !== true &&
    rule.meta.docs.category === "No Statements" &&
    rule.meta.docs.recommended !== false)
    .map(([name, rule]) => [
    `${ruleNameScope}/${name}`,
    rule.meta.docs.recommendedSeverity,
]));

var off = Object.fromEntries(Object.entries(rules).map(([name]) => [`${ruleNameScope}/${name}`, "off"]));

var strict = Object.fromEntries(Object.entries(rules)
    .filter(([, rule]) => rule.meta.deprecated !== true &&
    rule.meta.docs.recommended !== false &&
    rule.meta.docs.category !== "Stylistic")
    .map(([name, rule]) => [
    `${ruleNameScope}/${name}`,
    rule.meta.docs.recommendedSeverity,
]));

var stylistic = Object.fromEntries(Object.entries(rules)
    .filter(([, rule]) => rule.meta.deprecated !== true &&
    rule.meta.docs.category === "Stylistic" &&
    rule.meta.docs.recommended !== false)
    .map(([name, rule]) => [
    `${ruleNameScope}/${name}`,
    rule.meta.docs.recommendedSeverity,
]));

const meta = {
    name: "eslint-plugin-functional",
    version: __VERSION__,
};
const functional = {
    meta,
    rules,
};
const configs = {
    all: { plugins: { functional }, rules: all },
    lite: { plugins: { functional }, rules: lite },
    recommended: { plugins: { functional }, rules: recommended$1 },
    strict: { plugins: { functional }, rules: strict },
    off: { plugins: { functional }, rules: off },
    disableTypeChecked: {
        plugins: { functional },
        rules: disableTypeChecked,
    },
    externalVanillaRecommended: {
        plugins: { functional },
        rules: externalVanillaRecommended,
    },
    externalTypescriptRecommended: {
        plugins: { functional },
        rules: externalTypeScriptRecommended,
    },
    currying: { plugins: { functional }, rules: currying },
    noExceptions: { plugins: { functional }, rules: noExceptions },
    noMutations: { plugins: { functional }, rules: noMutations },
    noOtherParadigms: {
        plugins: { functional },
        rules: noOtherParadigms,
    },
    noStatements: { plugins: { functional }, rules: noStatements },
    stylistic: { plugins: { functional }, rules: stylistic },
};
// eslint-disable-next-line functional/immutable-data, functional/no-expression-statements
functional.configs = configs;

module.exports = functional;