diff --git a/.changeset/floppy-symbols-sing.md b/.changeset/floppy-symbols-sing.md new file mode 100644 index 000000000..11aa7c646 --- /dev/null +++ b/.changeset/floppy-symbols-sing.md @@ -0,0 +1,5 @@ +--- +'eslint-plugin-svelte': patch +--- + +fix: stop reporting child properties in `no-unused-props` when the parent object itself is used 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 84faa365e..5de3133c0 100644 --- a/packages/eslint-plugin-svelte/src/rules/no-unused-props.ts +++ b/packages/eslint-plugin-svelte/src/rules/no-unused-props.ts @@ -156,7 +156,12 @@ export default createRule('no-unused-props', { const paths: PropertyPath[] = []; for (const reference of variable.references) { - if ('identifier' in reference && reference.identifier.type === 'Identifier') { + if ( + 'identifier' in reference && + reference.identifier.type === 'Identifier' && + (reference.identifier.range[0] !== node.range[0] || + reference.identifier.range[1] !== node.range[1]) + ) { const referencePath = getPropertyPath(reference.identifier); paths.push(referencePath); } @@ -265,11 +270,17 @@ export default createRule('no-unused-props', { if (reportedProps.has(currentPathStr)) continue; const propType = typeChecker.getTypeOfSymbol(prop); - const isUsedInPath = usedPaths.some((path) => { - const usedPath = path.join('.'); - return usedPath === currentPathStr || usedPath.startsWith(`${currentPathStr}.`); + + const joinedUsedPaths = usedPaths.map((path) => path.join('.')); + const isUsedThisInPath = joinedUsedPaths.includes(currentPathStr); + const isUsedInPath = joinedUsedPaths.some((path) => { + return path.startsWith(`${currentPathStr}.`); }); + if (isUsedThisInPath && !isUsedInPath) { + continue; + } + const isUsedInProps = usedProps.has(propName); if (!isUsedInPath && !isUsedInProps) { @@ -282,10 +293,11 @@ export default createRule('no-unused-props', { parent: parentPath.join('.') } }); + continue; } - const isUsedNested = usedPaths.some((path) => { - return path.join('.').startsWith(`${currentPathStr}.`); + const isUsedNested = joinedUsedPaths.some((path) => { + return path.startsWith(`${currentPathStr}.`); }); if (isUsedNested || isUsedInProps) { @@ -324,6 +336,18 @@ export default createRule('no-unused-props', { return usedProps.size === 0; } + function normalizeUsedPaths(paths: PropertyPath[]): PropertyPath[] { + const normalized: PropertyPath[] = []; + for (const path of paths.sort((a, b) => a.length - b.length)) { + if (path.length === 0) continue; + if (normalized.some((p) => p.every((part, idx) => part === path[idx]))) { + continue; + } + normalized.push(path); + } + return normalized; + } + return { 'VariableDeclaration > VariableDeclarator': (node: TSESTree.VariableDeclarator) => { // Only check $props declarations @@ -359,7 +383,7 @@ export default createRule('no-unused-props', { checkUnusedProperties( propType, - usedPaths, + normalizeUsedPaths(usedPaths), usedProps, node.id, [], diff --git a/packages/eslint-plugin-svelte/tests/fixtures/rules/no-unused-props/valid/nested-props2-input.svelte b/packages/eslint-plugin-svelte/tests/fixtures/rules/no-unused-props/valid/nested-props2-input.svelte new file mode 100644 index 000000000..3fb8790fd --- /dev/null +++ b/packages/eslint-plugin-svelte/tests/fixtures/rules/no-unused-props/valid/nested-props2-input.svelte @@ -0,0 +1,14 @@ + + +Test diff --git a/packages/eslint-plugin-svelte/tests/fixtures/rules/no-unused-props/valid/nested-props3-input.svelte b/packages/eslint-plugin-svelte/tests/fixtures/rules/no-unused-props/valid/nested-props3-input.svelte new file mode 100644 index 000000000..7090054f8 --- /dev/null +++ b/packages/eslint-plugin-svelte/tests/fixtures/rules/no-unused-props/valid/nested-props3-input.svelte @@ -0,0 +1,16 @@ + + +Test diff --git a/packages/eslint-plugin-svelte/tests/fixtures/rules/no-unused-props/valid/nested-props4-input.svelte b/packages/eslint-plugin-svelte/tests/fixtures/rules/no-unused-props/valid/nested-props4-input.svelte new file mode 100644 index 000000000..15bdb1277 --- /dev/null +++ b/packages/eslint-plugin-svelte/tests/fixtures/rules/no-unused-props/valid/nested-props4-input.svelte @@ -0,0 +1,17 @@ + + +Test +Test