oxlint-plugin-react-doctor 0.7.7-dev.afed801 → 0.7.7-dev.bdd1321

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 +3 -329
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -18333,26 +18333,6 @@ const MEMBERSHIP_COMPARISON_OPERATORS = new Set([
18333
18333
  ]);
18334
18334
  const isNegativeOneLiteral = (expression) => Boolean(expression) && isNodeOfType(expression, "UnaryExpression") && expression.operator === "-" && isNodeOfType(expression.argument, "Literal") && expression.argument.value === 1;
18335
18335
  const isZeroLiteral = (expression) => Boolean(expression) && isNodeOfType(expression, "Literal") && expression.value === 0;
18336
- const isToIntegerOrInfinityZero = (value) => Number.isNaN(value) || Math.trunc(value) === 0;
18337
- const isZeroFromIndex = (expression) => {
18338
- if (!expression) return false;
18339
- const strippedExpression = stripParenExpression(expression);
18340
- if (isNodeOfType(strippedExpression, "Literal")) {
18341
- if (typeof strippedExpression.value === "number") return isToIntegerOrInfinityZero(strippedExpression.value);
18342
- if (typeof strippedExpression.value === "string") return isToIntegerOrInfinityZero(Number(strippedExpression.value));
18343
- return strippedExpression.value === null || strippedExpression.value === false;
18344
- }
18345
- if (isNodeOfType(strippedExpression, "UnaryExpression") && strippedExpression.operator === "void") return true;
18346
- if (isNodeOfType(strippedExpression, "UnaryExpression") && (strippedExpression.operator === "-" || strippedExpression.operator === "+") && isNodeOfType(strippedExpression.argument, "Literal") && typeof strippedExpression.argument.value === "number") return isToIntegerOrInfinityZero(strippedExpression.operator === "-" ? -strippedExpression.argument.value : strippedExpression.argument.value);
18347
- if (isNodeOfType(strippedExpression, "Identifier")) return (strippedExpression.name === "undefined" || strippedExpression.name === "NaN") && findVariableInitializer(strippedExpression, strippedExpression.name) === null;
18348
- return isNodeOfType(strippedExpression, "MemberExpression") && !strippedExpression.computed && isNodeOfType(strippedExpression.object, "Identifier") && strippedExpression.object.name === "Number" && isNodeOfType(strippedExpression.property, "Identifier") && strippedExpression.property.name === "NaN" && findVariableInitializer(strippedExpression.object, strippedExpression.object.name) === null;
18349
- };
18350
- const hasSemanticsPreservingIncludesArguments = (node) => {
18351
- if (node.arguments.length === 1) return !isNodeOfType(node.arguments[0], "SpreadElement");
18352
- if (node.arguments.length !== 2) return false;
18353
- if (isNodeOfType(node.arguments[0], "SpreadElement") || isNodeOfType(node.arguments[1], "SpreadElement")) return false;
18354
- return isZeroFromIndex(node.arguments[1]);
18355
- };
18356
18336
  const PARENT_WRAPPER_TYPES = new Set([
18357
18337
  "ParenthesizedExpression",
18358
18338
  "ChainExpression",
@@ -18373,306 +18353,6 @@ const isIndexOfResultUsedAsMembershipTest = (node) => {
18373
18353
  if (isNegativeOneLiteral(otherOperand)) return true;
18374
18354
  return isZeroLiteral(otherOperand) && (parent.operator === ">=" || parent.operator === "<");
18375
18355
  };
18376
- const getTypeAnnotation = (node) => {
18377
- if (!node || !("typeAnnotation" in node)) return null;
18378
- const annotation = node.typeAnnotation;
18379
- if (!annotation || !isNodeOfType(annotation, "TSTypeAnnotation")) return null;
18380
- return annotation.typeAnnotation;
18381
- };
18382
- const getDeclaredPropertyType = (members, propertyName) => {
18383
- for (const member of members) if (isNodeOfType(member, "TSPropertySignature") && isNodeOfType(member.key, "Identifier") && member.key.name === propertyName) return getTypeAnnotation(member);
18384
- return null;
18385
- };
18386
- const getArrayElementType = (typeNode) => {
18387
- if (!typeNode) return null;
18388
- if (isNodeOfType(typeNode, "TSArrayType")) return typeNode.elementType;
18389
- if (isNodeOfType(typeNode, "TSTypeReference") && isNodeOfType(typeNode.typeName, "Identifier") && (typeNode.typeName.name === "Array" || typeNode.typeName.name === "ReadonlyArray")) return typeNode.typeArguments?.params?.[0] ?? null;
18390
- if (isNodeOfType(typeNode, "TSUnionType")) {
18391
- const arrayElementTypes = typeNode.types.map(getArrayElementType).filter(Boolean);
18392
- return arrayElementTypes.length === 1 ? arrayElementTypes[0] : null;
18393
- }
18394
- return null;
18395
- };
18396
- const getDestructuredDeclaredType = (identifier) => {
18397
- const binding = findVariableInitializer(identifier, identifier.name);
18398
- if (!binding) return null;
18399
- const property = binding.bindingIdentifier.parent;
18400
- const objectPattern = property?.parent;
18401
- if (!isNodeOfType(property, "Property") || !isNodeOfType(property.key, "Identifier") || !isNodeOfType(objectPattern, "ObjectPattern")) return null;
18402
- const propsType = getTypeAnnotation(objectPattern);
18403
- if (!propsType) return null;
18404
- if (isNodeOfType(propsType, "TSTypeLiteral")) return getDeclaredPropertyType(propsType.members ?? [], property.key.name);
18405
- if (!isNodeOfType(propsType, "TSTypeReference") || !isNodeOfType(propsType.typeName, "Identifier")) return null;
18406
- const program = findProgramRoot(identifier);
18407
- if (!program) return null;
18408
- for (const statement of program.body) {
18409
- const declaration = isNodeOfType(statement, "ExportNamedDeclaration") ? statement.declaration : statement;
18410
- if (isNodeOfType(declaration, "TSInterfaceDeclaration") && isNodeOfType(declaration.id, "Identifier") && declaration.id.name === propsType.typeName.name) return getDeclaredPropertyType(declaration.body.body, property.key.name);
18411
- if (isNodeOfType(declaration, "TSTypeAliasDeclaration") && isNodeOfType(declaration.id, "Identifier") && declaration.id.name === propsType.typeName.name && isNodeOfType(declaration.typeAnnotation, "TSTypeLiteral")) return getDeclaredPropertyType(declaration.typeAnnotation.members ?? [], property.key.name);
18412
- }
18413
- return null;
18414
- };
18415
- const getIdentifierDeclaredType = (identifier, visitedBindingIdentifiers = /* @__PURE__ */ new Set()) => {
18416
- const binding = findVariableInitializer(identifier, identifier.name);
18417
- if (!binding || visitedBindingIdentifiers.has(binding.bindingIdentifier)) return null;
18418
- visitedBindingIdentifiers.add(binding.bindingIdentifier);
18419
- const directType = getTypeAnnotation(binding.bindingIdentifier);
18420
- if (directType) return directType;
18421
- const initializer = binding.initializer;
18422
- if (isNodeOfType(initializer, "TSAsExpression") || isNodeOfType(initializer, "TSTypeAssertion") || isNodeOfType(initializer, "TSSatisfiesExpression")) return initializer.typeAnnotation;
18423
- const destructuredType = getDestructuredDeclaredType(identifier);
18424
- if (destructuredType) return destructuredType;
18425
- const declarator = binding.bindingIdentifier.parent;
18426
- const declaration = declarator?.parent;
18427
- const forOfStatement = declaration?.parent;
18428
- if (isNodeOfType(declarator, "VariableDeclarator") && isNodeOfType(declaration, "VariableDeclaration") && isNodeOfType(forOfStatement, "ForOfStatement") && forOfStatement.left === declaration && isNodeOfType(forOfStatement.right, "Identifier")) return getArrayElementType(getIdentifierDeclaredType(forOfStatement.right, visitedBindingIdentifiers));
18429
- return null;
18430
- };
18431
- const isNativeIterationIndex = (identifier) => {
18432
- const binding = findVariableInitializer(identifier, identifier.name);
18433
- if (!binding) return false;
18434
- const callback = binding.bindingIdentifier.parent;
18435
- if (!isInlineFunctionExpression(callback)) return false;
18436
- const callbackCall = callback.parent;
18437
- if (!isNodeOfType(callbackCall, "CallExpression") || !isIterationCallbackCall(callbackCall) || !isNodeOfType(callbackCall.callee, "MemberExpression") || !isNodeOfType(callbackCall.callee.property, "Identifier")) return false;
18438
- const indexParameterPosition = callbackCall.callee.property.name === "reduce" || callbackCall.callee.property.name === "reduceRight" ? 2 : 1;
18439
- return callback.params?.[indexParameterPosition] === binding.bindingIdentifier;
18440
- };
18441
- const hasSameIdentifierBinding = (leftIdentifier, rightIdentifier) => {
18442
- if (leftIdentifier.name !== rightIdentifier.name) return false;
18443
- const leftBinding = findVariableInitializer(leftIdentifier, leftIdentifier.name);
18444
- const rightBinding = findVariableInitializer(rightIdentifier, rightIdentifier.name);
18445
- return Boolean(leftBinding && rightBinding && leftBinding.bindingIdentifier === rightBinding.bindingIdentifier);
18446
- };
18447
- const NON_NAN_RELATIONAL_OPERATORS = new Set([
18448
- "<",
18449
- "<=",
18450
- ">",
18451
- ">="
18452
- ]);
18453
- const testProvesIdentifierIsNotNaN = (test, identifier) => {
18454
- if (!test) return false;
18455
- const strippedTest = stripParenExpression(test);
18456
- if (isNodeOfType(strippedTest, "LogicalExpression") && strippedTest.operator === "&&") return testProvesIdentifierIsNotNaN(strippedTest.left, identifier) || testProvesIdentifierIsNotNaN(strippedTest.right, identifier);
18457
- if (!isNodeOfType(strippedTest, "BinaryExpression") || !NON_NAN_RELATIONAL_OPERATORS.has(strippedTest.operator)) return false;
18458
- return isNodeOfType(strippedTest.left, "Identifier") && hasSameIdentifierBinding(strippedTest.left, identifier) || isNodeOfType(strippedTest.right, "Identifier") && hasSameIdentifierBinding(strippedTest.right, identifier);
18459
- };
18460
- const writeTargetContainsIdentifierBinding = (writeTarget, identifier) => {
18461
- let containsBinding = false;
18462
- walkAst(writeTarget, (child) => {
18463
- if (isNodeOfType(child, "Identifier") && hasSameIdentifierBinding(child, identifier)) {
18464
- containsBinding = true;
18465
- return false;
18466
- }
18467
- });
18468
- return containsBinding;
18469
- };
18470
- const hasWriteBeforeQuery = (body, identifier) => {
18471
- const queryStart = getRangeStart(identifier);
18472
- if (queryStart === null) return true;
18473
- let hasEarlierWrite = false;
18474
- walkAst(body, (child) => {
18475
- if (hasEarlierWrite) return false;
18476
- const childStart = getRangeStart(child);
18477
- if (childStart !== null && childStart >= queryStart) return false;
18478
- if (child !== body && isFunctionLike$2(child)) return false;
18479
- const writeTarget = isNodeOfType(child, "AssignmentExpression") ? child.left : isNodeOfType(child, "UpdateExpression") ? child.argument : isNodeOfType(child, "ForInStatement") || isNodeOfType(child, "ForOfStatement") ? child.left : null;
18480
- if (writeTarget && writeTargetContainsIdentifierBinding(writeTarget, identifier)) {
18481
- hasEarlierWrite = true;
18482
- return false;
18483
- }
18484
- });
18485
- return hasEarlierWrite;
18486
- };
18487
- const isProtectedByRelationalLoopGuard = (identifier) => {
18488
- let descendant = identifier;
18489
- let ancestor = identifier.parent;
18490
- while (ancestor) {
18491
- if (isFunctionLike$2(ancestor)) return false;
18492
- if ((isNodeOfType(ancestor, "ForStatement") || isNodeOfType(ancestor, "WhileStatement")) && ancestor.body === descendant && testProvesIdentifierIsNotNaN(ancestor.test, identifier)) return !hasWriteBeforeQuery(ancestor.body, identifier);
18493
- descendant = ancestor;
18494
- ancestor = ancestor.parent;
18495
- }
18496
- return false;
18497
- };
18498
- const isKnownSafeIndexOfQuery = (query) => {
18499
- if (!query) return false;
18500
- const strippedQuery = stripParenExpression(query);
18501
- if (isNodeOfType(strippedQuery, "Literal")) return typeof strippedQuery.value !== "number" || Number.isFinite(strippedQuery.value);
18502
- if (!isNodeOfType(strippedQuery, "Identifier")) return false;
18503
- if (isNativeIterationIndex(strippedQuery)) return true;
18504
- return isProtectedByRelationalLoopGuard(strippedQuery);
18505
- };
18506
- const findSameFileTypeAlias = (reference, typeName) => {
18507
- const program = findProgramRoot(reference);
18508
- if (!program) return null;
18509
- for (const statement of program.body) {
18510
- const declaration = isNodeOfType(statement, "ExportNamedDeclaration") ? statement.declaration : statement;
18511
- if (declaration && isNodeOfType(declaration, "TSTypeAliasDeclaration") && isNodeOfType(declaration.id, "Identifier") && declaration.id.name === typeName) return declaration;
18512
- }
18513
- return null;
18514
- };
18515
- const hasDeclaredMembershipMethod = (members, methodName) => members.some((member) => (isNodeOfType(member, "TSMethodSignature") || isNodeOfType(member, "TSPropertySignature")) && isNodeOfType(member.key, "Identifier") && member.key.name === methodName);
18516
- const isKnownUserlandMembershipReceiver = (receiver, methodName) => {
18517
- if (!isNodeOfType(receiver, "Identifier")) return false;
18518
- const declaredType = getIdentifierDeclaredType(receiver);
18519
- if (!declaredType) return false;
18520
- if (isNodeOfType(declaredType, "TSTypeLiteral")) return hasDeclaredMembershipMethod(declaredType.members ?? [], methodName);
18521
- if (!isNodeOfType(declaredType, "TSTypeReference") || !isNodeOfType(declaredType.typeName, "Identifier")) return false;
18522
- const typeAlias = findSameFileTypeAlias(receiver, declaredType.typeName.name);
18523
- if (typeAlias && isNodeOfType(typeAlias.typeAnnotation, "TSTypeLiteral")) return hasDeclaredMembershipMethod(typeAlias.typeAnnotation.members ?? [], methodName);
18524
- const program = findProgramRoot(receiver);
18525
- if (!program) return false;
18526
- for (const statement of program.body) {
18527
- const declaration = isNodeOfType(statement, "ExportNamedDeclaration") ? statement.declaration : statement;
18528
- if (declaration && isNodeOfType(declaration, "TSInterfaceDeclaration") && isNodeOfType(declaration.id, "Identifier") && declaration.id.name === declaredType.typeName.name) return hasDeclaredMembershipMethod(declaration.body.body, methodName);
18529
- }
18530
- return false;
18531
- };
18532
- const findTypeParameter = (reference, typeName) => {
18533
- let ancestor = reference.parent;
18534
- while (ancestor) {
18535
- if (isFunctionLike$2(ancestor) || isNodeOfType(ancestor, "ClassDeclaration") || isNodeOfType(ancestor, "ClassExpression")) {
18536
- const matchingTypeParameter = ancestor.typeParameters?.params?.find((typeParameter) => isNodeOfType(typeParameter, "TSTypeParameter") && isNodeOfType(typeParameter.name, "Identifier") && typeParameter.name.name === typeName);
18537
- if (matchingTypeParameter && isNodeOfType(matchingTypeParameter, "TSTypeParameter")) return matchingTypeParameter;
18538
- }
18539
- ancestor = ancestor.parent;
18540
- }
18541
- return null;
18542
- };
18543
- const POSSIBLY_NUMERIC_TYPE_REFERENCE_NAMES = new Set(["NonNullable", "PropertyKey"]);
18544
- const buildTypeAliasArguments = (typeAlias, typeReference, inheritedArguments) => {
18545
- const typeArguments = new Map(inheritedArguments);
18546
- for (const [index, typeParameter] of (typeAlias.typeParameters?.params ?? []).entries()) {
18547
- if (!isNodeOfType(typeParameter, "TSTypeParameter")) continue;
18548
- if (!isNodeOfType(typeParameter.name, "Identifier")) continue;
18549
- const argument = typeReference.typeArguments?.params?.[index] ?? typeParameter.default;
18550
- if (argument) typeArguments.set(typeParameter.name.name, argument);
18551
- }
18552
- return typeArguments;
18553
- };
18554
- const typeCanHaveSameValueZeroDifference = (typeNode, reference, activeTypeNodes, typeArguments = /* @__PURE__ */ new Map()) => {
18555
- if (!typeNode) return false;
18556
- if (isNodeOfType(typeNode, "TSNumberKeyword") || isNodeOfType(typeNode, "TSAnyKeyword") || isNodeOfType(typeNode, "TSUnknownKeyword")) return true;
18557
- if (isNodeOfType(typeNode, "TSStringKeyword") || isNodeOfType(typeNode, "TSBooleanKeyword") || isNodeOfType(typeNode, "TSBigIntKeyword") || isNodeOfType(typeNode, "TSSymbolKeyword") || isNodeOfType(typeNode, "TSNullKeyword") || isNodeOfType(typeNode, "TSUndefinedKeyword") || isNodeOfType(typeNode, "TSObjectKeyword") || isNodeOfType(typeNode, "TSLiteralType") || isNodeOfType(typeNode, "TSFunctionType")) return false;
18558
- if (isNodeOfType(typeNode, "TSTypeLiteral")) return (typeNode.members?.length ?? 0) === 0;
18559
- if (isNodeOfType(typeNode, "TSTypeOperator") && typeNode.operator === "keyof") return false;
18560
- if (isNodeOfType(typeNode, "TSUnionType") || isNodeOfType(typeNode, "TSIntersectionType")) return typeNode.types.some((memberType) => typeCanHaveSameValueZeroDifference(memberType, reference, activeTypeNodes, typeArguments));
18561
- if (isNodeOfType(typeNode, "TSOptionalType") || isNodeOfType(typeNode, "TSRestType")) return typeCanHaveSameValueZeroDifference(typeNode.typeAnnotation, reference, activeTypeNodes, typeArguments);
18562
- if (isNodeOfType(typeNode, "TSNamedTupleMember")) return typeCanHaveSameValueZeroDifference(typeNode.elementType, reference, activeTypeNodes, typeArguments);
18563
- if (!isNodeOfType(typeNode, "TSTypeReference")) return true;
18564
- if (!isNodeOfType(typeNode.typeName, "Identifier")) return false;
18565
- const substitutedType = typeArguments.get(typeNode.typeName.name);
18566
- if (substitutedType) {
18567
- const remainingArguments = new Map(typeArguments);
18568
- remainingArguments.delete(typeNode.typeName.name);
18569
- return typeCanHaveSameValueZeroDifference(substitutedType, reference, activeTypeNodes, remainingArguments);
18570
- }
18571
- const typeParameter = findTypeParameter(reference, typeNode.typeName.name);
18572
- if (typeParameter) {
18573
- if (!typeParameter.constraint || activeTypeNodes.has(typeParameter)) return true;
18574
- activeTypeNodes.add(typeParameter);
18575
- const constraintCanDiffer = typeCanHaveSameValueZeroDifference(typeParameter.constraint, reference, activeTypeNodes, typeArguments);
18576
- activeTypeNodes.delete(typeParameter);
18577
- return constraintCanDiffer;
18578
- }
18579
- const typeAlias = findSameFileTypeAlias(reference, typeNode.typeName.name);
18580
- if (!typeAlias) return POSSIBLY_NUMERIC_TYPE_REFERENCE_NAMES.has(typeNode.typeName.name) || /(?:number|numeric)/i.test(typeNode.typeName.name);
18581
- if (activeTypeNodes.has(typeAlias)) return true;
18582
- activeTypeNodes.add(typeAlias);
18583
- const canDiffer = typeCanHaveSameValueZeroDifference(typeAlias.typeAnnotation, reference, activeTypeNodes, buildTypeAliasArguments(typeAlias, typeNode, typeArguments));
18584
- activeTypeNodes.delete(typeAlias);
18585
- return canDiffer;
18586
- };
18587
- const arrayTypeCanHaveSameValueZeroDifference = (typeNode, reference, activeTypeNodes, typeArguments = /* @__PURE__ */ new Map()) => {
18588
- if (!typeNode) return false;
18589
- if (isNodeOfType(typeNode, "TSArrayType")) return typeCanHaveSameValueZeroDifference(typeNode.elementType, reference, activeTypeNodes, typeArguments);
18590
- if (isNodeOfType(typeNode, "TSTupleType")) return typeNode.elementTypes.some((elementType) => {
18591
- if (isNodeOfType(elementType, "TSRestType")) return arrayTypeCanHaveSameValueZeroDifference(elementType.typeAnnotation, reference, activeTypeNodes, typeArguments);
18592
- if (isNodeOfType(elementType, "TSNamedTupleMember")) return typeCanHaveSameValueZeroDifference(elementType.elementType, reference, activeTypeNodes, typeArguments);
18593
- return typeCanHaveSameValueZeroDifference(elementType, reference, activeTypeNodes, typeArguments);
18594
- });
18595
- if (isNodeOfType(typeNode, "TSTypeOperator")) return arrayTypeCanHaveSameValueZeroDifference(typeNode.typeAnnotation ?? null, reference, activeTypeNodes, typeArguments);
18596
- if (isNodeOfType(typeNode, "TSUnionType") || isNodeOfType(typeNode, "TSIntersectionType")) return typeNode.types.some((memberType) => arrayTypeCanHaveSameValueZeroDifference(memberType, reference, activeTypeNodes, typeArguments));
18597
- if (!isNodeOfType(typeNode, "TSTypeReference") || !isNodeOfType(typeNode.typeName, "Identifier")) return false;
18598
- const substitutedType = typeArguments.get(typeNode.typeName.name);
18599
- if (substitutedType) {
18600
- const remainingArguments = new Map(typeArguments);
18601
- remainingArguments.delete(typeNode.typeName.name);
18602
- return arrayTypeCanHaveSameValueZeroDifference(substitutedType, reference, activeTypeNodes, remainingArguments);
18603
- }
18604
- if (typeNode.typeName.name === "Array" || typeNode.typeName.name === "ReadonlyArray") return typeCanHaveSameValueZeroDifference(typeNode.typeArguments?.params?.[0] ?? null, reference, activeTypeNodes, typeArguments);
18605
- const typeAlias = findSameFileTypeAlias(reference, typeNode.typeName.name);
18606
- if (!typeAlias || activeTypeNodes.has(typeAlias)) return false;
18607
- activeTypeNodes.add(typeAlias);
18608
- const canDiffer = arrayTypeCanHaveSameValueZeroDifference(typeAlias.typeAnnotation, reference, activeTypeNodes, buildTypeAliasArguments(typeAlias, typeNode, typeArguments));
18609
- activeTypeNodes.delete(typeAlias);
18610
- return canDiffer;
18611
- };
18612
- const isKnownArrayType = (typeNode, reference, activeTypeNodes, typeArguments = /* @__PURE__ */ new Map()) => {
18613
- if (!typeNode) return false;
18614
- if (isNodeOfType(typeNode, "TSArrayType") || isNodeOfType(typeNode, "TSTupleType")) return true;
18615
- if (isNodeOfType(typeNode, "TSTypeOperator")) return isKnownArrayType(typeNode.typeAnnotation ?? null, reference, activeTypeNodes, typeArguments);
18616
- if (isNodeOfType(typeNode, "TSUnionType")) {
18617
- const nonNullishTypes = typeNode.types.filter((memberType) => !isNodeOfType(memberType, "TSNullKeyword") && !isNodeOfType(memberType, "TSUndefinedKeyword"));
18618
- return nonNullishTypes.length > 0 && nonNullishTypes.every((memberType) => isKnownArrayType(memberType, reference, activeTypeNodes, typeArguments));
18619
- }
18620
- if (isNodeOfType(typeNode, "TSIntersectionType")) return typeNode.types.some((memberType) => isKnownArrayType(memberType, reference, activeTypeNodes, typeArguments));
18621
- if (!isNodeOfType(typeNode, "TSTypeReference") || !isNodeOfType(typeNode.typeName, "Identifier")) return false;
18622
- const substitutedType = typeArguments.get(typeNode.typeName.name);
18623
- if (substitutedType) {
18624
- const remainingArguments = new Map(typeArguments);
18625
- remainingArguments.delete(typeNode.typeName.name);
18626
- return isKnownArrayType(substitutedType, reference, activeTypeNodes, remainingArguments);
18627
- }
18628
- if (typeNode.typeName.name === "Array" || typeNode.typeName.name === "ReadonlyArray") return true;
18629
- const typeParameter = findTypeParameter(reference, typeNode.typeName.name);
18630
- if (typeParameter?.constraint) {
18631
- if (activeTypeNodes.has(typeParameter)) return false;
18632
- activeTypeNodes.add(typeParameter);
18633
- const isConstraintArray = isKnownArrayType(typeParameter.constraint, reference, activeTypeNodes, typeArguments);
18634
- activeTypeNodes.delete(typeParameter);
18635
- return isConstraintArray;
18636
- }
18637
- const typeAlias = findSameFileTypeAlias(reference, typeNode.typeName.name);
18638
- if (!typeAlias || activeTypeNodes.has(typeAlias)) return false;
18639
- activeTypeNodes.add(typeAlias);
18640
- const isArray = isKnownArrayType(typeAlias.typeAnnotation, reference, activeTypeNodes, buildTypeAliasArguments(typeAlias, typeNode, typeArguments));
18641
- activeTypeNodes.delete(typeAlias);
18642
- return isArray;
18643
- };
18644
- const isKnownNativeArrayReceiver = (receiver) => {
18645
- if (isNodeOfType(receiver, "ArrayExpression")) return true;
18646
- if (isNodeOfType(receiver, "Identifier") && isKnownArrayType(getIdentifierDeclaredType(receiver), receiver, /* @__PURE__ */ new Set())) return true;
18647
- const initializer = getResolvedInitializer(receiver)?.initializer;
18648
- if (!initializer) return false;
18649
- const strippedInitializer = stripParenExpression(initializer);
18650
- if (isNodeOfType(strippedInitializer, "ArrayExpression")) return true;
18651
- if (isNodeOfType(strippedInitializer, "NewExpression") && isNodeOfType(strippedInitializer.callee, "Identifier") && strippedInitializer.callee.name === "Array" && findVariableInitializer(strippedInitializer.callee, strippedInitializer.callee.name) === null) return true;
18652
- return isNodeOfType(strippedInitializer, "CallExpression") && isNodeOfType(strippedInitializer.callee, "MemberExpression") && isNodeOfType(strippedInitializer.callee.object, "Identifier") && strippedInitializer.callee.object.name === "Array" && isNodeOfType(strippedInitializer.callee.property, "Identifier") && (strippedInitializer.callee.property.name === "from" || strippedInitializer.callee.property.name === "of") && findVariableInitializer(strippedInitializer.callee.object, strippedInitializer.callee.object.name) === null;
18653
- };
18654
- const isKnownDenseArrayReceiver = (receiver) => {
18655
- const initializer = isNodeOfType(receiver, "Identifier") ? getResolvedInitializer(receiver)?.initializer : receiver;
18656
- if (!initializer) return false;
18657
- const strippedInitializer = stripParenExpression(initializer);
18658
- if (isNodeOfType(strippedInitializer, "ArrayExpression")) return (strippedInitializer.elements ?? []).every((element) => element !== null && !isNodeOfType(element, "SpreadElement"));
18659
- return isNodeOfType(strippedInitializer, "CallExpression") && isNodeOfType(strippedInitializer.callee, "MemberExpression") && isNodeOfType(strippedInitializer.callee.object, "Identifier") && strippedInitializer.callee.object.name === "Array" && isNodeOfType(strippedInitializer.callee.property, "Identifier") && (strippedInitializer.callee.property.name === "from" || strippedInitializer.callee.property.name === "of") && findVariableInitializer(strippedInitializer.callee.object, strippedInitializer.callee.object.name) === null;
18660
- };
18661
- const isKnownUnsafeIndexOfQuery = (query, receiver) => {
18662
- if (!query) return true;
18663
- const strippedQuery = stripParenExpression(query);
18664
- if (isNodeOfType(strippedQuery, "Identifier")) {
18665
- if (strippedQuery.name === "undefined" && findVariableInitializer(strippedQuery, strippedQuery.name) === null) return !isKnownDenseArrayReceiver(receiver);
18666
- if (strippedQuery.name === "NaN" && findVariableInitializer(strippedQuery, strippedQuery.name) === null) return true;
18667
- return typeCanHaveSameValueZeroDifference(getIdentifierDeclaredType(strippedQuery), strippedQuery, /* @__PURE__ */ new Set());
18668
- }
18669
- if (isNodeOfType(strippedQuery, "MemberExpression")) return !strippedQuery.computed && isNodeOfType(strippedQuery.object, "Identifier") && strippedQuery.object.name === "Number" && isNodeOfType(strippedQuery.property, "Identifier") && strippedQuery.property.name === "NaN" && findVariableInitializer(strippedQuery.object, strippedQuery.object.name) === null;
18670
- return true;
18671
- };
18672
- const isKnownUnsafeIndexOfReceiver = (receiver) => {
18673
- if (!isNodeOfType(receiver, "Identifier")) return false;
18674
- return arrayTypeCanHaveSameValueZeroDifference(getIdentifierDeclaredType(receiver), receiver, /* @__PURE__ */ new Set());
18675
- };
18676
18356
  const ITERATION_CALLBACK_METHOD_NAMES = new Set([
18677
18357
  "forEach",
18678
18358
  "map",
@@ -18801,22 +18481,16 @@ const jsSetMapLookups = defineRule({
18801
18481
  if (!isNodeOfType(node.callee, "MemberExpression") || !isNodeOfType(node.callee.property, "Identifier")) return;
18802
18482
  const methodName = node.callee.property.name;
18803
18483
  if (methodName !== "includes" && methodName !== "indexOf") return;
18804
- if (methodName === "includes" && !hasSemanticsPreservingIncludesArguments(node)) return;
18805
- if (methodName === "indexOf" && (node.arguments.length !== 1 || isNodeOfType(node.arguments[0], "SpreadElement") || !isIndexOfResultUsedAsMembershipTest(node))) return;
18484
+ if (methodName === "indexOf" && !isIndexOfResultUsedAsMembershipTest(node)) return;
18806
18485
  const rawReceiver = node.callee.object;
18807
18486
  if (!rawReceiver) return;
18808
18487
  const receiver = stripParenExpression(rawReceiver);
18809
- const isKnownNativeArray = isKnownNativeArrayReceiver(receiver);
18810
- if (isKnownUserlandMembershipReceiver(receiver, methodName)) return;
18811
- if (methodName === "includes" && node.arguments.length === 2 && !isKnownNativeArray) return;
18812
- const query = node.arguments[0];
18813
- if (methodName === "indexOf" && !isKnownSafeIndexOfQuery(query) && (isKnownUnsafeIndexOfQuery(query, receiver) || isKnownUnsafeIndexOfReceiver(receiver))) return;
18814
18488
  if (isLikelyStringReceiver(receiver)) return;
18815
18489
  if (isSmallInlineLiteralArray(receiver)) return;
18816
18490
  if (isScreamingSnakeCaseConstantReceiver(receiver)) return;
18817
18491
  if (isSmallFixedListMember(receiver)) return;
18818
- if (isSubstringSearchLiteral(query)) return;
18819
- if (isIndexedArrayElementWithStringArgument(receiver, query)) return;
18492
+ if (isSubstringSearchLiteral(node.arguments?.[0])) return;
18493
+ if (isIndexedArrayElementWithStringArgument(receiver, node.arguments?.[0])) return;
18820
18494
  const resolvedInitializer = getResolvedInitializer(receiver);
18821
18495
  if (resolvedInitializer) {
18822
18496
  if (isLikelyStringReceiver(resolvedInitializer.initializer)) return;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "oxlint-plugin-react-doctor",
3
- "version": "0.7.7-dev.afed801",
3
+ "version": "0.7.7-dev.bdd1321",
4
4
  "description": "React Doctor rules for oxlint.",
5
5
  "keywords": [
6
6
  "accessibility",