Skip to content

Commit 6183b6e

Browse files
authored
Add dollar-prefixed-store-uses-vars rule (#81)
1 parent 7843ca5 commit 6183b6e

9 files changed

+188
-1
lines changed

README.md

+1
Original file line numberDiff line numberDiff line change
@@ -302,6 +302,7 @@ These rules relate to this plugin works:
302302
| Rule ID | Description | |
303303
|:--------|:------------|:---|
304304
| [@ota-meshi/svelte/comment-directive](https://ota-meshi.github.io/eslint-plugin-svelte/rules/comment-directive/) | support comment-directives in HTML template | :star: |
305+
| [@ota-meshi/svelte/dollar-prefixed-store-uses-vars](https://ota-meshi.github.io/eslint-plugin-svelte/rules/dollar-prefixed-store-uses-vars/) | prevent $-prefixed variables to be marked as unused | :star: |
305306
| [@ota-meshi/svelte/system](https://ota-meshi.github.io/eslint-plugin-svelte/rules/system/) | system rule for working this plugin | :star: |
306307

307308
<!--RULES_TABLE_END-->

docs/__layout.svelte

+2-1
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
2020
import "../docs-svelte-kit/src/app.css"
2121
import "../docs-svelte-kit/src/site.css"
22+
// eslint-disable-next-line no-unused-vars -- ignore
2223
import { tocStore } from "$lib/utils"
2324
2425
export let moduleData
@@ -27,7 +28,7 @@
2728
$: fileInfo = moduleData.fileInfo
2829
$: {
2930
const toc = moduleData.toc
30-
tocStore.update(() => toc)
31+
$tocStore = toc
3132
}
3233
3334
let sidebarOpen = false

docs/rules.md

+1
Original file line numberDiff line numberDiff line change
@@ -70,4 +70,5 @@ These rules relate to this plugin works:
7070
| Rule ID | Description | |
7171
|:--------|:------------|:---|
7272
| [@ota-meshi/svelte/comment-directive](./rules/comment-directive.md) | support comment-directives in HTML template | :star: |
73+
| [@ota-meshi/svelte/dollar-prefixed-store-uses-vars](./rules/dollar-prefixed-store-uses-vars.md) | prevent $-prefixed variables to be marked as unused | :star: |
7374
| [@ota-meshi/svelte/system](./rules/system.md) | system rule for working this plugin | :star: |
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
---
2+
pageClass: "rule-details"
3+
sidebarDepth: 0
4+
title: "@ota-meshi/svelte/dollar-prefixed-store-uses-vars"
5+
description: "prevent $-prefixed variables to be marked as unused"
6+
---
7+
8+
# @ota-meshi/svelte/dollar-prefixed-store-uses-vars
9+
10+
> prevent $-prefixed variables to be marked as unused
11+
12+
- :exclamation: <badge text="This rule has not been released yet." vertical="middle" type="error"> **_This rule has not been released yet._** </badge>
13+
- :gear: This rule is included in `"plugin:@ota-meshi/svelte/base"` and `"plugin:@ota-meshi/svelte/recommended"`.
14+
15+
ESLint `no-unused-vars` rule does not detect store variables used as $-prefixed.
16+
This rule will find imported store variables that are used as $-prefixed and marks them as used.
17+
18+
This rule only has an effect when the `no-unused-vars` rule is enabled.
19+
20+
## :book: Rule Details
21+
22+
Without this rule this code triggers warning:
23+
24+
<ESLintCodeBlock rules="{ { 'no-unused-vars': ['error'] } }">
25+
26+
<!--eslint-skip-->
27+
28+
```svelte
29+
<script>
30+
/* eslint @ota-meshi/svelte/dollar-prefixed-store-uses-vars: "error" */
31+
import { a } from "./my-stores"
32+
33+
// The variable doesn't look like it's being referenced, but it may be used externally.
34+
$a = 42
35+
</script>
36+
```
37+
38+
</ESLintCodeBlock>
39+
40+
## :wrench: Options
41+
42+
Nothing.
43+
44+
## :mag: Implementation
45+
46+
- [Rule source](https://github.com/ota-meshi/eslint-plugin-svelte/blob/main/src/rules/dollar-prefixed-store-uses-vars.ts)
47+
- [Test source](https://github.com/ota-meshi/eslint-plugin-svelte/blob/main/tests/src/rules/dollar-prefixed-store-uses-vars.ts)

src/configs/base.ts

+1
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ export = {
1111

1212
// @ota-meshi/eslint-plugin-svelte rules
1313
"@ota-meshi/svelte/comment-directive": "error",
14+
"@ota-meshi/svelte/dollar-prefixed-store-uses-vars": "error",
1415
"@ota-meshi/svelte/system": "error",
1516
},
1617
},

src/configs/recommended.ts

+1
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ export = {
77
rules: {
88
// @ota-meshi/eslint-plugin-svelte rules
99
"@ota-meshi/svelte/comment-directive": "error",
10+
"@ota-meshi/svelte/dollar-prefixed-store-uses-vars": "error",
1011
"@ota-meshi/svelte/no-at-debug-tags": "warn",
1112
"@ota-meshi/svelte/no-at-html-tags": "error",
1213
"@ota-meshi/svelte/no-dupe-else-if-blocks": "error",
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
import type * as ESTree from "estree"
2+
import { createRule } from "../utils"
3+
import { findVariable } from "../utils/ast-utils"
4+
5+
export default createRule("dollar-prefixed-store-uses-vars", {
6+
meta: {
7+
docs: {
8+
description: "prevent $-prefixed variables to be marked as unused",
9+
category: "System",
10+
recommended: "base",
11+
},
12+
schema: [],
13+
messages: {},
14+
type: "problem",
15+
},
16+
create(context) {
17+
if (!context.parserServices.isSvelte) {
18+
return {}
19+
}
20+
21+
/** Process identifier */
22+
function processId(node: ESTree.Identifier) {
23+
const variable = findVariable(context, node)
24+
if (!variable) {
25+
return
26+
}
27+
for (const reference of variable.references) {
28+
if (
29+
reference.identifier.name.startsWith("$") &&
30+
reference.identifier.name.slice(1) === node.name
31+
) {
32+
context.markVariableAsUsed(node.name)
33+
break
34+
}
35+
}
36+
}
37+
38+
return {
39+
"ImportDefaultSpecifier > Identifier": processId,
40+
"ImportSpecifier > Identifier.local": processId,
41+
"ImportNamespaceSpecifier > Identifier": processId,
42+
}
43+
},
44+
})

src/utils/rules.ts

+2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import type { RuleModule } from "../types"
22
import buttonHasType from "../rules/button-has-type"
33
import commentDirective from "../rules/comment-directive"
4+
import dollarPrefixedStoreUsesVars from "../rules/dollar-prefixed-store-uses-vars"
45
import firstAttributeLinebreak from "../rules/first-attribute-linebreak"
56
import htmlQuotes from "../rules/html-quotes"
67
import indent from "../rules/indent"
@@ -24,6 +25,7 @@ import validCompile from "../rules/valid-compile"
2425
export const rules = [
2526
buttonHasType,
2627
commentDirective,
28+
dollarPrefixedStoreUsesVars,
2729
firstAttributeLinebreak,
2830
htmlQuotes,
2931
indent,
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
import { RuleTester, Linter } from "eslint"
2+
import rule from "../../../src/rules/dollar-prefixed-store-uses-vars"
3+
4+
describe("dollar-prefixed-store-uses-vars", () => {
5+
const ruleNoUnusedVars = new Linter().getRules().get("no-unused-vars")!
6+
const tester = new RuleTester({
7+
parser: require.resolve("svelte-eslint-parser"),
8+
parserOptions: {
9+
ecmaVersion: 2020,
10+
sourceType: "module",
11+
},
12+
})
13+
const linter = (tester as any).linter
14+
linter.defineRule("dollar-prefixed-store-uses-vars", rule)
15+
tester.run("no-unused-vars", ruleNoUnusedVars, {
16+
valid: [
17+
`
18+
<script>
19+
/* eslint dollar-prefixed-store-uses-vars: 2 */
20+
import { a } from "./stores"
21+
$a = 42
22+
</script>
23+
`,
24+
`
25+
<script>
26+
/* eslint dollar-prefixed-store-uses-vars: 2 */
27+
import { a as b } from "./stores"
28+
$b = 42
29+
</script>
30+
`,
31+
`
32+
<script>
33+
/* eslint dollar-prefixed-store-uses-vars: 2 */
34+
import a from "./stores"
35+
$a = 42
36+
</script>
37+
`,
38+
`
39+
<script>
40+
/* eslint dollar-prefixed-store-uses-vars: 2 */
41+
import * as a from "./stores"
42+
$a = 42
43+
</script>
44+
`,
45+
],
46+
invalid: [
47+
{
48+
code: `
49+
<script>
50+
/* eslint dollar-prefixed-store-uses-vars: 2 */
51+
import { a } from "./stores"
52+
$b = 42
53+
</script>
54+
`,
55+
errors: 1,
56+
},
57+
{
58+
code: `
59+
<script>
60+
/* eslint dollar-prefixed-store-uses-vars: 2 */
61+
import { a as b } from "./stores"
62+
$a = 42
63+
</script>
64+
`,
65+
errors: 1,
66+
},
67+
{
68+
code: `
69+
<script>
70+
/* eslint dollar-prefixed-store-uses-vars: 2 */
71+
import a from "./stores"
72+
$b = 42
73+
</script>
74+
`,
75+
errors: 1,
76+
},
77+
{
78+
code: `
79+
<script>
80+
/* eslint dollar-prefixed-store-uses-vars: 2 */
81+
import * as a from "./stores"
82+
$b = 42
83+
</script>
84+
`,
85+
errors: 1,
86+
},
87+
],
88+
})
89+
})

0 commit comments

Comments
 (0)