'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 * @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').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 { 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, isTypeNode } = require_index.default; /** * @type { WeakMap } */ const componentComments = /* @__PURE__ */ new WeakMap(); /** @type { Map | null } */ let coreRuleMap = null; /** @type { Map } */ 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 { return (coreRuleMap || (coreRuleMap = new eslint.Linter().getRules())).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[]} 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 breakFlag = false; traverseNodes(rootNode, { enterNode(node, parent) { if (breakFlag) 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 (breakFlag) return; if (result === node) breakFlag = true; else if (skipNodes[0] === node) skipNodes.shift(); } }); return result; } const sourceCode = newProxy(eslintSourceCode, { get tokensAndComments() { return getTokensAndComments(); }, getNodeByRangeIndex, getDeclaredVariables }, tokenStore); /** @type {WeakMap} */ 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 } 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 \`