"use strict";
const require_runtime = require("../_virtual/_rolldown/runtime.js");
const require_index = require("../utils/index.js");
//#region lib/rules/order-in-components.js
/**
* @fileoverview Keep order of properties in components
* @author Michał Sajnóg
*/
var require_order_in_components = /* @__PURE__ */ require_runtime.__commonJSMin(((exports, module) => {
	const utils = require_index.default;
	const traverseNodes = require("vue-eslint-parser").AST.traverseNodes;
	/**
	* @typedef {import('eslint-visitor-keys').VisitorKeys} VisitorKeys
	*/
	const defaultOrder = [
		"el",
		"name",
		"key",
		"parent",
		"functional",
		["delimiters", "comments"],
		[
			"components",
			"directives",
			"filters"
		],
		"extends",
		"mixins",
		["provide", "inject"],
		"ROUTER_GUARDS",
		"layout",
		"middleware",
		"validate",
		"scrollToTop",
		"transition",
		"loading",
		"inheritAttrs",
		"model",
		["props", "propsData"],
		"emits",
		"slots",
		"expose",
		"setup",
		"asyncData",
		"data",
		"fetch",
		"head",
		"computed",
		"watch",
		"watchQuery",
		"LIFECYCLE_HOOKS",
		"methods",
		["template", "render"],
		"renderError"
	];
	/** @type { { [key: string]: string[] } } */
	const groups = {
		LIFECYCLE_HOOKS: [
			"beforeCreate",
			"created",
			"beforeMount",
			"mounted",
			"beforeUpdate",
			"updated",
			"activated",
			"deactivated",
			"beforeUnmount",
			"unmounted",
			"beforeDestroy",
			"destroyed",
			"renderTracked",
			"renderTriggered",
			"errorCaptured"
		],
		ROUTER_GUARDS: [
			"beforeRouteEnter",
			"beforeRouteUpdate",
			"beforeRouteLeave"
		]
	};
	/**
	* @param {(string | string[])[]} order
	*/
	function getOrderMap(order) {
		/** @type {Map<string, number>} */
		const orderMap = /* @__PURE__ */ new Map();
		for (const [i, property] of order.entries()) if (Array.isArray(property)) for (const p of property) orderMap.set(p, i);
		else orderMap.set(property, i);
		return orderMap;
	}
	/**
	* @param {Token} node
	*/
	function isComma(node) {
		return node.type === "Punctuator" && node.value === ",";
	}
	const ARITHMETIC_OPERATORS = [
		"+",
		"-",
		"*",
		"/",
		"%",
		"**"
	];
	const BITWISE_OPERATORS = [
		"&",
		"|",
		"^",
		"~",
		"<<",
		">>",
		">>>"
	];
	const COMPARISON_OPERATORS = [
		"==",
		"!=",
		"===",
		"!==",
		">",
		">=",
		"<",
		"<="
	];
	const RELATIONAL_OPERATORS = ["in", "instanceof"];
	const ALL_BINARY_OPERATORS = /* @__PURE__ */ new Set([
		...ARITHMETIC_OPERATORS,
		...BITWISE_OPERATORS,
		...COMPARISON_OPERATORS,
		...RELATIONAL_OPERATORS
	]);
	const LOGICAL_OPERATORS = /* @__PURE__ */ new Set([
		"&&",
		"||",
		"??"
	]);
	const NO_SIDE_EFFECT_NODE_TYPES = /* @__PURE__ */ new Set([
		"FunctionExpression",
		"Identifier",
		"Literal",
		"ArrowFunctionExpression",
		"TemplateElement",
		"TSAsExpression"
	]);
	/**
	* Result `true` if the node is sure that there are no side effects
	*
	* Currently known side effects types
	*
	* node.type === 'CallExpression'
	* node.type === 'NewExpression'
	* node.type === 'UpdateExpression'
	* node.type === 'AssignmentExpression'
	* node.type === 'TaggedTemplateExpression'
	* node.type === 'UnaryExpression' && node.operator === 'delete'
	*
	* @param  {ASTNode} node target node
	* @param  {VisitorKeys} visitorKeys sourceCode.visitorKey
	* @returns {boolean} no side effects
	*/
	function isNotSideEffectsNode(node, visitorKeys) {
		let isValidOrder = true;
		/** @type {ASTNode | null} */
		let skipNode = null;
		traverseNodes(node, {
			visitorKeys,
			/** @param {ASTNode} node */
			enterNode(node) {
				if (!isValidOrder || skipNode) return;
				if (NO_SIDE_EFFECT_NODE_TYPES.has(node.type)) skipNode = node;
				else if (node.type !== "Property" && node.type !== "ObjectExpression" && node.type !== "ArrayExpression" && (node.type !== "UnaryExpression" || ![
					"!",
					"~",
					"+",
					"-",
					"typeof"
				].includes(node.operator)) && (node.type !== "BinaryExpression" || !ALL_BINARY_OPERATORS.has(node.operator)) && (node.type !== "LogicalExpression" || !LOGICAL_OPERATORS.has(node.operator)) && node.type !== "MemberExpression" && node.type !== "ConditionalExpression" && node.type !== "SpreadElement" && node.type !== "TemplateLiteral" && node.type !== "ChainExpression") isValidOrder = false;
			},
			/** @param {ASTNode} node */
			leaveNode(node) {
				if (skipNode === node) skipNode = null;
			}
		});
		return isValidOrder;
	}
	module.exports = {
		meta: {
			type: "suggestion",
			docs: {
				description: "enforce order of properties in components",
				categories: ["vue3-recommended", "vue2-recommended"],
				url: "https://eslint.vuejs.org/rules/order-in-components.html"
			},
			fixable: "code",
			hasSuggestions: true,
			schema: [{
				type: "object",
				properties: { order: { type: "array" } },
				additionalProperties: false
			}],
			messages: {
				order: "The \"{{name}}\" property should be above the \"{{firstUnorderedPropertyName}}\" property on line {{line}}.",
				reorderWithSideEffects: "Manually move \"{{name}}\" property above \"{{firstUnorderedPropertyName}}\" property on line {{line}} (might break side effects)."
			}
		},
		/** @param {RuleContext} context */
		create(context) {
			const orderMap = getOrderMap(((context.options[0] || {}).order || defaultOrder).map((property) => typeof property === "string" && groups[property] || property));
			const sourceCode = context.sourceCode;
			/**
			* @param {string} name
			*/
			function getOrderPosition(name) {
				return orderMap.get(name) ?? -1;
			}
			/**
			* @param {RuleFixer} fixer
			* @param {Property} propertyNode
			* @param {Property} unorderedPropertyNode
			*/
			function* handleFix(fixer, propertyNode, unorderedPropertyNode) {
				const afterComma = sourceCode.getTokenAfter(propertyNode);
				const hasAfterComma = isComma(afterComma);
				const beforeComma = sourceCode.getTokenBefore(propertyNode);
				const codeStart = beforeComma.range[1];
				const codeEnd = (hasAfterComma ? afterComma : propertyNode).range[1];
				const removeStart = hasAfterComma ? codeStart : beforeComma.range[0];
				yield fixer.removeRange([removeStart, codeEnd]);
				const propertyCode = sourceCode.text.slice(codeStart, codeEnd) + (hasAfterComma ? "" : ",");
				const insertTarget = sourceCode.getTokenBefore(unorderedPropertyNode);
				yield fixer.insertTextAfter(insertTarget, propertyCode);
			}
			/**
			* @param {(Property | SpreadElement)[]} propertiesNodes
			*/
			function checkOrder(propertiesNodes) {
				const properties = propertiesNodes.filter(utils.isProperty).map((property) => ({
					node: property,
					name: utils.getStaticPropertyName(property) || property.key.type === "Identifier" && property.key.name || ""
				}));
				for (const [i, property] of properties.entries()) {
					if (getOrderPosition(property.name) < 0) continue;
					const firstUnorderedProperty = properties.slice(0, i).filter((p) => getOrderPosition(p.name) > getOrderPosition(property.name)).sort((p1, p2) => getOrderPosition(p1.name) > getOrderPosition(p2.name) ? 1 : -1)[0];
					if (firstUnorderedProperty) {
						const line = firstUnorderedProperty.node.loc.start.line;
						const propertyNode = property.node;
						const firstUnorderedPropertyNode = firstUnorderedProperty.node;
						const hasSideEffectsPossibility = propertiesNodes.slice(propertiesNodes.indexOf(firstUnorderedPropertyNode), propertiesNodes.indexOf(propertyNode) + 1).some((property) => !isNotSideEffectsNode(property, sourceCode.visitorKeys));
						context.report({
							node: property.node,
							messageId: "order",
							data: {
								name: property.name,
								firstUnorderedPropertyName: firstUnorderedProperty.name,
								line
							},
							fix: hasSideEffectsPossibility ? void 0 : (fixer) => handleFix(fixer, propertyNode, firstUnorderedPropertyNode),
							suggest: hasSideEffectsPossibility ? [{
								messageId: "reorderWithSideEffects",
								data: {
									name: property.name,
									firstUnorderedPropertyName: firstUnorderedProperty.name,
									line
								},
								fix: (fixer) => handleFix(fixer, propertyNode, firstUnorderedPropertyNode)
							}] : void 0
						});
					}
				}
			}
			return utils.compositingVisitors(utils.executeOnVue(context, (obj) => {
				checkOrder(obj.properties);
			}), utils.defineScriptSetupVisitor(context, { onDefineOptionsEnter(node) {
				if (node.arguments.length === 0) return;
				const define = node.arguments[0];
				if (define.type !== "ObjectExpression") return;
				checkOrder(define.properties);
			} }));
		}
	};
}));
//#endregion
Object.defineProperty(exports, "default", {
	enumerable: true,
	get: function() {
		return require_order_in_components();
	}
});
