UNPKG

eslint-plugin-vue

Version:

Official ESLint plugin for Vue.js

131 lines (130 loc) 4.45 kB
"use strict"; const require_runtime = require("../_virtual/_rolldown/runtime.js"); const require_index = require("../utils/index.js"); //#region lib/rules/no-unused-vars.js /** * @fileoverview disallow unused variable definitions of v-for directives or scope attributes. * @author 薛定谔的猫<hh_2013@foxmail.com> */ var require_no_unused_vars = /* @__PURE__ */ require_runtime.__commonJSMin(((exports, module) => { const utils = require_index.default; /** * @typedef {VVariable['kind']} VariableKind */ /** * Groups variables by directive kind. * @param {VElement} node The element node * @returns { { [kind in VariableKind]?: VVariable[] } } The variables of grouped by directive kind. */ function groupingVariables(node) { /** @type { { [kind in VariableKind]?: VVariable[] } } */ const result = {}; for (const variable of node.variables) { const kind = variable.kind; result[kind] ||= []; result[kind].push(variable); } return result; } /** * Checks if the given variable was defined by destructuring. * @param {VVariable} variable the given variable to check * @returns {boolean} `true` if the given variable was defined by destructuring. */ function isDestructuringVar(variable) { /** @type {ASTNode | null} */ let parent = variable.id.parent; while (parent) { if (parent.type === "VForExpression" || parent.type === "VSlotScopeExpression") return false; if (parent.type === "Property" || parent.type === "ArrayPattern") return true; parent = parent.parent; } return false; } /** * Checks if the given variable name is used as a component tag in the element's descendants. * @param {string} variableName the variable name to check * @param {VElement} element the element node to search within * @returns {boolean} `true` if the variable name is used as a component tag. */ function isUsedAsComponentTag(variableName, element) { for (const child of element.children) { if (child.type !== "VElement") continue; if (child.rawName === variableName) return true; if (isUsedAsComponentTag(variableName, child)) return true; } return false; } module.exports = { meta: { type: "suggestion", docs: { description: "disallow unused variable definitions of v-for directives or scope attributes", categories: ["vue3-essential", "vue2-essential"], url: "https://eslint.vuejs.org/rules/no-unused-vars.html" }, fixable: null, hasSuggestions: true, schema: [{ type: "object", properties: { ignorePattern: { type: "string" } }, additionalProperties: false }], messages: { unusedVariable: "'{{name}}' is defined but never used.", replaceWithUnderscore: "Replace `{{name}}` with `_{{name}}` to ignore the unused variable." } }, /** @param {RuleContext} context */ create(context) { const ignorePattern = (context.options[0] || {}).ignorePattern; /** @type {RegExp | null} */ const ignoreRegEx = ignorePattern ? new RegExp(ignorePattern, "u") : null; /** * @param {VVariable[]} variables the variables of a single directive kind * @param {VElement} node the element node the variables belong to */ function checkVariableGroup(variables, node) { let hasAfterUsed = false; for (let i = variables.length - 1; i >= 0; i--) { const variable = variables[i]; if (variable.references.length > 0) { hasAfterUsed = true; continue; } if (ignoreRegEx != null && ignoreRegEx.test(variable.id.name)) continue; if (hasAfterUsed && !isDestructuringVar(variable)) continue; if (isUsedAsComponentTag(variable.id.name, node)) continue; context.report({ node: variable.id, loc: variable.id.loc, messageId: "unusedVariable", data: { name: variable.id.name }, suggest: ignorePattern === "^_" ? [{ messageId: "replaceWithUnderscore", data: { name: variable.id.name }, fix(fixer) { return fixer.replaceText(variable.id, `_${variable.id.name}`); } }] : [] }); } } return utils.defineTemplateBodyVisitor(context, { /** * @param {VElement} node */ VElement(node) { const vars = groupingVariables(node); for (const variables of Object.values(vars)) if (variables) checkVariableGroup(variables, node); } }); } }; })); //#endregion Object.defineProperty(exports, "default", { enumerable: true, get: function() { return require_no_unused_vars(); } });