Skip to content

Commit 6999c90

Browse files
committed
chore(prefer-svelte-reactivity): added rule implementation
1 parent 5ca61dd commit 6999c90

File tree

7 files changed

+87
-0
lines changed

7 files changed

+87
-0
lines changed

.changeset/rich-colts-nail.md

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'eslint-plugin-svelte': minor
3+
---
4+
5+
feat: added the `prefer-svelte-reactivity` rule

README.md

+1
Original file line numberDiff line numberDiff line change
@@ -272,6 +272,7 @@ These rules relate to possible syntax or logic errors in Svelte code:
272272
| [svelte/no-shorthand-style-property-overrides](https://sveltejs.github.io/eslint-plugin-svelte/rules/no-shorthand-style-property-overrides/) | disallow shorthand style properties that override related longhand properties | :star: |
273273
| [svelte/no-store-async](https://sveltejs.github.io/eslint-plugin-svelte/rules/no-store-async/) | disallow using async/await inside svelte stores because it causes issues with the auto-unsubscribing features | :star: |
274274
| [svelte/no-unknown-style-directive-property](https://sveltejs.github.io/eslint-plugin-svelte/rules/no-unknown-style-directive-property/) | disallow unknown `style:property` | :star: |
275+
| [svelte/prefer-svelte-reactivity](https://sveltejs.github.io/eslint-plugin-svelte/rules/prefer-svelte-reactivity/) | disallow using built-in classes where a reactive alternative is provided by svelte/reactivity | :star: |
275276
| [svelte/require-store-callbacks-use-set-param](https://sveltejs.github.io/eslint-plugin-svelte/rules/require-store-callbacks-use-set-param/) | store callbacks must use `set` param | |
276277
| [svelte/require-store-reactive-access](https://sveltejs.github.io/eslint-plugin-svelte/rules/require-store-reactive-access/) | disallow to use of the store itself as an operand. Need to use $ prefix or get function. | :star::wrench: |
277278
| [svelte/valid-compile](https://sveltejs.github.io/eslint-plugin-svelte/rules/valid-compile/) | disallow warnings when compiling. | |

docs/rules.md

+1
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ These rules relate to possible syntax or logic errors in Svelte code:
2929
| [svelte/no-shorthand-style-property-overrides](./rules/no-shorthand-style-property-overrides.md) | disallow shorthand style properties that override related longhand properties | :star: |
3030
| [svelte/no-store-async](./rules/no-store-async.md) | disallow using async/await inside svelte stores because it causes issues with the auto-unsubscribing features | :star: |
3131
| [svelte/no-unknown-style-directive-property](./rules/no-unknown-style-directive-property.md) | disallow unknown `style:property` | :star: |
32+
| [svelte/prefer-svelte-reactivity](./rules/prefer-svelte-reactivity.md) | disallow using built-in classes where a reactive alternative is provided by svelte/reactivity | :star: |
3233
| [svelte/require-store-callbacks-use-set-param](./rules/require-store-callbacks-use-set-param.md) | store callbacks must use `set` param | |
3334
| [svelte/require-store-reactive-access](./rules/require-store-reactive-access.md) | disallow to use of the store itself as an operand. Need to use $ prefix or get function. | :star::wrench: |
3435
| [svelte/valid-compile](./rules/valid-compile.md) | disallow warnings when compiling. | |

packages/eslint-plugin-svelte/src/configs/flat/recommended.ts

+1
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ const config: Linter.Config[] = [
3737
'svelte/no-unused-svelte-ignore': 'error',
3838
'svelte/no-useless-children-snippet': 'error',
3939
'svelte/no-useless-mustaches': 'error',
40+
'svelte/prefer-svelte-reactivity': 'error',
4041
'svelte/require-each-key': 'error',
4142
'svelte/require-event-dispatcher-types': 'error',
4243
'svelte/require-store-reactive-access': 'error',

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

+5
Original file line numberDiff line numberDiff line change
@@ -306,6 +306,11 @@ export interface RuleOptions {
306306
* @see https://sveltejs.github.io/eslint-plugin-svelte/rules/prefer-style-directive/
307307
*/
308308
'svelte/prefer-style-directive'?: Linter.RuleEntry<[]>
309+
/**
310+
* disallow using built-in classes where a reactive alternative is provided by svelte/reactivity
311+
* @see https://sveltejs.github.io/eslint-plugin-svelte/rules/prefer-svelte-reactivity/
312+
*/
313+
'svelte/prefer-svelte-reactivity'?: Linter.RuleEntry<[]>
309314
/**
310315
* require keyed `{#each}` block
311316
* @see https://sveltejs.github.io/eslint-plugin-svelte/rules/require-each-key/
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
import { ReferenceTracker } from '@eslint-community/eslint-utils';
2+
import { getSourceCode } from '../utils/compat.js';
3+
import { createRule } from '../utils/index.js';
4+
5+
export default createRule('prefer-svelte-reactivity', {
6+
meta: {
7+
docs: {
8+
description:
9+
'disallow using built-in classes where a reactive alternative is provided by svelte/reactivity',
10+
category: 'Possible Errors',
11+
recommended: true
12+
},
13+
schema: [],
14+
messages: {
15+
dateUsed: 'Found a usage of the built-in Date class. Use a SvelteDate instead.',
16+
mapUsed: 'Found a usage of the built-in Map class. Use a SvelteMap instead.',
17+
setUsed: 'Found a usage of the built-in Set class. Use a SvelteSet instead.',
18+
urlUsed: 'Found a usage of the built-in URL class. Use a SvelteURL instead.',
19+
urlSearchParamsUsed:
20+
'Found a usage of the built-in URLSearchParams class. Use a SvelteURLSearchParams instead.'
21+
},
22+
type: 'problem', // 'problem', or 'layout',
23+
conditions: [
24+
{
25+
svelteVersions: ['5'],
26+
svelteFileTypes: ['.svelte', '.svelte.[js|ts]']
27+
}
28+
]
29+
},
30+
create(context) {
31+
return {
32+
Program() {
33+
const referenceTracker = new ReferenceTracker(
34+
getSourceCode(context).scopeManager.globalScope!
35+
);
36+
for (const { node, path } of referenceTracker.iterateGlobalReferences({
37+
Date: {
38+
[ReferenceTracker.CONSTRUCT]: true
39+
},
40+
Map: {
41+
[ReferenceTracker.CONSTRUCT]: true
42+
},
43+
Set: {
44+
[ReferenceTracker.CONSTRUCT]: true
45+
},
46+
URL: {
47+
[ReferenceTracker.CALL]: true,
48+
[ReferenceTracker.CONSTRUCT]: true,
49+
[ReferenceTracker.READ]: true
50+
},
51+
URLSearchParams: {
52+
[ReferenceTracker.CALL]: true,
53+
[ReferenceTracker.CONSTRUCT]: true,
54+
[ReferenceTracker.READ]: true
55+
}
56+
})) {
57+
const typeToMessageId: Record<string, string> = {
58+
Date: 'dateUsed',
59+
Map: 'mapUsed',
60+
Set: 'setUsed',
61+
URL: 'urlUsed',
62+
URLSearchParams: 'urlSearchParamsUsed'
63+
};
64+
context.report({
65+
messageId: typeToMessageId[path[0]],
66+
node
67+
});
68+
}
69+
}
70+
};
71+
}
72+
});

packages/eslint-plugin-svelte/src/utils/rules.ts

+2
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ import preferClassDirective from '../rules/prefer-class-directive.js';
6060
import preferConst from '../rules/prefer-const.js';
6161
import preferDestructuredStoreProps from '../rules/prefer-destructured-store-props.js';
6262
import preferStyleDirective from '../rules/prefer-style-directive.js';
63+
import preferSvelteReactivity from '../rules/prefer-svelte-reactivity.js';
6364
import requireEachKey from '../rules/require-each-key.js';
6465
import requireEventDispatcherTypes from '../rules/require-event-dispatcher-types.js';
6566
import requireOptimizedStyleAttribute from '../rules/require-optimized-style-attribute.js';
@@ -135,6 +136,7 @@ export const rules = [
135136
preferConst,
136137
preferDestructuredStoreProps,
137138
preferStyleDirective,
139+
preferSvelteReactivity,
138140
requireEachKey,
139141
requireEventDispatcherTypes,
140142
requireOptimizedStyleAttribute,

0 commit comments

Comments
 (0)