@blumintinc/eslint-plugin-blumint 1.14.0 → 1.16.0
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 +36 -14
- package/lib/index.js +20 -12
- package/lib/rules/avoid-utils-directory.js +0 -4
- package/lib/rules/consistent-callback-naming.js +68 -3
- package/lib/rules/dynamic-https-errors.d.ts +1 -1
- package/lib/rules/dynamic-https-errors.js +119 -49
- package/lib/rules/enforce-boolean-naming-prefixes.d.ts +1 -0
- package/lib/rules/enforce-boolean-naming-prefixes.js +86 -331
- package/lib/rules/enforce-date-ttime.d.ts +1 -0
- package/lib/rules/enforce-date-ttime.js +156 -0
- package/lib/rules/enforce-dynamic-firebase-imports.d.ts +2 -1
- package/lib/rules/enforce-dynamic-firebase-imports.js +3 -2
- package/lib/rules/enforce-dynamic-imports.d.ts +2 -1
- package/lib/rules/enforce-dynamic-imports.js +42 -21
- package/lib/rules/enforce-f-extension-for-entry-points.d.ts +8 -0
- package/lib/rules/enforce-f-extension-for-entry-points.js +283 -0
- package/lib/rules/enforce-global-constants.js +3 -3
- package/lib/rules/enforce-id-capitalization.js +1 -1
- package/lib/rules/enforce-memoize-async.js +66 -15
- package/lib/rules/enforce-mui-rounded-icons.js +42 -1
- package/lib/rules/enforce-props-argument-name.js +42 -16
- package/lib/rules/enforce-stable-hash-spread-props.js +3 -3
- package/lib/rules/enforce-transform-memoization.js +1 -1
- package/lib/rules/enforce-verb-noun-naming.js +3817 -4641
- package/lib/rules/global-const-style.js +25 -4
- package/lib/rules/logical-top-to-bottom-grouping.js +80 -2
- package/lib/rules/memo-compare-deeply-complex-props.js +183 -6
- package/lib/rules/memo-nested-react-components.js +243 -103
- package/lib/rules/no-array-length-in-deps.js +74 -3
- package/lib/rules/no-async-foreach.js +7 -2
- package/lib/rules/no-circular-references.d.ts +2 -1
- package/lib/rules/no-circular-references.js +150 -489
- package/lib/rules/no-compositing-layer-props.js +31 -0
- package/lib/rules/no-console-error.js +12 -10
- package/lib/rules/no-empty-dependency-use-callbacks.js +1 -1
- package/lib/rules/no-entire-object-hook-deps.js +147 -65
- package/lib/rules/no-excessive-parent-chain.js +3 -0
- package/lib/rules/no-explicit-return-type.js +6 -0
- package/lib/rules/no-hungarian.js +119 -24
- package/lib/rules/no-inline-component-prop.js +16 -7
- package/lib/rules/no-margin-properties.js +7 -38
- package/lib/rules/no-passthrough-getters.d.ts +2 -2
- package/lib/rules/no-passthrough-getters.js +83 -1
- package/lib/rules/no-redundant-this-params.js +50 -1
- package/lib/rules/no-unmemoized-memo-without-props.js +1 -1
- package/lib/rules/no-unnecessary-destructuring-rename.js +2 -5
- package/lib/rules/no-unnecessary-verb-suffix.js +79 -0
- package/lib/rules/no-unused-props.js +215 -37
- package/lib/rules/no-useless-fragment.js +10 -2
- package/lib/rules/parallelize-async-operations.js +117 -54
- package/lib/rules/prefer-nullish-coalescing-boolean-props.js +109 -4
- package/lib/rules/prefer-params-over-parent-id.js +1 -1
- package/lib/rules/prefer-settings-object.js +27 -10
- package/lib/rules/prefer-type-alias-over-typeof-constant.js +75 -4
- package/lib/rules/prefer-use-deep-compare-memo.js +8 -14
- package/lib/rules/prefer-usememo-over-useeffect-usestate.js +1 -1
- package/lib/rules/prevent-children-clobber.js +9 -5
- package/lib/rules/react-memoize-literals.js +218 -13
- package/lib/rules/require-https-error-cause.js +30 -11
- package/lib/rules/require-memo.js +17 -9
- package/lib/rules/require-migration-script-metadata.d.ts +9 -0
- package/lib/rules/require-migration-script-metadata.js +206 -0
- package/lib/rules/warn-https-error-message-user-friendly.d.ts +1 -0
- package/lib/rules/warn-https-error-message-user-friendly.js +239 -0
- package/lib/utils/ASTHelpers.d.ts +49 -1
- package/lib/utils/ASTHelpers.js +394 -112
- package/package.json +7 -6
- package/release-manifest.json +166 -0
|
@@ -3,7 +3,8 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.enforceMemoizeAsync = void 0;
|
|
4
4
|
const utils_1 = require("@typescript-eslint/utils");
|
|
5
5
|
const createRule_1 = require("../utils/createRule");
|
|
6
|
-
const MEMOIZE_MODULE = 'typescript-memoize';
|
|
6
|
+
const MEMOIZE_MODULE = '@blumintinc/typescript-memoize';
|
|
7
|
+
const ALLOWED_MEMOIZE_MODULES = new Set([MEMOIZE_MODULE, 'typescript-memoize']);
|
|
7
8
|
/**
|
|
8
9
|
* Matches a memoize decorator in supported syntaxes:
|
|
9
10
|
* - @Alias()
|
|
@@ -38,33 +39,34 @@ exports.enforceMemoizeAsync = (0, createRule_1.createRule)({
|
|
|
38
39
|
meta: {
|
|
39
40
|
type: 'suggestion',
|
|
40
41
|
docs: {
|
|
41
|
-
description: 'Enforce @Memoize() decorator on async methods with 0-1 parameters to cache results and prevent redundant API calls or expensive computations.
|
|
42
|
+
description: 'Enforce @Memoize() decorator on async methods with 0-1 parameters to cache results and prevent redundant API calls or expensive computations. Without memoization, repeated calls trigger redundant requests or expensive computations, increasing latency. @Memoize() caches results by parameter, ensuring subsequent calls with identical inputs return immediately.',
|
|
42
43
|
recommended: 'error',
|
|
43
44
|
},
|
|
44
45
|
fixable: 'code',
|
|
45
46
|
schema: [],
|
|
46
47
|
messages: {
|
|
47
|
-
requireMemoize: 'Async methods with 0-1 parameters should be decorated with @Memoize()
|
|
48
|
+
requireMemoize: 'Async methods with 0-1 parameters should be decorated with @Memoize(). Without memoization, repeated calls trigger redundant network requests or expensive computations, increasing latency and risk of rate-limiting. @Memoize() caches results by parameter, ensuring subsequent calls with identical inputs return immediately. Fix: add @Memoize() above the method and import Memoize from "@blumintinc/typescript-memoize".',
|
|
48
49
|
},
|
|
49
50
|
},
|
|
50
51
|
defaultOptions: [],
|
|
51
52
|
create(context) {
|
|
52
53
|
let hasMemoizeImport = false;
|
|
53
|
-
|
|
54
|
-
|
|
54
|
+
const memoizeAliases = new Map(); // alias -> source module
|
|
55
|
+
const memoizeNamespaces = new Map(); // namespace -> source module
|
|
55
56
|
let scheduledImportFix = false;
|
|
56
57
|
return {
|
|
57
58
|
ImportDeclaration(node) {
|
|
58
|
-
if (node.source.value
|
|
59
|
+
if (ALLOWED_MEMOIZE_MODULES.has(String(node.source.value))) {
|
|
59
60
|
node.specifiers.forEach((spec) => {
|
|
60
61
|
if (spec.type === utils_1.AST_NODE_TYPES.ImportSpecifier &&
|
|
62
|
+
spec.imported.type === utils_1.AST_NODE_TYPES.Identifier &&
|
|
61
63
|
spec.imported.name === 'Memoize') {
|
|
62
64
|
hasMemoizeImport = true;
|
|
63
|
-
|
|
65
|
+
memoizeAliases.set(spec.local.name, String(node.source.value));
|
|
64
66
|
}
|
|
65
67
|
else if (spec.type === utils_1.AST_NODE_TYPES.ImportNamespaceSpecifier) {
|
|
66
68
|
hasMemoizeImport = true;
|
|
67
|
-
|
|
69
|
+
memoizeNamespaces.set(spec.local.name, String(node.source.value));
|
|
68
70
|
}
|
|
69
71
|
});
|
|
70
72
|
}
|
|
@@ -81,7 +83,39 @@ exports.enforceMemoizeAsync = (0, createRule_1.createRule)({
|
|
|
81
83
|
return;
|
|
82
84
|
}
|
|
83
85
|
// Check if method already has @Memoize or @Memoize() decorator
|
|
84
|
-
const hasDecorator = node.decorators?.some((decorator) =>
|
|
86
|
+
const hasDecorator = node.decorators?.some((decorator) => {
|
|
87
|
+
// If no named imports were found, we assume 'Memoize' is the intended name (for legacy/global support)
|
|
88
|
+
const aliasesToCheck = memoizeAliases.size === 0
|
|
89
|
+
? ['Memoize']
|
|
90
|
+
: Array.from(memoizeAliases.keys());
|
|
91
|
+
// Check against all known aliases
|
|
92
|
+
for (const alias of aliasesToCheck) {
|
|
93
|
+
if (isMemoizeDecorator(decorator, alias)) {
|
|
94
|
+
return true;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
// Also check against namespaces
|
|
98
|
+
const expression = decorator.expression;
|
|
99
|
+
if (expression.type === utils_1.AST_NODE_TYPES.MemberExpression &&
|
|
100
|
+
!expression.computed &&
|
|
101
|
+
expression.property.type === utils_1.AST_NODE_TYPES.Identifier &&
|
|
102
|
+
expression.property.name === 'Memoize' &&
|
|
103
|
+
expression.object.type === utils_1.AST_NODE_TYPES.Identifier &&
|
|
104
|
+
memoizeNamespaces.has(expression.object.name)) {
|
|
105
|
+
return true;
|
|
106
|
+
}
|
|
107
|
+
// Handle namespace call: @ns.Memoize()
|
|
108
|
+
if (expression.type === utils_1.AST_NODE_TYPES.CallExpression &&
|
|
109
|
+
expression.callee.type === utils_1.AST_NODE_TYPES.MemberExpression &&
|
|
110
|
+
!expression.callee.computed &&
|
|
111
|
+
expression.callee.property.type === utils_1.AST_NODE_TYPES.Identifier &&
|
|
112
|
+
expression.callee.property.name === 'Memoize' &&
|
|
113
|
+
expression.callee.object.type === utils_1.AST_NODE_TYPES.Identifier &&
|
|
114
|
+
memoizeNamespaces.has(expression.callee.object.name)) {
|
|
115
|
+
return true;
|
|
116
|
+
}
|
|
117
|
+
return false;
|
|
118
|
+
});
|
|
85
119
|
if (hasDecorator) {
|
|
86
120
|
return;
|
|
87
121
|
}
|
|
@@ -91,15 +125,32 @@ exports.enforceMemoizeAsync = (0, createRule_1.createRule)({
|
|
|
91
125
|
fix(fixer) {
|
|
92
126
|
const fixes = [];
|
|
93
127
|
const sourceCode = context.sourceCode;
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
128
|
+
// Determine which identifier to use for the decorator
|
|
129
|
+
let decoratorIdent = 'Memoize';
|
|
130
|
+
if (hasMemoizeImport) {
|
|
131
|
+
// Prefer 'Memoize' from the new package if available
|
|
132
|
+
if (memoizeAliases.has('Memoize') &&
|
|
133
|
+
memoizeAliases.get('Memoize') === MEMOIZE_MODULE) {
|
|
134
|
+
decoratorIdent = 'Memoize';
|
|
135
|
+
}
|
|
136
|
+
else if (memoizeAliases.size > 0) {
|
|
137
|
+
// Find first alias from new package, fallback to any alias
|
|
138
|
+
const newPackageAlias = Array.from(memoizeAliases.entries()).find(([_, pkg]) => pkg === MEMOIZE_MODULE)?.[0];
|
|
139
|
+
decoratorIdent =
|
|
140
|
+
newPackageAlias || Array.from(memoizeAliases.keys())[0];
|
|
141
|
+
}
|
|
142
|
+
else if (memoizeNamespaces.size > 0) {
|
|
143
|
+
// Prefer namespace from the new package if available
|
|
144
|
+
const newPackageNs = Array.from(memoizeNamespaces.entries()).find(([_, pkg]) => pkg === MEMOIZE_MODULE)?.[0];
|
|
145
|
+
const selectedNs = newPackageNs || Array.from(memoizeNamespaces.keys())[0];
|
|
146
|
+
decoratorIdent = `${selectedNs}.Memoize`;
|
|
147
|
+
}
|
|
148
|
+
}
|
|
97
149
|
const importStatement = `import { Memoize } from '${MEMOIZE_MODULE}';`;
|
|
98
150
|
// Add import if it's not already present; ensure we only add once per file
|
|
99
151
|
if (!hasMemoizeImport &&
|
|
100
|
-
|
|
101
|
-
!scheduledImportFix
|
|
102
|
-
!sourceCode.text.includes(importStatement)) {
|
|
152
|
+
memoizeNamespaces.size === 0 &&
|
|
153
|
+
!scheduledImportFix) {
|
|
103
154
|
const programBody = sourceCode.ast.body;
|
|
104
155
|
const firstImport = programBody.find((n) => n.type === utils_1.AST_NODE_TYPES.ImportDeclaration);
|
|
105
156
|
const anchorNode = (firstImport ?? programBody[0]);
|
|
@@ -3,6 +3,39 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.enforceMuiRoundedIcons = void 0;
|
|
4
4
|
const createRule_1 = require("../utils/createRule");
|
|
5
5
|
const utils_1 = require("@typescript-eslint/utils");
|
|
6
|
+
/**
|
|
7
|
+
* Non-Rounded MUI variant suffixes. An icon imported as one of these variants
|
|
8
|
+
* (e.g. `AddReactionOutlined`) maps to the Rounded variant of its BASE name
|
|
9
|
+
* (`AddReactionRounded`), not `AddReactionOutlinedRounded` (which doesn't exist).
|
|
10
|
+
* Matched exactly, so a distinct icon like `MailOutline` (ends in "Outline", not
|
|
11
|
+
* "Outlined") is left intact → `MailOutlineRounded`, which does exist.
|
|
12
|
+
*/
|
|
13
|
+
const VARIANT_SUFFIXES = ['Outlined', 'Sharp', 'TwoTone'];
|
|
14
|
+
/**
|
|
15
|
+
* @mui/icons-material brand icons that ship in a single (Filled) variant only —
|
|
16
|
+
* they have no Rounded counterpart, so the rule must not demand one. Computed
|
|
17
|
+
* from @mui/icons-material (the only base icons lacking a `*Rounded` sibling).
|
|
18
|
+
*/
|
|
19
|
+
const ICONS_WITHOUT_ROUNDED = new Set([
|
|
20
|
+
'Apple',
|
|
21
|
+
'GitHub',
|
|
22
|
+
'Google',
|
|
23
|
+
'Instagram',
|
|
24
|
+
'LinkedIn',
|
|
25
|
+
'Microsoft',
|
|
26
|
+
'Pinterest',
|
|
27
|
+
'Reddit',
|
|
28
|
+
'Telegram',
|
|
29
|
+
'Twitter',
|
|
30
|
+
'WhatsApp',
|
|
31
|
+
'X',
|
|
32
|
+
'YouTube',
|
|
33
|
+
]);
|
|
34
|
+
/** Strips a trailing non-Rounded variant suffix to recover the base icon name. */
|
|
35
|
+
const toBaseIconName = (iconName) => {
|
|
36
|
+
const suffix = VARIANT_SUFFIXES.find((variant) => iconName.endsWith(variant));
|
|
37
|
+
return suffix ? iconName.slice(0, -suffix.length) : iconName;
|
|
38
|
+
};
|
|
6
39
|
exports.enforceMuiRoundedIcons = (0, createRule_1.createRule)({
|
|
7
40
|
name: 'enforce-mui-rounded-icons',
|
|
8
41
|
meta: {
|
|
@@ -36,8 +69,16 @@ exports.enforceMuiRoundedIcons = (0, createRule_1.createRule)({
|
|
|
36
69
|
if (!iconName) {
|
|
37
70
|
return;
|
|
38
71
|
}
|
|
72
|
+
// Map a non-Rounded variant import to its base icon so the Rounded
|
|
73
|
+
// suggestion/fix targets a name that actually exists.
|
|
74
|
+
const baseIconName = toBaseIconName(iconName);
|
|
75
|
+
// Brand icons have no Rounded variant — demanding one is a false
|
|
76
|
+
// positive and the fix would point at a non-existent module.
|
|
77
|
+
if (ICONS_WITHOUT_ROUNDED.has(baseIconName)) {
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
39
80
|
// Create the rounded variant name
|
|
40
|
-
const roundedVariant = `${
|
|
81
|
+
const roundedVariant = `${baseIconName}Rounded`;
|
|
41
82
|
context.report({
|
|
42
83
|
node,
|
|
43
84
|
messageId: 'enforceRoundedVariant',
|
|
@@ -34,14 +34,48 @@ exports.enforcePropsArgumentName = (0, createRule_1.createRule)({
|
|
|
34
34
|
function endsWithProps(typeName) {
|
|
35
35
|
return typeName.endsWith('Props');
|
|
36
36
|
}
|
|
37
|
+
// Get all parameters that have a "Props" type
|
|
38
|
+
function getPropsParams(params) {
|
|
39
|
+
return params
|
|
40
|
+
.map((param) => {
|
|
41
|
+
const id = getIdFromParam(param);
|
|
42
|
+
if (id && id.typeAnnotation && id.typeAnnotation.typeAnnotation) {
|
|
43
|
+
const paramTypeName = getTypeName(id.typeAnnotation.typeAnnotation);
|
|
44
|
+
if (paramTypeName && endsWithProps(paramTypeName)) {
|
|
45
|
+
return { id, typeName: paramTypeName };
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
return null;
|
|
49
|
+
})
|
|
50
|
+
.filter((p) => !!p);
|
|
51
|
+
}
|
|
37
52
|
// Generate suggested parameter name for Props types
|
|
38
|
-
function getSuggestedParameterName(typeName, allParams, currentParam) {
|
|
53
|
+
function getSuggestedParameterName(typeName, allParams, currentParam, propsParams) {
|
|
39
54
|
const currentId = getIdFromParam(currentParam);
|
|
40
55
|
const currentName = currentId?.name;
|
|
41
56
|
const existingNames = new Set(allParams
|
|
42
57
|
.map((p) => getIdFromParam(p))
|
|
43
58
|
.filter((id) => !!id && id.name !== currentName)
|
|
44
59
|
.map((id) => id.name));
|
|
60
|
+
// If multiple parameters have the exact same Props type, allow the current names.
|
|
61
|
+
// This handles cases like (prevProps: TProps, nextProps: TProps) where
|
|
62
|
+
// forcing a single name based on the type would cause a collision or
|
|
63
|
+
// break descriptive naming.
|
|
64
|
+
const sameTypeParams = propsParams.filter((p) => p.typeName === typeName);
|
|
65
|
+
if (sameTypeParams.length > 1) {
|
|
66
|
+
// Keep the current name when multiple params share the same Props type.
|
|
67
|
+
// This preserves descriptive names like prevProps/nextProps.
|
|
68
|
+
if (!currentName) {
|
|
69
|
+
// Fallback should not occur since destructured params are filtered upstream.
|
|
70
|
+
let candidate = 'props';
|
|
71
|
+
let suffix = 2;
|
|
72
|
+
while (existingNames.has(candidate)) {
|
|
73
|
+
candidate = `props${suffix++}`;
|
|
74
|
+
}
|
|
75
|
+
return candidate;
|
|
76
|
+
}
|
|
77
|
+
return currentName;
|
|
78
|
+
}
|
|
45
79
|
if (typeName === 'Props') {
|
|
46
80
|
let candidate = 'props';
|
|
47
81
|
let suffix = 2;
|
|
@@ -50,17 +84,7 @@ exports.enforcePropsArgumentName = (0, createRule_1.createRule)({
|
|
|
50
84
|
}
|
|
51
85
|
return candidate;
|
|
52
86
|
}
|
|
53
|
-
//
|
|
54
|
-
const propsParams = allParams.filter((param) => {
|
|
55
|
-
if (param.type === utils_1.AST_NODE_TYPES.Identifier &&
|
|
56
|
-
param.typeAnnotation &&
|
|
57
|
-
param.typeAnnotation.typeAnnotation) {
|
|
58
|
-
const paramTypeName = getTypeName(param.typeAnnotation.typeAnnotation);
|
|
59
|
-
return paramTypeName && endsWithProps(paramTypeName);
|
|
60
|
-
}
|
|
61
|
-
return false;
|
|
62
|
-
});
|
|
63
|
-
// If there's only one Props parameter, suggest "props"
|
|
87
|
+
// If there's only one Props parameter (regardless of type name), suggest "props"
|
|
64
88
|
if (propsParams.length <= 1) {
|
|
65
89
|
let candidate = 'props';
|
|
66
90
|
let suffix = 2;
|
|
@@ -69,8 +93,8 @@ exports.enforcePropsArgumentName = (0, createRule_1.createRule)({
|
|
|
69
93
|
}
|
|
70
94
|
return candidate;
|
|
71
95
|
}
|
|
72
|
-
// If there are multiple Props parameters, use prefixed names
|
|
73
|
-
// For types like "UserProps", suggest "userProps"
|
|
96
|
+
// If there are multiple Props parameters with different types, use prefixed names.
|
|
97
|
+
// For types like "UserProps", suggest "userProps".
|
|
74
98
|
const baseName = typeName.slice(0, -5); // Remove "Props"
|
|
75
99
|
const camelCaseBase = baseName.charAt(0).toLowerCase() + baseName.slice(1);
|
|
76
100
|
let candidate = `${camelCaseBase}Props`;
|
|
@@ -138,6 +162,7 @@ exports.enforcePropsArgumentName = (0, createRule_1.createRule)({
|
|
|
138
162
|
return;
|
|
139
163
|
}
|
|
140
164
|
const sourceCode = context.sourceCode;
|
|
165
|
+
const propsParams = getPropsParams(node.params);
|
|
141
166
|
node.params.forEach((param) => {
|
|
142
167
|
if (isDestructuredParameter(param)) {
|
|
143
168
|
return;
|
|
@@ -146,7 +171,7 @@ exports.enforcePropsArgumentName = (0, createRule_1.createRule)({
|
|
|
146
171
|
if (id && id.typeAnnotation && id.typeAnnotation.typeAnnotation) {
|
|
147
172
|
const typeName = getTypeName(id.typeAnnotation.typeAnnotation);
|
|
148
173
|
if (typeName && endsWithProps(typeName)) {
|
|
149
|
-
const suggestedName = getSuggestedParameterName(typeName, node.params, param);
|
|
174
|
+
const suggestedName = getSuggestedParameterName(typeName, node.params, param, propsParams);
|
|
150
175
|
if (id.name !== suggestedName) {
|
|
151
176
|
const messageId = suggestedName === 'props'
|
|
152
177
|
? 'usePropsParameterName'
|
|
@@ -174,6 +199,7 @@ exports.enforcePropsArgumentName = (0, createRule_1.createRule)({
|
|
|
174
199
|
function checkClassMethod(node) {
|
|
175
200
|
const method = node.value;
|
|
176
201
|
const sourceCode = context.sourceCode;
|
|
202
|
+
const propsParams = getPropsParams(method.params);
|
|
177
203
|
method.params.forEach((param) => {
|
|
178
204
|
if (isDestructuredParameter(param)) {
|
|
179
205
|
return;
|
|
@@ -182,7 +208,7 @@ exports.enforcePropsArgumentName = (0, createRule_1.createRule)({
|
|
|
182
208
|
if (id && id.typeAnnotation && id.typeAnnotation.typeAnnotation) {
|
|
183
209
|
const typeName = getTypeName(id.typeAnnotation.typeAnnotation);
|
|
184
210
|
if (typeName && endsWithProps(typeName)) {
|
|
185
|
-
const suggestedName = getSuggestedParameterName(typeName, method.params, param);
|
|
211
|
+
const suggestedName = getSuggestedParameterName(typeName, method.params, param, propsParams);
|
|
186
212
|
if (id.name !== suggestedName) {
|
|
187
213
|
const messageId = suggestedName === 'props'
|
|
188
214
|
? 'usePropsParameterName'
|
|
@@ -31,12 +31,12 @@ function getFunctionName(node) {
|
|
|
31
31
|
}
|
|
32
32
|
return null;
|
|
33
33
|
}
|
|
34
|
-
function isProbablyComponent(node) {
|
|
34
|
+
function isProbablyComponent(node, context) {
|
|
35
35
|
const name = getFunctionName(node);
|
|
36
36
|
if (name && /^[A-Z]/.test(name)) {
|
|
37
37
|
return true;
|
|
38
38
|
}
|
|
39
|
-
if (ASTHelpers_1.ASTHelpers.returnsJSX(node.body)) {
|
|
39
|
+
if (ASTHelpers_1.ASTHelpers.returnsJSX(node.body, context)) {
|
|
40
40
|
return true;
|
|
41
41
|
}
|
|
42
42
|
return false;
|
|
@@ -236,7 +236,7 @@ exports.enforceStableHashSpreadProps = (0, createRule_1.createRule)({
|
|
|
236
236
|
}
|
|
237
237
|
functionStack.push({
|
|
238
238
|
node,
|
|
239
|
-
isComponent: isProbablyComponent(node),
|
|
239
|
+
isComponent: isProbablyComponent(node, context),
|
|
240
240
|
restNames,
|
|
241
241
|
propsIdentifiers,
|
|
242
242
|
});
|
|
@@ -8,7 +8,7 @@ exports.enforceTransformMemoization = (0, createRule_1.createRule)({
|
|
|
8
8
|
meta: {
|
|
9
9
|
type: 'problem',
|
|
10
10
|
docs: {
|
|
11
|
-
description: 'Enforce memoization of
|
|
11
|
+
description: 'Enforce memoization of transformValue and transformOnChange in adaptValue',
|
|
12
12
|
recommended: 'error',
|
|
13
13
|
},
|
|
14
14
|
schema: [],
|