diff --git a/docs/rules/README.md b/docs/rules/README.md index 9a54292c9..867cbe2bc 100644 --- a/docs/rules/README.md +++ b/docs/rules/README.md @@ -210,7 +210,7 @@ For example: | [vue/html-comment-content-newline](./html-comment-content-newline.md) | enforce unified line brake in HTML comments | :wrench: | :lipstick: | | [vue/html-comment-content-spacing](./html-comment-content-spacing.md) | enforce unified spacing in HTML comments | :wrench: | :lipstick: | | [vue/html-comment-indent](./html-comment-indent.md) | enforce consistent indentation in HTML comments | :wrench: | :lipstick: | -| [vue/match-component-file-name](./match-component-file-name.md) | require component name property to match its file name | | :hammer: | +| [vue/match-component-file-name](./match-component-file-name.md) | require component name property to match its file name | :bulb: | :hammer: | | [vue/match-component-import-name](./match-component-import-name.md) | require the registered component name to match the imported component name | | :warning: | | [vue/new-line-between-multi-line-property](./new-line-between-multi-line-property.md) | enforce new lines between multi-line properties in Vue components | :wrench: | :lipstick: | | [vue/next-tick-style](./next-tick-style.md) | enforce Promise or callback style in `nextTick` | :wrench: | :hammer: | diff --git a/docs/rules/match-component-file-name.md b/docs/rules/match-component-file-name.md index afd57a390..ae27d13b6 100644 --- a/docs/rules/match-component-file-name.md +++ b/docs/rules/match-component-file-name.md @@ -9,6 +9,8 @@ since: v5.2.0 > require component name property to match its file name +- :bulb: Some problems reported by this rule are manually fixable by editor [suggestions](https://eslint.org/docs/developer-guide/working-with-rules#providing-suggestions). + This rule reports if a component `name` property does not match its file name. You can define an array of file extensions this rule should verify for the component's name. diff --git a/lib/rules/match-component-file-name.js b/lib/rules/match-component-file-name.js index 57fd4ff89..40d01ba00 100644 --- a/lib/rules/match-component-file-name.js +++ b/lib/rules/match-component-file-name.js @@ -31,6 +31,8 @@ function canVerify(node) { module.exports = { meta: { + // eslint-disable-next-line eslint-plugin/require-meta-has-suggestions + hasSuggestions: true, type: 'suggestion', docs: { description: 'require component name property to match its file name', @@ -114,7 +116,17 @@ module.exports = { node, message: 'Component name `{{name}}` should match file name `{{filename}}`.', - data: { filename, name } + data: { filename, name }, + suggest: [ + { + desc: 'Rename component to match file name.', + fix(fixer) { + const quote = + node.type === 'TemplateLiteral' ? '`' : node.raw[0] + return fixer.replaceText(node, `${quote}${filename}${quote}`) + } + } + ] }) } } diff --git a/tests/lib/rules/match-component-file-name.js b/tests/lib/rules/match-component-file-name.js index d1b4c3371..83610962c 100644 --- a/tests/lib/rules/match-component-file-name.js +++ b/tests/lib/rules/match-component-file-name.js @@ -564,7 +564,18 @@ ruleTester.run('match-component-file-name', rule, { errors: [ { message: - 'Component name `MComponent` should match file name `MyComponent`.' + 'Component name `MComponent` should match file name `MyComponent`.', + suggestions: [ + { + desc: 'Rename component to match file name.', + output: ` + export default { + name: 'MyComponent', + render() { return
} + } + ` + } + ] } ] }, @@ -581,7 +592,46 @@ ruleTester.run('match-component-file-name', rule, { errors: [ { message: - 'Component name `MComponent` should match file name `MyComponent`.' + 'Component name `MComponent` should match file name `MyComponent`.', + suggestions: [ + { + desc: 'Rename component to match file name.', + output: ` + export default { + name: 'MyComponent', + render() { return
} + } + ` + } + ] + } + ] + }, + { + filename: 'MyComponent.jsx', + code: ` + export default { + name: "MComponent", + render() { return
} + } + `, + options: [{ extensions: ['jsx'] }], + parserOptions: jsxParserOptions, + errors: [ + { + message: + 'Component name `MComponent` should match file name `MyComponent`.', + suggestions: [ + { + desc: 'Rename component to match file name.', + output: ` + export default { + name: "MyComponent", + render() { return
} + } + ` + } + ] } ] }, @@ -598,7 +648,18 @@ ruleTester.run('match-component-file-name', rule, { errors: [ { message: - 'Component name `MComponent` should match file name `MyComponent`.' + 'Component name `MComponent` should match file name `MyComponent`.', + suggestions: [ + { + desc: 'Rename component to match file name.', + output: ` + export default { + name: \`MyComponent\`, + render() { return
} + } + ` + } + ] } ] }, @@ -620,7 +681,53 @@ ruleTester.run('match-component-file-name', rule, { errors: [ { message: - 'Component name `MComponent` should match file name `MyComponent`.' + 'Component name `MComponent` should match file name `MyComponent`.', + suggestions: [ + { + desc: 'Rename component to match file name.', + output: ` + + ` + } + ] + } + ] + }, + { + filename: 'MyComponent.vue', + code: ` + + `, + options: [{ extensions: ['vue'] }], + parser: require.resolve('vue-eslint-parser'), + parserOptions, + errors: [ + { + message: + 'Component name `MComponent` should match file name `MyComponent`.', + suggestions: [ + { + desc: 'Rename component to match file name.', + output: ` + + ` + } + ] } ] }, @@ -640,7 +747,20 @@ ruleTester.run('match-component-file-name', rule, { errors: [ { message: - 'Component name `MComponent` should match file name `MyComponent`.' + 'Component name `MComponent` should match file name `MyComponent`.', + suggestions: [ + { + desc: 'Rename component to match file name.', + output: ` + + ` + } + ] } ] }, @@ -659,7 +779,46 @@ ruleTester.run('match-component-file-name', rule, { errors: [ { message: - 'Component name `MComponent` should match file name `MyComponent`.' + 'Component name `MComponent` should match file name `MyComponent`.', + suggestions: [ + { + desc: 'Rename component to match file name.', + output: ` + new Vue({ + name: 'MyComponent', + template: '
' + }) + ` + } + ] + } + ] + }, + { + filename: 'MyComponent.js', + code: ` + new Vue({ + name: "MComponent", + template: '
' + }) + `, + options: [{ extensions: ['js'] }], + parserOptions, + errors: [ + { + message: + 'Component name `MComponent` should match file name `MyComponent`.', + suggestions: [ + { + desc: 'Rename component to match file name.', + output: ` + new Vue({ + name: "MyComponent", + template: '
' + }) + ` + } + ] } ] }, @@ -676,7 +835,18 @@ ruleTester.run('match-component-file-name', rule, { errors: [ { message: - 'Component name `MComponent` should match file name `MyComponent`.' + 'Component name `MComponent` should match file name `MyComponent`.', + suggestions: [ + { + desc: 'Rename component to match file name.', + output: ` + new Vue({ + name: \`MyComponent\`, + template: '
' + }) + ` + } + ] } ] }, @@ -692,7 +862,43 @@ ruleTester.run('match-component-file-name', rule, { errors: [ { message: - 'Component name `MComponent` should match file name `MyComponent`.' + 'Component name `MComponent` should match file name `MyComponent`.', + suggestions: [ + { + desc: 'Rename component to match file name.', + output: ` + Vue.mixin({ + name: 'MyComponent', + }) + ` + } + ] + } + ] + }, + { + filename: 'MyComponent.js', + code: ` + Vue.mixin({ + name: "MComponent", + }) + `, + options: [{ extensions: ['js'] }], + parserOptions, + errors: [ + { + message: + 'Component name `MComponent` should match file name `MyComponent`.', + suggestions: [ + { + desc: 'Rename component to match file name.', + output: ` + Vue.mixin({ + name: "MyComponent", + }) + ` + } + ] } ] }, @@ -708,7 +914,17 @@ ruleTester.run('match-component-file-name', rule, { errors: [ { message: - 'Component name `MComponent` should match file name `MyComponent`.' + 'Component name `MComponent` should match file name `MyComponent`.', + suggestions: [ + { + desc: 'Rename component to match file name.', + output: ` + Vue.mixin({ + name: \`MyComponent\`, + }) + ` + } + ] } ] }, @@ -724,7 +940,43 @@ ruleTester.run('match-component-file-name', rule, { errors: [ { message: - 'Component name `MComponent` should match file name `MyComponent`.' + 'Component name `MComponent` should match file name `MyComponent`.', + suggestions: [ + { + desc: 'Rename component to match file name.', + output: ` + Vue.component('MyComponent', { + template: '
' + }) + ` + } + ] + } + ] + }, + { + filename: 'MyComponent.js', + code: ` + Vue.component("MComponent", { + template: '
' + }) + `, + options: [{ extensions: ['js'] }], + parserOptions, + errors: [ + { + message: + 'Component name `MComponent` should match file name `MyComponent`.', + suggestions: [ + { + desc: 'Rename component to match file name.', + output: ` + Vue.component("MyComponent", { + template: '
' + }) + ` + } + ] } ] }, @@ -740,7 +992,17 @@ ruleTester.run('match-component-file-name', rule, { errors: [ { message: - 'Component name `MComponent` should match file name `MyComponent`.' + 'Component name `MComponent` should match file name `MyComponent`.', + suggestions: [ + { + desc: 'Rename component to match file name.', + output: ` + Vue.component(\`MyComponent\`, { + template: '
' + }) + ` + } + ] } ] }, @@ -756,7 +1018,17 @@ ruleTester.run('match-component-file-name', rule, { errors: [ { message: - 'Component name `MComponent` should match file name `MyComponent`.' + 'Component name `MComponent` should match file name `MyComponent`.', + suggestions: [ + { + desc: 'Rename component to match file name.', + output: ` + app.component(\`MyComponent\`, { + template: '
' + }) + ` + } + ] } ] }, @@ -775,7 +1047,18 @@ ruleTester.run('match-component-file-name', rule, { errors: [ { message: - 'Component name `my-component` should match file name `MyComponent`.' + 'Component name `my-component` should match file name `MyComponent`.', + suggestions: [ + { + desc: 'Rename component to match file name.', + output: ` + export default { + name: 'MyComponent', + render() { return
} + } + ` + } + ] } ] }, @@ -792,7 +1075,18 @@ ruleTester.run('match-component-file-name', rule, { errors: [ { message: - 'Component name `MyComponent` should match file name `my-component`.' + 'Component name `MyComponent` should match file name `my-component`.', + suggestions: [ + { + desc: 'Rename component to match file name.', + output: ` + export default { + name: 'my-component', + render() { return
} + } + ` + } + ] } ] }