Files
routie/frontend/node_modules/eslint-plugin-vue/dist/rules/no-unused-emit-declarations.js
T

224 lines
8.3 KiB
JavaScript

'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<Identifier>} contextReferenceIds
* @property {Set<Identifier>} 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<string, ComponentEmit>} */
const emitDeclarations = /* @__PURE__ */ new Map();
/** @type {Map<string, Expression>} */
const emitCalls = /* @__PURE__ */ new Map();
/** @type {Map<ObjectExpression | Program, SetupContext>} */
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<Expression | SpreadElement>} 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<Identifier>} 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<Identifier>} */
const contextReferenceIds = /* @__PURE__ */ new Set();
/** @type {Set<Identifier>} */
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<Identifier>} */
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();
}
});