From e70aab6c74b01eab1a188ebdcc4ef75740e5526f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Sajn=C3=B3g?= Date: Wed, 15 Aug 2018 23:21:44 +0200 Subject: [PATCH 1/3] Fix custom component detection --- lib/utils/index.js | 6 +++--- tests/lib/rules/no-unused-components.js | 24 ++++++++++++++++++++++++ 2 files changed, 27 insertions(+), 3 deletions(-) diff --git a/lib/utils/index.js b/lib/utils/index.js index b39eeba04..8c39c63d8 100644 --- a/lib/utils/index.js +++ b/lib/utils/index.js @@ -233,7 +233,7 @@ module.exports = { assert(node && node.type === 'VElement') return ( - (this.isHtmlElementNode(node) && !this.isHtmlWellKnownElementName(node.name)) || + (this.isHtmlElementNode(node) && !this.isHtmlWellKnownElementName(node.rawName)) || this.hasAttribute(node, 'is') || this.hasDirective(node, 'bind', 'is') ) @@ -280,7 +280,7 @@ module.exports = { isHtmlWellKnownElementName (name) { assert(typeof name === 'string') - return HTML_ELEMENT_NAMES.has(name.toLowerCase()) + return HTML_ELEMENT_NAMES.has(name) }, /** @@ -291,7 +291,7 @@ module.exports = { isHtmlVoidElementName (name) { assert(typeof name === 'string') - return VOID_ELEMENT_NAMES.has(name.toLowerCase()) + return VOID_ELEMENT_NAMES.has(name) }, /** diff --git a/tests/lib/rules/no-unused-components.js b/tests/lib/rules/no-unused-components.js index f412b3ecb..639039ef1 100644 --- a/tests/lib/rules/no-unused-components.js +++ b/tests/lib/rules/no-unused-components.js @@ -282,6 +282,30 @@ tester.run('no-unused-components', rule, { } ` }, + { + filename: 'test.vue', + code: ` + ` + }, // Ignore when `render` is used instead of temoplate { From 348b628f876d23b63645bd2e4bfd15f4039ea530 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Sajn=C3=B3g?= Date: Thu, 16 Aug 2018 00:00:19 +0200 Subject: [PATCH 2/3] Add ignoreWhenBindingPresent setting to no-unused-components --- docs/rules/no-unused-components.md | 48 ++++++++++++++++++++++++- lib/rules/no-unused-components.js | 46 ++++++++++++++---------- tests/lib/rules/no-unused-components.js | 28 +++++++++++++++ 3 files changed, 102 insertions(+), 20 deletions(-) diff --git a/docs/rules/no-unused-components.md b/docs/rules/no-unused-components.md index 7220df0c6..537ddee95 100644 --- a/docs/rules/no-unused-components.md +++ b/docs/rules/no-unused-components.md @@ -64,4 +64,50 @@ Note that components registered under other than `PascalCase` name have to be ca ## :wrench: Options -Nothing. +```json +{ + "vue/no-unused-components": ["error", { + "ignoreWhenBindingPresent": false + }] +} +``` + +- `ignoreWhenBindingPresent` ... surpresses all error if binding has been detected in the template + default `false` + + +:+1: Examples of **correct** code: + +```json +{ + "vue/no-unused-components": ["error", { + "ignoreWhenBindingPresent": true + }] +} +``` + +```html + + + +``` diff --git a/lib/rules/no-unused-components.js b/lib/rules/no-unused-components.js index 90673dfff..d152e0f8d 100644 --- a/lib/rules/no-unused-components.js +++ b/lib/rules/no-unused-components.js @@ -23,42 +23,50 @@ module.exports = { url: 'https://github.com/vuejs/eslint-plugin-vue/blob/v5.0.0-beta.3/docs/rules/no-unused-components.md' }, fixable: null, - schema: [] + schema: [{ + type: 'object', + properties: { + ignoreWhenBindingPresent: { + type: 'boolean' + } + }, + additionalProperties: false + }] }, create (context) { + const options = context.options[0] || {} const usedComponents = [] let registeredComponents = [] + let ignoreReporting = false let templateLocation return utils.defineTemplateBodyVisitor(context, { VElement (node) { - if (!utils.isCustomComponent(node)) return - let usedComponentName - - if (utils.hasAttribute(node, 'is')) { - usedComponentName = utils.findAttribute(node, 'is').value.value - } else if (utils.hasDirective(node, 'bind', 'is')) { - const directiveNode = utils.findDirective(node, 'bind', 'is') - if ( - directiveNode.value.type === 'VExpressionContainer' && - directiveNode.value.expression.type === 'Literal' - ) { - usedComponentName = directiveNode.value.expression.value - } - } else { - usedComponentName = node.rawName + if (utils.isHtmlElementNode(node) && !utils.isHtmlWellKnownElementName(node.rawName)) { + usedComponents.push(node.rawName) } + }, + "VAttribute[directive=true][key.name='bind'][key.argument='is']" (node) { + if (node.value.type !== 'VExpressionContainer') return - if (usedComponentName) { - usedComponents.push(usedComponentName) + if (node.value.expression.type === 'Literal') { + usedComponents.push(node.value.expression.value) + } else if (options.ignoreWhenBindingPresent) { + ignoreReporting = true } }, + "VAttribute[directive=false][key.name='is']" (node) { + usedComponents.push(node.value.value) + }, "VElement[name='template']" (rootNode) { templateLocation = templateLocation || rootNode.loc.start }, "VElement[name='template']:exit" (rootNode) { - if (rootNode.loc.start !== templateLocation) return + if ( + rootNode.loc.start !== templateLocation || + ignoreReporting + ) return registeredComponents .filter(({ name }) => { diff --git a/tests/lib/rules/no-unused-components.js b/tests/lib/rules/no-unused-components.js index 639039ef1..c1a2d222b 100644 --- a/tests/lib/rules/no-unused-components.js +++ b/tests/lib/rules/no-unused-components.js @@ -321,6 +321,34 @@ tester.run('no-unused-components', rule, { } } ` + }, + + // Setting: ignoreWhenBindingPresent + { + filename: 'test.vue', + code: ` + + `, + options: [{ ignoreWhenBindingPresent: true }] } ], invalid: [ From 187c7a37613bd02bc4fe2be96c3af2e4911d801c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Sajn=C3=B3g?= Date: Thu, 13 Sep 2018 22:35:10 +0200 Subject: [PATCH 3/3] Make ignoreWhenBindingPresent setting true by default in no-unused-components rule --- docs/rules/no-unused-components.md | 49 +++++++++++++++--- lib/rules/no-unused-components.js | 3 +- tests/lib/rules/no-unused-components.js | 67 ++++++++++++++++++------- 3 files changed, 94 insertions(+), 25 deletions(-) diff --git a/docs/rules/no-unused-components.md b/docs/rules/no-unused-components.md index 537ddee95..6375c111a 100644 --- a/docs/rules/no-unused-components.md +++ b/docs/rules/no-unused-components.md @@ -64,6 +64,20 @@ Note that components registered under other than `PascalCase` name have to be ca ## :wrench: Options +```json +{ + "vue/no-unused-components": ["error", { + "ignoreWhenBindingPresent": true + }] +} +``` + +- `ignoreWhenBindingPresent` ... surpresses all errors if binding has been detected in the template + default `true` + + +:+1: Examples of **incorrect** code: + ```json { "vue/no-unused-components": ["error", { @@ -72,16 +86,38 @@ Note that components registered under other than `PascalCase` name have to be ca } ``` -- `ignoreWhenBindingPresent` ... surpresses all error if binding has been detected in the template - default `false` +```html + + + +``` :+1: Examples of **correct** code: ```json { "vue/no-unused-components": ["error", { - "ignoreWhenBindingPresent": true + "ignoreWhenBindingPresent": false }] } ``` @@ -90,7 +126,9 @@ Note that components registered under other than `PascalCase` name have to be ca @@ -105,9 +143,6 @@ Note that components registered under other than `PascalCase` name have to be ca TheSelect, TheInput, }, - computed: { - computedComponent() { ... } - } } ``` diff --git a/lib/rules/no-unused-components.js b/lib/rules/no-unused-components.js index d152e0f8d..aff3743b2 100644 --- a/lib/rules/no-unused-components.js +++ b/lib/rules/no-unused-components.js @@ -36,6 +36,7 @@ module.exports = { create (context) { const options = context.options[0] || {} + const ignoreWhenBindingPresent = options.ignoreWhenBindingPresent !== undefined ? options.ignoreWhenBindingPresent : true const usedComponents = [] let registeredComponents = [] let ignoreReporting = false @@ -52,7 +53,7 @@ module.exports = { if (node.value.expression.type === 'Literal') { usedComponents.push(node.value.expression.value) - } else if (options.ignoreWhenBindingPresent) { + } else if (ignoreWhenBindingPresent) { ignoreReporting = true } }, diff --git a/tests/lib/rules/no-unused-components.js b/tests/lib/rules/no-unused-components.js index c1a2d222b..939413a59 100644 --- a/tests/lib/rules/no-unused-components.js +++ b/tests/lib/rules/no-unused-components.js @@ -307,23 +307,6 @@ tester.run('no-unused-components', rule, { ` }, - // Ignore when `render` is used instead of temoplate - { - filename: 'test.vue', - code: ` - ` - }, - - // Setting: ignoreWhenBindingPresent { filename: 'test.vue', code: ` @@ -349,6 +332,22 @@ tester.run('no-unused-components', rule, { } `, options: [{ ignoreWhenBindingPresent: true }] + }, + + // Ignore when `render` is used instead of temoplate + { + filename: 'test.vue', + code: ` + ` } ], invalid: [ @@ -416,6 +415,40 @@ tester.run('no-unused-components', rule, { message: 'The "the-button" component has been registered but not used.', line: 11 }] + }, + // Setting: ignoreWhenBindingPresent + { + filename: 'test.vue', + code: ` + + `, + options: [{ ignoreWhenBindingPresent: false }], + errors: [{ + message: 'The "Foo" component has been registered but not used.', + line: 13 + }, { + message: 'The "Bar" component has been registered but not used.', + line: 14 + }] } ] })