Skip to content

Commit 138380d

Browse files
authored
fix: stop reporting child properties in no-unused-props when the parent object itself is used (#1143)
1 parent 43f0ac3 commit 138380d

File tree

5 files changed

+83
-7
lines changed

5 files changed

+83
-7
lines changed

.changeset/floppy-symbols-sing.md

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'eslint-plugin-svelte': patch
3+
---
4+
5+
fix: stop reporting child properties in `no-unused-props` when the parent object itself is used

packages/eslint-plugin-svelte/src/rules/no-unused-props.ts

+31-7
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,12 @@ export default createRule('no-unused-props', {
156156

157157
const paths: PropertyPath[] = [];
158158
for (const reference of variable.references) {
159-
if ('identifier' in reference && reference.identifier.type === 'Identifier') {
159+
if (
160+
'identifier' in reference &&
161+
reference.identifier.type === 'Identifier' &&
162+
(reference.identifier.range[0] !== node.range[0] ||
163+
reference.identifier.range[1] !== node.range[1])
164+
) {
160165
const referencePath = getPropertyPath(reference.identifier);
161166
paths.push(referencePath);
162167
}
@@ -265,11 +270,17 @@ export default createRule('no-unused-props', {
265270
if (reportedProps.has(currentPathStr)) continue;
266271

267272
const propType = typeChecker.getTypeOfSymbol(prop);
268-
const isUsedInPath = usedPaths.some((path) => {
269-
const usedPath = path.join('.');
270-
return usedPath === currentPathStr || usedPath.startsWith(`${currentPathStr}.`);
273+
274+
const joinedUsedPaths = usedPaths.map((path) => path.join('.'));
275+
const isUsedThisInPath = joinedUsedPaths.includes(currentPathStr);
276+
const isUsedInPath = joinedUsedPaths.some((path) => {
277+
return path.startsWith(`${currentPathStr}.`);
271278
});
272279

280+
if (isUsedThisInPath && !isUsedInPath) {
281+
continue;
282+
}
283+
273284
const isUsedInProps = usedProps.has(propName);
274285

275286
if (!isUsedInPath && !isUsedInProps) {
@@ -282,10 +293,11 @@ export default createRule('no-unused-props', {
282293
parent: parentPath.join('.')
283294
}
284295
});
296+
continue;
285297
}
286298

287-
const isUsedNested = usedPaths.some((path) => {
288-
return path.join('.').startsWith(`${currentPathStr}.`);
299+
const isUsedNested = joinedUsedPaths.some((path) => {
300+
return path.startsWith(`${currentPathStr}.`);
289301
});
290302

291303
if (isUsedNested || isUsedInProps) {
@@ -324,6 +336,18 @@ export default createRule('no-unused-props', {
324336
return usedProps.size === 0;
325337
}
326338

339+
function normalizeUsedPaths(paths: PropertyPath[]): PropertyPath[] {
340+
const normalized: PropertyPath[] = [];
341+
for (const path of paths.sort((a, b) => a.length - b.length)) {
342+
if (path.length === 0) continue;
343+
if (normalized.some((p) => p.every((part, idx) => part === path[idx]))) {
344+
continue;
345+
}
346+
normalized.push(path);
347+
}
348+
return normalized;
349+
}
350+
327351
return {
328352
'VariableDeclaration > VariableDeclarator': (node: TSESTree.VariableDeclarator) => {
329353
// Only check $props declarations
@@ -359,7 +383,7 @@ export default createRule('no-unused-props', {
359383

360384
checkUnusedProperties(
361385
propType,
362-
usedPaths,
386+
normalizeUsedPaths(usedPaths),
363387
usedProps,
364388
node.id,
365389
[],
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<script lang="ts">
2+
import GenericPopout from './GenericPopout.svelte';
3+
4+
let {
5+
position
6+
}: {
7+
position: {
8+
x: number;
9+
y: number;
10+
};
11+
} = $props();
12+
</script>
13+
14+
<GenericPopout {position}>Test</GenericPopout>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
<script lang="ts">
2+
import GenericPopout from './GenericPopout.svelte';
3+
4+
let {
5+
wrapper
6+
}: {
7+
wrapper: {
8+
position: {
9+
x: number;
10+
y: number;
11+
};
12+
};
13+
} = $props();
14+
</script>
15+
16+
<GenericPopout position={wrapper.position}>Test</GenericPopout>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
<script lang="ts">
2+
import GenericPopout from './GenericPopout.svelte';
3+
4+
let {
5+
wrapper
6+
}: {
7+
wrapper: {
8+
position: {
9+
x: number;
10+
y: number;
11+
};
12+
};
13+
} = $props();
14+
</script>
15+
16+
<GenericPopout x={wrapper.position.x}>Test</GenericPopout>
17+
<GenericPopout position={wrapper.position}>Test</GenericPopout>

0 commit comments

Comments
 (0)