oxlint-plugin-react-doctor 0.7.8-dev.4829841 → 0.7.8-dev.ece35b3
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 +2 -407
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -22317,7 +22317,7 @@ const isReactSlotType = (typeNode, environment, activeDeclarations) => {
|
|
|
22317
22317
|
}
|
|
22318
22318
|
return environment.reactSlotTypeBindings.has(typeName);
|
|
22319
22319
|
};
|
|
22320
|
-
const getPropertyName
|
|
22320
|
+
const getPropertyName = (property) => {
|
|
22321
22321
|
if (!isNodeOfType(property, "TSPropertySignature") || property.computed) return null;
|
|
22322
22322
|
if (isNodeOfType(property.key, "Identifier")) return property.key.name;
|
|
22323
22323
|
if (isNodeOfType(property.key, "Literal") && typeof property.key.value === "string") return property.key.value;
|
|
@@ -22329,7 +22329,7 @@ const collectSlotPropertyNames = (propsType, environment, slotPropertyNames, act
|
|
|
22329
22329
|
if (isNodeOfType(propsType, "TSInterfaceDeclaration")) members = propsType.body.body;
|
|
22330
22330
|
if (members) {
|
|
22331
22331
|
for (const member of members) {
|
|
22332
|
-
const propertyName = getPropertyName
|
|
22332
|
+
const propertyName = getPropertyName(member);
|
|
22333
22333
|
if (!propertyName || !isNodeOfType(member, "TSPropertySignature")) continue;
|
|
22334
22334
|
const annotation = member.typeAnnotation;
|
|
22335
22335
|
if (annotation && isNodeOfType(annotation, "TSTypeAnnotation") && isReactSlotType(annotation.typeAnnotation, environment, /* @__PURE__ */ new Set())) slotPropertyNames.add(propertyName);
|
|
@@ -42992,31 +42992,6 @@ const noRenderReturnValue = defineRule({
|
|
|
42992
42992
|
});
|
|
42993
42993
|
//#endregion
|
|
42994
42994
|
//#region src/plugin/rules/state-and-effects/no-reset-all-state-on-prop-change.ts
|
|
42995
|
-
const SYNCHRONOUS_ARRAY_CALLBACK_METHOD_NAMES = new Set([
|
|
42996
|
-
"every",
|
|
42997
|
-
"filter",
|
|
42998
|
-
"find",
|
|
42999
|
-
"findIndex",
|
|
43000
|
-
"flatMap",
|
|
43001
|
-
"forEach",
|
|
43002
|
-
"map",
|
|
43003
|
-
"reduce",
|
|
43004
|
-
"reduceRight",
|
|
43005
|
-
"some"
|
|
43006
|
-
]);
|
|
43007
|
-
const createConstantFormula = (constantValue) => ({
|
|
43008
|
-
kind: "constant",
|
|
43009
|
-
constantValue
|
|
43010
|
-
});
|
|
43011
|
-
const createNotFormula = (formula) => ({
|
|
43012
|
-
kind: "not",
|
|
43013
|
-
left: formula
|
|
43014
|
-
});
|
|
43015
|
-
const createBinaryFormula = (kind, left, right) => ({
|
|
43016
|
-
kind,
|
|
43017
|
-
left,
|
|
43018
|
-
right
|
|
43019
|
-
});
|
|
43020
42995
|
const isUndefinedNode = (node) => {
|
|
43021
42996
|
if (node === null || node === void 0) return true;
|
|
43022
42997
|
return isNodeOfType(node, "Identifier") && node.name === "undefined";
|
|
@@ -43078,232 +43053,6 @@ const getLivePropExpressionIdentity = (analysis, context, node, visitedSymbolIds
|
|
|
43078
43053
|
}
|
|
43079
43054
|
return null;
|
|
43080
43055
|
};
|
|
43081
|
-
const getLivePropAtomKey = (identity) => `prop:${identity.propSymbolId}:${JSON.stringify(identity.memberPath)}:${identity.booleanNormalization}`;
|
|
43082
|
-
const getBooleanFormula$1 = (analysis, context, node, protectedSymbolIds, visitedSymbolIds = /* @__PURE__ */ new Set()) => {
|
|
43083
|
-
const expression = stripParenExpression(node);
|
|
43084
|
-
if (isNodeOfType(expression, "Literal")) return createConstantFormula(Boolean(expression.value));
|
|
43085
|
-
if (isNodeOfType(expression, "Identifier")) {
|
|
43086
|
-
if (expression.name === "undefined" && context.scopes.isGlobalReference(expression)) return createConstantFormula(false);
|
|
43087
|
-
const symbol = context.scopes.symbolFor(expression);
|
|
43088
|
-
if (!symbol) return null;
|
|
43089
|
-
if (!protectedSymbolIds.has(symbol.id) && symbol.kind === "const" && !visitedSymbolIds.has(symbol.id) && isNodeOfType(symbol.declarationNode, "VariableDeclarator") && symbol.declarationNode.id === symbol.bindingIdentifier) {
|
|
43090
|
-
const initializer = getDirectConstInitializer(symbol);
|
|
43091
|
-
if (initializer) {
|
|
43092
|
-
visitedSymbolIds.add(symbol.id);
|
|
43093
|
-
const initializerFormula = getBooleanFormula$1(analysis, context, initializer, protectedSymbolIds, visitedSymbolIds);
|
|
43094
|
-
if (initializerFormula) return initializerFormula;
|
|
43095
|
-
}
|
|
43096
|
-
}
|
|
43097
|
-
return {
|
|
43098
|
-
kind: "atom",
|
|
43099
|
-
atomKey: `symbol:${symbol.id}`
|
|
43100
|
-
};
|
|
43101
|
-
}
|
|
43102
|
-
if (isNodeOfType(expression, "MemberExpression")) {
|
|
43103
|
-
const identity = getLivePropExpressionIdentity(analysis, context, expression);
|
|
43104
|
-
return identity ? {
|
|
43105
|
-
kind: "atom",
|
|
43106
|
-
atomKey: getLivePropAtomKey(identity)
|
|
43107
|
-
} : null;
|
|
43108
|
-
}
|
|
43109
|
-
if (isNodeOfType(expression, "UnaryExpression") && expression.operator === "!") {
|
|
43110
|
-
const argumentFormula = getBooleanFormula$1(analysis, context, expression.argument, protectedSymbolIds, visitedSymbolIds);
|
|
43111
|
-
return argumentFormula ? createNotFormula(argumentFormula) : null;
|
|
43112
|
-
}
|
|
43113
|
-
if (isNodeOfType(expression, "CallExpression") && isNodeOfType(expression.callee, "Identifier") && expression.callee.name === "Boolean" && context.scopes.isGlobalReference(expression.callee) && expression.arguments.length === 1 && !isNodeOfType(expression.arguments[0], "SpreadElement")) return getBooleanFormula$1(analysis, context, expression.arguments[0], protectedSymbolIds, visitedSymbolIds);
|
|
43114
|
-
if (isNodeOfType(expression, "LogicalExpression") && (expression.operator === "&&" || expression.operator === "||")) {
|
|
43115
|
-
const leftFormula = getBooleanFormula$1(analysis, context, expression.left, protectedSymbolIds, new Set(visitedSymbolIds));
|
|
43116
|
-
const rightFormula = getBooleanFormula$1(analysis, context, expression.right, protectedSymbolIds, new Set(visitedSymbolIds));
|
|
43117
|
-
if (!leftFormula || !rightFormula) return null;
|
|
43118
|
-
return createBinaryFormula(expression.operator === "&&" ? "and" : "or", leftFormula, rightFormula);
|
|
43119
|
-
}
|
|
43120
|
-
if (isNodeOfType(expression, "ConditionalExpression")) {
|
|
43121
|
-
const testFormula = getBooleanFormula$1(analysis, context, expression.test, protectedSymbolIds, new Set(visitedSymbolIds));
|
|
43122
|
-
const consequentFormula = getBooleanFormula$1(analysis, context, expression.consequent, protectedSymbolIds, new Set(visitedSymbolIds));
|
|
43123
|
-
const alternateFormula = getBooleanFormula$1(analysis, context, expression.alternate, protectedSymbolIds, new Set(visitedSymbolIds));
|
|
43124
|
-
if (!testFormula || !consequentFormula || !alternateFormula) return null;
|
|
43125
|
-
return createBinaryFormula("or", createBinaryFormula("and", testFormula, consequentFormula), createBinaryFormula("and", createNotFormula(testFormula), alternateFormula));
|
|
43126
|
-
}
|
|
43127
|
-
if (isNodeOfType(expression, "BinaryExpression") && (expression.operator === "===" || expression.operator === "==" || expression.operator === "!==" || expression.operator === "!=")) {
|
|
43128
|
-
const leftIsBoolean = isNodeOfType(expression.left, "Literal") && typeof expression.left.value === "boolean";
|
|
43129
|
-
if (leftIsBoolean === (isNodeOfType(expression.right, "Literal") && typeof expression.right.value === "boolean")) return null;
|
|
43130
|
-
const booleanLiteral = leftIsBoolean ? expression.left : expression.right;
|
|
43131
|
-
const comparedFormula = getBooleanFormula$1(analysis, context, leftIsBoolean ? expression.right : expression.left, protectedSymbolIds, visitedSymbolIds);
|
|
43132
|
-
if (!comparedFormula || !isNodeOfType(booleanLiteral, "Literal")) return null;
|
|
43133
|
-
return (expression.operator === "===" || expression.operator === "==" ? booleanLiteral.value : !booleanLiteral.value) ? comparedFormula : createNotFormula(comparedFormula);
|
|
43134
|
-
}
|
|
43135
|
-
return null;
|
|
43136
|
-
};
|
|
43137
|
-
const evaluateBooleanFormula$1 = (formula, assignments) => {
|
|
43138
|
-
if (formula.kind === "constant") return formula.constantValue ?? null;
|
|
43139
|
-
if (formula.kind === "atom") return formula.atomKey === void 0 ? null : assignments.get(formula.atomKey) ?? null;
|
|
43140
|
-
if (formula.kind === "not") {
|
|
43141
|
-
if (!formula.left) return null;
|
|
43142
|
-
const value = evaluateBooleanFormula$1(formula.left, assignments);
|
|
43143
|
-
return value === null ? null : !value;
|
|
43144
|
-
}
|
|
43145
|
-
if (!formula.left || !formula.right) return null;
|
|
43146
|
-
const leftValue = evaluateBooleanFormula$1(formula.left, assignments);
|
|
43147
|
-
const rightValue = evaluateBooleanFormula$1(formula.right, assignments);
|
|
43148
|
-
if (formula.kind === "and") {
|
|
43149
|
-
if (leftValue === false || rightValue === false) return false;
|
|
43150
|
-
return leftValue === true && rightValue === true ? true : null;
|
|
43151
|
-
}
|
|
43152
|
-
if (leftValue === true || rightValue === true) return true;
|
|
43153
|
-
return leftValue === false && rightValue === false ? false : null;
|
|
43154
|
-
};
|
|
43155
|
-
const assignBooleanFact = (facts, atomKey, value) => {
|
|
43156
|
-
const existingValue = facts.assignments.get(atomKey);
|
|
43157
|
-
if (existingValue === void 0) {
|
|
43158
|
-
facts.assignments.set(atomKey, value);
|
|
43159
|
-
facts.didChange = true;
|
|
43160
|
-
} else if (existingValue !== value) facts.didConflict = true;
|
|
43161
|
-
};
|
|
43162
|
-
const addRequiredBooleanFacts = (formula, expectedValue, facts) => {
|
|
43163
|
-
const existingValue = evaluateBooleanFormula$1(formula, facts.assignments);
|
|
43164
|
-
if (existingValue !== null) {
|
|
43165
|
-
if (existingValue !== expectedValue) facts.didConflict = true;
|
|
43166
|
-
return;
|
|
43167
|
-
}
|
|
43168
|
-
if (formula.kind === "atom" && formula.atomKey !== void 0) {
|
|
43169
|
-
assignBooleanFact(facts, formula.atomKey, expectedValue);
|
|
43170
|
-
return;
|
|
43171
|
-
}
|
|
43172
|
-
if (formula.kind === "not" && formula.left) {
|
|
43173
|
-
addRequiredBooleanFacts(formula.left, !expectedValue, facts);
|
|
43174
|
-
return;
|
|
43175
|
-
}
|
|
43176
|
-
if (!formula.left || !formula.right) return;
|
|
43177
|
-
if (formula.kind === "and") {
|
|
43178
|
-
if (expectedValue) {
|
|
43179
|
-
addRequiredBooleanFacts(formula.left, true, facts);
|
|
43180
|
-
addRequiredBooleanFacts(formula.right, true, facts);
|
|
43181
|
-
return;
|
|
43182
|
-
}
|
|
43183
|
-
const leftValue = evaluateBooleanFormula$1(formula.left, facts.assignments);
|
|
43184
|
-
const rightValue = evaluateBooleanFormula$1(formula.right, facts.assignments);
|
|
43185
|
-
if (leftValue === true) addRequiredBooleanFacts(formula.right, false, facts);
|
|
43186
|
-
if (rightValue === true) addRequiredBooleanFacts(formula.left, false, facts);
|
|
43187
|
-
return;
|
|
43188
|
-
}
|
|
43189
|
-
if (!expectedValue) {
|
|
43190
|
-
addRequiredBooleanFacts(formula.left, false, facts);
|
|
43191
|
-
addRequiredBooleanFacts(formula.right, false, facts);
|
|
43192
|
-
return;
|
|
43193
|
-
}
|
|
43194
|
-
const leftValue = evaluateBooleanFormula$1(formula.left, facts.assignments);
|
|
43195
|
-
const rightValue = evaluateBooleanFormula$1(formula.right, facts.assignments);
|
|
43196
|
-
if (leftValue === false) addRequiredBooleanFacts(formula.right, true, facts);
|
|
43197
|
-
if (rightValue === false) addRequiredBooleanFacts(formula.left, true, facts);
|
|
43198
|
-
};
|
|
43199
|
-
const doConditionsImplyFormula = (conditions, target) => {
|
|
43200
|
-
const facts = {
|
|
43201
|
-
assignments: /* @__PURE__ */ new Map(),
|
|
43202
|
-
didConflict: false,
|
|
43203
|
-
didChange: true
|
|
43204
|
-
};
|
|
43205
|
-
while (facts.didChange && !facts.didConflict) {
|
|
43206
|
-
facts.didChange = false;
|
|
43207
|
-
for (const condition of conditions) addRequiredBooleanFacts(condition, true, facts);
|
|
43208
|
-
}
|
|
43209
|
-
return facts.didConflict || evaluateBooleanFormula$1(target, facts.assignments) === true;
|
|
43210
|
-
};
|
|
43211
|
-
const getFunctionBindingSymbol = (functionNode, scopes) => {
|
|
43212
|
-
if (isNodeOfType(functionNode, "FunctionDeclaration") && functionNode.id) return scopes.symbolFor(functionNode.id);
|
|
43213
|
-
const parent = functionNode.parent;
|
|
43214
|
-
if ((isNodeOfType(functionNode, "ArrowFunctionExpression") || isNodeOfType(functionNode, "FunctionExpression")) && isNodeOfType(parent, "VariableDeclarator") && parent.init === functionNode && isNodeOfType(parent.id, "Identifier")) return scopes.symbolFor(parent.id);
|
|
43215
|
-
return null;
|
|
43216
|
-
};
|
|
43217
|
-
const getComponentFunctionNode = (containingNode) => {
|
|
43218
|
-
if (isFunctionLike$1(containingNode)) return containingNode;
|
|
43219
|
-
if (!isNodeOfType(containingNode, "VariableDeclarator") || !containingNode.init) return null;
|
|
43220
|
-
const initializer = stripParenExpression(containingNode.init);
|
|
43221
|
-
if (isFunctionLike$1(initializer)) return initializer;
|
|
43222
|
-
if (!isNodeOfType(initializer, "CallExpression")) return null;
|
|
43223
|
-
const firstArgument = initializer.arguments[0];
|
|
43224
|
-
return firstArgument && !isNodeOfType(firstArgument, "SpreadElement") && isFunctionLike$1(firstArgument) ? firstArgument : null;
|
|
43225
|
-
};
|
|
43226
|
-
const isReferenceDirectlyCalled = (identifier) => {
|
|
43227
|
-
const unwrappedIdentifier = stripParenExpression(identifier);
|
|
43228
|
-
const parent = unwrappedIdentifier.parent;
|
|
43229
|
-
return isNodeOfType(parent, "CallExpression") && parent.callee === unwrappedIdentifier ? parent : null;
|
|
43230
|
-
};
|
|
43231
|
-
const getSynchronousCallbackCall = (functionNode) => {
|
|
43232
|
-
const callExpression = functionNode.parent;
|
|
43233
|
-
if (!isNodeOfType(callExpression, "CallExpression") || !callExpression.arguments.some((argument) => argument === functionNode) || !isNodeOfType(callExpression.callee, "MemberExpression")) return null;
|
|
43234
|
-
const methodName = getStaticMemberPropertyName(callExpression.callee);
|
|
43235
|
-
return methodName && SYNCHRONOUS_ARRAY_CALLBACK_METHOD_NAMES.has(methodName) ? callExpression : null;
|
|
43236
|
-
};
|
|
43237
|
-
const isNodeEvaluatedDuringRender = (node, componentNode, scopes, visitedFunctionSymbolIds = /* @__PURE__ */ new Set()) => {
|
|
43238
|
-
const functionNode = findEnclosingFunction$1(node);
|
|
43239
|
-
if (!functionNode) return false;
|
|
43240
|
-
if (functionNode === componentNode) return true;
|
|
43241
|
-
const synchronousCallbackCall = getSynchronousCallbackCall(functionNode);
|
|
43242
|
-
if (synchronousCallbackCall) return isNodeEvaluatedDuringRender(synchronousCallbackCall, componentNode, scopes, visitedFunctionSymbolIds);
|
|
43243
|
-
if (executesDuringRender(functionNode, scopes)) return isNodeEvaluatedDuringRender(functionNode.parent ?? functionNode, componentNode, scopes, visitedFunctionSymbolIds);
|
|
43244
|
-
const functionSymbol = getFunctionBindingSymbol(functionNode, scopes);
|
|
43245
|
-
if (!functionSymbol || visitedFunctionSymbolIds.has(functionSymbol.id)) return false;
|
|
43246
|
-
visitedFunctionSymbolIds.add(functionSymbol.id);
|
|
43247
|
-
let callCount = 0;
|
|
43248
|
-
for (const reference of functionSymbol.references) {
|
|
43249
|
-
const callExpression = isReferenceDirectlyCalled(reference.identifier);
|
|
43250
|
-
if (!callExpression) return false;
|
|
43251
|
-
if (!isNodeEvaluatedDuringRender(callExpression, componentNode, scopes, new Set(visitedFunctionSymbolIds))) return false;
|
|
43252
|
-
callCount += 1;
|
|
43253
|
-
}
|
|
43254
|
-
return callCount > 0;
|
|
43255
|
-
};
|
|
43256
|
-
const isInlineJsxCallback = (functionNode) => {
|
|
43257
|
-
let ancestor = functionNode.parent;
|
|
43258
|
-
while (ancestor) {
|
|
43259
|
-
if (isNodeOfType(ancestor, "JSXAttribute")) return true;
|
|
43260
|
-
if (isFunctionLike$1(ancestor) || isNodeOfType(ancestor, "Program")) return false;
|
|
43261
|
-
ancestor = ancestor.parent;
|
|
43262
|
-
}
|
|
43263
|
-
return false;
|
|
43264
|
-
};
|
|
43265
|
-
const collectExposureConditions = (analysis, context, node, componentNode, protectedSymbolIds) => {
|
|
43266
|
-
const conditions = [];
|
|
43267
|
-
let child = node;
|
|
43268
|
-
let parent = node.parent;
|
|
43269
|
-
while (parent) {
|
|
43270
|
-
if (isNodeOfType(parent, "LogicalExpression") && parent.right === child) {
|
|
43271
|
-
const leftFormula = getBooleanFormula$1(analysis, context, parent.left, protectedSymbolIds);
|
|
43272
|
-
if (leftFormula && parent.operator === "&&") conditions.push(leftFormula);
|
|
43273
|
-
if (leftFormula && parent.operator === "||") conditions.push(createNotFormula(leftFormula));
|
|
43274
|
-
} else if (isNodeOfType(parent, "ConditionalExpression")) {
|
|
43275
|
-
const testFormula = getBooleanFormula$1(analysis, context, parent.test, protectedSymbolIds);
|
|
43276
|
-
if (testFormula && parent.consequent === child) conditions.push(testFormula);
|
|
43277
|
-
if (testFormula && parent.alternate === child) conditions.push(createNotFormula(testFormula));
|
|
43278
|
-
} else if (isNodeOfType(parent, "IfStatement")) {
|
|
43279
|
-
const testFormula = getBooleanFormula$1(analysis, context, parent.test, protectedSymbolIds);
|
|
43280
|
-
if (testFormula && parent.consequent === child) conditions.push(testFormula);
|
|
43281
|
-
if (testFormula && parent.alternate === child) conditions.push(createNotFormula(testFormula));
|
|
43282
|
-
}
|
|
43283
|
-
if (parent === componentNode) break;
|
|
43284
|
-
if (isFunctionLike$1(parent) && parent !== componentNode && !isInlineJsxCallback(parent)) {
|
|
43285
|
-
const synchronousCallbackCall = getSynchronousCallbackCall(parent);
|
|
43286
|
-
if (synchronousCallbackCall) {
|
|
43287
|
-
child = synchronousCallbackCall;
|
|
43288
|
-
parent = synchronousCallbackCall.parent;
|
|
43289
|
-
continue;
|
|
43290
|
-
}
|
|
43291
|
-
const functionSymbol = getFunctionBindingSymbol(parent, context.scopes);
|
|
43292
|
-
if (functionSymbol?.references.length === 1) {
|
|
43293
|
-
const callExpression = isReferenceDirectlyCalled(functionSymbol.references[0].identifier);
|
|
43294
|
-
if (callExpression) {
|
|
43295
|
-
child = callExpression;
|
|
43296
|
-
parent = callExpression.parent;
|
|
43297
|
-
continue;
|
|
43298
|
-
}
|
|
43299
|
-
}
|
|
43300
|
-
break;
|
|
43301
|
-
}
|
|
43302
|
-
child = parent;
|
|
43303
|
-
parent = parent.parent;
|
|
43304
|
-
}
|
|
43305
|
-
return conditions;
|
|
43306
|
-
};
|
|
43307
43056
|
const isMountSnapshotInitializer = (context, node) => {
|
|
43308
43057
|
if (!isReactApiCall(node, "useMemo", context.scopes, { resolveNamedAliases: true }) || !isNodeOfType(node, "CallExpression")) return false;
|
|
43309
43058
|
const dependencies = node.arguments?.[1];
|
|
@@ -43379,158 +43128,6 @@ const countUseStates = (analysis, componentNode) => {
|
|
|
43379
43128
|
for (const ref of getDownstreamRefs(analysis, componentNode)) if (isState(analysis, ref)) stateVariables.add(ref.resolved);
|
|
43380
43129
|
return stateVariables.size;
|
|
43381
43130
|
};
|
|
43382
|
-
const getStateSymbolForSetter = (analysis, context, setterReference) => {
|
|
43383
|
-
const useStateDeclaration = getUseStateDecl(analysis, setterReference);
|
|
43384
|
-
if (!useStateDeclaration || !isNodeOfType(useStateDeclaration, "VariableDeclarator") || !isNodeOfType(useStateDeclaration.id, "ArrayPattern")) return null;
|
|
43385
|
-
const stateBinding = useStateDeclaration.id.elements[0];
|
|
43386
|
-
return stateBinding && isNodeOfType(stateBinding, "Identifier") ? context.scopes.symbolFor(stateBinding) : null;
|
|
43387
|
-
};
|
|
43388
|
-
const getPropertyName = (node) => {
|
|
43389
|
-
if (isNodeOfType(node, "Identifier")) return node.name;
|
|
43390
|
-
return isNodeOfType(node, "Literal") && typeof node.value === "string" ? node.value : null;
|
|
43391
|
-
};
|
|
43392
|
-
const isBooleanTypeNode = (node) => {
|
|
43393
|
-
if (!node) return false;
|
|
43394
|
-
if (isNodeOfType(node, "TSBooleanKeyword")) return true;
|
|
43395
|
-
if (!isNodeOfType(node, "TSUnionType")) return false;
|
|
43396
|
-
return node.types.every((typeNode) => isNodeOfType(typeNode, "TSBooleanKeyword") || isNodeOfType(typeNode, "TSUndefinedKeyword") || isNodeOfType(typeNode, "TSNullKeyword"));
|
|
43397
|
-
};
|
|
43398
|
-
const getBooleanPropertyType = (typeNode, propertyName, referenceNode) => {
|
|
43399
|
-
const unwrappedType = isNodeOfType(typeNode, "TSTypeAnnotation") ? typeNode.typeAnnotation : typeNode;
|
|
43400
|
-
if (isNodeOfType(unwrappedType, "TSTypeLiteral")) return unwrappedType.members.some((member) => isNodeOfType(member, "TSPropertySignature") && getPropertyName(member.key) === propertyName && isBooleanTypeNode(member.typeAnnotation?.typeAnnotation));
|
|
43401
|
-
if (!isNodeOfType(unwrappedType, "TSTypeReference") || !isNodeOfType(unwrappedType.typeName, "Identifier")) return false;
|
|
43402
|
-
const typeName = unwrappedType.typeName.name;
|
|
43403
|
-
if (hasEnclosingTypeParameterNamed(referenceNode, typeName)) return false;
|
|
43404
|
-
const programNode = findProgramNode(referenceNode);
|
|
43405
|
-
if (!isNodeOfType(programNode, "Program")) return false;
|
|
43406
|
-
const matchingInterfaces = programNode.body.flatMap((statement) => {
|
|
43407
|
-
const declaration = isNodeOfType(statement, "ExportNamedDeclaration") ? statement.declaration : statement;
|
|
43408
|
-
return isNodeOfType(declaration, "TSInterfaceDeclaration") && declaration.id.name === typeName ? [declaration] : [];
|
|
43409
|
-
});
|
|
43410
|
-
if (matchingInterfaces.length !== 1) return false;
|
|
43411
|
-
let sameNameTypeBindingCount = 0;
|
|
43412
|
-
walkAst(programNode, (candidate) => {
|
|
43413
|
-
const identifier = isNodeOfType(candidate, "TSInterfaceDeclaration") || isNodeOfType(candidate, "TSTypeAliasDeclaration") || isNodeOfType(candidate, "ClassDeclaration") || isNodeOfType(candidate, "ClassExpression") || isNodeOfType(candidate, "TSEnumDeclaration") ? candidate.id : isNodeOfType(candidate, "TSTypeParameter") ? candidate.name : null;
|
|
43414
|
-
if (isNodeOfType(identifier, "Identifier") && identifier.name === typeName) sameNameTypeBindingCount += 1;
|
|
43415
|
-
});
|
|
43416
|
-
if (sameNameTypeBindingCount !== 1) return false;
|
|
43417
|
-
return matchingInterfaces[0].body.body.some((member) => isNodeOfType(member, "TSPropertySignature") && getPropertyName(member.key) === propertyName && isBooleanTypeNode(member.typeAnnotation?.typeAnnotation));
|
|
43418
|
-
};
|
|
43419
|
-
const findProgramNode = (node) => {
|
|
43420
|
-
let currentNode = node;
|
|
43421
|
-
while (currentNode.parent) currentNode = currentNode.parent;
|
|
43422
|
-
return currentNode;
|
|
43423
|
-
};
|
|
43424
|
-
const hasBooleanBindingAnnotation = (symbol, identifier) => {
|
|
43425
|
-
const property = symbol.bindingIdentifier.parent;
|
|
43426
|
-
const objectPattern = property?.parent;
|
|
43427
|
-
if (!isNodeOfType(property, "Property") || !isNodeOfType(objectPattern, "ObjectPattern") || !objectPattern.typeAnnotation) return false;
|
|
43428
|
-
const propertyName = getPropertyName(property.key);
|
|
43429
|
-
return Boolean(propertyName && getBooleanPropertyType(objectPattern.typeAnnotation, propertyName, identifier));
|
|
43430
|
-
};
|
|
43431
|
-
const isBooleanExpression$1 = (context, node, visitedSymbolIds = /* @__PURE__ */ new Set()) => {
|
|
43432
|
-
const expression = stripParenExpression(node);
|
|
43433
|
-
if (isNodeOfType(expression, "Literal")) return typeof expression.value === "boolean";
|
|
43434
|
-
if (isNodeOfType(expression, "UnaryExpression") && expression.operator === "!") return true;
|
|
43435
|
-
if (isNodeOfType(expression, "BinaryExpression")) return [
|
|
43436
|
-
"==",
|
|
43437
|
-
"===",
|
|
43438
|
-
"!=",
|
|
43439
|
-
"!==",
|
|
43440
|
-
"<",
|
|
43441
|
-
"<=",
|
|
43442
|
-
">",
|
|
43443
|
-
">="
|
|
43444
|
-
].includes(expression.operator);
|
|
43445
|
-
if (isNodeOfType(expression, "CallExpression") && isNodeOfType(expression.callee, "Identifier") && expression.callee.name === "Boolean" && context.scopes.isGlobalReference(expression.callee)) return true;
|
|
43446
|
-
if (isNodeOfType(expression, "LogicalExpression")) return isBooleanExpression$1(context, expression.left, new Set(visitedSymbolIds)) && isBooleanExpression$1(context, expression.right, new Set(visitedSymbolIds));
|
|
43447
|
-
if (isNodeOfType(expression, "ConditionalExpression")) return isBooleanExpression$1(context, expression.consequent, new Set(visitedSymbolIds)) && isBooleanExpression$1(context, expression.alternate, new Set(visitedSymbolIds));
|
|
43448
|
-
if (!isNodeOfType(expression, "Identifier")) return false;
|
|
43449
|
-
const symbol = context.scopes.symbolFor(expression);
|
|
43450
|
-
if (!symbol || visitedSymbolIds.has(symbol.id)) return false;
|
|
43451
|
-
if (hasBooleanBindingAnnotation(symbol, expression)) return true;
|
|
43452
|
-
visitedSymbolIds.add(symbol.id);
|
|
43453
|
-
const initializer = getDirectConstInitializer(symbol);
|
|
43454
|
-
return Boolean(initializer && isBooleanExpression$1(context, initializer, visitedSymbolIds));
|
|
43455
|
-
};
|
|
43456
|
-
const getPropDerivedDependencySymbols = (analysis, context, dependencyReferences) => {
|
|
43457
|
-
const symbolsById = /* @__PURE__ */ new Map();
|
|
43458
|
-
for (const dependencyReference of dependencyReferences) {
|
|
43459
|
-
if (!getUpstreamRefs(analysis, dependencyReference).some((upstreamReference) => isProp(analysis, upstreamReference))) continue;
|
|
43460
|
-
const symbol = context.scopes.symbolFor(dependencyReference.identifier);
|
|
43461
|
-
if (symbol) symbolsById.set(symbol.id, symbol);
|
|
43462
|
-
}
|
|
43463
|
-
return [...symbolsById.values()];
|
|
43464
|
-
};
|
|
43465
|
-
const getImpliedDependencyValue = (conditions, dependencyFormulas) => {
|
|
43466
|
-
const impliesTrue = dependencyFormulas.some((dependencyFormula) => doConditionsImplyFormula(conditions, dependencyFormula));
|
|
43467
|
-
if (impliesTrue === dependencyFormulas.some((dependencyFormula) => doConditionsImplyFormula(conditions, createNotFormula(dependencyFormula)))) return null;
|
|
43468
|
-
return impliesTrue;
|
|
43469
|
-
};
|
|
43470
|
-
const getSetterExposureConditions = (analysis, context, setterReference, componentNode, protectedSymbolIds) => {
|
|
43471
|
-
const functionNode = findEnclosingFunction$1(setterReference.identifier);
|
|
43472
|
-
if (!functionNode) return null;
|
|
43473
|
-
if (isInlineJsxCallback(functionNode)) return [collectExposureConditions(analysis, context, functionNode, componentNode, protectedSymbolIds)];
|
|
43474
|
-
const functionSymbol = getFunctionBindingSymbol(functionNode, context.scopes);
|
|
43475
|
-
if (!functionSymbol || functionSymbol.references.length === 0) return null;
|
|
43476
|
-
const conditionsByReference = [];
|
|
43477
|
-
for (const reference of functionSymbol.references) {
|
|
43478
|
-
if (isReferenceDirectlyCalled(reference.identifier)) return null;
|
|
43479
|
-
let ancestor = reference.identifier.parent;
|
|
43480
|
-
while (ancestor && !isNodeOfType(ancestor, "JSXAttribute") && !isFunctionLike$1(ancestor)) ancestor = ancestor.parent;
|
|
43481
|
-
if (!isNodeOfType(ancestor, "JSXAttribute")) return null;
|
|
43482
|
-
conditionsByReference.push(collectExposureConditions(analysis, context, reference.identifier, componentNode, protectedSymbolIds));
|
|
43483
|
-
}
|
|
43484
|
-
return conditionsByReference;
|
|
43485
|
-
};
|
|
43486
|
-
const areAllSetterWritesVisibilityGuarded = (analysis, context, componentNode, resetSetterReferences, dependencySymbolIds, dependencyFormulas, visibleDependencyValue) => {
|
|
43487
|
-
const resetIdentifiers = new Set(resetSetterReferences.map((setterReference) => setterReference.identifier));
|
|
43488
|
-
const setterVariables = new Set(resetSetterReferences.map((reference) => reference.resolved));
|
|
43489
|
-
for (const setterVariable of setterVariables) {
|
|
43490
|
-
if (!setterVariable) return false;
|
|
43491
|
-
for (const setterReference of setterVariable.references) {
|
|
43492
|
-
if (setterVariable.identifiers.some((identifier) => identifier === setterReference.identifier)) continue;
|
|
43493
|
-
if (resetIdentifiers.has(setterReference.identifier)) continue;
|
|
43494
|
-
if (!getCallExpr(setterReference)) return false;
|
|
43495
|
-
const conditionsByExposure = getSetterExposureConditions(analysis, context, setterReference, componentNode, dependencySymbolIds);
|
|
43496
|
-
if (!conditionsByExposure || conditionsByExposure.some((conditions) => getImpliedDependencyValue(conditions, dependencyFormulas) !== visibleDependencyValue)) return false;
|
|
43497
|
-
}
|
|
43498
|
-
}
|
|
43499
|
-
return true;
|
|
43500
|
-
};
|
|
43501
|
-
const areAllResetStateReadsHiddenUntilReset = (analysis, context, componentNode, setterReferences, dependencyReferences) => {
|
|
43502
|
-
if (dependencyReferences.length !== 1) return false;
|
|
43503
|
-
const dependencySymbols = getPropDerivedDependencySymbols(analysis, context, dependencyReferences);
|
|
43504
|
-
if (dependencySymbols.length === 0 || dependencySymbols.some((symbol) => !isBooleanExpression$1(context, symbol.bindingIdentifier))) return false;
|
|
43505
|
-
const dependencySymbolIds = new Set(dependencySymbols.map((symbol) => symbol.id));
|
|
43506
|
-
const dependencyFormulas = dependencySymbols.map((symbol) => ({
|
|
43507
|
-
kind: "atom",
|
|
43508
|
-
atomKey: `symbol:${symbol.id}`
|
|
43509
|
-
}));
|
|
43510
|
-
const resetStateSymbolsById = /* @__PURE__ */ new Map();
|
|
43511
|
-
for (const setterReference of setterReferences) {
|
|
43512
|
-
const stateSymbol = getStateSymbolForSetter(analysis, context, setterReference);
|
|
43513
|
-
if (!stateSymbol) return false;
|
|
43514
|
-
resetStateSymbolsById.set(stateSymbol.id, stateSymbol);
|
|
43515
|
-
}
|
|
43516
|
-
let visibleDependencyValue = null;
|
|
43517
|
-
for (const stateSymbol of resetStateSymbolsById.values()) {
|
|
43518
|
-
let exposedReadCount = 0;
|
|
43519
|
-
for (const reference of stateSymbol.references) {
|
|
43520
|
-
if (reference.flag === "write") continue;
|
|
43521
|
-
const isRenderRead = isNodeEvaluatedDuringRender(reference.identifier, componentNode, context.scopes);
|
|
43522
|
-
const functionNode = findEnclosingFunction$1(reference.identifier);
|
|
43523
|
-
if (!isRenderRead && functionNode && !isInlineJsxCallback(functionNode)) return false;
|
|
43524
|
-
const referenceDependencyValue = getImpliedDependencyValue(collectExposureConditions(analysis, context, reference.identifier, componentNode, dependencySymbolIds), dependencyFormulas);
|
|
43525
|
-
if (referenceDependencyValue === null) return false;
|
|
43526
|
-
if (visibleDependencyValue !== null && visibleDependencyValue !== referenceDependencyValue) return false;
|
|
43527
|
-
visibleDependencyValue = referenceDependencyValue;
|
|
43528
|
-
exposedReadCount += 1;
|
|
43529
|
-
}
|
|
43530
|
-
if (exposedReadCount === 0) return false;
|
|
43531
|
-
}
|
|
43532
|
-
return Boolean(resetStateSymbolsById.size > 0 && visibleDependencyValue !== null && areAllSetterWritesVisibilityGuarded(analysis, context, componentNode, setterReferences, dependencySymbolIds, dependencyFormulas, visibleDependencyValue));
|
|
43533
|
-
};
|
|
43534
43131
|
const findPropUsedToResetAllState = (analysis, context, effectFnRefs, depsRefs, useEffectNode, effectFn) => {
|
|
43535
43132
|
const stateSetterRefs = effectFnRefs.filter((ref) => isSyncStateSetterCall(analysis, ref, effectFn));
|
|
43536
43133
|
if (stateSetterRefs.length === 0) return null;
|
|
@@ -43538,8 +43135,6 @@ const findPropUsedToResetAllState = (analysis, context, effectFnRefs, depsRefs,
|
|
|
43538
43135
|
if (stateSetterRefs.every((setterRef) => effectFnRefs.some((otherRef) => otherRef !== setterRef && otherRef.resolved === setterRef.resolved && Boolean(getCallExpr(otherRef)) && !isSyncStateSetterCall(analysis, otherRef, effectFn)))) return null;
|
|
43539
43136
|
const containing = findContainingNode(analysis, useEffectNode);
|
|
43540
43137
|
if (new Set(stateSetterRefs.map((setterRef) => setterRef.resolved)).size !== countUseStates(analysis, containing)) return null;
|
|
43541
|
-
const componentFunctionNode = containing ? getComponentFunctionNode(containing) : null;
|
|
43542
|
-
if (componentFunctionNode && areAllResetStateReadsHiddenUntilReset(analysis, context, componentFunctionNode, stateSetterRefs, depsRefs)) return null;
|
|
43543
43138
|
for (const depRef of depsRefs) for (const upRef of getUpstreamRefs(analysis, depRef)) if (isProp(analysis, upRef)) return upRef;
|
|
43544
43139
|
return null;
|
|
43545
43140
|
};
|