From d22cb94bcf77e95b81df2b6b55404e575c68f0a1 Mon Sep 17 00:00:00 2001 From: yosuke ota Date: Sat, 17 Jul 2021 14:57:29 +0900 Subject: [PATCH 1/5] Update `vue/no-unused-properties` and `vue/script-setup-uses-vars` rule to support style CSS vars --- lib/rules/no-unused-properties.js | 10 ++++ lib/rules/script-setup-uses-vars.js | 12 ++++- lib/utils/style-variables/index.js | 58 +++++++++++++++++++++++ tests/lib/rules/no-unused-properties.js | 32 +++++++++++++ tests/lib/rules/script-setup-uses-vars.js | 40 ++++++++++++++++ 5 files changed, 151 insertions(+), 1 deletion(-) create mode 100644 lib/utils/style-variables/index.js diff --git a/lib/rules/no-unused-properties.js b/lib/rules/no-unused-properties.js index 0e5b0b3e7..8b6bfa132 100644 --- a/lib/rules/no-unused-properties.js +++ b/lib/rules/no-unused-properties.js @@ -10,6 +10,7 @@ const utils = require('../utils') const eslintUtils = require('eslint-utils') +const { getStyleVariablesContext } = require('../utils/style-variables') /** * @typedef {import('../utils').GroupName} GroupName @@ -1056,6 +1057,15 @@ module.exports = { { /** @param {Program} node */ 'Program:exit'(node) { + const styleVars = getStyleVariablesContext(context) + if (styleVars) { + for (const { id } of styleVars.references) { + templatePropertiesContainer.usedProperties.addUsed( + id.name, + (context) => extractPatternOrThisProperties(id, context, true) + ) + } + } if (!node.templateBody) { reportUnusedProperties() } diff --git a/lib/rules/script-setup-uses-vars.js b/lib/rules/script-setup-uses-vars.js index 68e0b3fc3..a73a33678 100644 --- a/lib/rules/script-setup-uses-vars.js +++ b/lib/rules/script-setup-uses-vars.js @@ -4,6 +4,7 @@ */ 'use strict' +const { getStyleVariablesContext } = require('../utils/style-variables') // ------------------------------------------------------------------------------ // Requirements // ------------------------------------------------------------------------------ @@ -112,7 +113,16 @@ module.exports = { } } }, - undefined, + { + Program() { + const styleVars = getStyleVariablesContext(context) + if (styleVars) { + for (const ref of styleVars.references) { + context.markVariableAsUsed(ref.id.name) + } + } + } + }, { templateBodyTriggerSelector: 'Program' } diff --git a/lib/utils/style-variables/index.js b/lib/utils/style-variables/index.js new file mode 100644 index 000000000..c5f8e1601 --- /dev/null +++ b/lib/utils/style-variables/index.js @@ -0,0 +1,58 @@ +const { isVElement } = require('..') + +module.exports = { + getStyleVariablesContext +} + +class StyleVariablesContext { + /** + * @param {RuleContext} context + * @param {VElement[]} styles + */ + constructor(context, styles) { + this.context = context + this.styles = styles + /** @type {VReference[]} */ + this.references = [] + for (const style of styles) { + for (const node of style.children) { + if (node.type === 'VExpressionContainer') { + for (const ref of node.references.filter( + (ref) => ref.variable == null + )) { + this.references.push(ref) + } + } + } + } + } +} + +/** @type {Map e.name === 'style') + if (!styles.length) { + return null + } + let ctx = cache.get(styles[0]) + if (ctx) { + return ctx + } + ctx = new StyleVariablesContext(context, styles) + cache.set(styles[0], ctx) + return ctx +} diff --git a/tests/lib/rules/no-unused-properties.js b/tests/lib/rules/no-unused-properties.js index 4af8091af..164e562ab 100644 --- a/tests/lib/rules/no-unused-properties.js +++ b/tests/lib/rules/no-unused-properties.js @@ -1562,6 +1562,38 @@ tester.run('no-unused-properties', rule, { } `, options: allOptions + }, + + //style vars + { + filename: 'test.vue', + code: ` + + + + + + ` } ], diff --git a/tests/lib/rules/script-setup-uses-vars.js b/tests/lib/rules/script-setup-uses-vars.js index 5d3c80060..3ff893f86 100644 --- a/tests/lib/rules/script-setup-uses-vars.js +++ b/tests/lib/rules/script-setup-uses-vars.js @@ -179,6 +179,25 @@ describe('script-setup-uses-vars', () => {
` + }, + + //style vars + { + filename: 'test.vue', + code: ` + + + + ` } ], @@ -305,6 +324,27 @@ describe('script-setup-uses-vars', () => { line: 4 } ] + }, + + //style vars + { + filename: 'test.vue', + code: ` + + + + `, + errors: ["'color' is assigned a value but never used."] } ] }) From af17d4ff2485dfa55a390678c043da75da66cf21 Mon Sep 17 00:00:00 2001 From: yosuke ota Date: Sat, 17 Jul 2021 17:25:43 +0900 Subject: [PATCH 2/5] Add testcase --- tests/lib/rules/no-parsing-error.js | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/tests/lib/rules/no-parsing-error.js b/tests/lib/rules/no-parsing-error.js index 2b299f09a..12d195cb8 100644 --- a/tests/lib/rules/no-parsing-error.js +++ b/tests/lib/rules/no-parsing-error.js @@ -615,6 +615,32 @@ tester.run('no-parsing-error', rule, { { code: '', errors: ['Parsing error: x-invalid-namespace.'] + }, + + //style vars + { + filename: 'test.vue', + code: ` + + + `, + errors: [ + { + message: 'Parsing error: Unexpected end of expression.', + line: 5, + column: 33 + }, + { + message: 'Parsing error: Unexpected token size.', + line: 6, + column: 37 + } + ] } ] }) From d5f4ea0f05e5e6604e5f62f15d24a0a6c225157a Mon Sep 17 00:00:00 2001 From: yosuke ota Date: Sun, 18 Jul 2021 09:43:59 +0900 Subject: [PATCH 3/5] upgrade vue-eslint-parser --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 5821b2500..299296e16 100644 --- a/package.json +++ b/package.json @@ -56,7 +56,7 @@ "eslint-utils": "^2.1.0", "natural-compare": "^1.4.0", "semver": "^6.3.0", - "vue-eslint-parser": "^7.8.0" + "vue-eslint-parser": "^7.9.0" }, "devDependencies": { "@types/eslint": "^7.2.0", From 7fb7b2d890342b1c00a7259e28efd9f09cf2ab49 Mon Sep 17 00:00:00 2001 From: yosuke ota Date: Sun, 18 Jul 2021 09:47:16 +0900 Subject: [PATCH 4/5] update test --- tests/lib/rules/script-setup-uses-vars.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/lib/rules/script-setup-uses-vars.js b/tests/lib/rules/script-setup-uses-vars.js index 3ff893f86..dd49cf6a2 100644 --- a/tests/lib/rules/script-setup-uses-vars.js +++ b/tests/lib/rules/script-setup-uses-vars.js @@ -335,7 +335,7 @@ describe('script-setup-uses-vars', () => { const color = 'red' - `, + options: buildOptions() + }, + { + code: ` + + + + + `, + options: buildOptions({ version: '^2.6.0' }) + } + ], + invalid: [ + { + code: ` + + + + + `, + options: buildOptions({ version: '^3.0.0' }), + errors: [ + { + message: + 'SFC CSS variable injection is not supported until Vue.js "3.0.3".', + line: 21, + column: 18, + endLine: 21, + endColumn: 31 + }, + { + message: + 'SFC CSS variable injection is not supported until Vue.js "3.0.3".', + line: 24, + column: 22, + endLine: 24, + endColumn: 41 + } + ] + } + ] +})