diff --git a/lib/rules/max-props.js b/lib/rules/max-props.js index 698757e78..0dc3043bf 100644 --- a/lib/rules/max-props.js +++ b/lib/rules/max-props.js @@ -39,14 +39,17 @@ module.exports = { /** * @param {import('../utils').ComponentProp[]} props + * @param {CallExpression | Property} node */ - function checkMaxNumberOfProps(props) { - if (props.length > option.maxProps && props[0].node) { + function checkMaxNumberOfProps(props, node) { + const uniqueProps = new Set(props.map((prop) => prop.propName)) + const propCount = uniqueProps.size + if (propCount > option.maxProps && props[0].node) { context.report({ - node: props[0].node.parent, + node, messageId: 'tooManyProps', data: { - propCount: props.length, + propCount, limit: option.maxProps } }) @@ -54,12 +57,23 @@ module.exports = { } return utils.compositingVisitors( - utils.executeOnVue(context, (obj) => { - checkMaxNumberOfProps(utils.getComponentPropsFromOptions(obj)) + utils.executeOnVue(context, (node) => { + const propsNode = node.properties.find( + /** @returns {p is Property} */ + (p) => + p.type === 'Property' && utils.getStaticPropertyName(p) === 'props' + ) + + if (!propsNode) return + + checkMaxNumberOfProps( + utils.getComponentPropsFromOptions(node), + propsNode + ) }), utils.defineScriptSetupVisitor(context, { - onDefinePropsEnter(_, props) { - checkMaxNumberOfProps(props) + onDefinePropsEnter(node, props) { + checkMaxNumberOfProps(props, node) } }) ) diff --git a/tests/lib/rules/max-props.js b/tests/lib/rules/max-props.js index 1ebfb9cff..7d000f363 100644 --- a/tests/lib/rules/max-props.js +++ b/tests/lib/rules/max-props.js @@ -26,6 +26,15 @@ tester.run('max-props', rule, { `, options: [{ maxProps: 5 }] }, + { + filename: 'test.vue', + code: ` + + `, + options: [{ maxProps: 5 }] + }, { filename: 'test.vue', code: ` @@ -99,6 +108,20 @@ tester.run('max-props', rule, { parser: require.resolve('@typescript-eslint/parser') } } + }, + { + filename: 'test.vue', + code: ` + + `, + options: [{ maxProps: 2 }], + languageOptions: { + parserOptions: { + parser: require.resolve('@typescript-eslint/parser') + } + } } ], invalid: [ @@ -160,6 +183,56 @@ tester.run('max-props', rule, { endLine: 3 } ] + }, + { + filename: 'test.vue', + code: ` + + `, + options: [{ maxProps: 2 }], + languageOptions: { + parserOptions: { + parser: require.resolve('@typescript-eslint/parser') + } + }, + errors: [ + { + message: 'Component has too many props (3). Maximum allowed is 2.', + line: 3, + endLine: 3 + } + ] + }, + { + filename: 'test.vue', + code: ` + + `, + options: [{ maxProps: 2 }], + languageOptions: { + parserOptions: { + parser: require.resolve('@typescript-eslint/parser') + } + }, + errors: [ + { + message: 'Component has too many props (3). Maximum allowed is 2.', + line: 3, + endLine: 11 + } + ] } ] })