Repository: sveltejs/eslint-plugin-svelte
Pull request #1163 (2025-03-28 17:51:09)

feat: add fixer for `derived-has-same-inputs-outputs`
Simply replaces the param names with the correct ones since we're already aware of what they should be.

Depends on #1162 

changeset-bot[bot]: ###  ⚠️  No Changeset found

Latest commit: 397e365276bd4c47ff2931d4dab2de4633f38f14

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. **If these changes should result in a version bump, you need to add a changeset.**

<details><summary>This PR includes no changesets</summary>

  When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

</details>

[Click here to learn what changesets are, and how to add one](https://github.com/changesets/changesets/blob/main/docs/adding-a-changeset.md).

[Click here if you're a maintainer who wants to add a changeset to this PR](https://github.com/43081j/eslint-plugin-svelte/new/fixer-derived-inout?filename=.changeset/sour-planes-invent.md&value=---%0A%22eslint-plugin-svelte%22%3A%20patch%0A---%0A%0Afeat%3A%20add%20fixer%20for%20%60derived-has-same-inputs-outputs%60%0A)


github-actions[bot]: <!-- posted by pkg.pr.new-comment.mjs -->

## Try the Instant Preview in Online Playground

[ESLint Online Playground](https://eslint-online-playground.netlify.app/?overrideDeps=%7B%22eslint-plugin-svelte%22%3A%22https%3A%2F%2Fpkg.pr.new%2Feslint-plugin-svelte%401163%22%7D#eslint-plugin-svelte%20with%20typescript)

## Install the Instant Preview to Your Local

```
npm i https://pkg.pr.new/eslint-plugin-svelte@1163
```

## Published Instant Preview Packages:

- eslint-plugin-svelte: https://pkg.pr.new/eslint-plugin-svelte@1163

[View Commit](https://github.com/sveltejs/eslint-plugin-svelte/commit/397e365276bd4c47ff2931d4dab2de4633f38f14)
baseballyama: @43081j 

According to the official ESLint documentation, the following is stated about fixers.

> Best practices for fixes:
> Avoid any fixes that could change the runtime behavior of code and cause it to stop working.
> Make fixes as small as possible. Fixes that are unnecessarily large could conflict with other fixes, and prevent them from being applied.

https://eslint.org/docs/latest/extend/custom-rules#applying-fixes

In addition to this PR, it would also require changes to the places where the argument is used. In that case, we would need to check for any variable name conflicts, otherwise it would violate "Avoid any fixes that could change the runtime behavior of code and cause it to stop working.".

Therefore, implementing this as a fixer doesn’t seem appropriate. Would it be better to make it a suggestion at the very least?


43081j: similar to the other PR, i am aware of the best practices.

i just overlooked updating references to the parameters since we have no existing tests for those cases

if this becomes more complex than expected, it can be a suggestion.
43081j: ok @baseballyama i've updated this to rename references of the variable in the current function scope

if you want me to change it into a suggestion once you've re-reviewed, let me know and ill update
baseballyama: Can you add a changeset?
baseballyama: > it shouldn't as the suggestions apply one at a time. this is listing the output of each individual suggestion

Sorry! That's why I deleted the comment but you replied too fast😅

Patch:
diff --git a/.changeset/neat-dots-grin.md b/.changeset/neat-dots-grin.md
new file mode 100644
index 0000000..9a77b50
--- /dev/null
+++ b/.changeset/neat-dots-grin.md
@@ -0,0 +1,5 @@
+---
+'eslint-plugin-svelte': minor
+---
+
+Adds a suggestion to the `derived-has-same-inputs-outputs` rule which renames the outputs.
diff --git a/README.md b/README.md
index 59a2ec4..3308ebf 100644
--- a/README.md
+++ b/README.md
@@ -323,7 +323,7 @@ These rules relate to style guidelines, and are therefore quite subjective:
 | Rule ID | Description |    |
 |:--------|:------------|:---|
 | [svelte/consistent-selector-style](https://sveltejs.github.io/eslint-plugin-svelte/rules/consistent-selector-style/) | enforce a consistent style for CSS selectors |  |
-| [svelte/derived-has-same-inputs-outputs](https://sveltejs.github.io/eslint-plugin-svelte/rules/derived-has-same-inputs-outputs/) | derived store should use same variable names between values and callback |  |
+| [svelte/derived-has-same-inputs-outputs](https://sveltejs.github.io/eslint-plugin-svelte/rules/derived-has-same-inputs-outputs/) | derived store should use same variable names between values and callback | :bulb: |
 | [svelte/first-attribute-linebreak](https://sveltejs.github.io/eslint-plugin-svelte/rules/first-attribute-linebreak/) | enforce the location of first attribute | :wrench: |
 | [svelte/html-closing-bracket-new-line](https://sveltejs.github.io/eslint-plugin-svelte/rules/html-closing-bracket-new-line/) | Require or disallow a line break before tag's closing brackets | :wrench: |
 | [svelte/html-closing-bracket-spacing](https://sveltejs.github.io/eslint-plugin-svelte/rules/html-closing-bracket-spacing/) | require or disallow a space before tag's closing brackets | :wrench: |
diff --git a/docs/rules.md b/docs/rules.md
index f7d28ab..5a47dde 100644
--- a/docs/rules.md
+++ b/docs/rules.md
@@ -80,7 +80,7 @@ These rules relate to style guidelines, and are therefore quite subjective:
 | Rule ID                                                                                                  | Description                                                                        |          |
 | :------------------------------------------------------------------------------------------------------- | :--------------------------------------------------------------------------------- | :------- |
 | [svelte/consistent-selector-style](./rules/consistent-selector-style.md)                                 | enforce a consistent style for CSS selectors                                       |          |
-| [svelte/derived-has-same-inputs-outputs](./rules/derived-has-same-inputs-outputs.md)                     | derived store should use same variable names between values and callback           |          |
+| [svelte/derived-has-same-inputs-outputs](./rules/derived-has-same-inputs-outputs.md)                     | derived store should use same variable names between values and callback           | :bulb:   |
 | [svelte/first-attribute-linebreak](./rules/first-attribute-linebreak.md)                                 | enforce the location of first attribute                                            | :wrench: |
 | [svelte/html-closing-bracket-new-line](./rules/html-closing-bracket-new-line.md)                         | Require or disallow a line break before tag's closing brackets                     | :wrench: |
 | [svelte/html-closing-bracket-spacing](./rules/html-closing-bracket-spacing.md)                           | require or disallow a space before tag's closing brackets                          | :wrench: |
diff --git a/docs/rules/derived-has-same-inputs-outputs.md b/docs/rules/derived-has-same-inputs-outputs.md
index b059bc6..f8c6568 100644
--- a/docs/rules/derived-has-same-inputs-outputs.md
+++ b/docs/rules/derived-has-same-inputs-outputs.md
@@ -10,6 +10,8 @@ since: 'v2.8.0'
 
 > derived store should use same variable names between values and callback
 
+- :bulb: Some problems reported by this rule are manually fixable by editor [suggestions](https://eslint.org/docs/developer-guide/working-with-rules#providing-suggestions).
+
 ## :book: Rule Details
 
 This rule reports where variable names and callback function's argument names are different.
diff --git a/packages/eslint-plugin-svelte/src/rules/derived-has-same-inputs-outputs.ts b/packages/eslint-plugin-svelte/src/rules/derived-has-same-inputs-outputs.ts
index 3ea90c2..30f86aa 100644
--- a/packages/eslint-plugin-svelte/src/rules/derived-has-same-inputs-outputs.ts
+++ b/packages/eslint-plugin-svelte/src/rules/derived-has-same-inputs-outputs.ts
@@ -1,7 +1,48 @@
 import type { TSESTree } from '@typescript-eslint/types';
+import type { Variable } from '@typescript-eslint/scope-manager';
 import { createRule } from '../utils/index.js';
-import type { RuleContext } from '../types.js';
+import type { RuleContext, RuleFixer } from '../types.js';
 import { extractStoreReferences } from './reference-helpers/svelte-store.js';
+import { getScope } from '../utils/ast-utils.js';
+
+function findVariableForName(
+	context: RuleContext,
+	node: TSESTree.Node,
+	name: string,
+	expectedName: string
+): { hasConflict: boolean; variable: Variable | null } {
+	const scope = getScope(context, node);
+	let variable: Variable | null = null;
+
+	for (const ref of scope.references) {
+		if (ref.identifier.name === expectedName) {
+			return { hasConflict: true, variable: null };
+		}
+	}
+
+	for (const v of scope.variables) {
+		if (v.name === expectedName) {
+			return { hasConflict: true, variable: null };
+		}
+		if (v.name === name) {
+			variable = v;
+		}
+	}
+
+	return { hasConflict: false, variable };
+}
+
+function createFixer(node: TSESTree.Node, variable: Variable | null, name: string) {
+	return function* fix(fixer: RuleFixer) {
+		yield fixer.replaceText(node, name);
+
+		if (variable) {
+			for (const ref of variable.references) {
+				yield fixer.replaceText(ref.identifier, name);
+			}
+		}
+	};
+}
 
 export default createRule('derived-has-same-inputs-outputs', {
 	meta: {
@@ -11,9 +52,11 @@ export default createRule('derived-has-same-inputs-outputs', {
 			recommended: false,
 			conflictWithPrettier: false
 		},
+		hasSuggestions: true,
 		schema: [],
 		messages: {
-			unexpected: "The argument name should be '{{name}}'."
+			unexpected: "The argument name should be '{{name}}'.",
+			renameParam: 'Rename the parameter from {{oldName}} to {{newName}}.'
 		},
 		type: 'suggestion'
 	},
@@ -49,11 +92,27 @@ export default createRule('derived-has-same-inputs-outputs', {
 			if (fnParam.type !== 'Identifier') return;
 			const expectedName = `$${args.name}`;
 			if (expectedName !== fnParam.name) {
+				const { hasConflict, variable } = findVariableForName(
+					context,
+					fn.body,
+					fnParam.name,
+					expectedName
+				);
+
 				context.report({
 					node: fn,
 					loc: fnParam.loc,
 					messageId: 'unexpected',
-					data: { name: expectedName }
+					data: { name: expectedName },
+					suggest: hasConflict
+						? undefined
+						: [
+								{
+									messageId: 'renameParam',
+									data: { oldName: fnParam.name, newName: expectedName },
+									fix: createFixer(fnParam, variable, expectedName)
+								}
+							]
 				});
 			}
 		}
@@ -77,11 +136,27 @@ export default createRule('derived-has-same-inputs-outputs', {
 				if (element && element.type === 'Identifier' && argName) {
 					const expectedName = `$${argName}`;
 					if (expectedName !== element.name) {
+						const { hasConflict, variable } = findVariableForName(
+							context,
+							fn.body,
+							element.name,
+							expectedName
+						);
+
 						context.report({
 							node: fn,
 							loc: element.loc,
 							messageId: 'unexpected',
-							data: { name: expectedName }
+							data: { name: expectedName },
+							suggest: hasConflict
+								? undefined
+								: [
+										{
+											messageId: 'renameParam',
+											data: { oldName: element.name, newName: expectedName },
+											fix: createFixer(element, variable, expectedName)
+										}
+									]
 						});
 					}
 				}


Test patch:
diff --git a/packages/eslint-plugin-svelte/tests/fixtures/rules/derived-has-same-inputs-outputs/invalid/test01-errors.yaml b/packages/eslint-plugin-svelte/tests/fixtures/rules/derived-has-same-inputs-outputs/invalid/test01-errors.yaml
index 9ce09c0..2107d30 100644
--- a/packages/eslint-plugin-svelte/tests/fixtures/rules/derived-has-same-inputs-outputs/invalid/test01-errors.yaml
+++ b/packages/eslint-plugin-svelte/tests/fixtures/rules/derived-has-same-inputs-outputs/invalid/test01-errors.yaml
@@ -1,32 +1,1044 @@
 - message: The argument name should be '$a'.
   line: 3
   column: 13
-  suggestions: null
+  suggestions:
+    - desc: Rename the parameter from b to $a.
+      messageId: renameParam
+      output: |
+        import { derived } from 'svelte/store';
+
+        derived(a, ($a) => {
+        	/** do nothing */
+        });
+        derived(c, (d, set) => {
+        	/** do nothing */
+        });
+        derived([e, f], ([g, h]) => {
+        	/** do nothing */
+        });
+        derived([i, j], ([k, l], set) => {
+        	/** do nothing */
+        });
+        derived([null, l], ([$m, $n]) => {
+        	/** do nothing */
+        });
+        derived([o, null], ([$p, $q]) => {
+        	/** do nothing */
+        });
+        derived(a, (b) => {
+        	doSomethingWith(b);
+
+        	somethingWithACallback(() => {
+        		b;
+        	});
+        });
+        derived(a, (b) => {
+        	b;
+
+        	somethingWithACallback(() => {
+        		// purposely shadow the var, this should not be updated
+        		const b = 303;
+        		b;
+        	});
+        });
+        derived([e, f], ([g, h]) => {
+        	g;
+        	h;
+
+        	somethingWithACallback(() => {
+        		g;
+        		h;
+        	});
+        });
+        derived([e, f], ([g, h]) => {
+        	g;
+        	h;
+
+        	somethingWithACallback(() => {
+        		const g = 303;
+        		const h = 808;
+        		g;
+        		h;
+        	});
+        });
+        derived(a, (b) => {
+        	// cause a conflict in names so the suggestion can't work
+        	const $a = 303;
+        	$a;
+        });
+        somethingWithACallback(() => {
+        	const $a = 303;
+        	derived(a, (b) => {
+        		$a;
+        	});
+        });
 - message: The argument name should be '$c'.
   line: 6
   column: 13
-  suggestions: null
+  suggestions:
+    - desc: Rename the parameter from d to $c.
+      messageId: renameParam
+      output: |
+        import { derived } from 'svelte/store';
+
+        derived(a, (b) => {
+        	/** do nothing */
+        });
+        derived(c, ($c, set) => {
+        	/** do nothing */
+        });
+        derived([e, f], ([g, h]) => {
+        	/** do nothing */
+        });
+        derived([i, j], ([k, l], set) => {
+        	/** do nothing */
+        });
+        derived([null, l], ([$m, $n]) => {
+        	/** do nothing */
+        });
+        derived([o, null], ([$p, $q]) => {
+        	/** do nothing */
+        });
+        derived(a, (b) => {
+        	doSomethingWith(b);
+
+        	somethingWithACallback(() => {
+        		b;
+        	});
+        });
+        derived(a, (b) => {
+        	b;
+
+        	somethingWithACallback(() => {
+        		// purposely shadow the var, this should not be updated
+        		const b = 303;
+        		b;
+        	});
+        });
+        derived([e, f], ([g, h]) => {
+        	g;
+        	h;
+
+        	somethingWithACallback(() => {
+        		g;
+        		h;
+        	});
+        });
+        derived([e, f], ([g, h]) => {
+        	g;
+        	h;
+
+        	somethingWithACallback(() => {
+        		const g = 303;
+        		const h = 808;
+        		g;
+        		h;
+        	});
+        });
+        derived(a, (b) => {
+        	// cause a conflict in names so the suggestion can't work
+        	const $a = 303;
+        	$a;
+        });
+        somethingWithACallback(() => {
+        	const $a = 303;
+        	derived(a, (b) => {
+        		$a;
+        	});
+        });
 - message: The argument name should be '$e'.
   line: 9
   column: 19
-  suggestions: null
+  suggestions:
+    - desc: Rename the parameter from g to $e.
+      messageId: renameParam
+      output: |
+        import { derived } from 'svelte/store';
+
+        derived(a, (b) => {
+        	/** do nothing */
+        });
+        derived(c, (d, set) => {
+        	/** do nothing */
+        });
+        derived([e, f], ([$e, h]) => {
+        	/** do nothing */
+        });
+        derived([i, j], ([k, l], set) => {
+        	/** do nothing */
+        });
+        derived([null, l], ([$m, $n]) => {
+        	/** do nothing */
+        });
+        derived([o, null], ([$p, $q]) => {
+        	/** do nothing */
+        });
+        derived(a, (b) => {
+        	doSomethingWith(b);
+
+        	somethingWithACallback(() => {
+        		b;
+        	});
+        });
+        derived(a, (b) => {
+        	b;
+
+        	somethingWithACallback(() => {
+        		// purposely shadow the var, this should not be updated
+        		const b = 303;
+        		b;
+        	});
+        });
+        derived([e, f], ([g, h]) => {
+        	g;
+        	h;
+
+        	somethingWithACallback(() => {
+        		g;
+        		h;
+        	});
+        });
+        derived([e, f], ([g, h]) => {
+        	g;
+        	h;
+
+        	somethingWithACallback(() => {
+        		const g = 303;
+        		const h = 808;
+        		g;
+        		h;
+        	});
+        });
+        derived(a, (b) => {
+        	// cause a conflict in names so the suggestion can't work
+        	const $a = 303;
+        	$a;
+        });
+        somethingWithACallback(() => {
+        	const $a = 303;
+        	derived(a, (b) => {
+        		$a;
+        	});
+        });
 - message: The argument name should be '$f'.
   line: 9
   column: 22
-  suggestions: null
+  suggestions:
+    - desc: Rename the parameter from h to $f.
+      messageId: renameParam
+      output: |
+        import { derived } from 'svelte/store';
+
+        derived(a, (b) => {
+        	/** do nothing */
+        });
+        derived(c, (d, set) => {
+        	/** do nothing */
+        });
+        derived([e, f], ([g, $f]) => {
+        	/** do nothing */
+        });
+        derived([i, j], ([k, l], set) => {
+        	/** do nothing */
+        });
+        derived([null, l], ([$m, $n]) => {
+        	/** do nothing */
+        });
+        derived([o, null], ([$p, $q]) => {
+        	/** do nothing */
+        });
+        derived(a, (b) => {
+        	doSomethingWith(b);
+
+        	somethingWithACallback(() => {
+        		b;
+        	});
+        });
+        derived(a, (b) => {
+        	b;
+
+        	somethingWithACallback(() => {
+        		// purposely shadow the var, this should not be updated
+        		const b = 303;
+        		b;
+        	});
+        });
+        derived([e, f], ([g, h]) => {
+        	g;
+        	h;
+
+        	somethingWithACallback(() => {
+        		g;
+        		h;
+        	});
+        });
+        derived([e, f], ([g, h]) => {
+        	g;
+        	h;
+
+        	somethingWithACallback(() => {
+        		const g = 303;
+        		const h = 808;
+        		g;
+        		h;
+        	});
+        });
+        derived(a, (b) => {
+        	// cause a conflict in names so the suggestion can't work
+        	const $a = 303;
+        	$a;
+        });
+        somethingWithACallback(() => {
+        	const $a = 303;
+        	derived(a, (b) => {
+        		$a;
+        	});
+        });
 - message: The argument name should be '$i'.
   line: 12
   column: 19
-  suggestions: null
+  suggestions:
+    - desc: Rename the parameter from k to $i.
+      messageId: renameParam
+      output: |
+        import { derived } from 'svelte/store';
+
+        derived(a, (b) => {
+        	/** do nothing */
+        });
+        derived(c, (d, set) => {
+        	/** do nothing */
+        });
+        derived([e, f], ([g, h]) => {
+        	/** do nothing */
+        });
+        derived([i, j], ([$i, l], set) => {
+        	/** do nothing */
+        });
+        derived([null, l], ([$m, $n]) => {
+        	/** do nothing */
+        });
+        derived([o, null], ([$p, $q]) => {
+        	/** do nothing */
+        });
+        derived(a, (b) => {
+        	doSomethingWith(b);
+
+        	somethingWithACallback(() => {
+        		b;
+        	});
+        });
+        derived(a, (b) => {
+        	b;
+
+        	somethingWithACallback(() => {
+        		// purposely shadow the var, this should not be updated
+        		const b = 303;
+        		b;
+        	});
+        });
+        derived([e, f], ([g, h]) => {
+        	g;
+        	h;
+
+        	somethingWithACallback(() => {
+        		g;
+        		h;
+        	});
+        });
+        derived([e, f], ([g, h]) => {
+        	g;
+        	h;
+
+        	somethingWithACallback(() => {
+        		const g = 303;
+        		const h = 808;
+        		g;
+        		h;
+        	});
+        });
+        derived(a, (b) => {
+        	// cause a conflict in names so the suggestion can't work
+        	const $a = 303;
+        	$a;
+        });
+        somethingWithACallback(() => {
+        	const $a = 303;
+        	derived(a, (b) => {
+        		$a;
+        	});
+        });
 - message: The argument name should be '$j'.
   line: 12
   column: 22
-  suggestions: null
+  suggestions:
+    - desc: Rename the parameter from l to $j.
+      messageId: renameParam
+      output: |
+        import { derived } from 'svelte/store';
+
+        derived(a, (b) => {
+        	/** do nothing */
+        });
+        derived(c, (d, set) => {
+        	/** do nothing */
+        });
+        derived([e, f], ([g, h]) => {
+        	/** do nothing */
+        });
+        derived([i, j], ([k, $j], set) => {
+        	/** do nothing */
+        });
+        derived([null, l], ([$m, $n]) => {
+        	/** do nothing */
+        });
+        derived([o, null], ([$p, $q]) => {
+        	/** do nothing */
+        });
+        derived(a, (b) => {
+        	doSomethingWith(b);
+
+        	somethingWithACallback(() => {
+        		b;
+        	});
+        });
+        derived(a, (b) => {
+        	b;
+
+        	somethingWithACallback(() => {
+        		// purposely shadow the var, this should not be updated
+        		const b = 303;
+        		b;
+        	});
+        });
+        derived([e, f], ([g, h]) => {
+        	g;
+        	h;
+
+        	somethingWithACallback(() => {
+        		g;
+        		h;
+        	});
+        });
+        derived([e, f], ([g, h]) => {
+        	g;
+        	h;
+
+        	somethingWithACallback(() => {
+        		const g = 303;
+        		const h = 808;
+        		g;
+        		h;
+        	});
+        });
+        derived(a, (b) => {
+        	// cause a conflict in names so the suggestion can't work
+        	const $a = 303;
+        	$a;
+        });
+        somethingWithACallback(() => {
+        	const $a = 303;
+        	derived(a, (b) => {
+        		$a;
+        	});
+        });
 - message: The argument name should be '$l'.
   line: 15
   column: 26
-  suggestions: null
+  suggestions:
+    - desc: Rename the parameter from $n to $l.
+      messageId: renameParam
+      output: |
+        import { derived } from 'svelte/store';
+
+        derived(a, (b) => {
+        	/** do nothing */
+        });
+        derived(c, (d, set) => {
+        	/** do nothing */
+        });
+        derived([e, f], ([g, h]) => {
+        	/** do nothing */
+        });
+        derived([i, j], ([k, l], set) => {
+        	/** do nothing */
+        });
+        derived([null, l], ([$m, $l]) => {
+        	/** do nothing */
+        });
+        derived([o, null], ([$p, $q]) => {
+        	/** do nothing */
+        });
+        derived(a, (b) => {
+        	doSomethingWith(b);
+
+        	somethingWithACallback(() => {
+        		b;
+        	});
+        });
+        derived(a, (b) => {
+        	b;
+
+        	somethingWithACallback(() => {
+        		// purposely shadow the var, this should not be updated
+        		const b = 303;
+        		b;
+        	});
+        });
+        derived([e, f], ([g, h]) => {
+        	g;
+        	h;
+
+        	somethingWithACallback(() => {
+        		g;
+        		h;
+        	});
+        });
+        derived([e, f], ([g, h]) => {
+        	g;
+        	h;
+
+        	somethingWithACallback(() => {
+        		const g = 303;
+        		const h = 808;
+        		g;
+        		h;
+        	});
+        });
+        derived(a, (b) => {
+        	// cause a conflict in names so the suggestion can't work
+        	const $a = 303;
+        	$a;
+        });
+        somethingWithACallback(() => {
+        	const $a = 303;
+        	derived(a, (b) => {
+        		$a;
+        	});
+        });
 - message: The argument name should be '$o'.
   line: 18
   column: 22
+  suggestions:
+    - desc: Rename the parameter from $p to $o.
+      messageId: renameParam
+      output: |
+        import { derived } from 'svelte/store';
+
+        derived(a, (b) => {
+        	/** do nothing */
+        });
+        derived(c, (d, set) => {
+        	/** do nothing */
+        });
+        derived([e, f], ([g, h]) => {
+        	/** do nothing */
+        });
+        derived([i, j], ([k, l], set) => {
+        	/** do nothing */
+        });
+        derived([null, l], ([$m, $n]) => {
+        	/** do nothing */
+        });
+        derived([o, null], ([$o, $q]) => {
+        	/** do nothing */
+        });
+        derived(a, (b) => {
+        	doSomethingWith(b);
+
+        	somethingWithACallback(() => {
+        		b;
+        	});
+        });
+        derived(a, (b) => {
+        	b;
+
+        	somethingWithACallback(() => {
+        		// purposely shadow the var, this should not be updated
+        		const b = 303;
+        		b;
+        	});
+        });
+        derived([e, f], ([g, h]) => {
+        	g;
+        	h;
+
+        	somethingWithACallback(() => {
+        		g;
+        		h;
+        	});
+        });
+        derived([e, f], ([g, h]) => {
+        	g;
+        	h;
+
+        	somethingWithACallback(() => {
+        		const g = 303;
+        		const h = 808;
+        		g;
+        		h;
+        	});
+        });
+        derived(a, (b) => {
+        	// cause a conflict in names so the suggestion can't work
+        	const $a = 303;
+        	$a;
+        });
+        somethingWithACallback(() => {
+        	const $a = 303;
+        	derived(a, (b) => {
+        		$a;
+        	});
+        });
+- message: The argument name should be '$a'.
+  line: 21
+  column: 13
+  suggestions:
+    - desc: Rename the parameter from b to $a.
+      messageId: renameParam
+      output: |
+        import { derived } from 'svelte/store';
+
+        derived(a, (b) => {
+        	/** do nothing */
+        });
+        derived(c, (d, set) => {
+        	/** do nothing */
+        });
+        derived([e, f], ([g, h]) => {
+        	/** do nothing */
+        });
+        derived([i, j], ([k, l], set) => {
+        	/** do nothing */
+        });
+        derived([null, l], ([$m, $n]) => {
+        	/** do nothing */
+        });
+        derived([o, null], ([$p, $q]) => {
+        	/** do nothing */
+        });
+        derived(a, ($a) => {
+        	doSomethingWith($a);
+
+        	somethingWithACallback(() => {
+        		$a;
+        	});
+        });
+        derived(a, (b) => {
+        	b;
+
+        	somethingWithACallback(() => {
+        		// purposely shadow the var, this should not be updated
+        		const b = 303;
+        		b;
+        	});
+        });
+        derived([e, f], ([g, h]) => {
+        	g;
+        	h;
+
+        	somethingWithACallback(() => {
+        		g;
+        		h;
+        	});
+        });
+        derived([e, f], ([g, h]) => {
+        	g;
+        	h;
+
+        	somethingWithACallback(() => {
+        		const g = 303;
+        		const h = 808;
+        		g;
+        		h;
+        	});
+        });
+        derived(a, (b) => {
+        	// cause a conflict in names so the suggestion can't work
+        	const $a = 303;
+        	$a;
+        });
+        somethingWithACallback(() => {
+        	const $a = 303;
+        	derived(a, (b) => {
+        		$a;
+        	});
+        });
+- message: The argument name should be '$a'.
+  line: 28
+  column: 13
+  suggestions:
+    - desc: Rename the parameter from b to $a.
+      messageId: renameParam
+      output: |
+        import { derived } from 'svelte/store';
+
+        derived(a, (b) => {
+        	/** do nothing */
+        });
+        derived(c, (d, set) => {
+        	/** do nothing */
+        });
+        derived([e, f], ([g, h]) => {
+        	/** do nothing */
+        });
+        derived([i, j], ([k, l], set) => {
+        	/** do nothing */
+        });
+        derived([null, l], ([$m, $n]) => {
+        	/** do nothing */
+        });
+        derived([o, null], ([$p, $q]) => {
+        	/** do nothing */
+        });
+        derived(a, (b) => {
+        	doSomethingWith(b);
+
+        	somethingWithACallback(() => {
+        		b;
+        	});
+        });
+        derived(a, ($a) => {
+        	$a;
+
+        	somethingWithACallback(() => {
+        		// purposely shadow the var, this should not be updated
+        		const b = 303;
+        		b;
+        	});
+        });
+        derived([e, f], ([g, h]) => {
+        	g;
+        	h;
+
+        	somethingWithACallback(() => {
+        		g;
+        		h;
+        	});
+        });
+        derived([e, f], ([g, h]) => {
+        	g;
+        	h;
+
+        	somethingWithACallback(() => {
+        		const g = 303;
+        		const h = 808;
+        		g;
+        		h;
+        	});
+        });
+        derived(a, (b) => {
+        	// cause a conflict in names so the suggestion can't work
+        	const $a = 303;
+        	$a;
+        });
+        somethingWithACallback(() => {
+        	const $a = 303;
+        	derived(a, (b) => {
+        		$a;
+        	});
+        });
+- message: The argument name should be '$e'.
+  line: 37
+  column: 19
+  suggestions:
+    - desc: Rename the parameter from g to $e.
+      messageId: renameParam
+      output: |
+        import { derived } from 'svelte/store';
+
+        derived(a, (b) => {
+        	/** do nothing */
+        });
+        derived(c, (d, set) => {
+        	/** do nothing */
+        });
+        derived([e, f], ([g, h]) => {
+        	/** do nothing */
+        });
+        derived([i, j], ([k, l], set) => {
+        	/** do nothing */
+        });
+        derived([null, l], ([$m, $n]) => {
+        	/** do nothing */
+        });
+        derived([o, null], ([$p, $q]) => {
+        	/** do nothing */
+        });
+        derived(a, (b) => {
+        	doSomethingWith(b);
+
+        	somethingWithACallback(() => {
+        		b;
+        	});
+        });
+        derived(a, (b) => {
+        	b;
+
+        	somethingWithACallback(() => {
+        		// purposely shadow the var, this should not be updated
+        		const b = 303;
+        		b;
+        	});
+        });
+        derived([e, f], ([$e, h]) => {
+        	$e;
+        	h;
+
+        	somethingWithACallback(() => {
+        		$e;
+        		h;
+        	});
+        });
+        derived([e, f], ([g, h]) => {
+        	g;
+        	h;
+
+        	somethingWithACallback(() => {
+        		const g = 303;
+        		const h = 808;
+        		g;
+        		h;
+        	});
+        });
+        derived(a, (b) => {
+        	// cause a conflict in names so the suggestion can't work
+        	const $a = 303;
+        	$a;
+        });
+        somethingWithACallback(() => {
+        	const $a = 303;
+        	derived(a, (b) => {
+        		$a;
+        	});
+        });
+- message: The argument name should be '$f'.
+  line: 37
+  column: 22
+  suggestions:
+    - desc: Rename the parameter from h to $f.
+      messageId: renameParam
+      output: |
+        import { derived } from 'svelte/store';
+
+        derived(a, (b) => {
+        	/** do nothing */
+        });
+        derived(c, (d, set) => {
+        	/** do nothing */
+        });
+        derived([e, f], ([g, h]) => {
+        	/** do nothing */
+        });
+        derived([i, j], ([k, l], set) => {
+        	/** do nothing */
+        });
+        derived([null, l], ([$m, $n]) => {
+        	/** do nothing */
+        });
+        derived([o, null], ([$p, $q]) => {
+        	/** do nothing */
+        });
+        derived(a, (b) => {
+        	doSomethingWith(b);
+
+        	somethingWithACallback(() => {
+        		b;
+        	});
+        });
+        derived(a, (b) => {
+        	b;
+
+        	somethingWithACallback(() => {
+        		// purposely shadow the var, this should not be updated
+        		const b = 303;
+        		b;
+        	});
+        });
+        derived([e, f], ([g, $f]) => {
+        	g;
+        	$f;
+
+        	somethingWithACallback(() => {
+        		g;
+        		$f;
+        	});
+        });
+        derived([e, f], ([g, h]) => {
+        	g;
+        	h;
+
+        	somethingWithACallback(() => {
+        		const g = 303;
+        		const h = 808;
+        		g;
+        		h;
+        	});
+        });
+        derived(a, (b) => {
+        	// cause a conflict in names so the suggestion can't work
+        	const $a = 303;
+        	$a;
+        });
+        somethingWithACallback(() => {
+        	const $a = 303;
+        	derived(a, (b) => {
+        		$a;
+        	});
+        });
+- message: The argument name should be '$e'.
+  line: 46
+  column: 19
+  suggestions:
+    - desc: Rename the parameter from g to $e.
+      messageId: renameParam
+      output: |
+        import { derived } from 'svelte/store';
+
+        derived(a, (b) => {
+        	/** do nothing */
+        });
+        derived(c, (d, set) => {
+        	/** do nothing */
+        });
+        derived([e, f], ([g, h]) => {
+        	/** do nothing */
+        });
+        derived([i, j], ([k, l], set) => {
+        	/** do nothing */
+        });
+        derived([null, l], ([$m, $n]) => {
+        	/** do nothing */
+        });
+        derived([o, null], ([$p, $q]) => {
+        	/** do nothing */
+        });
+        derived(a, (b) => {
+        	doSomethingWith(b);
+
+        	somethingWithACallback(() => {
+        		b;
+        	});
+        });
+        derived(a, (b) => {
+        	b;
+
+        	somethingWithACallback(() => {
+        		// purposely shadow the var, this should not be updated
+        		const b = 303;
+        		b;
+        	});
+        });
+        derived([e, f], ([g, h]) => {
+        	g;
+        	h;
+
+        	somethingWithACallback(() => {
+        		g;
+        		h;
+        	});
+        });
+        derived([e, f], ([$e, h]) => {
+        	$e;
+        	h;
+
+        	somethingWithACallback(() => {
+        		const g = 303;
+        		const h = 808;
+        		g;
+        		h;
+        	});
+        });
+        derived(a, (b) => {
+        	// cause a conflict in names so the suggestion can't work
+        	const $a = 303;
+        	$a;
+        });
+        somethingWithACallback(() => {
+        	const $a = 303;
+        	derived(a, (b) => {
+        		$a;
+        	});
+        });
+- message: The argument name should be '$f'.
+  line: 46
+  column: 22
+  suggestions:
+    - desc: Rename the parameter from h to $f.
+      messageId: renameParam
+      output: |
+        import { derived } from 'svelte/store';
+
+        derived(a, (b) => {
+        	/** do nothing */
+        });
+        derived(c, (d, set) => {
+        	/** do nothing */
+        });
+        derived([e, f], ([g, h]) => {
+        	/** do nothing */
+        });
+        derived([i, j], ([k, l], set) => {
+        	/** do nothing */
+        });
+        derived([null, l], ([$m, $n]) => {
+        	/** do nothing */
+        });
+        derived([o, null], ([$p, $q]) => {
+        	/** do nothing */
+        });
+        derived(a, (b) => {
+        	doSomethingWith(b);
+
+        	somethingWithACallback(() => {
+        		b;
+        	});
+        });
+        derived(a, (b) => {
+        	b;
+
+        	somethingWithACallback(() => {
+        		// purposely shadow the var, this should not be updated
+        		const b = 303;
+        		b;
+        	});
+        });
+        derived([e, f], ([g, h]) => {
+        	g;
+        	h;
+
+        	somethingWithACallback(() => {
+        		g;
+        		h;
+        	});
+        });
+        derived([e, f], ([g, $f]) => {
+        	g;
+        	$f;
+
+        	somethingWithACallback(() => {
+        		const g = 303;
+        		const h = 808;
+        		g;
+        		h;
+        	});
+        });
+        derived(a, (b) => {
+        	// cause a conflict in names so the suggestion can't work
+        	const $a = 303;
+        	$a;
+        });
+        somethingWithACallback(() => {
+        	const $a = 303;
+        	derived(a, (b) => {
+        		$a;
+        	});
+        });
+- message: The argument name should be '$a'.
+  line: 57
+  column: 13
+  suggestions: null
+- message: The argument name should be '$a'.
+  line: 64
+  column: 14
   suggestions: null
diff --git a/packages/eslint-plugin-svelte/tests/fixtures/rules/derived-has-same-inputs-outputs/invalid/test01-input.js b/packages/eslint-plugin-svelte/tests/fixtures/rules/derived-has-same-inputs-outputs/invalid/test01-input.js
index 98d579b..0cda151 100644
--- a/packages/eslint-plugin-svelte/tests/fixtures/rules/derived-has-same-inputs-outputs/invalid/test01-input.js
+++ b/packages/eslint-plugin-svelte/tests/fixtures/rules/derived-has-same-inputs-outputs/invalid/test01-input.js
@@ -18,3 +18,50 @@ derived([null, l], ([$m, $n]) => {
 derived([o, null], ([$p, $q]) => {
 	/** do nothing */
 });
+derived(a, (b) => {
+	doSomethingWith(b);
+
+	somethingWithACallback(() => {
+		b;
+	});
+});
+derived(a, (b) => {
+	b;
+
+	somethingWithACallback(() => {
+		// purposely shadow the var, this should not be updated
+		const b = 303;
+		b;
+	});
+});
+derived([e, f], ([g, h]) => {
+	g;
+	h;
+
+	somethingWithACallback(() => {
+		g;
+		h;
+	});
+});
+derived([e, f], ([g, h]) => {
+	g;
+	h;
+
+	somethingWithACallback(() => {
+		const g = 303;
+		const h = 808;
+		g;
+		h;
+	});
+});
+derived(a, (b) => {
+	// cause a conflict in names so the suggestion can't work
+	const $a = 303;
+	$a;
+});
+somethingWithACallback(() => {
+	const $a = 303;
+	derived(a, (b) => {
+		$a;
+	});
+});