'use strict'; const require_runtime = require('../_virtual/_rolldown/runtime.js'); const require_index = require('../utils/index.js'); //#region lib/rules/no-unused-emit-declarations.js /** * @author ItMaga * See LICENSE file in root directory for full license. */ var require_no_unused_emit_declarations = /* @__PURE__ */ require_runtime.__commonJSMin(((exports, module) => { const { findVariable } = require("@eslint-community/eslint-utils"); const utils = require_index.default; /** * @typedef {import('../utils').ComponentEmit} ComponentEmit * @typedef {import('../utils').VueObjectData} VueObjectData */ /** * @typedef {object} SetupContext * @property {Set} contextReferenceIds * @property {Set} emitReferenceIds */ /** * @typedef {object} NameWithLoc * @property {string} name * @property {SourceLocation} loc * @property {Range} range */ /** * Get the name param node from the given CallExpression * @param {CallExpression} node CallExpression * @returns {NameWithLoc | null} */ function getNameParamNode(node) { const nameLiteralNode = node.arguments[0]; if (nameLiteralNode && utils.isStringLiteral(nameLiteralNode)) { const name = utils.getStringLiteralValue(nameLiteralNode); if (name != null) return { name, loc: nameLiteralNode.loc, range: nameLiteralNode.range }; } return null; } /** * Check if the given node is a reference of setup context * @param {Expression | Super | SpreadElement} value * @param {SetupContext} setupContext * @returns {boolean} * */ function hasReferenceId(value, setupContext) { const { contextReferenceIds, emitReferenceIds } = setupContext; return value.type === "Identifier" && (emitReferenceIds.has(value) || contextReferenceIds.has(value)); } module.exports = { meta: { type: "suggestion", docs: { description: "disallow unused emit declarations", categories: void 0, url: "https://eslint.vuejs.org/rules/no-unused-emit-declarations.html" }, fixable: null, schema: [], messages: { unused: "`{{name}}` is defined as emit but never used." } }, create(context) { /** @type {Map} */ const emitDeclarations = /* @__PURE__ */ new Map(); /** @type {Map} */ const emitCalls = /* @__PURE__ */ new Map(); /** @type {Map} */ const setupContexts = /* @__PURE__ */ new Map(); const programNode = context.sourceCode.ast; let emitParamName = ""; /** * @param {CallExpression} node * */ function addEmitCall(node) { const nameParamNode = getNameParamNode(node); if (nameParamNode) emitCalls.set(nameParamNode.name, node); } function clearEmits() { emitCalls.clear(); emitDeclarations.clear(); } /** * @param {Expression | SpreadElement} expression * @param {SetupContext} setupContext * @returns {boolean} * */ function checkExpressionReference(expression, setupContext) { if (expression.type === "MemberExpression") { if (hasReferenceId(utils.skipChainExpression(expression.object), setupContext)) { clearEmits(); return true; } } if (hasReferenceId(expression, setupContext)) { clearEmits(); return true; } return false; } /** * * @param {Array} args * @param {SetupContext} setupContext * @returns {boolean} */ function verifyArgumentsReferences(args, setupContext) { for (const argument of args) { if (argument.type === "ObjectExpression") { for (const property of argument.properties) if (property.type === "Property" && checkExpressionReference(property.value, setupContext)) return true; } if (argument.type === "ArrayExpression") for (const element of argument.elements) { if (!element) continue; if (checkExpressionReference(element, setupContext)) return true; } if (checkExpressionReference(argument, setupContext)) return true; } return false; } /** * @param {Expression | Super} callee * @param {Set} referenceIds * @param {CallExpression} node * */ function addEmitCallByReference(callee, referenceIds, node) { if (callee.type === "Identifier" && referenceIds.has(callee)) addEmitCall(node); } const callVisitor = { CallExpression(node, info) { const callee = utils.skipChainExpression(node.callee); let emit = null; if (callee.type === "MemberExpression") { const name = utils.getStaticPropertyName(callee); if (name === "emit" || name === "$emit") emit = { name, member: callee }; } const vueDefineNode = info ? info.node : programNode; const setupContext = setupContexts.get(vueDefineNode); if (setupContext) { if (callee.parent.type === "CallExpression" && callee.parent.arguments && verifyArgumentsReferences(callee.parent.arguments, setupContext)) return; const { contextReferenceIds, emitReferenceIds } = setupContext; addEmitCallByReference(callee, emitReferenceIds, node); if (emit && emit.name === "emit") addEmitCallByReference(utils.skipChainExpression(emit.member.object), contextReferenceIds, node); } if (emit && emit.name === "$emit") { const memObject = utils.skipChainExpression(emit.member.object); if (utils.isThis(memObject, context)) addEmitCall(node); } if (callee.type === "Identifier" && (callee.name === "$emit" || callee.name === emitParamName)) addEmitCall(node); } }; return utils.compositingVisitors(utils.defineTemplateBodyVisitor(context, callVisitor), utils.defineVueVisitor(context, { ...callVisitor, onVueObjectEnter(node) { for (const emit of utils.getComponentEmitsFromOptions(node)) if (emit.emitName) emitDeclarations.set(emit.emitName, emit); }, onSetupFunctionEnter(node, { node: vueNode }) { const contextParam = node.params[1]; if (!contextParam || contextParam.type === "RestElement" || contextParam.type === "ArrayPattern") return; /** @type {Set} */ const contextReferenceIds = /* @__PURE__ */ new Set(); /** @type {Set} */ const emitReferenceIds = /* @__PURE__ */ new Set(); if (contextParam.type === "ObjectPattern") { const emitProperty = utils.findAssignmentProperty(contextParam, "emit"); if (!emitProperty) return; const emitParam = emitProperty.value; const variable = emitParam.type === "Identifier" ? findVariable(utils.getScope(context, emitParam), emitParam) : null; if (!variable) return; for (const reference of variable.references) emitReferenceIds.add(reference.identifier); } else if (contextParam.type === "Identifier") { const variable = findVariable(utils.getScope(context, contextParam), contextParam); for (const reference of variable.references) contextReferenceIds.add(reference.identifier); } setupContexts.set(vueNode, { contextReferenceIds, emitReferenceIds }); } }), utils.defineScriptSetupVisitor(context, { onDefineEmitsEnter(node, emits) { for (const emit of emits) if (emit.emitName) emitDeclarations.set(emit.emitName, emit); if (!node.parent || node.parent.type !== "VariableDeclarator" || node.parent.init !== node) return; const emitParam = node.parent.id; if (emitParam.type !== "Identifier") return; emitParamName = emitParam.name; const variable = findVariable(utils.getScope(context, emitParam), emitParam); if (!variable) return; /** @type {Set} */ const emitReferenceIds = /* @__PURE__ */ new Set(); for (const reference of variable.references) emitReferenceIds.add(reference.identifier); setupContexts.set(programNode, { contextReferenceIds: /* @__PURE__ */ new Set(), emitReferenceIds }); }, onDefineModelEnter(node, model) { if (node.parent && node.parent.type === "VariableDeclarator" && node.parent.init === node) emitCalls.set(`update:${model.name.modelName}`, node); }, ...callVisitor }), { "Program:exit"() { for (const [name, emit] of emitDeclarations) if (!emitCalls.has(name) && emit.node) context.report({ node: emit.node, loc: emit.node.loc, messageId: "unused", data: { name } }); } }); } }; })); //#endregion Object.defineProperty(exports, 'default', { enumerable: true, get: function () { return require_no_unused_emit_declarations(); } });