From a41cf0a703e77e2e694ef9aaf439cb784076aeed Mon Sep 17 00:00:00 2001 From: baseballyama Date: Tue, 1 Apr 2025 01:44:39 +0900 Subject: [PATCH 1/2] fix(no-unused-props): handle alias props name properly --- .changeset/fifty-jeans-thank.md | 5 +++ .../src/rules/no-unused-props.ts | 32 +++++++++++++------ .../no-unused-props/valid/alias-input.svelte | 11 +++++++ 3 files changed, 39 insertions(+), 9 deletions(-) create mode 100644 .changeset/fifty-jeans-thank.md create mode 100644 packages/eslint-plugin-svelte/tests/fixtures/rules/no-unused-props/valid/alias-input.svelte diff --git a/.changeset/fifty-jeans-thank.md b/.changeset/fifty-jeans-thank.md new file mode 100644 index 000000000..77ea67965 --- /dev/null +++ b/.changeset/fifty-jeans-thank.md @@ -0,0 +1,5 @@ +--- +'eslint-plugin-svelte': patch +--- + +fix(no-unused-props): handle alias props name properly diff --git a/packages/eslint-plugin-svelte/src/rules/no-unused-props.ts b/packages/eslint-plugin-svelte/src/rules/no-unused-props.ts index 61b60e99e..abcb104db 100644 --- a/packages/eslint-plugin-svelte/src/rules/no-unused-props.ts +++ b/packages/eslint-plugin-svelte/src/rules/no-unused-props.ts @@ -6,6 +6,7 @@ import { findVariable } from '../utils/ast-utils.js'; import { toRegExp } from '../utils/regexp.js'; type PropertyPathArray = string[]; +type DeclaredPropertyNames = Set<{ originalName: string; aliasName: string }>; let isRemovedWarningShown = false; @@ -182,16 +183,27 @@ export default createRule('no-unused-props', { return sourceFile.fileName.includes('node_modules/typescript/lib/'); } - function getUsedPropertyNamesFromPattern(pattern: TSESTree.ObjectPattern): Set { - const usedProps = new Set(); + function getUsedPropertyNamesFromPattern( + pattern: TSESTree.ObjectPattern + ): DeclaredPropertyNames { + const usedProps: DeclaredPropertyNames = new Set(); for (const prop of pattern.properties) { - if (prop.type === 'Property' && prop.key.type === 'Identifier') { - usedProps.add(prop.key.name); + if (prop.type === 'Property') { + if (prop.key.type === 'Identifier') { + usedProps.add({ originalName: prop.key.name, aliasName: prop.key.name }); + } else if ( + prop.key.type === 'Literal' && + typeof prop.key.value === 'string' && + prop.value.type === 'Identifier' + ) { + usedProps.add({ originalName: prop.key.value, aliasName: prop.value.name }); + } } else if (prop.type === 'RestElement') { // If there's a rest element, all properties are potentially used return new Set(); } } + return usedProps; } @@ -229,7 +241,7 @@ export default createRule('no-unused-props', { }: { propsType: ts.Type; usedPropertyPaths: string[]; - declaredPropertyNames: Set; + declaredPropertyNames: DeclaredPropertyNames; reportNode: TSESTree.Node; parentPath: string[]; checkedPropsTypes: Set; @@ -287,7 +299,9 @@ export default createRule('no-unused-props', { continue; } - const isUsedInProps = declaredPropertyNames.has(propName); + const isUsedInProps = Array.from(declaredPropertyNames).some((p) => { + return p.originalName === propName; + }); if (!isUsedInPath && !isUsedInProps) { reportedPropertyPaths.add(currentPathStr); @@ -338,8 +352,8 @@ export default createRule('no-unused-props', { * Returns true if the destructuring pattern includes a rest element, * which means all remaining properties are potentially used. */ - function hasRestElement(usedProps: Set): boolean { - return usedProps.size === 0; + function hasRestElement(declaredPropertyNames: DeclaredPropertyNames): boolean { + return declaredPropertyNames.size === 0; } function normalizeUsedPaths(paths: PropertyPathArray[]): PropertyPathArray[] { @@ -370,7 +384,7 @@ export default createRule('no-unused-props', { const propsType = typeChecker.getTypeFromTypeNode(tsNode.type); let usedPropertyPathsArray: PropertyPathArray[] = []; - let declaredPropertyNames = new Set(); + let declaredPropertyNames: DeclaredPropertyNames = new Set(); if (node.id.type === 'ObjectPattern') { declaredPropertyNames = getUsedPropertyNamesFromPattern(node.id); diff --git a/packages/eslint-plugin-svelte/tests/fixtures/rules/no-unused-props/valid/alias-input.svelte b/packages/eslint-plugin-svelte/tests/fixtures/rules/no-unused-props/valid/alias-input.svelte new file mode 100644 index 000000000..857e6534d --- /dev/null +++ b/packages/eslint-plugin-svelte/tests/fixtures/rules/no-unused-props/valid/alias-input.svelte @@ -0,0 +1,11 @@ + + +

{test}

+
svelte/no-unused-props does not always respect aliases
From c8c404a361433f03e3ec4e4c8be6669540798c3c Mon Sep 17 00:00:00 2001 From: baseballyama Date: Tue, 1 Apr 2025 22:05:03 +0900 Subject: [PATCH 2/2] add test --- .../rules/no-unused-props/invalid/alias-errors.yaml | 4 ++++ .../rules/no-unused-props/invalid/alias-input.svelte | 10 ++++++++++ 2 files changed, 14 insertions(+) create mode 100644 packages/eslint-plugin-svelte/tests/fixtures/rules/no-unused-props/invalid/alias-errors.yaml create mode 100644 packages/eslint-plugin-svelte/tests/fixtures/rules/no-unused-props/invalid/alias-input.svelte diff --git a/packages/eslint-plugin-svelte/tests/fixtures/rules/no-unused-props/invalid/alias-errors.yaml b/packages/eslint-plugin-svelte/tests/fixtures/rules/no-unused-props/invalid/alias-errors.yaml new file mode 100644 index 000000000..89c1a84af --- /dev/null +++ b/packages/eslint-plugin-svelte/tests/fixtures/rules/no-unused-props/invalid/alias-errors.yaml @@ -0,0 +1,4 @@ +- message: "'test' is an unused Props property." + line: 7 + column: 8 + suggestions: null diff --git a/packages/eslint-plugin-svelte/tests/fixtures/rules/no-unused-props/invalid/alias-input.svelte b/packages/eslint-plugin-svelte/tests/fixtures/rules/no-unused-props/invalid/alias-input.svelte new file mode 100644 index 000000000..59f23192b --- /dev/null +++ b/packages/eslint-plugin-svelte/tests/fixtures/rules/no-unused-props/invalid/alias-input.svelte @@ -0,0 +1,10 @@ + + +{foo}