eslint-plugin-flawless 0.1.8 → 0.1.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -0
- package/dist/index.d.mts +27 -8
- package/dist/index.mjs +395 -46
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -184,6 +184,7 @@ Requires [type information](https://typescript-eslint.io/linting/typed-linting).
|
|
|
184
184
|
| [no-unnecessary-use-callback](src/rules/no-unnecessary-use-callback/documentation.md) | Disallow unnecessary usage of 'useCallback' | | |
|
|
185
185
|
| [no-unnecessary-use-memo](src/rules/no-unnecessary-use-memo/documentation.md) | Disallow unnecessary usage of 'useMemo' | | |
|
|
186
186
|
| [prefer-destructuring-assignment](src/rules/prefer-destructuring-assignment/documentation.md) | Enforce destructuring assignment for component props | 🔧 | |
|
|
187
|
+
| [prefer-parameter-destructuring](src/rules/prefer-parameter-destructuring/documentation.md) | Enforce destructuring parameters in the function signature | 🔧 | |
|
|
187
188
|
| [purity](src/rules/purity/documentation.md) | Disallow impure calls such as `math.random` or `os.clock` during render | | |
|
|
188
189
|
| [toml-sort-keys](src/rules/toml-sort-keys/documentation.md) | Enforce a configured sort order for TOML keys and tables | 🔧 | |
|
|
189
190
|
| [yaml-block-key-blank-lines](src/rules/yaml-block-key-blank-lines/documentation.md) | Enforce blank lines around top-level YAML block collection keys | 🔧 | |
|
package/dist/index.d.mts
CHANGED
|
@@ -24,7 +24,7 @@ interface JsxShorthandFragmentOptions {
|
|
|
24
24
|
*/
|
|
25
25
|
readonly mode?: Mode;
|
|
26
26
|
}
|
|
27
|
-
type Options$
|
|
27
|
+
type Options$4 = [JsxShorthandFragmentOptions?];
|
|
28
28
|
type Mode = "element" | "syntax";
|
|
29
29
|
//#endregion
|
|
30
30
|
//#region src/rules/naming-convention/utils/enums.d.ts
|
|
@@ -135,7 +135,7 @@ interface NamingSelector {
|
|
|
135
135
|
//#endregion
|
|
136
136
|
//#region src/rules/naming-convention/rule.d.ts
|
|
137
137
|
type MessageIds$2 = "doesNotMatchFormat" | "doesNotMatchFormatTrimmed" | "missingAffix" | "missingUnderscore" | "satisfyCustom" | "unexpectedUnderscore";
|
|
138
|
-
type Options$
|
|
138
|
+
type Options$3 = Array<NamingSelector>;
|
|
139
139
|
//#endregion
|
|
140
140
|
//#region src/rules/no-unnecessary-use-callback/rule.d.ts
|
|
141
141
|
declare const MESSAGE_ID_DEFAULT$1 = "default";
|
|
@@ -147,6 +147,16 @@ declare const MESSAGE_ID_DEFAULT = "default";
|
|
|
147
147
|
declare const MESSAGE_ID_INSIDE_USE_EFFECT = "noUnnecessaryUseMemoInsideUseEffect";
|
|
148
148
|
type MessageIds = typeof MESSAGE_ID_DEFAULT | typeof MESSAGE_ID_INSIDE_USE_EFFECT;
|
|
149
149
|
//#endregion
|
|
150
|
+
//#region src/rules/prefer-parameter-destructuring/rule.d.ts
|
|
151
|
+
type Options$2 = [{
|
|
152
|
+
/**
|
|
153
|
+
* Whether the autofix may hoist pattern defaults and computed keys past
|
|
154
|
+
* earlier statements, reordering their side effects. Defaults to `true`;
|
|
155
|
+
* set to `false` to withhold the fix in those cases.
|
|
156
|
+
*/
|
|
157
|
+
allowSideEffectReordering?: boolean;
|
|
158
|
+
}];
|
|
159
|
+
//#endregion
|
|
150
160
|
//#region src/rules/purity/rule.d.ts
|
|
151
161
|
interface PurityOptions {
|
|
152
162
|
/**
|
|
@@ -182,10 +192,10 @@ declare const plugin: {
|
|
|
182
192
|
"jsx-shorthand-boolean": TSESLint.RuleModule<"setAttributeValue", [], PluginDocumentation, TSESLint.RuleListener> & {
|
|
183
193
|
name: string;
|
|
184
194
|
};
|
|
185
|
-
"jsx-shorthand-fragment": TSESLint.RuleModule<MessageIds$3, Options$
|
|
195
|
+
"jsx-shorthand-fragment": TSESLint.RuleModule<MessageIds$3, Options$4, PluginDocumentation, TSESLint.RuleListener> & {
|
|
186
196
|
name: string;
|
|
187
197
|
};
|
|
188
|
-
"naming-convention": TSESLint.RuleModule<MessageIds$2, Options$
|
|
198
|
+
"naming-convention": TSESLint.RuleModule<MessageIds$2, Options$3, PluginDocumentation, TSESLint.RuleListener> & {
|
|
189
199
|
name: string;
|
|
190
200
|
};
|
|
191
201
|
"no-unnecessary-use-callback": TSESLint.RuleModule<MessageIds$1, [], PluginDocumentation, TSESLint.RuleListener> & {
|
|
@@ -197,6 +207,9 @@ declare const plugin: {
|
|
|
197
207
|
"prefer-destructuring-assignment": TSESLint.RuleModule<"default", [], PluginDocumentation, TSESLint.RuleListener> & {
|
|
198
208
|
name: string;
|
|
199
209
|
};
|
|
210
|
+
"prefer-parameter-destructuring": TSESLint.RuleModule<"default", Options$2, PluginDocumentation, TSESLint.RuleListener> & {
|
|
211
|
+
name: string;
|
|
212
|
+
};
|
|
200
213
|
purity: TSESLint.RuleModule<"impureCall", Options$1, PluginDocumentation, TSESLint.RuleListener> & {
|
|
201
214
|
name: string;
|
|
202
215
|
};
|
|
@@ -223,10 +236,10 @@ declare const _default: {
|
|
|
223
236
|
"jsx-shorthand-boolean": import("${configDir}").RuleModule<"setAttributeValue", [], PluginDocumentation, import("${configDir}").RuleListener> & {
|
|
224
237
|
name: string;
|
|
225
238
|
};
|
|
226
|
-
"jsx-shorthand-fragment": import("${configDir}").RuleModule<MessageIds$3, Options$
|
|
239
|
+
"jsx-shorthand-fragment": import("${configDir}").RuleModule<MessageIds$3, Options$4, PluginDocumentation, import("${configDir}").RuleListener> & {
|
|
227
240
|
name: string;
|
|
228
241
|
};
|
|
229
|
-
"naming-convention": import("${configDir}").RuleModule<MessageIds$2, Options$
|
|
242
|
+
"naming-convention": import("${configDir}").RuleModule<MessageIds$2, Options$3, PluginDocumentation, import("${configDir}").RuleListener> & {
|
|
230
243
|
name: string;
|
|
231
244
|
};
|
|
232
245
|
"no-unnecessary-use-callback": import("${configDir}").RuleModule<MessageIds$1, [], PluginDocumentation, import("${configDir}").RuleListener> & {
|
|
@@ -238,6 +251,9 @@ declare const _default: {
|
|
|
238
251
|
"prefer-destructuring-assignment": import("${configDir}").RuleModule<"default", [], PluginDocumentation, import("${configDir}").RuleListener> & {
|
|
239
252
|
name: string;
|
|
240
253
|
};
|
|
254
|
+
"prefer-parameter-destructuring": import("${configDir}").RuleModule<"default", Options$2, PluginDocumentation, import("${configDir}").RuleListener> & {
|
|
255
|
+
name: string;
|
|
256
|
+
};
|
|
241
257
|
purity: import("${configDir}").RuleModule<"impureCall", Options$1, PluginDocumentation, import("${configDir}").RuleListener> & {
|
|
242
258
|
name: string;
|
|
243
259
|
};
|
|
@@ -261,10 +277,10 @@ declare const _default: {
|
|
|
261
277
|
"jsx-shorthand-boolean": import("${configDir}").RuleModule<"setAttributeValue", [], PluginDocumentation, import("${configDir}").RuleListener> & {
|
|
262
278
|
name: string;
|
|
263
279
|
};
|
|
264
|
-
"jsx-shorthand-fragment": import("${configDir}").RuleModule<MessageIds$3, Options$
|
|
280
|
+
"jsx-shorthand-fragment": import("${configDir}").RuleModule<MessageIds$3, Options$4, PluginDocumentation, import("${configDir}").RuleListener> & {
|
|
265
281
|
name: string;
|
|
266
282
|
};
|
|
267
|
-
"naming-convention": import("${configDir}").RuleModule<MessageIds$2, Options$
|
|
283
|
+
"naming-convention": import("${configDir}").RuleModule<MessageIds$2, Options$3, PluginDocumentation, import("${configDir}").RuleListener> & {
|
|
268
284
|
name: string;
|
|
269
285
|
};
|
|
270
286
|
"no-unnecessary-use-callback": import("${configDir}").RuleModule<MessageIds$1, [], PluginDocumentation, import("${configDir}").RuleListener> & {
|
|
@@ -276,6 +292,9 @@ declare const _default: {
|
|
|
276
292
|
"prefer-destructuring-assignment": import("${configDir}").RuleModule<"default", [], PluginDocumentation, import("${configDir}").RuleListener> & {
|
|
277
293
|
name: string;
|
|
278
294
|
};
|
|
295
|
+
"prefer-parameter-destructuring": import("${configDir}").RuleModule<"default", Options$2, PluginDocumentation, import("${configDir}").RuleListener> & {
|
|
296
|
+
name: string;
|
|
297
|
+
};
|
|
279
298
|
purity: import("${configDir}").RuleModule<"impureCall", Options$1, PluginDocumentation, import("${configDir}").RuleListener> & {
|
|
280
299
|
name: string;
|
|
281
300
|
};
|
package/dist/index.mjs
CHANGED
|
@@ -8,7 +8,7 @@ import { findVariable } from "@typescript-eslint/utils/ast-utils";
|
|
|
8
8
|
import { getStaticTOMLValue } from "toml-eslint-parser";
|
|
9
9
|
//#region package.json
|
|
10
10
|
var name = "eslint-plugin-flawless";
|
|
11
|
-
var version = "0.1.
|
|
11
|
+
var version = "0.1.10";
|
|
12
12
|
var repository = {
|
|
13
13
|
"url": "git+https://github.com/christopher-buss/eslint-plugin-flawless.git",
|
|
14
14
|
"type": "git"
|
|
@@ -35,24 +35,24 @@ function createEslintRule(rule) {
|
|
|
35
35
|
}
|
|
36
36
|
//#endregion
|
|
37
37
|
//#region src/rules/jsx-shorthand-boolean/rule.ts
|
|
38
|
-
const RULE_NAME$
|
|
39
|
-
const MESSAGE_ID$
|
|
40
|
-
const messages$
|
|
41
|
-
function create$
|
|
38
|
+
const RULE_NAME$9 = "jsx-shorthand-boolean";
|
|
39
|
+
const MESSAGE_ID$4 = "setAttributeValue";
|
|
40
|
+
const messages$9 = { [MESSAGE_ID$4]: "Set an explicit value for boolean attribute '{{name}}'." };
|
|
41
|
+
function create$9(context) {
|
|
42
42
|
const { sourceCode } = context;
|
|
43
43
|
return { JSXAttribute(node) {
|
|
44
44
|
if (node.value !== null) return;
|
|
45
45
|
context.report({
|
|
46
46
|
data: { name: sourceCode.getText(node.name) },
|
|
47
47
|
fix: (fixer) => fixer.insertTextAfter(node.name, "={true}"),
|
|
48
|
-
messageId: MESSAGE_ID$
|
|
48
|
+
messageId: MESSAGE_ID$4,
|
|
49
49
|
node
|
|
50
50
|
});
|
|
51
51
|
} };
|
|
52
52
|
}
|
|
53
53
|
const jsxShorthandBoolean = createEslintRule({
|
|
54
|
-
name: RULE_NAME$
|
|
55
|
-
create: create$
|
|
54
|
+
name: RULE_NAME$9,
|
|
55
|
+
create: create$9,
|
|
56
56
|
defaultOptions: [],
|
|
57
57
|
meta: {
|
|
58
58
|
docs: {
|
|
@@ -62,19 +62,19 @@ const jsxShorthandBoolean = createEslintRule({
|
|
|
62
62
|
},
|
|
63
63
|
fixable: "code",
|
|
64
64
|
hasSuggestions: false,
|
|
65
|
-
messages: messages$
|
|
65
|
+
messages: messages$9,
|
|
66
66
|
schema: [],
|
|
67
67
|
type: "suggestion"
|
|
68
68
|
}
|
|
69
69
|
});
|
|
70
70
|
//#endregion
|
|
71
71
|
//#region src/rules/jsx-shorthand-fragment/rule.ts
|
|
72
|
-
const RULE_NAME$
|
|
72
|
+
const RULE_NAME$8 = "jsx-shorthand-fragment";
|
|
73
73
|
const MESSAGE_ID_NAMED = "useNamedFragment";
|
|
74
74
|
const MESSAGE_ID_SHORTHAND = "useShorthandFragment";
|
|
75
75
|
const DEFAULT_MODE = "syntax";
|
|
76
76
|
const DEFAULT_FRAGMENT_NAME = "Fragment";
|
|
77
|
-
const messages$
|
|
77
|
+
const messages$8 = {
|
|
78
78
|
[MESSAGE_ID_NAMED]: "Use the '{{name}}' component instead of fragment shorthand syntax.",
|
|
79
79
|
[MESSAGE_ID_SHORTHAND]: "Use the fragment shorthand syntax '<>...</>' instead of the '{{name}}' component."
|
|
80
80
|
};
|
|
@@ -110,7 +110,7 @@ function jsxNameToString(node) {
|
|
|
110
110
|
}
|
|
111
111
|
return null;
|
|
112
112
|
}
|
|
113
|
-
function create$
|
|
113
|
+
function create$8(context) {
|
|
114
114
|
const options = context.options[0] ?? {};
|
|
115
115
|
const mode = options.mode ?? DEFAULT_MODE;
|
|
116
116
|
const fragmentName = options.fragmentName ?? DEFAULT_FRAGMENT_NAME;
|
|
@@ -148,8 +148,8 @@ function create$7(context) {
|
|
|
148
148
|
} };
|
|
149
149
|
}
|
|
150
150
|
const jsxShorthandFragment = createEslintRule({
|
|
151
|
-
name: RULE_NAME$
|
|
152
|
-
create: create$
|
|
151
|
+
name: RULE_NAME$8,
|
|
152
|
+
create: create$8,
|
|
153
153
|
defaultOptions: [{
|
|
154
154
|
fragmentName: DEFAULT_FRAGMENT_NAME,
|
|
155
155
|
mode: DEFAULT_MODE
|
|
@@ -166,7 +166,7 @@ const jsxShorthandFragment = createEslintRule({
|
|
|
166
166
|
},
|
|
167
167
|
fixable: "code",
|
|
168
168
|
hasSuggestions: false,
|
|
169
|
-
messages: messages$
|
|
169
|
+
messages: messages$8,
|
|
170
170
|
schema: schema$2,
|
|
171
171
|
type: "suggestion"
|
|
172
172
|
}
|
|
@@ -1331,8 +1331,8 @@ const SCHEMA = {
|
|
|
1331
1331
|
};
|
|
1332
1332
|
//#endregion
|
|
1333
1333
|
//#region src/rules/naming-convention/rule.ts
|
|
1334
|
-
const RULE_NAME$
|
|
1335
|
-
const messages$
|
|
1334
|
+
const RULE_NAME$7 = "naming-convention";
|
|
1335
|
+
const messages$7 = {
|
|
1336
1336
|
doesNotMatchFormat: "{{type}} name `{{name}}` must match one of the following formats: {{formats}}",
|
|
1337
1337
|
doesNotMatchFormatTrimmed: "{{type}} name `{{name}}` trimmed as `{{processedName}}` must match one of the following formats: {{formats}}",
|
|
1338
1338
|
missingAffix: "{{type}} name `{{name}}` must have one of the following {{position}}es: {{affixes}}",
|
|
@@ -1362,12 +1362,11 @@ const camelCaseNamingConfig = [
|
|
|
1362
1362
|
selector: "typeLike"
|
|
1363
1363
|
}
|
|
1364
1364
|
];
|
|
1365
|
-
function create$
|
|
1365
|
+
function create$7(contextWithoutDefaults) {
|
|
1366
1366
|
const context = contextWithoutDefaults.options.length > 0 ? contextWithoutDefaults : Object.setPrototypeOf({ options: camelCaseNamingConfig }, contextWithoutDefaults);
|
|
1367
1367
|
const validators = parseOptions(context);
|
|
1368
1368
|
const compilerOptions = getParserServices(context, true).program?.getCompilerOptions() ?? {};
|
|
1369
|
-
function handleMember(validator,
|
|
1370
|
-
const { key } = node;
|
|
1369
|
+
function handleMember(validator, { key }, modifiers) {
|
|
1371
1370
|
if (requiresQuoting$1(key, compilerOptions.target)) modifiers.add(Modifier.requiresQuotes);
|
|
1372
1371
|
validator(key, modifiers);
|
|
1373
1372
|
}
|
|
@@ -1600,8 +1599,7 @@ function create$6(contextWithoutDefaults) {
|
|
|
1600
1599
|
validator: validators.enum
|
|
1601
1600
|
},
|
|
1602
1601
|
"TSEnumMember": {
|
|
1603
|
-
handler: (
|
|
1604
|
-
const { id } = node;
|
|
1602
|
+
handler: ({ id }, validator) => {
|
|
1605
1603
|
const modifiers = /* @__PURE__ */ new Set();
|
|
1606
1604
|
if (requiresQuoting$1(id, compilerOptions.target)) modifiers.add(Modifier.requiresQuotes);
|
|
1607
1605
|
validator(id, modifiers);
|
|
@@ -1682,8 +1680,8 @@ function create$6(contextWithoutDefaults) {
|
|
|
1682
1680
|
}));
|
|
1683
1681
|
}
|
|
1684
1682
|
const namingConvention = createEslintRule({
|
|
1685
|
-
name: RULE_NAME$
|
|
1686
|
-
create: create$
|
|
1683
|
+
name: RULE_NAME$7,
|
|
1684
|
+
create: create$7,
|
|
1687
1685
|
defaultOptions: camelCaseNamingConfig,
|
|
1688
1686
|
meta: {
|
|
1689
1687
|
docs: {
|
|
@@ -1693,7 +1691,7 @@ const namingConvention = createEslintRule({
|
|
|
1693
1691
|
},
|
|
1694
1692
|
fixable: void 0,
|
|
1695
1693
|
hasSuggestions: false,
|
|
1696
|
-
messages: messages$
|
|
1694
|
+
messages: messages$7,
|
|
1697
1695
|
schema: SCHEMA,
|
|
1698
1696
|
type: "suggestion"
|
|
1699
1697
|
}
|
|
@@ -1813,8 +1811,7 @@ function resolve(sourceCode, node) {
|
|
|
1813
1811
|
* @returns A rule `create` function.
|
|
1814
1812
|
* @template MessageIds - The rule's message identifiers.
|
|
1815
1813
|
*/
|
|
1816
|
-
function createUnnecessaryHookRule(
|
|
1817
|
-
const { hook, messageIds } = config;
|
|
1814
|
+
function createUnnecessaryHookRule({ hook, messageIds }) {
|
|
1818
1815
|
const skipComputation = hook === "useMemo";
|
|
1819
1816
|
return (context) => {
|
|
1820
1817
|
const { sourceCode } = context;
|
|
@@ -1961,15 +1958,15 @@ function resolveFactory(sourceCode, node) {
|
|
|
1961
1958
|
}
|
|
1962
1959
|
//#endregion
|
|
1963
1960
|
//#region src/rules/no-unnecessary-use-callback/rule.ts
|
|
1964
|
-
const RULE_NAME$
|
|
1961
|
+
const RULE_NAME$6 = "no-unnecessary-use-callback";
|
|
1965
1962
|
const MESSAGE_ID_DEFAULT$1 = "default";
|
|
1966
1963
|
const MESSAGE_ID_INSIDE_USE_EFFECT$1 = "noUnnecessaryUseCallbackInsideUseEffect";
|
|
1967
|
-
const messages$
|
|
1964
|
+
const messages$6 = {
|
|
1968
1965
|
[MESSAGE_ID_DEFAULT$1]: "An 'useCallback' with empty deps and no references to the component scope may be unnecessary.",
|
|
1969
1966
|
[MESSAGE_ID_INSIDE_USE_EFFECT$1]: "'{{name}}' is only used inside 1 useEffect, which may be unnecessary. You can move the computation into useEffect directly and merge the dependency arrays."
|
|
1970
1967
|
};
|
|
1971
1968
|
const noUnnecessaryUseCallback = createEslintRule({
|
|
1972
|
-
name: RULE_NAME$
|
|
1969
|
+
name: RULE_NAME$6,
|
|
1973
1970
|
create: createUnnecessaryHookRule({
|
|
1974
1971
|
hook: "useCallback",
|
|
1975
1972
|
messageIds: {
|
|
@@ -1985,22 +1982,22 @@ const noUnnecessaryUseCallback = createEslintRule({
|
|
|
1985
1982
|
requiresTypeChecking: false
|
|
1986
1983
|
},
|
|
1987
1984
|
hasSuggestions: false,
|
|
1988
|
-
messages: messages$
|
|
1985
|
+
messages: messages$6,
|
|
1989
1986
|
schema: [],
|
|
1990
1987
|
type: "suggestion"
|
|
1991
1988
|
}
|
|
1992
1989
|
});
|
|
1993
1990
|
//#endregion
|
|
1994
1991
|
//#region src/rules/no-unnecessary-use-memo/rule.ts
|
|
1995
|
-
const RULE_NAME$
|
|
1992
|
+
const RULE_NAME$5 = "no-unnecessary-use-memo";
|
|
1996
1993
|
const MESSAGE_ID_DEFAULT = "default";
|
|
1997
1994
|
const MESSAGE_ID_INSIDE_USE_EFFECT = "noUnnecessaryUseMemoInsideUseEffect";
|
|
1998
|
-
const messages$
|
|
1995
|
+
const messages$5 = {
|
|
1999
1996
|
[MESSAGE_ID_DEFAULT]: "An 'useMemo' with empty deps and no references to the component scope may be unnecessary.",
|
|
2000
1997
|
[MESSAGE_ID_INSIDE_USE_EFFECT]: "'{{name}}' is only used inside 1 useEffect, which may be unnecessary. You can move the computation into useEffect directly and merge the dependency arrays."
|
|
2001
1998
|
};
|
|
2002
1999
|
const noUnnecessaryUseMemo = createEslintRule({
|
|
2003
|
-
name: RULE_NAME$
|
|
2000
|
+
name: RULE_NAME$5,
|
|
2004
2001
|
create: createUnnecessaryHookRule({
|
|
2005
2002
|
hook: "useMemo",
|
|
2006
2003
|
messageIds: {
|
|
@@ -2016,16 +2013,16 @@ const noUnnecessaryUseMemo = createEslintRule({
|
|
|
2016
2013
|
requiresTypeChecking: false
|
|
2017
2014
|
},
|
|
2018
2015
|
hasSuggestions: false,
|
|
2019
|
-
messages: messages$
|
|
2016
|
+
messages: messages$5,
|
|
2020
2017
|
schema: [],
|
|
2021
2018
|
type: "suggestion"
|
|
2022
2019
|
}
|
|
2023
2020
|
});
|
|
2024
2021
|
//#endregion
|
|
2025
2022
|
//#region src/rules/prefer-destructuring-assignment/rule.ts
|
|
2026
|
-
const RULE_NAME$
|
|
2027
|
-
const MESSAGE_ID$
|
|
2028
|
-
const messages$
|
|
2023
|
+
const RULE_NAME$4 = "prefer-destructuring-assignment";
|
|
2024
|
+
const MESSAGE_ID$3 = "default";
|
|
2025
|
+
const messages$4 = { [MESSAGE_ID$3]: "Use destructuring assignment for component props." };
|
|
2029
2026
|
/**
|
|
2030
2027
|
* Identifiers that cannot be used as a binding name in strict-mode module code.
|
|
2031
2028
|
* A property may be accessed with such a name (`props.default`), but a shorthand
|
|
@@ -2151,7 +2148,7 @@ function reportComponent(context, scope, propsParameter, propertyVariable) {
|
|
|
2151
2148
|
const propertyNames = collectPropertyNames(memberReferences);
|
|
2152
2149
|
if (!(!hasNonMemberReference && propertyNames !== null && !wouldShadowExistingBinding(context.sourceCode, scope, propertyVariable, memberReferences))) {
|
|
2153
2150
|
for (const { member } of memberReferences) context.report({
|
|
2154
|
-
messageId: MESSAGE_ID$
|
|
2151
|
+
messageId: MESSAGE_ID$3,
|
|
2155
2152
|
node: member
|
|
2156
2153
|
});
|
|
2157
2154
|
return;
|
|
@@ -2168,7 +2165,7 @@ function reportComponent(context, scope, propsParameter, propertyVariable) {
|
|
|
2168
2165
|
if (index === 0) return [fixer.replaceTextRange([propsParameter.range[0], nameEnd], pattern), replaceAccess];
|
|
2169
2166
|
return replaceAccess;
|
|
2170
2167
|
},
|
|
2171
|
-
messageId: MESSAGE_ID$
|
|
2168
|
+
messageId: MESSAGE_ID$3,
|
|
2172
2169
|
node: member
|
|
2173
2170
|
});
|
|
2174
2171
|
}
|
|
@@ -2187,7 +2184,7 @@ function reportComponent(context, scope, propsParameter, propertyVariable) {
|
|
|
2187
2184
|
* @param context - The rule context.
|
|
2188
2185
|
* @returns The rule listener.
|
|
2189
2186
|
*/
|
|
2190
|
-
function create$
|
|
2187
|
+
function create$4(context) {
|
|
2191
2188
|
const { api, visitor } = core.getFunctionComponentCollector(context);
|
|
2192
2189
|
return {
|
|
2193
2190
|
...visitor,
|
|
@@ -2205,8 +2202,8 @@ function create$3(context) {
|
|
|
2205
2202
|
};
|
|
2206
2203
|
}
|
|
2207
2204
|
const preferDestructuringAssignment = createEslintRule({
|
|
2208
|
-
name: RULE_NAME$
|
|
2209
|
-
create: create$
|
|
2205
|
+
name: RULE_NAME$4,
|
|
2206
|
+
create: create$4,
|
|
2210
2207
|
defaultOptions: [],
|
|
2211
2208
|
meta: {
|
|
2212
2209
|
docs: {
|
|
@@ -2216,12 +2213,364 @@ const preferDestructuringAssignment = createEslintRule({
|
|
|
2216
2213
|
},
|
|
2217
2214
|
fixable: "code",
|
|
2218
2215
|
hasSuggestions: false,
|
|
2219
|
-
messages: messages$
|
|
2216
|
+
messages: messages$4,
|
|
2220
2217
|
schema: [],
|
|
2221
2218
|
type: "problem"
|
|
2222
2219
|
}
|
|
2223
2220
|
});
|
|
2224
2221
|
//#endregion
|
|
2222
|
+
//#region src/rules/prefer-parameter-destructuring/rule.ts
|
|
2223
|
+
const RULE_NAME$3 = "prefer-parameter-destructuring";
|
|
2224
|
+
const MESSAGE_ID$2 = "default";
|
|
2225
|
+
const messages$3 = { [MESSAGE_ID$2]: "Destructure parameter '{{name}}' in the function signature instead of the body." };
|
|
2226
|
+
/**
|
|
2227
|
+
* Collects the binding names introduced by a pattern (or parameter), including
|
|
2228
|
+
* names nested in object/array patterns, defaults, and rest elements.
|
|
2229
|
+
*
|
|
2230
|
+
* @param node - The pattern node to walk.
|
|
2231
|
+
* @param out - Receives every bound name, in source order.
|
|
2232
|
+
*/
|
|
2233
|
+
function collectBoundNames(node, out) {
|
|
2234
|
+
switch (node.type) {
|
|
2235
|
+
case AST_NODE_TYPES.ArrayPattern:
|
|
2236
|
+
for (const element of node.elements) if (element !== null) collectBoundNames(element, out);
|
|
2237
|
+
break;
|
|
2238
|
+
case AST_NODE_TYPES.AssignmentPattern:
|
|
2239
|
+
collectBoundNames(node.left, out);
|
|
2240
|
+
break;
|
|
2241
|
+
case AST_NODE_TYPES.Identifier:
|
|
2242
|
+
out.push(node.name);
|
|
2243
|
+
break;
|
|
2244
|
+
case AST_NODE_TYPES.ObjectPattern:
|
|
2245
|
+
for (const property of node.properties) collectBoundNames(property, out);
|
|
2246
|
+
break;
|
|
2247
|
+
case AST_NODE_TYPES.Property:
|
|
2248
|
+
collectBoundNames(node.value, out);
|
|
2249
|
+
break;
|
|
2250
|
+
case AST_NODE_TYPES.RestElement:
|
|
2251
|
+
collectBoundNames(node.argument, out);
|
|
2252
|
+
break;
|
|
2253
|
+
case AST_NODE_TYPES.TSParameterProperty:
|
|
2254
|
+
collectBoundNames(node.parameter, out);
|
|
2255
|
+
break;
|
|
2256
|
+
default: break;
|
|
2257
|
+
}
|
|
2258
|
+
}
|
|
2259
|
+
/**
|
|
2260
|
+
* Collects every top-level-body object destructuring of the parameter, or
|
|
2261
|
+
* bails when the parameter has any other reference (member access, call
|
|
2262
|
+
* argument, reassignment, a destructure inside a nested block or closure, …) —
|
|
2263
|
+
* those mean the parameter is genuinely used and must stay.
|
|
2264
|
+
*
|
|
2265
|
+
* @param variable - The parameter's resolved scope variable.
|
|
2266
|
+
* @param identifier - The parameter identifier (its default-value write
|
|
2267
|
+
* reference is not a use).
|
|
2268
|
+
* @param body - The function body; only its direct child declarations qualify.
|
|
2269
|
+
* @returns The qualifying destructuring statements in source order, or `null`
|
|
2270
|
+
* when the parameter has a non-destructuring reference.
|
|
2271
|
+
*/
|
|
2272
|
+
function collectDestructureStatements(variable, identifier, body) {
|
|
2273
|
+
const statements = [];
|
|
2274
|
+
for (const reference of variable.references) {
|
|
2275
|
+
const referenceIdentifier = reference.identifier;
|
|
2276
|
+
if (referenceIdentifier === identifier) continue;
|
|
2277
|
+
const { parent } = referenceIdentifier;
|
|
2278
|
+
if (parent.type === AST_NODE_TYPES.VariableDeclarator && parent.init === referenceIdentifier && parent.id.type === AST_NODE_TYPES.ObjectPattern && parent.parent.parent === body) statements.push({
|
|
2279
|
+
declaration: parent.parent,
|
|
2280
|
+
declarator: parent,
|
|
2281
|
+
pattern: parent.id
|
|
2282
|
+
});
|
|
2283
|
+
else return null;
|
|
2284
|
+
}
|
|
2285
|
+
statements.sort((left, right) => left.declarator.range[0] - right.declarator.range[0]);
|
|
2286
|
+
return statements;
|
|
2287
|
+
}
|
|
2288
|
+
/**
|
|
2289
|
+
* Collects the binding names of every parameter other than the target one, so
|
|
2290
|
+
* the fix can avoid creating a duplicate parameter name (a SyntaxError in a
|
|
2291
|
+
* non-simple parameter list).
|
|
2292
|
+
*
|
|
2293
|
+
* @param node - The function whose parameters are inspected.
|
|
2294
|
+
* @param parameter - The parameter being rewritten (excluded).
|
|
2295
|
+
* @returns The other parameters' bound names.
|
|
2296
|
+
*/
|
|
2297
|
+
function collectOtherParameterNames(node, parameter) {
|
|
2298
|
+
const names = [];
|
|
2299
|
+
for (const other of node.params) if (other !== parameter) collectBoundNames(other, names);
|
|
2300
|
+
return new Set(names);
|
|
2301
|
+
}
|
|
2302
|
+
/**
|
|
2303
|
+
* A structural check for AST nodes reached through visitor keys.
|
|
2304
|
+
*
|
|
2305
|
+
* @param value - The child value to test.
|
|
2306
|
+
* @returns `true` when the value is an AST node.
|
|
2307
|
+
*/
|
|
2308
|
+
function isNodeLike(value) {
|
|
2309
|
+
return typeof value === "object" && value !== null && typeof value.type === "string";
|
|
2310
|
+
}
|
|
2311
|
+
/**
|
|
2312
|
+
* Checks whether a pattern subtree contains `await` or `yield` (in a computed
|
|
2313
|
+
* key or default value). Parameter initializers may not contain either, so no
|
|
2314
|
+
* signature form exists and the destructuring is not reported.
|
|
2315
|
+
*
|
|
2316
|
+
* @param root - The pattern to walk.
|
|
2317
|
+
* @param visitorKeys - The parser's visitor keys, used to walk without
|
|
2318
|
+
* following `parent` links.
|
|
2319
|
+
* @returns `true` if `await`/`yield` appears anywhere in the pattern.
|
|
2320
|
+
*/
|
|
2321
|
+
function containsAwaitOrYield(root, visitorKeys) {
|
|
2322
|
+
const stack = [root];
|
|
2323
|
+
for (let current = stack.pop(); current !== void 0; current = stack.pop()) {
|
|
2324
|
+
if (current.type === AST_NODE_TYPES.AwaitExpression || current.type === AST_NODE_TYPES.YieldExpression) return true;
|
|
2325
|
+
for (const key of visitorKeys[current.type] ?? []) {
|
|
2326
|
+
const child = current[key];
|
|
2327
|
+
const children = Array.isArray(child) ? child : [child];
|
|
2328
|
+
for (const item of children) if (isNodeLike(item)) stack.push(item);
|
|
2329
|
+
}
|
|
2330
|
+
}
|
|
2331
|
+
return false;
|
|
2332
|
+
}
|
|
2333
|
+
/**
|
|
2334
|
+
* Extracts the identifier a parameter binds, unwrapping a default value
|
|
2335
|
+
* (`obj = {}`); patterns, rest parameters, and TS parameter properties yield
|
|
2336
|
+
* `null`.
|
|
2337
|
+
*
|
|
2338
|
+
* @param parameter - The parameter node.
|
|
2339
|
+
* @returns The parameter's identifier, or `null` when it is not a plain one.
|
|
2340
|
+
*/
|
|
2341
|
+
function getParameterIdentifier(parameter) {
|
|
2342
|
+
if (parameter.type === AST_NODE_TYPES.Identifier) return parameter;
|
|
2343
|
+
if (parameter.type === AST_NODE_TYPES.AssignmentPattern && parameter.left.type === AST_NODE_TYPES.Identifier) return parameter.left;
|
|
2344
|
+
return null;
|
|
2345
|
+
}
|
|
2346
|
+
/**
|
|
2347
|
+
* Determines whether any expression inside the patterns (computed keys,
|
|
2348
|
+
* default values, moved type annotations) references a binding that would be
|
|
2349
|
+
* out of scope — or in its temporal dead zone — at the parameter position:
|
|
2350
|
+
* anything declared in the function body, a parameter at or after the target,
|
|
2351
|
+
* or this function's own `arguments`.
|
|
2352
|
+
*
|
|
2353
|
+
* @param query - The rewrite being planned.
|
|
2354
|
+
* @param patterns - The object patterns being moved.
|
|
2355
|
+
* @returns `true` when moving the patterns would break a reference.
|
|
2356
|
+
*/
|
|
2357
|
+
function hasUnsafePatternReferences({ body, identifier, node, scope }, patterns) {
|
|
2358
|
+
function inPattern(range) {
|
|
2359
|
+
return patterns.some((pattern) => range[0] >= pattern.range[0] && range[1] <= pattern.range[1]);
|
|
2360
|
+
}
|
|
2361
|
+
const stack = [scope];
|
|
2362
|
+
for (let current = stack.pop(); current !== void 0; current = stack.pop()) {
|
|
2363
|
+
stack.push(...current.childScopes);
|
|
2364
|
+
for (const reference of current.references) {
|
|
2365
|
+
if (!inPattern(reference.identifier.range)) continue;
|
|
2366
|
+
const { resolved } = reference;
|
|
2367
|
+
if (resolved === null) continue;
|
|
2368
|
+
if (resolved.defs.length === 0) {
|
|
2369
|
+
const blockRange = resolved.scope.block.range;
|
|
2370
|
+
if (blockRange[0] >= node.range[0] && blockRange[1] <= node.range[1]) return true;
|
|
2371
|
+
continue;
|
|
2372
|
+
}
|
|
2373
|
+
if (resolved.defs.some((definition) => {
|
|
2374
|
+
const { range } = definition.name;
|
|
2375
|
+
if (inPattern(range)) return false;
|
|
2376
|
+
if (range[1] <= node.range[0] || range[0] >= node.range[1]) return false;
|
|
2377
|
+
if (range[0] >= body.range[0]) return true;
|
|
2378
|
+
return range[0] >= identifier.range[0];
|
|
2379
|
+
})) return true;
|
|
2380
|
+
}
|
|
2381
|
+
}
|
|
2382
|
+
return false;
|
|
2383
|
+
}
|
|
2384
|
+
/**
|
|
2385
|
+
* Checks whether a function body opens with a `"use strict"` directive. A
|
|
2386
|
+
* destructured parameter makes the parameter list non-simple, and a function
|
|
2387
|
+
* with a non-simple parameter list may not contain a `"use strict"` directive,
|
|
2388
|
+
* so such functions are skipped entirely.
|
|
2389
|
+
*
|
|
2390
|
+
* @param body - The function body.
|
|
2391
|
+
* @returns `true` if the body has a `"use strict"` directive.
|
|
2392
|
+
*/
|
|
2393
|
+
function hasUseStrictDirective(body) {
|
|
2394
|
+
for (const statement of body.body) {
|
|
2395
|
+
if (statement.type !== AST_NODE_TYPES.ExpressionStatement || typeof statement.directive !== "string") break;
|
|
2396
|
+
if (statement.directive === "use strict") return true;
|
|
2397
|
+
}
|
|
2398
|
+
return false;
|
|
2399
|
+
}
|
|
2400
|
+
/**
|
|
2401
|
+
* Checks whether evaluating the pattern can execute arbitrary code — a default
|
|
2402
|
+
* value or a computed key — as opposed to only performing property reads.
|
|
2403
|
+
*
|
|
2404
|
+
* @param node - The pattern node to walk.
|
|
2405
|
+
* @returns `true` when the pattern contains a default value or computed key.
|
|
2406
|
+
*/
|
|
2407
|
+
function patternExecutesCode(node) {
|
|
2408
|
+
if (node.type === AST_NODE_TYPES.AssignmentPattern) return true;
|
|
2409
|
+
if (node.type === AST_NODE_TYPES.Property) return node.computed || patternExecutesCode(node.value);
|
|
2410
|
+
if (node.type === AST_NODE_TYPES.ObjectPattern) return node.properties.some((property) => patternExecutesCode(property));
|
|
2411
|
+
if (node.type === AST_NODE_TYPES.ArrayPattern) return node.elements.some((element) => element !== null && patternExecutesCode(element));
|
|
2412
|
+
if (node.type === AST_NODE_TYPES.RestElement) return patternExecutesCode(node.argument);
|
|
2413
|
+
return false;
|
|
2414
|
+
}
|
|
2415
|
+
/**
|
|
2416
|
+
* Computes the removal range for a declaration, swallowing the whole line
|
|
2417
|
+
* (indentation and trailing newline) when the declaration is alone on it.
|
|
2418
|
+
*
|
|
2419
|
+
* @param sourceCode - Provides the raw text around the declaration.
|
|
2420
|
+
* @param statement - The declaration to remove.
|
|
2421
|
+
* @returns The range to delete.
|
|
2422
|
+
*/
|
|
2423
|
+
function statementRemovalRange({ text }, statement) {
|
|
2424
|
+
const [start, end] = statement.range;
|
|
2425
|
+
const lineStart = text.lastIndexOf("\n", start - 1) + 1;
|
|
2426
|
+
const newlineIndex = text.indexOf("\n", end);
|
|
2427
|
+
const lineEnd = newlineIndex === -1 ? text.length : newlineIndex + 1;
|
|
2428
|
+
const leadingIsBlank = text.slice(lineStart, start).trim().length === 0;
|
|
2429
|
+
const trailingIsBlank = text.slice(end, newlineIndex === -1 ? text.length : newlineIndex).trim().length === 0;
|
|
2430
|
+
if (leadingIsBlank && trailingIsBlank) return [lineStart, lineEnd];
|
|
2431
|
+
return [start, end];
|
|
2432
|
+
}
|
|
2433
|
+
/**
|
|
2434
|
+
* Builds the autofix, or returns `null` when the rewrite is not unambiguously
|
|
2435
|
+
* safe: unrelated sibling declarators, unmergeable or annotated patterns,
|
|
2436
|
+
* duplicate or colliding binding names, expressions that reference bindings
|
|
2437
|
+
* unavailable at the parameter position, a defused temporal dead zone, or —
|
|
2438
|
+
* with `allowSideEffectReordering: false` — side effects that would be
|
|
2439
|
+
* reordered.
|
|
2440
|
+
*
|
|
2441
|
+
* @param query - The rewrite being planned.
|
|
2442
|
+
* @returns The fix plan, or `null` when only a report should be emitted.
|
|
2443
|
+
*/
|
|
2444
|
+
function planFix(query) {
|
|
2445
|
+
const { allowSideEffectReordering, body, identifier, node, otherParameterNames, sourceCode, statements } = query;
|
|
2446
|
+
const declaratorSet = new Set(statements.map((statement) => statement.declarator));
|
|
2447
|
+
const declarations = [...new Set(statements.map((statement) => statement.declaration))];
|
|
2448
|
+
if (!declarations.every((declaration) => {
|
|
2449
|
+
return declaration.declarations.every((declarator) => declaratorSet.has(declarator));
|
|
2450
|
+
})) return null;
|
|
2451
|
+
const patterns = statements.map((statement) => statement.pattern);
|
|
2452
|
+
if (!allowSideEffectReordering && patterns.some((pattern) => patternExecutesCode(pattern))) {
|
|
2453
|
+
const leadingStatements = new Set(body.body.slice(0, declarations.length));
|
|
2454
|
+
if (!declarations.every((declaration) => leadingStatements.has(declaration))) return null;
|
|
2455
|
+
}
|
|
2456
|
+
if (declarations.some((declaration) => {
|
|
2457
|
+
return sourceCode.getDeclaredVariables(declaration).some((declared) => {
|
|
2458
|
+
return declared.references.some((reference) => reference.identifier.range[0] < declaration.range[0]);
|
|
2459
|
+
});
|
|
2460
|
+
})) return null;
|
|
2461
|
+
if (patterns.some((pattern) => pattern.typeAnnotation !== void 0) && (patterns.length > 1 || identifier.typeAnnotation !== void 0)) return null;
|
|
2462
|
+
if (patterns.length > 1) {
|
|
2463
|
+
if (patterns.some((pattern) => {
|
|
2464
|
+
return pattern.properties.some((property) => property.type === AST_NODE_TYPES.RestElement);
|
|
2465
|
+
})) return null;
|
|
2466
|
+
}
|
|
2467
|
+
const boundNames = [];
|
|
2468
|
+
for (const pattern of patterns) collectBoundNames(pattern, boundNames);
|
|
2469
|
+
if (new Set(boundNames).size !== boundNames.length) return null;
|
|
2470
|
+
if (boundNames.some((name) => otherParameterNames.has(name))) return null;
|
|
2471
|
+
if (hasUnsafePatternReferences(query, patterns)) return null;
|
|
2472
|
+
const [firstPattern] = patterns;
|
|
2473
|
+
let parameterText;
|
|
2474
|
+
if (patterns.length === 1 && firstPattern !== void 0) parameterText = sourceCode.getText(firstPattern);
|
|
2475
|
+
else {
|
|
2476
|
+
const innerTexts = patterns.map((pattern) => sourceCode.getText(pattern).slice(1, -1).trim().replace(/,$/u, "").trim()).filter((text) => text.length > 0);
|
|
2477
|
+
parameterText = innerTexts.length === 0 ? "{}" : `{ ${innerTexts.join(", ")} }`;
|
|
2478
|
+
}
|
|
2479
|
+
if (node.type === AST_NODE_TYPES.ArrowFunctionExpression && sourceCode.getTokenAfter(identifier)?.value === "=>") parameterText = `(${parameterText})`;
|
|
2480
|
+
const parameterRange = [identifier.range[0], identifier.typeAnnotation?.range[0] ?? identifier.range[1]];
|
|
2481
|
+
const removalRanges = declarations.map((declaration) => {
|
|
2482
|
+
return statementRemovalRange(sourceCode, declaration);
|
|
2483
|
+
});
|
|
2484
|
+
return {
|
|
2485
|
+
parameterRange,
|
|
2486
|
+
parameterText,
|
|
2487
|
+
removalRanges
|
|
2488
|
+
};
|
|
2489
|
+
}
|
|
2490
|
+
/**
|
|
2491
|
+
* Reports body destructuring statements of parameters that have no other use,
|
|
2492
|
+
* preferring the pattern in the function signature. The autofix rewrites the
|
|
2493
|
+
* parameter (merging multiple statements into one pattern) and removes the
|
|
2494
|
+
* statements; it is withheld when the rewrite is not unambiguously safe, see
|
|
2495
|
+
* {@link planFix}.
|
|
2496
|
+
*
|
|
2497
|
+
* @param context - The rule context.
|
|
2498
|
+
* @param optionsWithDefault - The resolved rule options.
|
|
2499
|
+
* @returns The rule listener.
|
|
2500
|
+
*/
|
|
2501
|
+
function create$3(context, optionsWithDefault) {
|
|
2502
|
+
const [{ allowSideEffectReordering = true }] = optionsWithDefault;
|
|
2503
|
+
function checkFunction(node) {
|
|
2504
|
+
const { body, params } = node;
|
|
2505
|
+
if (body.type !== AST_NODE_TYPES.BlockStatement || hasUseStrictDirective(body)) return;
|
|
2506
|
+
const scope = context.sourceCode.getScope(node);
|
|
2507
|
+
for (const parameter of params) {
|
|
2508
|
+
const identifier = getParameterIdentifier(parameter);
|
|
2509
|
+
if (identifier === null || identifier.name === "this") continue;
|
|
2510
|
+
const variable = scope.variables.find((candidate) => {
|
|
2511
|
+
return candidate.defs.some((definition) => definition.name === identifier);
|
|
2512
|
+
});
|
|
2513
|
+
if (variable?.defs.length !== 1) continue;
|
|
2514
|
+
const statements = collectDestructureStatements(variable, identifier, body);
|
|
2515
|
+
if (statements === null || statements.length === 0) continue;
|
|
2516
|
+
if (statements.some(({ pattern }) => {
|
|
2517
|
+
return containsAwaitOrYield(pattern, context.sourceCode.visitorKeys);
|
|
2518
|
+
})) continue;
|
|
2519
|
+
const otherParameterNames = collectOtherParameterNames(node, parameter);
|
|
2520
|
+
if (otherParameterNames.has(identifier.name)) continue;
|
|
2521
|
+
const plan = planFix({
|
|
2522
|
+
allowSideEffectReordering,
|
|
2523
|
+
body,
|
|
2524
|
+
identifier,
|
|
2525
|
+
node,
|
|
2526
|
+
otherParameterNames,
|
|
2527
|
+
scope,
|
|
2528
|
+
sourceCode: context.sourceCode,
|
|
2529
|
+
statements
|
|
2530
|
+
});
|
|
2531
|
+
for (const [index, statement] of statements.entries()) context.report({
|
|
2532
|
+
data: { name: identifier.name },
|
|
2533
|
+
fix(fixer) {
|
|
2534
|
+
if (index !== 0 || plan === null) return null;
|
|
2535
|
+
return [fixer.replaceTextRange(plan.parameterRange, plan.parameterText), ...plan.removalRanges.map((range) => fixer.removeRange(range))];
|
|
2536
|
+
},
|
|
2537
|
+
messageId: MESSAGE_ID$2,
|
|
2538
|
+
node: statement.declarator
|
|
2539
|
+
});
|
|
2540
|
+
}
|
|
2541
|
+
}
|
|
2542
|
+
return {
|
|
2543
|
+
ArrowFunctionExpression: checkFunction,
|
|
2544
|
+
FunctionDeclaration: checkFunction,
|
|
2545
|
+
FunctionExpression: checkFunction
|
|
2546
|
+
};
|
|
2547
|
+
}
|
|
2548
|
+
const preferParameterDestructuring = createEslintRule({
|
|
2549
|
+
name: RULE_NAME$3,
|
|
2550
|
+
create: create$3,
|
|
2551
|
+
defaultOptions: [{ allowSideEffectReordering: true }],
|
|
2552
|
+
meta: {
|
|
2553
|
+
defaultOptions: [{ allowSideEffectReordering: true }],
|
|
2554
|
+
docs: {
|
|
2555
|
+
description: "Enforce destructuring parameters in the function signature",
|
|
2556
|
+
recommended: false,
|
|
2557
|
+
requiresTypeChecking: false
|
|
2558
|
+
},
|
|
2559
|
+
fixable: "code",
|
|
2560
|
+
hasSuggestions: false,
|
|
2561
|
+
messages: messages$3,
|
|
2562
|
+
schema: [{
|
|
2563
|
+
additionalProperties: false,
|
|
2564
|
+
properties: { allowSideEffectReordering: {
|
|
2565
|
+
description: "Whether the autofix may hoist pattern defaults and computed keys past earlier statements, reordering their side effects. Set to false to withhold the fix in those cases.",
|
|
2566
|
+
type: "boolean"
|
|
2567
|
+
} },
|
|
2568
|
+
type: "object"
|
|
2569
|
+
}],
|
|
2570
|
+
type: "suggestion"
|
|
2571
|
+
}
|
|
2572
|
+
});
|
|
2573
|
+
//#endregion
|
|
2225
2574
|
//#region src/rules/purity/rule.ts
|
|
2226
2575
|
const RULE_NAME$2 = "purity";
|
|
2227
2576
|
const MESSAGE_ID$1 = "impureCall";
|
|
@@ -2460,8 +2809,7 @@ function makeRank(order) {
|
|
|
2460
2809
|
return Number.POSITIVE_INFINITY;
|
|
2461
2810
|
};
|
|
2462
2811
|
}
|
|
2463
|
-
function makeFallback(
|
|
2464
|
-
const { caseSensitive = true, natural = false, type = "asc" } = config;
|
|
2812
|
+
function makeFallback({ caseSensitive = true, natural = false, type = "asc" }) {
|
|
2465
2813
|
const sensitivity = caseSensitive ? "variant" : "accent";
|
|
2466
2814
|
return (a, b) => {
|
|
2467
2815
|
const result = a.localeCompare(b, "en", {
|
|
@@ -2709,6 +3057,7 @@ const plugin = {
|
|
|
2709
3057
|
"no-unnecessary-use-callback": noUnnecessaryUseCallback,
|
|
2710
3058
|
"no-unnecessary-use-memo": noUnnecessaryUseMemo,
|
|
2711
3059
|
"prefer-destructuring-assignment": preferDestructuringAssignment,
|
|
3060
|
+
"prefer-parameter-destructuring": preferParameterDestructuring,
|
|
2712
3061
|
"purity": purity,
|
|
2713
3062
|
"toml-sort-keys": tomlSortKeys,
|
|
2714
3063
|
"yaml-block-key-blank-lines": yamlBlockKeyBlankLines
|