Skip to content

Commit 4deb69d

Browse files
committed
wip: address feedbakc
1 parent 09f0249 commit 4deb69d

File tree

5 files changed

+53
-38
lines changed

5 files changed

+53
-38
lines changed

src/rules/prefer-destructured-store-props.ts

+39-14
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
1+
import type * as ESTree from "estree"
12
import type { TSESTree } from "@typescript-eslint/types"
23
import type { AST } from "svelte-eslint-parser"
34
import { createRule } from "../utils"
5+
import { getStringIfConstant } from "../utils/ast-utils"
6+
7+
type NodeRecord = { property: string; node: TSESTree.MemberExpression }
48

59
export default createRule("prefer-destructured-store-props", {
610
meta: {
@@ -13,61 +17,82 @@ export default createRule("prefer-destructured-store-props", {
1317
hasSuggestions: true,
1418
schema: [],
1519
messages: {
16-
useDestructuring: `Destructure {{prop}} from store {{store}} for better change tracking & fewer redraws`,
17-
fixUseDestructuring: `Using destructuring like $: ({ {{prop}} } = {{store}}); will run faster`,
20+
useDestructuring: `Destructure {{property}} from store {{store}} for better change tracking & fewer redraws`,
21+
fixUseDestructuring: `Using destructuring like $: ({ {{property}} } = {{store}}); will run faster`,
1822
},
1923
type: "suggestion",
2024
},
2125
create(context) {
2226
let script: AST.SvelteScriptElement
23-
const reports: TSESTree.MemberExpression[] = []
27+
const reports: NodeRecord[] = []
2428

2529
return {
2630
[`SvelteScriptElement`](node: AST.SvelteScriptElement) {
2731
script = node
2832
},
2933

30-
// {$foo.bar + baz}
34+
// {$foo.bar}
3135
// should be
3236
// $: ({ bar } = $foo);
33-
// {bar + baz}
34-
[`MemberExpression[object.name=/^\\$/][property.type="Identifier"]`](
37+
// {bar}
38+
// Same with {$foo["bar"]}
39+
[`MemberExpression[object.name=/^\\$/]`](
3540
node: TSESTree.MemberExpression,
3641
) {
37-
reports.push(node)
42+
const property =
43+
node.property.type === "Identifier"
44+
? node.property.name
45+
: getStringIfConstant(node.property as ESTree.Expression)
46+
47+
if (!property) {
48+
return
49+
}
50+
51+
reports.push({ property, node })
3852
},
3953

4054
[`Program:exit`]() {
41-
reports.forEach((node) => {
55+
reports.forEach(({ property, node }) => {
4256
const store = (node.object as TSESTree.Identifier).name
43-
const prop = (node.property as TSESTree.Identifier).name
57+
// let prop: string | null = null
58+
59+
// if (node.property.type === "Literal") {
60+
// prop = node.property.value as string
61+
// } else if (node.property.type === "Identifier") {
62+
// prop = node.property.name
63+
// }
4464

4565
context.report({
4666
node,
4767
messageId: "useDestructuring",
4868
data: {
4969
store,
50-
prop,
70+
property,
5171
},
72+
5273
suggest: [
5374
{
5475
messageId: "fixUseDestructuring",
5576
data: {
5677
store,
57-
prop,
78+
property,
5879
},
5980

6081
fix(fixer) {
61-
if (!script || !script.endTag) {
82+
// Avoid autofix suggestions for:
83+
// dynamic accesses like {$foo[bar]}
84+
// no <script> tag
85+
// no <script> ending
86+
if (node.computed || !script || !script.endTag) {
6287
return []
6388
}
6489

6590
return [
6691
fixer.insertTextAfterRange(
6792
[script.endTag.range[0], script.endTag.range[0]],
68-
`$: ({ ${prop} } = ${store});\n`,
93+
`$: ({ ${property} } = ${store});\n`,
6994
),
70-
fixer.replaceText(node, prop),
95+
fixer.replaceText(node, property),
7196
]
7297
},
7398
},

tests/fixtures/rules/prefer-destructured-store-props/invalid/test01-errors.json

+7-19
Original file line numberDiff line numberDiff line change
@@ -7,32 +7,20 @@
77
{
88
"desc": "Using destructuring like $: ({ bar } = $foo); will run faster",
99
"messageId": "fixUseDestructuring",
10-
"output": "<!-- prettier-ignore -->\n<script>\n\n$: ({ bar } = $foo);\n</script>\n\n{bar}\n{$foo[bar]}\n\n<!-- eslint-disable-next-line dot-notation -- tests -->\n{$foo.bar}\n"
10+
"output": "<!-- prettier-ignore -->\n<script>\n\n$: ({ bar } = $foo);\n</script>\n\n{bar}\n\n{$foo[baz]}\n\n<!-- eslint-disable-next-line dot-notation -- tests -->\n{$foo[\"qux\"]}\n"
1111
}
1212
]
1313
},
1414
{
15-
"message": "Destructure bar from store $foo for better change tracking & fewer redraws",
16-
"line": 7,
15+
"message": "Destructure baz from store $foo for better change tracking & fewer redraws",
16+
"line": 8,
1717
"column": 2,
18-
"suggestions": [
19-
{
20-
"desc": "Using destructuring like $: ({ bar } = $foo); will run faster",
21-
"messageId": "fixUseDestructuring",
22-
"output": "<!-- prettier-ignore -->\n<script>\n\n$: ({ bar } = $foo);\n</script>\n\n{$foo.bar}\n{bar}\n\n<!-- eslint-disable-next-line dot-notation -- tests -->\n{$foo.bar}\n"
23-
}
24-
]
18+
"suggestions": null
2519
},
2620
{
27-
"message": "Destructure bar from store $foo for better change tracking & fewer redraws",
28-
"line": 10,
21+
"message": "Destructure qux from store $foo for better change tracking & fewer redraws",
22+
"line": 11,
2923
"column": 2,
30-
"suggestions": [
31-
{
32-
"desc": "Using destructuring like $: ({ bar } = $foo); will run faster",
33-
"messageId": "fixUseDestructuring",
34-
"output": "<!-- prettier-ignore -->\n<script>\n\n$: ({ bar } = $foo);\n</script>\n\n{$foo.bar}\n{$foo[bar]}\n\n<!-- eslint-disable-next-line dot-notation -- tests -->\n{bar}\n"
35-
}
36-
]
24+
"suggestions": null
3725
}
3826
]

tests/fixtures/rules/prefer-destructured-store-props/invalid/test01-input.svelte

+3-2
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@
44
</script>
55

66
{$foo.bar}
7-
{$foo[bar]}
7+
8+
{$foo[baz]}
89

910
<!-- eslint-disable-next-line dot-notation -- tests -->
10-
{$foo.bar}
11+
{$foo["qux"]}

tests/fixtures/rules/prefer-destructured-store-props/invalid/test02-errors.json

+2-2
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,13 @@
77
},
88
{
99
"message": "Destructure bar from store $foo for better change tracking & fewer redraws",
10-
"line": 3,
10+
"line": 4,
1111
"column": 2,
1212
"suggestions": null
1313
},
1414
{
1515
"message": "Destructure bar from store $foo for better change tracking & fewer redraws",
16-
"line": 6,
16+
"line": 7,
1717
"column": 2,
1818
"suggestions": null
1919
}
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
<!-- prettier-ignore -->
22
{$foo.bar}
3+
34
{$foo[bar]}
45

56
<!-- eslint-disable-next-line dot-notation -- tests -->
6-
{$foo.bar}
7+
{$foo["bar"]}

0 commit comments

Comments
 (0)