Skip to content

Commit 4a4575e

Browse files
committed
fix: use a suggestion instead
1 parent 2c83156 commit 4a4575e

File tree

6 files changed

+284
-38
lines changed

6 files changed

+284
-38
lines changed

packages/eslint-plugin-svelte/src/rules/require-store-callbacks-use-set-param.ts

Lines changed: 71 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,36 @@
1+
import { getScope } from '../utils/ast-utils.js';
2+
import type { RuleContext, SuggestionReportDescriptor } from '../types.js';
13
import { createRule } from '../utils/index.js';
24
import { extractStoreReferences } from './reference-helpers/svelte-store.js';
5+
import type { TSESTree } from '@typescript-eslint/types';
6+
import type { Variable } from '@typescript-eslint/scope-manager';
7+
import { getSourceCode } from '../utils/compat.js';
8+
9+
function findVariableForName(
10+
context: RuleContext,
11+
node: TSESTree.Node,
12+
name: string | null,
13+
expectedName: string
14+
): { hasConflict: boolean; variable: Variable | null } {
15+
const scope = getScope(context, node);
16+
let hasConflict = false;
17+
let variable: Variable | null = null;
18+
19+
for (const v of scope.variables) {
20+
if (hasConflict && (variable || name === null)) {
21+
break;
22+
}
23+
if (v.name === expectedName) {
24+
hasConflict = true;
25+
continue;
26+
}
27+
if (name !== null && v.name === name) {
28+
variable = v;
29+
}
30+
}
31+
32+
return { hasConflict, variable };
33+
}
334

