eslint-plugin-react-x 5.14.6 → 5.14.8
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/dist/index.js +188 -161
- package/package.json +8 -8
package/dist/index.js
CHANGED
|
@@ -144,7 +144,7 @@ const rules$6 = {
|
|
|
144
144
|
//#endregion
|
|
145
145
|
//#region package.json
|
|
146
146
|
var name$6 = "eslint-plugin-react-x";
|
|
147
|
-
var version = "5.14.
|
|
147
|
+
var version = "5.14.8";
|
|
148
148
|
|
|
149
149
|
//#endregion
|
|
150
150
|
//#region src/utils/create-rule.ts
|
|
@@ -1344,7 +1344,14 @@ const MUTATING_METHODS = /* @__PURE__ */ new Set([
|
|
|
1344
1344
|
"splice",
|
|
1345
1345
|
"unshift"
|
|
1346
1346
|
]);
|
|
1347
|
-
|
|
1347
|
+
/**
|
|
1348
|
+
* Known navigation hooks.
|
|
1349
|
+
*/
|
|
1350
|
+
const NAVIGATION_HOOKS = /* @__PURE__ */ new Set([
|
|
1351
|
+
"useNavigate",
|
|
1352
|
+
"useNavigation",
|
|
1353
|
+
"useRouter"
|
|
1354
|
+
]);
|
|
1348
1355
|
function resolveToFunctionNode(context, node, seen = /* @__PURE__ */ new Set()) {
|
|
1349
1356
|
const expr = Extract.unwrap(node);
|
|
1350
1357
|
if (Check.isFunction(expr)) return expr;
|
|
@@ -1386,12 +1393,11 @@ function isInitializedFromCall(context, node, isCall) {
|
|
|
1386
1393
|
function isInitializedFromUseRef(context, node) {
|
|
1387
1394
|
return isInitializedFromCall(context, node, (init) => core.isUseRefCall(context, init));
|
|
1388
1395
|
}
|
|
1389
|
-
function isInitializedFromUseRouter(context, node) {
|
|
1390
|
-
return isInitializedFromCall(context, node, (init) => isUseRouterCall(context, init));
|
|
1391
|
-
}
|
|
1392
1396
|
function isKnownNonMutatingMethodCall(context, node) {
|
|
1393
1397
|
const callee = Extract.unwrap(node.callee);
|
|
1394
|
-
return Check.isExpression(callee) &&
|
|
1398
|
+
return Check.isExpression(callee) && isInitializedFromCall(context, callee, (init) => {
|
|
1399
|
+
return NAVIGATION_HOOKS.values().some((hook) => core.isAPICall(hook)(context, init));
|
|
1400
|
+
});
|
|
1395
1401
|
}
|
|
1396
1402
|
function isRefLikeChain(context, node) {
|
|
1397
1403
|
return hasRefLikeNameInChain(node) || isInitializedFromUseRef(context, node);
|
|
@@ -4206,21 +4212,6 @@ const IMPURE_CTORS = /* @__PURE__ */ new Set([
|
|
|
4206
4212
|
"Worker",
|
|
4207
4213
|
"XMLHttpRequest"
|
|
4208
4214
|
]);
|
|
4209
|
-
|
|
4210
|
-
//#endregion
|
|
4211
|
-
//#region src/rules/purity/purity.ts
|
|
4212
|
-
const RULE_NAME$7 = "purity";
|
|
4213
|
-
var purity_default = createRule({
|
|
4214
|
-
meta: {
|
|
4215
|
-
type: "problem",
|
|
4216
|
-
docs: { description: "Validates that components and hooks are pure by checking that they do not call known-impure functions during render." },
|
|
4217
|
-
messages: { default: "Do not call '{{name}}' during render. Components and hooks must be pure. Move this call into an event handler, effect, or state initializer." },
|
|
4218
|
-
schema: []
|
|
4219
|
-
},
|
|
4220
|
-
name: RULE_NAME$7,
|
|
4221
|
-
create: create$7,
|
|
4222
|
-
defaultOptions: []
|
|
4223
|
-
});
|
|
4224
4215
|
/**
|
|
4225
4216
|
* Recursively resolve an identifier to the root builtin global object name.
|
|
4226
4217
|
* Follows simple assignment chains like `const M = Math` or `const w = window`.
|
|
@@ -4248,6 +4239,21 @@ function resolveBuiltinObjectName(context, node, seen = /* @__PURE__ */ new Set(
|
|
|
4248
4239
|
}
|
|
4249
4240
|
return null;
|
|
4250
4241
|
}
|
|
4242
|
+
|
|
4243
|
+
//#endregion
|
|
4244
|
+
//#region src/rules/purity/purity.ts
|
|
4245
|
+
const RULE_NAME$7 = "purity";
|
|
4246
|
+
var purity_default = createRule({
|
|
4247
|
+
meta: {
|
|
4248
|
+
type: "problem",
|
|
4249
|
+
docs: { description: "Validates that components and hooks are pure by checking that they do not call known-impure functions during render." },
|
|
4250
|
+
messages: { default: "Do not call '{{name}}' during render. Components and hooks must be pure. Move this call into an event handler, effect, or state initializer." },
|
|
4251
|
+
schema: []
|
|
4252
|
+
},
|
|
4253
|
+
name: RULE_NAME$7,
|
|
4254
|
+
create: create$7,
|
|
4255
|
+
defaultOptions: []
|
|
4256
|
+
});
|
|
4251
4257
|
function create$7(context) {
|
|
4252
4258
|
const hc = core.getHookCollector(context);
|
|
4253
4259
|
const fc = core.getFunctionComponentCollector(context);
|
|
@@ -4335,6 +4341,150 @@ const SYNC_ARRAY_CALLBACKS = /* @__PURE__ */ new Set([
|
|
|
4335
4341
|
"some",
|
|
4336
4342
|
"sort"
|
|
4337
4343
|
]);
|
|
4344
|
+
function createBindingResolver(context) {
|
|
4345
|
+
const bindings = /* @__PURE__ */ new Map();
|
|
4346
|
+
const memberBindings = /* @__PURE__ */ new Map();
|
|
4347
|
+
const jsxRefs = /* @__PURE__ */ new Set();
|
|
4348
|
+
function getVariable(node) {
|
|
4349
|
+
return findVariable(context.sourceCode.getScope(node), node) ?? null;
|
|
4350
|
+
}
|
|
4351
|
+
function getBindingValue(node) {
|
|
4352
|
+
const value = Extract.unwrap(node);
|
|
4353
|
+
if (value.type === AST_NODE_TYPES.Identifier) {
|
|
4354
|
+
const variable = getVariable(value);
|
|
4355
|
+
return variable == null ? { kind: "unknown" } : {
|
|
4356
|
+
kind: "variable",
|
|
4357
|
+
variable
|
|
4358
|
+
};
|
|
4359
|
+
}
|
|
4360
|
+
if (isFunctionExpressionLike(value)) return {
|
|
4361
|
+
kind: "function",
|
|
4362
|
+
node: value
|
|
4363
|
+
};
|
|
4364
|
+
if (value.type === AST_NODE_TYPES.CallExpression && (core.isUseRefCall(context, value) || core.isCreateRefCall(context, value))) return { kind: "ref" };
|
|
4365
|
+
if (value.type === AST_NODE_TYPES.MemberExpression) {
|
|
4366
|
+
const property = Extract.getPropertyName(value.property);
|
|
4367
|
+
if (property != null && isRefLikeName(property)) return { kind: "ref" };
|
|
4368
|
+
}
|
|
4369
|
+
return { kind: "unknown" };
|
|
4370
|
+
}
|
|
4371
|
+
function addBinding(variable, value, position) {
|
|
4372
|
+
const events = bindings.get(variable) ?? [];
|
|
4373
|
+
bindings.set(variable, events);
|
|
4374
|
+
events.push({
|
|
4375
|
+
position,
|
|
4376
|
+
value
|
|
4377
|
+
});
|
|
4378
|
+
}
|
|
4379
|
+
function addIdentifierBinding(node, value, position = node.range[0]) {
|
|
4380
|
+
const variable = getVariable(node);
|
|
4381
|
+
if (variable != null) addBinding(variable, getBindingValue(value), position);
|
|
4382
|
+
}
|
|
4383
|
+
function addFunctionBinding(node, value, position) {
|
|
4384
|
+
const variable = getVariable(node);
|
|
4385
|
+
if (variable != null) addBinding(variable, {
|
|
4386
|
+
kind: "function",
|
|
4387
|
+
node: value
|
|
4388
|
+
}, position);
|
|
4389
|
+
}
|
|
4390
|
+
function addMemberBinding(object, property, value, position) {
|
|
4391
|
+
const variable = getVariable(object);
|
|
4392
|
+
if (variable == null) return;
|
|
4393
|
+
const properties = memberBindings.get(variable) ?? /* @__PURE__ */ new Map();
|
|
4394
|
+
memberBindings.set(variable, properties);
|
|
4395
|
+
const events = properties.get(property) ?? [];
|
|
4396
|
+
properties.set(property, events);
|
|
4397
|
+
events.push({
|
|
4398
|
+
position,
|
|
4399
|
+
value: getBindingValue(value)
|
|
4400
|
+
});
|
|
4401
|
+
}
|
|
4402
|
+
function addJsxRef(node) {
|
|
4403
|
+
const variable = getVariable(node);
|
|
4404
|
+
if (variable != null) jsxRefs.add(variable);
|
|
4405
|
+
}
|
|
4406
|
+
function resolveRef(variable, position, seen = /* @__PURE__ */ new Set()) {
|
|
4407
|
+
if (seen.has(variable)) return null;
|
|
4408
|
+
seen.add(variable);
|
|
4409
|
+
if (jsxRefs.has(variable) || isRefLikeName(variable.name)) return variable;
|
|
4410
|
+
const event = getLatestValue(bindings.get(variable), position);
|
|
4411
|
+
if (event != null) switch (event.value.kind) {
|
|
4412
|
+
case "ref": return variable;
|
|
4413
|
+
case "variable": return resolveRef(event.value.variable, event.position, seen);
|
|
4414
|
+
case "function":
|
|
4415
|
+
case "unknown": return null;
|
|
4416
|
+
}
|
|
4417
|
+
return null;
|
|
4418
|
+
}
|
|
4419
|
+
function resolveFunction(variable, position, seen = /* @__PURE__ */ new Set()) {
|
|
4420
|
+
if (seen.has(variable)) return null;
|
|
4421
|
+
seen.add(variable);
|
|
4422
|
+
const event = getLatestValue(bindings.get(variable), position);
|
|
4423
|
+
if (event == null) return null;
|
|
4424
|
+
switch (event.value.kind) {
|
|
4425
|
+
case "function": return event.value.node;
|
|
4426
|
+
case "variable": return resolveFunction(event.value.variable, event.position, seen);
|
|
4427
|
+
case "ref":
|
|
4428
|
+
case "unknown": return null;
|
|
4429
|
+
}
|
|
4430
|
+
}
|
|
4431
|
+
function resolveCallable(node, position) {
|
|
4432
|
+
const callee = Extract.unwrap(node);
|
|
4433
|
+
if (isFunctionExpressionLike(callee)) return callee;
|
|
4434
|
+
if (callee.type === AST_NODE_TYPES.Identifier) {
|
|
4435
|
+
const variable = getVariable(callee);
|
|
4436
|
+
return variable == null ? null : resolveFunction(variable, position);
|
|
4437
|
+
}
|
|
4438
|
+
if (callee.type !== AST_NODE_TYPES.MemberExpression) return null;
|
|
4439
|
+
const object = Extract.unwrap(callee.object);
|
|
4440
|
+
const property = Extract.getPropertyName(callee.property);
|
|
4441
|
+
if (object.type !== AST_NODE_TYPES.Identifier || property == null) return null;
|
|
4442
|
+
const variable = getVariable(object);
|
|
4443
|
+
if (variable == null) return null;
|
|
4444
|
+
const event = getLatestValue(memberBindings.get(variable)?.get(property), position);
|
|
4445
|
+
if (event == null) return null;
|
|
4446
|
+
if (event.value.kind === "function") return event.value.node;
|
|
4447
|
+
if (event.value.kind === "variable") return resolveFunction(event.value.variable, event.position);
|
|
4448
|
+
return null;
|
|
4449
|
+
}
|
|
4450
|
+
function getRefTarget(node) {
|
|
4451
|
+
const object = Extract.unwrap(node.object);
|
|
4452
|
+
if (object.type === AST_NODE_TYPES.Identifier) {
|
|
4453
|
+
const variable = getVariable(object);
|
|
4454
|
+
if (variable == null) return null;
|
|
4455
|
+
const identity = resolveRef(variable, node.range[0]);
|
|
4456
|
+
return identity == null ? null : { identity };
|
|
4457
|
+
}
|
|
4458
|
+
if (object.type === AST_NODE_TYPES.MemberExpression) {
|
|
4459
|
+
const property = Extract.getPropertyName(object.property);
|
|
4460
|
+
if (property != null && isRefLikeName(property)) return { identity: null };
|
|
4461
|
+
}
|
|
4462
|
+
return null;
|
|
4463
|
+
}
|
|
4464
|
+
function getNullBranch(test, identity) {
|
|
4465
|
+
return getNullCheckBranch(test, (candidate) => {
|
|
4466
|
+
if (candidate.type !== AST_NODE_TYPES.MemberExpression || Extract.getPropertyName(candidate.property) !== "current") return false;
|
|
4467
|
+
return getRefTarget(candidate)?.identity === identity;
|
|
4468
|
+
}, (candidate) => {
|
|
4469
|
+
if (candidate.type === AST_NODE_TYPES.Literal) return candidate.value == null;
|
|
4470
|
+
if (candidate.type === AST_NODE_TYPES.UnaryExpression && candidate.operator === "void") return true;
|
|
4471
|
+
if (candidate.type !== AST_NODE_TYPES.Identifier || candidate.name !== "undefined") return false;
|
|
4472
|
+
const variable = getVariable(candidate);
|
|
4473
|
+
return variable == null || variable.defs.length === 0;
|
|
4474
|
+
});
|
|
4475
|
+
}
|
|
4476
|
+
return {
|
|
4477
|
+
addFunctionBinding,
|
|
4478
|
+
addIdentifierBinding,
|
|
4479
|
+
addJsxRef,
|
|
4480
|
+
addMemberBinding,
|
|
4481
|
+
getNullBranch,
|
|
4482
|
+
getRefTarget,
|
|
4483
|
+
getVariable,
|
|
4484
|
+
resolveCallable,
|
|
4485
|
+
resolveRef
|
|
4486
|
+
};
|
|
4487
|
+
}
|
|
4338
4488
|
function getLatestValue(events, position) {
|
|
4339
4489
|
let latest = null;
|
|
4340
4490
|
for (const event of events ?? []) {
|
|
@@ -4375,6 +4525,16 @@ function isReachedThroughFunctions(node, boundary, reached) {
|
|
|
4375
4525
|
}
|
|
4376
4526
|
return current === boundary;
|
|
4377
4527
|
}
|
|
4528
|
+
function getRefAccess(node) {
|
|
4529
|
+
let parent = node.parent;
|
|
4530
|
+
while (Check.isTypeExpression(parent)) parent = parent.parent;
|
|
4531
|
+
const isDirectWrite = parent.type === AST_NODE_TYPES.AssignmentExpression ? parent.left === node || Extract.unwrap(parent.left) === node : parent.type === AST_NODE_TYPES.UpdateExpression ? parent.argument === node || Extract.unwrap(parent.argument) === node : false;
|
|
4532
|
+
return {
|
|
4533
|
+
isInitializationWrite: parent.type === AST_NODE_TYPES.AssignmentExpression && parent.operator === "=" && (parent.left === node || Extract.unwrap(parent.left) === node),
|
|
4534
|
+
isWrite: isDirectWrite || isNestedRefCurrentWrite(node),
|
|
4535
|
+
node
|
|
4536
|
+
};
|
|
4537
|
+
}
|
|
4378
4538
|
/**
|
|
4379
4539
|
* Check whether `node` (a `ref.current` MemberExpression) is being written to indirectly through
|
|
4380
4540
|
* a nested property write, e.g. `ref.current.inner = value` or `ref.current.inner++`.
|
|
@@ -4396,16 +4556,6 @@ function isNestedRefCurrentWrite(node) {
|
|
|
4396
4556
|
return false;
|
|
4397
4557
|
}
|
|
4398
4558
|
}
|
|
4399
|
-
function getRefAccess(node) {
|
|
4400
|
-
let parent = node.parent;
|
|
4401
|
-
while (Check.isTypeExpression(parent)) parent = parent.parent;
|
|
4402
|
-
const isDirectWrite = parent.type === AST_NODE_TYPES.AssignmentExpression ? parent.left === node || Extract.unwrap(parent.left) === node : parent.type === AST_NODE_TYPES.UpdateExpression ? parent.argument === node || Extract.unwrap(parent.argument) === node : false;
|
|
4403
|
-
return {
|
|
4404
|
-
isInitializationWrite: parent.type === AST_NODE_TYPES.AssignmentExpression && parent.operator === "=" && (parent.left === node || Extract.unwrap(parent.left) === node),
|
|
4405
|
-
isWrite: isDirectWrite || isNestedRefCurrentWrite(node),
|
|
4406
|
-
node
|
|
4407
|
-
};
|
|
4408
|
-
}
|
|
4409
4559
|
/**
|
|
4410
4560
|
* Parse an exact nullish check and return the branch where the checked value is null/undefined.
|
|
4411
4561
|
* Truthiness checks such as `!ref.current` are deliberately excluded: falsy ref values are not
|
|
@@ -4469,7 +4619,7 @@ function isAfterTerminatingNonNullGuard(node, getNullBranch) {
|
|
|
4469
4619
|
statement = statement.parent;
|
|
4470
4620
|
}
|
|
4471
4621
|
const block = statement.parent;
|
|
4472
|
-
const index = block.body.
|
|
4622
|
+
const index = block.body.findIndex((sibling) => sibling === statement);
|
|
4473
4623
|
for (let i = index - 1; i >= 0; i--) {
|
|
4474
4624
|
const sibling = block.body[i];
|
|
4475
4625
|
if (sibling?.type !== AST_NODE_TYPES.IfStatement) continue;
|
|
@@ -4503,156 +4653,33 @@ var refs_default = createRule({
|
|
|
4503
4653
|
function create$6(context) {
|
|
4504
4654
|
const hc = core.getHookCollector(context);
|
|
4505
4655
|
const fc = core.getFunctionComponentCollector(context);
|
|
4506
|
-
const
|
|
4507
|
-
const memberBindings = /* @__PURE__ */ new Map();
|
|
4508
|
-
const jsxRefs = /* @__PURE__ */ new Set();
|
|
4656
|
+
const { addFunctionBinding, addIdentifierBinding, addJsxRef, addMemberBinding, getNullBranch, getRefTarget, getVariable, resolveCallable, resolveRef } = createBindingResolver(context);
|
|
4509
4657
|
const calls = [];
|
|
4510
4658
|
const refAccesses = [];
|
|
4511
|
-
function getVariable(node) {
|
|
4512
|
-
return findVariable(context.sourceCode.getScope(node), node) ?? null;
|
|
4513
|
-
}
|
|
4514
|
-
function addBinding(variable, value, position) {
|
|
4515
|
-
const events = bindings.get(variable) ?? [];
|
|
4516
|
-
bindings.set(variable, events);
|
|
4517
|
-
events.push({
|
|
4518
|
-
position,
|
|
4519
|
-
value
|
|
4520
|
-
});
|
|
4521
|
-
}
|
|
4522
|
-
function addIdentifierBinding(node, value, position = node.range[0]) {
|
|
4523
|
-
const variable = getVariable(node);
|
|
4524
|
-
if (variable != null) addBinding(variable, value, position);
|
|
4525
|
-
}
|
|
4526
|
-
function addMemberBinding(object, property, value, position) {
|
|
4527
|
-
const variable = getVariable(object);
|
|
4528
|
-
if (variable == null) return;
|
|
4529
|
-
const properties = memberBindings.get(variable) ?? /* @__PURE__ */ new Map();
|
|
4530
|
-
memberBindings.set(variable, properties);
|
|
4531
|
-
const events = properties.get(property) ?? [];
|
|
4532
|
-
properties.set(property, events);
|
|
4533
|
-
events.push({
|
|
4534
|
-
position,
|
|
4535
|
-
value
|
|
4536
|
-
});
|
|
4537
|
-
}
|
|
4538
|
-
function bindingValueFrom(node) {
|
|
4539
|
-
const value = Extract.unwrap(node);
|
|
4540
|
-
if (value.type === AST_NODE_TYPES.Identifier) {
|
|
4541
|
-
const variable = getVariable(value);
|
|
4542
|
-
return variable == null ? { kind: "unknown" } : {
|
|
4543
|
-
kind: "variable",
|
|
4544
|
-
variable
|
|
4545
|
-
};
|
|
4546
|
-
}
|
|
4547
|
-
if (isFunctionExpressionLike(value)) return {
|
|
4548
|
-
kind: "function",
|
|
4549
|
-
node: value
|
|
4550
|
-
};
|
|
4551
|
-
if (value.type === AST_NODE_TYPES.CallExpression && (core.isUseRefCall(context, value) || core.isCreateRefCall(context, value))) return { kind: "ref" };
|
|
4552
|
-
if (value.type === AST_NODE_TYPES.MemberExpression) {
|
|
4553
|
-
const property = Extract.getPropertyName(value.property);
|
|
4554
|
-
if (property != null && isRefLikeName(property)) return { kind: "ref" };
|
|
4555
|
-
}
|
|
4556
|
-
return { kind: "unknown" };
|
|
4557
|
-
}
|
|
4558
|
-
function resolveRef(variable, position, seen = /* @__PURE__ */ new Set()) {
|
|
4559
|
-
if (seen.has(variable)) return null;
|
|
4560
|
-
seen.add(variable);
|
|
4561
|
-
if (jsxRefs.has(variable) || isRefLikeName(variable.name)) return variable;
|
|
4562
|
-
const event = getLatestValue(bindings.get(variable), position);
|
|
4563
|
-
if (event != null) switch (event.value.kind) {
|
|
4564
|
-
case "ref": return variable;
|
|
4565
|
-
case "variable": return resolveRef(event.value.variable, event.position, seen);
|
|
4566
|
-
case "function":
|
|
4567
|
-
case "unknown": return null;
|
|
4568
|
-
}
|
|
4569
|
-
return null;
|
|
4570
|
-
}
|
|
4571
|
-
function resolveFunction(variable, position, seen = /* @__PURE__ */ new Set()) {
|
|
4572
|
-
if (seen.has(variable)) return null;
|
|
4573
|
-
seen.add(variable);
|
|
4574
|
-
const event = getLatestValue(bindings.get(variable), position);
|
|
4575
|
-
if (event == null) return null;
|
|
4576
|
-
switch (event.value.kind) {
|
|
4577
|
-
case "function": return event.value.node;
|
|
4578
|
-
case "variable": return resolveFunction(event.value.variable, event.position, seen);
|
|
4579
|
-
case "ref":
|
|
4580
|
-
case "unknown": return null;
|
|
4581
|
-
}
|
|
4582
|
-
}
|
|
4583
|
-
function resolveCallable(node, position) {
|
|
4584
|
-
const callee = Extract.unwrap(node);
|
|
4585
|
-
if (isFunctionExpressionLike(callee)) return callee;
|
|
4586
|
-
if (callee.type === AST_NODE_TYPES.Identifier) {
|
|
4587
|
-
const variable = getVariable(callee);
|
|
4588
|
-
return variable == null ? null : resolveFunction(variable, position);
|
|
4589
|
-
}
|
|
4590
|
-
if (callee.type !== AST_NODE_TYPES.MemberExpression) return null;
|
|
4591
|
-
const object = Extract.unwrap(callee.object);
|
|
4592
|
-
const property = Extract.getPropertyName(callee.property);
|
|
4593
|
-
if (object.type !== AST_NODE_TYPES.Identifier || property == null) return null;
|
|
4594
|
-
const variable = getVariable(object);
|
|
4595
|
-
if (variable == null) return null;
|
|
4596
|
-
const event = getLatestValue(memberBindings.get(variable)?.get(property), position);
|
|
4597
|
-
if (event == null) return null;
|
|
4598
|
-
if (event.value.kind === "function") return event.value.node;
|
|
4599
|
-
if (event.value.kind === "variable") return resolveFunction(event.value.variable, event.position);
|
|
4600
|
-
return null;
|
|
4601
|
-
}
|
|
4602
|
-
function getRefTarget(node) {
|
|
4603
|
-
const object = Extract.unwrap(node.object);
|
|
4604
|
-
if (object.type === AST_NODE_TYPES.Identifier) {
|
|
4605
|
-
const variable = getVariable(object);
|
|
4606
|
-
if (variable == null) return null;
|
|
4607
|
-
const identity = resolveRef(variable, node.range[0]);
|
|
4608
|
-
return identity == null ? null : { identity };
|
|
4609
|
-
}
|
|
4610
|
-
if (object.type === AST_NODE_TYPES.MemberExpression) {
|
|
4611
|
-
const property = Extract.getPropertyName(object.property);
|
|
4612
|
-
if (property != null && isRefLikeName(property)) return { identity: null };
|
|
4613
|
-
}
|
|
4614
|
-
return null;
|
|
4615
|
-
}
|
|
4616
|
-
function getNullBranch(test, identity) {
|
|
4617
|
-
return getNullCheckBranch(test, (candidate) => {
|
|
4618
|
-
if (candidate.type !== AST_NODE_TYPES.MemberExpression || Extract.getPropertyName(candidate.property) !== "current") return false;
|
|
4619
|
-
return getRefTarget(candidate)?.identity === identity;
|
|
4620
|
-
}, (candidate) => {
|
|
4621
|
-
if (candidate.type === AST_NODE_TYPES.Literal) return candidate.value == null;
|
|
4622
|
-
if (candidate.type === AST_NODE_TYPES.UnaryExpression && candidate.operator === "void") return true;
|
|
4623
|
-
if (candidate.type !== AST_NODE_TYPES.Identifier || candidate.name !== "undefined") return false;
|
|
4624
|
-
const variable = getVariable(candidate);
|
|
4625
|
-
return variable == null || variable.defs.length === 0;
|
|
4626
|
-
});
|
|
4627
|
-
}
|
|
4628
4659
|
return merge(hc.visitor, fc.visitor, {
|
|
4629
4660
|
AssignmentExpression(node) {
|
|
4630
4661
|
if (node.operator !== "=") return;
|
|
4631
4662
|
const left = Extract.unwrap(node.left);
|
|
4632
4663
|
if (left.type === AST_NODE_TYPES.Identifier) {
|
|
4633
|
-
addIdentifierBinding(left,
|
|
4664
|
+
addIdentifierBinding(left, node.right, node.range[0]);
|
|
4634
4665
|
return;
|
|
4635
4666
|
}
|
|
4636
4667
|
if (left.type !== AST_NODE_TYPES.MemberExpression) return;
|
|
4637
4668
|
const object = Extract.unwrap(left.object);
|
|
4638
4669
|
const property = Extract.getPropertyName(left.property);
|
|
4639
|
-
if (object.type === AST_NODE_TYPES.Identifier && property != null) addMemberBinding(object, property,
|
|
4670
|
+
if (object.type === AST_NODE_TYPES.Identifier && property != null) addMemberBinding(object, property, node.right, node.range[0]);
|
|
4640
4671
|
},
|
|
4641
4672
|
CallExpression(node) {
|
|
4642
4673
|
calls.push(node);
|
|
4643
4674
|
},
|
|
4644
4675
|
FunctionDeclaration(node) {
|
|
4645
|
-
if (node.id != null)
|
|
4646
|
-
kind: "function",
|
|
4647
|
-
node
|
|
4648
|
-
}, -1);
|
|
4676
|
+
if (node.id != null) addFunctionBinding(node.id, node, -1);
|
|
4649
4677
|
},
|
|
4650
4678
|
JSXAttribute(node) {
|
|
4651
4679
|
if (node.name.type !== AST_NODE_TYPES.JSXIdentifier || node.name.name !== "ref" || node.value?.type !== AST_NODE_TYPES.JSXExpressionContainer) return;
|
|
4652
4680
|
const expression = Extract.unwrap(node.value.expression);
|
|
4653
4681
|
if (expression.type !== AST_NODE_TYPES.Identifier) return;
|
|
4654
|
-
|
|
4655
|
-
if (variable != null) jsxRefs.add(variable);
|
|
4682
|
+
addJsxRef(expression);
|
|
4656
4683
|
},
|
|
4657
4684
|
MemberExpression(node) {
|
|
4658
4685
|
if (Extract.getPropertyName(node.property) !== "current") return;
|
|
@@ -4746,7 +4773,7 @@ function create$6(context) {
|
|
|
4746
4773
|
},
|
|
4747
4774
|
VariableDeclarator(node) {
|
|
4748
4775
|
if (node.id.type !== AST_NODE_TYPES.Identifier || node.init == null) return;
|
|
4749
|
-
addIdentifierBinding(node.id,
|
|
4776
|
+
addIdentifierBinding(node.id, node.init, node.range[0]);
|
|
4750
4777
|
}
|
|
4751
4778
|
});
|
|
4752
4779
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "eslint-plugin-react-x",
|
|
3
|
-
"version": "5.14.
|
|
3
|
+
"version": "5.14.8",
|
|
4
4
|
"description": "A set of composable ESLint rules for libraries and frameworks that use React as a UI runtime.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"react",
|
|
@@ -45,12 +45,12 @@
|
|
|
45
45
|
"string-ts": "^2.3.1",
|
|
46
46
|
"ts-api-utils": "^2.5.0",
|
|
47
47
|
"ts-pattern": "^5.9.0",
|
|
48
|
-
"@eslint-react/
|
|
49
|
-
"@eslint-react/
|
|
50
|
-
"@eslint-react/jsx": "5.14.
|
|
51
|
-
"@eslint-react/
|
|
52
|
-
"@eslint-react/shared": "5.14.
|
|
53
|
-
"@eslint-react/
|
|
48
|
+
"@eslint-react/core": "5.14.8",
|
|
49
|
+
"@eslint-react/eslint": "5.14.8",
|
|
50
|
+
"@eslint-react/jsx": "5.14.8",
|
|
51
|
+
"@eslint-react/var": "5.14.8",
|
|
52
|
+
"@eslint-react/shared": "5.14.8",
|
|
53
|
+
"@eslint-react/ast": "5.14.8"
|
|
54
54
|
},
|
|
55
55
|
"devDependencies": {
|
|
56
56
|
"@types/react": "^19.2.17",
|
|
@@ -59,7 +59,7 @@
|
|
|
59
59
|
"eslint": "^10.7.0",
|
|
60
60
|
"react": "^19.2.7",
|
|
61
61
|
"react-dom": "^19.2.7",
|
|
62
|
-
"tsdown": "^0.22.
|
|
62
|
+
"tsdown": "^0.22.5",
|
|
63
63
|
"tsl": "^1.0.30",
|
|
64
64
|
"tsl-dx": "^0.13.2",
|
|
65
65
|
"typescript": "6.0.3",
|