@pobammer-ts/small-rules 2.1.0 → 2.2.1

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 (3) hide show
  1. package/dist/index.d.ts +122 -286
  2. package/dist/index.js +316 -190
  3. package/package.json +21 -22
package/dist/index.js CHANGED
@@ -7,15 +7,17 @@ import { ResolverFactory } from "oxc-resolver";
7
7
  import { type } from "arktype";
8
8
  //#region src/rules/array-type-generic.ts
9
9
  function toGenericArrayType(typeNode, sourceCode) {
10
+ if (typeNode.type === "TSParenthesizedType") return toGenericArrayType(typeNode.typeAnnotation, sourceCode);
10
11
  if (typeNode.type === "TSArrayType") return `Array<${toGenericArrayType(typeNode.elementType, sourceCode)}>`;
11
12
  if (typeNode.type === "TSTypeOperator" && typeNode.operator === "readonly" && typeNode.typeAnnotation.type === "TSArrayType") return `ReadonlyArray<${toGenericArrayType(typeNode.typeAnnotation.elementType, sourceCode)}>`;
12
13
  return sourceCode.getText(typeNode);
13
14
  }
14
15
  function isTopLevelArrayType({ parent }) {
15
- return !(parent.type === "TSRestType" && parent.parent.type === "TSTupleType" || parent.type === "TSTupleType" || parent.type === "TSArrayType" || parent.type === "TSTypeOperator" && parent.operator === "readonly");
16
+ const meaningfulParent = parent.type === "TSParenthesizedType" ? parent.parent : parent;
17
+ return !(meaningfulParent.type === "TSRestType" && meaningfulParent.parent.type === "TSTupleType" || meaningfulParent.type === "TSTupleType" || meaningfulParent.type === "TSArrayType" || meaningfulParent.type === "TSTypeOperator" && meaningfulParent.operator === "readonly");
16
18
  }
