/** * @author Yosuke Ota * See LICENSE file in root directory for full license. */ 'use strict' // ------------------------------------------------------------------------------ // Requirements // ------------------------------------------------------------------------------ const utils = require('../utils') const { findVariable } = require('eslint-utils') // ------------------------------------------------------------------------------ // Rule Definition // ------------------------------------------------------------------------------ module.exports = { meta: { type: 'problem', docs: { description: 'disallow to pass multiple arguments to scoped slots', categories: ['vue3-recommended', 'recommended'], url: 'https://eslint.vuejs.org/rules/no-multiple-slot-args.html' }, fixable: null, schema: [], messages: { unexpected: 'Unexpected multiple arguments.', unexpectedSpread: 'Unexpected spread argument.' } }, /** @param {RuleContext} context */ create(context) { /** * Verify the given node * @param {MemberExpression | Identifier} node The node to verify */ function verify(node) { const parent = node.parent if ( parent.type === 'VariableDeclarator' && parent.id.type === 'Identifier' ) { // const foo = this.$scopedSlots.foo verifyReferences(parent.id) return } if ( parent.type === 'AssignmentExpression' && parent.right === node && parent.left.type === 'Identifier' ) { // foo = this.$scopedSlots.foo verifyReferences(parent.left) return } if (parent.type !== 'CallExpression' || parent.arguments.includes(node)) { return } if (!parent.arguments.length) { return } if (parent.arguments.length > 1) { context.report({ node: parent.arguments[1], messageId: 'unexpected' }) } if (parent.arguments[0].type === 'SpreadElement') { context.report({ node: parent.arguments[0], messageId: 'unexpectedSpread' }) } } /** * Verify the references of the given node. * @param {Identifier} node The node to verify */ function verifyReferences(node) { const variable = findVariable(context.getScope(), node) if (!variable) { return } for (const reference of variable.references) { if (!reference.isRead()) { continue } /** @type {Identifier} */ const id = reference.identifier verify(id) } } return utils.defineVueVisitor(context, { /** @param {MemberExpression} node */ MemberExpression(node) { const object = utils.skipChainExpression(node.object) if (object.type !== 'MemberExpression') { return } const name = utils.getStaticPropertyName(object) if (!name || (name !== '$slots' && name !== '$scopedSlots')) { return } if (!utils.isThis(object.object, context)) { return } verify(node) } }) } }