diff --git a/.changeset/neat-dots-grin.md b/.changeset/neat-dots-grin.md new file mode 100644 index 000000000..9a77b5022 --- /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 db731dd26..735d4279d 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 58d896b10..55cfee95f 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 b059bc655..f8c6568e8 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 3ea90c277..30f86aa31 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) + } + ] }); } } 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 9ce09c034..2107d3072 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 98d579bcc..0cda15103 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; + }); +});