435
export default createRule('require-store-callbacks-use-set-param', {
536
meta: {
@@ -8,10 +39,12 @@ export default createRule('require-store-callbacks-use-set-param', {
839
category: 'Possible Errors',
940
recommended: false
1041
},
11-
fixable: 'code',
42+
hasSuggestions: true,
1243
schema: [],
1344
messages: {
14-
unexpected: 'Store callbacks must use `set` param.'
45+
unexpected: 'Store callbacks must use `set` param.',
46+
updateParam: 'Rename parameter from {{oldName}} to `set`.',
47+
addParam: 'Add a `set` parameter.'
1548
},
1649
type: 'suggestion'
1750
},
@@ -25,23 +58,48 @@ export default createRule('require-store-callbacks-use-set-param', {
2558
}
2659
const param = fn.params[0];
2760
if (!param || (param.type === 'Identifier' && param.name !== 'set')) {
28-
context.report({
29-
node: fn,
30-
loc: fn.loc,
31-
messageId: 'unexpected',
32-
fix: (fixer) => {
33-
if (param) {
34-
return fixer.replaceText(param, 'set');
35-
}
36-
const token = context.getSourceCode().getTokenBefore(fn.body, {
61+
const { hasConflict, variable } = findVariableForName(
62+
context,
63+
fn.body,
64+
param ? param.name : null,
65+
'set'
66+
);
67+
const suggest: SuggestionReportDescriptor[] = [];
68+
if (!hasConflict) {
69+
if (param) {
70+
suggest.push({
71+
messageId: 'updateParam',
72+
data: { oldName: param.name },
73+
*fix(fixer) {
74+
yield fixer.replaceText(param, 'set');
75+
76+
if (variable) {
77+
for (const ref of variable.references) {
78+
yield fixer.replaceText(ref.identifier, 'set');
79+
}
80+
}
81+
}
82+
});
83+
} else {
84+
const token = getSourceCode(context).getTokenBefore(fn.body, {
3785
filter: (token) => token.type === 'Punctuator' && token.value === '(',
3886
includeComments: false
3987
});
4088
if (token) {
41-
return fixer.insertTextAfter(token, 'set');
89+
suggest.push({
90+
messageId: 'addParam',
91+
fix(fixer) {
92+
return fixer.insertTextAfter(token, 'set');
93+
}
94+
});
4295
}
43-
return [];
4496
}
97+
}
98+
context.report({
99+
node: fn,
100+
loc: fn.loc,
101+
messageId: 'unexpected',
102+
suggest
45103
});
46104
}
47105
}
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,159 @@
11
- message: Store callbacks must use `set` param.
22
line: 4
33
column: 18
4-
suggestions: null
4+
suggestions:
5+
- desc: Add a `set` parameter.
6+
messageId: addParam
7+
output: |
8+
<script>
9+
import { readable, writable } from 'svelte/store';
10+
11+
readable(false, (set) => true);
12+
readable(false, (foo) => true);
13+
14+
writable(false, () => true);
15+
writable(false, (foo) => true);
16+
17+
readable(false, (foo) => {
18+
foo;
19+
insideACallback(() => {
20+
foo;
21+
});
22+
conflictingName(() => {
23+
const foo = 303;
24+
foo;
25+
});
26+
});
27+
28+
readable(false, () => {
29+
const set = 303;
30+
});
31+
</script>
532
- message: Store callbacks must use `set` param.
633
line: 5
734
column: 18
8-
suggestions: null
35+
suggestions:
36+
- desc: Rename parameter from foo to `set`.
37+
messageId: updateParam
38+
output: |
39+
<script>
40+
import { readable, writable } from 'svelte/store';
41+
42+
readable(false, () => true);
43+
readable(false, (set) => true);
44+
45+
writable(false, () => true);
46+
writable(false, (foo) => true);
47+
48+
readable(false, (foo) => {
49+
foo;
50+
insideACallback(() => {
51+
foo;
52+
});
53+
conflictingName(() => {
54+
const foo = 303;
55+
foo;
56+
});
57+
});
58+
59+
readable(false, () => {
60+
const set = 303;
61+
});
62+
</script>
963
- message: Store callbacks must use `set` param.
1064
line: 7
1165
column: 18
12-
suggestions: null
66+
suggestions:
67+
- desc: Add a `set` parameter.
68+
messageId: addParam
69+
output: |
70+
<script>
71+
import { readable, writable } from 'svelte/store';
72+
73+
readable(false, () => true);
74+
readable(false, (foo) => true);
75+
76+
writable(false, (set) => true);
77+
writable(false, (foo) => true);
78+
79+
readable(false, (foo) => {
80+
foo;
81+
insideACallback(() => {
82+
foo;
83+
});
84+
conflictingName(() => {
85+
const foo = 303;
86+
foo;
87+
});
88+
});
89+
90+
readable(false, () => {
91+
const set = 303;
92+
});
93+
</script>
1394
- message: Store callbacks must use `set` param.
1495
line: 8
1596
column: 18
97+
suggestions:
98+
- desc: Rename parameter from foo to `set`.
99+
messageId: updateParam
100+
output: |
101+
<script>
102+
import { readable, writable } from 'svelte/store';
103+
104+
readable(false, () => true);
105+
readable(false, (foo) => true);
106+
107+
writable(false, () => true);
108+
writable(false, (set) => true);
109+
110+
readable(false, (foo) => {
111+
foo;
112+
insideACallback(() => {
113+
foo;
114+
});
115+
conflictingName(() => {
116+
const foo = 303;
117+
foo;
118+
});
119+
});
120+
121+
readable(false, () => {
122+
const set = 303;
123+
});
124+
</script>
125+
- message: Store callbacks must use `set` param.
126+
line: 10
127+
column: 19
128+
suggestions:
129+
- desc: Rename parameter from foo to `set`.
130+
messageId: updateParam
131+
output: |
132+
<script>
133+
import { readable, writable } from 'svelte/store';
134+
135+
readable(false, () => true);
136+
readable(false, (foo) => true);
137+
138+
writable(false, () => true);
139+
writable(false, (foo) => true);
140+
141+
readable(false, (set) => {
142+
set;
143+
insideACallback(() => {
144+
set;
145+
});
146+
conflictingName(() => {
147+
const foo = 303;
148+
foo;
149+
});
150+
});
151+
152+
readable(false, () => {
153+
const set = 303;
154+
});
155+
</script>
156+
- message: Store callbacks must use `set` param.
157+
line: 21
158+
column: 19
16159
suggestions: null

packages/eslint-plugin-svelte/tests/fixtures/rules/require-store-callbacks-use-set-param/invalid/test01-input.svelte

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,19 @@
66
77
writable(false, () => true);
88
writable(false, (foo) => true);
9+
10+
readable(false, (foo) => {
11+
foo;
12+
insideACallback(() => {
13+
foo;
14+
});
15+
conflictingName(() => {
16+
const foo = 303;
17+
foo;
18+
});
19+
});
20+
21+
readable(false, () => {
22+
const set = 303;
23+
});
924
</script>

packages/eslint-plugin-svelte/tests/fixtures/rules/require-store-callbacks-use-set-param/invalid/test01-output.svelte

Lines changed: 0 additions & 9 deletions
This file was deleted.
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,64 @@
11
- message: Store callbacks must use `set` param.
22
line: 4
33
column: 18
4-
suggestions: null
4+
suggestions:
5+
- desc: Add a `set` parameter.
6+
messageId: addParam
7+
output: |
8+
<script>
9+
import { readable, writable } from 'svelte/store';
10+
11+
readable(false, function (set) {});
12+
readable(false, (foo) => function () {});
13+
14+
writable(false, () => function () {});
15+
writable(false, (foo) => function () {});
16+
</script>
517
- message: Store callbacks must use `set` param.
618
line: 5
719
column: 18
8-
suggestions: null
20+
suggestions:
21+
- desc: Rename parameter from foo to `set`.
22+
messageId: updateParam
23+
output: |
24+
<script>
25+
import { readable, writable } from 'svelte/store';
26+
27+
readable(false, function () {});
28+
readable(false, (set) => function () {});
29+
30+
writable(false, () => function () {});
31+
writable(false, (foo) => function () {});
32+
</script>
933
- message: Store callbacks must use `set` param.
1034
line: 7
1135
column: 18
12-
suggestions: null
36+
suggestions:
37+
- desc: Add a `set` parameter.
38+
messageId: addParam
39+
output: |
40+
<script>
41+
import { readable, writable } from 'svelte/store';
42+
43+
readable(false, function () {});
44+
readable(false, (foo) => function () {});
45+
46+
writable(false, (set) => function () {});
47+
writable(false, (foo) => function () {});
48+
</script>
1349
- message: Store callbacks must use `set` param.
1450
line: 8
1551
column: 18
16-
suggestions: null
52+
suggestions:
53+
- desc: Rename parameter from foo to `set`.
54+
messageId: updateParam
55+
output: |
56+
<script>
57+
import { readable, writable } from 'svelte/store';
58+
59+
readable(false, function () {});
60+
readable(false, (foo) => function () {});
61+
62+
writable(false, () => function () {});
63+
writable(false, (set) => function () {});
64+
</script>

packages/eslint-plugin-svelte/tests/fixtures/rules/require-store-callbacks-use-set-param/invalid/test02-output.svelte

Lines changed: 0 additions & 9 deletions
This file was deleted.

0 commit comments

Comments
 (0)