{"version":3,"file":"prefer-void-zero.mjs","names":[],"sources":["../../../src/rules/code-style/prefer-void-zero.ts"],"sourcesContent":["import type {Rule} from 'eslint'\n\n/**\n * ESLint rule: prefer-void-zero\n *\n * Detects and fixes `undefined` to `void 0` in value positions.\n * Only fixes value-level `undefined`, NOT type annotations.\n */\nconst directTypeContexts = new Set(['TSTypeAnnotation', 'TSTypeAliasDeclaration', 'TSInterfaceDeclaration', 'TSTypeParameterDeclaration', 'TSTypeParameterInstantiation', 'TSTypeLiteral', 'TSPropertySignature', 'TSMethodSignature', 'TSIndexSignature', 'TSFunctionType', 'TSConstructorType', 'TSMappedType', 'TSConditionalType', 'TSInferType', 'TSTypeQuery', 'TSTypePredicate'])\nconst importExportTypes = new Set(['ImportSpecifier', 'ImportDefaultSpecifier', 'ImportNamespaceSpecifier', 'ExportSpecifier'])\n\nconst rule: Rule.RuleModule = {\n  meta: {\n    type: 'suggestion',\n    docs: {description: 'Prefer `void 0` over `undefined` in value positions', recommended: false},\n    fixable: 'code',\n    schema: [],\n    messages: {preferVoidZero: 'Use `void 0` instead of `undefined`'}\n  },\n  create(context) {\n    function isInTypeContext(node: Rule.Node): boolean { /* Check if the node is in a type annotation context */\n      let current: Rule.Node | null = node\n      while (current) {\n        const {parent} = current as Rule.Node & {parent?: Rule.Node}\n        if (parent === void 0 || parent === null) break\n        const parentType = parent.type as string /* 使用 string 类型来绕过 TypeScript 的类型检查 */\n\n        if (directTypeContexts.has(parentType)) return true\n        if (parentType === 'TSUnionType' || parentType === 'TSIntersectionType') return true /* Union/Intersection types */\n        if (parentType === 'TSUndefinedKeyword') return true /* TSUndefinedKeyword is always a type */\n\n        if (parentType === 'TSAsExpression') { /* TSAsExpression - check if we're in the type part */\n          const asExpr = parent as Rule.Node & {typeAnnotation: Rule.Node}\n          if (asExpr.typeAnnotation === current) return true\n        }\n\n        if (parentType === 'TSSatisfiesExpression') { /* TSSatisfiesExpression - check if we're in the type part */\n          const satisfiesExpr = parent as Rule.Node & {typeAnnotation: Rule.Node}\n          if (satisfiesExpr.typeAnnotation === current) return true\n        }\n        if (parentType === 'TSTypeReference') return true /* TSTypeReference - this is a type context */\n        current = parent\n      }\n      return false\n    }\n\n    function isUndefinedValue(node: Rule.Node): boolean { /* Check if this is the global `undefined` identifier being used as a value */\n      if (node.type !== 'Identifier') return false\n      const id = node as Rule.Node & {name: string}\n      if (id.name !== 'undefined') return false\n\n      if (isInTypeContext(node)) return false /* Skip if in type context */\n\n      const {parent} = node /* Skip if it's a property key (not value) */\n      if (parent?.type === 'Property') {\n        const prop = parent as Rule.Node & {key: Rule.Node, shorthand: boolean}\n        if (prop.key === node && !prop.shorthand) return false\n      }\n      if (parent?.type === 'AssignmentExpression') { /* Skip if it's being declared/assigned to */\n        const assign = parent as Rule.Node & {left: Rule.Node}\n        if (assign.left === node) return false\n      }\n      if (parent?.type === 'VariableDeclarator') { /* Skip if it's a variable declarator id */\n        const decl = parent as Rule.Node & {id: Rule.Node}\n        if (decl.id === node) return false\n      }\n      if (['FunctionDeclaration', 'FunctionExpression', 'ArrowFunctionExpression'].includes(parent?.type ?? '')) { /* Skip if it's a function parameter name */\n        const fn = parent as Rule.Node & {params: Rule.Node[]}\n        if (fn.params.includes(node)) return false\n      }\n      if (parent?.type && importExportTypes.has(parent.type as string)) return false /* Skip if it's an import/export specifier */\n      if (parent?.type !== 'MemberExpression') return true /* Skip member expression property (obj.undefined) */\n\n      const member = parent as Rule.Node & {property: Rule.Node, computed: boolean}\n      if (member.property === node && !member.computed) return false\n      return true\n    }\n\n    return {\n      Identifier(node) {\n        if (!isUndefinedValue(node)) return\n        context.report({node, messageId: 'preferVoidZero', fix: fixer => fixer.replaceText(node, 'void 0')})\n      }\n    }\n  }\n}\n\nexport default rule\n"],"mappings":";;;;;;;AAQA,MAAM,qBAAqB,IAAI,IAAI;CAAC;CAAoB;CAA0B;CAA0B;CAA8B;CAAgC;CAAiB;CAAuB;CAAqB;CAAoB;CAAkB;CAAqB;CAAgB;CAAqB;CAAe;CAAe;CAAkB,CAAC;AACxX,MAAM,oBAAoB,IAAI,IAAI;CAAC;CAAmB;CAA0B;CAA4B;CAAkB,CAAC;AAE/H,MAAM,OAAwB;CAC5B,MAAM;EACJ,MAAM;EACN,MAAM;GAAC,aAAa;GAAuD,aAAa;GAAM;EAC9F,SAAS;EACT,QAAQ,EAAE;EACV,UAAU,EAAC,gBAAgB,uCAAsC;EAClE;CACD,OAAO,SAAS;EACd,SAAS,gBAAgB,MAA0B;GACjD,IAAI,UAA4B;AAChC,UAAO,SAAS;IACd,MAAM,EAAC,WAAU;AACjB,QAAI,WAAW,KAAK,KAAK,WAAW,KAAM;IAC1C,MAAM,aAAa,OAAO;AAE1B,QAAI,mBAAmB,IAAI,WAAW,CAAE,QAAO;AAC/C,QAAI,eAAe,iBAAiB,eAAe,qBAAsB,QAAO;AAChF,QAAI,eAAe,qBAAsB,QAAO;AAEhD,QAAI,eAAe,kBAEjB;SADe,OACJ,mBAAmB,QAAS,QAAO;;AAGhD,QAAI,eAAe,yBAEjB;SADsB,OACJ,mBAAmB,QAAS,QAAO;;AAEvD,QAAI,eAAe,kBAAmB,QAAO;AAC7C,cAAU;;AAEZ,UAAO;;EAGT,SAAS,iBAAiB,MAA0B;AAClD,OAAI,KAAK,SAAS,aAAc,QAAO;AAEvC,OADW,KACJ,SAAS,YAAa,QAAO;AAEpC,OAAI,gBAAgB,KAAK,CAAE,QAAO;GAElC,MAAM,EAAC,WAAU;AACjB,OAAI,QAAQ,SAAS,YAAY;IAC/B,MAAM,OAAO;AACb,QAAI,KAAK,QAAQ,QAAQ,CAAC,KAAK,UAAW,QAAO;;AAEnD,OAAI,QAAQ,SAAS,wBAEnB;QADe,OACJ,SAAS,KAAM,QAAO;;AAEnC,OAAI,QAAQ,SAAS,sBAEnB;QADa,OACJ,OAAO,KAAM,QAAO;;AAE/B,OAAI;IAAC;IAAuB;IAAsB;IAA0B,CAAC,SAAS,QAAQ,QAAQ,GAAG,EAEvG;QADW,OACJ,OAAO,SAAS,KAAK,CAAE,QAAO;;AAEvC,OAAI,QAAQ,QAAQ,kBAAkB,IAAI,OAAO,KAAe,CAAE,QAAO;AACzE,OAAI,QAAQ,SAAS,mBAAoB,QAAO;GAEhD,MAAM,SAAS;AACf,OAAI,OAAO,aAAa,QAAQ,CAAC,OAAO,SAAU,QAAO;AACzD,UAAO;;AAGT,SAAO,EACL,WAAW,MAAM;AACf,OAAI,CAAC,iBAAiB,KAAK,CAAE;AAC7B,WAAQ,OAAO;IAAC;IAAM,WAAW;IAAkB,MAAK,UAAS,MAAM,YAAY,MAAM,SAAS;IAAC,CAAC;KAEvG;;CAEJ"}