{"version":3,"file":"prefer-lookup-table.cjs","names":[],"sources":["../../../src/rules/code-style/prefer-lookup-table.ts"],"sourcesContent":["import type {Rule} from 'eslint'\n\n/**\n * ESLint rule: prefer-lookup-table\n *\n * Detects long chains of `||` checks against the same variable and suggests using a Set lookup or Array.includes.\n */\nconst rule: Rule.RuleModule = {\n  meta: {\n    type: 'suggestion',\n    docs: {\n      description: 'Prefer Set.has or Array.includes for multiple equality checks against the same variable',\n      recommended: false\n    },\n    fixable: 'code',\n    schema: [\n      {\n        type: 'object',\n        properties: {\n          threshold: {type: 'integer', minimum: 3, default: 4}\n        },\n        additionalProperties: false\n      }\n    ],\n    messages: {\n      preferLookup: 'Found {{count}} checks against the same value. Consider optimizing with a lookup table (Set/Array).'\n    }\n  },\n  create(context) {\n    const {sourceCode} = context\n    const options = (context.options[0] ?? {}) as {threshold?: number}\n    const threshold = options.threshold ?? 4\n\n    function getNormalizedText(node: Rule.Node): string { /* 辅助函数：标准化节点文本，去除空格干扰 */\n      return sourceCode.getText(node).replaceAll(/\\s+/g, '')\n    }\n\n    function isEqualityCheck(node: Rule.Node): boolean { /* 辅助函数：判断是否是简单的相等比较节点 */\n      if (node.type !== 'BinaryExpression') return false\n      const op = (node as unknown as {operator: string}).operator\n      return op === '===' || op === '=='\n    }\n\n    function isPure(node: Rule.Node): boolean { /* 辅助函数：判断节点是否包含副作用 */\n      return node.type === 'Identifier' || node.type === 'MemberExpression' || node.type === 'Literal'\n    }\n\n    function collectConditions(node: Rule.Node, operator: string, conditions: Rule.Node[] = []): Rule.Node[] { /* 递归收集 LogicalExpression 中的所有条件 */\n      if (node.type === 'LogicalExpression' && (node as unknown as {operator: string}).operator === operator) {\n        const logicalNode = node as Rule.Node & {left: Rule.Node, right: Rule.Node, operator: string}\n        collectConditions(logicalNode.left, operator, conditions)\n        collectConditions(logicalNode.right, operator, conditions)\n      } else conditions.push(node)\n      return conditions\n    }\n\n    const reportSet = new Set<Rule.Node>()\n\n    return {\n      LogicalExpression(node) {\n        if ((node as unknown as {operator: string}).operator !== '||') return /* 只处理 || 链 */\n        if (reportSet.has(node)) return /* 避免重复报告子节点 */\n        const currentParent = node.parent\n        if (currentParent?.type === 'LogicalExpression' && (currentParent as unknown as {operator: string}).operator === '||') return /* 让顶层处理 */\n\n        const conditions = collectConditions(node, '||')\n        if (conditions.length < threshold) return\n\n        const subjectMap = new Map<string, {subject: Rule.Node, values: Rule.Node[]}>() /* 分析每个条件 */\n\n        for (const condition of conditions) {\n          if (!isEqualityCheck(condition)) continue /* 必须是相等比较 */\n\n          const binExpr = condition as Rule.Node & {left: Rule.Node, right: Rule.Node}\n          let subject: Rule.Node | null = null\n          let value: Rule.Node | null = null\n\n          if (isPure(binExpr.left) && binExpr.right.type === 'Literal') { /* 尝试找出 subject (变量) 和 value (字面量) */\n            subject = binExpr.left\n            value = binExpr.right\n          } else if (isPure(binExpr.right) && binExpr.left.type === 'Literal') {\n            subject = binExpr.right\n            value = binExpr.left\n          }\n\n          if (subject !== null && value !== null) {\n            const subjectKey = getNormalizedText(subject)\n            if (!subjectMap.has(subjectKey)) subjectMap.set(subjectKey, {subject, values: []})\n            subjectMap.get(subjectKey)!.values.push(value)\n          }\n        }\n\n        for (const [_, {subject, values}] of subjectMap.entries()) { /* 检查是否有某个 subject 超过阈值 */\n          if (values.length >= threshold) {\n            context.report({\n              node,\n              messageId: 'preferLookup',\n              data: {count: values.length.toString()},\n              fix(fixer) {\n                const valuesText = values.map((v: Rule.Node) => sourceCode.getText(v)).join(', ')\n                const subjectText = sourceCode.getText(subject)\n                return fixer.replaceText(node, `new Set([${valuesText}]).has(${subjectText})`)\n              }\n            })\n            break\n          }\n        }\n      }\n    }\n  }\n}\n\nexport default rule\n"],"mappings":";;;;;;;AAOA,MAAM,OAAwB;CAC5B,MAAM;EACJ,MAAM;EACN,MAAM;GACJ,aAAa;GACb,aAAa;GACd;EACD,SAAS;EACT,QAAQ,CACN;GACE,MAAM;GACN,YAAY,EACV,WAAW;IAAC,MAAM;IAAW,SAAS;IAAG,SAAS;IAAE,EACrD;GACD,sBAAsB;GACvB,CACF;EACD,UAAU,EACR,cAAc,uGACf;EACF;CACD,OAAO,SAAS;EACd,MAAM,EAAC,eAAc;EAErB,MAAM,aADW,QAAQ,QAAQ,MAAM,EAAE,EACf,aAAa;EAEvC,SAAS,kBAAkB,MAAyB;AAClD,UAAO,WAAW,QAAQ,KAAK,CAAC,WAAW,QAAQ,GAAG;;EAGxD,SAAS,gBAAgB,MAA0B;AACjD,OAAI,KAAK,SAAS,mBAAoB,QAAO;GAC7C,MAAM,KAAM,KAAuC;AACnD,UAAO,OAAO,SAAS,OAAO;;EAGhC,SAAS,OAAO,MAA0B;AACxC,UAAO,KAAK,SAAS,gBAAgB,KAAK,SAAS,sBAAsB,KAAK,SAAS;;EAGzF,SAAS,kBAAkB,MAAiB,UAAkB,aAA0B,EAAE,EAAe;AACvG,OAAI,KAAK,SAAS,uBAAwB,KAAuC,aAAa,UAAU;IACtG,MAAM,cAAc;AACpB,sBAAkB,YAAY,MAAM,UAAU,WAAW;AACzD,sBAAkB,YAAY,OAAO,UAAU,WAAW;SACrD,YAAW,KAAK,KAAK;AAC5B,UAAO;;EAGT,MAAM,4BAAY,IAAI,KAAgB;AAEtC,SAAO,EACL,kBAAkB,MAAM;AACtB,OAAK,KAAuC,aAAa,KAAM;AAC/D,OAAI,UAAU,IAAI,KAAK,CAAE;GACzB,MAAM,gBAAgB,KAAK;AAC3B,OAAI,eAAe,SAAS,uBAAwB,cAAgD,aAAa,KAAM;GAEvH,MAAM,aAAa,kBAAkB,MAAM,KAAK;AAChD,OAAI,WAAW,SAAS,UAAW;GAEnC,MAAM,6BAAa,IAAI,KAAwD;AAE/E,QAAK,MAAM,aAAa,YAAY;AAClC,QAAI,CAAC,gBAAgB,UAAU,CAAE;IAEjC,MAAM,UAAU;IAChB,IAAI,UAA4B;IAChC,IAAI,QAA0B;AAE9B,QAAI,OAAO,QAAQ,KAAK,IAAI,QAAQ,MAAM,SAAS,WAAW;AAC5D,eAAU,QAAQ;AAClB,aAAQ,QAAQ;eACP,OAAO,QAAQ,MAAM,IAAI,QAAQ,KAAK,SAAS,WAAW;AACnE,eAAU,QAAQ;AAClB,aAAQ,QAAQ;;AAGlB,QAAI,YAAY,QAAQ,UAAU,MAAM;KACtC,MAAM,aAAa,kBAAkB,QAAQ;AAC7C,SAAI,CAAC,WAAW,IAAI,WAAW,CAAE,YAAW,IAAI,YAAY;MAAC;MAAS,QAAQ,EAAE;MAAC,CAAC;AAClF,gBAAW,IAAI,WAAW,CAAE,OAAO,KAAK,MAAM;;;AAIlD,QAAK,MAAM,CAAC,GAAG,EAAC,SAAS,aAAY,WAAW,SAAS,CACvD,KAAI,OAAO,UAAU,WAAW;AAC9B,YAAQ,OAAO;KACb;KACA,WAAW;KACX,MAAM,EAAC,OAAO,OAAO,OAAO,UAAU,EAAC;KACvC,IAAI,OAAO;MACT,MAAM,aAAa,OAAO,KAAK,MAAiB,WAAW,QAAQ,EAAE,CAAC,CAAC,KAAK,KAAK;MACjF,MAAM,cAAc,WAAW,QAAQ,QAAQ;AAC/C,aAAO,MAAM,YAAY,MAAM,YAAY,WAAW,SAAS,YAAY,GAAG;;KAEjF,CAAC;AACF;;KAIP;;CAEJ"}