diff --git a/lib/rules/one-component-per-file.js b/lib/rules/one-component-per-file.js index b0cd795f9..02b4f299e 100644 --- a/lib/rules/one-component-per-file.js +++ b/lib/rules/one-component-per-file.js @@ -29,7 +29,7 @@ module.exports = { {}, utils.executeOnVueComponent(context, (node, type) => { if (type === 'definition') { - const defType = getVueComponentDefinitionType(node) + const defType = getVueComponentDefinitionType(context, node) if (defType === 'mixin') { return } diff --git a/lib/rules/require-expose.js b/lib/rules/require-expose.js index 5dca62ad9..7a2f31242 100644 --- a/lib/rules/require-expose.js +++ b/lib/rules/require-expose.js @@ -272,7 +272,7 @@ module.exports = { return } if (type === 'definition') { - const defType = getVueComponentDefinitionType(component) + const defType = getVueComponentDefinitionType(context, component) if (defType === 'mixin') { return } diff --git a/lib/rules/require-name-property.js b/lib/rules/require-name-property.js index 62eb0cfd5..0a29cedec 100644 --- a/lib/rules/require-name-property.js +++ b/lib/rules/require-name-property.js @@ -60,7 +60,7 @@ module.exports = { } return utils.executeOnVue(context, (component, type) => { if (type === 'definition') { - const defType = getVueComponentDefinitionType(component) + const defType = getVueComponentDefinitionType(context, component) if (defType === 'mixin') { return } diff --git a/lib/utils/index.js b/lib/utils/index.js index ef8cd0ee9..84eed26bd 100644 --- a/lib/utils/index.js +++ b/lib/utils/index.js @@ -2479,10 +2479,11 @@ function isVueComponentFile(node, path) { /** * Get the Vue component definition type from given node * Vue.component('xxx', {}) || component('xxx', {}) + * @param {RuleContext} context The rule context to use parser services. * @param {ObjectExpression} node Node to check * @returns {'component' | 'mixin' | 'extend' | 'createApp' | 'defineComponent' | null} */ -function getVueComponentDefinitionType(node) { +function getVueComponentDefinitionType(context, node) { const parent = getParent(node) if (parent.type === 'CallExpression') { const callee = parent.callee @@ -2527,6 +2528,23 @@ function getVueComponentDefinitionType(node) { if (callee.name === 'createApp') { // for Vue.js 3.x // createApp({}) + + const variable = findVariable(context.getScope(), callee) + + // only lint the createApp function that import from vue + if(variable !== null && variable.defs.length === 1) { + const def = variable.defs[0] + if ( + def.type === 'ImportBinding' && + def.node.type === 'ImportSpecifier' && + def.node.imported.type === 'Identifier' && + def.node.parent.type === 'ImportDeclaration' && + def.node.parent.source.value !== 'vue' + ) { + return null + } + } + const isAppVueComponent = isObjectArgument(parent) return isAppVueComponent ? 'createApp' : null } @@ -2603,7 +2621,7 @@ function getVueObjectType(context, node) { case 'CallExpression': { // Vue.component('xxx', {}) || component('xxx', {}) if ( - getVueComponentDefinitionType(node) != null && + getVueComponentDefinitionType(context, node) != null && skipTSAsExpression(parent.arguments.slice(-1)[0]) === node ) { return 'definition' diff --git a/tests/lib/rules/one-component-per-file.js b/tests/lib/rules/one-component-per-file.js index 579c470fc..60f7f2827 100644 --- a/tests/lib/rules/one-component-per-file.js +++ b/tests/lib/rules/one-component-per-file.js @@ -54,6 +54,21 @@ ruleTester.run('one-component-per-file', rule, { Vue.mixin({}) Vue.component('name', {}) ` + }, + { + filename: 'test.js', + code: ` + import { createApp } from 'vue' + createApp({}) + ` + }, + { + filename: 'test.js', + code: ` + import { createApp } from 'other.js' + createApp({}) + createApp({}) + ` } ], invalid: [ @@ -95,6 +110,18 @@ ruleTester.run('one-component-per-file', rule, { 'There is more than one component in this file.', 'There is more than one component in this file.' ] + }, + { + filename: 'test.vue', + code: ` + import { createApp } from 'vue' + createApp({}) + createApp({}) + `, + errors: [ + 'There is more than one component in this file.', + 'There is more than one component in this file.' + ] } ] })