@@ -3,6 +3,7 @@ import type { TSESTree } from "@typescript-eslint/types"
3
3
import type { AST } from "svelte-eslint-parser"
4
4
import { createRule } from "../utils"
5
5
import { getStringIfConstant } from "../utils/ast-utils"
6
+ import { returnStatement } from "@babel/types"
6
7
7
8
type NodeRecord = { property : string ; node : TSESTree . MemberExpression }
8
9
@@ -17,20 +18,33 @@ export default createRule("prefer-destructured-store-props", {
17
18
hasSuggestions : true ,
18
19
schema : [ ] ,
19
20
messages : {
20
- useDestructuring : `Destructure {{property}} from store {{store}} for better change tracking & fewer redraws` ,
21
+ useDestructuring : `Destructure {{property}} from {{store}} for better change tracking & fewer redraws` ,
21
22
fixUseDestructuring : `Using destructuring like $: ({ {{property}} } = {{store}}); will run faster` ,
22
23
} ,
23
24
type : "suggestion" ,
24
25
} ,
25
26
create ( context ) {
26
27
let script : AST . SvelteScriptElement
28
+
29
+ // Store off instances of probably-destructurable statements
27
30
const reports : NodeRecord [ ] = [ ]
28
31
32
+ // Store off defined variable names so we can avoid offering a suggestion in those cases
33
+ const defined : Set < string > = new Set ( )
34
+
29
35
return {
30
36
[ `SvelteScriptElement` ] ( node : AST . SvelteScriptElement ) {
31
37
script = node
32
38
} ,
33
39
40
+ [ `VariableDeclarator[id.type="Identifier"]` ] (
41
+ node : TSESTree . VariableDeclarator ,
42
+ ) {
43
+ const { name } = node . id as TSESTree . Identifier
44
+
45
+ defined . add ( name )
46
+ } ,
47
+
34
48
// {$foo.bar}
35
49
// should be
36
50
// $: ({ bar } = $foo);
@@ -54,13 +68,6 @@ export default createRule("prefer-destructured-store-props", {
54
68
[ `Program:exit` ] ( ) {
55
69
reports . forEach ( ( { property, node } ) => {
56
70
const store = ( node . object 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
- // }
64
71
65
72
context . report ( {
66
73
node,
@@ -70,33 +77,42 @@ export default createRule("prefer-destructured-store-props", {
70
77
property,
71
78
} ,
72
79
73
- suggest : [
74
- {
75
- messageId : "fixUseDestructuring" ,
76
- data : {
77
- store,
78
- property,
79
- } ,
80
+ // Avoid suggestions for:
81
+ // dynamic accesses like {$foo[bar]}
82
+ // no <script> tag
83
+ // no <script> ending
84
+ // variable name already defined
85
+ suggest :
86
+ node . computed ||
87
+ ! script ||
88
+ ! script . endTag ||
89
+ defined . has ( property )
90
+ ? [ ]
91
+ : [
92
+ {
93
+ messageId : "fixUseDestructuring" ,
94
+ data : {
95
+ store,
96
+ property,
97
+ } ,
80
98
81
- fix ( fixer ) {
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 ) {
87
- return [ ]
88
- }
99
+ fix ( fixer ) {
100
+ // This is only necessary to make TS shut up about script.endTag maybe being null
101
+ // but since we already checked it above that warning is just wrong
102
+ if ( ! script . endTag ) {
103
+ return [ ]
104
+ }
89
105
90
- return [
91
- fixer . insertTextAfterRange (
92
- [ script . endTag . range [ 0 ] , script . endTag . range [ 0 ] ] ,
93
- `$: ({ ${ property } } = ${ store } );\n` ,
94
- ) ,
95
- fixer . replaceText ( node , property ) ,
96
- ]
97
- } ,
98
- } ,
99
- ] ,
106
+ return [
107
+ fixer . insertTextAfterRange (
108
+ [ script . endTag . range [ 0 ] , script . endTag . range [ 0 ] ] ,
109
+ `$: ({ ${ property } } = ${ store } );\n` ,
110
+ ) ,
111
+ fixer . replaceText ( node , property ) ,
112
+ ]
113
+ } ,
114
+ } ,
115
+ ] ,
100
116
} )
101
117
} )
102
118
} ,
0 commit comments