oxlint-plugin-react-doctor 0.7.6-dev.55cebeb → 0.7.6-dev.5699529
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/index.js +49 -270
- package/package.json +1 -1
package/README.md
CHANGED
package/dist/index.js
CHANGED
|
@@ -10948,7 +10948,7 @@ const findDeclaratorForBinding = (bindingIdentifier) => {
|
|
|
10948
10948
|
};
|
|
10949
10949
|
//#endregion
|
|
10950
10950
|
//#region src/plugin/utils/executes-during-render.ts
|
|
10951
|
-
const SYNCHRONOUS_ITERATION_METHOD_NAMES
|
|
10951
|
+
const SYNCHRONOUS_ITERATION_METHOD_NAMES = new Set([
|
|
10952
10952
|
"map",
|
|
10953
10953
|
"filter",
|
|
10954
10954
|
"forEach",
|
|
@@ -10984,7 +10984,7 @@ const executesDuringRender = (functionNode, scopes) => {
|
|
|
10984
10984
|
if (parent.callee === functionNode) return true;
|
|
10985
10985
|
if ((scopes ? isReactApiCall(parent, REACT_RENDER_PHASE_HOOK_NAMES, scopes, { allowGlobalReactNamespace: true }) : isHookCall$2(parent, REACT_RENDER_PHASE_HOOK_NAMES)) && parent.arguments?.[0] === functionNode) return true;
|
|
10986
10986
|
if (scopes && parent.arguments?.[1] === functionNode && (isGlobalArrayFromMember(parent.callee, scopes) || isConstAliasOfGlobalArrayFrom(parent.callee, scopes))) return true;
|
|
10987
|
-
return isNodeOfType(parent.callee, "MemberExpression") && !parent.callee.computed && isNodeOfType(parent.callee.property, "Identifier") && SYNCHRONOUS_ITERATION_METHOD_NAMES
|
|
10987
|
+
return isNodeOfType(parent.callee, "MemberExpression") && !parent.callee.computed && isNodeOfType(parent.callee.property, "Identifier") && SYNCHRONOUS_ITERATION_METHOD_NAMES.has(parent.callee.property.name) && parent.arguments?.[0] === functionNode;
|
|
10988
10988
|
};
|
|
10989
10989
|
//#endregion
|
|
10990
10990
|
//#region src/plugin/utils/find-render-phase-component-or-hook.ts
|
|
@@ -15826,7 +15826,7 @@ const jotaiTqUseRawQueryAtom = defineRule({
|
|
|
15826
15826
|
});
|
|
15827
15827
|
//#endregion
|
|
15828
15828
|
//#region src/plugin/rules/js-performance/js-async-reduce-without-awaited-acc.ts
|
|
15829
|
-
const isAsyncFunctionLike
|
|
15829
|
+
const isAsyncFunctionLike = (node) => {
|
|
15830
15830
|
if (!node) return false;
|
|
15831
15831
|
if (!isNodeOfType(node, "ArrowFunctionExpression") && !isNodeOfType(node, "FunctionExpression")) return false;
|
|
15832
15832
|
return node.async === true;
|
|
@@ -15893,7 +15893,7 @@ const jsAsyncReduceWithoutAwaitedAcc = defineRule({
|
|
|
15893
15893
|
const args = node.arguments ?? [];
|
|
15894
15894
|
if (args.length === 0) return;
|
|
15895
15895
|
const reducerCandidate = stripParenExpression(args[0]);
|
|
15896
|
-
if (!isAsyncFunctionLike
|
|
15896
|
+
if (!isAsyncFunctionLike(reducerCandidate)) return;
|
|
15897
15897
|
const reducer = reducerCandidate;
|
|
15898
15898
|
if (!containsDirectAwait(reducer.body)) return;
|
|
15899
15899
|
const firstParameter = classifyFirstParameter(reducer);
|
|
@@ -28479,271 +28479,21 @@ const noCallComponentAsFunction = defineRule({
|
|
|
28479
28479
|
}
|
|
28480
28480
|
});
|
|
28481
28481
|
//#endregion
|
|
28482
|
-
//#region src/plugin/utils/
|
|
28483
|
-
const
|
|
28484
|
-
|
|
28485
|
-
|
|
28486
|
-
|
|
28487
|
-
|
|
28488
|
-
//#region src/plugin/utils/is-hook-binding-in-scope.ts
|
|
28489
|
-
const isHookBindingInScope = (node, query) => {
|
|
28490
|
-
const { bindingName, hookName, destructureIndex } = query;
|
|
28491
|
-
let cursor = node;
|
|
28492
|
-
while (cursor) {
|
|
28493
|
-
if (isNodeOfType(cursor, "BlockStatement") || isNodeOfType(cursor, "Program")) for (const statement of cursor.body ?? []) {
|
|
28494
|
-
if (!isNodeOfType(statement, "VariableDeclaration")) continue;
|
|
28495
|
-
for (const declarator of statement.declarations ?? []) {
|
|
28496
|
-
if (!isNodeOfType(declarator.init, "CallExpression")) continue;
|
|
28497
|
-
if (!isHookCall$2(declarator.init, hookName)) continue;
|
|
28498
|
-
if (destructureIndex !== void 0) {
|
|
28499
|
-
if (!isNodeOfType(declarator.id, "ArrayPattern")) continue;
|
|
28500
|
-
const elements = declarator.id.elements ?? [];
|
|
28501
|
-
if (elements.length <= destructureIndex) continue;
|
|
28502
|
-
const element = elements[destructureIndex];
|
|
28503
|
-
if (isNodeOfType(element, "Identifier") && element.name === bindingName) return true;
|
|
28504
|
-
} else if (isNodeOfType(declarator.id, "Identifier") && declarator.id.name === bindingName) return true;
|
|
28505
|
-
}
|
|
28506
|
-
}
|
|
28507
|
-
cursor = cursor.parent ?? null;
|
|
28508
|
-
}
|
|
28509
|
-
return false;
|
|
28510
|
-
};
|
|
28511
|
-
//#endregion
|
|
28512
|
-
//#region src/plugin/utils/is-use-state-setter-in-scope.ts
|
|
28513
|
-
const isUseStateSetterInScope = (node, setterName) => isHookBindingInScope(node, {
|
|
28514
|
-
bindingName: setterName,
|
|
28515
|
-
hookName: "useState",
|
|
28516
|
-
destructureIndex: 1
|
|
28482
|
+
//#region src/plugin/utils/define-retired-rule.ts
|
|
28483
|
+
const defineRetiredRule = (rule) => defineRule({
|
|
28484
|
+
...rule,
|
|
28485
|
+
defaultEnabled: false,
|
|
28486
|
+
lifecycle: "retired",
|
|
28487
|
+
create: () => ({})
|
|
28517
28488
|
});
|
|
28518
28489
|
//#endregion
|
|
28519
28490
|
//#region src/plugin/rules/state-and-effects/no-cascading-set-state.ts
|
|
28520
|
-
const
|
|
28521
|
-
if (isNodeOfType(node, "ArrowFunctionExpression") || isNodeOfType(node, "FunctionExpression") || isNodeOfType(node, "FunctionDeclaration")) return Boolean(node.async);
|
|
28522
|
-
return false;
|
|
28523
|
-
};
|
|
28524
|
-
const SYNCHRONOUS_ITERATION_METHOD_NAMES = new Set([
|
|
28525
|
-
"forEach",
|
|
28526
|
-
"map",
|
|
28527
|
-
"filter",
|
|
28528
|
-
"reduce",
|
|
28529
|
-
"reduceRight",
|
|
28530
|
-
"flatMap",
|
|
28531
|
-
"some",
|
|
28532
|
-
"every",
|
|
28533
|
-
"find",
|
|
28534
|
-
"findIndex",
|
|
28535
|
-
"findLast",
|
|
28536
|
-
"findLastIndex",
|
|
28537
|
-
"sort"
|
|
28538
|
-
]);
|
|
28539
|
-
const runsOnEffectDispatch = (functionNode) => {
|
|
28540
|
-
const parent = functionNode.parent;
|
|
28541
|
-
if (!parent || !isNodeOfType(parent, "CallExpression")) return false;
|
|
28542
|
-
if (parent.callee === functionNode) return true;
|
|
28543
|
-
if (!(parent.arguments ?? []).some((argument) => argument === functionNode)) return false;
|
|
28544
|
-
const callee = parent.callee;
|
|
28545
|
-
return isNodeOfType(callee, "MemberExpression") && isNodeOfType(callee.property, "Identifier") && SYNCHRONOUS_ITERATION_METHOD_NAMES.has(callee.property.name);
|
|
28546
|
-
};
|
|
28547
|
-
const isTerminatingStatement = (statement) => isNodeOfType(statement, "BreakStatement") || isNodeOfType(statement, "ReturnStatement") || isNodeOfType(statement, "ThrowStatement") || isNodeOfType(statement, "ContinueStatement");
|
|
28548
|
-
const analyzeBranchStatements = (branch, context) => analyzeStatementSequence(isNodeOfType(branch, "BlockStatement") ? branch.body ?? [] : [branch], context);
|
|
28549
|
-
const analyzeStatementSequence = (statements, context) => {
|
|
28550
|
-
let fallThroughCount = 0;
|
|
28551
|
-
let maxTerminatedCount = 0;
|
|
28552
|
-
for (const statement of statements) {
|
|
28553
|
-
if (isNodeOfType(statement, "IfStatement")) {
|
|
28554
|
-
fallThroughCount += countMaxPathSetStateCalls(statement.test, context);
|
|
28555
|
-
const thenSummary = analyzeBranchStatements(statement.consequent, context);
|
|
28556
|
-
const elseSummary = statement.alternate ? analyzeBranchStatements(statement.alternate, context) : {
|
|
28557
|
-
fallThroughCount: 0,
|
|
28558
|
-
maxTerminatedCount: 0,
|
|
28559
|
-
doAllPathsTerminate: false
|
|
28560
|
-
};
|
|
28561
|
-
maxTerminatedCount = Math.max(maxTerminatedCount, fallThroughCount + thenSummary.maxTerminatedCount, fallThroughCount + elseSummary.maxTerminatedCount);
|
|
28562
|
-
if (thenSummary.doAllPathsTerminate && elseSummary.doAllPathsTerminate) return {
|
|
28563
|
-
fallThroughCount: 0,
|
|
28564
|
-
maxTerminatedCount,
|
|
28565
|
-
doAllPathsTerminate: true
|
|
28566
|
-
};
|
|
28567
|
-
const fallThroughBranchCounts = [...thenSummary.doAllPathsTerminate ? [] : [thenSummary.fallThroughCount], ...elseSummary.doAllPathsTerminate ? [] : [elseSummary.fallThroughCount]];
|
|
28568
|
-
fallThroughCount += Math.max(...fallThroughBranchCounts);
|
|
28569
|
-
continue;
|
|
28570
|
-
}
|
|
28571
|
-
if (isTerminatingStatement(statement)) {
|
|
28572
|
-
const terminatedPathCount = fallThroughCount + countMaxPathSetStateCalls(statement, context);
|
|
28573
|
-
return {
|
|
28574
|
-
fallThroughCount: 0,
|
|
28575
|
-
maxTerminatedCount: Math.max(maxTerminatedCount, terminatedPathCount),
|
|
28576
|
-
doAllPathsTerminate: true
|
|
28577
|
-
};
|
|
28578
|
-
}
|
|
28579
|
-
fallThroughCount += countMaxPathSetStateCalls(statement, context);
|
|
28580
|
-
}
|
|
28581
|
-
return {
|
|
28582
|
-
fallThroughCount,
|
|
28583
|
-
maxTerminatedCount,
|
|
28584
|
-
doAllPathsTerminate: false
|
|
28585
|
-
};
|
|
28586
|
-
};
|
|
28587
|
-
const countStatementSequenceSetStateCalls = (statements, context) => {
|
|
28588
|
-
const summary = analyzeStatementSequence(statements, context);
|
|
28589
|
-
return Math.max(summary.fallThroughCount, summary.maxTerminatedCount);
|
|
28590
|
-
};
|
|
28591
|
-
const collectLocalHelperFunctions = (root) => {
|
|
28592
|
-
const helpersByName = /* @__PURE__ */ new Map();
|
|
28593
|
-
const visit = (node) => {
|
|
28594
|
-
if (isNodeOfType(node, "FunctionDeclaration") && node.id) helpersByName.set(node.id.name, node);
|
|
28595
|
-
if (isNodeOfType(node, "VariableDeclarator") && isNodeOfType(node.id, "Identifier") && node.init && isFunctionLike$2(node.init)) helpersByName.set(node.id.name, node.init);
|
|
28596
|
-
if (isNodeOfType(node, "VariableDeclarator") && isNodeOfType(node.id, "Identifier") && node.init && isNodeOfType(node.init, "CallExpression") && isNodeOfType(node.init.callee, "Identifier") && node.init.callee.name === "useCallback" && node.init.arguments?.[0] && isFunctionLike$2(node.init.arguments[0])) helpersByName.set(node.id.name, node.init.arguments[0]);
|
|
28597
|
-
const record = node;
|
|
28598
|
-
for (const key of Object.keys(record)) {
|
|
28599
|
-
if (key === "parent") continue;
|
|
28600
|
-
const child = record[key];
|
|
28601
|
-
if (Array.isArray(child)) {
|
|
28602
|
-
for (const item of child) if (item && typeof item === "object" && "type" in item) visit(item);
|
|
28603
|
-
} else if (child && typeof child === "object" && "type" in child) visit(child);
|
|
28604
|
-
}
|
|
28605
|
-
};
|
|
28606
|
-
visit(root);
|
|
28607
|
-
return helpersByName;
|
|
28608
|
-
};
|
|
28609
|
-
const isWholesaleDelegationCall = (callNode, effectCallback) => {
|
|
28610
|
-
const parent = callNode.parent;
|
|
28611
|
-
if (!parent) return false;
|
|
28612
|
-
if (parent === effectCallback) return true;
|
|
28613
|
-
if (!isNodeOfType(parent, "ExpressionStatement")) return false;
|
|
28614
|
-
return parent.parent === effectCallback.body;
|
|
28615
|
-
};
|
|
28616
|
-
const countFunctionBodySetStateCalls = (functionNode, context) => {
|
|
28617
|
-
if (isAsyncFunctionLike(functionNode)) return 0;
|
|
28618
|
-
const body = functionNode.body;
|
|
28619
|
-
if (!body) return 0;
|
|
28620
|
-
return countMaxPathSetStateCalls(body, context);
|
|
28621
|
-
};
|
|
28622
|
-
const countMaxPathSetStateCalls = (node, context) => {
|
|
28623
|
-
if (!node || typeof node !== "object") return 0;
|
|
28624
|
-
if (isFunctionLike$2(node)) return 0;
|
|
28625
|
-
if (isNodeOfType(node, "BlockStatement") || isNodeOfType(node, "Program")) return countStatementSequenceSetStateCalls(node.body ?? [], context);
|
|
28626
|
-
if (isNodeOfType(node, "IfStatement") || isNodeOfType(node, "ConditionalExpression")) {
|
|
28627
|
-
const consequent = node.consequent;
|
|
28628
|
-
const alternate = node.alternate;
|
|
28629
|
-
const testCount = countMaxPathSetStateCalls(node.test, context);
|
|
28630
|
-
const thenCount = countMaxPathSetStateCalls(consequent, context);
|
|
28631
|
-
const elseCount = alternate ? countMaxPathSetStateCalls(alternate, context) : 0;
|
|
28632
|
-
return testCount + Math.max(thenCount, elseCount);
|
|
28633
|
-
}
|
|
28634
|
-
if (isNodeOfType(node, "SwitchStatement")) {
|
|
28635
|
-
let maxRunSetters = 0;
|
|
28636
|
-
let currentRunSetters = 0;
|
|
28637
|
-
for (const switchCase of node.cases ?? []) {
|
|
28638
|
-
const consequent = switchCase.consequent ?? [];
|
|
28639
|
-
let caseSetters = 0;
|
|
28640
|
-
let runEnds = false;
|
|
28641
|
-
for (const statement of consequent) {
|
|
28642
|
-
caseSetters += countMaxPathSetStateCalls(statement, context);
|
|
28643
|
-
if (isTerminatingStatement(statement)) runEnds = true;
|
|
28644
|
-
}
|
|
28645
|
-
currentRunSetters += caseSetters;
|
|
28646
|
-
if (runEnds) {
|
|
28647
|
-
if (currentRunSetters > maxRunSetters) maxRunSetters = currentRunSetters;
|
|
28648
|
-
currentRunSetters = 0;
|
|
28649
|
-
}
|
|
28650
|
-
}
|
|
28651
|
-
if (currentRunSetters > maxRunSetters) maxRunSetters = currentRunSetters;
|
|
28652
|
-
return maxRunSetters;
|
|
28653
|
-
}
|
|
28654
|
-
if (isNodeOfType(node, "TryStatement")) {
|
|
28655
|
-
const tryCount = countMaxPathSetStateCalls(node.block, context);
|
|
28656
|
-
const catchCount = node.handler ? countMaxPathSetStateCalls(node.handler.body, context) : 0;
|
|
28657
|
-
const finallyCount = node.finalizer ? countMaxPathSetStateCalls(node.finalizer, context) : 0;
|
|
28658
|
-
return Math.max(tryCount, catchCount) + finallyCount;
|
|
28659
|
-
}
|
|
28660
|
-
if (isNodeOfType(node, "CallExpression") && isSetterCall(node) && isNodeOfType(node.callee, "Identifier") && isUseStateSetterInScope(node, node.callee.name)) {
|
|
28661
|
-
let nestedSettersInArgs = 0;
|
|
28662
|
-
for (const argument of node.arguments ?? []) nestedSettersInArgs += isFunctionLike$2(argument) ? countFunctionBodySetStateCalls(argument, context) : countMaxPathSetStateCalls(argument, context);
|
|
28663
|
-
return 1 + nestedSettersInArgs;
|
|
28664
|
-
}
|
|
28665
|
-
if (isNodeOfType(node, "CallExpression") && isNodeOfType(node.callee, "Identifier")) {
|
|
28666
|
-
const helperFunction = context.helpersByName.get(node.callee.name);
|
|
28667
|
-
if (helperFunction && !context.activeHelpers.has(helperFunction) && isWholesaleDelegationCall(node, context.effectCallback)) {
|
|
28668
|
-
context.activeHelpers.add(helperFunction);
|
|
28669
|
-
let helperCount = countFunctionBodySetStateCalls(helperFunction, context);
|
|
28670
|
-
context.activeHelpers.delete(helperFunction);
|
|
28671
|
-
for (const argument of node.arguments ?? []) helperCount += countMaxPathSetStateCalls(argument, context);
|
|
28672
|
-
return helperCount;
|
|
28673
|
-
}
|
|
28674
|
-
}
|
|
28675
|
-
const countChild = (child) => {
|
|
28676
|
-
if (isFunctionLike$2(child)) return runsOnEffectDispatch(child) ? countFunctionBodySetStateCalls(child, context) : 0;
|
|
28677
|
-
return countMaxPathSetStateCalls(child, context);
|
|
28678
|
-
};
|
|
28679
|
-
let total = 0;
|
|
28680
|
-
const nodeRecord = node;
|
|
28681
|
-
for (const key of Object.keys(nodeRecord)) {
|
|
28682
|
-
if (key === "parent") continue;
|
|
28683
|
-
const child = nodeRecord[key];
|
|
28684
|
-
if (Array.isArray(child)) {
|
|
28685
|
-
for (const item of child) if (item && typeof item === "object" && "type" in item) total += countChild(item);
|
|
28686
|
-
} else if (child && typeof child === "object" && "type" in child) total += countChild(child);
|
|
28687
|
-
}
|
|
28688
|
-
return total;
|
|
28689
|
-
};
|
|
28690
|
-
const isInitOnlyEffect = (node) => {
|
|
28691
|
-
const depsArg = node.arguments?.[1];
|
|
28692
|
-
if (!depsArg) return false;
|
|
28693
|
-
if (!isNodeOfType(depsArg, "ArrayExpression")) return false;
|
|
28694
|
-
return (depsArg.elements ?? []).length === 0;
|
|
28695
|
-
};
|
|
28696
|
-
const DEV_ENV_FLAG_NAMES = new Set([
|
|
28697
|
-
"DEV",
|
|
28698
|
-
"PROD",
|
|
28699
|
-
"MODE",
|
|
28700
|
-
"NODE_ENV"
|
|
28701
|
-
]);
|
|
28702
|
-
const mentionsDevEnvFlag = (node) => {
|
|
28703
|
-
if (!node || typeof node !== "object") return false;
|
|
28704
|
-
if (isNodeOfType(node, "MemberExpression") && isNodeOfType(node.property, "Identifier") && DEV_ENV_FLAG_NAMES.has(node.property.name) && isNodeOfType(node.object, "MemberExpression") && isNodeOfType(node.object.property, "Identifier") && node.object.property.name === "env") return true;
|
|
28705
|
-
const record = node;
|
|
28706
|
-
for (const key of Object.keys(record)) {
|
|
28707
|
-
if (key === "parent") continue;
|
|
28708
|
-
const child = record[key];
|
|
28709
|
-
if (Array.isArray(child)) {
|
|
28710
|
-
for (const item of child) if (item && typeof item === "object" && "type" in item && mentionsDevEnvFlag(item)) return true;
|
|
28711
|
-
} else if (child && typeof child === "object" && "type" in child && mentionsDevEnvFlag(child)) return true;
|
|
28712
|
-
}
|
|
28713
|
-
return false;
|
|
28714
|
-
};
|
|
28715
|
-
const isDevOnlyGuardedEffect = (callback) => {
|
|
28716
|
-
const body = callback.body;
|
|
28717
|
-
if (!body || !isNodeOfType(body, "BlockStatement")) return false;
|
|
28718
|
-
const firstStatement = (body.body ?? [])[0];
|
|
28719
|
-
if (!firstStatement) return false;
|
|
28720
|
-
if (!isNodeOfType(firstStatement, "IfStatement") || firstStatement.alternate) return false;
|
|
28721
|
-
const consequent = firstStatement.consequent;
|
|
28722
|
-
if (!(isTerminatingStatement(consequent) || isNodeOfType(consequent, "BlockStatement") && (consequent.body ?? []).some((inner) => isTerminatingStatement(inner)))) return false;
|
|
28723
|
-
return mentionsDevEnvFlag(firstStatement.test);
|
|
28724
|
-
};
|
|
28725
|
-
const noCascadingSetState = defineRule({
|
|
28491
|
+
const noCascadingSetState = defineRetiredRule({
|
|
28726
28492
|
id: "no-cascading-set-state",
|
|
28727
28493
|
title: "Multiple setState calls in one effect",
|
|
28728
28494
|
severity: "warn",
|
|
28729
28495
|
tags: ["test-noise"],
|
|
28730
|
-
recommendation: "
|
|
28731
|
-
create: (context) => ({ CallExpression(node) {
|
|
28732
|
-
if (!isHookCall$2(node, EFFECT_HOOK_NAMES$1)) return;
|
|
28733
|
-
if (isInitOnlyEffect(node)) return;
|
|
28734
|
-
const callback = getEffectCallback(node, context.scopes);
|
|
28735
|
-
if (!callback) return;
|
|
28736
|
-
if (isDevOnlyGuardedEffect(callback)) return;
|
|
28737
|
-
const setStateCallCount = countFunctionBodySetStateCalls(callback, {
|
|
28738
|
-
helpersByName: collectLocalHelperFunctions(findProgramRoot(node) ?? callback),
|
|
28739
|
-
activeHelpers: /* @__PURE__ */ new Set(),
|
|
28740
|
-
effectCallback: callback
|
|
28741
|
-
});
|
|
28742
|
-
if (setStateCallCount >= 3) context.report({
|
|
28743
|
-
node,
|
|
28744
|
-
message: `${setStateCallCount} setState calls in one useEffect redraw your screen each time they run together.`
|
|
28745
|
-
});
|
|
28746
|
-
} })
|
|
28496
|
+
recommendation: "Retired: React batches synchronous state updates from one effect into the same follow-up commit, so setter count does not prove repeated redraws."
|
|
28747
28497
|
});
|
|
28748
28498
|
//#endregion
|
|
28749
28499
|
//#region src/plugin/rules/state-and-effects/no-chain-state-updates.ts
|
|
@@ -30617,6 +30367,9 @@ const noDirectMutationState = defineRule({
|
|
|
30617
30367
|
})
|
|
30618
30368
|
});
|
|
30619
30369
|
//#endregion
|
|
30370
|
+
//#region src/plugin/utils/is-setter-identifier.ts
|
|
30371
|
+
const isSetterIdentifier = (name) => SETTER_PATTERN.test(name);
|
|
30372
|
+
//#endregion
|
|
30620
30373
|
//#region src/plugin/rules/state-and-effects/utils/collect-use-state-bindings.ts
|
|
30621
30374
|
const collectUseStateBindings = (componentBody) => {
|
|
30622
30375
|
const bindings = [];
|
|
@@ -32887,6 +32640,9 @@ const noEventTriggerState = defineRule({
|
|
|
32887
32640
|
}
|
|
32888
32641
|
});
|
|
32889
32642
|
//#endregion
|
|
32643
|
+
//#region src/plugin/utils/is-setter-call.ts
|
|
32644
|
+
const isSetterCall = (node) => isNodeOfType(node, "CallExpression") && isNodeOfType(node.callee, "Identifier") && isSetterIdentifier(node.callee.name);
|
|
32645
|
+
//#endregion
|
|
32890
32646
|
//#region src/plugin/rules/state-and-effects/no-fetch-in-effect.ts
|
|
32891
32647
|
const IMPORT_INITIALIZER_TYPES = new Set([
|
|
32892
32648
|
"ImportSpecifier",
|
|
@@ -47248,6 +47004,37 @@ const containsLocaleEnvironmentRead = (expression) => {
|
|
|
47248
47004
|
return readsLocaleEnvironment;
|
|
47249
47005
|
};
|
|
47250
47006
|
//#endregion
|
|
47007
|
+
//#region src/plugin/utils/is-hook-binding-in-scope.ts
|
|
47008
|
+
const isHookBindingInScope = (node, query) => {
|
|
47009
|
+
const { bindingName, hookName, destructureIndex } = query;
|
|
47010
|
+
let cursor = node;
|
|
47011
|
+
while (cursor) {
|
|
47012
|
+
if (isNodeOfType(cursor, "BlockStatement") || isNodeOfType(cursor, "Program")) for (const statement of cursor.body ?? []) {
|
|
47013
|
+
if (!isNodeOfType(statement, "VariableDeclaration")) continue;
|
|
47014
|
+
for (const declarator of statement.declarations ?? []) {
|
|
47015
|
+
if (!isNodeOfType(declarator.init, "CallExpression")) continue;
|
|
47016
|
+
if (!isHookCall$2(declarator.init, hookName)) continue;
|
|
47017
|
+
if (destructureIndex !== void 0) {
|
|
47018
|
+
if (!isNodeOfType(declarator.id, "ArrayPattern")) continue;
|
|
47019
|
+
const elements = declarator.id.elements ?? [];
|
|
47020
|
+
if (elements.length <= destructureIndex) continue;
|
|
47021
|
+
const element = elements[destructureIndex];
|
|
47022
|
+
if (isNodeOfType(element, "Identifier") && element.name === bindingName) return true;
|
|
47023
|
+
} else if (isNodeOfType(declarator.id, "Identifier") && declarator.id.name === bindingName) return true;
|
|
47024
|
+
}
|
|
47025
|
+
}
|
|
47026
|
+
cursor = cursor.parent ?? null;
|
|
47027
|
+
}
|
|
47028
|
+
return false;
|
|
47029
|
+
};
|
|
47030
|
+
//#endregion
|
|
47031
|
+
//#region src/plugin/utils/is-use-state-setter-in-scope.ts
|
|
47032
|
+
const isUseStateSetterInScope = (node, setterName) => isHookBindingInScope(node, {
|
|
47033
|
+
bindingName: setterName,
|
|
47034
|
+
hookName: "useState",
|
|
47035
|
+
destructureIndex: 1
|
|
47036
|
+
});
|
|
47037
|
+
//#endregion
|
|
47251
47038
|
//#region src/plugin/rules/performance/rendering-hydration-no-flicker.ts
|
|
47252
47039
|
const USE_EFFECT_ONLY = new Set(["useEffect"]);
|
|
47253
47040
|
const argumentsReadRefCurrent = (callArguments) => callArguments.some((argument) => {
|
|
@@ -48937,14 +48724,6 @@ const rerenderTransitionsScroll = defineRule({
|
|
|
48937
48724
|
} })
|
|
48938
48725
|
});
|
|
48939
48726
|
//#endregion
|
|
48940
|
-
//#region src/plugin/utils/define-retired-rule.ts
|
|
48941
|
-
const defineRetiredRule = (rule) => defineRule({
|
|
48942
|
-
...rule,
|
|
48943
|
-
defaultEnabled: false,
|
|
48944
|
-
lifecycle: "retired",
|
|
48945
|
-
create: () => ({})
|
|
48946
|
-
});
|
|
48947
|
-
//#endregion
|
|
48948
48727
|
//#region src/plugin/rules/react-native/rn-animate-layout-property.ts
|
|
48949
48728
|
const rnAnimateLayoutProperty = defineRetiredRule({
|
|
48950
48729
|
id: "rn-animate-layout-property",
|