From 7c8c99800887f2d1573be412ec51ae4e7bb82913 Mon Sep 17 00:00:00 2001 From: ItMaga Date: Sun, 24 Mar 2024 01:42:22 +0300 Subject: [PATCH 1/3] Fixed false negatives for props in template in `vue/no-unused-properties` --- lib/rules/no-unused-properties.js | 33 +++++-- tests/lib/rules/no-unused-properties.js | 112 ++++++++++++++++++++++++ 2 files changed, 139 insertions(+), 6 deletions(-) diff --git a/lib/rules/no-unused-properties.js b/lib/rules/no-unused-properties.js index d09aca5c2..6cebf3603 100644 --- a/lib/rules/no-unused-properties.js +++ b/lib/rules/no-unused-properties.js @@ -233,6 +233,8 @@ module.exports = { const deepData = Boolean(options.deepData) const ignorePublicMembers = Boolean(options.ignorePublicMembers) const unreferencedOptions = new Set(options.unreferencedOptions || []) + /** @type {null | Pattern} */ + let propsReferencePattern = null const propertyReferenceExtractor = definePropertyReferenceExtractor( context, @@ -332,8 +334,9 @@ module.exports = { for (const property of container.properties) { if ( - property.groupName === 'props' && - propertyReferencesForProps.hasProperty(property.name) + (property.groupName === 'props' && + propertyReferencesForProps.hasProperty(property.name)) || + propertyReferences.hasProperty('$props') ) { // used props continue @@ -369,6 +372,7 @@ module.exports = { } continue } + context.report({ node: property.node, messageId: 'unused', @@ -450,9 +454,9 @@ module.exports = { return } - const pattern = target.parent.id + propsReferencePattern = target.parent.id const propertyReferences = - propertyReferenceExtractor.extractFromPattern(pattern) + propertyReferenceExtractor.extractFromPattern(propsReferencePattern) container.propertyReferencesForProps.push(propertyReferences) }, onDefineModelEnter(node, model) { @@ -705,9 +709,26 @@ module.exports = { * @param {VExpressionContainer} node */ VExpressionContainer(node) { - templatePropertiesContainer.propertyReferences.push( + const property = propertyReferenceExtractor.extractFromVExpressionContainer(node) - ) + + templatePropertiesContainer.propertyReferences.push(property) + + if (!propsReferencePattern) { + return + } + + // props.prop in template + for (const key of property.allProperties().keys()) { + if ( + propsReferencePattern.type === 'Identifier' && + propsReferencePattern.name === key + ) { + templatePropertiesContainer.propertyReferences.push( + property.getNest(key) + ) + } + } }, /** * @param {VAttribute} node diff --git a/tests/lib/rules/no-unused-properties.js b/tests/lib/rules/no-unused-properties.js index 65b185298..1236a6911 100644 --- a/tests/lib/rules/no-unused-properties.js +++ b/tests/lib/rules/no-unused-properties.js @@ -51,6 +51,23 @@ const unreferencedOptions = { ] } +// tester.run('no-unused-properties', rule, { +// valid: [ +// { +// filename: 'test.vue', +// code: ` +// +// ` +// } +// ], +// invalid: [] +// }) +// return + tester.run('no-unused-properties', rule, { valid: [ { @@ -433,6 +450,20 @@ tester.run('no-unused-properties', rule, { ` }, + // a property used as a template $props expression + { + filename: 'test.vue', + code: ` + + + ` + }, // properties used in a template expression { @@ -625,6 +656,20 @@ tester.run('no-unused-properties', rule, { ` }, + // a property used in v-on as $props expression + { + filename: 'test.vue', + code: ` + + + ` + }, // data used in a script expression { @@ -2167,6 +2212,38 @@ tester.run('no-unused-properties', rule, { {{ foo }} ` + }, + + // props.prop in template + { + filename: 'test.vue', + code: ` + + ` + }, + { + filename: 'test.vue', + code: ` + + ` + }, + { + code: ` + + `, + ...getTypeScriptFixtureTestOptions() } ], invalid: [ @@ -3895,6 +3972,41 @@ tester.run('no-unused-properties', rule, { line: 6 } ] + }, + + // props.prop in template + { + filename: 'test.vue', + code: ` + + `, + errors: ["'b' of property found, but never used."] + }, + { + filename: 'test.vue', + code: ` + + `, + errors: ["'b' of property found, but never used."] + }, + { + code: ` + + `, + errors: ["'baz' of property found, but never used."], + ...getTypeScriptFixtureTestOptions() } ] }) From 7018649ea2fe1a5cae93139897d6b730e7e098e7 Mon Sep 17 00:00:00 2001 From: ItMaga Date: Sun, 24 Mar 2024 01:55:19 +0300 Subject: [PATCH 2/3] chore: remove comments --- tests/lib/rules/no-unused-properties.js | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/tests/lib/rules/no-unused-properties.js b/tests/lib/rules/no-unused-properties.js index 1236a6911..19b3351e7 100644 --- a/tests/lib/rules/no-unused-properties.js +++ b/tests/lib/rules/no-unused-properties.js @@ -51,23 +51,6 @@ const unreferencedOptions = { ] } -// tester.run('no-unused-properties', rule, { -// valid: [ -// { -// filename: 'test.vue', -// code: ` -// -// ` -// } -// ], -// invalid: [] -// }) -// return - tester.run('no-unused-properties', rule, { valid: [ { From 34df4e6774cbf0a15c0de2fced375d48b1910cbb Mon Sep 17 00:00:00 2001 From: ItMaga Date: Wed, 3 Apr 2024 19:37:36 +0300 Subject: [PATCH 3/3] feat: add test cases --- tests/lib/rules/no-unused-properties.js | 26 +++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/tests/lib/rules/no-unused-properties.js b/tests/lib/rules/no-unused-properties.js index 19b3351e7..eee8b6a51 100644 --- a/tests/lib/rules/no-unused-properties.js +++ b/tests/lib/rules/no-unused-properties.js @@ -2198,6 +2198,16 @@ tester.run('no-unused-properties', rule, { }, // props.prop in template + { + filename: 'test.vue', + code: ` + + ` + }, { filename: 'test.vue', code: ` @@ -3957,6 +3967,22 @@ tester.run('no-unused-properties', rule, { ] }, + // a property used as a template $props member expression + { + filename: 'test.vue', + code: ` + + + `, + errors: ["'bar' of property found, but never used."] + }, + // props.prop in template { filename: 'test.vue',