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.
Files changed (2) hide show
  1. package/dist/index.js +7 -356
  2. 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$1 = (node) => {
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$1(member);
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$1(objectPattern);
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$1(binding.bindingIdentifier);
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 SYNCHRONOUS_CALLBACK_ARGUMENT_INDEX_BY_METHOD = new Map([
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
- const propertyName = getStaticPropertyName(parent);
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, { nativeMethodScopes: context.scopes }))) return;
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."
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "oxlint-plugin-react-doctor",
3
- "version": "0.7.7-dev.e632f8a",
3
+ "version": "0.7.7-dev.ed241c3",
4
4
  "description": "React Doctor rules for oxlint.",
5
5
  "keywords": [
6
6
  "accessibility",