eslint-plugin-react-x 5.14.7 → 5.14.9
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 +361 -387
- package/package.json +10 -10
package/dist/index.js
CHANGED
|
@@ -8,8 +8,8 @@ import { AST_NODE_TYPES } from "@typescript-eslint/types";
|
|
|
8
8
|
import { computeObjectType, isAssignmentTargetEqual, isInitializedFromReact, resolve, resolveEnclosingAssignmentTarget } from "@eslint-react/var";
|
|
9
9
|
import { DefinitionType, ScopeType } from "@typescript-eslint/scope-manager";
|
|
10
10
|
import { findVariable, getStaticValue } from "@typescript-eslint/utils/ast-utils";
|
|
11
|
-
import { P, isMatching, match } from "ts-pattern";
|
|
12
11
|
import { compare } from "compare-versions";
|
|
12
|
+
import { P, isMatching, match } from "ts-pattern";
|
|
13
13
|
import { getConstrainedTypeAtLocation } from "@typescript-eslint/type-utils";
|
|
14
14
|
import { unionConstituents } from "ts-api-utils";
|
|
15
15
|
import { simpleTraverse } from "@typescript-eslint/typescript-estree";
|
|
@@ -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.9";
|
|
148
148
|
|
|
149
149
|
//#endregion
|
|
150
150
|
//#region src/utils/create-rule.ts
|
|
@@ -1282,7 +1282,7 @@ function create$49(context) {
|
|
|
1282
1282
|
recordCallEdge(node);
|
|
1283
1283
|
const callee = Extract.unwrap(node.callee);
|
|
1284
1284
|
if (callee.type !== AST_NODE_TYPES.MemberExpression) return;
|
|
1285
|
-
const method = Extract.
|
|
1285
|
+
const method = Extract.getCalleeName(node);
|
|
1286
1286
|
if (method == null || !MUTATING_ARRAY_METHODS.has(method)) return;
|
|
1287
1287
|
const origin = resolveGlobalOrigin(context, callee.object);
|
|
1288
1288
|
if (origin == null) return;
|
|
@@ -1376,8 +1376,7 @@ function isRefLikeName$1(name) {
|
|
|
1376
1376
|
function hasRefLikeNameInChain(node) {
|
|
1377
1377
|
if (node.type === AST_NODE_TYPES.Identifier) return isRefLikeName$1(node.name);
|
|
1378
1378
|
if (node.type !== AST_NODE_TYPES.MemberExpression) return false;
|
|
1379
|
-
|
|
1380
|
-
return propertyName != null ? isRefLikeName$1(propertyName) || hasRefLikeNameInChain(node.object) : hasRefLikeNameInChain(node.object);
|
|
1379
|
+
return node.property.type === AST_NODE_TYPES.Identifier ? isRefLikeName$1(node.property.name) || hasRefLikeNameInChain(node.object) : hasRefLikeNameInChain(node.object);
|
|
1381
1380
|
}
|
|
1382
1381
|
function isInitializedFromCall(context, node, isCall) {
|
|
1383
1382
|
const root = node.type === AST_NODE_TYPES.Identifier ? node : Extract.getRootIdentifier(node);
|
|
@@ -1440,8 +1439,8 @@ function createImmutabilityCollector() {
|
|
|
1440
1439
|
CallExpression(node) {
|
|
1441
1440
|
const callee = Extract.unwrap(node.callee);
|
|
1442
1441
|
if (callee.type === AST_NODE_TYPES.MemberExpression) {
|
|
1443
|
-
const
|
|
1444
|
-
if (
|
|
1442
|
+
const method = Extract.getCalleeName(node);
|
|
1443
|
+
if (method != null && MUTATING_METHODS.has(method)) {
|
|
1445
1444
|
const root = Extract.getRootIdentifier(callee.object);
|
|
1446
1445
|
if (root != null) pushMutation("value", node, callee.object, root);
|
|
1447
1446
|
}
|
|
@@ -1570,191 +1569,9 @@ function create$48(context) {
|
|
|
1570
1569
|
} });
|
|
1571
1570
|
}
|
|
1572
1571
|
|
|
1573
|
-
//#endregion
|
|
1574
|
-
//#region ../../.pkgs/eff/dist/index.js
|
|
1575
|
-
function not(predicate) {
|
|
1576
|
-
return (data) => !predicate(data);
|
|
1577
|
-
}
|
|
1578
|
-
/**
|
|
1579
|
-
* Creates a function that can be used in a data-last (aka `pipe`able) or
|
|
1580
|
-
* data-first style.
|
|
1581
|
-
*
|
|
1582
|
-
* The first parameter to `dual` is either the arity of the uncurried function
|
|
1583
|
-
* or a predicate that determines if the function is being used in a data-first
|
|
1584
|
-
* or data-last style.
|
|
1585
|
-
*
|
|
1586
|
-
* Using the arity is the most common use case, but there are some cases where
|
|
1587
|
-
* you may want to use a predicate. For example, if you have a function that
|
|
1588
|
-
* takes an optional argument, you can use a predicate to determine if the
|
|
1589
|
-
* function is being used in a data-first or data-last style.
|
|
1590
|
-
*
|
|
1591
|
-
* You can pass either the arity of the uncurried function or a predicate
|
|
1592
|
-
* which determines if the function is being used in a data-first or
|
|
1593
|
-
* data-last style.
|
|
1594
|
-
*
|
|
1595
|
-
* **Example** (Using arity to determine data-first or data-last style)
|
|
1596
|
-
*
|
|
1597
|
-
* ```ts
|
|
1598
|
-
* import { dual, pipe } from "effect/Function"
|
|
1599
|
-
*
|
|
1600
|
-
* const sum = dual<
|
|
1601
|
-
* (that: number) => (self: number) => number,
|
|
1602
|
-
* (self: number, that: number) => number
|
|
1603
|
-
* >(2, (self, that) => self + that)
|
|
1604
|
-
*
|
|
1605
|
-
* console.log(sum(2, 3)) // 5
|
|
1606
|
-
* console.log(pipe(2, sum(3))) // 5
|
|
1607
|
-
* ```
|
|
1608
|
-
*
|
|
1609
|
-
* **Example** (Using call signatures to define the overloads)
|
|
1610
|
-
*
|
|
1611
|
-
* ```ts
|
|
1612
|
-
* import { dual, pipe } from "effect/Function"
|
|
1613
|
-
*
|
|
1614
|
-
* const sum: {
|
|
1615
|
-
* (that: number): (self: number) => number
|
|
1616
|
-
* (self: number, that: number): number
|
|
1617
|
-
* } = dual(2, (self: number, that: number): number => self + that)
|
|
1618
|
-
*
|
|
1619
|
-
* console.log(sum(2, 3)) // 5
|
|
1620
|
-
* console.log(pipe(2, sum(3))) // 5
|
|
1621
|
-
* ```
|
|
1622
|
-
*
|
|
1623
|
-
* **Example** (Using a predicate to determine data-first or data-last style)
|
|
1624
|
-
*
|
|
1625
|
-
* ```ts
|
|
1626
|
-
* import { dual, pipe } from "effect/Function"
|
|
1627
|
-
*
|
|
1628
|
-
* const sum = dual<
|
|
1629
|
-
* (that: number) => (self: number) => number,
|
|
1630
|
-
* (self: number, that: number) => number
|
|
1631
|
-
* >(
|
|
1632
|
-
* (args) => args.length === 2,
|
|
1633
|
-
* (self, that) => self + that
|
|
1634
|
-
* )
|
|
1635
|
-
*
|
|
1636
|
-
* console.log(sum(2, 3)) // 5
|
|
1637
|
-
* console.log(pipe(2, sum(3))) // 5
|
|
1638
|
-
* ```
|
|
1639
|
-
*
|
|
1640
|
-
* @param arity - The arity of the uncurried function or a predicate that determines if the function is being used in a data-first or data-last style.
|
|
1641
|
-
* @param body - The function to be curried.
|
|
1642
|
-
* @since 1.0.0
|
|
1643
|
-
*/
|
|
1644
|
-
const dual = function(arity, body) {
|
|
1645
|
-
if (typeof arity === "function") return function() {
|
|
1646
|
-
return arity(arguments) ? body.apply(this, arguments) : ((self) => body(self, ...arguments));
|
|
1647
|
-
};
|
|
1648
|
-
switch (arity) {
|
|
1649
|
-
case 0:
|
|
1650
|
-
case 1: throw new RangeError(`Invalid arity ${arity}`);
|
|
1651
|
-
case 2: return function(a, b) {
|
|
1652
|
-
if (arguments.length >= 2) return body(a, b);
|
|
1653
|
-
return function(self) {
|
|
1654
|
-
return body(self, a);
|
|
1655
|
-
};
|
|
1656
|
-
};
|
|
1657
|
-
case 3: return function(a, b, c) {
|
|
1658
|
-
if (arguments.length >= 3) return body(a, b, c);
|
|
1659
|
-
return function(self) {
|
|
1660
|
-
return body(self, a, b);
|
|
1661
|
-
};
|
|
1662
|
-
};
|
|
1663
|
-
default: return function() {
|
|
1664
|
-
if (arguments.length >= arity) return body.apply(this, arguments);
|
|
1665
|
-
const args = arguments;
|
|
1666
|
-
return function(self) {
|
|
1667
|
-
return body(self, ...args);
|
|
1668
|
-
};
|
|
1669
|
-
};
|
|
1670
|
-
}
|
|
1671
|
-
};
|
|
1672
|
-
/**
|
|
1673
|
-
* Do nothing and return `void`.
|
|
1674
|
-
*/
|
|
1675
|
-
function constVoid() {}
|
|
1676
|
-
/**
|
|
1677
|
-
* Do nothing and return `true`.
|
|
1678
|
-
*
|
|
1679
|
-
* @returns true
|
|
1680
|
-
*/
|
|
1681
|
-
function constTrue() {
|
|
1682
|
-
return true;
|
|
1683
|
-
}
|
|
1684
|
-
/**
|
|
1685
|
-
* Do nothing and return `false`.
|
|
1686
|
-
*
|
|
1687
|
-
* @returns false
|
|
1688
|
-
*/
|
|
1689
|
-
function constFalse() {
|
|
1690
|
-
return false;
|
|
1691
|
-
}
|
|
1692
|
-
/**
|
|
1693
|
-
* Composes two functions, `ab` and `bc` into a single function that takes in an argument `a` of type `A` and returns a result of type `C`.
|
|
1694
|
-
* The result is obtained by first applying the `ab` function to `a` and then applying the `bc` function to the result of `ab`.
|
|
1695
|
-
*
|
|
1696
|
-
* @param self - The first function to apply (or the composed function in data-last style).
|
|
1697
|
-
* @param bc - The second function to apply.
|
|
1698
|
-
* @returns A composed function that applies both functions in sequence.
|
|
1699
|
-
* @example
|
|
1700
|
-
* ```ts
|
|
1701
|
-
* import * as assert from "node:assert"
|
|
1702
|
-
* import { compose } from "effect/Function"
|
|
1703
|
-
*
|
|
1704
|
-
* const increment = (n: number) => n + 1;
|
|
1705
|
-
* const square = (n: number) => n * n;
|
|
1706
|
-
*
|
|
1707
|
-
* assert.strictEqual(compose(increment, square)(2), 9);
|
|
1708
|
-
* ```
|
|
1709
|
-
*
|
|
1710
|
-
* @since 1.0.0
|
|
1711
|
-
*/
|
|
1712
|
-
const compose = dual(2, (ab, bc) => (a) => bc(ab(a)));
|
|
1713
|
-
function flow(ab, bc, cd, de, ef, fg, gh, hi, ij) {
|
|
1714
|
-
switch (arguments.length) {
|
|
1715
|
-
case 1: return ab;
|
|
1716
|
-
case 2: return function() {
|
|
1717
|
-
return bc(ab.apply(this, arguments));
|
|
1718
|
-
};
|
|
1719
|
-
case 3: return function() {
|
|
1720
|
-
return cd(bc(ab.apply(this, arguments)));
|
|
1721
|
-
};
|
|
1722
|
-
case 4: return function() {
|
|
1723
|
-
return de(cd(bc(ab.apply(this, arguments))));
|
|
1724
|
-
};
|
|
1725
|
-
case 5: return function() {
|
|
1726
|
-
return ef(de(cd(bc(ab.apply(this, arguments)))));
|
|
1727
|
-
};
|
|
1728
|
-
case 6: return function() {
|
|
1729
|
-
return fg(ef(de(cd(bc(ab.apply(this, arguments))))));
|
|
1730
|
-
};
|
|
1731
|
-
case 7: return function() {
|
|
1732
|
-
return gh(fg(ef(de(cd(bc(ab.apply(this, arguments)))))));
|
|
1733
|
-
};
|
|
1734
|
-
case 8: return function() {
|
|
1735
|
-
return hi(gh(fg(ef(de(cd(bc(ab.apply(this, arguments))))))));
|
|
1736
|
-
};
|
|
1737
|
-
case 9: return function() {
|
|
1738
|
-
return ij(hi(gh(fg(ef(de(cd(bc(ab.apply(this, arguments)))))))));
|
|
1739
|
-
};
|
|
1740
|
-
}
|
|
1741
|
-
}
|
|
1742
|
-
function getOrInsertComputed(map, key, callback) {
|
|
1743
|
-
if (map.has(key)) return map.get(key);
|
|
1744
|
-
const value = callback(key);
|
|
1745
|
-
map.set(key, value);
|
|
1746
|
-
return value;
|
|
1747
|
-
}
|
|
1748
|
-
|
|
1749
1572
|
//#endregion
|
|
1750
1573
|
//#region src/rules/no-access-state-in-setstate/no-access-state-in-setstate.ts
|
|
1751
1574
|
const RULE_NAME$47 = "no-access-state-in-setstate";
|
|
1752
|
-
function isKeyLiteral$1(node, key) {
|
|
1753
|
-
return match(key).with({ type: AST_NODE_TYPES.Literal }, constTrue).with({
|
|
1754
|
-
type: AST_NODE_TYPES.TemplateLiteral,
|
|
1755
|
-
expressions: []
|
|
1756
|
-
}, constTrue).with({ type: AST_NODE_TYPES.Identifier }, () => !node.computed).otherwise(constFalse);
|
|
1757
|
-
}
|
|
1758
1575
|
var no_access_state_in_setstate_default = createRule({
|
|
1759
1576
|
meta: {
|
|
1760
1577
|
type: "problem",
|
|
@@ -1800,7 +1617,7 @@ function create$47(context) {
|
|
|
1800
1617
|
if (currMethod == null || isStatic) return;
|
|
1801
1618
|
const [setState, hasThisState = false] = setStateStack.at(-1) ?? [];
|
|
1802
1619
|
if (setState == null || hasThisState) return;
|
|
1803
|
-
if (
|
|
1620
|
+
if (node.property.type !== AST_NODE_TYPES.Identifier || node.property.name !== "state") return;
|
|
1804
1621
|
context.report({
|
|
1805
1622
|
messageId: "default",
|
|
1806
1623
|
node
|
|
@@ -1826,7 +1643,7 @@ function create$47(context) {
|
|
|
1826
1643
|
const [setState, hasThisState = false] = setStateStack.at(-1) ?? [];
|
|
1827
1644
|
if (setState == null || hasThisState) return;
|
|
1828
1645
|
if (node.init == null || node.init.type !== AST_NODE_TYPES.ThisExpression || node.id.type !== AST_NODE_TYPES.ObjectPattern) return;
|
|
1829
|
-
if (!node.id.properties.some((prop) => prop.type === AST_NODE_TYPES.Property &&
|
|
1646
|
+
if (!node.id.properties.some((prop) => prop.type === AST_NODE_TYPES.Property && !prop.computed && prop.key.type === AST_NODE_TYPES.Identifier && prop.key.name === "state")) return;
|
|
1830
1647
|
context.report({
|
|
1831
1648
|
messageId: "default",
|
|
1832
1649
|
node
|
|
@@ -1952,7 +1769,7 @@ function create$46(context) {
|
|
|
1952
1769
|
case AST_NODE_TYPES.LogicalExpression: return [...visitKeyExpression(node.left), ...visitKeyExpression(node.right)];
|
|
1953
1770
|
case AST_NODE_TYPES.CallExpression: {
|
|
1954
1771
|
const callee = Extract.unwrap(node.callee);
|
|
1955
|
-
if (callee.type === AST_NODE_TYPES.MemberExpression && Extract.
|
|
1772
|
+
if (callee.type === AST_NODE_TYPES.MemberExpression && Extract.getCalleeName(node) === "toString" && isArrayIndex(callee.object)) return [{
|
|
1956
1773
|
messageId: "default",
|
|
1957
1774
|
node: callee.object
|
|
1958
1775
|
}];
|
|
@@ -2408,7 +2225,7 @@ function create$32(context) {
|
|
|
2408
2225
|
const call = Traverse.findParent(jsxElement, (n) => {
|
|
2409
2226
|
if (n.type !== AST_NODE_TYPES.CallExpression) return false;
|
|
2410
2227
|
const callee = Extract.unwrap(n.callee);
|
|
2411
|
-
return callee.type === AST_NODE_TYPES.MemberExpression &&
|
|
2228
|
+
return callee.type === AST_NODE_TYPES.MemberExpression && callee.property.type === AST_NODE_TYPES.Identifier && callee.property.name === "map";
|
|
2412
2229
|
});
|
|
2413
2230
|
const iter = Traverse.findParent(jsxElement, Check.isFunction, (n) => n === call);
|
|
2414
2231
|
if (!Check.isFunction(iter)) return;
|
|
@@ -2668,6 +2485,166 @@ function create$28(context) {
|
|
|
2668
2485
|
} };
|
|
2669
2486
|
}
|
|
2670
2487
|
|
|
2488
|
+
//#endregion
|
|
2489
|
+
//#region ../../.pkgs/eff/dist/index.js
|
|
2490
|
+
function not(predicate) {
|
|
2491
|
+
return (data) => !predicate(data);
|
|
2492
|
+
}
|
|
2493
|
+
/**
|
|
2494
|
+
* Creates a function that can be used in a data-last (aka `pipe`able) or
|
|
2495
|
+
* data-first style.
|
|
2496
|
+
*
|
|
2497
|
+
* The first parameter to `dual` is either the arity of the uncurried function
|
|
2498
|
+
* or a predicate that determines if the function is being used in a data-first
|
|
2499
|
+
* or data-last style.
|
|
2500
|
+
*
|
|
2501
|
+
* Using the arity is the most common use case, but there are some cases where
|
|
2502
|
+
* you may want to use a predicate. For example, if you have a function that
|
|
2503
|
+
* takes an optional argument, you can use a predicate to determine if the
|
|
2504
|
+
* function is being used in a data-first or data-last style.
|
|
2505
|
+
*
|
|
2506
|
+
* You can pass either the arity of the uncurried function or a predicate
|
|
2507
|
+
* which determines if the function is being used in a data-first or
|
|
2508
|
+
* data-last style.
|
|
2509
|
+
*
|
|
2510
|
+
* **Example** (Using arity to determine data-first or data-last style)
|
|
2511
|
+
*
|
|
2512
|
+
* ```ts
|
|
2513
|
+
* import { dual, pipe } from "effect/Function"
|
|
2514
|
+
*
|
|
2515
|
+
* const sum = dual<
|
|
2516
|
+
* (that: number) => (self: number) => number,
|
|
2517
|
+
* (self: number, that: number) => number
|
|
2518
|
+
* >(2, (self, that) => self + that)
|
|
2519
|
+
*
|
|
2520
|
+
* console.log(sum(2, 3)) // 5
|
|
2521
|
+
* console.log(pipe(2, sum(3))) // 5
|
|
2522
|
+
* ```
|
|
2523
|
+
*
|
|
2524
|
+
* **Example** (Using call signatures to define the overloads)
|
|
2525
|
+
*
|
|
2526
|
+
* ```ts
|
|
2527
|
+
* import { dual, pipe } from "effect/Function"
|
|
2528
|
+
*
|
|
2529
|
+
* const sum: {
|
|
2530
|
+
* (that: number): (self: number) => number
|
|
2531
|
+
* (self: number, that: number): number
|
|
2532
|
+
* } = dual(2, (self: number, that: number): number => self + that)
|
|
2533
|
+
*
|
|
2534
|
+
* console.log(sum(2, 3)) // 5
|
|
2535
|
+
* console.log(pipe(2, sum(3))) // 5
|
|
2536
|
+
* ```
|
|
2537
|
+
*
|
|
2538
|
+
* **Example** (Using a predicate to determine data-first or data-last style)
|
|
2539
|
+
*
|
|
2540
|
+
* ```ts
|
|
2541
|
+
* import { dual, pipe } from "effect/Function"
|
|
2542
|
+
*
|
|
2543
|
+
* const sum = dual<
|
|
2544
|
+
* (that: number) => (self: number) => number,
|
|
2545
|
+
* (self: number, that: number) => number
|
|
2546
|
+
* >(
|
|
2547
|
+
* (args) => args.length === 2,
|
|
2548
|
+
* (self, that) => self + that
|
|
2549
|
+
* )
|
|
2550
|
+
*
|
|
2551
|
+
* console.log(sum(2, 3)) // 5
|
|
2552
|
+
* console.log(pipe(2, sum(3))) // 5
|
|
2553
|
+
* ```
|
|
2554
|
+
*
|
|
2555
|
+
* @param arity - The arity of the uncurried function or a predicate that determines if the function is being used in a data-first or data-last style.
|
|
2556
|
+
* @param body - The function to be curried.
|
|
2557
|
+
* @since 1.0.0
|
|
2558
|
+
*/
|
|
2559
|
+
const dual = function(arity, body) {
|
|
2560
|
+
if (typeof arity === "function") return function() {
|
|
2561
|
+
return arity(arguments) ? body.apply(this, arguments) : ((self) => body(self, ...arguments));
|
|
2562
|
+
};
|
|
2563
|
+
switch (arity) {
|
|
2564
|
+
case 0:
|
|
2565
|
+
case 1: throw new RangeError(`Invalid arity ${arity}`);
|
|
2566
|
+
case 2: return function(a, b) {
|
|
2567
|
+
if (arguments.length >= 2) return body(a, b);
|
|
2568
|
+
return function(self) {
|
|
2569
|
+
return body(self, a);
|
|
2570
|
+
};
|
|
2571
|
+
};
|
|
2572
|
+
case 3: return function(a, b, c) {
|
|
2573
|
+
if (arguments.length >= 3) return body(a, b, c);
|
|
2574
|
+
return function(self) {
|
|
2575
|
+
return body(self, a, b);
|
|
2576
|
+
};
|
|
2577
|
+
};
|
|
2578
|
+
default: return function() {
|
|
2579
|
+
if (arguments.length >= arity) return body.apply(this, arguments);
|
|
2580
|
+
const args = arguments;
|
|
2581
|
+
return function(self) {
|
|
2582
|
+
return body(self, ...args);
|
|
2583
|
+
};
|
|
2584
|
+
};
|
|
2585
|
+
}
|
|
2586
|
+
};
|
|
2587
|
+
/**
|
|
2588
|
+
* Do nothing and return `void`.
|
|
2589
|
+
*/
|
|
2590
|
+
function constVoid() {}
|
|
2591
|
+
/**
|
|
2592
|
+
* Composes two functions, `ab` and `bc` into a single function that takes in an argument `a` of type `A` and returns a result of type `C`.
|
|
2593
|
+
* The result is obtained by first applying the `ab` function to `a` and then applying the `bc` function to the result of `ab`.
|
|
2594
|
+
*
|
|
2595
|
+
* @param self - The first function to apply (or the composed function in data-last style).
|
|
2596
|
+
* @param bc - The second function to apply.
|
|
2597
|
+
* @returns A composed function that applies both functions in sequence.
|
|
2598
|
+
* @example
|
|
2599
|
+
* ```ts
|
|
2600
|
+
* import * as assert from "node:assert"
|
|
2601
|
+
* import { compose } from "effect/Function"
|
|
2602
|
+
*
|
|
2603
|
+
* const increment = (n: number) => n + 1;
|
|
2604
|
+
* const square = (n: number) => n * n;
|
|
2605
|
+
*
|
|
2606
|
+
* assert.strictEqual(compose(increment, square)(2), 9);
|
|
2607
|
+
* ```
|
|
2608
|
+
*
|
|
2609
|
+
* @since 1.0.0
|
|
2610
|
+
*/
|
|
2611
|
+
const compose = dual(2, (ab, bc) => (a) => bc(ab(a)));
|
|
2612
|
+
function flow(ab, bc, cd, de, ef, fg, gh, hi, ij) {
|
|
2613
|
+
switch (arguments.length) {
|
|
2614
|
+
case 1: return ab;
|
|
2615
|
+
case 2: return function() {
|
|
2616
|
+
return bc(ab.apply(this, arguments));
|
|
2617
|
+
};
|
|
2618
|
+
case 3: return function() {
|
|
2619
|
+
return cd(bc(ab.apply(this, arguments)));
|
|
2620
|
+
};
|
|
2621
|
+
case 4: return function() {
|
|
2622
|
+
return de(cd(bc(ab.apply(this, arguments))));
|
|
2623
|
+
};
|
|
2624
|
+
case 5: return function() {
|
|
2625
|
+
return ef(de(cd(bc(ab.apply(this, arguments)))));
|
|
2626
|
+
};
|
|
2627
|
+
case 6: return function() {
|
|
2628
|
+
return fg(ef(de(cd(bc(ab.apply(this, arguments))))));
|
|
2629
|
+
};
|
|
2630
|
+
case 7: return function() {
|
|
2631
|
+
return gh(fg(ef(de(cd(bc(ab.apply(this, arguments)))))));
|
|
2632
|
+
};
|
|
2633
|
+
case 8: return function() {
|
|
2634
|
+
return hi(gh(fg(ef(de(cd(bc(ab.apply(this, arguments))))))));
|
|
2635
|
+
};
|
|
2636
|
+
case 9: return function() {
|
|
2637
|
+
return ij(hi(gh(fg(ef(de(cd(bc(ab.apply(this, arguments)))))))));
|
|
2638
|
+
};
|
|
2639
|
+
}
|
|
2640
|
+
}
|
|
2641
|
+
function getOrInsertComputed(map, key, callback) {
|
|
2642
|
+
if (map.has(key)) return map.get(key);
|
|
2643
|
+
const value = callback(key);
|
|
2644
|
+
map.set(key, value);
|
|
2645
|
+
return value;
|
|
2646
|
+
}
|
|
2647
|
+
|
|
2671
2648
|
//#endregion
|
|
2672
2649
|
//#region src/rules/no-leaked-conditional-rendering/lib.ts
|
|
2673
2650
|
/**
|
|
@@ -3303,7 +3280,7 @@ function containsUseComments(context, node) {
|
|
|
3303
3280
|
return context.sourceCode.getCommentsInside(node).some(({ value }) => /use\([\s\S]*?\)/u.test(value) || /use[A-Z0-9]\w*\([\s\S]*?\)/u.test(value));
|
|
3304
3281
|
}
|
|
3305
3282
|
function isTestMock(node) {
|
|
3306
|
-
return node != null && node.type === AST_NODE_TYPES.MemberExpression && node.object.type === AST_NODE_TYPES.Identifier &&
|
|
3283
|
+
return node != null && node.type === AST_NODE_TYPES.MemberExpression && node.object.type === AST_NODE_TYPES.Identifier && node.property.type === AST_NODE_TYPES.Identifier && node.property.name === "mock";
|
|
3307
3284
|
}
|
|
3308
3285
|
function isTestMockCallback(node) {
|
|
3309
3286
|
return node != null && Check.isFunction(node) && node.parent.type === AST_NODE_TYPES.CallExpression && isTestMock(node.parent.callee) && node.parent.arguments[1] === node;
|
|
@@ -3618,12 +3595,6 @@ const LIFECYCLE_METHODS = /* @__PURE__ */ new Set([
|
|
|
3618
3595
|
"UNSAFE_componentWillReceiveProps",
|
|
3619
3596
|
"UNSAFE_componentWillUpdate"
|
|
3620
3597
|
]);
|
|
3621
|
-
function isKeyLiteral(node, key) {
|
|
3622
|
-
return match(key).with({ type: AST_NODE_TYPES.Literal }, constTrue).with({
|
|
3623
|
-
type: AST_NODE_TYPES.TemplateLiteral,
|
|
3624
|
-
expressions: []
|
|
3625
|
-
}, constTrue).with({ type: AST_NODE_TYPES.Identifier }, () => !node.computed).otherwise(constFalse);
|
|
3626
|
-
}
|
|
3627
3598
|
|
|
3628
3599
|
//#endregion
|
|
3629
3600
|
//#region src/rules/no-unused-class-component-members/no-unused-class-component-members.ts
|
|
@@ -3658,8 +3629,7 @@ function create$11(context) {
|
|
|
3658
3629
|
const usages = propertyUsages.get(currentClass);
|
|
3659
3630
|
if (defs == null) return;
|
|
3660
3631
|
for (const def of defs) {
|
|
3661
|
-
const methodName =
|
|
3662
|
-
if (methodName == null) continue;
|
|
3632
|
+
const methodName = def.name;
|
|
3663
3633
|
if (usages?.has(methodName) ?? false) continue;
|
|
3664
3634
|
if (LIFECYCLE_METHODS.has(methodName)) if (methodName === "shouldComponentUpdate" && core.isPureComponent(currentClass)) {} else continue;
|
|
3665
3635
|
context.report({
|
|
@@ -3677,7 +3647,7 @@ function create$11(context) {
|
|
|
3677
3647
|
const currentClass = classStack.at(-1);
|
|
3678
3648
|
if (currentClass == null || !core.isClassComponent(currentClass)) return;
|
|
3679
3649
|
if (node.static) return;
|
|
3680
|
-
if (
|
|
3650
|
+
if (!node.computed && node.key.type === AST_NODE_TYPES.Identifier) propertyDefs.get(currentClass)?.add(node.key);
|
|
3681
3651
|
}
|
|
3682
3652
|
function methodExit() {
|
|
3683
3653
|
methodStack.pop();
|
|
@@ -3692,13 +3662,12 @@ function create$11(context) {
|
|
|
3692
3662
|
const currentMethod = methodStack.at(-1);
|
|
3693
3663
|
if (currentClass == null || currentMethod == null) return;
|
|
3694
3664
|
if (!core.isClassComponent(currentClass) || currentMethod.static) return;
|
|
3695
|
-
if (node.object.type !== AST_NODE_TYPES.ThisExpression ||
|
|
3665
|
+
if (node.object.type !== AST_NODE_TYPES.ThisExpression || node.computed || node.property.type !== AST_NODE_TYPES.Identifier) return;
|
|
3696
3666
|
if (node.parent.type === AST_NODE_TYPES.AssignmentExpression && node.parent.left === node) {
|
|
3697
3667
|
propertyDefs.get(currentClass)?.add(node.property);
|
|
3698
3668
|
return;
|
|
3699
3669
|
}
|
|
3700
|
-
|
|
3701
|
-
if (propertyName != null) propertyUsages.get(currentClass)?.add(propertyName);
|
|
3670
|
+
propertyUsages.get(currentClass)?.add(node.property.name);
|
|
3702
3671
|
},
|
|
3703
3672
|
MethodDefinition: methodEnter,
|
|
3704
3673
|
"MethodDefinition:exit": methodExit,
|
|
@@ -3710,10 +3679,7 @@ function create$11(context) {
|
|
|
3710
3679
|
if (currentClass == null || currentMethod == null) return;
|
|
3711
3680
|
if (!core.isClassComponent(currentClass) || currentMethod.static) return;
|
|
3712
3681
|
if (node.init != null && node.init.type === AST_NODE_TYPES.ThisExpression && node.id.type === AST_NODE_TYPES.ObjectPattern) {
|
|
3713
|
-
for (const prop of node.id.properties) if (prop.type === AST_NODE_TYPES.Property &&
|
|
3714
|
-
const keyName = Extract.getPropertyName(prop.key);
|
|
3715
|
-
if (keyName != null) propertyUsages.get(currentClass)?.add(keyName);
|
|
3716
|
-
}
|
|
3682
|
+
for (const prop of node.id.properties) if (prop.type === AST_NODE_TYPES.Property && !prop.computed && prop.key.type === AST_NODE_TYPES.Identifier) propertyUsages.get(currentClass)?.add(prop.key.name);
|
|
3717
3683
|
}
|
|
3718
3684
|
}
|
|
3719
3685
|
};
|
|
@@ -4212,21 +4178,6 @@ const IMPURE_CTORS = /* @__PURE__ */ new Set([
|
|
|
4212
4178
|
"Worker",
|
|
4213
4179
|
"XMLHttpRequest"
|
|
4214
4180
|
]);
|
|
4215
|
-
|
|
4216
|
-
//#endregion
|
|
4217
|
-
//#region src/rules/purity/purity.ts
|
|
4218
|
-
const RULE_NAME$7 = "purity";
|
|
4219
|
-
var purity_default = createRule({
|
|
4220
|
-
meta: {
|
|
4221
|
-
type: "problem",
|
|
4222
|
-
docs: { description: "Validates that components and hooks are pure by checking that they do not call known-impure functions during render." },
|
|
4223
|
-
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." },
|
|
4224
|
-
schema: []
|
|
4225
|
-
},
|
|
4226
|
-
name: RULE_NAME$7,
|
|
4227
|
-
create: create$7,
|
|
4228
|
-
defaultOptions: []
|
|
4229
|
-
});
|
|
4230
4181
|
/**
|
|
4231
4182
|
* Recursively resolve an identifier to the root builtin global object name.
|
|
4232
4183
|
* Follows simple assignment chains like `const M = Math` or `const w = window`.
|
|
@@ -4254,6 +4205,21 @@ function resolveBuiltinObjectName(context, node, seen = /* @__PURE__ */ new Set(
|
|
|
4254
4205
|
}
|
|
4255
4206
|
return null;
|
|
4256
4207
|
}
|
|
4208
|
+
|
|
4209
|
+
//#endregion
|
|
4210
|
+
//#region src/rules/purity/purity.ts
|
|
4211
|
+
const RULE_NAME$7 = "purity";
|
|
4212
|
+
var purity_default = createRule({
|
|
4213
|
+
meta: {
|
|
4214
|
+
type: "problem",
|
|
4215
|
+
docs: { description: "Validates that components and hooks are pure by checking that they do not call known-impure functions during render." },
|
|
4216
|
+
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." },
|
|
4217
|
+
schema: []
|
|
4218
|
+
},
|
|
4219
|
+
name: RULE_NAME$7,
|
|
4220
|
+
create: create$7,
|
|
4221
|
+
defaultOptions: []
|
|
4222
|
+
});
|
|
4257
4223
|
function create$7(context) {
|
|
4258
4224
|
const hc = core.getHookCollector(context);
|
|
4259
4225
|
const fc = core.getFunctionComponentCollector(context);
|
|
@@ -4341,6 +4307,149 @@ const SYNC_ARRAY_CALLBACKS = /* @__PURE__ */ new Set([
|
|
|
4341
4307
|
"some",
|
|
4342
4308
|
"sort"
|
|
4343
4309
|
]);
|
|
4310
|
+
function createBindingResolver(context) {
|
|
4311
|
+
const bindings = /* @__PURE__ */ new Map();
|
|
4312
|
+
const memberBindings = /* @__PURE__ */ new Map();
|
|
4313
|
+
const jsxRefs = /* @__PURE__ */ new Set();
|
|
4314
|
+
function getVariable(node) {
|
|
4315
|
+
return findVariable(context.sourceCode.getScope(node), node) ?? null;
|
|
4316
|
+
}
|
|
4317
|
+
function getBindingValue(node) {
|
|
4318
|
+
const value = Extract.unwrap(node);
|
|
4319
|
+
if (value.type === AST_NODE_TYPES.Identifier) {
|
|
4320
|
+
const variable = getVariable(value);
|
|
4321
|
+
return variable == null ? { kind: "unknown" } : {
|
|
4322
|
+
kind: "variable",
|
|
4323
|
+
variable
|
|
4324
|
+
};
|
|
4325
|
+
}
|
|
4326
|
+
if (isFunctionExpressionLike(value)) return {
|
|
4327
|
+
kind: "function",
|
|
4328
|
+
node: value
|
|
4329
|
+
};
|
|
4330
|
+
if (value.type === AST_NODE_TYPES.CallExpression && (core.isUseRefCall(context, value) || core.isCreateRefCall(context, value))) return { kind: "ref" };
|
|
4331
|
+
if (value.type === AST_NODE_TYPES.MemberExpression && value.property.type === AST_NODE_TYPES.Identifier) {
|
|
4332
|
+
if (isRefLikeName(value.property.name)) return { kind: "ref" };
|
|
4333
|
+
}
|
|
4334
|
+
return { kind: "unknown" };
|
|
4335
|
+
}
|
|
4336
|
+
function addBinding(variable, value, position) {
|
|
4337
|
+
const events = bindings.get(variable) ?? [];
|
|
4338
|
+
bindings.set(variable, events);
|
|
4339
|
+
events.push({
|
|
4340
|
+
position,
|
|
4341
|
+
value
|
|
4342
|
+
});
|
|
4343
|
+
}
|
|
4344
|
+
function addIdentifierBinding(node, value, position = node.range[0]) {
|
|
4345
|
+
const variable = getVariable(node);
|
|
4346
|
+
if (variable != null) addBinding(variable, getBindingValue(value), position);
|
|
4347
|
+
}
|
|
4348
|
+
function addFunctionBinding(node, value, position) {
|
|
4349
|
+
const variable = getVariable(node);
|
|
4350
|
+
if (variable != null) addBinding(variable, {
|
|
4351
|
+
kind: "function",
|
|
4352
|
+
node: value
|
|
4353
|
+
}, position);
|
|
4354
|
+
}
|
|
4355
|
+
function addMemberBinding(object, property, value, position) {
|
|
4356
|
+
const variable = getVariable(object);
|
|
4357
|
+
if (variable == null) return;
|
|
4358
|
+
const properties = memberBindings.get(variable) ?? /* @__PURE__ */ new Map();
|
|
4359
|
+
memberBindings.set(variable, properties);
|
|
4360
|
+
const events = properties.get(property) ?? [];
|
|
4361
|
+
properties.set(property, events);
|
|
4362
|
+
events.push({
|
|
4363
|
+
position,
|
|
4364
|
+
value: getBindingValue(value)
|
|
4365
|
+
});
|
|
4366
|
+
}
|
|
4367
|
+
function addJsxRef(node) {
|
|
4368
|
+
const variable = getVariable(node);
|
|
4369
|
+
if (variable != null) jsxRefs.add(variable);
|
|
4370
|
+
}
|
|
4371
|
+
function resolveRef(variable, position, seen = /* @__PURE__ */ new Set()) {
|
|
4372
|
+
if (seen.has(variable)) return null;
|
|
4373
|
+
seen.add(variable);
|
|
4374
|
+
if (jsxRefs.has(variable) || isRefLikeName(variable.name)) return variable;
|
|
4375
|
+
const event = getLatestValue(bindings.get(variable), position);
|
|
4376
|
+
if (event != null) switch (event.value.kind) {
|
|
4377
|
+
case "ref": return variable;
|
|
4378
|
+
case "variable": return resolveRef(event.value.variable, event.position, seen);
|
|
4379
|
+
case "function":
|
|
4380
|
+
case "unknown": return null;
|
|
4381
|
+
}
|
|
4382
|
+
return null;
|
|
4383
|
+
}
|
|
4384
|
+
function resolveFunction(variable, position, seen = /* @__PURE__ */ new Set()) {
|
|
4385
|
+
if (seen.has(variable)) return null;
|
|
4386
|
+
seen.add(variable);
|
|
4387
|
+
const event = getLatestValue(bindings.get(variable), position);
|
|
4388
|
+
if (event == null) return null;
|
|
4389
|
+
switch (event.value.kind) {
|
|
4390
|
+
case "function": return event.value.node;
|
|
4391
|
+
case "variable": return resolveFunction(event.value.variable, event.position, seen);
|
|
4392
|
+
case "ref":
|
|
4393
|
+
case "unknown": return null;
|
|
4394
|
+
}
|
|
4395
|
+
}
|
|
4396
|
+
function resolveCallable(node, position) {
|
|
4397
|
+
const callee = Extract.unwrap(node);
|
|
4398
|
+
if (isFunctionExpressionLike(callee)) return callee;
|
|
4399
|
+
if (callee.type === AST_NODE_TYPES.Identifier) {
|
|
4400
|
+
const variable = getVariable(callee);
|
|
4401
|
+
return variable == null ? null : resolveFunction(variable, position);
|
|
4402
|
+
}
|
|
4403
|
+
if (callee.type !== AST_NODE_TYPES.MemberExpression || callee.property.type !== AST_NODE_TYPES.Identifier) return null;
|
|
4404
|
+
const object = Extract.unwrap(callee.object);
|
|
4405
|
+
const property = callee.property.name;
|
|
4406
|
+
if (object.type !== AST_NODE_TYPES.Identifier) return null;
|
|
4407
|
+
const variable = getVariable(object);
|
|
4408
|
+
if (variable == null) return null;
|
|
4409
|
+
const event = getLatestValue(memberBindings.get(variable)?.get(property), position);
|
|
4410
|
+
if (event == null) return null;
|
|
4411
|
+
if (event.value.kind === "function") return event.value.node;
|
|
4412
|
+
if (event.value.kind === "variable") return resolveFunction(event.value.variable, event.position);
|
|
4413
|
+
return null;
|
|
4414
|
+
}
|
|
4415
|
+
function getRefTarget(node) {
|
|
4416
|
+
const object = Extract.unwrap(node.object);
|
|
4417
|
+
if (object.type === AST_NODE_TYPES.Identifier) {
|
|
4418
|
+
const variable = getVariable(object);
|
|
4419
|
+
if (variable == null) return null;
|
|
4420
|
+
const identity = resolveRef(variable, node.range[0]);
|
|
4421
|
+
return identity == null ? null : { identity };
|
|
4422
|
+
}
|
|
4423
|
+
if (object.type === AST_NODE_TYPES.MemberExpression && object.property.type === AST_NODE_TYPES.Identifier) {
|
|
4424
|
+
if (isRefLikeName(object.property.name)) return { identity: null };
|
|
4425
|
+
}
|
|
4426
|
+
return null;
|
|
4427
|
+
}
|
|
4428
|
+
function getNullBranch(test, identity) {
|
|
4429
|
+
return getNullCheckBranch(test, (candidate) => {
|
|
4430
|
+
if (candidate.type !== AST_NODE_TYPES.MemberExpression) return false;
|
|
4431
|
+
if (candidate.property.type !== AST_NODE_TYPES.Identifier || candidate.property.name !== "current") return false;
|
|
4432
|
+
return getRefTarget(candidate)?.identity === identity;
|
|
4433
|
+
}, (candidate) => {
|
|
4434
|
+
if (candidate.type === AST_NODE_TYPES.Literal) return candidate.value == null;
|
|
4435
|
+
if (candidate.type === AST_NODE_TYPES.UnaryExpression && candidate.operator === "void") return true;
|
|
4436
|
+
if (candidate.type !== AST_NODE_TYPES.Identifier || candidate.name !== "undefined") return false;
|
|
4437
|
+
const variable = getVariable(candidate);
|
|
4438
|
+
return variable == null || variable.defs.length === 0;
|
|
4439
|
+
});
|
|
4440
|
+
}
|
|
4441
|
+
return {
|
|
4442
|
+
addFunctionBinding,
|
|
4443
|
+
addIdentifierBinding,
|
|
4444
|
+
addJsxRef,
|
|
4445
|
+
addMemberBinding,
|
|
4446
|
+
getNullBranch,
|
|
4447
|
+
getRefTarget,
|
|
4448
|
+
getVariable,
|
|
4449
|
+
resolveCallable,
|
|
4450
|
+
resolveRef
|
|
4451
|
+
};
|
|
4452
|
+
}
|
|
4344
4453
|
function getLatestValue(events, position) {
|
|
4345
4454
|
let latest = null;
|
|
4346
4455
|
for (const event of events ?? []) {
|
|
@@ -4355,15 +4464,9 @@ function isFunctionExpressionLike(node) {
|
|
|
4355
4464
|
function isRefLikeName(name) {
|
|
4356
4465
|
return name === "ref" || name.endsWith("Ref");
|
|
4357
4466
|
}
|
|
4358
|
-
function getCalleeName(node) {
|
|
4359
|
-
const callee = Extract.unwrap(node.callee);
|
|
4360
|
-
if (callee.type === AST_NODE_TYPES.Identifier) return callee.name;
|
|
4361
|
-
if (callee.type === AST_NODE_TYPES.MemberExpression) return Extract.getPropertyName(callee.property);
|
|
4362
|
-
return null;
|
|
4363
|
-
}
|
|
4364
4467
|
function getSynchronousCallbackIndexes(node) {
|
|
4365
4468
|
const callee = Extract.unwrap(node.callee);
|
|
4366
|
-
const name = getCalleeName(node);
|
|
4469
|
+
const name = Extract.getCalleeName(node);
|
|
4367
4470
|
if (name == null) return [];
|
|
4368
4471
|
if (callee.type === AST_NODE_TYPES.MemberExpression && SYNC_ARRAY_CALLBACKS.has(name)) return [0];
|
|
4369
4472
|
switch (name) {
|
|
@@ -4381,6 +4484,16 @@ function isReachedThroughFunctions(node, boundary, reached) {
|
|
|
4381
4484
|
}
|
|
4382
4485
|
return current === boundary;
|
|
4383
4486
|
}
|
|
4487
|
+
function getRefAccess(node) {
|
|
4488
|
+
let parent = node.parent;
|
|
4489
|
+
while (Check.isTypeExpression(parent)) parent = parent.parent;
|
|
4490
|
+
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;
|
|
4491
|
+
return {
|
|
4492
|
+
isInitializationWrite: parent.type === AST_NODE_TYPES.AssignmentExpression && parent.operator === "=" && (parent.left === node || Extract.unwrap(parent.left) === node),
|
|
4493
|
+
isWrite: isDirectWrite || isNestedRefCurrentWrite(node),
|
|
4494
|
+
node
|
|
4495
|
+
};
|
|
4496
|
+
}
|
|
4384
4497
|
/**
|
|
4385
4498
|
* Check whether `node` (a `ref.current` MemberExpression) is being written to indirectly through
|
|
4386
4499
|
* a nested property write, e.g. `ref.current.inner = value` or `ref.current.inner++`.
|
|
@@ -4402,16 +4515,6 @@ function isNestedRefCurrentWrite(node) {
|
|
|
4402
4515
|
return false;
|
|
4403
4516
|
}
|
|
4404
4517
|
}
|
|
4405
|
-
function getRefAccess(node) {
|
|
4406
|
-
let parent = node.parent;
|
|
4407
|
-
while (Check.isTypeExpression(parent)) parent = parent.parent;
|
|
4408
|
-
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;
|
|
4409
|
-
return {
|
|
4410
|
-
isInitializationWrite: parent.type === AST_NODE_TYPES.AssignmentExpression && parent.operator === "=" && (parent.left === node || Extract.unwrap(parent.left) === node),
|
|
4411
|
-
isWrite: isDirectWrite || isNestedRefCurrentWrite(node),
|
|
4412
|
-
node
|
|
4413
|
-
};
|
|
4414
|
-
}
|
|
4415
4518
|
/**
|
|
4416
4519
|
* Parse an exact nullish check and return the branch where the checked value is null/undefined.
|
|
4417
4520
|
* Truthiness checks such as `!ref.current` are deliberately excluded: falsy ref values are not
|
|
@@ -4475,7 +4578,7 @@ function isAfterTerminatingNonNullGuard(node, getNullBranch) {
|
|
|
4475
4578
|
statement = statement.parent;
|
|
4476
4579
|
}
|
|
4477
4580
|
const block = statement.parent;
|
|
4478
|
-
const index = block.body.
|
|
4581
|
+
const index = block.body.findIndex((sibling) => sibling === statement);
|
|
4479
4582
|
for (let i = index - 1; i >= 0; i--) {
|
|
4480
4583
|
const sibling = block.body[i];
|
|
4481
4584
|
if (sibling?.type !== AST_NODE_TYPES.IfStatement) continue;
|
|
@@ -4509,159 +4612,35 @@ var refs_default = createRule({
|
|
|
4509
4612
|
function create$6(context) {
|
|
4510
4613
|
const hc = core.getHookCollector(context);
|
|
4511
4614
|
const fc = core.getFunctionComponentCollector(context);
|
|
4512
|
-
const
|
|
4513
|
-
const memberBindings = /* @__PURE__ */ new Map();
|
|
4514
|
-
const jsxRefs = /* @__PURE__ */ new Set();
|
|
4615
|
+
const { addFunctionBinding, addIdentifierBinding, addJsxRef, addMemberBinding, getNullBranch, getRefTarget, getVariable, resolveCallable, resolveRef } = createBindingResolver(context);
|
|
4515
4616
|
const calls = [];
|
|
4516
4617
|
const refAccesses = [];
|
|
4517
|
-
function getVariable(node) {
|
|
4518
|
-
return findVariable(context.sourceCode.getScope(node), node) ?? null;
|
|
4519
|
-
}
|
|
4520
|
-
function addBinding(variable, value, position) {
|
|
4521
|
-
const events = bindings.get(variable) ?? [];
|
|
4522
|
-
bindings.set(variable, events);
|
|
4523
|
-
events.push({
|
|
4524
|
-
position,
|
|
4525
|
-
value
|
|
4526
|
-
});
|
|
4527
|
-
}
|
|
4528
|
-
function addIdentifierBinding(node, value, position = node.range[0]) {
|
|
4529
|
-
const variable = getVariable(node);
|
|
4530
|
-
if (variable != null) addBinding(variable, value, position);
|
|
4531
|
-
}
|
|
4532
|
-
function addMemberBinding(object, property, value, position) {
|
|
4533
|
-
const variable = getVariable(object);
|
|
4534
|
-
if (variable == null) return;
|
|
4535
|
-
const properties = memberBindings.get(variable) ?? /* @__PURE__ */ new Map();
|
|
4536
|
-
memberBindings.set(variable, properties);
|
|
4537
|
-
const events = properties.get(property) ?? [];
|
|
4538
|
-
properties.set(property, events);
|
|
4539
|
-
events.push({
|
|
4540
|
-
position,
|
|
4541
|
-
value
|
|
4542
|
-
});
|
|
4543
|
-
}
|
|
4544
|
-
function bindingValueFrom(node) {
|
|
4545
|
-
const value = Extract.unwrap(node);
|
|
4546
|
-
if (value.type === AST_NODE_TYPES.Identifier) {
|
|
4547
|
-
const variable = getVariable(value);
|
|
4548
|
-
return variable == null ? { kind: "unknown" } : {
|
|
4549
|
-
kind: "variable",
|
|
4550
|
-
variable
|
|
4551
|
-
};
|
|
4552
|
-
}
|
|
4553
|
-
if (isFunctionExpressionLike(value)) return {
|
|
4554
|
-
kind: "function",
|
|
4555
|
-
node: value
|
|
4556
|
-
};
|
|
4557
|
-
if (value.type === AST_NODE_TYPES.CallExpression && (core.isUseRefCall(context, value) || core.isCreateRefCall(context, value))) return { kind: "ref" };
|
|
4558
|
-
if (value.type === AST_NODE_TYPES.MemberExpression) {
|
|
4559
|
-
const property = Extract.getPropertyName(value.property);
|
|
4560
|
-
if (property != null && isRefLikeName(property)) return { kind: "ref" };
|
|
4561
|
-
}
|
|
4562
|
-
return { kind: "unknown" };
|
|
4563
|
-
}
|
|
4564
|
-
function resolveRef(variable, position, seen = /* @__PURE__ */ new Set()) {
|
|
4565
|
-
if (seen.has(variable)) return null;
|
|
4566
|
-
seen.add(variable);
|
|
4567
|
-
if (jsxRefs.has(variable) || isRefLikeName(variable.name)) return variable;
|
|
4568
|
-
const event = getLatestValue(bindings.get(variable), position);
|
|
4569
|
-
if (event != null) switch (event.value.kind) {
|
|
4570
|
-
case "ref": return variable;
|
|
4571
|
-
case "variable": return resolveRef(event.value.variable, event.position, seen);
|
|
4572
|
-
case "function":
|
|
4573
|
-
case "unknown": return null;
|
|
4574
|
-
}
|
|
4575
|
-
return null;
|
|
4576
|
-
}
|
|
4577
|
-
function resolveFunction(variable, position, seen = /* @__PURE__ */ new Set()) {
|
|
4578
|
-
if (seen.has(variable)) return null;
|
|
4579
|
-
seen.add(variable);
|
|
4580
|
-
const event = getLatestValue(bindings.get(variable), position);
|
|
4581
|
-
if (event == null) return null;
|
|
4582
|
-
switch (event.value.kind) {
|
|
4583
|
-
case "function": return event.value.node;
|
|
4584
|
-
case "variable": return resolveFunction(event.value.variable, event.position, seen);
|
|
4585
|
-
case "ref":
|
|
4586
|
-
case "unknown": return null;
|
|
4587
|
-
}
|
|
4588
|
-
}
|
|
4589
|
-
function resolveCallable(node, position) {
|
|
4590
|
-
const callee = Extract.unwrap(node);
|
|
4591
|
-
if (isFunctionExpressionLike(callee)) return callee;
|
|
4592
|
-
if (callee.type === AST_NODE_TYPES.Identifier) {
|
|
4593
|
-
const variable = getVariable(callee);
|
|
4594
|
-
return variable == null ? null : resolveFunction(variable, position);
|
|
4595
|
-
}
|
|
4596
|
-
if (callee.type !== AST_NODE_TYPES.MemberExpression) return null;
|
|
4597
|
-
const object = Extract.unwrap(callee.object);
|
|
4598
|
-
const property = Extract.getPropertyName(callee.property);
|
|
4599
|
-
if (object.type !== AST_NODE_TYPES.Identifier || property == null) return null;
|
|
4600
|
-
const variable = getVariable(object);
|
|
4601
|
-
if (variable == null) return null;
|
|
4602
|
-
const event = getLatestValue(memberBindings.get(variable)?.get(property), position);
|
|
4603
|
-
if (event == null) return null;
|
|
4604
|
-
if (event.value.kind === "function") return event.value.node;
|
|
4605
|
-
if (event.value.kind === "variable") return resolveFunction(event.value.variable, event.position);
|
|
4606
|
-
return null;
|
|
4607
|
-
}
|
|
4608
|
-
function getRefTarget(node) {
|
|
4609
|
-
const object = Extract.unwrap(node.object);
|
|
4610
|
-
if (object.type === AST_NODE_TYPES.Identifier) {
|
|
4611
|
-
const variable = getVariable(object);
|
|
4612
|
-
if (variable == null) return null;
|
|
4613
|
-
const identity = resolveRef(variable, node.range[0]);
|
|
4614
|
-
return identity == null ? null : { identity };
|
|
4615
|
-
}
|
|
4616
|
-
if (object.type === AST_NODE_TYPES.MemberExpression) {
|
|
4617
|
-
const property = Extract.getPropertyName(object.property);
|
|
4618
|
-
if (property != null && isRefLikeName(property)) return { identity: null };
|
|
4619
|
-
}
|
|
4620
|
-
return null;
|
|
4621
|
-
}
|
|
4622
|
-
function getNullBranch(test, identity) {
|
|
4623
|
-
return getNullCheckBranch(test, (candidate) => {
|
|
4624
|
-
if (candidate.type !== AST_NODE_TYPES.MemberExpression || Extract.getPropertyName(candidate.property) !== "current") return false;
|
|
4625
|
-
return getRefTarget(candidate)?.identity === identity;
|
|
4626
|
-
}, (candidate) => {
|
|
4627
|
-
if (candidate.type === AST_NODE_TYPES.Literal) return candidate.value == null;
|
|
4628
|
-
if (candidate.type === AST_NODE_TYPES.UnaryExpression && candidate.operator === "void") return true;
|
|
4629
|
-
if (candidate.type !== AST_NODE_TYPES.Identifier || candidate.name !== "undefined") return false;
|
|
4630
|
-
const variable = getVariable(candidate);
|
|
4631
|
-
return variable == null || variable.defs.length === 0;
|
|
4632
|
-
});
|
|
4633
|
-
}
|
|
4634
4618
|
return merge(hc.visitor, fc.visitor, {
|
|
4635
4619
|
AssignmentExpression(node) {
|
|
4636
4620
|
if (node.operator !== "=") return;
|
|
4637
4621
|
const left = Extract.unwrap(node.left);
|
|
4638
4622
|
if (left.type === AST_NODE_TYPES.Identifier) {
|
|
4639
|
-
addIdentifierBinding(left,
|
|
4623
|
+
addIdentifierBinding(left, node.right, node.range[0]);
|
|
4640
4624
|
return;
|
|
4641
4625
|
}
|
|
4642
|
-
if (left.type !== AST_NODE_TYPES.MemberExpression) return;
|
|
4626
|
+
if (left.type !== AST_NODE_TYPES.MemberExpression || left.property.type !== AST_NODE_TYPES.Identifier) return;
|
|
4643
4627
|
const object = Extract.unwrap(left.object);
|
|
4644
|
-
|
|
4645
|
-
if (object.type === AST_NODE_TYPES.Identifier && property != null) addMemberBinding(object, property, bindingValueFrom(node.right), node.range[0]);
|
|
4628
|
+
if (object.type === AST_NODE_TYPES.Identifier) addMemberBinding(object, left.property.name, node.right, node.range[0]);
|
|
4646
4629
|
},
|
|
4647
4630
|
CallExpression(node) {
|
|
4648
4631
|
calls.push(node);
|
|
4649
4632
|
},
|
|
4650
4633
|
FunctionDeclaration(node) {
|
|
4651
|
-
if (node.id != null)
|
|
4652
|
-
kind: "function",
|
|
4653
|
-
node
|
|
4654
|
-
}, -1);
|
|
4634
|
+
if (node.id != null) addFunctionBinding(node.id, node, -1);
|
|
4655
4635
|
},
|
|
4656
4636
|
JSXAttribute(node) {
|
|
4657
4637
|
if (node.name.type !== AST_NODE_TYPES.JSXIdentifier || node.name.name !== "ref" || node.value?.type !== AST_NODE_TYPES.JSXExpressionContainer) return;
|
|
4658
4638
|
const expression = Extract.unwrap(node.value.expression);
|
|
4659
4639
|
if (expression.type !== AST_NODE_TYPES.Identifier) return;
|
|
4660
|
-
|
|
4661
|
-
if (variable != null) jsxRefs.add(variable);
|
|
4640
|
+
addJsxRef(expression);
|
|
4662
4641
|
},
|
|
4663
4642
|
MemberExpression(node) {
|
|
4664
|
-
if (
|
|
4643
|
+
if (node.property.type !== AST_NODE_TYPES.Identifier || node.property.name !== "current") return;
|
|
4665
4644
|
refAccesses.push(getRefAccess(node));
|
|
4666
4645
|
},
|
|
4667
4646
|
"Program:exit"(program) {
|
|
@@ -4734,7 +4713,7 @@ function create$6(context) {
|
|
|
4734
4713
|
const boundary = Traverse.findParent(call, isBoundary);
|
|
4735
4714
|
if (boundary == null || !isReachedDuringRender(call, boundary)) continue;
|
|
4736
4715
|
const callee = Extract.unwrap(call.callee);
|
|
4737
|
-
const calleeName = getCalleeName(call);
|
|
4716
|
+
const calleeName = Extract.getCalleeName(call);
|
|
4738
4717
|
const callArguments = call.arguments;
|
|
4739
4718
|
if (core.isHookCall(call) || calleeName === "mergeRefs" || calleeName === "render" && callee.type === AST_NODE_TYPES.MemberExpression) continue;
|
|
4740
4719
|
for (const argument of callArguments) {
|
|
@@ -4752,7 +4731,7 @@ function create$6(context) {
|
|
|
4752
4731
|
},
|
|
4753
4732
|
VariableDeclarator(node) {
|
|
4754
4733
|
if (node.id.type !== AST_NODE_TYPES.Identifier || node.init == null) return;
|
|
4755
|
-
addIdentifierBinding(node.id,
|
|
4734
|
+
addIdentifierBinding(node.id, node.init, node.range[0]);
|
|
4756
4735
|
}
|
|
4757
4736
|
});
|
|
4758
4737
|
}
|
|
@@ -6987,12 +6966,8 @@ function isHookDecl(node) {
|
|
|
6987
6966
|
if (node.id.type !== AST_NODE_TYPES.Identifier) return false;
|
|
6988
6967
|
const init = node.init;
|
|
6989
6968
|
if (init == null || init.type !== AST_NODE_TYPES.CallExpression) return false;
|
|
6990
|
-
const
|
|
6991
|
-
|
|
6992
|
-
case AST_NODE_TYPES.Identifier: return core.isHookName(callee.name);
|
|
6993
|
-
case AST_NODE_TYPES.MemberExpression: return callee.property.type === AST_NODE_TYPES.Identifier && core.isHookName(callee.property.name);
|
|
6994
|
-
default: return false;
|
|
6995
|
-
}
|
|
6969
|
+
const name = Extract.getCalleeName(init);
|
|
6970
|
+
return name != null && core.isHookName(name);
|
|
6996
6971
|
}
|
|
6997
6972
|
function isInitializedFromRef(context, name, initialScope, seen = /* @__PURE__ */ new Set()) {
|
|
6998
6973
|
if (seen.has(name)) return false;
|
|
@@ -7077,8 +7052,7 @@ function create$5(context) {
|
|
|
7077
7052
|
if (setupFnRef.current === node) setupFnRef.current = null;
|
|
7078
7053
|
};
|
|
7079
7054
|
function isThenCall(node) {
|
|
7080
|
-
|
|
7081
|
-
return callee.type === AST_NODE_TYPES.MemberExpression && Extract.getPropertyName(callee.property) === "then";
|
|
7055
|
+
return Extract.unwrap(node.callee).type === AST_NODE_TYPES.MemberExpression && Extract.getCalleeName(node) === "then";
|
|
7082
7056
|
}
|
|
7083
7057
|
function isUseStateCall(node) {
|
|
7084
7058
|
return core.isUseStateLikeCall(node, additionalStateHooks);
|
|
@@ -7122,7 +7096,7 @@ function create$5(context) {
|
|
|
7122
7096
|
const innerCallee = Extract.unwrap(callee.callee);
|
|
7123
7097
|
if (innerCallee.type !== AST_NODE_TYPES.MemberExpression) return false;
|
|
7124
7098
|
if (!("name" in innerCallee.object)) return false;
|
|
7125
|
-
const isAt = Extract.
|
|
7099
|
+
const isAt = Extract.getCalleeName(callee) === "at";
|
|
7126
7100
|
const [index] = callee.arguments;
|
|
7127
7101
|
if (!isAt || index == null) return false;
|
|
7128
7102
|
return getStaticValue(index, context.sourceCode.getScope(node))?.value === 1 && isIdFromUseStateCall(innerCallee.object);
|
|
@@ -7344,7 +7318,7 @@ function create$4(context) {
|
|
|
7344
7318
|
const innerCallee = Extract.unwrap(callee.callee);
|
|
7345
7319
|
if (innerCallee.type !== AST_NODE_TYPES.MemberExpression) return false;
|
|
7346
7320
|
if (!("name" in innerCallee.object)) return false;
|
|
7347
|
-
const isAt = Extract.
|
|
7321
|
+
const isAt = Extract.getCalleeName(callee) === "at";
|
|
7348
7322
|
const [index] = callee.arguments;
|
|
7349
7323
|
if (!isAt || index == null) return false;
|
|
7350
7324
|
return getStaticValue(index, context.sourceCode.getScope(node))?.value === 1 && isIdFromUseStateCall(innerCallee.object);
|
|
@@ -7569,7 +7543,7 @@ function isEvalCall(node) {
|
|
|
7569
7543
|
case AST_NODE_TYPES.Identifier: return callee.name === "eval";
|
|
7570
7544
|
case AST_NODE_TYPES.MemberExpression:
|
|
7571
7545
|
if (!Check.isIdentifier(Extract.unwrap(callee.object), "globalThis")) return false;
|
|
7572
|
-
return
|
|
7546
|
+
return !callee.computed && callee.property.type === AST_NODE_TYPES.Identifier && callee.property.name === "eval";
|
|
7573
7547
|
default: return false;
|
|
7574
7548
|
}
|
|
7575
7549
|
}
|
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.9",
|
|
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/ast": "5.14.
|
|
49
|
-
"@eslint-react/
|
|
50
|
-
"@eslint-react/eslint": "5.14.
|
|
51
|
-
"@eslint-react/
|
|
52
|
-
"@eslint-react/
|
|
53
|
-
"@eslint-react/shared": "5.14.
|
|
48
|
+
"@eslint-react/ast": "5.14.9",
|
|
49
|
+
"@eslint-react/jsx": "5.14.9",
|
|
50
|
+
"@eslint-react/eslint": "5.14.9",
|
|
51
|
+
"@eslint-react/var": "5.14.9",
|
|
52
|
+
"@eslint-react/core": "5.14.9",
|
|
53
|
+
"@eslint-react/shared": "5.14.9"
|
|
54
54
|
},
|
|
55
55
|
"devDependencies": {
|
|
56
56
|
"@types/react": "^19.2.17",
|
|
@@ -59,12 +59,12 @@
|
|
|
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.7",
|
|
63
63
|
"tsl": "^1.0.30",
|
|
64
64
|
"tsl-dx": "^0.13.2",
|
|
65
65
|
"typescript": "6.0.3",
|
|
66
|
-
"@local/
|
|
67
|
-
"@local/
|
|
66
|
+
"@local/eff": "0.0.0",
|
|
67
|
+
"@local/configs": "0.0.0"
|
|
68
68
|
},
|
|
69
69
|
"peerDependencies": {
|
|
70
70
|
"eslint": "*",
|