From 56bcdb43c2c99b0d64fba94591c8d814614262b8 Mon Sep 17 00:00:00 2001 From: Flo Edelmann Date: Thu, 27 Jan 2022 13:14:28 +0100 Subject: [PATCH 1/4] Support template literal component names in `vue/no-undef-components` (#1782) * Move `isStringLiteral` function to utils * Support template literal component names in `vue/no-undef-components` --- lib/rules/no-undef-components.js | 7 ++++--- lib/rules/prefer-separate-static-class.js | 21 +++++---------------- lib/utils/index.js | 11 +++++++++++ tests/lib/rules/no-undef-components.js | 13 +++++++++++++ 4 files changed, 33 insertions(+), 19 deletions(-) diff --git a/lib/rules/no-undef-components.js b/lib/rules/no-undef-components.js index aa9ddb0dd..e56f0412c 100644 --- a/lib/rules/no-undef-components.js +++ b/lib/rules/no-undef-components.js @@ -202,9 +202,10 @@ module.exports = { const nameProperty = utils.findProperty(obj, 'name') - if (nameProperty) { - if (nameProperty.value.type === 'Literal') { - registeredComponentNames.push(`${nameProperty.value.value}`) + if (nameProperty && utils.isStringLiteral(nameProperty.value)) { + const name = utils.getStringLiteralValue(nameProperty.value) + if (name) { + registeredComponentNames.push(name) } } diff --git a/lib/rules/prefer-separate-static-class.js b/lib/rules/prefer-separate-static-class.js index 504d95d60..0ebeb2451 100644 --- a/lib/rules/prefer-separate-static-class.js +++ b/lib/rules/prefer-separate-static-class.js @@ -8,22 +8,11 @@ // Requirements // ------------------------------------------------------------------------------ -const { defineTemplateBodyVisitor, getStringLiteralValue } = require('../utils') - -// ------------------------------------------------------------------------------ -// Helpers -// ------------------------------------------------------------------------------ - -/** - * @param {ASTNode} node - * @returns {node is Literal | TemplateLiteral} - */ -function isStringLiteral(node) { - return ( - (node.type === 'Literal' && typeof node.value === 'string') || - (node.type === 'TemplateLiteral' && node.expressions.length === 0) - ) -} +const { + defineTemplateBodyVisitor, + isStringLiteral, + getStringLiteralValue +} = require('../utils') /** * @param {Expression | VForExpression | VOnExpression | VSlotScopeExpression | VFilterSequenceExpression} expressionNode diff --git a/lib/utils/index.js b/lib/utils/index.js index bacb892ba..69cd84a31 100644 --- a/lib/utils/index.js +++ b/lib/utils/index.js @@ -758,6 +758,17 @@ module.exports = { } }, + /** + * @param {ASTNode} node + * @returns {node is Literal | TemplateLiteral} + */ + isStringLiteral(node) { + return ( + (node.type === 'Literal' && typeof node.value === 'string') || + (node.type === 'TemplateLiteral' && node.expressions.length === 0) + ) + }, + /** * Check whether the given node is a custom component or not. * @param {VElement} node The start tag node to check. diff --git a/tests/lib/rules/no-undef-components.js b/tests/lib/rules/no-undef-components.js index 8bc637f45..b3a7af106 100644 --- a/tests/lib/rules/no-undef-components.js +++ b/tests/lib/rules/no-undef-components.js @@ -504,6 +504,19 @@ tester.run('no-undef-components', rule, { ` }, + { + filename: 'test.vue', + code: ` + + + ` + }, { filename: 'test.vue', code: ` From d6f0337d88ce39214f4bf2853a5cdc26e2c30e32 Mon Sep 17 00:00:00 2001 From: Flo Edelmann Date: Thu, 27 Jan 2022 14:38:40 +0100 Subject: [PATCH 2/4] Meta: Fix `replacedBy` position (#1783) --- lib/rules/name-property-casing.js | 4 ++-- lib/rules/no-confusing-v-for-v-if.js | 4 ++-- lib/rules/no-unregistered-components.js | 4 ++-- tools/update-docs-rules-index.js | 2 +- tools/update-docs.js | 4 ++-- 5 files changed, 9 insertions(+), 9 deletions(-) diff --git a/lib/rules/name-property-casing.js b/lib/rules/name-property-casing.js index d86435a95..29c100db5 100644 --- a/lib/rules/name-property-casing.js +++ b/lib/rules/name-property-casing.js @@ -19,10 +19,10 @@ module.exports = { description: 'enforce specific casing for the name property in Vue components', categories: ['vue3-strongly-recommended', 'strongly-recommended'], - url: 'https://eslint.vuejs.org/rules/name-property-casing.html', - replacedBy: ['component-definition-name-casing'] + url: 'https://eslint.vuejs.org/rules/name-property-casing.html' }, deprecated: true, + replacedBy: ['component-definition-name-casing'], fixable: 'code', // or "code" or "whitespace" schema: [ { diff --git a/lib/rules/no-confusing-v-for-v-if.js b/lib/rules/no-confusing-v-for-v-if.js index 4135f163a..1842f7c8c 100644 --- a/lib/rules/no-confusing-v-for-v-if.js +++ b/lib/rules/no-confusing-v-for-v-if.js @@ -43,10 +43,10 @@ module.exports = { docs: { description: 'disallow confusing `v-for` and `v-if` on the same element', categories: ['vue3-recommended', 'recommended'], - url: 'https://eslint.vuejs.org/rules/no-confusing-v-for-v-if.html', - replacedBy: ['no-use-v-if-with-v-for'] + url: 'https://eslint.vuejs.org/rules/no-confusing-v-for-v-if.html' }, deprecated: true, + replacedBy: ['no-use-v-if-with-v-for'], fixable: null, schema: [] }, diff --git a/lib/rules/no-unregistered-components.js b/lib/rules/no-unregistered-components.js index efd265e55..4ba755dd3 100644 --- a/lib/rules/no-unregistered-components.js +++ b/lib/rules/no-unregistered-components.js @@ -44,10 +44,10 @@ module.exports = { 'disallow using components that are not registered inside templates', categories: null, recommended: false, - url: 'https://eslint.vuejs.org/rules/no-unregistered-components.html', - replacedBy: ['no-undef-components'] + url: 'https://eslint.vuejs.org/rules/no-unregistered-components.html' }, deprecated: true, + replacedBy: ['no-undef-components'], fixable: null, schema: [ { diff --git a/tools/update-docs-rules-index.js b/tools/update-docs-rules-index.js index 913db1b91..9b177d7ac 100644 --- a/tools/update-docs-rules-index.js +++ b/tools/update-docs-rules-index.js @@ -38,7 +38,7 @@ function toRuleRow(rule) { function toDeprecatedRuleRow(rule) { const link = `[${rule.ruleId}](./${rule.name}.md)` - const replacedRules = rule.meta.docs.replacedBy || [] + const replacedRules = rule.meta.replacedBy || [] const replacedBy = replacedRules .map((name) => `[vue/${name}](./${name}.md)`) .join(', ') diff --git a/tools/update-docs.js b/tools/update-docs.js index 098585887..a7b847eee 100644 --- a/tools/update-docs.js +++ b/tools/update-docs.js @@ -120,8 +120,8 @@ class DocFile { const notes = [] if (meta.deprecated) { - if (meta.docs.replacedBy) { - const replacedRules = meta.docs.replacedBy.map( + if (meta.replacedBy) { + const replacedRules = meta.replacedBy.map( (name) => `[vue/${name}](${name}.md) rule` ) notes.push( From bd1fcb5533946a98bda6cbbbde66817ce1a6f74c Mon Sep 17 00:00:00 2001 From: Yosuke Ota Date: Fri, 4 Feb 2022 19:13:18 +0900 Subject: [PATCH 3/4] Fix false positives due to conflicts with other rules in `vue/no-unused-properties` rule (#1790) --- lib/rules/no-unused-properties.js | 6 ++-- tests/lib/rules/no-unused-properties.js | 42 ++++++++++++++++++++++++- 2 files changed, 45 insertions(+), 3 deletions(-) diff --git a/lib/rules/no-unused-properties.js b/lib/rules/no-unused-properties.js index 74762e446..1414df359 100644 --- a/lib/rules/no-unused-properties.js +++ b/lib/rules/no-unused-properties.js @@ -586,8 +586,7 @@ module.exports = { } }), { - /** @param {Program} node */ - 'Program:exit'(node) { + Program() { const styleVars = getStyleVariablesContext(context) if (styleVars) { templatePropertiesContainer.propertyReferences.push( @@ -596,6 +595,9 @@ module.exports = { ) ) } + }, + /** @param {Program} node */ + 'Program:exit'(node) { if (!node.templateBody) { reportUnusedProperties() } diff --git a/tests/lib/rules/no-unused-properties.js b/tests/lib/rules/no-unused-properties.js index 0023443cb..a75d83e72 100644 --- a/tests/lib/rules/no-unused-properties.js +++ b/tests/lib/rules/no-unused-properties.js @@ -4,7 +4,8 @@ */ 'use strict' -const RuleTester = require('eslint').RuleTester +const { RuleTester, Linter } = require('eslint') +const assert = require('assert') const rule = require('../../../lib/rules/no-unused-properties') const tester = new RuleTester({ @@ -2805,3 +2806,42 @@ tester.run('no-unused-properties', rule, { } ] }) + +// https://github.com/vuejs/eslint-plugin-vue/issues/1789 +describe('`vue/no-unused-properties` and `vue/no-unused-components` should not conflict.', () => { + const linter = new Linter() + linter.defineParser('vue-eslint-parser', require('vue-eslint-parser')) + linter.defineRule( + 'vue/no-unused-components', + require('../../../lib/rules/no-unused-components') + ) + linter.defineRule('vue/no-unused-properties', rule) + + const config = { + parser: 'vue-eslint-parser', + parserOptions: { + ecmaVersion: 2020, + sourceType: 'module' + }, + rules: { + 'vue/no-unused-components': 'error', + 'vue/no-unused-properties': 'error' + } + } + + it('should not be a false positive when using CSS v-bind().', () => { + const code = ` + + + ` + assert.deepStrictEqual(linter.verify(code, config, 'test.vue'), []) + }) +}) From 7ebbd85dcfffd54d58d7b727408104f7278cc924 Mon Sep 17 00:00:00 2001 From: yosuke ota Date: Fri, 4 Feb 2022 20:14:09 +0900 Subject: [PATCH 4/4] 8.4.1 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 3ef950099..4579c6545 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "eslint-plugin-vue", - "version": "8.4.0", + "version": "8.4.1", "description": "Official ESLint plugin for Vue.js", "main": "lib/index.js", "scripts": {