diff --git a/.changeset/nine-zebras-rule.md b/.changeset/nine-zebras-rule.md new file mode 100644 index 000000000..8621702eb --- /dev/null +++ b/.changeset/nine-zebras-rule.md @@ -0,0 +1,5 @@ +--- +"eslint-plugin-vue": patch +--- + +Improved performance and type safety in `vue/prefer-use-template-ref` diff --git a/lib/rules/prefer-use-template-ref.js b/lib/rules/prefer-use-template-ref.js index eb8b8c06d..14323b2e2 100644 --- a/lib/rules/prefer-use-template-ref.js +++ b/lib/rules/prefer-use-template-ref.js @@ -8,40 +8,29 @@ const utils = require('../utils') /** * @typedef ScriptRef - * @type {{node: Expression, ref: string}} + * @type {[string, CallExpression]} */ -/** - * @param declarator {VariableDeclarator} - * @returns {ScriptRef} - * */ -function convertDeclaratorToScriptRef(declarator) { - return { - // @ts-ignore - node: declarator.init, - // @ts-ignore - ref: declarator.id.name - } -} - /** * @param body {(Statement | ModuleDeclaration)[]} * @returns {ScriptRef[]} * */ function getScriptRefsFromSetupFunction(body) { - /** @type {VariableDeclaration[]} */ - const variableDeclarations = body.filter( - (child) => child.type === 'VariableDeclaration' - ) - const variableDeclarators = variableDeclarations.map( - (declaration) => declaration.declarations[0] - ) - const refDeclarators = variableDeclarators.filter((declarator) => - // @ts-ignore - ['ref', 'shallowRef'].includes(declarator.init?.callee?.name) - ) + return body.flatMap((child) => { + if (child.type === 'VariableDeclaration') { + const declarator = child.declarations[0] + + if ( + declarator.init?.type === 'CallExpression' && + declarator.init.callee?.type === 'Identifier' && + declarator.id.type === 'Identifier' && + ['ref', 'shallowRef'].includes(declarator.init.callee.name) + ) + return [[declarator.id.name, declarator.init]] + } - return refDeclarators.map(convertDeclaratorToScriptRef) + return [] + }) } /** @type {import("eslint").Rule.RuleModule} */ @@ -94,21 +83,20 @@ module.exports = { }), { 'Program:exit'() { + const scriptRefsMap = new Map(scriptRefs) + for (const templateRef of templateRefs) { - const scriptRef = scriptRefs.find( - (scriptRef) => scriptRef.ref === templateRef - ) + const scriptRef = scriptRefsMap.get(templateRef) if (!scriptRef) { continue } context.report({ - node: scriptRef.node, + node: scriptRef, messageId: 'preferUseTemplateRef', data: { - // @ts-ignore - name: scriptRef.node?.callee?.name + name: /** @type {Identifier} */ (scriptRef.callee).name } }) }