diff --git a/.changeset/fluffy-chicken-happen.md b/.changeset/fluffy-chicken-happen.md new file mode 100644 index 000000000..7120e2628 --- /dev/null +++ b/.changeset/fluffy-chicken-happen.md @@ -0,0 +1,5 @@ +--- +"eslint-plugin-svelte": minor +--- + +feat: add `require-store-callbacks-use-set-param` rule diff --git a/README.md b/README.md index 4f19f5e35..bc6fc8f8c 100644 --- a/README.md +++ b/README.md @@ -271,6 +271,7 @@ These rules relate to possible syntax or logic errors in Svelte code: | [svelte/no-shorthand-style-property-overrides](https://ota-meshi.github.io/eslint-plugin-svelte/rules/no-shorthand-style-property-overrides/) | disallow shorthand style properties that override related longhand properties | :star: | | [svelte/no-store-async](https://ota-meshi.github.io/eslint-plugin-svelte/rules/no-store-async/) | disallow using async/await inside svelte stores because it causes issues with the auto-unsubscribing features | | | [svelte/no-unknown-style-directive-property](https://ota-meshi.github.io/eslint-plugin-svelte/rules/no-unknown-style-directive-property/) | disallow unknown `style:property` | :star: | +| [svelte/require-store-callbacks-use-set-param](https://ota-meshi.github.io/eslint-plugin-svelte/rules/require-store-callbacks-use-set-param/) | (no description) | | | [svelte/valid-compile](https://ota-meshi.github.io/eslint-plugin-svelte/rules/valid-compile/) | disallow warnings when compiling. | :star: | ## Security Vulnerability diff --git a/docs/rules.md b/docs/rules.md index 9601f4517..946972a4e 100644 --- a/docs/rules.md +++ b/docs/rules.md @@ -24,6 +24,7 @@ These rules relate to possible syntax or logic errors in Svelte code: | [svelte/no-shorthand-style-property-overrides](./rules/no-shorthand-style-property-overrides.md) | disallow shorthand style properties that override related longhand properties | :star: | | [svelte/no-store-async](./rules/no-store-async.md) | disallow using async/await inside svelte stores because it causes issues with the auto-unsubscribing features | | | [svelte/no-unknown-style-directive-property](./rules/no-unknown-style-directive-property.md) | disallow unknown `style:property` | :star: | +| [svelte/require-store-callbacks-use-set-param](./rules/require-store-callbacks-use-set-param.md) | (no description) | | | [svelte/valid-compile](./rules/valid-compile.md) | disallow warnings when compiling. | :star: | ## Security Vulnerability diff --git a/docs/rules/require-store-callbacks-use-set-param.md b/docs/rules/require-store-callbacks-use-set-param.md new file mode 100644 index 000000000..e7300daa5 --- /dev/null +++ b/docs/rules/require-store-callbacks-use-set-param.md @@ -0,0 +1,76 @@ +--- +pageClass: "rule-details" +sidebarDepth: 0 +title: "svelte/require-store-callbacks-use-set-param" +description: "store callbacks must use `set` param" +--- + +# svelte/require-store-callbacks-use-set-param + +> Store callbacks must use `set` param. + +## :book: Rule Details + +This rule disallows if `readable` / `writable` store's setter function doesn't use `set` parameter.
+This rule doesn't check `derived` store. Therefore if you set a updated value asynchronously, please don't forget to use `set` function. + + + + + +```svelte + +``` + + + +## :wrench: Options + +Nothing. + +## :books: Further Reading + +- [Svelte - Docs > RUN TIME > svelte/store](https://svelte.dev/docs#run-time-svelte-store) + +## :mag: Implementation + +- [Rule source](https://github.com/ota-meshi/eslint-plugin-svelte/blob/main/src/rules/require-store-callbacks-use-set-param.ts) +- [Test source](https://github.com/ota-meshi/eslint-plugin-svelte/blob/main/tests/src/rules/require-store-callbacks-use-set-param.ts) diff --git a/package.json b/package.json index 09bf15212..0cc69de87 100644 --- a/package.json +++ b/package.json @@ -174,7 +174,7 @@ "access": "public" }, "typeCoverage": { - "atLeast": 98.71, + "atLeast": 98.72, "cache": true, "detail": true, "ignoreAsAssertion": true, diff --git a/src/rules/require-store-callbacks-use-set-param.ts b/src/rules/require-store-callbacks-use-set-param.ts new file mode 100644 index 000000000..005b186e5 --- /dev/null +++ b/src/rules/require-store-callbacks-use-set-param.ts @@ -0,0 +1,44 @@ +import { createRule } from "../utils" +import { extractStoreReferences } from "./reference-helpers/svelte-store" + +export default createRule("require-store-callbacks-use-set-param", { + meta: { + docs: { + description: "store callbacks must use `set` param", + category: "Possible Errors", + recommended: false, + }, + schema: [], + messages: { + unexpected: "Store callbacks must use `set` param.", + }, + type: "suggestion", + }, + create(context) { + return { + Program() { + for (const { node } of extractStoreReferences(context, [ + "readable", + "writable", + ])) { + const [_, fn] = node.arguments + if ( + !fn || + (fn.type !== "ArrowFunctionExpression" && + fn.type !== "FunctionExpression") + ) { + continue + } + const param = fn.params[0] + if (!param || (param.type === "Identifier" && param.name !== "set")) { + context.report({ + node: fn, + loc: fn.loc!, + messageId: "unexpected", + }) + } + } + }, + } + }, +}) diff --git a/src/utils/rules.ts b/src/utils/rules.ts index d4157c2e4..f4bc55b2b 100644 --- a/src/utils/rules.ts +++ b/src/utils/rules.ts @@ -33,6 +33,7 @@ import preferClassDirective from "../rules/prefer-class-directive" import preferDestructuredStoreProps from "../rules/prefer-destructured-store-props" import preferStyleDirective from "../rules/prefer-style-directive" import requireOptimizedStyleAttribute from "../rules/require-optimized-style-attribute" +import requireStoreCallbacksUseSetParam from "../rules/require-store-callbacks-use-set-param" import requireStoresInit from "../rules/require-stores-init" import shorthandAttribute from "../rules/shorthand-attribute" import shorthandDirective from "../rules/shorthand-directive" @@ -76,6 +77,7 @@ export const rules = [ preferDestructuredStoreProps, preferStyleDirective, requireOptimizedStyleAttribute, + requireStoreCallbacksUseSetParam, requireStoresInit, shorthandAttribute, shorthandDirective, diff --git a/tests/fixtures/rules/html-self-closing/invalid/presets/html/preset-html-errors.yaml b/tests/fixtures/rules/html-self-closing/invalid/presets/html/preset-html-errors.yaml new file mode 100644 index 000000000..b22c0655f --- /dev/null +++ b/tests/fixtures/rules/html-self-closing/invalid/presets/html/preset-html-errors.yaml @@ -0,0 +1,16 @@ +- message: Disallow self-closing on HTML elements. + line: 3 + column: 3 + suggestions: null +- message: Require self-closing on HTML void elements. + line: 4 + column: 3 + suggestions: null +- message: Disallow self-closing on Svelte custom components. + line: 5 + column: 3 + suggestions: null +- message: Require self-closing on Svelte special elements. + line: 8 + column: 1 + suggestions: null diff --git a/tests/fixtures/rules/html-self-closing/invalid/presets/none/preset-none-errors.yaml b/tests/fixtures/rules/html-self-closing/invalid/presets/none/preset-none-errors.yaml new file mode 100644 index 000000000..cde3eff78 --- /dev/null +++ b/tests/fixtures/rules/html-self-closing/invalid/presets/none/preset-none-errors.yaml @@ -0,0 +1,16 @@ +- message: Disallow self-closing on HTML elements. + line: 3 + column: 3 + suggestions: null +- message: Disallow self-closing on Svelte custom components. + line: 4 + column: 3 + suggestions: null +- message: Disallow self-closing on HTML void elements. + line: 5 + column: 3 + suggestions: null +- message: Disallow self-closing on Svelte special elements. + line: 8 + column: 1 + suggestions: null diff --git a/tests/fixtures/rules/require-store-callbacks-use-set-param/invalid/test01-errors.yaml b/tests/fixtures/rules/require-store-callbacks-use-set-param/invalid/test01-errors.yaml new file mode 100644 index 000000000..89483b9f1 --- /dev/null +++ b/tests/fixtures/rules/require-store-callbacks-use-set-param/invalid/test01-errors.yaml @@ -0,0 +1,16 @@ +- message: Store callbacks must use `set` param. + line: 4 + column: 19 + suggestions: null +- message: Store callbacks must use `set` param. + line: 5 + column: 19 + suggestions: null +- message: Store callbacks must use `set` param. + line: 7 + column: 19 + suggestions: null +- message: Store callbacks must use `set` param. + line: 8 + column: 19 + suggestions: null diff --git a/tests/fixtures/rules/require-store-callbacks-use-set-param/invalid/test01-input.svelte b/tests/fixtures/rules/require-store-callbacks-use-set-param/invalid/test01-input.svelte new file mode 100644 index 000000000..ddc584cec --- /dev/null +++ b/tests/fixtures/rules/require-store-callbacks-use-set-param/invalid/test01-input.svelte @@ -0,0 +1,9 @@ + diff --git a/tests/fixtures/rules/require-store-callbacks-use-set-param/invalid/test02-errors.yaml b/tests/fixtures/rules/require-store-callbacks-use-set-param/invalid/test02-errors.yaml new file mode 100644 index 000000000..89483b9f1 --- /dev/null +++ b/tests/fixtures/rules/require-store-callbacks-use-set-param/invalid/test02-errors.yaml @@ -0,0 +1,16 @@ +- message: Store callbacks must use `set` param. + line: 4 + column: 19 + suggestions: null +- message: Store callbacks must use `set` param. + line: 5 + column: 19 + suggestions: null +- message: Store callbacks must use `set` param. + line: 7 + column: 19 + suggestions: null +- message: Store callbacks must use `set` param. + line: 8 + column: 19 + suggestions: null diff --git a/tests/fixtures/rules/require-store-callbacks-use-set-param/invalid/test02-input.svelte b/tests/fixtures/rules/require-store-callbacks-use-set-param/invalid/test02-input.svelte new file mode 100644 index 000000000..2f789ab7f --- /dev/null +++ b/tests/fixtures/rules/require-store-callbacks-use-set-param/invalid/test02-input.svelte @@ -0,0 +1,9 @@ + diff --git a/tests/fixtures/rules/require-store-callbacks-use-set-param/valid/test01-input.svelte b/tests/fixtures/rules/require-store-callbacks-use-set-param/valid/test01-input.svelte new file mode 100644 index 000000000..bd88ad43e --- /dev/null +++ b/tests/fixtures/rules/require-store-callbacks-use-set-param/valid/test01-input.svelte @@ -0,0 +1,24 @@ + diff --git a/tests/fixtures/rules/require-store-callbacks-use-set-param/valid/test02-input.svelte b/tests/fixtures/rules/require-store-callbacks-use-set-param/valid/test02-input.svelte new file mode 100644 index 000000000..160e18ae9 --- /dev/null +++ b/tests/fixtures/rules/require-store-callbacks-use-set-param/valid/test02-input.svelte @@ -0,0 +1,32 @@ + diff --git a/tests/src/rules/require-store-callbacks-use-set-param.ts b/tests/src/rules/require-store-callbacks-use-set-param.ts new file mode 100644 index 000000000..f2d3b3ab2 --- /dev/null +++ b/tests/src/rules/require-store-callbacks-use-set-param.ts @@ -0,0 +1,16 @@ +import { RuleTester } from "eslint" +import rule from "../../../src/rules/require-store-callbacks-use-set-param" +import { loadTestCases } from "../../utils/utils" + +const tester = new RuleTester({ + parserOptions: { + ecmaVersion: 2020, + sourceType: "module", + }, +}) + +tester.run( + "require-store-callbacks-use-set-param", + rule as any, + loadTestCases("require-store-callbacks-use-set-param"), +)