17
19
  const arrayTypeGeneric = defineRule({
18
- create(context) {
20
+ createOnce(context) {
19
21
  function reportArrayType(node) {
20
22
  context.report({
21
23
  fix(fixer) {
@@ -343,7 +345,7 @@ function isKeyOfNode(key) {
343
345
  function isComponentName(name) {
344
346
  return COMPONENT_NAME_PATTERN.test(name);
345
347
  }
346
- function isVariableDeclarator$1(node) {
348
+ function isVariableDeclarator(node) {
347
349
  return node.type === "VariableDeclarator";
348
350
  }
349
351
  function getTypeAnnotationFromBinding(binding) {
@@ -369,7 +371,7 @@ function getImportedName({ imported }) {
369
371
  function hasName(node) {
370
372
  return node.type === "Identifier" && isStringRaw(node.name);
371
373
  }
372
- function isIdentifierName$1(node) {
374
+ function isIdentifierName(node) {
373
375
  return node.type === "Identifier";
374
376
  }
375
377
  function isJsxIdentifier$1(node) {
@@ -381,7 +383,7 @@ function isJsxOpeningExpression(node) {
381
383
  function isImportDeclaration(node) {
382
384
  return node.type === "ImportDeclaration";
383
385
  }
384
- function isStringLiteral$1(node) {
386
+ function isStringLiteral(node) {
385
387
  return node.type === "Literal" && isStringRaw(node.value);
386
388
  }
387
389
  function isCallExpression$1(node) {
@@ -429,7 +431,7 @@ function isImportDefaultSpecifier(node) {
429
431
  function isImportNamespaceSpecifier(node) {
430
432
  return node.type === "ImportNamespaceSpecifier";
431
433
  }
432
- function isVariableDeclaration$1(node) {
434
+ function isVariableDeclaration(node) {
433
435
  return node.type === "VariableDeclaration";
434
436
  }
435
437
  function isExportNamedDeclaration(node) {
@@ -462,7 +464,7 @@ function isFunction(node) {
462
464
  function isTsQualifiedName(node) {
463
465
  return node.type === "TSQualifiedName";
464
466
  }
465
- function isNumericLiteral$1(node) {
467
+ function isNumericLiteral(node) {
466
468
  return node.type === "Literal" && isNumberRaw(node.value);
467
469
  }
468
470
  function isNewExpression(node) {
@@ -498,9 +500,15 @@ function isThisExpression(node) {
498
500
  function isStaticRequire(node) {
499
501
  if (!isCallExpression$1(node) || node.optional) return false;
500
502
  const { callee } = node;
501
- if (!isIdentifierName$1(callee) || callee.name !== "require" || node.arguments.length !== 1) return false;
503
+ if (!isIdentifierName(callee) || callee.name !== "require" || node.arguments.length !== 1) return false;
502
504
  const [argument] = node.arguments;
503
- return argument !== void 0 && isStringLiteral$1(argument);
505
+ return argument !== void 0 && isStringLiteral(argument);
506
+ }
507
+ function isBindingIdentifier(node) {
508
+ return node.type === "Identifier";
509
+ }
510
+ function isExpressionNode(node) {
511
+ return node.type !== "PrivateIdentifier";
504
512
  }
505
513
  //#endregion
506
514
  //#region src/rules/ban-react-fc.ts
@@ -519,7 +527,7 @@ function getTypeAnnotationFromId(node) {
519
527
  return isTsTypeAnnotation(typeAnnotation) ? typeAnnotation : void 0;
520
528
  }
521
529
  const banReactFc = defineRule({
522
- create(context) {
530
+ createOnce(context) {
523
531
  return { VariableDeclarator(node) {
524
532
  const typeAnnotation = getTypeAnnotationFromId(node);
525
533
  if (typeAnnotation === void 0) return;
@@ -548,7 +556,6 @@ function normalizeBannedTypes(rawOptions) {
548
556
  const bannedTypes = new Map(DEFAULT_BANNED_TYPES);
549
557
  if (!(isRecord(rawOptions) && "bannedTypes" in rawOptions)) return bannedTypes;
550
558
  const { bannedTypes: configuredBannedTypes } = rawOptions;
551
- if (configuredBannedTypes === void 0) return bannedTypes;
552
559
  if (isStringArray$1(configuredBannedTypes)) {
553
560
  for (const typeName of configuredBannedTypes) bannedTypes.set(typeName.toLowerCase(), {
554
561
  originalName: typeName,
@@ -1427,7 +1434,7 @@ const enforceIanitorCheckType = defineRule({
1427
1434
  const { init, id } = node;
1428
1435
  if (init?.type !== "CallExpression" || !isIanitorValidator(init)) return;
1429
1436
  hasIanitorReference = true;
1430
- if (id.type === "Identifier" && id.typeAnnotation !== void 0) return;
1437
+ if (id.type === "Identifier" && id.typeAnnotation !== void 0 && id.typeAnnotation !== null) return;
1431
1438
  const complexity = calculateIanitorComplexity(init);
1432
1439
  if (complexity < config.baseThreshold) return;
1433
1440
  variableDeclaratorsToCheck.set(node, { complexity });
@@ -1881,7 +1888,7 @@ function getBindingTypeAnnotation(bindingName) {
1881
1888
  }
1882
1889
  function hasContextualArrayAnnotation(node, sourceCode) {
1883
1890
  const { parent } = node;
1884
- if (isVariableDeclarator$1(parent) && parent.init === node) {
1891
+ if (isVariableDeclarator(parent) && parent.init === node) {
1885
1892
  const typeAnnotation = getBindingTypeAnnotation(parent.id);
1886
1893
  if (typeAnnotation === void 0) return false;
1887
1894
  return extractElementTypeFromArrayAnnotation(typeAnnotation.typeAnnotation, sourceCode) !== void 0;
@@ -2050,7 +2057,7 @@ function reportLengthArrayConstructor(context, node, options, lengthExpressionTe
2050
2057
  }
2051
2058
  function getPushCollapseCandidate(sourceCode, statements, index) {
2052
2059
  const statement = statements[index];
2053
- if (statement === void 0 || !isVariableDeclaration$1(statement)) return void 0;
2060
+ if (statement === void 0 || !isVariableDeclaration(statement)) return void 0;
2054
2061
  if (statement.kind !== "const" && statement.kind !== "let") return void 0;
2055
2062
  if (statement.declarations.length !== 1) return void 0;
2056
2063
  const [declarator] = statement.declarations;
@@ -2199,9 +2206,6 @@ const VISITOR_KEYS_TO_SKIP = new Set([
2199
2206
  function isIdentifierReference$1(node) {
2200
2207
  return node.type === "Identifier";
2201
2208
  }
2202
- function isBindingIdentifier$1(node) {
2203
- return node.type === "Identifier";
2204
- }
2205
2209
  function isNode(value) {
2206
2210
  return "type" in value && typeof value.type === "string";
2207
2211
  }
@@ -2237,10 +2241,10 @@ function getArrayIndexAssignment(statement, arrayIdentifierName, expectedIndex)
2237
2241
  const { expression } = statement;
2238
2242
  if (!isAssignmentExpression(expression) || expression.operator !== "=") return void 0;
2239
2243
  const { left } = expression;
2240
- if (!isMemberExpression(left) || left.optional || !left.computed) return void 0;
2244
+ if (!(isMemberExpression(left) && left.computed)) return void 0;
2241
2245
  const { object, property } = left;
2242
2246
  if (!isIdentifierReference$1(object) || object.name !== arrayIdentifierName) return void 0;
2243
- if (!isNumericLiteral$1(property) || property.value !== expectedIndex) return void 0;
2247
+ if (!isNumericLiteral(property) || property.value !== expectedIndex) return void 0;
2244
2248
  return {
2245
2249
  expression,
2246
2250
  statement
@@ -2248,13 +2252,13 @@ function getArrayIndexAssignment(statement, arrayIdentifierName, expectedIndex)
2248
2252
  }
2249
2253
  function getCandidate(sourceCode, statements, index) {
2250
2254
  const declaration = statements[index];
2251
- if (declaration === void 0 || !isVariableDeclaration$1(declaration) || declaration.declarations.length !== 1) return;
2255
+ if (declaration === void 0 || !isVariableDeclaration(declaration) || declaration.declarations.length !== 1) return;
2252
2256
  const [declarator] = declaration.declarations;
2253
2257
  /* v8 ignore next -- guarded by declarations.length === 1; undefined is a parser invariant. @preserve */
2254
- if (declarator === void 0 || !isVariableDeclarator$1(declarator) || declarator.init === null) return;
2258
+ if (declarator === void 0 || !isVariableDeclarator(declarator) || declarator.init === null) return;
2255
2259
  const { init } = declarator;
2256
2260
  if (!isNewExpression(init) || init.arguments.length > 0 || !isGlobalArrayConstructor(sourceCode, init)) return;
2257
- if (!isBindingIdentifier$1(declarator.id)) return void 0;
2261
+ if (!isBindingIdentifier(declarator.id)) return void 0;
2258
2262
  const arrayIdentifierName = declarator.id.name;
2259
2263
  const foundAssignments = new Array();
2260
2264
  let scanIndex = index + 1;
@@ -2373,9 +2377,6 @@ function isAllowAutofixOption(value) {
2373
2377
  }
2374
2378
  //#endregion
2375
2379
  //#region src/rules/no-array-size-assignment.ts
2376
- function isExpressionNode$1(node) {
2377
- return node.type !== "PrivateIdentifier";
2378
- }
2379
2380
  function areEquivalentTargets(left, right, sourceCode) {
2380
2381
  if (left.type !== right.type) return false;
2381
2382
  switch (left.type) {
@@ -2394,7 +2395,7 @@ function areEquivalentMembers(left, right, sourceCode) {
2394
2395
  return left.computed ? areEquivalentComputedProperties(left.property, right.property, sourceCode) : areEquivalentStaticProperties(left.property, right.property);
2395
2396
  }
2396
2397
  function areEquivalentComputedProperties(left, right, sourceCode) {
2397
- return isExpressionNode$1(left) && isExpressionNode$1(right) && areEquivalentTargets(left, right, sourceCode);
2398
+ return isExpressionNode(left) && isExpressionNode(right) && areEquivalentTargets(left, right, sourceCode);
2398
2399
  }
2399
2400
  function areEquivalentStaticProperties(left, right) {
2400
2401
  if (left.type === "PrivateIdentifier" || right.type === "PrivateIdentifier") return left.type === "PrivateIdentifier" && right.type === "PrivateIdentifier" && left.name === right.name;
@@ -2409,7 +2410,7 @@ function isSafeMemberAccess(node, allowLiteralRoot) {
2409
2410
  if (node.optional || !isSafeMemberAccess(node.object, false)) return false;
2410
2411
  if (node.computed)
2411
2412
  /* v8 ignore next -- @preserve computed member properties are expressions in parser output. */
2412
- return isExpressionNode$1(node.property) ? isSafeMemberAccess(node.property, true) : false;
2413
+ return isExpressionNode(node.property) ? isSafeMemberAccess(node.property, true) : false;
2413
2414
  return node.property.type === "Identifier" || node.property.type === "PrivateIdentifier";
2414
2415
  default: return false;
2415
2416
  }
@@ -2440,7 +2441,7 @@ function getAppendTarget(node, sourceCode, environment) {
2440
2441
  const noArraySizeAssignment = defineRule({
2441
2442
  create(context) {
2442
2443
  const [options] = context.options;
2443
- const allowAutofix = isAllowAutofixOption(options) && options?.allowAutofix === true;
2444
+ const allowAutofix = isAllowAutofixOption(options) && options.allowAutofix;
2444
2445
  const environment = options?.environment === "standard" ? "standard" : "roblox-ts";
2445
2446
  const { sourceCode } = context;
2446
2447
  return { AssignmentExpression(node) {
@@ -2595,7 +2596,8 @@ function isPromiseChainCall(node) {
2595
2596
  return PROMISE_CHAIN_METHODS.has(node.callee.property.name);
2596
2597
  }
2597
2598
  function isAsyncIife({ callee }) {
2598
- return (callee.type === "ArrowFunctionExpression" || callee.type === "FunctionExpression") && callee.async;
2599
+ const unwrapped = unwrapExpression(callee);
2600
+ return (unwrapped.type === "ArrowFunctionExpression" || unwrapped.type === "FunctionExpression") && unwrapped.async;
2599
2601
  }
2600
2602
  function getThisAsyncMethodName({ callee }, asyncMethods) {
2601
2603
  if (callee.type !== "MemberExpression" || callee.object.type !== "ThisExpression" || callee.property.type !== "Identifier") return;
@@ -2613,6 +2615,7 @@ function getLocalVariableAssignment(node) {
2613
2615
  }
2614
2616
  function isNonIifeFunction(node) {
2615
2617
  if (node.type !== "ArrowFunctionExpression" && node.type !== "FunctionExpression") return false;
2618
+ if (node.parent.type === "ParenthesizedExpression" && node.parent.parent.type === "CallExpression" && node.parent.parent.callee === node.parent) return false;
2616
2619
  return node.parent.type !== "CallExpression" || node.parent.callee !== node;
2617
2620
  }
2618
2621
  function isInsideSkippedFunction(node, constructorBody) {
@@ -2740,9 +2743,6 @@ const noCascadingSetState = defineRule({
2740
2743
  });
2741
2744
  //#endregion
2742
2745
  //#region src/rules/no-color3-constructor.ts
2743
- function isNumericLiteral(node) {
2744
- return node.type === "Literal" && isNumberRaw(node.value);
2745
- }
2746
2746
  function mapComponentToRgbRange(value) {
2747
2747
  return Math.round(value > 1 ? value : value * 255);
2748
2748
  }
@@ -3645,6 +3645,7 @@ function unwrapNode(node) {
3645
3645
  /* v8 ignore next -- @preserve wrapper variants are parser-shape defensive cases. */
3646
3646
  switch (node.type) {
3647
3647
  case "ChainExpression":
3648
+ case "ParenthesizedExpression":
3648
3649
  case "TSAsExpression":
3649
3650
  case "TSInstantiationExpression":
3650
3651
  case "TSNonNullExpression":
@@ -4569,7 +4570,7 @@ function isStandaloneUpdateExpression(node) {
4569
4570
  const noIncrementDecrement = defineRule({
4570
4571
  create(context) {
4571
4572
  const [options] = context.options;
4572
- const allowAutofix = isAllowAutofixOption(options) && options.allowAutofix === true;
4573
+ const allowAutofix = isAllowAutofixOption(options) && options.allowAutofix;
4573
4574
  const { sourceCode } = context;
4574
4575
  return { UpdateExpression(node) {
4575
4576
  if (!isStandaloneUpdateExpression(node)) return;
@@ -4705,7 +4706,6 @@ function traverseForThis(currentNode, visited) {
4705
4706
  return false;
4706
4707
  }
4707
4708
  function childUsesThis(childValue, visited) {
4708
- if (childValue === void 0) return false;
4709
4709
  if (Array.isArray(childValue)) {
4710
4710
  for (const item of childValue) if (isNode$1(item) && traverseForThis(item, visited)) return true;
4711
4711
  return false;
@@ -4833,7 +4833,7 @@ const VALID_EXPRESSIONS = new Set([
4833
4833
  function isExpression$1(node) {
4834
4834
  return VALID_EXPRESSIONS.has(node.type);
4835
4835
  }
4836
- function isModuleLevelScope$1(scope) {
4836
+ function isModuleLevelScope(scope) {
4837
4837
  return scope.type === "module" || scope.type === "global";
4838
4838
  }
4839
4839
  function isImportBinding(scopeVariable) {
@@ -4854,7 +4854,7 @@ function getConstInitializer(definition) {
4854
4854
  }
4855
4855
  function getModuleConstInitializer(sourceCode, identifier) {
4856
4856
  const variable = getVariableByName(sourceCode.getScope(identifier), identifier.name);
4857
- if (variable === void 0 || !isModuleLevelScope$1(variable.scope)) return void 0;
4857
+ if (variable === void 0 || !isModuleLevelScope(variable.scope)) return void 0;
4858
4858
  for (const definition of variable.defs) {
4859
4859
  const initializer = getConstInitializer(definition);
4860
4860
  if (initializer !== void 0) return initializer;
@@ -4924,7 +4924,7 @@ function isStaticExpression(sourceCode, expression, seen, options) {
4924
4924
  function isStaticIdentifier(sourceCode, identifier, seen, options) {
4925
4925
  const variable = getVariableByName(sourceCode.getScope(identifier), identifier.name);
4926
4926
  if (variable === void 0) return options.staticGlobalFactories.has(identifier.name);
4927
- if (!isModuleLevelScope$1(variable.scope)) return false;
4927
+ if (!isModuleLevelScope(variable.scope)) return false;
4928
4928
  if (isImportBinding(variable)) return true;
4929
4929
  for (const definition of variable.defs) {
4930
4930
  const initializer = getConstInitializer(definition);
@@ -4964,9 +4964,6 @@ function getVariableInitializer(definition) {
4964
4964
  if (definition.type !== "Variable" || definition.node.type !== "VariableDeclarator") return void 0;
4965
4965
  return definition.node.init ?? void 0;
4966
4966
  }
4967
- function isModuleLevelScope(scope) {
4968
- return scope.type === "module" || scope.type === "global";
4969
- }
4970
4967
  function getRootIdentifier$1(expression) {
4971
4968
  let currentExpression = unwrapExpression(expression);
4972
4969
  while (currentExpression.type === "MemberExpression") {
@@ -5028,6 +5025,7 @@ const noNativePropertiesSpread = defineRule({
5028
5025
  const { value } = node;
5029
5026
  if (value?.type !== "JSXExpressionContainer") return;
5030
5027
  const { expression } = value;
5028
+ /* v8 ignore next -- @preserve Oxc only produces JSXEmptyExpression here for rejected parse-error cases. */
5031
5029
  if (expression.type === "JSXEmptyExpression") return;
5032
5030
  const objectExpression = resolveObjectExpression(sourceCode, expression, /* @__PURE__ */ new Set());
5033
5031
  if (objectExpression === void 0) return;
@@ -5541,6 +5539,10 @@ function getFunctionComponentName(node) {
5541
5539
  if (parent.type === "VariableDeclarator" && parent.id.type === "Identifier") return parent.id.name;
5542
5540
  }
5543
5541
  }
5542
+ function getArrowExpressionBody(node) {
5543
+ if (node.body.type === "BlockStatement") return void 0;
5544
+ return unwrapExpression(node.body);
5545
+ }
5544
5546
  function getImportSourceFromVariable(variable) {
5545
5547
  for (const definition of variable.defs) {
5546
5548
  /* v8 ignore start -- @preserve imported component variables only carry import binding definitions here. */
@@ -5597,8 +5599,9 @@ const noRedundantAspectRatioConstraint = defineRule({
5597
5599
  return {
5598
5600
  ArrowFunctionExpression(node) {
5599
5601
  const name = getFunctionComponentName(node);
5600
- if (name === void 0 || node.body.type !== "JSXElement" && node.body.type !== "JSXFragment") return;
5601
- if (!hasAspectRatioConstraintInSubtree(node.body)) return;
5602
+ const body = getArrowExpressionBody(node);
5603
+ if (name === void 0 || body === void 0 || body.type !== "JSXElement" && body.type !== "JSXFragment") return;
5604
+ if (!hasAspectRatioConstraintInSubtree(body)) return;
5602
5605
  protectedComponents.add(name);
5603
5606
  },
5604
5607
  FunctionDeclaration(node) {
@@ -5702,7 +5705,15 @@ function isPropertyValueReference(node) {
5702
5705
  /* v8 ignore next -- @preserve scope reference identifiers always have parents in parser-produced ASTs. */
5703
5706
  const parent = ascendPastWrappers$1(node.parent ?? void 0);
5704
5707
  /* v8 ignore next -- @preserve scope references always have parents in parser-produced ASTs. */
5705
- return parent?.type === "Property" && parent.value === node;
5708
+ return parent?.type === "Property" && unwrapPropertyValue(parent.value) === node;
5709
+ }
5710
+ function unwrapPropertyValue(node) {
5711
+ let current = node;
5712
+ while (isWrapperParent(current)) current = current.expression;
5713
+ return current;
5714
+ }
5715
+ function isWrapperParent(node) {
5716
+ return WRAPPER_PARENT_TYPES$1.has(node.type);
5706
5717
  }
5707
5718
  function getDeclaredFunctionVariable(sourceCode, node) {
5708
5719
  if (node.type === "FunctionDeclaration") {
@@ -5792,10 +5803,118 @@ const noRenderHelperFunctions = defineRule({
5792
5803
  }
5793
5804
  });
5794
5805
  //#endregion
5806
+ //#region src/rules/no-restricted-property-assignment.ts
5807
+ function isRestriction(value) {
5808
+ if (!isRecord(value)) return false;
5809
+ if (!isStringRaw(value.object)) return false;
5810
+ if (!Array.isArray(value.properties)) return false;
5811
+ if (!value.properties.every((property) => isStringRaw(property))) return false;
5812
+ return value.message === void 0 || isStringRaw(value.message);
5813
+ }
5814
+ function isRuleOptions(value) {
5815
+ if (!isRecord(value)) return false;
5816
+ if (!Array.isArray(value.restrictions)) return false;
5817
+ if (!value.restrictions.every(isRestriction)) return false;
5818
+ return value.checkComputed === void 0 || typeof value.checkComputed === "boolean";
5819
+ }
5820
+ function isMemberExpressionTarget(node) {
5821
+ return node.type === "MemberExpression";
5822
+ }
5823
+ const noRestrictedPropertyAssignment = defineRule({
5824
+ createOnce(context) {
5825
+ let restrictions = [];
5826
+ let checkComputed = true;
5827
+ function reportIfRestricted(node, reportNode) {
5828
+ if (!isMemberExpressionTarget(node)) return;
5829
+ if (node.computed && !checkComputed) return;
5830
+ if (node.object.type !== "Identifier") return;
5831
+ const property = getMemberPropertyName(node);
5832
+ if (property === void 0) return;
5833
+ for (const restriction of restrictions) {
5834
+ if (restriction.object !== node.object.name) continue;
5835
+ if (restriction.properties.includes("*") || restriction.properties.includes(property)) {
5836
+ if (restriction.message === void 0) context.report({
5837
+ data: {
5838
+ object: node.object.name,
5839
+ property
5840
+ },
5841
+ messageId: "restricted",
5842
+ node: reportNode
5843
+ });
5844
+ else context.report({
5845
+ data: { message: restriction.message },
5846
+ messageId: "restrictedCustom",
5847
+ node: reportNode
5848
+ });
5849
+ return;
5850
+ }
5851
+ }
5852
+ }
5853
+ return {
5854
+ AssignmentExpression(node) {
5855
+ reportIfRestricted(node.left, node);
5856
+ },
5857
+ before() {
5858
+ const [options] = context.options;
5859
+ if (!isRuleOptions(options)) {
5860
+ restrictions = [];
5861
+ checkComputed = true;
5862
+ return;
5863
+ }
5864
+ const { checkComputed: nextCheckComputed, restrictions: nextRestrictions } = options;
5865
+ restrictions = nextRestrictions;
5866
+ checkComputed = nextCheckComputed ?? true;
5867
+ },
5868
+ UpdateExpression(node) {
5869
+ reportIfRestricted(node.argument, node);
5870
+ }
5871
+ };
5872
+ },
5873
+ meta: {
5874
+ docs: {
5875
+ description: "Disallow assignment to restricted object properties.",
5876
+ recommended: true
5877
+ },
5878
+ messages: {
5879
+ restricted: "Assignment to '{{object}}.{{property}}' is not permitted.",
5880
+ restrictedCustom: "{{message}}"
5881
+ },
5882
+ schema: [{
5883
+ additionalProperties: false,
5884
+ properties: {
5885
+ checkComputed: {
5886
+ default: true,
5887
+ type: "boolean"
5888
+ },
5889
+ restrictions: {
5890
+ items: {
5891
+ additionalProperties: false,
5892
+ properties: {
5893
+ message: { type: "string" },
5894
+ object: { type: "string" },
5895
+ properties: {
5896
+ items: { type: "string" },
5897
+ minItems: 1,
5898
+ type: "array"
5899
+ }
5900
+ },
5901
+ required: ["object", "properties"],
5902
+ type: "object"
5903
+ },
5904
+ type: "array"
5905
+ }
5906
+ },
5907
+ required: ["restrictions"],
5908
+ type: "object"
5909
+ }],
5910
+ type: "problem"
5911
+ }
5912
+ });
5913
+ //#endregion
5795
5914
  //#region src/rules/no-spec-file-extension.ts
5796
5915
  const SPEC_EXTENSION_PATTERN = /\.spec\.(?:ts|tsx)$/u;
5797
5916
  const noSpecFileExtension = defineRule({
5798
- create(context) {
5917
+ createOnce(context) {
5799
5918
  return { Program(node) {
5800
5919
  const { filename } = context;
5801
5920
  if (!(filename && SPEC_EXTENSION_PATTERN.test(filename))) return;
@@ -5861,7 +5980,7 @@ function isStringElementName(node) {
5861
5980
  }
5862
5981
  function isStaticComponentVariable(variable, name) {
5863
5982
  if (isImportBinding(variable)) return isComponentName(name) || name === REACT_FRAGMENT;
5864
- if (!isModuleLevelScope$1(variable.scope)) return false;
5983
+ if (!isModuleLevelScope(variable.scope)) return false;
5865
5984
  if (!isComponentName(name) && name !== REACT_FRAGMENT) return false;
5866
5985
  for (const definition of variable.defs) {
5867
5986
  if (definition.type === "FunctionName" || definition.type === "ClassName") return true;
@@ -6000,7 +6119,7 @@ function isPromiseDelayAwaitCall(node) {
6000
6119
  return getMemberPropertyName(delayCallee) === "delay";
6001
6120
  }
6002
6121
  const noTaskWait = defineRule({
6003
- create(context) {
6122
+ createOnce(context) {
6004
6123
  return { CallExpression(node) {
6005
6124
  if (isPromiseDelayAwaitCall(node)) {
6006
6125
  context.report({
@@ -6032,7 +6151,7 @@ const noTaskWait = defineRule({
6032
6151
  //#endregion
6033
6152
  //#region src/rules/no-underscore-react-properties.ts
6034
6153
  const noUnderscoreReactProperties = defineRule({
6035
- create(context) {
6154
+ createOnce(context) {
6036
6155
  return { JSXAttribute(node) {
6037
6156
  if (node.name.type !== "JSXIdentifier" || !node.name.name.startsWith("_")) return;
6038
6157
  context.report({
@@ -6256,20 +6375,11 @@ function collectAllScopes(root) {
6256
6375
  const current = stack.pop();
6257
6376
  /* v8 ignore next -- @preserve non-empty traversal stack always yields a scope from pop. */
6258
6377
  if (current === void 0) break;
6259
- scopes[size++] = current;
6378
+ if (current.type !== "global") scopes[size++] = current;
6260
6379
  for (const childScope of current.childScopes) stack.push(childScope);
6261
6380
  }
6262
6381
  return scopes;
6263
6382
  }
6264
- function isBindingIdentifier(node) {
6265
- return node.type === "Identifier";
6266
- }
6267
- function isVariableDeclarator(node) {
6268
- return node.type === "VariableDeclarator";
6269
- }
6270
- function isVariableDeclaration(node) {
6271
- return node.type === "VariableDeclaration";
6272
- }
6273
6383
  function isFunctionLikeInitializer(node) {
6274
6384
  return isCallbackFunction(node) || node.type === "ClassExpression";
6275
6385
  }
@@ -6278,7 +6388,8 @@ function isObjectLikeInitializer(initializer, patterns, sourceCode) {
6278
6388
  if (initializer.type === "JSXElement" || initializer.type === "JSXFragment") return true;
6279
6389
  if (initializer.type !== "CallExpression" && initializer.type !== "NewExpression") return false;
6280
6390
  const candidateText = sourceCode.getText(initializer.callee);
6281
- return patterns.some((pattern) => pattern.test(candidateText));
6391
+ for (const pattern of patterns) if (pattern.test(candidateText)) return true;
6392
+ return false;
6282
6393
  }
6283
6394
  function isStatementContainer(node) {
6284
6395
  return node.type === "Program" || node.type === "BlockStatement";
@@ -6365,6 +6476,11 @@ function isAutoInlineSafeInitializer(sourceCode, node) {
6365
6476
  if (node.type === "Literal") return true;
6366
6477
  return isStaticExpression(sourceCode, node, /* @__PURE__ */ new Set(), STATIC_OPTIONS$1) && hasOnlyRelocatableCalls(node, STATIC_OPTIONS$1.staticGlobalFactories);
6367
6478
  }
6479
+ function getInlineInitializerText(sourceCode, initializer) {
6480
+ let current = initializer;
6481
+ while (current.type === "ParenthesizedExpression") current = current.expression;
6482
+ return sourceCode.getText(current);
6483
+ }
6368
6484
  function areAdjacentStatements(first, second) {
6369
6485
  const { parent } = first;
6370
6486
  /* v8 ignore next -- @preserve VariableDeclaration parents visited by this rule are Program or BlockStatement containers. */
@@ -6471,7 +6587,6 @@ const noUselessConstants = defineRule({
6471
6587
  };
6472
6588
  }
6473
6589
  function inspectScope(scope) {
6474
- if (scope.type === "global") return;
6475
6590
  const fixableConstants = new Array();
6476
6591
  for (const scopeVariable of scope.variables) {
6477
6592
  const candidate = getUselessConstantCandidate(scope, scopeVariable);
@@ -6489,7 +6604,7 @@ const noUselessConstants = defineRule({
6489
6604
  }
6490
6605
  fixableConstants.push({
6491
6606
  declarationNode: candidate.declarationNode,
6492
- initializerText: sourceCode.getText(candidate.initializer),
6607
+ initializerText: getInlineInitializerText(sourceCode, candidate.initializer),
6493
6608
  name: candidate.name,
6494
6609
  referenceIdentifier: candidate.referenceIdentifier,
6495
6610
  reportNode: candidate.reportNode
@@ -18311,9 +18426,6 @@ function isIdentifierNamed(node, name) {
18311
18426
  function isBooleanLiteral(node) {
18312
18427
  return node.type === "Literal" && typeof node.value === "boolean";
18313
18428
  }
18314
- function isStringLiteral(node) {
18315
- return node.type === "Literal" && isStringRaw(node.value);
18316
- }
18317
18429
  function getIntrinsicClassName(node) {
18318
18430
  if (node.type !== "JSXIdentifier") return void 0;
18319
18431
  const className = intrinsicClassNamesByTagName.get(node.name.toLowerCase());
@@ -18328,6 +18440,7 @@ function getJsxAttributeExpression(node) {
18328
18440
  const { value } = node;
18329
18441
  if (value === null) return void 0;
18330
18442
  if (value.type === "Literal") return value;
18443
+ /* v8 ignore next -- @preserve Oxc only produces JSXEmptyExpression here for rejected parse-error cases. */
18331
18444
  if (value.type !== "JSXExpressionContainer" || value.expression.type === "JSXEmptyExpression") return void 0;
18332
18445
  return value.expression;
18333
18446
  }
@@ -18426,7 +18539,7 @@ function matchesTuple(expected, actual) {
18426
18539
  return true;
18427
18540
  }
18428
18541
  function extractNumberValue(node) {
18429
- if (isNumericLiteral$1(node)) return node.value;
18542
+ if (isNumericLiteral(node)) return node.value;
18430
18543
  if (isMathHuge(node)) return Number.POSITIVE_INFINITY;
18431
18544
  if (node.type !== "UnaryExpression") return void 0;
18432
18545
  if (node.operator !== "+" && node.operator !== "-") return void 0;
@@ -18469,13 +18582,16 @@ function extractVector2Value(node) {
18469
18582
  }
18470
18583
  if (node.type !== "NewExpression" || !isIdentifierNamed(node.callee, "Vector2")) return void 0;
18471
18584
  if (node.arguments.length === 0) return [0, 0];
18472
- const components = extractPair(node.arguments);
18585
+ return extractNumberPair(node.arguments);
18586
+ }
18587
+ function extractNumberPair(argumentsList) {
18588
+ const components = extractPair(argumentsList);
18473
18589
  if (components === void 0) return void 0;
18474
- const [xNode, yNode] = components;
18475
- const x = extractNumberValue(xNode);
18476
- const y = extractNumberValue(yNode);
18477
- if (x === void 0 || y === void 0) return void 0;
18478
- return [x, y];
18590
+ const [firstNode, secondNode] = components;
18591
+ const first = extractNumberValue(firstNode);
18592
+ const second = extractNumberValue(secondNode);
18593
+ if (first === void 0 || second === void 0) return void 0;
18594
+ return [first, second];
18479
18595
  }
18480
18596
  function extractNumberTriple(argumentsList) {
18481
18597
  const components = extractTriple(argumentsList);
@@ -18512,23 +18628,30 @@ function extractVector3Value(node) {
18512
18628
  function extractUDimValue(node) {
18513
18629
  if (node.type !== "NewExpression" || !isIdentifierNamed(node.callee, "UDim")) return void 0;
18514
18630
  if (node.arguments.length === 0) return [0, 0];
18515
- const components = extractPair(node.arguments);
18631
+ return extractNumberPair(node.arguments);
18632
+ }
18633
+ function extractNumberQuadruple(argumentsList) {
18634
+ const components = extractQuadruple(argumentsList);
18516
18635
  if (components === void 0) return void 0;
18517
- const [scaleNode, offsetNode] = components;
18518
- const scale = extractNumberValue(scaleNode);
18519
- const offset = extractNumberValue(offsetNode);
18520
- if (scale === void 0 || offset === void 0) return void 0;
18521
- return [scale, offset];
18636
+ const [firstNode, secondNode, thirdNode, fourthNode] = components;
18637
+ const first = extractNumberValue(firstNode);
18638
+ const second = extractNumberValue(secondNode);
18639
+ const third = extractNumberValue(thirdNode);
18640
+ const fourth = extractNumberValue(fourthNode);
18641
+ if (first === void 0 || second === void 0 || third === void 0 || fourth === void 0) return;
18642
+ return [
18643
+ first,
18644
+ second,
18645
+ third,
18646
+ fourth
18647
+ ];
18522
18648
  }
18523
18649
  function extractUDim2Value(node) {
18524
18650
  if (node.type === "CallExpression") {
18525
18651
  const path = getMemberPath(node.callee);
18526
- const components = extractPair(node.arguments);
18652
+ const components = extractNumberPair(node.arguments);
18527
18653
  if (path === void 0 || components === void 0) return void 0;
18528
- const [firstNode, secondNode] = components;
18529
- const first = extractNumberValue(firstNode);
18530
- const second = extractNumberValue(secondNode);
18531
- if (first === void 0 || second === void 0) return void 0;
18654
+ const [first, second] = components;
18532
18655
  if (path.length === 2 && path[0] === "UDim2" && path[1] === "fromOffset") return [
18533
18656
  0,
18534
18657
  first,
@@ -18550,20 +18673,7 @@ function extractUDim2Value(node) {
18550
18673
  0,
18551
18674
  0
18552
18675
  ];
18553
- const components = extractQuadruple(node.arguments);
18554
- if (components === void 0) return void 0;
18555
- const [scaleXNode, offsetXNode, scaleYNode, offsetYNode] = components;
18556
- const scaleX = extractNumberValue(scaleXNode);
18557
- const offsetX = extractNumberValue(offsetXNode);
18558
- const scaleY = extractNumberValue(scaleYNode);
18559
- const offsetY = extractNumberValue(offsetYNode);
18560
- if (scaleX === void 0 || offsetX === void 0 || scaleY === void 0 || offsetY === void 0) return;
18561
- return [
18562
- scaleX,
18563
- offsetX,
18564
- scaleY,
18565
- offsetY
18566
- ];
18676
+ return extractNumberQuadruple(node.arguments);
18567
18677
  }
18568
18678
  function extractRectValue(node) {
18569
18679
  if (node.type !== "NewExpression" || !isIdentifierNamed(node.callee, "Rect")) return void 0;
@@ -18573,20 +18683,7 @@ function extractRectValue(node) {
18573
18683
  0,
18574
18684
  0
18575
18685
  ];
18576
- const components = extractQuadruple(node.arguments);
18577
- if (components === void 0) return void 0;
18578
- const [minimumXNode, minimumYNode, maximumXNode, maximumYNode] = components;
18579
- const minimumX = extractNumberValue(minimumXNode);
18580
- const minimumY = extractNumberValue(minimumYNode);
18581
- const maximumX = extractNumberValue(maximumXNode);
18582
- const maximumY = extractNumberValue(maximumYNode);
18583
- if (minimumX === void 0 || minimumY === void 0 || maximumX === void 0 || maximumY === void 0) return;
18584
- return [
18585
- minimumX,
18586
- minimumY,
18587
- maximumX,
18588
- maximumY
18589
- ];
18686
+ return extractNumberQuadruple(node.arguments);
18590
18687
  }
18591
18688
  function extractRGBFromComponents(components) {
18592
18689
  const [redNode, greenNode, blueNode] = components;
@@ -18944,10 +19041,22 @@ function normalizeOptions$1(raw) {
18944
19041
  stateHooks: new Set(isStringArray$1(raw.stateHooks) ? raw.stateHooks : DEFAULT_STATE_HOOKS)
18945
19042
  };
18946
19043
  }
19044
+ function getNamespacedCallNames(callee) {
19045
+ if (callee.type !== "MemberExpression" || callee.computed || callee.object.type !== "Identifier" || callee.property.type !== "Identifier") return;
19046
+ return {
19047
+ objectName: callee.object.name,
19048
+ propertyName: callee.property.name
19049
+ };
19050
+ }
19051
+ function getNonComputedCalleePropertyName(callee) {
19052
+ if (callee.type !== "MemberExpression" || callee.computed || callee.property.type !== "Identifier") return;
19053
+ return callee.property.name;
19054
+ }
18947
19055
  function isHookCall$1(node, hookIdentifiers, reactNamespaces, hookNames) {
18948
19056
  const { callee } = node;
18949
19057
  if (callee.type === "Identifier") return hookIdentifiers.has(callee.name);
18950
- if (callee.type === "MemberExpression" && !callee.computed && callee.object.type === "Identifier" && callee.property.type === "Identifier") return reactNamespaces.has(callee.object.name) && hookNames.has(callee.property.name);
19058
+ const memberNames = getNamespacedCallNames(callee);
19059
+ if (memberNames !== void 0) return reactNamespaces.has(memberNames.objectName) && hookNames.has(memberNames.propertyName);
18951
19060
  return false;
18952
19061
  }
18953
19062
  function getFunctionName$1(node) {
@@ -19269,7 +19378,8 @@ function buildFunctionContext(node, propertyCallbackPrefixes, functionId, isCust
19269
19378
  function isPropertyCallbackCall(callExpression, functionContext, propertyCallbackPrefixes) {
19270
19379
  const { callee } = callExpression;
19271
19380
  if (callee.type === "Identifier") return functionContext.propertyCallbackIdentifiers.has(callee.name);
19272
- if (callee.type === "MemberExpression" && !callee.computed && callee.object.type === "Identifier" && callee.property.type === "Identifier") return functionContext.propertyObjectName !== void 0 && callee.object.name === functionContext.propertyObjectName && hasPrefix(callee.property.name, propertyCallbackPrefixes);
19381
+ const memberNames = getNamespacedCallNames(callee);
19382
+ if (memberNames !== void 0) return functionContext.propertyObjectName !== void 0 && memberNames.objectName === functionContext.propertyObjectName && hasPrefix(memberNames.propertyName, propertyCallbackPrefixes);
19273
19383
  return false;
19274
19384
  }
19275
19385
  function hasDependencyIdentifier(callExpression, name) {
@@ -19319,7 +19429,8 @@ function collectSetterCalls(statements, stateSetterIdentifiers) {
19319
19429
  function isAllowedPropertyCallbackCall(callExpression, propertyCallbackIdentifiers) {
19320
19430
  const { callee } = callExpression;
19321
19431
  if (callee.type === "Identifier") return propertyCallbackIdentifiers.has(callee.name);
19322
- return callee.type === "MemberExpression" && !callee.computed && callee.object.type === "Identifier" && callee.property.type === "Identifier" && propertyCallbackIdentifiers.has(callee.object.name);
19432
+ const memberNames = getNamespacedCallNames(callee);
19433
+ return memberNames !== void 0 && propertyCallbackIdentifiers.has(memberNames.objectName);
19323
19434
  }
19324
19435
  function hasNonSetterSideEffect(statements, stateSetterIdentifiers, propertyCallbackIdentifiers) {
19325
19436
  for (const statement of statements) {
@@ -19357,8 +19468,7 @@ function hasOnlyLogCalls(statements) {
19357
19468
  return hasOnlyNestedStatementsMatching(statements, (statement) => {
19358
19469
  const callExpression = getCallExpressionFromStatement(statement);
19359
19470
  if (callExpression === void 0) return false;
19360
- if (callExpression.callee.type === "MemberExpression" && !callExpression.callee.computed && callExpression.callee.object.type === "Identifier" && callExpression.callee.object.name === "console" && callExpression.callee.property.type === "Identifier") return true;
19361
- return false;
19471
+ return getNamespacedCallNames(callExpression.callee)?.objectName === "console";
19362
19472
  });
19363
19473
  }
19364
19474
  const SUBSCRIBE_METHODS = new Set([
@@ -19371,8 +19481,8 @@ function hasExternalStorePattern(statements) {
19371
19481
  return statements.some((statement) => {
19372
19482
  const callExpression = getCallExpressionFromStatement(statement);
19373
19483
  if (callExpression === void 0) return false;
19374
- if (callExpression.callee.type === "MemberExpression" && !callExpression.callee.computed && callExpression.callee.property.type === "Identifier") return SUBSCRIBE_METHODS.has(callExpression.callee.property.name);
19375
- return false;
19484
+ const propertyName = getNonComputedCalleePropertyName(callExpression.callee);
19485
+ return propertyName !== void 0 && SUBSCRIBE_METHODS.has(propertyName);
19376
19486
  });
19377
19487
  }
19378
19488
  function isRefCurrentArgument(argument, referenceIdentifiers) {
@@ -20080,7 +20190,7 @@ function objectExpressionMatches(sourceCode, expression, predicate) {
20080
20190
  if (unwrapped.type === "ObjectExpression") return predicate(unwrapped);
20081
20191
  if (unwrapped.type !== "Identifier") return false;
20082
20192
  const variable = getVariableByName(sourceCode.getScope(unwrapped), unwrapped.name);
20083
- if (variable === void 0 || !isModuleLevelScope$1(variable.scope) || isImportBinding(variable)) return false;
20193
+ if (variable === void 0 || !isModuleLevelScope(variable.scope) || isImportBinding(variable)) return false;
20084
20194
  for (const definition of variable.defs) {
20085
20195
  const initializer = getConstInitializer(definition);
20086
20196
  if (initializer === void 0) continue;
@@ -20283,7 +20393,7 @@ const preferClassProperties = defineRule({
20283
20393
  //#endregion
20284
20394
  //#region src/rules/prefer-constant-dispatch.ts
20285
20395
  function isModuleScopeConst(variable) {
20286
- if (!isModuleLevelScope$1(variable.scope)) return false;
20396
+ if (!isModuleLevelScope(variable.scope)) return false;
20287
20397
  for (const definition of variable.defs) {
20288
20398
  if (definition.type !== "Variable") continue;
20289
20399
  const declarator = definition.node;
@@ -20302,7 +20412,7 @@ function resolvesToConstantIdentifier(sourceCode, identifier) {
20302
20412
  function resolvesToModuleScopeBinding(sourceCode, identifier) {
20303
20413
  const variable = getVariableByName(sourceCode.getScope(identifier), identifier.name);
20304
20414
  if (variable === void 0) return false;
20305
- return isImportBinding(variable) || isModuleLevelScope$1(variable.scope);
20415
+ return isImportBinding(variable) || isModuleLevelScope(variable.scope);
20306
20416
  }
20307
20417
  function isConstantMemberExpression(sourceCode, memberExpression) {
20308
20418
  let current = memberExpression;
@@ -20721,7 +20831,7 @@ function getContextStackReplacement(componentName, chain, sourceCode) {
20721
20831
  const preferContextStack = defineRule({
20722
20832
  create(context) {
20723
20833
  const { filename, sourceCode } = context;
20724
- /* v8 ignore start -- @preserve RuleTester/runtime filenames are present; empty filename is a defensive host guard. */
20834
+ /* v8 ignore start -- @preserve rule harness/runtime filenames are present; empty filename is a defensive host guard. */
20725
20835
  const discoveredContextStack = filename === "" ? { found: false } : discoverLocalComponent(filename, CONTEXT_STACK_COMPONENT);
20726
20836
  /* v8 ignore stop -- @preserve */
20727
20837
  const contextStackIdentifiers = /* @__PURE__ */ new Set();
@@ -21018,7 +21128,7 @@ function validateAssertionCall(context, assertionCall, deterministic, hasIndeter
21018
21128
  return;
21019
21129
  }
21020
21130
  const [firstArgument] = assertionCall.arguments;
21021
- if (firstArgument === void 0 || firstArgument.type === "SpreadElement" || !isNumericLiteral$1(firstArgument)) {
21131
+ if (firstArgument === void 0 || firstArgument.type === "SpreadElement" || !isNumericLiteral(firstArgument)) {
21022
21132
  context.report({
21023
21133
  messageId: "assertionsRequiresNumberArgument",
21024
21134
  node: assertionCall
@@ -21124,11 +21234,16 @@ function normalizeAdditionalStaticFactories(rawOptions) {
21124
21234
  return new Set(additionalStaticFactories);
21125
21235
  }
21126
21236
  function isJavaScriptXmlElementAssignedToModuleConst(context, node) {
21127
- const { parent } = node;
21128
- if (parent.type !== "VariableDeclarator" || parent.id.type !== "Identifier" || parent.init !== node) return false;
21129
- const variable = getVariableByName(context.sourceCode.getScope(node), parent.id.name);
21237
+ let current = node;
21238
+ let { parent } = current;
21239
+ while (parent.type === "ParenthesizedExpression") {
21240
+ current = parent;
21241
+ ({parent} = current);
21242
+ }
21243
+ if (parent.type !== "VariableDeclarator" || parent.id.type !== "Identifier" || parent.init !== current) return false;
21244
+ const variable = getVariableByName(context.sourceCode.getScope(current), parent.id.name);
21130
21245
  /* v8 ignore start -- @preserve module const declarators have a matching scope variable. */
21131
- return variable === void 0 ? false : isModuleLevelScope$1(variable.scope);
21246
+ return variable === void 0 ? false : isModuleLevelScope(variable.scope);
21132
21247
  /* v8 ignore stop -- @preserve */
21133
21248
  }
21134
21249
  function isStaticAttributeValue(context, attribute, seen, staticOptions) {
@@ -21176,9 +21291,9 @@ function isInsideHoistedJsxElement(context, node) {
21176
21291
  if (parent.type === "VariableDeclarator" && parent.id.type === "Identifier" && parent.init === current) {
21177
21292
  const variable = getVariableByName(context.sourceCode.getScope(current), parent.id.name);
21178
21293
  /* v8 ignore next -- @preserve module-level JSX declarators have scope variables in parser scopes. */
21179
- if (variable !== void 0 && isModuleLevelScope$1(variable.scope)) return true;
21294
+ if (variable !== void 0 && isModuleLevelScope(variable.scope)) return true;
21180
21295
  }
21181
- if (parent.type === "JSXElement" || parent.type === "JSXFragment") current = parent;
21296
+ if (parent.type === "JSXElement" || parent.type === "JSXFragment" || parent.type === "ParenthesizedExpression") current = parent;
21182
21297
  ({parent} = parent);
21183
21298
  }
21184
21299
  return false;
@@ -21233,6 +21348,7 @@ const STATIC_OPTIONS = { staticGlobalFactories: new Set(DEFAULT_STATIC_GLOBAL_FA
21233
21348
  function getAttributeExpression(node) {
21234
21349
  const { value } = node;
21235
21350
  if (value?.type !== "JSXExpressionContainer") return void 0;
21351
+ /* v8 ignore next -- @preserve Oxc only produces JSXEmptyExpression here for rejected parse-error cases. */
21236
21352
  if (value.expression.type === "JSXEmptyExpression") return void 0;
21237
21353
  return value.expression;
21238
21354
  }
@@ -21240,6 +21356,8 @@ function isJsxElementAssignedToModuleConst(context, node) {
21240
21356
  let current = node;
21241
21357
  while (true) {
21242
21358
  const { parent } = current;
21359
+ /* v8 ignore next -- @preserve decorated parser ASTs keep JSX ancestors attached until traversal stops. */
21360
+ if (parent === null) return false;
21243
21361
  if (parent.type === "VariableDeclarator") return isModuleConstDeclaration(context, node, parent, current);
21244
21362
  const nextParent = getWalkableJsxParent(parent);
21245
21363
  if (nextParent === void 0) return false;
@@ -21247,7 +21365,7 @@ function isJsxElementAssignedToModuleConst(context, node) {
21247
21365
  }
21248
21366
  }
21249
21367
  function getWalkableJsxParent(parent) {
21250
- if (parent.type === "JSXElement" || parent.type === "JSXFragment" || parent.type === "JSXExpressionContainer" || parent.type === "ArrayExpression") return parent;
21368
+ if (parent.type === "JSXElement" || parent.type === "JSXFragment" || parent.type === "JSXExpressionContainer" || parent.type === "ParenthesizedExpression" || parent.type === "ArrayExpression") return parent;
21251
21369
  }
21252
21370
  function isModuleConstDeclaration(context, node, parent, current) {
21253
21371
  /* v8 ignore next -- @preserve non-identifier module bindings cannot be referenced as JSX constants. */
@@ -21255,7 +21373,7 @@ function isModuleConstDeclaration(context, node, parent, current) {
21255
21373
  /* v8 ignore next -- @preserve walkable JSX parents are followed only through initializer positions. */
21256
21374
  if (parent.init !== current) return false;
21257
21375
  const variable = getVariableByName(context.sourceCode.getScope(node), parent.id.name);
21258
- return variable !== void 0 && isModuleLevelScope$1(variable.scope);
21376
+ return variable !== void 0 && isModuleLevelScope(variable.scope);
21259
21377
  }
21260
21378
  function reportHoistableObject(context, objectExpression) {
21261
21379
  const objectText = context.sourceCode.getText(objectExpression);
@@ -21308,8 +21426,13 @@ const preferHoistedJsxObjectProperties = defineRule({
21308
21426
  function isSimpleReceiver({ type }) {
21309
21427
  return type === "Identifier" || type === "MemberExpression" || type === "CallExpression" || type === "NewExpression" || type === "ThisExpression";
21310
21428
  }
21429
+ function stripParenthesizedExpression$1(expression) {
21430
+ let current = expression;
21431
+ while (current.type === "ParenthesizedExpression") current = current.expression;
21432
+ return current;
21433
+ }
21311
21434
  const preferIdiv = defineRule({
21312
- create(context) {
21435
+ createOnce(context) {
21313
21436
  return { CallExpression(node) {
21314
21437
  if (node.optional) return;
21315
21438
  const callee = unwrapExpression(node.callee);
@@ -21321,9 +21444,9 @@ const preferIdiv = defineRule({
21321
21444
  const expression = unwrapExpression(argument);
21322
21445
  if (expression.type !== "BinaryExpression" || expression.operator !== "/") return;
21323
21446
  const left = unwrapExpression(expression.left);
21324
- const leftText = context.sourceCode.getText(expression.left);
21447
+ const leftText = context.sourceCode.getText(stripParenthesizedExpression$1(expression.left));
21325
21448
  const receiverText = isSimpleReceiver(left) ? leftText : `(${leftText})`;
21326
- const rightText = context.sourceCode.getText(expression.right);
21449
+ const rightText = context.sourceCode.getText(stripParenthesizedExpression$1(expression.right));
21327
21450
  context.report({
21328
21451
  fix: (fixer) => fixer.replaceText(node, `${receiverText}.idiv(${rightText})`),
21329
21452
  messageId: "useIdiv",
@@ -21406,7 +21529,7 @@ function getPortalReplacement(componentName, node, sourceCode) {
21406
21529
  const preferLocalPortalComponent = defineRule({
21407
21530
  create(context) {
21408
21531
  const { filename, sourceCode } = context;
21409
- /* v8 ignore start -- @preserve RuleTester/runtime filenames are present; empty filename is a defensive host guard. */
21532
+ /* v8 ignore start -- @preserve rule harness/runtime filenames are present; empty filename is a defensive host guard. */
21410
21533
  const discoveredPortal = filename === "" ? { found: false } : discoverLocalComponent(filename, PORTAL_COMPONENT);
21411
21534
  /* v8 ignore stop -- @preserve */
21412
21535
  const availablePortalIdentifiers = /* @__PURE__ */ new Set();
@@ -21480,6 +21603,7 @@ function isKnownNonNumberIdentifier(sourceCode, identifier) {
21480
21603
  return false;
21481
21604
  }
21482
21605
  function isKnownNonNumberExpression(sourceCode, expression) {
21606
+ if (expression.type === "ParenthesizedExpression") return isKnownNonNumberExpression(sourceCode, expression.expression);
21483
21607
  if (expression.type === "TSAsExpression" || expression.type === "TSTypeAssertion") return !isNumberTypeAnnotation(expression.typeAnnotation);
21484
21608
  /* v8 ignore next -- @preserve literal non-number cases are covered by direct literal tests. */
21485
21609
  if (isKnownNonNumberLiteral(expression)) return true;
@@ -21489,9 +21613,15 @@ function isKnownNonNumberExpression(sourceCode, expression) {
21489
21613
  function getComparableText(sourceCode, expression) {
21490
21614
  return sourceCode.getText(unwrapExpression(expression));
21491
21615
  }
21616
+ function stripParenthesizedExpression(expression) {
21617
+ let current = expression;
21618
+ while (current.type === "ParenthesizedExpression") current = current.expression;
21619
+ return current;
21620
+ }
21492
21621
  function getMathArgumentText(sourceCode, expression) {
21493
- if (expression.type === "SequenceExpression") return `(${sourceCode.getText(expression)})`;
21494
- return sourceCode.getText(expression);
21622
+ const unwrapped = stripParenthesizedExpression(expression);
21623
+ if (unwrapped.type === "SequenceExpression") return `(${sourceCode.getText(unwrapped)})`;
21624
+ return sourceCode.getText(unwrapped);
21495
21625
  }
21496
21626
  function getPreferredMathMethod(sourceCode, node) {
21497
21627
  if (node.test.type !== "BinaryExpression") return void 0;
@@ -21870,7 +22000,7 @@ function getEnumMemberName(node) {
21870
22000
  return IS_INTEGER.test(node.id.value) ? void 0 : node.id.value;
21871
22001
  }
21872
22002
  const preferPascalCaseEnums = defineRule({
21873
- create(context) {
22003
+ createOnce(context) {
21874
22004
  return {
21875
22005
  TSEnumDeclaration(node) {
21876
22006
  const identifier = node.id.name;
@@ -21905,7 +22035,7 @@ const preferPascalCaseEnums = defineRule({
21905
22035
  //#endregion
21906
22036
  //#region src/rules/prefer-sequence-overloads.ts
21907
22037
  function isNumericLiteralValue(node, value) {
21908
- return isNumericLiteral$1(node) && node.value === value;
22038
+ return isNumericLiteral(node) && node.value === value;
21909
22039
  }
21910
22040
  function getSequenceKeypointName(sequenceName) {
21911
22041
  if (sequenceName === "ColorSequence") return "ColorSequenceKeypoint";
@@ -21957,7 +22087,7 @@ function getKeypointArrayReplacement(context, node, sequenceName, keypointName)
21957
22087
  };
21958
22088
  }
21959
22089
  const preferSequenceOverloads = defineRule({
21960
- create(context) {
22090
+ createOnce(context) {
21961
22091
  return { NewExpression(node) {
21962
22092
  if (node.callee.type !== "Identifier") return;
21963
22093
  const sequenceName = node.callee.name;
@@ -22284,7 +22414,7 @@ function isPlural(identifier) {
22284
22414
  return lastToken !== void 0 && isPluralWord(lastToken.lowercased, lastToken.original);
22285
22415
  }
22286
22416
  const preferSingularEnums = defineRule({
22287
- create(context) {
22417
+ createOnce(context) {
22288
22418
  return { TSEnumDeclaration({ id }) {
22289
22419
  const { name } = id;
22290
22420
  if (!isPlural(name)) return;
@@ -22310,9 +22440,6 @@ const preferSingularEnums = defineRule({
22310
22440
  function canRender(node) {
22311
22441
  return node.type === "JSXElement" || node.type === "JSXFragment";
22312
22442
  }
22313
- function isExpressionNode(node) {
22314
- return node.type !== "PrivateIdentifier";
22315
- }
22316
22443
  function areEquivalentExpressionOrSuper(left, right, sourceCode) {
22317
22444
  if (left.type === "Super" || right.type === "Super") return left.type === "Super" && right.type === "Super";
22318
22445
  return areEquivalentExpression(left, right, sourceCode);
@@ -22962,7 +23089,7 @@ function countCaptureGroups(replacement) {
22962
23089
  if (dollarReferences === null) return 0;
22963
23090
  let maxGroup = 0;
22964
23091
  for (const dollarReference of dollarReferences) {
22965
- const groupNumber = Number.parseInt(dollarReference.slice(1), 10);
23092
+ const groupNumber = Math.trunc(Number(dollarReference.slice(1)));
22966
23093
  if (groupNumber > maxGroup) maxGroup = groupNumber;
22967
23094
  }
22968
23095
  return maxGroup;
@@ -23372,18 +23499,18 @@ function isDefaultOrNamespaceImportName(identifier) {
23372
23499
  if (isImportDefaultSpecifier(parent) && parent.local === identifier || isImportNamespaceSpecifier(parent) && parent.local === identifier) return true;
23373
23500
  if (isImportSpecifier$1(parent) && parent.local === identifier) {
23374
23501
  const { imported } = parent;
23375
- if (isIdentifierName$1(imported) && imported.name === "default") return true;
23502
+ if (isIdentifierName(imported) && imported.name === "default") return true;
23376
23503
  }
23377
- return isVariableDeclarator$1(parent) && parent.id === identifier && parent.init !== null && isStaticRequire(parent.init);
23504
+ return isVariableDeclarator(parent) && parent.id === identifier && parent.init !== null && isStaticRequire(parent.init);
23378
23505
  }
23379
23506
  function isExportedIdentifier(identifier) {
23380
23507
  /* v8 ignore next -- parser-produced identifiers in this rule always expose a name. @preserve */
23381
23508
  if (!hasName(identifier)) return false;
23382
23509
  const { parent } = identifier;
23383
- if (isVariableDeclarator$1(parent) && parent.id === identifier) {
23510
+ if (isVariableDeclarator(parent) && parent.id === identifier) {
23384
23511
  const declaration = parent.parent;
23385
23512
  /* v8 ignore next -- variable declarator definitions are always parented by a variable declaration. @preserve */
23386
- return isVariableDeclaration$1(declaration) ? isExportNamedDeclaration(declaration.parent) : false;
23513
+ return isVariableDeclaration(declaration) ? isExportNamedDeclaration(declaration.parent) : false;
23387
23514
  }
23388
23515
  if (isFunctionDeclaration(parent) && parent.id === identifier) return isExportNamedDeclaration(parent.parent);
23389
23516
  if (isClass(parent) && parent.id === identifier) return isExportNamedDeclaration(parent.parent);
@@ -23434,16 +23561,16 @@ function getImportSource(definition) {
23434
23561
  if (definition.type === "ImportBinding") {
23435
23562
  const { parent } = definition;
23436
23563
  /* v8 ignore else -- parser import bindings retain their ImportDeclaration parent. @preserve */
23437
- if (parent !== null && isImportDeclaration(parent) && isStringLiteral$1(parent.source)) return parent.source.value;
23564
+ if (parent !== null && isImportDeclaration(parent) && isStringLiteral(parent.source)) return parent.source.value;
23438
23565
  }
23439
23566
  /* v8 ignore next -- variable import checks only reach require-backed variable definitions. @preserve */
23440
23567
  if (definition.type === "Variable") {
23441
23568
  const { node } = definition;
23442
23569
  /* v8 ignore else -- callers only ask for sources from static require declarators. @preserve */
23443
- if (isVariableDeclarator$1(node) && node.init !== null && isStaticRequire(node.init)) {
23570
+ if (isVariableDeclarator(node) && node.init !== null && isStaticRequire(node.init)) {
23444
23571
  const [argument] = node.init.arguments;
23445
23572
  /* v8 ignore next -- static require recognition requires a string literal source. @preserve */
23446
- if (argument !== void 0 && isStringLiteral$1(argument)) return argument.value;
23573
+ if (argument !== void 0 && isStringLiteral(argument)) return argument.value;
23447
23574
  }
23448
23575
  }
23449
23576
  }
@@ -23501,9 +23628,9 @@ function shouldSkipVariable(definition, definitionName, options) {
23501
23628
  function getSpecialCaseReplacement(variable) {
23502
23629
  if (variable.name !== "plr") return void 0;
23503
23630
  const [definition] = variable.defs;
23504
- if (definition?.type !== "Variable" || !isVariableDeclarator$1(definition.node) || definition.node.init === null) return;
23631
+ if (definition?.type !== "Variable" || !isVariableDeclarator(definition.node) || definition.node.init === null) return;
23505
23632
  const { init } = definition.node;
23506
- if (isMemberExpression(init) && !init.computed && isIdentifierName$1(init.object) && init.object.name === "Players" && isIdentifierName$1(init.property) && init.property.name === "LocalPlayer") return "localPlayer";
23633
+ if (isMemberExpression(init) && !init.computed && isIdentifierName(init.object) && init.object.name === "Players" && isIdentifierName(init.property) && init.property.name === "LocalPlayer") return "localPlayer";
23507
23634
  }
23508
23635
  function computeSafeSamples(samples, scopes, isSafeNameForVariable, options) {
23509
23636
  const safeSamples = new Array();
@@ -23525,7 +23652,7 @@ function computeSafeSamples(samples, scopes, isSafeNameForVariable, options) {
23525
23652
  };
23526
23653
  }
23527
23654
  function createIsSafeNameForVariable(definition, variable, isSafeGeneratedName) {
23528
- const avoidArgumentsReplacement = definition.type === "Variable" && isVariableDeclarator$1(definition.node) && definition.node.init === null;
23655
+ const avoidArgumentsReplacement = definition.type === "Variable" && isVariableDeclarator(definition.node) && definition.node.init === null;
23529
23656
  const avoidArgumentsInArrowParameter = definition.type === "Parameter" && variable.scope.type === "function" && variable.scope.block.type === "ArrowFunctionExpression";
23530
23657
  const shouldAvoidArguments = avoidArgumentsReplacement || avoidArgumentsInArrowParameter;
23531
23658
  return (name, scopes) => {
@@ -23552,7 +23679,7 @@ function checkVariable(variable, options, scopeToNamesGeneratedByFixer, isSafeGe
23552
23679
  if (definition === void 0) return;
23553
23680
  const definitionName = definition.name;
23554
23681
  /* v8 ignore next -- parser variable definitions in this rule expose identifier names. @preserve */
23555
- if (!isIdentifierName$1(definitionName)) return;
23682
+ if (!isIdentifierName(definitionName)) return;
23556
23683
  if (shouldSkipVariable(definition, definitionName, options)) return;
23557
23684
  const isSafeNameForVariable = createIsSafeNameForVariable(definition, variable, isSafeGeneratedName);
23558
23685
  const specialCaseReplacement = getSpecialCaseReplacement(variable);
@@ -23598,7 +23725,7 @@ function checkPossiblyWeirdClassVariable(variable, variableChecker) {
23598
23725
  }
23599
23726
  const definitionName = definition.name;
23600
23727
  /* v8 ignore next -- parser class-name definitions expose identifier names. @preserve */
23601
- if (!isIdentifierName$1(definitionName)) {
23728
+ if (!isIdentifierName(definitionName)) {
23602
23729
  variableChecker(variable);
23603
23730
  return;
23604
23731
  }
@@ -23649,7 +23776,7 @@ function getFixablePropertyReplacement(node, samples) {
23649
23776
  if (samples?.length !== 1 || !isObjectPropertyKey(node)) return void 0;
23650
23777
  const [replacement] = samples;
23651
23778
  const { parent } = node;
23652
- if (replacement !== void 0 && isProperty(parent) && isStringLiteral$1(parent.value) && isValidIdentifier(replacement)) return replacement;
23779
+ if (replacement !== void 0 && isProperty(parent) && isStringLiteral(parent.value) && isValidIdentifier(replacement)) return replacement;
23653
23780
  }
23654
23781
  const preventAbbreviations = defineRule({
23655
23782
  create(context) {
@@ -25275,36 +25402,27 @@ function isAssignedJSXValue(node) {
25275
25402
  if (parent.type === "AssignmentExpression") return parent.right === current;
25276
25403
  return false;
25277
25404
  }
25278
- function isTernaryJSXChild(node) {
25405
+ function isJSXChildWrappedBy(node, wrapperType) {
25279
25406
  let current = getParent(node);
25280
25407
  /* v8 ignore next -- @preserve visited JSX nodes have parent links in parser-produced ASTs. */
25281
25408
  if (current === void 0) return false;
25282
- let foundTernary = false;
25283
- while (current !== void 0 && (current.type === "ConditionalExpression" || WRAPPER_PARENT_TYPES.has(current.type))) {
25284
- if (current.type === "ConditionalExpression") foundTernary = true;
25409
+ let foundWrapper = false;
25410
+ while (current !== void 0 && (current.type === wrapperType || WRAPPER_PARENT_TYPES.has(current.type))) {
25411
+ /* v8 ignore else -- @preserve current parser output keeps wrapped JSX operands attached directly to the wrapper here. */
25412
+ if (current.type === wrapperType) foundWrapper = true;
25285
25413
  current = getParent(current);
25286
25414
  }
25287
- if (!foundTernary || current?.type !== "JSXExpressionContainer") return false;
25415
+ if (!foundWrapper || current?.type !== "JSXExpressionContainer") return false;
25288
25416
  const containerParent = getParent(current);
25289
25417
  /* v8 ignore next -- @preserve parser-produced JSX expression containers are attached to a parent. */
25290
25418
  if (containerParent === void 0) return false;
25291
25419
  return containerParent.type === "JSXElement" || containerParent.type === "JSXFragment";
25292
25420
  }
25421
+ function isTernaryJSXChild(node) {
25422
+ return isJSXChildWrappedBy(node, "ConditionalExpression");
25423
+ }
25293
25424
  function isLogicalJSXChild(node) {
25294
- let current = getParent(node);
25295
- /* v8 ignore next -- @preserve visited JSX nodes have parent links in parser-produced ASTs. */
25296
- if (current === void 0) return false;
25297
- let foundLogical = false;
25298
- while (current !== void 0 && (current.type === "LogicalExpression" || WRAPPER_PARENT_TYPES.has(current.type))) {
25299
- /* v8 ignore else -- @preserve current parser output keeps logical JSX operands attached directly to LogicalExpression here. */
25300
- if (current.type === "LogicalExpression") foundLogical = true;
25301
- current = getParent(current);
25302
- }
25303
- if (!foundLogical || current?.type !== "JSXExpressionContainer") return false;
25304
- const containerParent = getParent(current);
25305
- /* v8 ignore next -- @preserve parser-produced JSX expression containers are attached to a parent. */
25306
- if (containerParent === void 0) return false;
25307
- return containerParent.type === "JSXElement" || containerParent.type === "JSXFragment";
25425
+ return isJSXChildWrappedBy(node, "LogicalExpression");
25308
25426
  }
25309
25427
  const requireReactComponentKeys = defineRule({
25310
25428
  create(context) {
@@ -25613,7 +25731,7 @@ function getEnclosingFunctionName(node) {
25613
25731
  }
25614
25732
  function getAssignedName({ parent }) {
25615
25733
  if (parent?.type === "VariableDeclarator" && parent.id.type === "Identifier") return parent.id.name;
25616
- if (parent?.type === "PropertyDefinition" || parent?.type === "Property" || parent?.type === "MethodDefinition") {
25734
+ if (parent?.type === "PropertyDefinition" || parent?.type === "MethodDefinition") {
25617
25735
  if (parent.key.type === "PrivateIdentifier") return `#${parent.key.name}`;
25618
25736
  /* v8 ignore next -- @preserve class and object member keys are identifiers after private keys are handled. */
25619
25737
  if (parent.key.type === "Identifier") return parent.key.name;
@@ -25707,7 +25825,7 @@ const requireThrowErrorCapture = defineRule({
25707
25825
  create(context) {
25708
25826
  const { sourceCode } = context;
25709
25827
  const allowList = context.options[0]?.allow ?? [];
25710
- /* v8 ignore next -- @preserve RuleTester and Oxlint provide a physical filename for rule execution. */
25828
+ /* v8 ignore next -- @preserve the rule harness and Oxlint provide a physical filename for rule execution. */
25711
25829
  const physicalFilename = context.physicalFilename ?? "<input>";
25712
25830
  return { ThrowStatement(node) {
25713
25831
  const { argument } = node;
@@ -25801,7 +25919,7 @@ function isNotSpread(node) {
25801
25919
  return node.type !== "SpreadElement";
25802
25920
  }
25803
25921
  const requireUnicodeRegex = defineRule({
25804
- create(context) {
25922
+ createOnce(context) {
25805
25923
  return { CallExpression(node) {
25806
25924
  if (!isIdentifierWithName(node.callee, "regex")) return;
25807
25925
  if (node.arguments.length < 2) {
@@ -25843,9 +25961,9 @@ function reportEmptyDefaultValue(context, defaultValue) {
25843
25961
  function checkParameterDefaults(context, parameters) {
25844
25962
  for (const parameter of parameters) {
25845
25963
  if (parameter.type === "AssignmentPattern" && parameter.left.type === "ObjectPattern") {
25964
+ checkObjectPatternDefaults(context, parameter.left);
25846
25965
  /* v8 ignore next -- @preserve assignment pattern defaults are parser expression nodes. */
25847
25966
  if (isNode$1(parameter.right)) reportEmptyDefaultValue(context, parameter.right);
25848
- checkObjectPatternDefaults(context, parameter.left);
25849
25967
  continue;
25850
25968
  }
25851
25969
  if (parameter.type !== "ObjectPattern") continue;
@@ -26126,8 +26244,12 @@ function getHookName(node) {
26126
26244
  function getMemberExpressionDepth(node) {
26127
26245
  let depth = 0;
26128
26246
  let current = node;
26129
- if (current.type === "ChainExpression") current = current.expression;
26130
- while (current.type === "MemberExpression") {
26247
+ while (true) {
26248
+ if (current.type === "ChainExpression" || current.type === "ParenthesizedExpression" || current.type === "TSAsExpression" || current.type === "TSNonNullExpression" || current.type === "TSSatisfiesExpression" || current.type === "TSTypeAssertion") {
26249
+ current = current.expression;
26250
+ continue;
26251
+ }
26252
+ if (current.type !== "MemberExpression") break;
26131
26253
  depth += 1;
26132
26254
  current = current.object;
26133
26255
  }
@@ -26135,15 +26257,21 @@ function getMemberExpressionDepth(node) {
26135
26257
  }
26136
26258
  function getRootIdentifier(node) {
26137
26259
  let current = node;
26138
- if (current.type === "ChainExpression") current = current.expression;
26139
- while (current.type === "MemberExpression" || current.type === "TSNonNullExpression") current = current.type === "MemberExpression" ? current.object : current.expression;
26260
+ while (true) {
26261
+ if (current.type === "ChainExpression" || current.type === "ParenthesizedExpression" || current.type === "TSAsExpression" || current.type === "TSNonNullExpression" || current.type === "TSSatisfiesExpression" || current.type === "TSTypeAssertion") {
26262
+ current = current.expression;
26263
+ continue;
26264
+ }
26265
+ if (current.type !== "MemberExpression") break;
26266
+ current = current.object;
26267
+ }
26140
26268
  return current.type === "Identifier" ? current : void 0;
26141
26269
  }
26142
26270
  function collectIdentifierNames(node) {
26143
26271
  if (node.type === "Identifier") return [node.name];
26144
26272
  if (node.type === "MemberExpression") return collectIdentifierNames(node.object);
26145
26273
  if (node.type === "ChainExpression") return collectIdentifierNames(node.expression);
26146
- if (node.type === "TSNonNullExpression" || node.type === "TSAsExpression" || node.type === "TSSatisfiesExpression" || node.type === "TSTypeAssertion") return collectIdentifierNames(node.expression);
26274
+ if (node.type === "ParenthesizedExpression" || node.type === "TSNonNullExpression" || node.type === "TSAsExpression" || node.type === "TSSatisfiesExpression" || node.type === "TSTypeAssertion") return collectIdentifierNames(node.expression);
26147
26275
  if (node.type === "BinaryExpression" || node.type === "LogicalExpression") return [...collectIdentifierNames(node.left), ...collectIdentifierNames(node.right)];
26148
26276
  if (node.type === "UnaryExpression") return collectIdentifierNames(node.argument);
26149
26277
  if (node.type === "ConditionalExpression") return [
@@ -26158,7 +26286,7 @@ function isExpression(node) {
26158
26286
  }
26159
26287
  function nodeToSafeDependencyPath(node, sourceCode) {
26160
26288
  if (node.type === "Identifier") return node.name;
26161
- if (node.type === "ChainExpression" || isExpression(node)) return nodeToSafeDependencyPath(node.expression, sourceCode);
26289
+ if (node.type === "ChainExpression" || node.type === "ParenthesizedExpression" || isExpression(node)) return nodeToSafeDependencyPath(node.expression, sourceCode);
26162
26290
  /* v8 ignore next -- @preserve dependency path conversion only receives identifiers, chains, transparent TS wrappers, or member expressions. */
26163
26291
  if (node.type === "MemberExpression") {
26164
26292
  const objectPath = nodeToSafeDependencyPath(node.object, sourceCode);
@@ -26372,7 +26500,7 @@ function getCaptureInfo(current, name, variable, sourceCode) {
26372
26500
  };
26373
26501
  }
26374
26502
  function isTransparentExpressionNode(node) {
26375
- return node.type === "TSSatisfiesExpression" || node.type === "TSAsExpression" || node.type === "TSTypeAssertion" || node.type === "TSNonNullExpression";
26503
+ return node.type === "ParenthesizedExpression" || node.type === "TSSatisfiesExpression" || node.type === "TSAsExpression" || node.type === "TSTypeAssertion" || node.type === "TSNonNullExpression";
26376
26504
  }
26377
26505
  function visitChildNodes(current, sourceCode, visit) {
26378
26506
  /* v8 ignore next -- @preserve parser node types visited here have registered visitor keys. */
@@ -26433,7 +26561,7 @@ function parseDependencies(node, sourceCode) {
26433
26561
  for (const element of node.elements) {
26434
26562
  if (!element) continue;
26435
26563
  const actualNode = element.type === "SpreadElement" ? element.argument : element;
26436
- const name = sourceCode.getText(actualNode);
26564
+ const name = nodeToSafeDependencyPath(actualNode, sourceCode);
26437
26565
  const depth = getMemberExpressionDepth(actualNode);
26438
26566
  dependencies.push({
26439
26567
  depth,
@@ -26785,9 +26913,6 @@ function isReactHookName(name) {
26785
26913
  function getOptions(value) {
26786
26914
  return isRecord(value) ? value : {};
26787
26915
  }
26788
- function isIdentifierName(node) {
26789
- return node.type === "Identifier";
26790
- }
26791
26916
  function isComponentOrHook(node) {
26792
26917
  if ((node.type === "FunctionDeclaration" || node.type === "FunctionExpression") && node.id !== null) return isComponentName(node.id.name) || isReactHookName(node.id.name);
26793
26918
  const { parent } = node;
@@ -26906,6 +27031,7 @@ const smallRules = definePlugin({
26906
27031
  "no-recursive": noRecursive,
26907
27032
  "no-redundant-aspect-ratio-constraint": noRedundantAspectRatioConstraint,
26908
27033
  "no-render-helper-functions": noRenderHelperFunctions,
27034
+ "no-restricted-property-assignment": noRestrictedPropertyAssignment,
26909
27035
  "no-spec-file-extension": noSpecFileExtension,
26910
27036
  "no-static-react-create-element": noStaticReactCreateElement,
26911
27037
  "no-table-create-map": noTableCreateMap,