@blumintinc/eslint-plugin-blumint 1.20.134 → 1.20.136
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/lib/index.js +1 -1
- package/lib/rules/consistent-callback-naming.js +16 -0
- package/lib/rules/enforce-assert-safe-object-key.js +403 -9
- package/lib/rules/enforce-fieldpath-syntax-in-docsetter.js +40 -4
- package/lib/rules/enforce-id-capitalization.js +18 -0
- package/lib/rules/enforce-props-argument-name.js +28 -2
- package/lib/rules/enforce-props-naming-consistency.js +28 -2
- package/lib/rules/no-inline-component-prop.js +8 -5
- package/lib/rules/no-object-values-on-strings.js +23 -6
- package/lib/rules/no-passthrough-getters.js +10 -2
- package/lib/rules/no-redundant-annotation-assertion.js +611 -38
- package/lib/rules/no-unnecessary-verb-suffix.js +46 -4
- package/lib/rules/no-useless-usememo-primitives.js +30 -9
- package/lib/rules/no-usememo-for-pass-by-value.js +185 -31
- package/lib/rules/parallelize-async-operations.js +10 -1
- package/lib/rules/prefer-map-over-conditional-dispatch.js +36 -8
- package/lib/utils/fixtureCorpus.d.ts +148 -8
- package/lib/utils/fixtureCorpus.js +207 -10
- package/lib/utils/harvestRuleTesterCases.d.ts +15 -0
- package/lib/utils/harvestRuleTesterCases.js +30 -3
- package/lib/utils/importRemoval.js +35 -6
- package/lib/utils/replacementSegments.d.ts +35 -0
- package/lib/utils/replacementSegments.js +55 -0
- package/package.json +1 -1
- package/release-manifest.json +143 -0
|
@@ -42,6 +42,33 @@ const getEnclosingClass = (node) => {
|
|
|
42
42
|
* cannot be resolved through scope analysis, the fix is withheld whenever the
|
|
43
43
|
* name occurs anywhere in the class other than at its declaration.
|
|
44
44
|
*/
|
|
45
|
+
/**
|
|
46
|
+
* The member name a `this.<x>` access reads, whatever its spelling.
|
|
47
|
+
*
|
|
48
|
+
* Keying the check on the dot spelling alone left `this['settings']` invisible,
|
|
49
|
+
* so the rename shipped and stranded it — the class no longer had the member the
|
|
50
|
+
* getter reads (#1882, the sibling of #1881). A computed access with a static
|
|
51
|
+
* string is the SAME member as the dot form, and the fixer cannot rewrite it
|
|
52
|
+
* either, so it has to count. `null` marks a genuinely dynamic key, which names
|
|
53
|
+
* no member statically and therefore strands nothing.
|
|
54
|
+
*/
|
|
55
|
+
const staticMemberName = (node) => {
|
|
56
|
+
if (!node.computed) {
|
|
57
|
+
return node.property.type === utils_1.AST_NODE_TYPES.Identifier
|
|
58
|
+
? node.property.name
|
|
59
|
+
: null;
|
|
60
|
+
}
|
|
61
|
+
if (node.property.type === utils_1.AST_NODE_TYPES.Literal &&
|
|
62
|
+
typeof node.property.value === 'string') {
|
|
63
|
+
return node.property.value;
|
|
64
|
+
}
|
|
65
|
+
if (node.property.type === utils_1.AST_NODE_TYPES.TemplateLiteral &&
|
|
66
|
+
node.property.expressions.length === 0 &&
|
|
67
|
+
node.property.quasis.length === 1) {
|
|
68
|
+
return node.property.quasis[0].value.cooked;
|
|
69
|
+
}
|
|
70
|
+
return null;
|
|
71
|
+
};
|
|
45
72
|
const parameterPropertyRenameIsUnsafe = (classNode, name, declarationId) => {
|
|
46
73
|
let unsafe = false;
|
|
47
74
|
const visit = (node) => {
|
|
@@ -50,8 +77,7 @@ const parameterPropertyRenameIsUnsafe = (classNode, name, declarationId) => {
|
|
|
50
77
|
}
|
|
51
78
|
if (node.type === utils_1.AST_NODE_TYPES.MemberExpression &&
|
|
52
79
|
node.object.type === utils_1.AST_NODE_TYPES.ThisExpression &&
|
|
53
|
-
node
|
|
54
|
-
node.property.name === name) {
|
|
80
|
+
staticMemberName(node) === name) {
|
|
55
81
|
unsafe = true;
|
|
56
82
|
return;
|
|
57
83
|
}
|
|
@@ -414,17 +414,20 @@ exports.noInlineComponentProp = (0, createRule_1.createRule)({
|
|
|
414
414
|
if (!definition)
|
|
415
415
|
return;
|
|
416
416
|
const defNode = definition.node;
|
|
417
|
-
if (!defNode ||
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
417
|
+
if (!defNode || defNode.type !== utils_1.AST_NODE_TYPES.VariableDeclarator) {
|
|
418
|
+
return;
|
|
419
|
+
}
|
|
420
|
+
// `global-const-style` autofixes a module-scope object literal to
|
|
421
|
+
// `as const`, so reading `init` raw lets one fixer silence this rule.
|
|
422
|
+
const holder = unwrapExpression(defNode.init);
|
|
423
|
+
if (!holder || holder.type !== utils_1.AST_NODE_TYPES.ObjectExpression) {
|
|
421
424
|
return;
|
|
422
425
|
}
|
|
423
426
|
if (resolvedOptions.allowModuleScopeFactories &&
|
|
424
427
|
isStableForConsumer(defNode, consumerFunction)) {
|
|
425
428
|
return;
|
|
426
429
|
}
|
|
427
|
-
const fnNode = findObjectPropertyFunction(
|
|
430
|
+
const fnNode = findObjectPropertyFunction(holder, member.property.name);
|
|
428
431
|
if (fnNode &&
|
|
429
432
|
isComponentLikeFunction(fnNode, context, member.property.name)) {
|
|
430
433
|
report(member, propName, member.property.name);
|
|
@@ -68,18 +68,33 @@ exports.noObjectValuesOnStrings = (0, createRule_1.createRule)({
|
|
|
68
68
|
node.callee.property.name === 'values' &&
|
|
69
69
|
node.arguments.length > 0);
|
|
70
70
|
}
|
|
71
|
+
/**
|
|
72
|
+
* `a?.b()` parses as a ChainExpression wrapping the call. The wrapper is
|
|
73
|
+
* ESTree-only, so it has no TypeScript node: leaving it in place defeats
|
|
74
|
+
* both the syntactic tests below and `getTypeAtLocation`, and a nullable
|
|
75
|
+
* receiver is exactly where `?.` gets written.
|
|
76
|
+
*/
|
|
77
|
+
function unwrapChain(node) {
|
|
78
|
+
let current = node;
|
|
79
|
+
while (current.type === utils_1.AST_NODE_TYPES.ChainExpression) {
|
|
80
|
+
current = current.expression;
|
|
81
|
+
}
|
|
82
|
+
return current;
|
|
83
|
+
}
|
|
71
84
|
/**
|
|
72
85
|
* Checks if a node is a string literal or template literal
|
|
73
86
|
*/
|
|
74
87
|
function isStringLiteral(node) {
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
88
|
+
const inner = unwrapChain(node);
|
|
89
|
+
return ((inner.type === utils_1.AST_NODE_TYPES.Literal &&
|
|
90
|
+
typeof inner.value === 'string') ||
|
|
91
|
+
inner.type === utils_1.AST_NODE_TYPES.TemplateLiteral);
|
|
78
92
|
}
|
|
79
93
|
/**
|
|
80
94
|
* Checks if a node is likely to produce a string value based on AST patterns
|
|
81
95
|
*/
|
|
82
|
-
function isLikelyStringExpression(
|
|
96
|
+
function isLikelyStringExpression(maybeChained) {
|
|
97
|
+
const node = unwrapChain(maybeChained);
|
|
83
98
|
// Check for string concatenation
|
|
84
99
|
if (node.type === utils_1.AST_NODE_TYPES.BinaryExpression &&
|
|
85
100
|
node.operator === '+' &&
|
|
@@ -190,8 +205,10 @@ exports.noObjectValuesOnStrings = (0, createRule_1.createRule)({
|
|
|
190
205
|
CallExpression(node) {
|
|
191
206
|
// Check if the call is Object.values()
|
|
192
207
|
if (isObjectValuesCall(node)) {
|
|
193
|
-
|
|
194
|
-
|
|
208
|
+
// The message quotes what the author wrote, so text comes from the
|
|
209
|
+
// original node while every test below reads through the chain.
|
|
210
|
+
const argumentText = sourceCode.getText(node.arguments[0]);
|
|
211
|
+
const argument = unwrapChain(node.arguments[0]);
|
|
195
212
|
// Quick check for string literals and template literals
|
|
196
213
|
if (isStringLiteral(argument)) {
|
|
197
214
|
context.report({
|
|
@@ -421,8 +421,16 @@ exports.noPassthroughGetters = (0, createRule_1.createRule)({
|
|
|
421
421
|
if (node.type === 'ConditionalExpression') {
|
|
422
422
|
return true;
|
|
423
423
|
}
|
|
424
|
-
// Check for optional chaining like this.settings?.property
|
|
425
|
-
|
|
424
|
+
// Check for optional chaining like this.settings?.property. `a?.b` parses
|
|
425
|
+
// as a ChainExpression wrapping the member access, so the wrapper has to
|
|
426
|
+
// be stripped here or this arm never fires — the shape stays silent only
|
|
427
|
+
// because the member walker cannot follow it, which would reverse the
|
|
428
|
+
// moment that walker learns to.
|
|
429
|
+
let unchained = node;
|
|
430
|
+
while (unchained.type === 'ChainExpression') {
|
|
431
|
+
unchained = unchained.expression;
|
|
432
|
+
}
|
|
433
|
+
if (unchained.type === 'MemberExpression' && unchained.optional) {
|
|
426
434
|
return true;
|
|
427
435
|
}
|
|
428
436
|
// The nullish coalescing check is already covered by the LogicalExpression check above
|