-
-
Notifications
You must be signed in to change notification settings - Fork 26
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: implement
stores-no-async
(#225)
* feat: implement stores-no-async rule * test: add tests * docs: add docs * chore: add changeset * fix: remove since * fix: changeset * fix: use ReferenceTracker * fix: handled if fn is undefined * fix: handle FunctionExpression also
- Loading branch information
1 parent
dcb5f48
commit a3888b3
Showing
18 changed files
with
263 additions
and
27 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
--- | ||
"eslint-plugin-svelte": minor | ||
--- | ||
|
||
Add svelte/stores-no-async rule |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
--- | ||
pageClass: "rule-details" | ||
sidebarDepth: 0 | ||
title: "svelte/no-store-async" | ||
description: "disallow using async/await inside svelte stores" | ||
--- | ||
|
||
# svelte/no-store-async | ||
|
||
> disallow using async/await inside svelte stores | ||
- :gear: This rule is included in `"plugin:svelte/recommended"`. | ||
|
||
## :book: Rule Details | ||
|
||
This rule reports all uses of async/await inside svelte stores. | ||
Because it causes issues with the auto-unsubscribing features. | ||
|
||
<ESLintCodeBlock language="javascript"> | ||
|
||
<!--eslint-skip--> | ||
|
||
```js | ||
/* eslint svelte/no-store-async: "error" */ | ||
|
||
import { writable, readable, derived } from "svelte/store" | ||
|
||
/* ✓ GOOD */ | ||
const w1 = writable(false, () => {}) | ||
const r1 = readable(false, () => {}) | ||
const d1 = derived(a1, ($a1) => {}) | ||
|
||
/* ✗ BAD */ | ||
const w2 = writable(false, async () => {}) | ||
const r2 = readable(false, async () => {}) | ||
const d2 = derived(a1, async ($a1) => {}) | ||
``` | ||
|
||
</ESLintCodeBlock> | ||
|
||
## :wrench: Options | ||
|
||
Nothing. | ||
|
||
## :books: Further Reading | ||
|
||
- [Svelte - Docs > 4. Prefix stores with $ to access their values / Store contract](https://svelte.dev/docs#component-format-script-4-prefix-stores-with-$-to-access-their-values-store-contract) | ||
|
||
## :rocket: Version | ||
|
||
This rule was introduced in eslint-plugin-svelte v3.1.0 | ||
|
||
## :mag: Implementation | ||
|
||
- [Rule source](https://github.com/ota-meshi/eslint-plugin-svelte/blob/main/src/rules/no-store-async.ts) | ||
- [Test source](https://github.com/ota-meshi/eslint-plugin-svelte/blob/main/tests/src/rules/no-store-async.ts) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
import { createRule } from "../utils" | ||
import { extractStoreReferences } from "./reference-helpers/svelte-store" | ||
|
||
export default createRule("no-store-async", { | ||
meta: { | ||
docs: { | ||
description: | ||
"disallow using async/await inside svelte stores because it causes issues with the auto-unsubscribing features", | ||
category: "Possible Errors", | ||
recommended: true, | ||
default: "error", | ||
}, | ||
schema: [], | ||
messages: { | ||
unexpected: "Do not pass async functions to svelte stores.", | ||
}, | ||
type: "problem", | ||
}, | ||
create(context) { | ||
return { | ||
Program() { | ||
for (const { node } of extractStoreReferences(context)) { | ||
const [, fn] = node.arguments | ||
if ( | ||
!fn || | ||
(fn.type !== "ArrowFunctionExpression" && | ||
fn.type !== "FunctionExpression") || | ||
!fn.async | ||
) { | ||
continue | ||
} | ||
|
||
const start = fn.loc?.start ?? { line: 1, column: 0 } | ||
context.report({ | ||
node: fn, | ||
loc: { | ||
start, | ||
end: { | ||
line: start.line, | ||
column: start.column + 5, | ||
}, | ||
}, | ||
messageId: "unexpected", | ||
}) | ||
} | ||
}, | ||
} | ||
}, | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
import type * as ESTree from "estree" | ||
import { ReferenceTracker } from "eslint-utils" | ||
import type { RuleContext } from "../../types" | ||
|
||
/** Extract 'svelte/store' references */ | ||
export function* extractStoreReferences( | ||
context: RuleContext, | ||
): Generator<{ node: ESTree.CallExpression; name: string }, void> { | ||
const referenceTracker = new ReferenceTracker(context.getScope()) | ||
for (const { node, path } of referenceTracker.iterateEsmReferences({ | ||
"svelte/store": { | ||
[ReferenceTracker.ESM]: true, | ||
writable: { | ||
[ReferenceTracker.CALL]: true, | ||
}, | ||
readable: { | ||
[ReferenceTracker.CALL]: true, | ||
}, | ||
derived: { | ||
[ReferenceTracker.CALL]: true, | ||
}, | ||
}, | ||
})) { | ||
yield { | ||
node: node as ESTree.CallExpression, | ||
name: path[path.length - 1], | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
12 changes: 12 additions & 0 deletions
12
tests/fixtures/rules/no-store-async/invalid/test01-errors.yaml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
- message: Do not pass async functions to svelte stores. | ||
line: 3 | ||
column: 28 | ||
suggestions: null | ||
- message: Do not pass async functions to svelte stores. | ||
line: 6 | ||
column: 28 | ||
suggestions: null | ||
- message: Do not pass async functions to svelte stores. | ||
line: 9 | ||
column: 24 | ||
suggestions: null |
11 changes: 11 additions & 0 deletions
11
tests/fixtures/rules/no-store-async/invalid/test01-input.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
import { writable, readable, derived } from "svelte/store" | ||
|
||
const w2 = writable(false, async () => { | ||
/** do nothing */ | ||
}) | ||
const r2 = readable(false, async () => { | ||
/** do nothing */ | ||
}) | ||
const d2 = derived(a1, async ($a1) => { | ||
/** do nothing */ | ||
}) |
12 changes: 12 additions & 0 deletions
12
tests/fixtures/rules/no-store-async/invalid/test02-errors.yaml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
- message: Do not pass async functions to svelte stores. | ||
line: 3 | ||
column: 35 | ||
suggestions: null | ||
- message: Do not pass async functions to svelte stores. | ||
line: 6 | ||
column: 35 | ||
suggestions: null | ||
- message: Do not pass async functions to svelte stores. | ||
line: 9 | ||
column: 31 | ||
suggestions: null |
11 changes: 11 additions & 0 deletions
11
tests/fixtures/rules/no-store-async/invalid/test02-input.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
import * as stores from "svelte/store" | ||
|
||
const w2 = stores.writable(false, async () => { | ||
/** do nothing */ | ||
}) | ||
const r2 = stores.readable(false, async () => { | ||
/** do nothing */ | ||
}) | ||
const d2 = stores.derived(a1, async ($a1) => { | ||
/** do nothing */ | ||
}) |
12 changes: 12 additions & 0 deletions
12
tests/fixtures/rules/no-store-async/invalid/test03-errors.yaml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
- message: Do not pass async functions to svelte stores. | ||
line: 3 | ||
column: 21 | ||
suggestions: null | ||
- message: Do not pass async functions to svelte stores. | ||
line: 6 | ||
column: 21 | ||
suggestions: null | ||
- message: Do not pass async functions to svelte stores. | ||
line: 9 | ||
column: 18 | ||
suggestions: null |
11 changes: 11 additions & 0 deletions
11
tests/fixtures/rules/no-store-async/invalid/test03-input.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
import { writable as A, readable as B, derived as C } from "svelte/store" | ||
|
||
const w2 = A(false, async () => { | ||
/** do nothing */ | ||
}) | ||
const r2 = B(false, async () => { | ||
/** do nothing */ | ||
}) | ||
const d2 = C(a1, async ($a1) => { | ||
/** do nothing */ | ||
}) |
12 changes: 12 additions & 0 deletions
12
tests/fixtures/rules/no-store-async/invalid/test04-errors.yaml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
- message: Do not pass async functions to svelte stores. | ||
line: 3 | ||
column: 28 | ||
suggestions: null | ||
- message: Do not pass async functions to svelte stores. | ||
line: 6 | ||
column: 28 | ||
suggestions: null | ||
- message: Do not pass async functions to svelte stores. | ||
line: 9 | ||
column: 24 | ||
suggestions: null |
11 changes: 11 additions & 0 deletions
11
tests/fixtures/rules/no-store-async/invalid/test04-input.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
import { writable, readable, derived } from "svelte/store" | ||
|
||
const w2 = writable(false, async function () { | ||
/** do nothing */ | ||
}) | ||
const r2 = readable(false, async function () { | ||
/** do nothing */ | ||
}) | ||
const d2 = derived(a1, async function ($a1) { | ||
/** do nothing */ | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
import { writable, readable, derived } from "svelte/store" | ||
|
||
const w1 = writable(false, () => { | ||
/** do nothing */ | ||
}) | ||
const w2 = writable(false) | ||
const r1 = readable(false, () => { | ||
/** do nothing */ | ||
}) | ||
const r2 = readable(false) | ||
const d1 = derived(a1, ($a1) => { | ||
/** do nothing */ | ||
}) | ||
const d2 = derived(a1) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
import { RuleTester } from "eslint" | ||
import rule from "../../../src/rules/no-store-async" | ||
import { loadTestCases } from "../../utils/utils" | ||
|
||
const tester = new RuleTester({ | ||
parserOptions: { | ||
ecmaVersion: 2020, | ||
sourceType: "module", | ||
}, | ||
}) | ||
|
||
tester.run("no-store-async", rule as any, loadTestCases("no-store-async")) |