diff --git a/lib/rules/prefer-use-template-ref.js b/lib/rules/prefer-use-template-ref.js index 916583e9f..7d01958b7 100644 --- a/lib/rules/prefer-use-template-ref.js +++ b/lib/rules/prefer-use-template-ref.js @@ -6,14 +6,42 @@ const utils = require('../utils') -/** @param expression {Expression | null} */ -function expressionIsRef(expression) { - return ( +/** + * @typedef ScriptRef + * @type {{node: Expression, ref: string}} + */ + +/** + * @param declarator {VariableDeclarator} + * @returns {ScriptRef} + * */ +function convertDeclaratorToScriptRef(declarator) { + return { + // @ts-ignore + node: declarator.init, // @ts-ignore - expression?.callee?.name === 'ref' || + 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 - expression?.callee?.name === 'shallowRef' + ['ref', 'shallowRef'].includes(declarator.init?.callee?.name) ) + + return refDeclarators.map(convertDeclaratorToScriptRef) } /** @type {import("eslint").Rule.RuleModule} */ @@ -36,40 +64,33 @@ module.exports = { /** @type Set */ const templateRefs = new Set() - /** - * @typedef ScriptRef - * @type {{node: Expression, ref: string}} - */ - /** * @type ScriptRef[] */ const scriptRefs = [] return utils.compositingVisitors( - utils.defineTemplateBodyVisitor( - context, - { - 'VAttribute[directive=false]'(node) { - if (node.key.name === 'ref' && node.value?.value) { - templateRefs.add(node.value.value) - } + utils.defineTemplateBodyVisitor(context, { + 'VAttribute[directive=false]'(node) { + if (node.key.name === 'ref' && node.value?.value) { + templateRefs.add(node.value.value) } - }, - { - VariableDeclarator(declarator) { - if (!expressionIsRef(declarator.init)) { - return - } + } + }), + utils.defineVueVisitor(context, { + onSetupFunctionEnter(node) { + // @ts-ignore + const newScriptRefs = getScriptRefsFromSetupFunction(node.body.body) - scriptRefs.push({ - // @ts-ignore - node: declarator.init, - // @ts-ignore - ref: declarator.id.name - }) - } + scriptRefs.push(...newScriptRefs) + } + }), + utils.defineScriptSetupVisitor(context, { + Program(node) { + const newScriptRefs = getScriptRefsFromSetupFunction(node.body) + + scriptRefs.push(...newScriptRefs) } - ), + }), { 'Program:exit'() { for (const templateRef of templateRefs) { diff --git a/tests/lib/rules/prefer-use-template-ref.js b/tests/lib/rules/prefer-use-template-ref.js index fe1ee2d2f..77020cdcf 100644 --- a/tests/lib/rules/prefer-use-template-ref.js +++ b/tests/lib/rules/prefer-use-template-ref.js @@ -197,6 +197,61 @@ tester.run('prefer-use-template-ref', rule, { const button = ref(); ` + }, + { + filename: 'ref-in-block.vue', + code: ` + + + ` + }, + { + filename: 'ref-in-block-setup-fn.vue', + code: ` + + + ` } ], invalid: [ @@ -278,36 +333,6 @@ tester.run('prefer-use-template-ref', rule, { } ] }, - { - filename: 'ref-in-block.vue', - code: ` - - - `, - errors: [ - { - messageId: 'preferUseTemplateRef', - data: { - name: 'ref' - }, - line: 14, - column: 33 - } - ] - }, { filename: 'setup-function-only-refs.vue', code: `