eslint-plugin-vue
Version:
Official ESLint plugin for Vue.js
114 lines (111 loc) • 3.66 kB
JavaScript
;
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();
}
});