UNPKG

eslint-plugin-vue

Version:

Official ESLint plugin for Vue.js

2,640 lines 100 kB
"use strict";
const require_runtime = require("../_virtual/_rolldown/runtime.js");
const require_scope$1 = require("./scope.js");
const require_html_elements$1 = require("./html-elements.js");
const require_svg_elements$1 = require("./svg-elements.js");
const require_math_elements$1 = require("./math-elements.js");
const require_void_elements$1 = require("./void-elements.js");
const require_vue2_builtin_components$1 = require("./vue2-builtin-components.js");
const require_vue3_builtin_components$1 = require("./vue3-builtin-components.js");
const require_vue_builtin_elements$1 = require("./vue-builtin-elements.js");
const require_index = require("./ts-utils/index.js");
//#region lib/utils/index.js
/**
* @author Toru Nagashima <https://github.com/mysticatea>
* @copyright 2017 Toru Nagashima. All rights reserved.
* See LICENSE file in root directory for full license.
*/
var require_utils = /* @__PURE__ */ require_runtime.__commonJSMin(((exports, module) => {
	const { getScope } = require_scope$1.default;
	/**
	* @typedef {import('eslint').Rule.RuleModule} RuleModule
	* @typedef {import('estree').Position} Position
	* @typedef {import('eslint').Rule.CodePath} CodePath
	* @typedef {import('eslint').Rule.CodePathSegment} CodePathSegment
	*/
	/**
	* @typedef {import('../../typings/eslint-plugin-vue/util-types/utils').ComponentArrayProp} ComponentArrayProp
	* @typedef {import('../../typings/eslint-plugin-vue/util-types/utils').ComponentObjectProp} ComponentObjectProp
	* @typedef {import('../../typings/eslint-plugin-vue/util-types/utils').ComponentTypeProp} ComponentTypeProp
	* @typedef {import('../../typings/eslint-plugin-vue/util-types/utils').ComponentInferTypeProp} ComponentInferTypeProp
	* @typedef {import('../../typings/eslint-plugin-vue/util-types/utils').ComponentUnknownProp} ComponentUnknownProp
	* @typedef {import('../../typings/eslint-plugin-vue/util-types/utils').ComponentProp} ComponentProp
	* @typedef {import('../../typings/eslint-plugin-vue/util-types/utils').ComponentArrayEmit} ComponentArrayEmit
	* @typedef {import('../../typings/eslint-plugin-vue/util-types/utils').ComponentObjectEmit} ComponentObjectEmit
	* @typedef {import('../../typings/eslint-plugin-vue/util-types/utils').ComponentTypeEmit} ComponentTypeEmit
	* @typedef {import('../../typings/eslint-plugin-vue/util-types/utils').ComponentInferTypeEmit} ComponentInferTypeEmit
	* @typedef {import('../../typings/eslint-plugin-vue/util-types/utils').ComponentUnknownEmit} ComponentUnknownEmit
	* @typedef {import('../../typings/eslint-plugin-vue/util-types/utils').ComponentEmit} ComponentEmit
	* @typedef {import('../../typings/eslint-plugin-vue/util-types/utils').NameWithLoc} NameWithLoc
	* @typedef {import('../../typings/eslint-plugin-vue/util-types/utils').ComponentTypeSlot} ComponentTypeSlot
	* @typedef {import('../../typings/eslint-plugin-vue/util-types/utils').ComponentInferTypeSlot} ComponentInferTypeSlot
	* @typedef {import('../../typings/eslint-plugin-vue/util-types/utils').ComponentUnknownSlot} ComponentUnknownSlot
	* @typedef {import('../../typings/eslint-plugin-vue/util-types/utils').ComponentSlot} ComponentSlot
	* @typedef {import('../../typings/eslint-plugin-vue/util-types/utils').ComponentModelName} ComponentModelName
	* @typedef {import('../../typings/eslint-plugin-vue/util-types/utils').ComponentModel} ComponentModel
	*/
	/**
	* @typedef { {key: string | null, value: BlockStatement | null} } ComponentComputedProperty
	*/
	/**
	* @typedef { 'props' | 'asyncData' | 'data' | 'computed' | 'setup' | 'watch' | 'methods' | 'provide' | 'inject' | 'expose' } GroupName
	* @typedef { { type: 'array',  name: string, groupName: GroupName, node: Literal | TemplateLiteral } } ComponentArrayPropertyData
	* @typedef { { type: 'object', name: string, groupName: GroupName, node: Identifier | Literal | TemplateLiteral, property: Property } } ComponentObjectPropertyData
	* @typedef { ComponentArrayPropertyData | ComponentObjectPropertyData } ComponentPropertyData
	*/
	/**
	* @typedef {import('../../typings/eslint-plugin-vue/util-types/utils').VueObjectType} VueObjectType
	* @typedef {import('../../typings/eslint-plugin-vue/util-types/utils').VueObjectData} VueObjectData
	* @typedef {import('../../typings/eslint-plugin-vue/util-types/utils').VueVisitor} VueVisitor
	* @typedef {import('../../typings/eslint-plugin-vue/util-types/utils').ScriptSetupVisitor} ScriptSetupVisitor
	*/
	const HTML_ELEMENT_NAMES = new Set(require_html_elements$1.default);
	const SVG_ELEMENT_NAMES = new Set(require_svg_elements$1.default);
	const MATH_ELEMENT_NAMES = new Set(require_math_elements$1.default);
	const VOID_ELEMENT_NAMES = new Set(require_void_elements$1.default);
	const VUE2_BUILTIN_COMPONENT_NAMES = new Set(require_vue2_builtin_components$1.default);
	const VUE3_BUILTIN_COMPONENT_NAMES = new Set(require_vue3_builtin_components$1.default);
	const VUE_BUILTIN_ELEMENT_NAMES = new Set(require_vue_builtin_elements$1.default);
	const BUILTIN_DIRECTIVE_NAMES = /* @__PURE__ */ new Set([
		"bind",
		"on",
		"text",
		"html",
		"show",
		"if",
		"else",
		"else-if",
		"for",
		"model",
		"slot",
		"pre",
		"cloak",
		"once",
		"memo",
		"is"
	]);
	const { createRequire } = require("node:module");
	const path = require("node:path");
	const { traverseNodes, getFallbackKeys, NS } = require("vue-eslint-parser").AST;
	const { findVariable, ReferenceTracker } = require("@eslint-community/eslint-utils");
	const { getComponentPropsFromTypeDefine, getComponentEmitsFromTypeDefine, getComponentSlotsFromTypeDefine, isExhaustiveSwitch, isTypeNode } = require_index.default;
	/**
	* @type { WeakMap<RuleContext, Token[]> }
	*/
	const componentComments = /* @__PURE__ */ new WeakMap();
	/** @type { Map<string, RuleModule> | null } */
	let coreRuleMap = null;
	/** @type { Map<string, RuleModule> } */
	const stylisticRuleMap = /* @__PURE__ */ new Map();
	/**
	* Get the core rule implementation from the rule name
	* @param {string} name
	* @returns {RuleModule | null}
	*/
	function getCoreRule(name) {
		const eslint = require("eslint");
		try {
			coreRuleMap ||= new eslint.Linter().getRules();
			return coreRuleMap.get(name) || null;
		} catch {}
		const { builtinRules } = require("eslint/use-at-your-own-risk");
		return builtinRules.get(name) || null;
	}
	/**
	* Get ESLint Stylistic rule implementation from the rule name
	* @param {string} name
	* @param {'@stylistic/eslint-plugin' | '@stylistic/eslint-plugin-ts' | '@stylistic/eslint-plugin-js'} [preferModule]
	* @returns {RuleModule | null}
	*/
	function getStylisticRule(name, preferModule) {
		if (!preferModule) {
			const cached = stylisticRuleMap.get(name);
			if (cached) return cached;
		}
		const stylisticPluginNames = [
			"@stylistic/eslint-plugin",
			"@stylistic/eslint-plugin-ts",
			"@stylistic/eslint-plugin-js"
		];
		if (preferModule) stylisticPluginNames.unshift(preferModule);
		for (const stylisticPluginName of stylisticPluginNames) try {
			const rule = createRequire(`${process.cwd()}/__placeholder__.js`)(stylisticPluginName)?.rules?.[name];
			if (!preferModule) stylisticRuleMap.set(name, rule);
			return rule;
		} catch {}
		return null;
	}
	/**
	* @template {object} T
	* @param {T} target
	* @param {Partial<T>[]} propsArray
	* @returns {T}
	*/
	function newProxy(target, ...propsArray) {
		return new Proxy({}, {
			get(_object, key) {
				for (const props of propsArray) if (key in props) return props[key];
				return target[key];
			},
			has(_object, key) {
				return key in target;
			},
			ownKeys(_object) {
				return Reflect.ownKeys(target);
			},
			getPrototypeOf(_object) {
				return Reflect.getPrototypeOf(target);
			}
		});
	}
	/**
	* Wrap the rule context object to override methods which access to tokens (such as getTokenAfter).
	* @param {RuleContext} context The rule context object.
	* @param {ParserServices.TokenStore} tokenStore The token store object for template.
	* @param {Object} options The option of this rule.
	* @param {boolean} [options.applyDocument] If `true`, apply check to document fragment.
	* @returns {RuleContext}
	*/
	function wrapContextToOverrideTokenMethods(context, tokenStore, options) {
		const eslintSourceCode = context.sourceCode;
		const rootNode = options.applyDocument ? eslintSourceCode.parserServices.getDocumentFragment && eslintSourceCode.parserServices.getDocumentFragment() : eslintSourceCode.ast.templateBody;
		/** @type {Token[] | null} */
		let tokensAndComments = null;
		function getTokensAndComments() {
			if (tokensAndComments) return tokensAndComments;
			tokensAndComments = rootNode ? tokenStore.getTokens(rootNode, { includeComments: true }) : [];
			return tokensAndComments;
		}
		/** @param {number} index */
		function getNodeByRangeIndex(index) {
			if (!rootNode) return eslintSourceCode.ast;
			/** @type {ASTNode} */
			let result = eslintSourceCode.ast;
			/** @type {ASTNode[]} */
			const skipNodes = [];
			let shouldBreak = false;
			traverseNodes(rootNode, {
				enterNode(node, parent) {
					if (shouldBreak) return;
					if (skipNodes[0] === parent) {
						skipNodes.unshift(node);
						return;
					}
					if (node.range[0] <= index && index < node.range[1]) result = node;
					else skipNodes.unshift(node);
				},
				leaveNode(node) {
					if (shouldBreak) return;
					if (result === node) shouldBreak = true;
					else if (skipNodes[0] === node) skipNodes.shift();
				}
			});
			return result;
		}
		const sourceCode = newProxy(eslintSourceCode, {
			get tokensAndComments() {
				return getTokensAndComments();
			},
			getNodeByRangeIndex,
			getDeclaredVariables
		}, tokenStore);
		/** @type {WeakMap<ASTNode, import('eslint').Scope.ScopeManager>} */
		const containerScopes = /* @__PURE__ */ new WeakMap();
		/**
		* @param {ASTNode} node
		* @returns {import('eslint').Scope.ScopeManager|null}
		*/
		function getContainerScope(node) {
			const exprContainer = getVExpressionContainer(node);
			if (!exprContainer) return null;
			const cache = containerScopes.get(exprContainer);
			if (cache) return cache;
			const programNode = eslintSourceCode.ast;
			const parserOptions = context.languageOptions?.parserOptions ?? context.parserOptions ?? {};
			const ecmaFeatures = parserOptions.ecmaFeatures || {};
			const ecmaVersion = context.languageOptions?.ecmaVersion ?? parserOptions.ecmaVersion ?? 2020;
			const sourceType = programNode.sourceType;
			try {
				const eslintScope = createRequire(require.resolve("eslint"))("eslint-scope");
				const scopeProgram = newProxy(programNode, { body: [newProxy(exprContainer, { type: "ExpressionStatement" })] });
				const scope = eslintScope.analyze(scopeProgram, {
					ignoreEval: true,
					nodejsScope: false,
					impliedStrict: ecmaFeatures.impliedStrict,
					ecmaVersion,
					sourceType,
					fallback: getFallbackKeys
				});
				containerScopes.set(exprContainer, scope);
				return scope;
			} catch {}
			return null;
		}
		return newProxy(context, {
			getSourceCode() {
				return sourceCode;
			},
			get sourceCode() {
				return sourceCode;
			},
			getDeclaredVariables
		});
		/**
		* @param {ESNode} node
		* @returns {Variable[]}
		*/
		function getDeclaredVariables(node) {
			return getContainerScope(node)?.getDeclaredVariables(node) ?? [];
		}
	}
	/**
	* Wrap the rule context object to override report method to skip the dynamic argument.
	* @param {RuleContext} context The rule context object.
	* @returns {RuleContext}
	*/
	function wrapContextToOverrideReportMethodToSkipDynamicArgument(context) {
		const sourceCode = context.sourceCode;
		const templateBody = sourceCode.ast.templateBody;
		if (!templateBody) return context;
		/** @type {Range[]} */
		const directiveKeyRanges = [];
		traverseNodes(templateBody, {
			enterNode(node, parent) {
				if (parent && parent.type === "VDirectiveKey" && node.type === "VExpressionContainer") directiveKeyRanges.push(node.range);
			},
			leaveNode() {}
		});
		return newProxy(context, { report(descriptor, ...args) {
			let range = null;
			if (descriptor.loc) {
				const startLoc = descriptor.loc.start || descriptor.loc;
				const endLoc = descriptor.loc.end || startLoc;
				range = [sourceCode.getIndexFromLoc(startLoc), sourceCode.getIndexFromLoc(endLoc)];
			} else if (descriptor.node) range = descriptor.node.range;
			if (range) {
				for (const directiveKeyRange of directiveKeyRanges) if (range[0] < directiveKeyRange[1] && directiveKeyRange[0] < range[1]) return;
			}
			context.report(descriptor, ...args);
		} });
	}
	/**
	* @callback WrapRuleCreate
	* @param {RuleContext} ruleContext
	* @param {WrapRuleCreateContext} wrapContext
	* @returns {TemplateListener}
	*
	* @typedef {object} WrapRuleCreateContext
	* @property {RuleListener} baseHandlers
	*/
	/**
	* @callback WrapRulePreprocess
	* @param {RuleContext} ruleContext
	* @param {WrapRulePreprocessContext} wrapContext
	* @returns {void}
	*
	* @typedef {object} WrapRulePreprocessContext
	* @property { (override: Partial<RuleContext>) => RuleContext } wrapContextToOverrideProperties Wrap the rule context object to override
	* @property { (visitor: TemplateListener) => void } defineVisitor Define template body visitor
	*/
	/**
	* @typedef {object} WrapRuleOptions
	* @property {string[]} [categories] The categories of this rule.
	* @property {boolean} [skipDynamicArguments] If `true`, skip validation within dynamic arguments.
	* @property {boolean} [skipDynamicArgumentsReport] If `true`, skip report within dynamic arguments.
	* @property {boolean} [applyDocument] If `true`, apply check to document fragment.
	* @property {boolean} [skipBaseHandlers] If `true`, skip base rule handlers.
	* @property {WrapRulePreprocess} [preprocess] Preprocess to calling create of base rule.
	* @property {WrapRuleCreate} [create] If define, extend base rule.
	*/
	/**
	* Wrap a given core rule to apply it to Vue.js template.
	* @param {string} coreRuleName The name of the core rule implementation to wrap.
	* @param {WrapRuleOptions} [options] The option of this rule.
	* @returns {RuleModule} The wrapped rule implementation.
	*/
	function wrapCoreRule(coreRuleName, options) {
		const coreRule = getCoreRule(coreRuleName);
		if (!coreRule) return {
			meta: {
				type: "problem",
				docs: { url: `https://eslint.vuejs.org/rules/${coreRuleName}.html` }
			},
			create(context) {
				return defineTemplateBodyVisitor(context, { "VElement[name='template'][parent.type='VDocumentFragment']"(node) {
					context.report({
						node,
						message: `Failed to extend ESLint core rule "${coreRuleName}". You may be able to use this rule by upgrading the version of ESLint. If you cannot upgrade it, turn off this rule.`
					});
				} });
			}
		};
		const rule = wrapRuleModule(coreRule, coreRuleName, options);
		const meta = {
			...rule.meta,
			docs: {
				...rule.meta.docs,
				extensionSource: {
					url: coreRule.meta.docs.url,
					name: "ESLint core"
				}
			}
		};
		return {
			...rule,
			meta
		};
	}
	/**
	* @typedef {object} RuleNames
	* @property {string} core The name of the core rule implementation to wrap.
	* @property {string} stylistic The name of ESLint Stylistic rule implementation to wrap.
	* @property {string} vue The name of the wrapped rule
	*/
	/**
	* Wrap a core rule or ESLint Stylistic rule to apply it to Vue.js template.
	* @param {RuleNames|string} ruleNames The names of the rule implementation to wrap.
	* @param {WrapRuleOptions} [options] The option of this rule.
	* @returns {RuleModule} The wrapped rule implementation.
	*/
	function wrapStylisticOrCoreRule(ruleNames, options) {
		const stylisticRuleName = typeof ruleNames === "string" ? ruleNames : ruleNames.stylistic;
		const coreRuleName = typeof ruleNames === "string" ? ruleNames : ruleNames.core;
		const vueRuleName = typeof ruleNames === "string" ? ruleNames : ruleNames.vue;
		const stylisticRule = getStylisticRule(stylisticRuleName);
		const baseRule = stylisticRule || getCoreRule(coreRuleName);
		if (!baseRule) return {
			meta: {
				type: "problem",
				docs: { url: `https://eslint.vuejs.org/rules/${vueRuleName}.html` }
			},
			create(context) {
				return defineTemplateBodyVisitor(context, { "VElement[name='template'][parent.type='VDocumentFragment']"(node) {
					context.report({
						node,
						message: `Failed to extend ESLint Stylistic rule "${stylisticRule}". You may be able to use this rule by installing ESLint Stylistic plugin (https://eslint.style/). If you cannot install it, turn off this rule.`
					});
				} });
			}
		};
		const rule = wrapRuleModule(baseRule, vueRuleName, options);
		const jsRule = getStylisticRule(stylisticRuleName, "@stylistic/eslint-plugin-js");
		const description = stylisticRule ? `${jsRule?.meta.docs.description} in \`<template>\`` : rule.meta.docs.description;
		const meta = {
			...rule.meta,
			docs: {
				...rule.meta.docs,
				description,
				extensionSource: {
					url: baseRule.meta.docs.url,
					name: stylisticRule ? "ESLint Stylistic" : "ESLint core"
				}
			},
			deprecated: void 0,
			replacedBy: void 0
		};
		return {
			...rule,
			meta
		};
	}
	/**
	* Wrap a given rule to apply it to Vue.js template.
	* @param {RuleModule} baseRule The rule implementation to wrap.
	* @param {string} ruleName The name of the wrapped rule.
	* @param {WrapRuleOptions} [options] The option of this rule.
	* @returns {RuleModule} The wrapped rule implementation.
	*/
	function wrapRuleModule(baseRule, ruleName, options) {
		let description = baseRule.meta.docs.description;
		if (description) description += " in `<template>`";
		const { categories, skipDynamicArguments, skipDynamicArgumentsReport, skipBaseHandlers, applyDocument, preprocess, create } = options || {};
		return {
			create(context) {
				const sourceCode = context.sourceCode;
				const tokenStore = sourceCode.parserServices.getTemplateBodyTokenStore && sourceCode.parserServices.getTemplateBodyTokenStore();
				if (tokenStore) context = wrapContextToOverrideTokenMethods(context, tokenStore, { applyDocument });
				if (skipDynamicArgumentsReport) context = wrapContextToOverrideReportMethodToSkipDynamicArgument(context);
				/** @type {TemplateListener} */
				const handlers = {};
				if (preprocess) preprocess(context, {
					wrapContextToOverrideProperties(override) {
						context = newProxy(context, override);
						return context;
					},
					defineVisitor(visitor) {
						compositingVisitors(handlers, visitor);
					}
				});
				const baseHandlers = baseRule.create(context);
				if (!skipBaseHandlers) compositingVisitors(handlers, baseHandlers);
				if (handlers.Program) {
					handlers[applyDocument ? "VDocumentFragment" : "VElement[parent.type!='VElement']"] = handlers.Program;
					delete handlers.Program;
				}
				if (handlers["Program:exit"]) {
					handlers[applyDocument ? "VDocumentFragment:exit" : "VElement[parent.type!='VElement']:exit"] = handlers["Program:exit"];
					delete handlers["Program:exit"];
				}
				if (skipDynamicArguments) {
					let isWithinDynamicArguments = false;
					for (const name of Object.keys(handlers)) {
						const original = handlers[name];
						/** @param {any[]} args */
						handlers[name] = (...args) => {
							if (isWithinDynamicArguments) return;
							original(...args);
						};
					}
					handlers["VDirectiveKey > VExpressionContainer"] = () => {
						isWithinDynamicArguments = true;
					};
					handlers["VDirectiveKey > VExpressionContainer:exit"] = () => {
						isWithinDynamicArguments = false;
					};
				}
				if (create) compositingVisitors(handlers, create(context, { baseHandlers }));
				if (applyDocument) return defineDocumentVisitor(context, handlers);
				return defineTemplateBodyVisitor(context, handlers);
			},
			meta: Object.assign({}, baseRule.meta, { docs: Object.assign({}, baseRule.meta.docs, {
				description,
				category: null,
				categories,
				url: `https://eslint.vuejs.org/rules/${ruleName}.html`
			}) })
		};
	}
	module.exports = {
		/**
		* Register the given visitor to parser services.
		* If the parser service of `vue-eslint-parser` was not found,
		* this generates a warning.
		*
		* @param {RuleContext} context The rule context to use parser services.
		* @param {TemplateListener} templateBodyVisitor The visitor to traverse the template body.
		* @param {RuleListener} [scriptVisitor] The visitor to traverse the script.
		* @param { { templateBodyTriggerSelector: "Program" | "Program:exit" } } [options] The options.
		* @returns {RuleListener} The merged visitor.
		*/
		defineTemplateBodyVisitor,
		/**
		* Register the given visitor to parser services.
		* If the parser service of `vue-eslint-parser` was not found,
		* this generates a warning.
		*
		* @param {RuleContext} context The rule context to use parser services.
		* @param {TemplateListener} documentVisitor The visitor to traverse the document.
		* @param { { triggerSelector: "Program" | "Program:exit" } } [options] The options.
		* @returns {RuleListener} The merged visitor.
		*/
		defineDocumentVisitor,
		/**
		* Wrap a given core rule to apply it to Vue.js template.
		* @type {typeof wrapCoreRule}
		*/
		wrapCoreRule,
		wrapStylisticOrCoreRule,
		getCoreRule,
		/**
		* Checks whether the given value is defined.
		* @template T
		* @param {T | null | undefined} v
		* @returns {v is T}
		*/
		isDef,
		/**
		* Flattens arrays, objects and iterable objects.
		* @template T
		* @param {T | Iterable<T> | null | undefined} v
		* @returns {T[]}
		*/
		flatten,
		/**
		* Get the previous sibling element of the given element.
		* @param {VElement} node The element node to get the previous sibling element.
		* @returns {VElement|null} The previous sibling element.
		*/
		prevSibling(node) {
			let prevElement = null;
			const siblings = node.parent && node.parent.children || [];
			for (const siblingNode of siblings) {
				if (siblingNode === node) return prevElement;
				if (siblingNode.type === "VElement") prevElement = siblingNode;
			}
			return null;
		},
		/**
		* Check whether the given directive attribute has their empty value (`=""`).
		* @param {VDirective} node The directive attribute node to check.
		* @param {RuleContext} context The rule context to use parser services.
		* @returns {boolean} `true` if the directive attribute has their empty value (`=""`).
		*/
		isEmptyValueDirective(node, context) {
			if (node.value == null) return false;
			if (node.value.expression != null) return false;
			let valueText = context.sourceCode.getText(node.value);
			if ((valueText[0] === "\"" || valueText[0] === "'") && valueText[0] === valueText.at(-1)) valueText = valueText.slice(1, -1);
			return !valueText;
		},
		/**
		* Check whether the given directive attribute has their empty expression value (e.g. `=" "`, `="/* &ast;/"`).
		* @param {VDirective} node The directive attribute node to check.
		* @param {RuleContext} context The rule context to use parser services.
		* @returns {boolean} `true` if the directive attribute has their empty expression value.
		*/
		isEmptyExpressionValueDirective(node, context) {
			if (node.value == null) return false;
			if (node.value.expression != null) return false;
			const sourceCode = context.sourceCode;
			const valueNode = node.value;
			const tokenStore = sourceCode.parserServices.getTemplateBodyTokenStore();
			let quote1 = null;
			let quote2 = null;
			for (const token of tokenStore.getTokens(node)) {
				if (token.range[1] <= valueNode.range[0]) continue;
				if (valueNode.range[1] <= token.range[0]) return true;
				if (!quote1 && token.type === "Punctuator" && (token.value === "\"" || token.value === "'")) {
					quote1 = token;
					continue;
				}
				if (!quote2 && quote1 && token.type === "Punctuator" && token.value === quote1.value) {
					quote2 = token;
					continue;
				}
				return false;
			}
			return true;
		},
		/**
		* Get the attribute which has the given name.
		* @param {VElement} node The start tag node to check.
		* @param {string} name The attribute name to check.
		* @param {string} [value] The attribute value to check.
		* @returns {VAttribute | null} The found attribute.
		*/
		getAttribute,
		/**
		* Check whether the given start tag has specific directive.
		* @param {VElement} node The start tag node to check.
		* @param {string} name The attribute name to check.
		* @param {string} [value] The attribute value to check.
		* @returns {boolean} `true` if the start tag has the attribute.
		*/
		hasAttribute,
		/**
		* Get the directive list which has the given name.
		* @param {VElement | VStartTag} node The start tag node to check.
		* @param {string} name The directive name to check.
		* @returns {VDirective[]} The array of `v-slot` directives.
		*/
		getDirectives,
		/**
		* Get the directive which has the given name.
		* @param {VElement} node The start tag node to check.
		* @param {string} name The directive name to check.
		* @param {string} [argument] The directive argument to check.
		* @returns {VDirective | null} The found directive.
		*/
		getDirective,
		/**
		* Check whether the given start tag has specific directive.
		* @param {VElement} node The start tag node to check.
		* @param {string} name The directive name to check.
		* @param {string} [argument] The directive argument to check.
		* @returns {boolean} `true` if the start tag has the directive.
		*/
		hasDirective,
		isVBindSameNameShorthand,
		/**
		* Returns the list of all registered components
		* @param {ObjectExpression} componentObject
		* @returns { { node: Property, name: string }[] } Array of ASTNodes
		*/
		getRegisteredComponents(componentObject) {
			const componentsNode = componentObject.properties.find(
				/**
				* @param {ESNode} p
				* @returns {p is (Property & { key: Identifier & {name: 'components'}, value: ObjectExpression })}
				*/
				(p) => p.type === "Property" && getStaticPropertyName(p) === "components" && p.value.type === "ObjectExpression"
			);
			if (!componentsNode) return [];
			return componentsNode.value.properties.filter(isProperty).map((node) => {
				const name = getStaticPropertyName(node);
				return name ? {
					node,
					name
				} : null;
			}).filter(isDef);
		},
		/**
		* Check whether the previous sibling element has `if` or `else-if` directive.
		* @param {VElement} node The element node to check.
		* @returns {boolean} `true` if the previous sibling element has `if` or `else-if` directive.
		*/
		prevElementHasIf(node) {
			const prev = this.prevSibling(node);
			return prev != null && prev.startTag.attributes.some((a) => a.directive && (a.key.name.name === "if" || a.key.name.name === "else-if"));
		},
		/**
		* Returns a generator with all child element v-if chains of the given element.
		* @param {VElement} node The element node to check.
		* @returns {IterableIterator<VElement[]>}
		*/
		*iterateChildElementsChains(node) {
			let isVIf = false;
			/** @type {VElement[]} */
			let elementChain = [];
			for (const childNode of node.children) if (childNode.type === "VElement") {
				let connected;
				if (hasDirective(childNode, "if")) {
					connected = false;
					isVIf = true;
				} else if (hasDirective(childNode, "else-if")) {
					connected = isVIf;
					isVIf = true;
				} else if (hasDirective(childNode, "else")) {
					connected = isVIf;
					isVIf = false;
				} else {
					connected = false;
					isVIf = false;
				}
				if (connected) elementChain.push(childNode);
				else {
					if (elementChain.length > 0) yield elementChain;
					elementChain = [childNode];
				}
			} else if (childNode.type !== "VText" || childNode.value.trim() !== "") isVIf = false;
			if (elementChain.length > 0) yield elementChain;
		},
		isStringLiteral,
		/**
		* Check whether the given node is a custom component or not.
		* @param {VElement} node The start tag node to check.
		* @param {boolean} [shouldIgnoreElementNamespaces=false] If `true`, ignore element namespaces.
		* @returns {boolean} `true` if the node is a custom component.
		*/
		isCustomComponent(node, shouldIgnoreElementNamespaces = false) {
			if (hasAttribute(node, "is") || hasDirective(node, "bind", "is") || hasDirective(node, "is")) return true;
			const isHtmlName = this.isHtmlWellKnownElementName(node.rawName);
			const isSvgName = this.isSvgWellKnownElementName(node.rawName);
			const isMathName = this.isMathWellKnownElementName(node.rawName);
			if (shouldIgnoreElementNamespaces) return !isHtmlName && !isSvgName && !isMathName;
			return this.isHtmlElementNode(node) && !isHtmlName || this.isSvgElementNode(node) && !isSvgName || this.isMathElementNode(node) && !isMathName;
		},
		/**
		* Check whether the given node is a HTML element or not.
		* @param {VElement} node The node to check.
		* @returns {boolean} `true` if the node is a HTML element.
		*/
		isHtmlElementNode(node) {
			return node.namespace === NS.HTML;
		},
		/**
		* Check whether the given node is a SVG element or not.
		* @param {VElement} node The node to check.
		* @returns {boolean} `true` if the name is a SVG element.
		*/
		isSvgElementNode(node) {
			return node.namespace === NS.SVG;
		},
		/**
		* Check whether the given name is a MathML element or not.
		* @param {VElement} node The node to check.
		* @returns {boolean} `true` if the node is a MathML element.
		*/
		isMathElementNode(node) {
			return node.namespace === NS.MathML;
		},
		VUE2_BUILTIN_COMPONENT_NAMES,
		VUE3_BUILTIN_COMPONENT_NAMES,
		/**
		* Check whether the given name is an well-known element or not.
		* @param {string} name The name to check.
		* @returns {boolean} `true` if the name is an well-known element name.
		*/
		isHtmlWellKnownElementName(name) {
			return HTML_ELEMENT_NAMES.has(name);
		},
		/**
		* Check whether the given name is an well-known SVG element or not.
		* @param {string} name The name to check.
		* @returns {boolean} `true` if the name is an well-known SVG element name.
		*/
		isSvgWellKnownElementName(name) {
			return SVG_ELEMENT_NAMES.has(name);
		},
		/**
		* Check whether the given name is a well-known MathML element or not.
		* @param {string} name The name to check.
		* @returns {boolean} `true` if the name is a well-known MathML element name.
		*/
		isMathWellKnownElementName(name) {
			return MATH_ELEMENT_NAMES.has(name);
		},
		/**
		* Check whether the given name is a void element name or not.
		* @param {string} name The name to check.
		* @returns {boolean} `true` if the name is a void element name.
		*/
		isHtmlVoidElementName(name) {
			return VOID_ELEMENT_NAMES.has(name);
		},
		/**
		* Check whether the given name is Vue builtin component name or not.
		* @param {string} name The name to check.
		* @returns {boolean} `true` if the name is a builtin component name
		*/
		isBuiltInComponentName(name) {
			return VUE3_BUILTIN_COMPONENT_NAMES.has(name) || VUE2_BUILTIN_COMPONENT_NAMES.has(name);
		},
		/**
		* Check whether the given name is Vue builtin element name or not.
		* @param {string} name The name to check.
		* @returns {boolean} `true` if the name is a builtin Vue element name
		*/
		isVueBuiltInElementName(name) {
			return VUE_BUILTIN_ELEMENT_NAMES.has(name.toLowerCase());
		},
		/**
		* Check whether the given name is Vue builtin directive name or not.
		* @param {string} name The name to check.
		* @returns {boolean} `true` if the name is a builtin Directive name
		*/
		isBuiltInDirectiveName(name) {
			return BUILTIN_DIRECTIVE_NAMES.has(name);
		},
		/**
		* Gets the property name of a given node.
		* @param {Property|AssignmentProperty|MethodDefinition|MemberExpression} node - The node to get.
		* @return {string|null} The property name if static. Otherwise, null.
		*/
		getStaticPropertyName,
		/**
		* Gets the string of a given node.
		* @param {Literal|TemplateLiteral} node - The node to get.
		* @return {string|null} The string if static. Otherwise, null.
		*/
		getStringLiteralValue,
		/**
		* Gets the name parameter from the given call expression.
		* @param {CallExpression} node - The call expression to get.
		* @returns {NameWithLoc|null} The name and location if static.
		*/
		getNameParamNode,
		/**
		* Get all props by looking at all component's properties
		* @param {ObjectExpression} componentObject Object with component definition
		* @return {(ComponentArrayProp | ComponentObjectProp | ComponentUnknownProp)[]} Array of component props
		*/
		getComponentPropsFromOptions,
		/**
		* Get all emits by looking at all component's properties
		* @param {ObjectExpression} componentObject Object with component definition
		* @return {(ComponentArrayEmit | ComponentObjectEmit | ComponentUnknownEmit)[]} Array of component emits
		*/
		getComponentEmitsFromOptions,
		/**
		* Get all computed properties by looking at all component's properties
		* @param {ObjectExpression} componentObject Object with component definition
		* @return {ComponentComputedProperty[]} Array of computed properties in format: [{key: String, value: ASTNode}]
		*/
		getComputedProperties(componentObject) {
			const computedPropertiesNode = componentObject.properties.find(
				/**
				* @param {ESNode} p
				* @returns {p is (Property & { key: Identifier & {name: 'computed'}, value: ObjectExpression })}
				*/
				(p) => p.type === "Property" && getStaticPropertyName(p) === "computed" && p.value.type === "ObjectExpression"
			);
			if (!computedPropertiesNode) return [];
			return computedPropertiesNode.value.properties.filter(isProperty).map((cp) => {
				const key = getStaticPropertyName(cp);
				/** @type {Expression} */
				const propValue = skipTSAsExpression(cp.value);
				/** @type {BlockStatement | null} */
				let value = null;
				if (propValue.type === "FunctionExpression") value = propValue.body;
				else if (propValue.type === "ObjectExpression") {
					const get = findProperty(propValue, "get", (p) => p.value.type === "FunctionExpression");
					value = get ? get.value.body : null;
				}
				return {
					key,
					value
				};
			});
		},
		/**
		* Get getter body from computed function
		* @param {CallExpression} callExpression call of computed function
		* @return {FunctionExpression | ArrowFunctionExpression | null} getter function
		*/
		getGetterBodyFromComputedFunction(callExpression) {
			if (callExpression.arguments.length === 0) return null;
			const arg = callExpression.arguments[0];
			if (arg.type === "FunctionExpression" || arg.type === "ArrowFunctionExpression") return arg;
			if (arg.type === "ObjectExpression") {
				const getProperty = findProperty(arg, "get", (p) => p.value.type === "FunctionExpression" || p.value.type === "ArrowFunctionExpression");
				return getProperty ? getProperty.value : null;
			}
			return null;
		},
		isTypeScriptFile,
		isVueFile,
		/**
		* Checks whether the current file is uses `<script setup>`
		* @param {RuleContext} context The ESLint rule context object.
		*/
		isScriptSetup,
		/**
		* Gets the element of `<script setup>`
		* @param {RuleContext} context The ESLint rule context object.
		* @returns {VElement | null} the element of `<script setup>`
		*/
		getScriptSetupElement,
		/**
		* Check if current file is a Vue instance or component and call callback
		* @param {RuleContext} context The ESLint rule context object.
		* @param { (node: ObjectExpression, type: VueObjectType) => void } cb Callback function
		*/
		executeOnVue(context, cb) {
			return compositingVisitors(this.executeOnVueComponent(context, cb), this.executeOnVueInstance(context, cb));
		},
		/**
		* Define handlers to traverse the Vue Objects.
		* Some special events are available to visitor.
		*
		* - `onVueObjectEnter` ... Event when Vue Object is found.
		* - `onVueObjectExit` ... Event when Vue Object visit ends.
		* - `onSetupFunctionEnter` ... Event when setup function found.
		* - `onRenderFunctionEnter` ... Event when render function found.
		*
		* @param {RuleContext} context The ESLint rule context object.
		* @param {VueVisitor} visitor The visitor to traverse the Vue Objects.
		*/
		defineVueVisitor(context, visitor) {
			/** @type {VueObjectData | null} */
			let vueStack = null;
			/**
			* @param {string} key
			* @param {ESNode} node
			*/
			function callVisitor(key, node) {
				if (visitor[key] && vueStack) visitor[key](node, vueStack);
			}
			/** @type {NodeListener} */
			const vueVisitor = {};
			for (const key in visitor) vueVisitor[key] = (node) => callVisitor(key, node);
			/**
			* @param {ObjectExpression} node
			*/
			vueVisitor.ObjectExpression = (node) => {
				const type = getVueObjectType(context, node);
				if (type) {
					vueStack = {
						node,
						type,
						parent: vueStack,
						get functional() {
							const functional = node.properties.find(
								/**
								* @param {Property | SpreadElement} p
								* @returns {p is Property}
								*/
								(p) => p.type === "Property" && getStaticPropertyName(p) === "functional"
							);
							if (!functional) return false;
							return functional.value.type !== "Literal" || functional.value.value !== false;
						}
					};
					callVisitor("onVueObjectEnter", node);
				}
				callVisitor("ObjectExpression", node);
			};
			vueVisitor["ObjectExpression:exit"] = (node) => {
				callVisitor("ObjectExpression:exit", node);
				if (vueStack && vueStack.node === node) {
					callVisitor("onVueObjectExit", node);
					vueStack = vueStack.parent;
				}
			};
			if (visitor.onSetupFunctionEnter || visitor.onSetupFunctionExit || visitor.onRenderFunctionEnter) {
				const setups = /* @__PURE__ */ new Set();
				/** @param { (FunctionExpression | ArrowFunctionExpression) & { parent: Property } } node */
				vueVisitor["Property[value.type=/^(Arrow)?FunctionExpression$/] > :function"] = (node) => {
					/** @type {Property} */
					const prop = node.parent;
					if (vueStack && prop.parent === vueStack.node && prop.value === node) {
						const name = getStaticPropertyName(prop);
						if (name === "setup") {
							callVisitor("onSetupFunctionEnter", node);
							setups.add(node);
						} else if (name === "render") callVisitor("onRenderFunctionEnter", node);
					}
					callVisitor("Property[value.type=/^(Arrow)?FunctionExpression$/] > :function", node);
				};
				if (visitor.onSetupFunctionExit)
 /** @param { (FunctionExpression | ArrowFunctionExpression) & { parent: Property } } node */
				vueVisitor["Property[value.type=/^(Arrow)?FunctionExpression$/] > :function:exit"] = (node) => {
					if (!setups.has(node)) return;
					callVisitor("onSetupFunctionExit", node);
					setups.delete(node);
				};
			}
			return vueVisitor;
		},
		/**
		* Define handlers to traverse the AST nodes in `<script setup>`.
		* Some special events are available to visitor.
		*
		* - `onDefinePropsEnter` ... Event when defineProps is found.
		* - `onDefinePropsExit` ... Event when defineProps visit ends.
		* - `onDefineEmitsEnter` ... Event when defineEmits is found.
		* - `onDefineEmitsExit` ... Event when defineEmits visit ends.
		* - `onDefineOptionsEnter` ... Event when defineOptions is found.
		* - `onDefineOptionsExit` ... Event when defineOptions visit ends.
		* - `onDefineSlotsEnter` ... Event when defineSlots is found.
		* - `onDefineSlotsExit` ... Event when defineSlots visit ends.
		* - `onDefineExposeEnter` ... Event when defineExpose is found.
		* - `onDefineExposeExit` ... Event when defineExpose visit ends.
		* - `onDefineModelEnter` ... Event when defineModel is found.
		* - `onDefineModelExit` ... Event when defineModel visit ends.
		*
		* @param {RuleContext} context The ESLint rule context object.
		* @param {ScriptSetupVisitor} visitor The visitor to traverse the AST nodes.
		*/
		defineScriptSetupVisitor(context, visitor) {
			const scriptSetup = getScriptSetupElement(context);
			if (scriptSetup == null) return {};
			const scriptSetupRange = scriptSetup.range;
			/**
			* @param {ESNode} node
			*/
			function isInScriptSetup(node) {
				return scriptSetupRange[0] <= node.range[0] && node.range[1] <= scriptSetupRange[1];
			}
			/**
			* @param {string} key
			* @param {ESNode} node
			* @param {any[]} args
			*/
			function callVisitor(key, node, ...args) {
				if (visitor[key] && (node.type === "Program" || isInScriptSetup(node))) visitor[key](node, ...args);
			}
			/** @type {NodeListener} */
			const scriptSetupVisitor = {};
			for (const key in visitor) scriptSetupVisitor[key] = (node) => callVisitor(key, node);
			class MacroListener {
				/**
				* @param {string} name
				* @param {string} enterName
				* @param {string} exitName
				* @param {(candidateMacro: Expression | null, node: CallExpression) => boolean} isMacroNode
				* @param {(context: RuleContext, node: CallExpression) => unknown} buildParam
				*/
				constructor(name, enterName, exitName, isMacroNode, buildParam) {
					this.name = name;
					this.enterName = enterName;
					this.exitName = exitName;
					this.isMacroNode = isMacroNode;
					this.buildParam = buildParam;
					this.hasListener = Boolean(visitor[this.enterName] || visitor[this.exitName]);
					this.paramsMap = /* @__PURE__ */ new Map();
				}
			}
			const macroListenerList = [
				new MacroListener("defineProps", "onDefinePropsEnter", "onDefinePropsExit", (candidateMacro, node) => candidateMacro === node || candidateMacro === getWithDefaults(node), getComponentPropsFromDefineProps),
				new MacroListener("defineEmits", "onDefineEmitsEnter", "onDefineEmitsExit", (candidateMacro, node) => candidateMacro === node, getComponentEmitsFromDefineEmits),
				new MacroListener("defineOptions", "onDefineOptionsEnter", "onDefineOptionsExit", (candidateMacro, node) => candidateMacro === node, () => void 0),
				new MacroListener("defineSlots", "onDefineSlotsEnter", "onDefineSlotsExit", (candidateMacro, node) => candidateMacro === node, getComponentSlotsFromDefineSlots),
				new MacroListener("defineExpose", "onDefineExposeEnter", "onDefineExposeExit", (candidateMacro, node) => candidateMacro === node, () => void 0),
				new MacroListener("defineModel", "onDefineModelEnter", "onDefineModelExit", (candidateMacro, node) => candidateMacro === node, getComponentModelFromDefineModel)
			].filter((m) => m.hasListener);
			if (macroListenerList.length > 0) {
				/** @type {Expression | null} */
				let candidateMacro = null;
				/** @param {VariableDeclarator|ExpressionStatement} node */
				scriptSetupVisitor["Program > VariableDeclaration > VariableDeclarator, Program > ExpressionStatement"] = (node) => {
					if (!candidateMacro) candidateMacro = node.type === "VariableDeclarator" ? node.init : node.expression;
				};
				/** @param {VariableDeclarator|ExpressionStatement} node */
				scriptSetupVisitor["Program > VariableDeclaration > VariableDeclarator, Program > ExpressionStatement:exit"] = (node) => {
					if (candidateMacro === (node.type === "VariableDeclarator" ? node.init : node.expression)) candidateMacro = null;
				};
				/**
				* @param {CallExpression} node
				*/
				scriptSetupVisitor.CallExpression = (node) => {
					if (candidateMacro && isInScriptSetup(node) && node.callee.type === "Identifier") for (const macroListener of macroListenerList) {
						if (node.callee.name !== macroListener.name || !macroListener.isMacroNode(candidateMacro, node)) continue;
						const param = macroListener.buildParam(context, node);
						callVisitor(macroListener.enterName, node, param);
						macroListener.paramsMap.set(node, param);
						break;
					}
					callVisitor("CallExpression", node);
				};
				scriptSetupVisitor["CallExpression:exit"] = (node) => {
					callVisitor("CallExpression:exit", node);
					for (const macroListener of macroListenerList) {
						if (!macroListener.paramsMap.has(node)) continue;
						callVisitor(macroListener.exitName, node, macroListener.paramsMap.get(node));
						macroListener.paramsMap.delete(node);
					}
				};
			}
			return scriptSetupVisitor;
		},
		/**
		* Checks whether given defineProps call node has withDefaults.
		* @param {CallExpression} node The node of defineProps
		* @returns {node is CallExpression & { parent: CallExpression }}
		*/
		hasWithDefaults,
		/**
		* Gets a map of the expressions defined in withDefaults.
		* @param {CallExpression} node The node of defineProps
		* @returns { { [key: string]: Expression | undefined } }
		*/
		getWithDefaultsPropExpressions(node) {
			const map = getWithDefaultsProps(node);
			/** @type {Record<string, Expression | undefined>} */
			const result = {};
			for (const [key, prop] of Object.entries(map)) result[key] = prop && prop.value;
			return result;
		},
		/**
		* Gets a map of the property nodes defined in withDefaults.
		* @param {CallExpression} node The node of defineProps
		* @returns { { [key: string]: Property | undefined } }
		*/
		getWithDefaultsProps,
		/**
		* Gets the default definition nodes for defineProp
		* using the props destructure with assignment pattern.
		* @param {CallExpression} node The node of defineProps
		* @returns { Record<string, {prop: AssignmentProperty , expression: Expression} | undefined> }
		*/
		getDefaultPropExpressionsForPropsDestructure,
		getLeftOfDefineProps,
		/**
		* Checks whether the given defineProps node is using Props Destructure.
		* @param {CallExpression} node The node of defineProps
		* @returns {boolean}
		*/
		isUsingPropsDestructure(node) {
			return getLeftOfDefineProps(node)?.type === "ObjectPattern";
		},
		/**
		* Gets the props destructure property nodes for defineProp.
		* @param {CallExpression} node The node of defineProps
		* @returns { Record<string, AssignmentProperty | undefined> }
		*/
		getPropsDestructure,
		getVueObjectType,
		getVueComponentDefinitionType,
		/**
		* Checks whether the given object is an SFC definition.
		* @param {RuleContext} context The ESLint rule context object.
		* @param {ObjectExpression} node Node to check
		* @returns { boolean } `true`, the given object is an SFC definition.
		*/
		isSFCObject,
		compositingVisitors,
		/**
		* Check if current file is a Vue instance (new Vue) and call callback
		* @param {RuleContext} context The ESLint rule context object.
		* @param { (node: ObjectExpression, type: VueObjectType) => void } cb Callback function
		*/
		executeOnVueInstance(context, cb) {
			return { 
			/** @param {ObjectExpression} node */
"ObjectExpression:exit"(node) {
				const type = getVueObjectType(context, node);
				if (!type || type !== "instance") return;
				cb(node, type);
			} };
		},
		/**
		* Check if current file is a Vue component and call callback
		* @param {RuleContext} context The ESLint rule context object.
		* @param { (node: ObjectExpression, type: VueObjectType) => void } cb Callback function
		*/
		executeOnVueComponent(context, cb) {
			return { 
			/** @param {ObjectExpression} node */
"ObjectExpression:exit"(node) {
				const type = getVueObjectType(context, node);
				if (!type || type !== "mark" && type !== "export" && type !== "definition") return;
				cb(node, type);
			} };
		},
		/**
		* Check call `Vue.component` and call callback.
		* @param {RuleContext} _context The ESLint rule context object.
		* @param { (node: CallExpression) => void } cb Callback function
		*/
		executeOnCallVueComponent(_context, cb) {
			return { 
			/** @param {Identifier & { parent: MemberExpression & { parent: CallExpression } } } node */
"CallExpression > MemberExpression > Identifier[name='component']": (node) => {
				const callExpr = node.parent.parent;
				const callee = callExpr.callee;
				if (callee.type === "MemberExpression") {
					if (skipTSAsExpression(callee.object).type === "Identifier" && callee.property === node && callExpr.arguments.length > 0) cb(callExpr);
				}
			} };
		},
		/**
		* Return generator with all properties
		* @param {ObjectExpression} node Node to check
		* @param {Set<GroupName>} groups Name of parent group
		* @returns {IterableIterator<ComponentPropertyData>}
		*/
		*iterateProperties(node, groups) {
			for (const item of node.properties) {
				if (item.type !== "Property") continue;
				const name = getStaticPropertyName(item);
				if (!name || !groups.has(name)) continue;
				yield* this.iteratePropertyValue(item.value, name);
			}
		},
		/**
		* Return generator with all properties defined by the given property value.
		* @param {Expression} value Property value node to check
		* @param {GroupName} groupName Name of parent group
		* @returns {IterableIterator<ComponentPropertyData>}
		*/
		*iteratePropertyValue(value, groupName) {
			switch (value.type) {
				case "ArrayExpression":
					yield* this.iterateArrayExpression(value, groupName);
					break;
				case "ObjectExpression":
					yield* this.iterateObjectExpression(value, groupName);
					break;
				case "FunctionExpression":
					yield* this.iterateFunctionExpression(value, groupName);
					break;
				case "ArrowFunctionExpression": yield* this.iterateArrowFunctionExpression(value, groupName);
			}
		},
		/**
		* Return generator with all elements inside ArrayExpression
		* @param {ArrayExpression} node Node to check
		* @param {GroupName} groupName Name of parent group
		* @returns {IterableIterator<ComponentArrayPropertyData>}
		*/
		*iterateArrayExpression(node, groupName) {
			for (const item of node.elements) {
				if (!item || item.type !== "Literal" && item.type !== "TemplateLiteral") continue;
				const name = getStringLiteralValue(item);
				if (name) yield {
					type: "array",
					name,
					groupName,
					node: item
				};
			}
		},
		/**
		* Return generator with all elements inside ObjectExpression
		* @param {ObjectExpression} node Node to check
		* @param {GroupName} groupName Name of parent group
		* @returns {IterableIterator<ComponentObjectPropertyData>}
		*/
		*iterateObjectExpression(node, groupName) {
			/** @type {Set<Property> | undefined} */
			let usedGetter;
			for (const item of node.properties) {
				if (item.type !== "Property") continue;
				const key = item.key;
				if (key.type === "Identifier" || key.type === "Literal" || key.type === "TemplateLiteral") {
					const name = getStaticPropertyName(item);
					if (name) {
						if (item.kind === "set" && node.properties.some((item2) => {
							if (item2.type === "Property" && item2.kind === "get") {
								if (!usedGetter) usedGetter = /* @__PURE__ */ new Set();
								if (usedGetter.has(item2)) return false;
								if (getStaticPropertyName(item2) === name) {
									usedGetter.add(item2);
									return true;
								}
							}
							return false;
						})) continue;
						yield {
							type: "object",
							name,
							groupName,
							node: key,
							property: item
						};
					}
				}
			}
		},
		/**
		* Return generator with all elements inside FunctionExpression
		* @param {FunctionExpression} node Node to check
		* @param {GroupName} groupName Name of parent group
		* @returns {IterableIterator<ComponentObjectPropertyData>}
		*/
		*iterateFunctionExpression(node, groupName) {
			if (node.body.type === "BlockStatement") {
				for (const item of node.body.body) if (item.type === "ReturnStatement" && item.argument && item.argument.type === "ObjectExpression") yield* this.iterateObjectExpression(item.argument, groupName);
			}
		},
		/**
		* Return generator with all elements inside ArrowFunctionExpression
		* @param {ArrowFunctionExpression} node Node to check
		* @param {GroupName} groupName Name of parent group
		* @returns {IterableIterator<ComponentObjectPropertyData>}
		*/
		*iterateArrowFunctionExpression(node, groupName) {
			const body = node.body;
			if (body.type === "BlockStatement") {
				for (const item of body.body) if (item.type === "ReturnStatement" && item.argument && item.argument.type === "ObjectExpression") yield* this.iterateObjectExpression(item.argument, groupName);
			} else if (body.type === "ObjectExpression") yield* this.iterateObjectExpression(body, groupName);
		},
		/**
		* Find all functions which do not always return values
		* @param {RuleContext} context The ESLint rule context object.
		* @param {boolean} treatUndefinedAsUnspecified
		* @param { (node: ArrowFunctionExpression | FunctionExpression | FunctionDeclaration) => void } cb Callback function
		* @returns {RuleListener}
		*/
		executeOnFunctionsWithoutReturn(context, treatUndefinedAsUnspecified, cb) {
			/**
			* @typedef {object} FuncInfo
			* @property {FuncInfo | null} funcInfo
			* @property {CodePath} codePath
			* @property {boolean} hasReturn
			* @property {boolean} hasReturnValue
			* @property {ArrowFunctionExpression | FunctionExpression | FunctionDeclaration} node
			* @property {CodePathSegment[]} currentSegments
			*/
			/** @type {FuncInfo | null} */
			let funcInfo = null;
			/** @type {WeakSet<CodePathSegment>} */
			const spuriousSegments = /* @__PURE__ */ new WeakSet();
			/** @type {WeakSet<CodePathSegment>} */
			const caseBodySegments = /* @__PURE__ */ new WeakSet();
			let caseBodyDepth = 0;
			/**
			* Treat spurious segments the same as unreachable.
			* @param {CodePathSegment} segment
			*/
			function isEffectivelyUnreachable(segment) {
				return !segment.reachable || spuriousSegments.has(segment);
			}
			function isValidReturn() {
				if (!funcInfo) return true;
				if (funcInfo.currentSegments.some((segment) => !isEffectivelyUnreachable(segment))) return false;
				return !treatUndefinedAsUnspecified || funcInfo.hasReturnValue;
			}
			return {
				/**
				* @param {CodePath} codePath
				* @param {ESNode} node
				*/
				onCodePathStart(codePath, node) {
					if (node.type === "ArrowFunctionExpression" || node.type === "FunctionExpression" || node.type === "FunctionDeclaration") funcInfo = {
						codePath,
						currentSegments: [],
						funcInfo,
						hasReturn: false,
						hasReturnValue: false,
						node
					};
				},
				/** @param {CodePathSegment} segment */
				onCodePathSegmentStart(segment) {
					funcInfo?.currentSegments.push(segment);
					if (segment.prevSegments.length > 0 && segment.prevSegments.every(isEffectivelyUnreachable)) spuriousSegments.add(segment);
					if (caseBodyDepth > 0) caseBodySegments.add(segment);
				},
				onCodePathSegmentEnd() {
					funcInfo?.currentSegments.pop();
				},
				onCodePathEnd() {
					funcInfo &&= funcInfo.funcInfo;
				},
				/** @param {ReturnStatement} node */
				ReturnStatement(node) {
					if (!funcInfo) return;
					funcInfo.hasReturn = true;
					funcInfo.hasReturnValue = Boolean(node.argument);
				},
				SwitchCase() {
					caseBodyDepth++;
				},
				"SwitchCase:exit"() {
					caseBodyDepth--;
				},
				/** @param {SwitchStatement} node */
				"SwitchStatement:exit"(node) {
					if (!funcInfo) return;
					if (node.cases.some((switchCase) => switchCase.test === null)) return;
					if (!isExhaustiveSwitch(context, node)) return;
					if (funcInfo.currentSegments.some((post) => post.prevSegments.some((prev) => !isEffectivelyUnreachable(prev) && caseBodySegments.has(prev)))) return;
					for (const segment of funcInfo.currentSegments) spuriousSegments.add(segment);
				},
				/** @param {ArrowFunctionExpression} node */
				"ArrowFunctionExpression:exit"(node) {
					if (funcInfo && !isValidReturn() && !node.expression) cb(funcInfo.node);
				},
				"FunctionExpression:exit"() {
					if (funcInfo && !isValidReturn()) cb(funcInfo.node);
				}
			};
		},
		/**
		* Check whether the component is declared in a single line or not.
		* @param {ASTNode} node
		* @returns {boolean}
		*/
		isSingleLine(node) {
			return node.loc.start.line === node.loc.end.line;
		},
		/**
		* Check whether the templateBody of the program has invalid EOF or not.
		* @param {Program} node The program node to check.
		* @returns {boolean} `true` if it has invalid EOF.
		*/
		hasInvalidEOF(node) {
			const body = node.templateBody;
			if (body == null || body.errors == null) return false;
			return body.errors.some((error) => typeof error.code === "string" && error.code.startsWith("eof-"));
		},
		/**
		* Get the chaining nodes of MemberExpression.
		*
		* @param  {ESNode} node The node to parse
		* @return {[ESNode, ...MemberExpression[]]} The chaining nodes
		*/
		getMemberChaining(node) {
			/** @type {MemberExpression[]} */
			const nodes = [];
			let n = skipChainExpression(node);
			while (n.type === "MemberExpression") {
				nodes.push(n);
				n = skipChainExpression(n.object);
			}
			return [n, ...nodes.reverse()];
		},
		/**
		* return two string editdistance
		* @param {string} a string a to compare
		* @param {string} b string b to compare
		* @returns {number}
		*/
		editDistance(a, b) {
			if (a === b) return 0;
			const alen = a.length;
			const blen = b.length;
			const dp = Array.from({ length: alen + 1 }, () => Array.from({ length: blen + 1 }, () => 0));
			for (let i = 0; i <= alen; i++) dp[i][0] = i;
			for (let j = 0; j <= blen; j++) dp[0][j] = j;
			for (let i = 1; i <= alen; i++) for (let j = 1; j <= blen; j++) dp[i][j] = a[i - 1] === b[j - 1] ? dp[i - 1][j - 1] : Math.min(dp[i - 1][j], dp[i][j - 1], dp[i - 1][j - 1]) + 1;
			return dp[alen][blen];
		},
		/**
		* Checks whether the target node is within the given range.
		* @param { [number, number] | ASTNode | Token } rangeOrNode
		* @param {ASTNode | Token} target
		*/
		inRange(rangeOrNode, target) {
			const range = Array.isArray(rangeOrNode) ? rangeOrNode : rangeOrNode.range;
			return range[0] <= target.range[0] && target.range[1] <= range[1];
		},
		/**
		* Checks whether the given node is Property.
		*/
		isProperty,
		/**
		* Checks whether the given node is AssignmentProperty.
		*/
		isAssignmentProperty,
		/**
		* Checks whether the given node is VElement.
		*/
		isVElement,
		/**
		* Finds the property with the given name from the given ObjectExpression node.
		*/
		findProperty,
		/**
		* Finds the assignment property with the given name from the given ObjectPattern node.
		*/
		findAssignmentProperty,
		/**
		* Checks if the given node is a property value.
		* @param {Property} prop
		* @param {Expression} node
		*/
		isPropertyChain,
		/**
		* Retrieve `TSAsExpression#expression` value if the given node a `TSAsExpression` node. Otherwise, pass through it.
		*/
		skipTSAsExpression,
		/**
		* Retrieve `AssignmentPattern#left` value if the given node a `AssignmentPattern` node. Otherwise, pass through it.
		*/
		skipDefaultParamValue,
		/**
		* Retrieve `ChainExpression#expression` value if the given node a `ChainExpression` node. Otherwise, pass through it.
		*/
		skipChainExpression,
		/**
		* Checks whether the given node is in a type annotation.
		*/
		withinTypeNode,
		findVariableByIdentifier,
		getScope,
		/**
		* Checks whether the given node is in export default.
		* @param {ASTNode} node
		* @returns {boolean}
		*/
		isInExportDefault,
		/**
		* Check whether the given node is `this` or variable that stores `this`.
		* @param  {ESNode} node The node to check
		* @param {RuleContext} context The rule context to use parser services.
		* @returns {boolean} `true` if the given node is `this`.
		*/
		isThis(node, context) {
			if (node.type === "ThisExpression") return true;
			if (node.type !== "Identifier") return false;
			const parent = node.parent;
			if (parent.type === "MemberExpression" && parent.property === node || parent.type === "Property" && parent.key === node && !parent.computed) return false;
			const variable = findVariable(getScope(context, node), node);
			if (variable != null && variable.defs.length === 1) {
				const def = variable.defs[0];
				if (def.type === "Variable" && def.parent.kind === "const" && def.node.id.type === "Identifier") return Boolean(def.node && def.node.init && def.node.init.type === "ThisExpression");
			}
			return false;
		},
		/**
		* Check if a call expression is Object.assign with the given node as first argument
		* @param {CallExpression} callExpr
		* @param {ASTNode} targetNode
		* @returns {boolean}
		*/
		isObjectAssignCall(callExpr, targetNode) {
			const { callee, arguments: args } = callExpr;
			return args.length > 0 && args[0] === targetNode && callee?.type === "MemberExpression" && callee.object?.type === "Identifier" && callee.object.name === "Object" && callee.property?.type === "Identifier" && callee.property.name === "assign";
		},
		/**
		* @param {MemberExpression|Identifier} props
		* @returns { { kind: 'assignment' | 'update' | 'call' , node: ESNode, pathNodes: MemberExpression[] } | null }
		*/
		findMutating(props) {
			/** @type {MemberExpression[]} */
			const pathNodes = [];
			/** @type {MemberExpression | Identifier | ChainExpression} */
			let node = props;
			let target = node.parent;
			while (true) {
				const step = this.findMutatingStep(node, target, pathNodes);
				if (step.done) return step.result;
				node = step.node;
				target = step.target;
			}
		},
		/**
		* Resolve a single step of the parent chain walk in `findMutating`.
		* @param {MemberExpression | Identifier | ChainExpression} node
		* @param {ASTNode} target
		* @param {MemberExpression[]} pathNodes
		* @returns {{ done: true, result: { kind: 'assignment' | 'update' | 'call', node: ESNode, pathNodes: MemberExpression[] } | null } | { done: false, node: MemberExpression | ChainExpression, target: ASTNode }}
		*/
		findMutatingStep(node, target, pathNodes) {
			switch (target.type) {
				case "AssignmentExpression":
					if (target.left === node) return {
						done: true,
						result: {
							kind: "assignment",
							node: target,
							pathNodes
						}
					};
					return {
						done: true,
						result: null
					};
				case "UpdateExpression": return {
					done: true,
					result: {
						kind: "update",
						node: target,
						pathNodes
					}
				};
				case "UnaryExpression":
					if (target.operator === "delete") return {
						done: true,
						result: {
							kind: "update",
							node: target,
							pathNodes
						}
					};
					return {
						done: true,
						result: null
					};
				case "CallExpression": {
					const mem = pathNodes.at(-1);
					if (mem && target.callee === node) {
						const callName = getStaticPropertyName(mem);
						if (callName && /^(?:push|pop|shift|unshift|reverse|splice|sort|copyWithin|fill)$/u.test(callName)) {
							pathNodes.pop();
							return {
								done: true,
								result: {
									kind: "call",
									node: target,
									pathNodes
								}
							};
						}
					}
					if (this.isObjectAssignCall(target, node)) return {
						done: true,
						result: {
							kind: "call",
							node: target,
							pathNodes
						}
					};
					return {
						done: true,
						result: null
					};
				}
				case "MemberExpression":
					if (target.object === node) {
						pathNodes.push(target);
						return {
							done: false,
							node: target,
							target: target.parent
						};
					}
					return {
						done: true,
						result: null
					};
				case "ChainExpression": return {
					done: false,
					node: target,
					target: target.parent
				};
				default: return {
					done: true,
					result: null
				};
			}
		},
		/**
		* Return generator with the all handler nodes defined in the given watcher property.
		* @param {Property|Expression} property
		* @returns {IterableIterator<Expression>}
		*/
		iterateWatchHandlerValues,
		/**
		* Wraps composition API trace map in 'vue', '@vue/composition-api' and '@nuxtjs/composition-api' imports, or '#imports' from unimport
		* @param {import('@eslint-community/eslint-utils').TYPES.TraceMap} map
		*/
		createCompositionApiTraceMap,
		/**
		* Iterates all references in the given trace map.
		* Take the third argument option to detect auto-imported references.
		*
		* @param {import('@eslint-community/eslint-utils').ReferenceTracker} tracker
		* @param {import('@eslint-community/eslint-utils').TYPES.TraceMap} map
		* @returns {ReturnType<import('@eslint-community/eslint-utils').ReferenceTracker['iterateEsmReferences']>}
		*/
		*iterateReferencesTraceMap(tracker, map) {
			const esmTraceMap = this.createCompositionApiTraceMap({
				...map,
				[ReferenceTracker.ESM]: true
			});
			for (const ref of tracker.iterateEsmReferences(esmTraceMap)) yield ref;
			for (const ref of tracker.iterateGlobalReferences(map)) yield ref;
		},
		/**
		* Checks whether or not the tokens of two given nodes are same.
		* @param {ASTNode} left A node 1 to compare.
		* @param {ASTNode} right A node 2 to compare.
		* @param {ParserServices.TokenStore | SourceCode} sourceCode The ESLint source code object.
		* @returns {boolean} the source code for the given node.
		*/
		equalTokens(left, right, sourceCode) {
			const tokensL = sourceCode.getTokens(left);
			const tokensR = sourceCode.getTokens(right);
			if (tokensL.length !== tokensR.length) return false;
			return tokensL.every((token, i) => token.type === tokensR[i].type && token.value === tokensR[i].value);
		}
	};
	/**
	* Checks whether the given value is defined.
	* @template T
	* @param {T | null | undefined} v
	* @returns {v is T}
	*/
	function isDef(v) {
		return v != null;
	}
	/**
	* Flattens arrays, objects and iterable objects.
	* @template T
	* @param {T | Iterable<T> | null | undefined} v
	* @returns {T[]}
	*/
	function flatten(v) {
		/** @type {T[]} */
		const result = [];
		if (v) {
			if (isIterable(v)) result.push(...v);
			else result.push(v);
		}
		return result;
	}
	/**
	* @param {*} v
	* @returns {v is Iterable<any>}
	*/
	function isIterable(v) {
		return v && Symbol.iterator in v;
	}
	/**
	* Register the given visitor to parser services.
	* If the parser service of `vue-eslint-parser` was not found,
	* this generates a warning.
	*
	* @param {RuleContext} context The rule context to use parser services.
	* @param {TemplateListener} templateBodyVisitor The visitor to traverse the template body.
	* @param {RuleListener} [scriptVisitor] The visitor to traverse the script.
	* @param { { templateBodyTriggerSelector: "Program" | "Program:exit" } } [options] The options.
	* @returns {RuleListener} The merged visitor.
	*/
	function defineTemplateBodyVisitor(context, templateBodyVisitor, scriptVisitor, options) {
		const sourceCode = context.sourceCode;
		if (sourceCode.parserServices.defineTemplateBodyVisitor == null) {
			const filename = context.filename;
			if (path.extname(filename) === ".vue") context.report({
				loc: {
					line: 1,
					column: 0
				},
				message: "Use the latest vue-eslint-parser. See also https://eslint.vuejs.org/user-guide/#what-is-the-use-the-latest-vue-eslint-parser-error."
			});
			return {};
		}
		return sourceCode.parserServices.defineTemplateBodyVisitor(templateBodyVisitor, scriptVisitor, options);
	}
	/**
	* Register the given visitor to parser services.
	* If the parser service of `vue-eslint-parser` was not found,
	* this generates a warning.
	*
	* @param {RuleContext} context The rule context to use parser services.
	* @param {TemplateListener} documentVisitor The visitor to traverse the document.
	* @param { { triggerSelector: "Program" | "Program:exit" } } [options] The options.
	* @returns {RuleListener} The merged visitor.
	*/
	function defineDocumentVisitor(context, documentVisitor, options) {
		const sourceCode = context.sourceCode;
		if (sourceCode.parserServices.defineDocumentVisitor == null) {
			const filename = context.filename;
			if (path.extname(filename) === ".vue") context.report({
				loc: {
					line: 1,
					column: 0
				},
				message: "Use the latest vue-eslint-parser. See also https://eslint.vuejs.org/user-guide/#what-is-the-use-the-latest-vue-eslint-parser-error."
			});
			return {};
		}
		return sourceCode.parserServices.defineDocumentVisitor(documentVisitor, options);
	}
	/**
	* @template T
	* @param {T} visitor
	* @param {...(TemplateListener | RuleListener | NodeListener)} visitors
	* @returns {T}
	*/
	function compositingVisitors(visitor, ...visitors) {
		for (const v of visitors) for (const key in v) if (visitor[key]) {
			const o = visitor[key];
			visitor[key] = (...args) => {
				o(...args);
				v[key](...args);
			};
		} else visitor[key] = v[key];
		return visitor;
	}
	/**
	* Find the variable of a given identifier.
	* @param {RuleContext} context The rule context
	* @param {Identifier} node The variable name to find.
	* @returns {Variable|null} The found variable or null.
	*/
	function findVariableByIdentifier(context, node) {
		return findVariable(getScope(context, node), node);
	}
	/**
	* Finds the property with the given name from the given ObjectExpression node.
	* @param {ObjectExpression} node
	* @param {string} name
	* @param { (p: Property) => boolean } [filter]
	* @returns { (Property) | null}
	*/
	function findProperty(node, name, filter) {
		const predicate = filter ? (prop) => isProperty(prop) && getStaticPropertyName(prop) === name && filter(prop) : (prop) => isProperty(prop) && getStaticPropertyName(prop) === name;
		return node.properties.find(predicate) || null;
	}
	/**
	* Finds the assignment property with the given name from the given ObjectPattern node.
	* @param {ObjectPattern} node
	* @param {string} name
	* @param { (p: AssignmentProperty) => boolean } [filter]
	* @returns { (AssignmentProperty) | null}
	*/
	function findAssignmentProperty(node, name, filter) {
		const predicate = filter ? (prop) => isAssignmentProperty(prop) && getStaticPropertyName(prop) === name && filter(prop) : (prop) => isAssignmentProperty(prop) && getStaticPropertyName(prop) === name;
		return node.properties.find(predicate) || null;
	}
	/**
	* Checks whether the given node is Property.
	* @param {Property | SpreadElement | AssignmentProperty} node
	* @returns {node is Property}
	*/
	function isProperty(node) {
		if (node.type !== "Property") return false;
		return !node.parent || node.parent.type === "ObjectExpression";
	}
	/**
	* Checks whether the given node is AssignmentProperty.
	* @param {AssignmentProperty | RestElement} node
	* @returns {node is AssignmentProperty}
	*/
	function isAssignmentProperty(node) {
		return node.type === "Property";
	}
	/**
	* Checks whether the given node is VElement.
	* @param {VElement | VExpressionContainer | VText | VDocumentFragment} node
	* @returns {node is VElement}
	*/
	function isVElement(node) {
		return node.type === "VElement";
	}
	/**
	* Checks whether the given node is in export default.
	* @param {ASTNode} node
	* @returns {boolean}
	*/
	function isInExportDefault(node) {
		/** @type {ASTNode | null} */
		let parent = node.parent;
		while (parent) {
			if (parent.type === "ExportDefaultDeclaration") return true;
			parent = parent.parent;
		}
		return false;
	}
	/**
	* Retrieve `TSAsExpression#expression` value if the given node a `TSAsExpression` node. Otherwise, pass through it.
	* @template T Node type
	* @param {T | TSAsExpression} node The node to address.
	* @returns {T} The `TSAsExpression#expression` value if the node is a `TSAsExpression` node. Otherwise, the node.
	*/
	function skipTSAsExpression(node) {
		if (!node) return node;
		if (node.type === "TSAsExpression") return skipTSAsExpression(node.expression);
		return node;
	}
	/**
	* Gets the parent node of the given node. This method returns a value ignoring `X as F`.
	* @param {Expression} node
	* @returns {ASTNode}
	*/
	function getParent(node) {
		let parent = node.parent;
		while (parent.type === "TSAsExpression") parent = parent.parent;
		return parent;
	}
	/**
	* Checks if the given node is a property value.
	* @param {Property} prop
	* @param {Expression} node
	*/
	function isPropertyChain(prop, node) {
		let value = node;
		while (value.parent.type === "TSAsExpression") value = value.parent;
		return prop === value.parent && prop.value === value;
	}
	/**
	* Retrieve `AssignmentPattern#left` value if the given node a `AssignmentPattern` node. Otherwise, pass through it.
	* @template T Node type
	* @param {T | AssignmentPattern} node The node to address.
	* @return {T} The `AssignmentPattern#left` value if the node is a `AssignmentPattern` node. Otherwise, the node.
	*/
	function skipDefaultParamValue(node) {
		if (!node) return node;
		if (node.type === "AssignmentPattern") return skipDefaultParamValue(node.left);
		return node;
	}
	/**
	* Retrieve `ChainExpression#expression` value if the given node a `ChainExpression` node. Otherwise, pass through it.
	* @template T Node type
	* @param {T | ChainExpression} node The node to address.
	* @returns {T} The `ChainExpression#expression` value if the node is a `ChainExpression` node. Otherwise, the node.
	*/
	function skipChainExpression(node) {
		if (!node) return node;
		if (node.type === "ChainExpression") return skipChainExpression(node.expression);
		return node;
	}
	/**
	* Checks whether the given node is in a type annotation.
	* @param {ESNode} node
	* @returns {boolean}
	*/
	function withinTypeNode(node) {
		/** @type {ASTNode | null} */
		let target = node;
		while (target) {
			if (isTypeNode(target)) return true;
			target = target.parent;
		}
		return false;
	}
	/**
	* Gets the property name of a given node.
	* @param {Property|AssignmentProperty|MethodDefinition|MemberExpression} node - The node to get.
	* @return {string|null} The property name if static. Otherwise, null.
	*/
	function getStaticPropertyName(node) {
		if (node.type === "Property" || node.type === "MethodDefinition") {
			if (!node.computed) {
				const key = node.key;
				if (key.type === "Identifier") return key.name;
			}
			const key = node.key;
			return getStringLiteralValue(key);
		}
		if (node.type === "MemberExpression") {
			if (!node.computed) {
				const property = node.property;
				if (property.type === "Identifier") return property.name;
				return null;
			}
			const property = node.property;
			return getStringLiteralValue(property);
		}
		return null;
	}
	/**
	* Gets the string of a given node.
	* @param {Literal|TemplateLiteral} node - The node to get.
	* @param {boolean} [stringOnly]
	* @return {string|null} The string if static. Otherwise, null.
	*/
	function getStringLiteralValue(node, stringOnly) {
		if (node.type === "Literal") {
			if (node.value == null) {
				if (!stringOnly && node.bigint != null) return node.bigint;
				return null;
			}
			if (typeof node.value === "string") return node.value;
			if (!stringOnly) return String(node.value);
			return null;
		}
		if (node.type === "TemplateLiteral" && node.expressions.length === 0 && node.quasis.length === 1) return node.quasis[0].value.cooked;
		return null;
	}
	/**
	* Gets the name parameter from the given call expression.
	* @param {CallExpression} node - The call expression to get.
	* @returns {NameWithLoc|null} The name and location if static.
	*/
	function getNameParamNode(node) {
		const nameLiteralNode = node.arguments[0];
		if (nameLiteralNode && isStringLiteral(nameLiteralNode)) {
			const name = getStringLiteralValue(nameLiteralNode);
			if (name != null) return {
				name,
				loc: nameLiteralNode.loc,
				range: nameLiteralNode.range
			};
		}
		return null;
	}
	/**
	* Gets the VExpressionContainer of a given node.
	* @param {ASTNode} node - The node to get.
	* @return {VExpressionContainer|null}
	*/
	function getVExpressionContainer(node) {
		/** @type {ASTNode | null} */
		let n = node;
		while (n && n.type !== "VExpressionContainer") n = n.parent;
		return n;
	}
	/**
	* @param {string} path
	*/
	function isTypeScriptFile(path) {
		return path.endsWith(".ts") || path.endsWith(".tsx") || path.endsWith(".mts");
	}
	/**
	* @param {string} path
	*/
	function isVueFile(path) {
		return path.endsWith(".vue") || path.endsWith(".jsx") || path.endsWith(".tsx");
	}
	/**
	* Checks whether the current file is uses `<script setup>`
	* @param {RuleContext} context The ESLint rule context object.
	*/
	function isScriptSetup(context) {
		return Boolean(getScriptSetupElement(context));
	}
	/**
	* Gets the element of `<script setup>`
	* @param {RuleContext} context The ESLint rule context object.
	* @returns {VElement | null} the element of `<script setup>`
	*/
	function getScriptSetupElement(context) {
		const sourceCode = context.sourceCode;
		const df = sourceCode.parserServices.getDocumentFragment && sourceCode.parserServices.getDocumentFragment();
		if (!df) return null;
		const scripts = df.children.filter(
			/** @returns {e is VElement} */
			(e) => isVElement(e) && e.name === "script"
		);
		if (scripts.length === 2) return scripts.find((e) => hasAttribute(e, "setup")) || null;
		const script = scripts[0];
		if (script && hasAttribute(script, "setup")) return script;
		return null;
	}
	/**
	* Check whether the given node is a Vue component based
	* on the filename and default export type
	* export default {} in .vue || .jsx
	* @param {ESNode} node Node to check
	* @param {string} path File name with extension
	* @returns {boolean}
	*/
	function isVueComponentFile(node, path) {
		return isVueFile(path) && node.type === "ExportDefaultDeclaration" && node.declaration.type === "ObjectExpression";
	}
	/**
	* Whether the given callee refers to a symbol exported by Vue.
	* @param {Identifier} callee Node to check.
	* @param {RuleContext} context The rule context to use parser services.
	* @returns {boolean}
	*/
	function isGlobalOrImportedFromVue(callee, context) {
		const globalScope = context.sourceCode.scopeManager.globalScope;
		if (globalScope === null) return true;
		const tracker = new ReferenceTracker(globalScope);
		const globalTraceMap = { [callee.name]: { [ReferenceTracker.CALL]: true } };
		const cjsTraceMap = createCompositionApiTraceMap(globalTraceMap);
		const esmTraceMap = createCompositionApiTraceMap({
			[ReferenceTracker.ESM]: true,
			[callee.name]: { [ReferenceTracker.CALL]: true }
		});
		function* allReferences() {
			yield* tracker.iterateGlobalReferences(globalTraceMap);
			yield* tracker.iterateEsmReferences(esmTraceMap);
			yield* tracker.iterateCjsReferences(cjsTraceMap);
		}
		for (const { node } of allReferences()) if (node === callee.parent) return true;
		const variable = findVariable(getScope(context, callee), callee);
		if (variable !== null && variable.defs.length === 1) {
			const def = variable.defs[0];
			/** @type {Set<string | null>} */
			const vueLikePackageNames = /* @__PURE__ */ new Set([
				"vue",
				"@vue/composition-api",
				"@nuxtjs/composition-api"
			]);
			if (def.type === "ImportBinding" && def.node.type === "ImportSpecifier" && def.node.imported.type === "Identifier" && def.node.parent.type === "ImportDeclaration") return vueLikePackageNames.has(def.node.parent.source.value);
			if (def.type === "Variable" && def.node.id.type === "ObjectPattern" && def.node.init !== null) {
				const init = def.node.init;
				if (init.type === "CallExpression") {
					const firstArg = init.arguments[0];
					if (init.callee.type === "Identifier" && init.callee.name === "require") {
						const source = isStringLiteral(firstArg) ? getStringLiteralValue(firstArg) : null;
						return vueLikePackageNames.has(source);
					}
				}
			}
			if ([
				"CatchClause",
				"ClassName",
				"FunctionName",
				"TDZ"
			].includes(def.type)) return false;
		}
		return true;
	}
	/**
	* Get the Vue component definition type from given node
	* Vue.component('xxx', {}) || component('xxx', {})
	* @param {RuleContext} context The rule context to use parser services.
	* @param {ObjectExpression} node Node to check
	* @returns {'component' | 'mixin' | 'extend' | 'createApp' | 'defineComponent' | 'defineNuxtComponent' | null}
	*/
	function getVueComponentDefinitionType(context, node) {
		const parent = getParent(node);
		if (parent.type === "CallExpression") {
			const callee = parent.callee;
			if (callee.type === "MemberExpression") {
				const calleeObject = skipTSAsExpression(callee.object);
				if (calleeObject.type === "Identifier") {
					const propName = getStaticPropertyName(callee);
					if (calleeObject.name === "Vue") return propName && isObjectArgument(parent) && (propName === "component" || propName === "mixin" || propName === "extend") ? propName : null;
					return propName && isObjectArgument(parent) && (propName === "component" || propName === "mixin") ? propName : null;
				}
			} else if (callee.type === "Identifier") {
				if (callee.name === "defineNuxtComponent") return isObjectArgument(parent) ? "defineNuxtComponent" : null;
				if ((callee.name === "component" || callee.name === "createApp" || callee.name === "defineComponent") && isGlobalOrImportedFromVue(callee, context)) return isObjectArgument(parent) ? callee.name : null;
			}
		}
		return null;
	}
	/** @param {CallExpression} node */
	function isObjectArgument(node) {
		const lastArgument = node.arguments.at(-1);
		return lastArgument && skipTSAsExpression(lastArgument).type === "ObjectExpression";
	}
	/**
	* Check whether given node is new Vue instance
	* new Vue({})
	* @param {NewExpression} node Node to check
	* @returns {boolean}
	*/
	function isVueInstance(node) {
		const callee = node.callee;
		return node.type === "NewExpression" && callee.type === "Identifier" && callee.name === "Vue" && node.arguments.length > 0 && skipTSAsExpression(node.arguments[0]).type === "ObjectExpression";
	}
	/**
	* If the given object is a Vue component or instance, returns the Vue definition type.
	* @param {RuleContext} context The ESLint rule context object.
	* @param {ObjectExpression} node Node to check
	* @returns { VueObjectType | null } The Vue definition type.
	*/
	function getVueObjectType(context, node) {
		if (node.type !== "ObjectExpression") return null;
		const parent = getParent(node);
		switch (parent.type) {
			case "ExportDefaultDeclaration": {
				const filePath = context.filename;
				if (isVueComponentFile(parent, filePath) && skipTSAsExpression(parent.declaration) === node) {
					const scriptSetup = getScriptSetupElement(context);
					if (scriptSetup && scriptSetup.range[0] <= parent.range[0] && parent.range[1] <= scriptSetup.range[1]) return null;
					return "export";
				}
				break;
			}
			case "CallExpression":
				if (getVueComponentDefinitionType(context, node) != null && skipTSAsExpression(parent.arguments.at(-1)) === node) return "definition";
				break;
			case "NewExpression": if (isVueInstance(parent) && skipTSAsExpression(parent.arguments[0]) === node) return "instance";
		}
		if (getComponentComments(context).some((el) => el.loc.end.line === node.loc.start.line - 1)) return "mark";
		return null;
	}
	/**
	* Checks whether the given object is an SFC definition.
	* @param {RuleContext} context The ESLint rule context object.
	* @param {ObjectExpression} node Node to check
	* @returns { boolean } `true`, the given object is an SFC definition.
	*/
	function isSFCObject(context, node) {
		if (node.type !== "ObjectExpression") return false;
		const filePath = context.filename;
		const ext = path.extname(filePath);
		if (ext !== ".vue" && ext) return false;
		return isSFC(node);
		/**
		* @param {Expression} node
		* @returns {boolean}
		*/
		function isSFC(node) {
			const parent = getParent(node);
			switch (parent.type) {
				case "ExportDefaultDeclaration": {
					if (skipTSAsExpression(parent.declaration) !== node) return false;
					const scriptSetup = getScriptSetupElement(context);
					return !scriptSetup || scriptSetup.range[0] > parent.range[0] || parent.range[1] > scriptSetup.range[1];
				}
				case "CallExpression": {
					if (parent.arguments.every((arg) => skipTSAsExpression(arg) !== node)) return false;
					const { callee } = parent;
					if (callee.type === "Identifier" && (callee.name === "defineComponent" || callee.name === "defineNuxtComponent") || callee.type === "MemberExpression" && callee.object.type === "Identifier" && callee.object.name === "Vue" && callee.property.type === "Identifier" && callee.property.name === "extend") return isSFC(parent);
					return false;
				}
				case "VariableDeclarator": {
					if (skipTSAsExpression(parent.init) !== node || parent.id.type !== "Identifier") return false;
					const variable = findVariable(getScope(context, node), parent.id);
					if (!variable) return false;
					return variable.references.some((ref) => isSFC(ref.identifier));
				}
			}
			return false;
		}
	}
	/**
	* Gets the component comments of a given context.
	* @param {RuleContext} context The ESLint rule context object.
	* @return {Token[]} The the component comments.
	*/
	function getComponentComments(context) {
		let tokens = componentComments.get(context);
		if (tokens) return tokens;
		tokens = context.sourceCode.getAllComments().filter((comment) => /@vue\/component/g.test(comment.value));
		componentComments.set(context, tokens);
		return tokens;
	}
	/**
	* Return generator with the all handler nodes defined in the given watcher property.
	* @param {Property|Expression} property
	* @returns {IterableIterator<Expression>}
	*/
	function* iterateWatchHandlerValues(property) {
		const value = property.type === "Property" ? property.value : property;
		if (value.type === "ObjectExpression") {
			const handler = findProperty(value, "handler");
			if (handler) yield handler.value;
		} else if (value.type === "ArrayExpression") {
			for (const element of value.elements) if (isDef(element) && element.type !== "SpreadElement") yield* iterateWatchHandlerValues(element);
		} else yield value;
	}
	/**
	* Wraps composition API trace map in 'vue', '@vue/composition-api' and '@nuxtjs/composition-api' imports, or '#imports' from unimport
	* @param {import('@eslint-community/eslint-utils').TYPES.TraceMap} map
	*/
	function createCompositionApiTraceMap(map) {
		return {
			vue: map,
			"@vue/composition-api": map,
			"@nuxtjs/composition-api": map,
			"#imports": map
		};
	}
	/**
	* Get the attribute which has the given name.
	* @param {VElement} node The start tag node to check.
	* @param {string} name The attribute name to check.
	* @param {string} [value] The attribute value to check.
	* @returns {VAttribute | null} The found attribute.
	*/
	function getAttribute(node, name, value) {
		return node.startTag.attributes.find(
			/**
			* @param {VAttribute | VDirective} node
			* @returns {node is VAttribute}
			*/
			(node) => !node.directive && node.key.name === name && (value === void 0 || node.value != null && node.value.value === value)
		) || null;
	}
	/**
	* Get the directive list which has the given name.
	* @param {VElement | VStartTag} node The start tag node to check.
	* @param {string} name The directive name to check.
	* @returns {VDirective[]} The array of `v-slot` directives.
	*/
	function getDirectives(node, name) {
		return (node.type === "VElement" ? node.startTag : node).attributes.filter(
			/**
			* @param {VAttribute | VDirective} node
			* @returns {node is VDirective}
			*/
			(node) => node.directive && node.key.name.name === name
		);
	}
	/**
	* Get the directive which has the given name.
	* @param {VElement} node The start tag node to check.
	* @param {string} name The directive name to check.
	* @param {string} [argument] The directive argument to check.
	* @returns {VDirective | null} The found directive.
	*/
	function getDirective(node, name, argument) {
		return node.startTag.attributes.find(
			/**
			* @param {VAttribute | VDirective} node
			* @returns {node is VDirective}
			*/
			(node) => node.directive && node.key.name.name === name && (argument === void 0 || (node.key.argument && node.key.argument.type === "VIdentifier" && node.key.argument.name) === argument)
		) || null;
	}
	/**
	* Check whether the given start tag has specific directive.
	* @param {VElement} node The start tag node to check.
	* @param {string} name The attribute name to check.
	* @param {string} [value] The attribute value to check.
	* @returns {boolean} `true` if the start tag has the attribute.
	*/
	function hasAttribute(node, name, value) {
		return Boolean(getAttribute(node, name, value));
	}
	/**
	* Check whether the given start tag has specific directive.
	* @param {VElement} node The start tag node to check.
	* @param {string} name The directive name to check.
	* @param {string} [argument] The directive argument to check.
	* @returns {boolean} `true` if the start tag has the directive.
	*/
	function hasDirective(node, name, argument) {
		return Boolean(getDirective(node, name, argument));
	}
	/**
	* Check whether the given directive node is v-bind same-name shorthand.
	* @param {VAttribute | VDirective} node The directive node to check.
	* @returns {node is VDirective & { value: VExpressionContainer & { expression: Identifier } }} `true` if the directive node is v-bind same-name shorthand.
	*/
	function isVBindSameNameShorthand(node) {
		return node.directive && node.key.name.name === "bind" && node.value?.expression?.type === "Identifier" && node.key.range[0] <= node.value.range[0] && node.value.range[1] <= node.key.range[1];
	}
	/**
	* @param {ASTNode} node
	* @returns {node is Literal | TemplateLiteral}
	*/
	function isStringLiteral(node) {
		return node.type === "Literal" && typeof node.value === "string" || node.type === "TemplateLiteral" && node.expressions.length === 0;
	}
	/**
	* Checks whether given defineProps call node has withDefaults.
	* @param {CallExpression} node The node of defineProps
	* @returns {node is CallExpression & { parent: CallExpression }}
	*/
	function hasWithDefaults(node) {
		return node.parent && node.parent.type === "CallExpression" && node.parent.arguments[0] === node && node.parent.callee.type === "Identifier" && node.parent.callee.name === "withDefaults";
	}
	/**
	* Get the withDefaults call node from given defineProps call node.
	* @param {CallExpression} node The node of defineProps
	* @returns {CallExpression | null}
	*/
	function getWithDefaults(node) {
		return hasWithDefaults(node) ? node.parent : null;
	}
	/**
	* Gets a map of the property nodes defined in withDefaults.
	* @param {CallExpression} node The node of defineProps
	* @returns { { [key: string]: Property | undefined } }
	*/
	function getWithDefaultsProps(node) {
		if (!hasWithDefaults(node)) return {};
		const param = node.parent.arguments[1];
		if (!param || param.type !== "ObjectExpression") return {};
		/** @type {Record<string, Property>} */
		const result = {};
		for (const prop of param.properties) {
			if (prop.type !== "Property") continue;
			const name = getStaticPropertyName(prop);
			if (name != null) result[name] = prop;
		}
		return result;
	}
	/**
	* Gets the props destructure property nodes for defineProp.
	* @param {CallExpression} node The node of defineProps
	* @returns { Record<string, AssignmentProperty | undefined> }
	*/
	function getPropsDestructure(node) {
		/** @type {ReturnType<typeof getPropsDestructure>} */
		const result = Object.create(null);
		const left = getLeftOfDefineProps(node);
		if (!left || left.type !== "ObjectPattern") return result;
		for (const prop of left.properties) {
			if (prop.type !== "Property") continue;
			const name = getStaticPropertyName(prop);
			if (name != null) result[name] = prop;
		}
		return result;
	}
	/**
	* Gets the default definition nodes for defineProp
	* using the props destructure with assignment pattern.
	* @param {CallExpression} node The node of defineProps
	* @returns { Record<string, {prop: AssignmentProperty , expression: Expression} | undefined> }
	*/
	function getDefaultPropExpressionsForPropsDestructure(node) {
		/** @type {ReturnType<typeof getDefaultPropExpressionsForPropsDestructure>} */
		const result = Object.create(null);
		const propsDestructureEntries = Object.entries(getPropsDestructure(node));
		for (const [name, prop] of propsDestructureEntries) {
			if (!prop) continue;
			const value = prop.value;
			if (value.type !== "AssignmentPattern") continue;
			result[name] = {
				prop,
				expression: value.right
			};
		}
		return result;
	}
	/**
	* Gets the pattern of the left operand of defineProps.
	* @param {CallExpression} node The node of defineProps
	* @returns {Pattern | null} The pattern of the left operand of defineProps
	*/
	function getLeftOfDefineProps(node) {
		let target = node;
		if (hasWithDefaults(target)) target = target.parent;
		if (!target.parent) return null;
		if (target.parent.type === "VariableDeclarator" && target.parent.init === target) return target.parent.id;
		return null;
	}
	/**
	* Get all props from component options object.
	* @param {ObjectExpression} componentObject Object with component definition
	* @return {(ComponentArrayProp | ComponentObjectProp | ComponentUnknownProp)[]} Array of component props
	*/
	function getComponentPropsFromOptions(componentObject) {
		const propsNode = componentObject.properties.find(
			/**
			* @param {ESNode} p
			* @returns {p is (Property & { key: Identifier & {name: 'props'} })}
			*/
			(p) => p.type === "Property" && getStaticPropertyName(p) === "props"
		);
		if (!propsNode) return [];
		if (propsNode.value.type !== "ObjectExpression" && propsNode.value.type !== "ArrayExpression") return [{
			type: "unknown",
			propName: null,
			node: propsNode.value
		}];
		return getComponentPropsFromDefine(propsNode.value);
	}
	/**
	* Get all emits from component options object.
	* @param {ObjectExpression} componentObject Object with component definition
	* @return {(ComponentArrayEmit | ComponentObjectEmit | ComponentUnknownEmit)[]} Array of component emits
	*/
	function getComponentEmitsFromOptions(componentObject) {
		const emitsNode = componentObject.properties.find(
			/**
			* @param {ESNode} p
			* @returns {p is (Property & { key: Identifier & {name: 'emits'} })}
			*/
			(p) => p.type === "Property" && getStaticPropertyName(p) === "emits"
		);
		if (!emitsNode) return [];
		if (emitsNode.value.type !== "ObjectExpression" && emitsNode.value.type !== "ArrayExpression") return [{
			type: "unknown",
			emitName: null,
			node: emitsNode.value
		}];
		return getComponentEmitsFromDefine(emitsNode.value);
	}
	/**
	* Get all props from `defineProps` call expression.
	* @param {RuleContext} context The rule context object.
	* @param {CallExpression} node `defineProps` call expression
	* @return {ComponentProp[]} Array of component props
	*/
	function getComponentPropsFromDefineProps(context, node) {
		if (node.arguments.length > 0) {
			const defNode = getObjectOrArray(context, node.arguments[0]);
			if (defNode) return getComponentPropsFromDefine(defNode);
			return [{
				type: "unknown",
				propName: null,
				node: node.arguments[0]
			}];
		}
		const typeArguments = "typeArguments" in node ? node.typeArguments : node.typeParameters;
		if (typeArguments && typeArguments.params.length > 0) return getComponentPropsFromTypeDefine(context, typeArguments.params[0]);
		return [{
			type: "unknown",
			propName: null,
			node: null
		}];
	}
	/**
	* Get all emits from `defineEmits` call expression.
	* @param {RuleContext} context The rule context object.
	* @param {CallExpression} node `defineEmits` call expression
	* @return {ComponentEmit[]} Array of component emits
	*/
	function getComponentEmitsFromDefineEmits(context, node) {
		if (node.arguments.length > 0) {
			const defNode = getObjectOrArray(context, node.arguments[0]);
			if (defNode) return getComponentEmitsFromDefine(defNode);
			return [{
				type: "unknown",
				emitName: null,
				node: node.arguments[0]
			}];
		}
		const typeArguments = "typeArguments" in node ? node.typeArguments : node.typeParameters;
		if (typeArguments && typeArguments.params.length > 0) return getComponentEmitsFromTypeDefine(context, typeArguments.params[0]);
		return [{
			type: "unknown",
			emitName: null,
			node: null
		}];
	}
	/**
	* Get all slots from `defineSlots` call expression.
	* @param {RuleContext} context The rule context object.
	* @param {CallExpression} node `defineSlots` call expression
	* @return {ComponentSlot[]} Array of component slots
	*/
	function getComponentSlotsFromDefineSlots(context, node) {
		const typeArguments = "typeArguments" in node ? node.typeArguments : node.typeParameters;
		if (typeArguments && typeArguments.params.length > 0) return getComponentSlotsFromTypeDefine(context, typeArguments.params[0]);
		return [{
			type: "unknown",
			slotName: null,
			node: null
		}];
	}
	/**
	* Get model info from `defineModel` call expression.
	* @param {RuleContext} _context The rule context object.
	* @param {CallExpression} node `defineModel` call expression
	* @return {ComponentModel} Object of component model
	*/
	function getComponentModelFromDefineModel(_context, node) {
		/** @type {ComponentModelName} */
		let name = {
			modelName: "modelValue",
			node: null
		};
		/** @type {Expression|null} */
		let options = node.arguments[0]?.type === "SpreadElement" ? null : node.arguments[0];
		if (node.arguments.length > 0) {
			const nameNodeCandidate = skipTSAsExpression(node.arguments[0]);
			if (nameNodeCandidate.type === "Literal") {
				name = {
					modelName: String(nameNodeCandidate.value),
					node: nameNodeCandidate
				};
				options = node.arguments[1]?.type === "SpreadElement" ? null : node.arguments[1];
			}
		}
		const typeArguments = "typeArguments" in node ? node.typeArguments : node.typeParameters;
		if (typeArguments && typeArguments.params.length > 0) return {
			name,
			options,
			typeNode: typeArguments.params[0]
		};
		return {
			name,
			options,
			typeNode: null
		};
	}
	/**
	* Get all props by looking at all component's properties
	* @param {ObjectExpression|ArrayExpression} propsNode Object with props definition
	* @return {(ComponentArrayProp | ComponentObjectProp | ComponentUnknownProp)[]} Array of component props
	*/
	function getComponentPropsFromDefine(propsNode) {
		if (propsNode.type === "ObjectExpression") return propsNode.properties.map(
			/** @returns {ComponentArrayProp | ComponentObjectProp | ComponentUnknownProp} */
			(prop) => {
				if (!isProperty(prop)) return {
					type: "unknown",
					propName: null,
					node: prop
				};
				const propName = getStaticPropertyName(prop);
				if (propName != null) return {
					type: "object",
					key: prop.key,
					propName,
					value: skipTSAsExpression(prop.value),
					node: prop
				};
				return {
					type: "object",
					key: null,
					propName: null,
					value: skipTSAsExpression(prop.value),
					node: prop
				};
			}
		);
		return propsNode.elements.filter(isDef).map((prop) => {
			if (prop.type === "Literal" || prop.type === "TemplateLiteral") {
				const propName = getStringLiteralValue(prop);
				if (propName != null) return {
					type: "array",
					key: prop,
					propName,
					value: null,
					node: prop
				};
			}
			return {
				type: "array",
				key: null,
				propName: null,
				value: null,
				node: prop
			};
		});
	}
	/**
	* Get all emits by looking at all component's properties
	* @param {ObjectExpression|ArrayExpression} emitsNode Object with emits definition
	* @return {(ComponentArrayEmit | ComponentObjectEmit | ComponentUnknownEmit)[]} Array of component emits.
	*/
	function getComponentEmitsFromDefine(emitsNode) {
		if (emitsNode.type === "ObjectExpression") return emitsNode.properties.map((prop) => {
			if (!isProperty(prop)) return {
				type: "unknown",
				key: null,
				emitName: null,
				value: null,
				node: prop
			};
			const emitName = getStaticPropertyName(prop);
			if (emitName != null) return {
				type: "object",
				key: prop.key,
				emitName,
				value: skipTSAsExpression(prop.value),
				node: prop
			};
			return {
				type: "object",
				key: null,
				emitName: null,
				value: skipTSAsExpression(prop.value),
				node: prop
			};
		});
		return emitsNode.elements.filter(isDef).map((emit) => {
			if (emit.type === "Literal" || emit.type === "TemplateLiteral") {
				const emitName = getStringLiteralValue(emit);
				if (emitName != null) return {
					type: "array",
					key: emit,
					emitName,
					value: null,
					node: emit
				};
			}
			return {
				type: "array",
				key: null,
				emitName: null,
				value: null,
				node: emit
			};
		});
	}
	/**
	* @param {RuleContext} context The rule context object.
	* @param {ESNode} node
	* @returns {ObjectExpression | ArrayExpression | null}
	*/
	function getObjectOrArray(context, node) {
		if (node.type === "ObjectExpression") return node;
		if (node.type === "ArrayExpression") return node;
		if (node.type === "Identifier") {
			const variable = findVariable(getScope(context, node), node);
			if (variable != null && variable.defs.length === 1) {
				const def = variable.defs[0];
				if (def.type === "Variable" && def.parent.kind === "const" && def.node.id.type === "Identifier" && def.node.init) return getObjectOrArray(context, def.node.init);
			}
		}
		return null;
	}
}));
//#endregion
Object.defineProperty(exports, "default", {
	enumerable: true,
	get: function() {
		return require_utils();
	}
});