UNPKG

eslint-plugin-vue

Version:

Official ESLint plugin for Vue.js

114 lines (111 loc) 3.66 kB
'use strict'; const require_runtime = require('../_virtual/_rolldown/runtime.js'); const require_index = require('../utils/index.js'); //#region lib/rules/return-in-emits-validator.js /** * @author Yosuke Ota * See LICENSE file in root directory for full license. */ var require_return_in_emits_validator = /* @__PURE__ */ require_runtime.__commonJSMin(((exports, module) => { const utils = require_index.default; /** * @typedef {import('../utils').ComponentEmit} ComponentEmit * @typedef {import('../utils').ComponentObjectEmit} ComponentObjectEmit */ /** * Checks if the given node value is falsy. * @param {Expression} node The node to check * @returns {boolean} If `true`, the given node value is falsy. */ function isFalsy(node) { if (node.type === "Literal") { if (node.bigint) return node.bigint === "0"; if (!node.value) return true; } return node.type === "Identifier" && (node.name === "undefined" || node.name === "NaN"); } module.exports = { meta: { type: "problem", docs: { description: "enforce that a return statement is present in emits validator", categories: ["vue3-essential", "vue2-essential"], url: "https://eslint.vuejs.org/rules/return-in-emits-validator.html" }, fixable: null, schema: [], messages: { expectedTrue: "Expected to return a true value in \"{{name}}\" emits validator.", expectedBoolean: "Expected to return a boolean value in \"{{name}}\" emits validator." } }, create(context) { /** @type {ComponentObjectEmit[]} */ const emitsValidators = []; /** * @typedef {object} ScopeStack * @property {ScopeStack | null} upper * @property {FunctionExpression | FunctionDeclaration | ArrowFunctionExpression} functionNode * @property {boolean} hasReturnValue * @property {boolean} possibleOfReturnTrue */ /** * @type {ScopeStack | null} */ let scopeStack = null; /** * @param {ComponentEmit[]} emits */ function processEmits(emits) { for (const emit of emits) { if (emit.type !== "object" || !emit.value) continue; if (emit.value.type !== "FunctionExpression" && emit.value.type !== "ArrowFunctionExpression") continue; emitsValidators.push(emit); } } return utils.compositingVisitors(utils.defineScriptSetupVisitor(context, { onDefineEmitsEnter(_node, emits) { processEmits(emits); } }), utils.defineVueVisitor(context, { onVueObjectEnter(obj) { processEmits(utils.getComponentEmitsFromOptions(obj)); } }), { ":function"(node) { scopeStack = { upper: scopeStack, functionNode: node, hasReturnValue: false, possibleOfReturnTrue: false }; if (node.type === "ArrowFunctionExpression" && node.expression) { scopeStack.hasReturnValue = true; if (!isFalsy(node.body)) scopeStack.possibleOfReturnTrue = true; } }, ReturnStatement(node) { if (!scopeStack) return; if (node.argument) { scopeStack.hasReturnValue = true; if (!isFalsy(node.argument)) scopeStack.possibleOfReturnTrue = true; } }, ":function:exit"(node) { if (scopeStack && !scopeStack.possibleOfReturnTrue) { const emits = emitsValidators.find((e) => e.value === node); if (emits) context.report({ node, messageId: scopeStack.hasReturnValue ? "expectedTrue" : "expectedBoolean", data: { name: emits.emitName || "Unknown" } }); } scopeStack = scopeStack && scopeStack.upper; } }); } }; })); //#endregion Object.defineProperty(exports, 'default', { enumerable: true, get: function () { return require_return_in_emits_validator(); } });