Skip to content

Commit 303f74f

Browse files
committed
add excludedRunes option
1 parent c3d5bd7 commit 303f74f

17 files changed

+121
-10
lines changed

packages/eslint-plugin-svelte/src/rule-types.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -523,8 +523,8 @@ type SveltePreferClassDirective = []|[{
523523
}]
524524
// ----- svelte/prefer-const -----
525525
type SveltePreferConst = []|[{
526-
destructuring?: ("any" | "all")
527-
ignoreReadBeforeAssign?: boolean
526+
excludedRunes?: string[]
527+
[k: string]: unknown | undefined
528528
}]
529529
// ----- svelte/shorthand-attribute -----
530530
type SvelteShorthandAttribute = []|[{

packages/eslint-plugin-svelte/src/rules/prefer-const.ts

+21-5
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ function findDeclarationCallee(node: TSESTree.Expression) {
2121
* Determines if a declaration should be skipped in the const preference analysis.
2222
* Specifically checks for Svelte's state management utilities ($props, $derived).
2323
*/
24-
function shouldSkipDeclaration(declaration: TSESTree.Expression | null) {
24+
function shouldSkipDeclaration(declaration: TSESTree.Expression | null, excludedRunes: string[]) {
2525
if (!declaration) {
2626
return false;
2727
}
@@ -31,15 +31,15 @@ function shouldSkipDeclaration(declaration: TSESTree.Expression | null) {
3131
return false;
3232
}
3333

34-
if (callee.type === 'Identifier' && ['$props', '$state', '$derived'].includes(callee.name)) {
34+
if (callee.type === 'Identifier' && excludedRunes.includes(callee.name)) {
3535
return true;
3636
}
3737

3838
if (callee.type !== 'MemberExpression' || callee.object.type !== 'Identifier') {
3939
return false;
4040
}
4141

42-
if (callee.object.name === '$state' || callee.object.name === '$derived') {
42+
if (excludedRunes.includes(callee.object.name)) {
4343
return true;
4444
}
4545

@@ -54,16 +54,32 @@ export default createRule('prefer-const', {
5454
category: 'Best Practices',
5555
recommended: false,
5656
extensionRule: 'prefer-const'
57-
}
57+
},
58+
schema: [
59+
{
60+
type: 'object',
61+
properties: {
62+
excludedRunes: {
63+
type: 'array',
64+
items: {
65+
type: 'string'
66+
}
67+
}
68+
}
69+
}
70+
]
5871
},
5972
create(context) {
73+
const config = context.options[0] ?? {};
74+
const excludedRunes = config.excludedRunes ?? ['$props', '$derived'];
75+
6076
return defineWrapperListener(coreRule, context, {
6177
createListenerProxy(coreListener) {
6278
return {
6379
...coreListener,
6480
VariableDeclaration(node) {
6581
for (const decl of node.declarations) {
66-
if (shouldSkipDeclaration(decl.init)) {
82+
if (shouldSkipDeclaration(decl.init, excludedRunes)) {
6783
return;
6884
}
6985
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"options": [{ "excludedRunes": [] }]
3+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
- message: "'prop1' is never reassigned. Use 'const' instead."
2+
line: 2
3+
column: 8
4+
suggestions: null
5+
- message: "'prop2' is never reassigned. Use 'const' instead."
6+
line: 2
7+
column: 15
8+
suggestions: null
9+
- message: "'zero' is never reassigned. Use 'const' instead."
10+
line: 3
11+
column: 6
12+
suggestions: null
13+
- message: "'derived' is never reassigned. Use 'const' instead."
14+
line: 4
15+
column: 6
16+
suggestions: null
17+
- message: "'derivedBy' is never reassigned. Use 'const' instead."
18+
line: 5
19+
column: 6
20+
suggestions: null
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
<script>
2+
let { prop1, prop2 } = $props();
3+
let zero = $state(0);
4+
let derived = $derived(zero * 2);
5+
let derivedBy = $derived.by(calc());
6+
</script>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
<script>
2+
const { prop1, prop2 } = $props();
3+
const zero = $state(0);
4+
const derived = $derived(zero * 2);
5+
const derivedBy = $derived.by(calc());
6+
</script>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"options": [{ "excludedRunes": ["$state"] }]
3+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
- message: "'prop1' is never reassigned. Use 'const' instead."
2+
line: 2
3+
column: 8
4+
suggestions: null
5+
- message: "'prop2' is never reassigned. Use 'const' instead."
6+
line: 2
7+
column: 15
8+
suggestions: null
9+
- message: "'derived' is never reassigned. Use 'const' instead."
10+
line: 4
11+
column: 6
12+
suggestions: null
13+
- message: "'derivedBy' is never reassigned. Use 'const' instead."
14+
line: 5
15+
column: 6
16+
suggestions: null
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
<script>
2+
let { prop1, prop2 } = $props();
3+
let zero = $state(0);
4+
let derived = $derived(zero * 2);
5+
let derivedBy = $derived.by(calc());
6+
</script>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
<script>
2+
const { prop1, prop2 } = $props();
3+
let zero = $state(0);
4+
const derived = $derived(zero * 2);
5+
const derivedBy = $derived.by(calc());
6+
</script>

packages/eslint-plugin-svelte/tests/fixtures/rules/prefer-const/invalid/test01-errors.yaml

+8
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,14 @@
22
line: 3
33
column: 6
44
suggestions: null
5+
- message: "'state' is never reassigned. Use 'const' instead."
6+
line: 4
7+
column: 6
8+
suggestions: null
9+
- message: "'raw' is never reassigned. Use 'const' instead."
10+
line: 5
11+
column: 6
12+
suggestions: null
513
- message: "'doubled' is never reassigned. Use 'const' instead."
614
line: 6
715
column: 6

packages/eslint-plugin-svelte/tests/fixtures/rules/prefer-const/invalid/test01-output.svelte

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
<script>
22
let { prop1, prop2 } = $props();
33
const zero = 0;
4-
let state = $state(0);
5-
let raw = $state.raw(0);
4+
const state = $state(0);
5+
const raw = $state.raw(0);
66
const doubled = state * 2;
77
let derived = $derived(state * 2);
88
const calculated = calc();
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"options": [{ "excludedRunes": [] }]
3+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
<script>
2+
const { prop1, prop2 } = $props();
3+
const zero = $state(0);
4+
const derived = $derived(zero * 2);
5+
const derivedBy = $derived.by(calc());
6+
</script>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"options": [{ "excludedRunes": ["$props", "$derived", "$state"] }]
3+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
<script>
2+
let { prop1, prop2 } = $props();
3+
let zero = $state(0);
4+
let derived = $derived(zero * 2);
5+
let derivedBy = $derived.by(calc());
6+
</script>
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
11
<script>
2-
const a = {};
2+
let { prop1, prop2 } = $props();
3+
const zero = $state(0);
4+
let derived = $derived(zero * 2);
5+
let derivedBy = $derived.by(calc());
36
</script>

0 commit comments

Comments
 (0)