oxlint-plugin-react-doctor 0.7.7-dev.e632f8a → 0.7.7-dev.ed241c3
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 +7 -356
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -4573,23 +4573,6 @@ const hasPossibleStaticPropertyWrite = (identifier, propertyName, scopes) => {
|
|
|
4573
4573
|
return writtenPropertyName === null || writtenPropertyName === propertyName;
|
|
4574
4574
|
}));
|
|
4575
4575
|
};
|
|
4576
|
-
const canExecuteBefore = (candidateNode, referenceNode, scopes) => {
|
|
4577
|
-
const candidateBoundary = findExecutionBoundary(candidateNode);
|
|
4578
|
-
const referenceBoundary = findExecutionBoundary(referenceNode);
|
|
4579
|
-
if (!candidateBoundary || !referenceBoundary) return true;
|
|
4580
|
-
if (candidateBoundary === referenceBoundary) return candidateNode.range[0] < referenceNode.range[0];
|
|
4581
|
-
if (!isFunctionLike$1(candidateBoundary)) return true;
|
|
4582
|
-
return isFunctionSynchronouslyInvokedBefore(candidateBoundary, referenceNode, scopes);
|
|
4583
|
-
};
|
|
4584
|
-
const hasPossibleStaticPropertyWriteBefore = (identifier, propertyName, referenceNode, scopes) => {
|
|
4585
|
-
if (!isNodeOfType(identifier, "Identifier")) return false;
|
|
4586
|
-
return getPotentiallyAliasedSymbols(identifier, scopes).some((symbol) => symbol.references.some((reference) => {
|
|
4587
|
-
const writeTarget = getMemberWriteTarget(reference.identifier);
|
|
4588
|
-
if (!writeTarget || !canExecuteBefore(writeTarget, referenceNode, scopes)) return false;
|
|
4589
|
-
const writtenPropertyName = getResolvedStaticPropertyName(writeTarget, scopes);
|
|
4590
|
-
return writtenPropertyName === null || writtenPropertyName === propertyName;
|
|
4591
|
-
}));
|
|
4592
|
-
};
|
|
4593
4576
|
const hasPossibleStaticPropertyMutationOrEscape = (identifier, propertyName, scopes) => {
|
|
4594
4577
|
if (!isNodeOfType(identifier, "Identifier")) return false;
|
|
4595
4578
|
if (hasPossibleStaticPropertyWrite(identifier, propertyName, scopes)) return true;
|
|
@@ -20164,14 +20147,14 @@ const isIndexOfResultUsedAsMembershipTest = (node) => {
|
|
|
20164
20147
|
if (isNegativeOneLiteral(otherOperand)) return true;
|
|
20165
20148
|
return isZeroLiteral(otherOperand) && (parent.operator === ">=" || parent.operator === "<");
|
|
20166
20149
|
};
|
|
20167
|
-
const getTypeAnnotation
|
|
20150
|
+
const getTypeAnnotation = (node) => {
|
|
20168
20151
|
if (!node || !("typeAnnotation" in node)) return null;
|
|
20169
20152
|
const annotation = node.typeAnnotation;
|
|
20170
20153
|
if (!annotation || !isNodeOfType(annotation, "TSTypeAnnotation")) return null;
|
|
20171
20154
|
return annotation.typeAnnotation;
|
|
20172
20155
|
};
|
|
20173
20156
|
const getDeclaredPropertyType = (members, propertyName) => {
|
|
20174
|
-
for (const member of members) if (isNodeOfType(member, "TSPropertySignature") && isNodeOfType(member.key, "Identifier") && member.key.name === propertyName) return getTypeAnnotation
|
|
20157
|
+
for (const member of members) if (isNodeOfType(member, "TSPropertySignature") && isNodeOfType(member.key, "Identifier") && member.key.name === propertyName) return getTypeAnnotation(member);
|
|
20175
20158
|
return null;
|
|
20176
20159
|
};
|
|
20177
20160
|
const getArrayElementType = (typeNode) => {
|
|
@@ -20190,7 +20173,7 @@ const getDestructuredDeclaredType = (identifier) => {
|
|
|
20190
20173
|
const property = binding.bindingIdentifier.parent;
|
|
20191
20174
|
const objectPattern = property?.parent;
|
|
20192
20175
|
if (!isNodeOfType(property, "Property") || !isNodeOfType(property.key, "Identifier") || !isNodeOfType(objectPattern, "ObjectPattern")) return null;
|
|
20193
|
-
const propsType = getTypeAnnotation
|
|
20176
|
+
const propsType = getTypeAnnotation(objectPattern);
|
|
20194
20177
|
if (!propsType) return null;
|
|
20195
20178
|
if (isNodeOfType(propsType, "TSTypeLiteral")) return getDeclaredPropertyType(propsType.members ?? [], property.key.name);
|
|
20196
20179
|
if (!isNodeOfType(propsType, "TSTypeReference") || !isNodeOfType(propsType.typeName, "Identifier")) return null;
|
|
@@ -20207,7 +20190,7 @@ const getIdentifierDeclaredType = (identifier, visitedBindingIdentifiers = /* @_
|
|
|
20207
20190
|
const binding = findVariableInitializer(identifier, identifier.name);
|
|
20208
20191
|
if (!binding || visitedBindingIdentifiers.has(binding.bindingIdentifier)) return null;
|
|
20209
20192
|
visitedBindingIdentifiers.add(binding.bindingIdentifier);
|
|
20210
|
-
const directType = getTypeAnnotation
|
|
20193
|
+
const directType = getTypeAnnotation(binding.bindingIdentifier);
|
|
20211
20194
|
if (directType) return directType;
|
|
20212
20195
|
const initializer = binding.initializer;
|
|
20213
20196
|
if (isNodeOfType(initializer, "TSAsExpression") || isNodeOfType(initializer, "TSTypeAssertion") || isNodeOfType(initializer, "TSSatisfiesExpression")) return initializer.typeAnnotation;
|
|
@@ -27372,211 +27355,6 @@ const computeExternallyDriven = (analysis, declarator) => {
|
|
|
27372
27355
|
return hasDeferredCallSite;
|
|
27373
27356
|
};
|
|
27374
27357
|
//#endregion
|
|
27375
|
-
//#region src/plugin/rules/state-and-effects/utils/effect/is-proven-native-read-method.ts
|
|
27376
|
-
const ARRAY_READ_METHOD_NAMES$1 = new Set([
|
|
27377
|
-
"at",
|
|
27378
|
-
"concat",
|
|
27379
|
-
"entries",
|
|
27380
|
-
"every",
|
|
27381
|
-
"filter",
|
|
27382
|
-
"find",
|
|
27383
|
-
"findIndex",
|
|
27384
|
-
"findLast",
|
|
27385
|
-
"findLastIndex",
|
|
27386
|
-
"flat",
|
|
27387
|
-
"flatMap",
|
|
27388
|
-
"forEach",
|
|
27389
|
-
"includes",
|
|
27390
|
-
"indexOf",
|
|
27391
|
-
"join",
|
|
27392
|
-
"keys",
|
|
27393
|
-
"lastIndexOf",
|
|
27394
|
-
"map",
|
|
27395
|
-
"reduce",
|
|
27396
|
-
"reduceRight",
|
|
27397
|
-
"slice",
|
|
27398
|
-
"some",
|
|
27399
|
-
"toLocaleString",
|
|
27400
|
-
"toReversed",
|
|
27401
|
-
"toSorted",
|
|
27402
|
-
"toSpliced",
|
|
27403
|
-
"toString",
|
|
27404
|
-
"values",
|
|
27405
|
-
"with"
|
|
27406
|
-
]);
|
|
27407
|
-
const MAP_READ_METHOD_NAMES = new Set([
|
|
27408
|
-
"entries",
|
|
27409
|
-
"forEach",
|
|
27410
|
-
"get",
|
|
27411
|
-
"has",
|
|
27412
|
-
"keys",
|
|
27413
|
-
"values"
|
|
27414
|
-
]);
|
|
27415
|
-
const SET_READ_METHOD_NAMES = new Set([
|
|
27416
|
-
"difference",
|
|
27417
|
-
"entries",
|
|
27418
|
-
"forEach",
|
|
27419
|
-
"has",
|
|
27420
|
-
"intersection",
|
|
27421
|
-
"isDisjointFrom",
|
|
27422
|
-
"isSubsetOf",
|
|
27423
|
-
"isSupersetOf",
|
|
27424
|
-
"keys",
|
|
27425
|
-
"symmetricDifference",
|
|
27426
|
-
"union",
|
|
27427
|
-
"values"
|
|
27428
|
-
]);
|
|
27429
|
-
const FUNCTION_READ_METHOD_NAMES = new Set(["bind"]);
|
|
27430
|
-
const PROMISE_READ_METHOD_NAMES = new Set([
|
|
27431
|
-
"catch",
|
|
27432
|
-
"finally",
|
|
27433
|
-
"then"
|
|
27434
|
-
]);
|
|
27435
|
-
const STRING_READ_METHOD_NAMES$1 = new Set([
|
|
27436
|
-
"at",
|
|
27437
|
-
"charAt",
|
|
27438
|
-
"charCodeAt",
|
|
27439
|
-
"codePointAt",
|
|
27440
|
-
"concat",
|
|
27441
|
-
"endsWith",
|
|
27442
|
-
"includes",
|
|
27443
|
-
"indexOf",
|
|
27444
|
-
"isWellFormed",
|
|
27445
|
-
"lastIndexOf",
|
|
27446
|
-
"localeCompare",
|
|
27447
|
-
"match",
|
|
27448
|
-
"matchAll",
|
|
27449
|
-
"normalize",
|
|
27450
|
-
"padEnd",
|
|
27451
|
-
"padStart",
|
|
27452
|
-
"repeat",
|
|
27453
|
-
"replace",
|
|
27454
|
-
"replaceAll",
|
|
27455
|
-
"search",
|
|
27456
|
-
"slice",
|
|
27457
|
-
"split",
|
|
27458
|
-
"startsWith",
|
|
27459
|
-
"substring",
|
|
27460
|
-
"toLocaleLowerCase",
|
|
27461
|
-
"toLocaleUpperCase",
|
|
27462
|
-
"toLowerCase",
|
|
27463
|
-
"toString",
|
|
27464
|
-
"toUpperCase",
|
|
27465
|
-
"toWellFormed",
|
|
27466
|
-
"trim",
|
|
27467
|
-
"trimEnd",
|
|
27468
|
-
"trimStart",
|
|
27469
|
-
"valueOf"
|
|
27470
|
-
]);
|
|
27471
|
-
const NATIVE_TYPE_NAMES = new Set([
|
|
27472
|
-
"Array",
|
|
27473
|
-
"Map",
|
|
27474
|
-
"Promise",
|
|
27475
|
-
"PromiseLike",
|
|
27476
|
-
"ReadonlyArray",
|
|
27477
|
-
"ReadonlyMap",
|
|
27478
|
-
"ReadonlySet",
|
|
27479
|
-
"Set"
|
|
27480
|
-
]);
|
|
27481
|
-
const nativeTypeDeclarationsByProgram = /* @__PURE__ */ new WeakMap();
|
|
27482
|
-
const shadowedNativeTypeNamesByBinding = /* @__PURE__ */ new WeakMap();
|
|
27483
|
-
const isWithinNode = (node, ancestor) => {
|
|
27484
|
-
let current = node;
|
|
27485
|
-
while (current) {
|
|
27486
|
-
if (current === ancestor) return true;
|
|
27487
|
-
current = current.parent;
|
|
27488
|
-
}
|
|
27489
|
-
return false;
|
|
27490
|
-
};
|
|
27491
|
-
const findTypeDeclarationScope = (declaration) => {
|
|
27492
|
-
let current = declaration.parent;
|
|
27493
|
-
while (current) {
|
|
27494
|
-
if (isNodeOfType(current, "Program") || isNodeOfType(current, "BlockStatement") || isNodeOfType(current, "TSModuleBlock") || isNodeOfType(current, "StaticBlock")) return current;
|
|
27495
|
-
current = current.parent;
|
|
27496
|
-
}
|
|
27497
|
-
return null;
|
|
27498
|
-
};
|
|
27499
|
-
const getDeclaredTypeName = (declaration) => {
|
|
27500
|
-
if (!isNodeOfType(declaration, "ClassDeclaration") && !isNodeOfType(declaration, "TSEnumDeclaration") && !isNodeOfType(declaration, "TSImportEqualsDeclaration") && !isNodeOfType(declaration, "TSInterfaceDeclaration") && !isNodeOfType(declaration, "TSModuleDeclaration") && !isNodeOfType(declaration, "TSTypeAliasDeclaration")) return null;
|
|
27501
|
-
return declaration.id && isNodeOfType(declaration.id, "Identifier") ? declaration.id.name : null;
|
|
27502
|
-
};
|
|
27503
|
-
const getNativeTypeDeclarations = (program) => {
|
|
27504
|
-
const cachedDeclarations = nativeTypeDeclarationsByProgram.get(program);
|
|
27505
|
-
if (cachedDeclarations) return cachedDeclarations;
|
|
27506
|
-
const declarations = [];
|
|
27507
|
-
walkAst(program, (candidate) => {
|
|
27508
|
-
if (isNodeOfType(candidate, "ImportDeclaration")) {
|
|
27509
|
-
for (const specifier of candidate.specifiers) if (NATIVE_TYPE_NAMES.has(specifier.local.name)) declarations.push({
|
|
27510
|
-
name: specifier.local.name,
|
|
27511
|
-
scope: program
|
|
27512
|
-
});
|
|
27513
|
-
return;
|
|
27514
|
-
}
|
|
27515
|
-
const declaredTypeName = getDeclaredTypeName(candidate);
|
|
27516
|
-
if (!declaredTypeName || !NATIVE_TYPE_NAMES.has(declaredTypeName)) return;
|
|
27517
|
-
const declarationScope = findTypeDeclarationScope(candidate);
|
|
27518
|
-
if (declarationScope) declarations.push({
|
|
27519
|
-
name: declaredTypeName,
|
|
27520
|
-
scope: declarationScope
|
|
27521
|
-
});
|
|
27522
|
-
});
|
|
27523
|
-
nativeTypeDeclarationsByProgram.set(program, declarations);
|
|
27524
|
-
return declarations;
|
|
27525
|
-
};
|
|
27526
|
-
const getShadowedNativeTypeNames = (binding) => {
|
|
27527
|
-
const cachedNames = shadowedNativeTypeNamesByBinding.get(binding);
|
|
27528
|
-
if (cachedNames) return cachedNames;
|
|
27529
|
-
const shadowedNames = /* @__PURE__ */ new Set();
|
|
27530
|
-
for (const typeName of NATIVE_TYPE_NAMES) if (hasEnclosingTypeParameterNamed(binding, typeName)) shadowedNames.add(typeName);
|
|
27531
|
-
const program = findProgramRoot(binding);
|
|
27532
|
-
if (program) {
|
|
27533
|
-
for (const declaration of getNativeTypeDeclarations(program)) if (isWithinNode(binding, declaration.scope)) shadowedNames.add(declaration.name);
|
|
27534
|
-
}
|
|
27535
|
-
shadowedNativeTypeNamesByBinding.set(binding, shadowedNames);
|
|
27536
|
-
return shadowedNames;
|
|
27537
|
-
};
|
|
27538
|
-
const getParameterBinding = (definitionName) => {
|
|
27539
|
-
if (isNodeOfType(definitionName, "Identifier")) return definitionName;
|
|
27540
|
-
if (!isNodeOfType(definitionName, "AssignmentPattern")) return null;
|
|
27541
|
-
return isNodeOfType(definitionName.left, "Identifier") ? definitionName.left : null;
|
|
27542
|
-
};
|
|
27543
|
-
const getTypeAnnotation = (binding) => {
|
|
27544
|
-
if (!isNodeOfType(binding, "Identifier")) return null;
|
|
27545
|
-
const annotation = binding.typeAnnotation;
|
|
27546
|
-
return annotation && isNodeOfType(annotation, "TSTypeAnnotation") ? annotation.typeAnnotation : null;
|
|
27547
|
-
};
|
|
27548
|
-
const isNullishType = (typeNode) => isNodeOfType(typeNode, "TSNullKeyword") || isNodeOfType(typeNode, "TSUndefinedKeyword");
|
|
27549
|
-
const isNativeReadMethod = (typeNode, methodName, shadowedTypeNames) => {
|
|
27550
|
-
if (isNodeOfType(typeNode, "TSArrayType") || isNodeOfType(typeNode, "TSTupleType")) return ARRAY_READ_METHOD_NAMES$1.has(methodName);
|
|
27551
|
-
if (isNodeOfType(typeNode, "TSStringKeyword")) return STRING_READ_METHOD_NAMES$1.has(methodName);
|
|
27552
|
-
if (isNodeOfType(typeNode, "TSFunctionType")) return FUNCTION_READ_METHOD_NAMES.has(methodName);
|
|
27553
|
-
if (isNodeOfType(typeNode, "TSLiteralType") && isNodeOfType(typeNode.literal, "Literal") && typeof typeNode.literal.value === "string") return STRING_READ_METHOD_NAMES$1.has(methodName);
|
|
27554
|
-
if (isNodeOfType(typeNode, "TSTypeOperator") && typeNode.operator === "readonly" && typeNode.typeAnnotation) return isNativeReadMethod(typeNode.typeAnnotation, methodName, shadowedTypeNames);
|
|
27555
|
-
if (isNodeOfType(typeNode, "TSUnionType")) {
|
|
27556
|
-
let hasNonNullishMember = false;
|
|
27557
|
-
for (const memberType of typeNode.types) {
|
|
27558
|
-
if (isNullishType(memberType)) continue;
|
|
27559
|
-
hasNonNullishMember = true;
|
|
27560
|
-
if (!isNativeReadMethod(memberType, methodName, shadowedTypeNames)) return false;
|
|
27561
|
-
}
|
|
27562
|
-
return hasNonNullishMember;
|
|
27563
|
-
}
|
|
27564
|
-
if (!isNodeOfType(typeNode, "TSTypeReference") || !isNodeOfType(typeNode.typeName, "Identifier")) return false;
|
|
27565
|
-
if (shadowedTypeNames.has(typeNode.typeName.name)) return false;
|
|
27566
|
-
if (typeNode.typeName.name === "Array" || typeNode.typeName.name === "ReadonlyArray") return ARRAY_READ_METHOD_NAMES$1.has(methodName);
|
|
27567
|
-
if (typeNode.typeName.name === "Map" || typeNode.typeName.name === "ReadonlyMap") return MAP_READ_METHOD_NAMES.has(methodName);
|
|
27568
|
-
if (typeNode.typeName.name === "Set" || typeNode.typeName.name === "ReadonlySet") return SET_READ_METHOD_NAMES.has(methodName);
|
|
27569
|
-
if (typeNode.typeName.name === "Promise" || typeNode.typeName.name === "PromiseLike") return PROMISE_READ_METHOD_NAMES.has(methodName);
|
|
27570
|
-
return false;
|
|
27571
|
-
};
|
|
27572
|
-
const isProvenNativeReadMethod = (ref, methodName) => Boolean(ref.resolved?.defs.some((definition) => {
|
|
27573
|
-
if (definition.type !== "Parameter") return false;
|
|
27574
|
-
const parameterBinding = getParameterBinding(definition.name);
|
|
27575
|
-
if (!parameterBinding) return false;
|
|
27576
|
-
const typeAnnotation = getTypeAnnotation(parameterBinding);
|
|
27577
|
-
return Boolean(typeAnnotation && isNativeReadMethod(typeAnnotation, methodName, getShadowedNativeTypeNames(parameterBinding)));
|
|
27578
|
-
}));
|
|
27579
|
-
//#endregion
|
|
27580
27358
|
//#region src/plugin/rules/state-and-effects/utils/effect/react.ts
|
|
27581
27359
|
const KNOWN_PURE_HOC_NAMES = new Set(["memo", "forwardRef"]);
|
|
27582
27360
|
const startsWithUppercase = (name) => Boolean(name && name.length > 0 && name[0] >= "A" && name[0] <= "Z");
|
|
@@ -27803,132 +27581,7 @@ const isRefCurrent = (ref) => {
|
|
|
27803
27581
|
const isStateSetterCall = (analysis, ref) => isEventualCallTo(analysis, ref, (innerRef) => isStateSetter(analysis, innerRef));
|
|
27804
27582
|
const isSyncStateSetterCall = (analysis, ref, effectFn) => isStateSetterCall(analysis, ref) && isSynchronous(ref.identifier, effectFn) && !resolvesToAsyncFunction(ref);
|
|
27805
27583
|
const HANDLER_NAMED_METHOD_PATTERN = /^(on|handle)[A-Z]/;
|
|
27806
|
-
const
|
|
27807
|
-
["every", 0],
|
|
27808
|
-
["filter", 0],
|
|
27809
|
-
["find", 0],
|
|
27810
|
-
["findIndex", 0],
|
|
27811
|
-
["findLast", 0],
|
|
27812
|
-
["findLastIndex", 0],
|
|
27813
|
-
["flatMap", 0],
|
|
27814
|
-
["forEach", 0],
|
|
27815
|
-
["map", 0],
|
|
27816
|
-
["reduce", 0],
|
|
27817
|
-
["reduceRight", 0],
|
|
27818
|
-
["replace", 1],
|
|
27819
|
-
["replaceAll", 1],
|
|
27820
|
-
["some", 0]
|
|
27821
|
-
]);
|
|
27822
|
-
const addSimpleBindingNames = (pattern, names) => {
|
|
27823
|
-
if (isNodeOfType(pattern, "Identifier")) {
|
|
27824
|
-
if (names.has(pattern.name)) return false;
|
|
27825
|
-
names.add(pattern.name);
|
|
27826
|
-
return true;
|
|
27827
|
-
}
|
|
27828
|
-
if (isNodeOfType(pattern, "AssignmentPattern")) return addSimpleBindingNames(pattern.left, names);
|
|
27829
|
-
if (isNodeOfType(pattern, "RestElement")) return addSimpleBindingNames(pattern.argument, names);
|
|
27830
|
-
if (isNodeOfType(pattern, "ObjectPattern")) {
|
|
27831
|
-
let didAddName = false;
|
|
27832
|
-
for (const property of pattern.properties) didAddName = addSimpleBindingNames(isNodeOfType(property, "Property") ? property.value : property, names) || didAddName;
|
|
27833
|
-
return didAddName;
|
|
27834
|
-
}
|
|
27835
|
-
if (isNodeOfType(pattern, "ArrayPattern")) {
|
|
27836
|
-
let didAddName = false;
|
|
27837
|
-
for (const element of pattern.elements) if (element) didAddName = addSimpleBindingNames(element, names) || didAddName;
|
|
27838
|
-
return didAddName;
|
|
27839
|
-
}
|
|
27840
|
-
return false;
|
|
27841
|
-
};
|
|
27842
|
-
const getSimpleParameterNames = (callback) => {
|
|
27843
|
-
if (!isFunctionLike$1(callback)) return /* @__PURE__ */ new Set();
|
|
27844
|
-
const names = /* @__PURE__ */ new Set();
|
|
27845
|
-
for (const parameter of callback.params ?? []) addSimpleBindingNames(parameter, names);
|
|
27846
|
-
return names;
|
|
27847
|
-
};
|
|
27848
|
-
const inlineCallbackInvokesParameter = (callback) => {
|
|
27849
|
-
const parameterNames = getSimpleParameterNames(callback);
|
|
27850
|
-
if (parameterNames.size === 0 || !isFunctionLike$1(callback)) return false;
|
|
27851
|
-
let didAddAlias = true;
|
|
27852
|
-
while (didAddAlias) {
|
|
27853
|
-
didAddAlias = false;
|
|
27854
|
-
walkAst(callback.body, (candidate) => {
|
|
27855
|
-
if (candidate !== callback.body && isFunctionLike$1(candidate)) return false;
|
|
27856
|
-
if (isNodeOfType(candidate, "AssignmentExpression") && candidate.operator === "=" && isNodeOfType(candidate.left, "Identifier")) {
|
|
27857
|
-
const assignedValueRoot = getRootIdentifier$1(candidate.right);
|
|
27858
|
-
if (isNodeOfType(assignedValueRoot, "Identifier") && parameterNames.has(assignedValueRoot.name) && !parameterNames.has(candidate.left.name)) {
|
|
27859
|
-
parameterNames.add(candidate.left.name);
|
|
27860
|
-
didAddAlias = true;
|
|
27861
|
-
}
|
|
27862
|
-
return;
|
|
27863
|
-
}
|
|
27864
|
-
if (!isNodeOfType(candidate, "VariableDeclarator") || !candidate.init) return;
|
|
27865
|
-
const initializerRoot = getRootIdentifier$1(candidate.init);
|
|
27866
|
-
if (!isNodeOfType(initializerRoot, "Identifier") || !parameterNames.has(initializerRoot.name)) return;
|
|
27867
|
-
if (addSimpleBindingNames(candidate.id, parameterNames)) didAddAlias = true;
|
|
27868
|
-
});
|
|
27869
|
-
}
|
|
27870
|
-
let didInvokeParameter = false;
|
|
27871
|
-
walkAst(callback.body, (candidate) => {
|
|
27872
|
-
if (didInvokeParameter) return false;
|
|
27873
|
-
if (candidate !== callback.body && isFunctionLike$1(candidate)) return false;
|
|
27874
|
-
if (!isNodeOfType(candidate, "CallExpression")) return;
|
|
27875
|
-
const callee = stripParenExpression(candidate.callee);
|
|
27876
|
-
if (isNodeOfType(callee, "Identifier") && parameterNames.has(callee.name)) {
|
|
27877
|
-
didInvokeParameter = true;
|
|
27878
|
-
return false;
|
|
27879
|
-
}
|
|
27880
|
-
if (isNodeOfType(callee, "MemberExpression")) {
|
|
27881
|
-
const receiverRoot = getRootIdentifier$1(callee.object);
|
|
27882
|
-
if (receiverRoot && parameterNames.has(receiverRoot.name)) {
|
|
27883
|
-
didInvokeParameter = true;
|
|
27884
|
-
return false;
|
|
27885
|
-
}
|
|
27886
|
-
}
|
|
27887
|
-
});
|
|
27888
|
-
return didInvokeParameter;
|
|
27889
|
-
};
|
|
27890
|
-
const callbackInvokesPropCallback = (analysis, callback) => {
|
|
27891
|
-
if (!isFunctionLike$1(callback)) return false;
|
|
27892
|
-
let didInvokePropCallback = false;
|
|
27893
|
-
walkAst(callback.body, (candidate) => {
|
|
27894
|
-
if (didInvokePropCallback) return false;
|
|
27895
|
-
if (candidate !== callback.body && isFunctionLike$1(candidate)) return false;
|
|
27896
|
-
if (!isNodeOfType(candidate, "CallExpression")) return;
|
|
27897
|
-
if (getDownstreamRefs(analysis, stripParenExpression(candidate.callee)).some((reference) => isPropCallbackInvocationRef(analysis, reference))) {
|
|
27898
|
-
didInvokePropCallback = true;
|
|
27899
|
-
return false;
|
|
27900
|
-
}
|
|
27901
|
-
});
|
|
27902
|
-
return didInvokePropCallback;
|
|
27903
|
-
};
|
|
27904
|
-
const isNativeMethodSuppressionSafe = (analysis, callExpression, methodName, scopes) => {
|
|
27905
|
-
if (!isNodeOfType(callExpression, "CallExpression")) return false;
|
|
27906
|
-
const callee = stripParenExpression(callExpression.callee);
|
|
27907
|
-
if (!isNodeOfType(callee, "MemberExpression")) return false;
|
|
27908
|
-
const receiver = stripParenExpression(callee.object);
|
|
27909
|
-
if (!isNodeOfType(receiver, "Identifier")) return false;
|
|
27910
|
-
const receiverSymbol = scopes.symbolFor(receiver);
|
|
27911
|
-
if (!receiverSymbol || hasSymbolWriteBefore(receiverSymbol, callExpression, scopes) || hasPossibleStaticPropertyWriteBefore(receiver, methodName, callExpression, scopes)) return false;
|
|
27912
|
-
let callResult = callExpression;
|
|
27913
|
-
let callResultConsumer = callResult.parent;
|
|
27914
|
-
while (callResultConsumer && (TRANSPARENT_EXPRESSION_WRAPPER_TYPES.has(callResultConsumer.type) && "expression" in callResultConsumer && callResultConsumer.expression === callResult || isNodeOfType(callResultConsumer, "MemberExpression") && callResultConsumer.object === callResult)) {
|
|
27915
|
-
callResult = callResultConsumer;
|
|
27916
|
-
callResultConsumer = callResult.parent;
|
|
27917
|
-
}
|
|
27918
|
-
if (isNodeOfType(callResultConsumer, "CallExpression") && callResultConsumer.callee === callResult) return false;
|
|
27919
|
-
const callbackArgumentIndex = SYNCHRONOUS_CALLBACK_ARGUMENT_INDEX_BY_METHOD.get(methodName);
|
|
27920
|
-
if (callbackArgumentIndex === void 0) return true;
|
|
27921
|
-
const callbackArgument = callExpression.arguments?.[callbackArgumentIndex];
|
|
27922
|
-
if (!callbackArgument) return true;
|
|
27923
|
-
const callbackValue = stripParenExpression(callbackArgument);
|
|
27924
|
-
if (isFunctionLike$1(callbackValue)) return !inlineCallbackInvokesParameter(callbackValue) && !callbackInvokesPropCallback(analysis, callbackValue);
|
|
27925
|
-
if (!isNodeOfType(callbackValue, "Identifier")) return false;
|
|
27926
|
-
const callbackRef = getRef(analysis, callbackValue);
|
|
27927
|
-
if (!callbackRef || isPropAlias(analysis, callbackRef)) return false;
|
|
27928
|
-
const callbackFunction = resolveToFunction(callbackRef);
|
|
27929
|
-
return Boolean(callbackFunction && isFunctionLike$1(callbackFunction) && !inlineCallbackInvokesParameter(callbackFunction) && !callbackInvokesPropCallback(analysis, callbackFunction));
|
|
27930
|
-
};
|
|
27931
|
-
const isPropCallbackInvocationRef = (analysis, ref, options = {}) => {
|
|
27584
|
+
const isPropCallbackInvocationRef = (analysis, ref) => {
|
|
27932
27585
|
if (!isPropAlias(analysis, ref)) return false;
|
|
27933
27586
|
let effectiveNode = ref.identifier;
|
|
27934
27587
|
let parent = effectiveNode.parent;
|
|
@@ -27941,9 +27594,7 @@ const isPropCallbackInvocationRef = (analysis, ref, options = {}) => {
|
|
|
27941
27594
|
if (isNodeOfType(parent, "MemberExpression") && parent.object === effectiveNode) {
|
|
27942
27595
|
const memberParent = parent.parent;
|
|
27943
27596
|
if (isNodeOfType(memberParent, "CallExpression") && memberParent.callee === parent) {
|
|
27944
|
-
|
|
27945
|
-
if (propertyName && HANDLER_NAMED_METHOD_PATTERN.test(propertyName)) return true;
|
|
27946
|
-
if (options.nativeMethodScopes && isCustomHookParameter(ref) && propertyName && isProvenNativeReadMethod(ref, propertyName) && isNativeMethodSuppressionSafe(analysis, memberParent, propertyName, options.nativeMethodScopes)) return false;
|
|
27597
|
+
if (!parent.computed && isNodeOfType(parent.property, "Identifier") && HANDLER_NAMED_METHOD_PATTERN.test(parent.property.name)) return true;
|
|
27947
27598
|
return isWholePropsObjectReference(analysis, ref);
|
|
27948
27599
|
}
|
|
27949
27600
|
}
|
|
@@ -41414,7 +41065,7 @@ const noPropCallbackInRender = defineRule({
|
|
|
41414
41065
|
if (!analysis) return;
|
|
41415
41066
|
const callee = stripParenExpression(node.callee);
|
|
41416
41067
|
if (isFunctionLike$1(callee)) return;
|
|
41417
|
-
if (!getDownstreamRefs(analysis, callee).some((reference) => isPropCallbackInvocationRef(analysis, reference
|
|
41068
|
+
if (!getDownstreamRefs(analysis, callee).some((reference) => isPropCallbackInvocationRef(analysis, reference))) return;
|
|
41418
41069
|
context.report({
|
|
41419
41070
|
node,
|
|
41420
41071
|
message: "This prop callback runs during render. React can replay or discard render work, so the callback can fire more than once or for UI that never commits."
|