@pobammer-ts/eslint-cease-nonsense-rules 1.10.0 → 1.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -19767,14 +19767,414 @@ var preferPascalCaseEnums = {
19767
19767
  };
19768
19768
  var prefer_pascal_case_enums_default = preferPascalCaseEnums;
19769
19769
 
19770
- // src/rules/prefer-sequence-overloads.ts
19770
+ // src/utilities/pattern-replacement/pattern-matcher.ts
19771
+ import { AST_NODE_TYPES as AST_NODE_TYPES10 } from "@typescript-eslint/types";
19772
+
19773
+ // src/utilities/pattern-replacement/constant-folder.ts
19771
19774
  import { AST_NODE_TYPES as AST_NODE_TYPES9 } from "@typescript-eslint/types";
19775
+ function normalizeZero(num) {
19776
+ return Object.is(num, -0) ? 0 : num;
19777
+ }
19778
+ function unwrap(node) {
19779
+ switch (node.type) {
19780
+ case AST_NODE_TYPES9.TSAsExpression:
19781
+ case AST_NODE_TYPES9.TSNonNullExpression:
19782
+ return unwrap(node.expression);
19783
+ default:
19784
+ return node;
19785
+ }
19786
+ }
19787
+ function evaluateConstant(node) {
19788
+ const expression = unwrap(node);
19789
+ if (expression.type === AST_NODE_TYPES9.Literal && typeof expression.value === "number") {
19790
+ return normalizeZero(expression.value);
19791
+ }
19792
+ if (expression.type === AST_NODE_TYPES9.UnaryExpression) {
19793
+ const argument = evaluateConstant(expression.argument);
19794
+ if (argument === undefined)
19795
+ return;
19796
+ switch (expression.operator) {
19797
+ case "-":
19798
+ return normalizeZero(-argument);
19799
+ case "+":
19800
+ return normalizeZero(Number(argument));
19801
+ default:
19802
+ return;
19803
+ }
19804
+ }
19805
+ if (expression.type === AST_NODE_TYPES9.BinaryExpression) {
19806
+ if (expression.left.type === AST_NODE_TYPES9.PrivateIdentifier)
19807
+ return;
19808
+ const left = evaluateConstant(expression.left);
19809
+ const right = evaluateConstant(expression.right);
19810
+ if (left === undefined || right === undefined)
19811
+ return;
19812
+ let result;
19813
+ switch (expression.operator) {
19814
+ case "+":
19815
+ result = left + right;
19816
+ break;
19817
+ case "-":
19818
+ result = left - right;
19819
+ break;
19820
+ case "*":
19821
+ result = left * right;
19822
+ break;
19823
+ case "/":
19824
+ result = left / right;
19825
+ break;
19826
+ default:
19827
+ return;
19828
+ }
19829
+ return Number.isFinite(result) ? normalizeZero(result) : undefined;
19830
+ }
19831
+ return;
19832
+ }
19833
+
19834
+ // src/utilities/pattern-replacement/pattern-matcher.ts
19835
+ function buildPatternIndex(patterns2) {
19836
+ const index2 = new Map;
19837
+ for (const pattern4 of patterns2) {
19838
+ const key = pattern4.type === "constructor" ? `constructor:${pattern4.typeName}` : `staticMethod:${pattern4.typeName}:${pattern4.methodName}`;
19839
+ const existing = index2.get(key);
19840
+ if (existing)
19841
+ existing.push(pattern4);
19842
+ else
19843
+ index2.set(key, [pattern4]);
19844
+ }
19845
+ return index2;
19846
+ }
19847
+ function resolveCallee(node) {
19848
+ const callee = unwrap(node.callee);
19849
+ if (node.type === AST_NODE_TYPES10.NewExpression && callee.type === AST_NODE_TYPES10.Identifier) {
19850
+ return { kind: "constructor", typeName: callee.name };
19851
+ }
19852
+ if (node.type === AST_NODE_TYPES10.CallExpression) {
19853
+ const member = callee.type === AST_NODE_TYPES10.ChainExpression ? unwrap(callee.expression) : callee;
19854
+ if (member.type === AST_NODE_TYPES10.MemberExpression && !member.computed) {
19855
+ const object3 = unwrap(member.object);
19856
+ if (object3.type === AST_NODE_TYPES10.Identifier && member.property.type === AST_NODE_TYPES10.Identifier) {
19857
+ return {
19858
+ kind: "staticMethod",
19859
+ methodName: member.property.name,
19860
+ typeName: object3.name
19861
+ };
19862
+ }
19863
+ }
19864
+ }
19865
+ return { kind: "unknown" };
19866
+ }
19867
+ function captureParameter(node, sourceCode) {
19868
+ const expression = unwrap(node);
19869
+ const sourceText = sourceCode.getText(expression);
19870
+ const constValue = evaluateConstant(expression);
19871
+ let expressionKey;
19872
+ let isComplex = false;
19873
+ if (expression.type === AST_NODE_TYPES10.Literal && typeof expression.value === "number") {
19874
+ expressionKey = `literal:${normalizeZero(expression.value)}`;
19875
+ } else if (expression.type === AST_NODE_TYPES10.Identifier) {
19876
+ if (expression.name === "undefined")
19877
+ expressionKey = "undefined";
19878
+ else
19879
+ expressionKey = `id:${expression.name}`;
19880
+ } else if (constValue === undefined) {
19881
+ expressionKey = `complex:${sourceText}`;
19882
+ isComplex = true;
19883
+ } else
19884
+ expressionKey = `const:${constValue}`;
19885
+ if (constValue === undefined)
19886
+ return { expressionKey, isComplex, node: expression, sourceText };
19887
+ return { constValue, expressionKey, isComplex, node: expression, sourceText };
19888
+ }
19889
+ function matchParameters(patterns2, parameters3, sourceCode) {
19890
+ const captures = new Map;
19891
+ const optionalStart = patterns2.findIndex((parsedArg) => parsedArg.kind === "optional");
19892
+ const minimumParameters = optionalStart === -1 ? patterns2.length : optionalStart;
19893
+ if (parameters3.length < minimumParameters || parameters3.length > patterns2.length)
19894
+ return;
19895
+ for (let index2 = 0;index2 < patterns2.length; index2 += 1) {
19896
+ const pattern4 = patterns2[index2];
19897
+ if (pattern4 === undefined)
19898
+ continue;
19899
+ const parameter2 = parameters3[index2];
19900
+ const unwrappedParameter = parameter2 === undefined ? undefined : unwrap(parameter2);
19901
+ const isMissing = parameter2 === undefined || unwrappedParameter?.type === AST_NODE_TYPES10.Identifier && unwrappedParameter.name === "undefined";
19902
+ if (pattern4.kind === "literal") {
19903
+ if (isMissing)
19904
+ return;
19905
+ const captured = captureParameter(parameter2, sourceCode);
19906
+ if (captured.constValue !== pattern4.value)
19907
+ return;
19908
+ } else if (pattern4.kind === "optional") {
19909
+ if (isMissing)
19910
+ continue;
19911
+ const captured = captureParameter(parameter2, sourceCode);
19912
+ if (captured.constValue !== pattern4.value)
19913
+ return;
19914
+ } else if (pattern4.kind === "capture") {
19915
+ if (isMissing)
19916
+ return;
19917
+ const captured = captureParameter(parameter2, sourceCode);
19918
+ const captureName = pattern4.name;
19919
+ const existing = captures.get(captureName);
19920
+ if (existing !== undefined && existing.expressionKey !== captured.expressionKey)
19921
+ return;
19922
+ captures.set(captureName, captured);
19923
+ } else if (pattern4.kind === "wildcard" && isMissing)
19924
+ return;
19925
+ }
19926
+ return captures;
19927
+ }
19928
+ var CONDITION_PATTERN = regex2("^(?<operator>[!<>=]+)\\s*(?<target>.+)$");
19929
+ function parseCondition(condition) {
19930
+ const match = CONDITION_PATTERN.exec(condition);
19931
+ return match ? [match.groups.operator, match.groups.target] : ["==", "0"];
19932
+ }
19933
+ function evaluateConditions(conditions, captures) {
19934
+ for (const [name, condition] of conditions) {
19935
+ const captured = captures.get(name);
19936
+ if (captured?.constValue === undefined)
19937
+ return false;
19938
+ const value = captured.constValue;
19939
+ const [operator, targetStr] = parseCondition(condition);
19940
+ const target2 = Number.parseFloat(targetStr);
19941
+ if (!Number.isFinite(target2))
19942
+ return false;
19943
+ let passes;
19944
+ switch (operator) {
19945
+ case "!=":
19946
+ passes = value !== target2;
19947
+ break;
19948
+ case "==":
19949
+ passes = value === target2;
19950
+ break;
19951
+ case ">":
19952
+ passes = value > target2;
19953
+ break;
19954
+ case "<":
19955
+ passes = value < target2;
19956
+ break;
19957
+ case ">=":
19958
+ passes = value >= target2;
19959
+ break;
19960
+ case "<=":
19961
+ passes = value <= target2;
19962
+ break;
19963
+ default:
19964
+ passes = false;
19965
+ }
19966
+ if (!passes)
19967
+ return false;
19968
+ }
19969
+ return true;
19970
+ }
19971
+ function canSafelySubstitute(captures) {
19972
+ for (const [, captured] of captures)
19973
+ if (captured.isComplex)
19974
+ return false;
19975
+ return true;
19976
+ }
19977
+ // src/utilities/pattern-replacement/pattern-parser.ts
19978
+ var CONSTRUCTOR_PATTERN = regex2("^new\\s+(?<typeName>\\w+)\\((?<argumentsString>.*)\\)$");
19979
+ var STATIC_METHOD_PATTERN = regex2("^(?<typeName>\\w+)\\.(?<methodName>\\w+)\\((?<argumentsString>.*)\\)$");
19980
+ var STATIC_ACCESS_PATTERN = regex2("^(?<typeName>\\w+)\\.(?<property>\\w+)$");
19981
+ var CALL_PATTERN = regex2("^(?<name>\\w+)\\((?<argumentsString>.*)\\)$");
19982
+ function parseParameters(parametersString) {
19983
+ const trimmed = parametersString.trim();
19984
+ if (trimmed === "")
19985
+ return [];
19986
+ const parameters3 = trimmed.split(",").map((parameter2) => parameter2.trim());
19987
+ const result = new Array;
19988
+ let size = 0;
19989
+ for (const parameter2 of parameters3) {
19990
+ if (parameter2 === "_")
19991
+ result[size++] = { kind: "wildcard" };
19992
+ else if (parameter2.startsWith("$"))
19993
+ result[size++] = { kind: "capture", name: parameter2.slice(1) };
19994
+ else if (parameter2.endsWith("?")) {
19995
+ const value = Number.parseFloat(parameter2.slice(0, -1));
19996
+ result[size++] = { kind: "optional", value };
19997
+ } else {
19998
+ const value = Number.parseFloat(parameter2);
19999
+ result[size++] = { kind: "literal", value };
20000
+ }
20001
+ }
20002
+ return result;
20003
+ }
20004
+ function parseReplacement(replacement) {
20005
+ const staticMatch = STATIC_ACCESS_PATTERN.exec(replacement);
20006
+ if (staticMatch && !replacement.includes("("))
20007
+ return { ...staticMatch.groups, kind: "staticAccess" };
20008
+ const callMatch = CALL_PATTERN.exec(replacement);
20009
+ if (callMatch) {
20010
+ const { name, argumentsString } = callMatch.groups;
20011
+ const parameters3 = argumentsString.trim() === "" ? [] : argumentsString.split(",").map((value) => value.trim());
20012
+ return { kind: "call", name, parameters: parameters3 };
20013
+ }
20014
+ return { kind: "identifier", name: replacement };
20015
+ }
20016
+ function parsePattern(match, replacement, when) {
20017
+ const conditions = new Map;
20018
+ if (when)
20019
+ for (const [key, value] of Object.entries(when))
20020
+ conditions.set(key, value);
20021
+ const constructorMatch = CONSTRUCTOR_PATTERN.exec(match);
20022
+ if (constructorMatch) {
20023
+ const { typeName, argumentsString } = constructorMatch.groups;
20024
+ return {
20025
+ conditions,
20026
+ original: match,
20027
+ parameters: parseParameters(argumentsString),
20028
+ replacement: parseReplacement(replacement),
20029
+ type: "constructor",
20030
+ typeName
20031
+ };
20032
+ }
20033
+ const staticMethodMatch = STATIC_METHOD_PATTERN.exec(match);
20034
+ if (staticMethodMatch) {
20035
+ const { typeName, methodName, argumentsString } = staticMethodMatch.groups;
20036
+ return {
20037
+ conditions,
20038
+ methodName,
20039
+ original: match,
20040
+ parameters: parseParameters(argumentsString),
20041
+ replacement: parseReplacement(replacement),
20042
+ type: "staticMethod",
20043
+ typeName
20044
+ };
20045
+ }
20046
+ throw new Error(`Invalid pattern: ${match}`);
20047
+ }
20048
+ // src/utilities/pattern-replacement/pattern-types.ts
20049
+ function pattern4(configuration) {
20050
+ return configuration;
20051
+ }
20052
+ // src/utilities/pattern-replacement/replacement-generator.ts
20053
+ function getReplacementIdentifier(replacement) {
20054
+ switch (replacement.kind) {
20055
+ case "identifier":
20056
+ return replacement.name;
20057
+ case "call":
20058
+ return replacement.name;
20059
+ case "staticAccess":
20060
+ return;
20061
+ }
20062
+ }
20063
+ function generateReplacement(replacement, captures) {
20064
+ const { kind } = replacement;
20065
+ switch (kind) {
20066
+ case "identifier":
20067
+ return replacement.name;
20068
+ case "staticAccess":
20069
+ return `${replacement.typeName}.${replacement.property}`;
20070
+ case "call": {
20071
+ const parameters3 = replacement.parameters.map((argument) => {
20072
+ if (argument.startsWith("$")) {
20073
+ const captureName = argument.slice(1);
20074
+ const captured = captures.get(captureName);
20075
+ if (captured === undefined)
20076
+ throw new Error(`Missing capture: ${captureName}`);
20077
+ return captured.sourceText;
20078
+ }
20079
+ return argument;
20080
+ });
20081
+ return `${replacement.name}(${parameters3.join(", ")})`;
20082
+ }
20083
+ default:
20084
+ throw new Error(`Unknown replacement kind: ${kind}`);
20085
+ }
20086
+ }
20087
+ // src/rules/prefer-pattern-replacements.ts
20088
+ var isRuleOptions2 = Compile(build_default.Object({
20089
+ patterns: build_default.Array(build_default.Object({}, { additionalProperties: true }))
20090
+ }));
20091
+ function parsePatterns(patterns2) {
20092
+ return patterns2.map((pattern5) => parsePattern(pattern5.match, pattern5.replacement, pattern5.when));
20093
+ }
20094
+ var preferPatternReplacements = {
20095
+ create(context) {
20096
+ const validatedOptions = isRuleOptions2.Check(context.options[0]) ? context.options[0] : undefined;
20097
+ if (!validatedOptions || validatedOptions.patterns.length === 0)
20098
+ return {};
20099
+ const parsedPatterns = parsePatterns(validatedOptions.patterns);
20100
+ const patternIndex = buildPatternIndex(parsedPatterns);
20101
+ const { sourceCode } = context;
20102
+ function hasNameConflict(node, identifierName) {
20103
+ let scope = sourceCode.getScope(node);
20104
+ while (scope) {
20105
+ if (scope.set.has(identifierName))
20106
+ return true;
20107
+ scope = scope.upper ?? undefined;
20108
+ }
20109
+ return false;
20110
+ }
20111
+ function checkNode(node) {
20112
+ const resolved = resolveCallee(node);
20113
+ if (resolved.kind === "unknown")
20114
+ return;
20115
+ const key = resolved.kind === "constructor" ? `constructor:${resolved.typeName}` : `staticMethod:${resolved.typeName}:${resolved.methodName}`;
20116
+ const candidates2 = patternIndex.get(key);
20117
+ if (!candidates2 || candidates2.length === 0)
20118
+ return;
20119
+ for (const pattern5 of candidates2) {
20120
+ const captures = matchParameters(pattern5.parameters, node.arguments, sourceCode);
20121
+ if (!(captures && evaluateConditions(pattern5.conditions, captures) && canSafelySubstitute(captures))) {
20122
+ continue;
20123
+ }
20124
+ const replacementId = getReplacementIdentifier(pattern5.replacement);
20125
+ if (replacementId && hasNameConflict(node, replacementId))
20126
+ continue;
20127
+ const originalText = sourceCode.getText(node);
20128
+ const replacementText = generateReplacement(pattern5.replacement, captures);
20129
+ context.report({
20130
+ data: { original: originalText, replacement: replacementText },
20131
+ fix: (fixer) => fixer.replaceText(node, replacementText),
20132
+ messageId: "preferReplacement",
20133
+ node
20134
+ });
20135
+ return;
20136
+ }
20137
+ }
20138
+ return {
20139
+ CallExpression: checkNode,
20140
+ NewExpression: checkNode
20141
+ };
20142
+ },
20143
+ defaultOptions: [{ patterns: [] }],
20144
+ meta: {
20145
+ docs: {
20146
+ description: "Enforce using configured replacements for common constructor/method patterns",
20147
+ recommended: false
20148
+ },
20149
+ fixable: "code",
20150
+ messages: {
20151
+ preferReplacement: "Prefer '{{replacement}}' over '{{original}}'"
20152
+ },
20153
+ schema: [
20154
+ {
20155
+ additionalProperties: false,
20156
+ properties: {
20157
+ patterns: {
20158
+ items: { type: "object" },
20159
+ type: "array"
20160
+ }
20161
+ },
20162
+ type: "object"
20163
+ }
20164
+ ],
20165
+ type: "suggestion"
20166
+ }
20167
+ };
20168
+ var prefer_pattern_replacements_default = preferPatternReplacements;
20169
+
20170
+ // src/rules/prefer-sequence-overloads.ts
20171
+ import { AST_NODE_TYPES as AST_NODE_TYPES11 } from "@typescript-eslint/types";
19772
20172
  var sequenceDescriptors = [
19773
20173
  { keypointName: "ColorSequenceKeypoint", sequenceName: "ColorSequence" },
19774
20174
  { keypointName: "NumberSequenceKeypoint", sequenceName: "NumberSequence" }
19775
20175
  ];
19776
20176
  function isSequenceIdentifier(node) {
19777
- if (node.type !== AST_NODE_TYPES9.Identifier)
20177
+ if (node.type !== AST_NODE_TYPES11.Identifier)
19778
20178
  return false;
19779
20179
  for (const { sequenceName } of sequenceDescriptors)
19780
20180
  if (sequenceName === node.name)
@@ -19788,16 +20188,16 @@ function findDescriptor(sequenceName) {
19788
20188
  return;
19789
20189
  }
19790
20190
  var isNumericLiteral = Compile(build_default.Object({
19791
- type: build_default.Literal(AST_NODE_TYPES9.Literal),
20191
+ type: build_default.Literal(AST_NODE_TYPES11.Literal),
19792
20192
  value: build_default.Number()
19793
20193
  }));
19794
20194
  function isExpressionArgument(argument) {
19795
- return argument !== undefined && argument.type !== AST_NODE_TYPES9.SpreadElement;
20195
+ return argument !== undefined && argument.type !== AST_NODE_TYPES11.SpreadElement;
19796
20196
  }
19797
20197
  function extractKeypoint(element, descriptor) {
19798
- if (element === undefined || element.type !== AST_NODE_TYPES9.NewExpression)
20198
+ if (element === undefined || element.type !== AST_NODE_TYPES11.NewExpression)
19799
20199
  return;
19800
- if (element.callee.type !== AST_NODE_TYPES9.Identifier || element.callee.name !== descriptor.keypointName)
20200
+ if (element.callee.type !== AST_NODE_TYPES11.Identifier || element.callee.name !== descriptor.keypointName)
19801
20201
  return;
19802
20202
  if (element.arguments.length !== 2)
19803
20203
  return;
@@ -19827,7 +20227,7 @@ var preferSequenceOverloads = {
19827
20227
  if (descriptor === undefined || node.arguments.length !== 1)
19828
20228
  return;
19829
20229
  const [argument] = node.arguments;
19830
- if (argument === undefined || argument.type !== AST_NODE_TYPES9.ArrayExpression || argument.elements.length !== 2)
20230
+ if (argument === undefined || argument.type !== AST_NODE_TYPES11.ArrayExpression || argument.elements.length !== 2)
19831
20231
  return;
19832
20232
  const firstElement = argument.elements[0] ?? undefined;
19833
20233
  const secondElement = argument.elements[1] ?? undefined;
@@ -20173,16 +20573,16 @@ var preferUDim2Shorthand = {
20173
20573
  var prefer_udim2_shorthand_default = preferUDim2Shorthand;
20174
20574
 
20175
20575
  // src/rules/react-hooks-strict-return.ts
20176
- import { AST_NODE_TYPES as AST_NODE_TYPES10 } from "@typescript-eslint/utils";
20576
+ import { AST_NODE_TYPES as AST_NODE_TYPES12 } from "@typescript-eslint/utils";
20177
20577
  var MAX_RETURN_ELEMENTS = 2;
20178
20578
  var HOOK_PATTERN = /^use[A-Z0-9].*$/;
20179
20579
  function isHookNode(node) {
20180
20580
  let name;
20181
- if (node.type === AST_NODE_TYPES10.VariableDeclarator && node.id.type === AST_NODE_TYPES10.Identifier) {
20581
+ if (node.type === AST_NODE_TYPES12.VariableDeclarator && node.id.type === AST_NODE_TYPES12.Identifier) {
20182
20582
  ({ name } = node.id);
20183
- } else if (node.type === AST_NODE_TYPES10.FunctionDeclaration && node.id)
20583
+ } else if (node.type === AST_NODE_TYPES12.FunctionDeclaration && node.id)
20184
20584
  ({ name } = node.id);
20185
- else if (node.type === AST_NODE_TYPES10.FunctionExpression && node.id)
20585
+ else if (node.type === AST_NODE_TYPES12.FunctionExpression && node.id)
20186
20586
  ({ name } = node.id);
20187
20587
  return name !== undefined && HOOK_PATTERN.test(name);
20188
20588
  }
@@ -20206,27 +20606,27 @@ function getArrayElementsFromVariable(scope, name) {
20206
20606
  if (!identifier3.parent)
20207
20607
  continue;
20208
20608
  const { parent } = identifier3;
20209
- if (parent.type !== AST_NODE_TYPES10.VariableDeclarator)
20609
+ if (parent.type !== AST_NODE_TYPES12.VariableDeclarator)
20210
20610
  continue;
20211
- if (!parent.init || parent.init.type !== AST_NODE_TYPES10.ArrayExpression)
20611
+ if (!parent.init || parent.init.type !== AST_NODE_TYPES12.ArrayExpression)
20212
20612
  continue;
20213
20613
  elements.push(...parent.init.elements);
20214
20614
  }
20215
20615
  return elements;
20216
20616
  }
20217
20617
  function countReturnElements(argument, scope) {
20218
- if (argument.type === AST_NODE_TYPES10.Identifier)
20618
+ if (argument.type === AST_NODE_TYPES12.Identifier)
20219
20619
  return getArrayElementsFromVariable(scope, argument.name).length;
20220
- if (argument.type !== AST_NODE_TYPES10.ArrayExpression)
20620
+ if (argument.type !== AST_NODE_TYPES12.ArrayExpression)
20221
20621
  return 0;
20222
20622
  let count = 0;
20223
20623
  for (const element of argument.elements) {
20224
20624
  if (element === null)
20225
20625
  count += 1;
20226
- else if (element.type === AST_NODE_TYPES10.SpreadElement) {
20227
- if (element.argument.type === AST_NODE_TYPES10.Identifier) {
20626
+ else if (element.type === AST_NODE_TYPES12.SpreadElement) {
20627
+ if (element.argument.type === AST_NODE_TYPES12.Identifier) {
20228
20628
  count += getArrayElementsFromVariable(scope, element.argument.name).length;
20229
- } else if (element.argument.type === AST_NODE_TYPES10.ArrayExpression) {
20629
+ } else if (element.argument.type === AST_NODE_TYPES12.ArrayExpression) {
20230
20630
  count += element.argument.elements.length;
20231
20631
  } else
20232
20632
  count += 1;
@@ -20239,14 +20639,14 @@ function exceedsMaxReturnProperties(node, scope) {
20239
20639
  const { argument } = node;
20240
20640
  if (argument === null)
20241
20641
  return false;
20242
- if (argument.type === AST_NODE_TYPES10.ObjectExpression)
20642
+ if (argument.type === AST_NODE_TYPES12.ObjectExpression)
20243
20643
  return false;
20244
- if (argument.type === AST_NODE_TYPES10.Identifier) {
20644
+ if (argument.type === AST_NODE_TYPES12.Identifier) {
20245
20645
  const variable = getVariableByName(scope, argument.name);
20246
20646
  if (variable) {
20247
20647
  for (const { identifier: identifier3 } of variable.references) {
20248
20648
  const { parent } = identifier3;
20249
- if (parent?.type === AST_NODE_TYPES10.VariableDeclarator && parent.init?.type === AST_NODE_TYPES10.ObjectExpression) {
20649
+ if (parent?.type === AST_NODE_TYPES12.VariableDeclarator && parent.init?.type === AST_NODE_TYPES12.ObjectExpression) {
20250
20650
  return false;
20251
20651
  }
20252
20652
  }
@@ -20268,13 +20668,13 @@ var reactHooksStrictReturn = {
20268
20668
  return {
20269
20669
  ArrowFunctionExpression(node) {
20270
20670
  const { parent } = node;
20271
- if (parent?.type === AST_NODE_TYPES10.VariableDeclarator && parent.id.type === AST_NODE_TYPES10.Identifier && HOOK_PATTERN.test(parent.id.name)) {
20671
+ if (parent?.type === AST_NODE_TYPES12.VariableDeclarator && parent.id.type === AST_NODE_TYPES12.Identifier && HOOK_PATTERN.test(parent.id.name)) {
20272
20672
  hookDepth += 1;
20273
20673
  }
20274
20674
  },
20275
20675
  "ArrowFunctionExpression:exit"(node) {
20276
20676
  const { parent } = node;
20277
- if (parent?.type === AST_NODE_TYPES10.VariableDeclarator && parent.id.type === AST_NODE_TYPES10.Identifier && HOOK_PATTERN.test(parent.id.name)) {
20677
+ if (parent?.type === AST_NODE_TYPES12.VariableDeclarator && parent.id.type === AST_NODE_TYPES12.Identifier && HOOK_PATTERN.test(parent.id.name)) {
20278
20678
  hookDepth -= 1;
20279
20679
  }
20280
20680
  },
@@ -20323,7 +20723,7 @@ var isHookConfiguration = build_default.Object({
20323
20723
  allowAsync: build_default.Boolean(),
20324
20724
  name: build_default.String()
20325
20725
  });
20326
- var isRuleOptions2 = Compile(build_default.Object({
20726
+ var isRuleOptions3 = Compile(build_default.Object({
20327
20727
  environment: isEnvironmentMode,
20328
20728
  hooks: build_default.Array(isHookConfiguration)
20329
20729
  }, { additionalProperties: true }));
@@ -20334,7 +20734,7 @@ function parseOptions2(options3) {
20334
20734
  hooks: DEFAULT_HOOKS
20335
20735
  };
20336
20736
  }
20337
- if (!isRuleOptions2.Check(options3)) {
20737
+ if (!isRuleOptions3.Check(options3)) {
20338
20738
  return {
20339
20739
  environment: "roblox-ts",
20340
20740
  hooks: DEFAULT_HOOKS
@@ -20644,7 +21044,7 @@ var requireNamedEffectFunctions = {
20644
21044
  var require_named_effect_functions_default = requireNamedEffectFunctions;
20645
21045
 
20646
21046
  // src/rules/require-paired-calls.ts
20647
- import { AST_NODE_TYPES as AST_NODE_TYPES11 } from "@typescript-eslint/types";
21047
+ import { AST_NODE_TYPES as AST_NODE_TYPES13 } from "@typescript-eslint/types";
20648
21048
  var isStringArray = Compile(build_default.Readonly(build_default.Array(build_default.String())));
20649
21049
  var isPairConfiguration = Compile(build_default.Readonly(build_default.Object({
20650
21050
  alternatives: build_default.Optional(isStringArray),
@@ -20655,27 +21055,27 @@ var isPairConfiguration = Compile(build_default.Readonly(build_default.Object({
20655
21055
  requireSync: build_default.Optional(build_default.Boolean()),
20656
21056
  yieldingFunctions: build_default.Optional(isStringArray)
20657
21057
  })));
20658
- var isRuleOptions3 = Compile(build_default.Partial(build_default.Readonly(build_default.Object({
21058
+ var isRuleOptions4 = Compile(build_default.Partial(build_default.Readonly(build_default.Object({
20659
21059
  allowConditionalClosers: build_default.Optional(build_default.Boolean()),
20660
21060
  allowMultipleOpeners: build_default.Optional(build_default.Boolean()),
20661
21061
  maxNestingDepth: build_default.Optional(build_default.Number()),
20662
21062
  pairs: build_default.Readonly(build_default.Array(isPairConfiguration))
20663
21063
  }))));
20664
21064
  var LOOP_NODE_TYPES = new Set([
20665
- AST_NODE_TYPES11.DoWhileStatement,
20666
- AST_NODE_TYPES11.ForInStatement,
20667
- AST_NODE_TYPES11.ForOfStatement,
20668
- AST_NODE_TYPES11.ForStatement,
20669
- AST_NODE_TYPES11.WhileStatement
21065
+ AST_NODE_TYPES13.DoWhileStatement,
21066
+ AST_NODE_TYPES13.ForInStatement,
21067
+ AST_NODE_TYPES13.ForOfStatement,
21068
+ AST_NODE_TYPES13.ForStatement,
21069
+ AST_NODE_TYPES13.WhileStatement
20670
21070
  ]);
20671
21071
  var DEFAULT_ROBLOX_YIELDING_FUNCTIONS = ["task.wait", "wait", "*.WaitForChild", "*.*Async"];
20672
21072
  function getCallName(node) {
20673
21073
  const { callee } = node;
20674
- if (callee.type === AST_NODE_TYPES11.Identifier)
21074
+ if (callee.type === AST_NODE_TYPES13.Identifier)
20675
21075
  return callee.name;
20676
- if (callee.type === AST_NODE_TYPES11.MemberExpression) {
20677
- const object3 = callee.object.type === AST_NODE_TYPES11.Identifier ? callee.object.name : undefined;
20678
- const property = callee.property.type === AST_NODE_TYPES11.Identifier ? callee.property.name : undefined;
21076
+ if (callee.type === AST_NODE_TYPES13.MemberExpression) {
21077
+ const object3 = callee.object.type === AST_NODE_TYPES13.Identifier ? callee.object.name : undefined;
21078
+ const property = callee.property.type === AST_NODE_TYPES13.Identifier ? callee.property.name : undefined;
20679
21079
  if (object3 !== undefined && property !== undefined)
20680
21080
  return `${object3}.${property}`;
20681
21081
  }
@@ -20711,12 +21111,12 @@ function isLoopLikeStatement(node) {
20711
21111
  return LOOP_NODE_TYPES.has(node.type);
20712
21112
  }
20713
21113
  function isSwitchStatement(node) {
20714
- return node?.type === AST_NODE_TYPES11.SwitchStatement;
21114
+ return node?.type === AST_NODE_TYPES13.SwitchStatement;
20715
21115
  }
20716
21116
  function findLabeledStatementBody(label, startingNode) {
20717
21117
  let current = startingNode;
20718
21118
  while (current) {
20719
- if (current.type === AST_NODE_TYPES11.LabeledStatement && current.label.name === label.name)
21119
+ if (current.type === AST_NODE_TYPES13.LabeledStatement && current.label.name === label.name)
20720
21120
  return current.body;
20721
21121
  current = current.parent ?? undefined;
20722
21122
  }
@@ -20765,7 +21165,7 @@ var messages = {
20765
21165
  var rule = {
20766
21166
  create(context) {
20767
21167
  const [rawOptions] = context.options;
20768
- const baseOptions = isRuleOptions3.Check(rawOptions) ? rawOptions : {};
21168
+ const baseOptions = isRuleOptions4.Check(rawOptions) ? rawOptions : {};
20769
21169
  const options3 = {
20770
21170
  allowConditionalClosers: baseOptions.allowConditionalClosers ?? false,
20771
21171
  allowMultipleOpeners: baseOptions.allowMultipleOpeners ?? true,
@@ -20865,12 +21265,12 @@ var rule = {
20865
21265
  if (configuration.platform !== "roblox")
20866
21266
  return false;
20867
21267
  const yieldingFunctions = configuration.yieldingFunctions ?? DEFAULT_ROBLOX_YIELDING_FUNCTIONS;
20868
- return yieldingFunctions.some((pattern4) => {
20869
- if (pattern4.startsWith("*.")) {
20870
- const methodName = pattern4.slice(2);
21268
+ return yieldingFunctions.some((pattern5) => {
21269
+ if (pattern5.startsWith("*.")) {
21270
+ const methodName = pattern5.slice(2);
20871
21271
  return functionName.endsWith(`.${methodName}`);
20872
21272
  }
20873
- return functionName === pattern4;
21273
+ return functionName === pattern5;
20874
21274
  });
20875
21275
  }
20876
21276
  function onFunctionEnter(node) {
@@ -20978,7 +21378,7 @@ var rule = {
20978
21378
  function onIfConsequentExit(node) {
20979
21379
  const consequentNode = node;
20980
21380
  const { parent } = consequentNode;
20981
- if (parent?.type === AST_NODE_TYPES11.IfStatement) {
21381
+ if (parent?.type === AST_NODE_TYPES13.IfStatement) {
20982
21382
  const branches = branchStacks.get(parent) ?? [];
20983
21383
  branches.push(cloneStack());
20984
21384
  branchStacks.set(parent, branches);
@@ -20993,7 +21393,7 @@ var rule = {
20993
21393
  function onIfAlternateExit(node) {
20994
21394
  const alternateNode = node;
20995
21395
  const { parent } = alternateNode;
20996
- if (parent?.type === AST_NODE_TYPES11.IfStatement) {
21396
+ if (parent?.type === AST_NODE_TYPES13.IfStatement) {
20997
21397
  const branches = branchStacks.get(parent) ?? [];
20998
21398
  branches.push(cloneStack());
20999
21399
  branchStacks.set(parent, branches);
@@ -21042,7 +21442,7 @@ var rule = {
21042
21442
  function onTryBlockExit(node) {
21043
21443
  const blockNode = node;
21044
21444
  const { parent } = blockNode;
21045
- if (parent?.type === AST_NODE_TYPES11.TryStatement) {
21445
+ if (parent?.type === AST_NODE_TYPES13.TryStatement) {
21046
21446
  const branches = branchStacks.get(parent) ?? [];
21047
21447
  branches.push(cloneStack());
21048
21448
  branchStacks.set(parent, branches);
@@ -21061,7 +21461,7 @@ var rule = {
21061
21461
  function onCatchClauseExit(node) {
21062
21462
  const catchNode = node;
21063
21463
  const { parent } = catchNode;
21064
- if (parent?.type === AST_NODE_TYPES11.TryStatement) {
21464
+ if (parent?.type === AST_NODE_TYPES13.TryStatement) {
21065
21465
  const branches = branchStacks.get(parent) ?? [];
21066
21466
  branches.push(cloneStack());
21067
21467
  branchStacks.set(parent, branches);
@@ -21124,7 +21524,7 @@ var rule = {
21124
21524
  function onSwitchCaseExit(node) {
21125
21525
  const caseNode = node;
21126
21526
  const { parent } = caseNode;
21127
- if (parent?.type === AST_NODE_TYPES11.SwitchStatement) {
21527
+ if (parent?.type === AST_NODE_TYPES13.SwitchStatement) {
21128
21528
  const branches = branchStacks.get(parent) ?? [];
21129
21529
  branches.push(cloneStack());
21130
21530
  branchStacks.set(parent, branches);
@@ -21155,7 +21555,7 @@ var rule = {
21155
21555
  for (const { opener, config, node: node2 } of openerStack) {
21156
21556
  const validClosers = getValidClosers(config);
21157
21557
  const closer = validClosers.length === 1 ? validClosers[0] ?? "closer" : validClosers.join("' or '");
21158
- const statementType = statementNode.type === AST_NODE_TYPES11.ReturnStatement ? "return" : "throw";
21558
+ const statementType = statementNode.type === AST_NODE_TYPES13.ReturnStatement ? "return" : "throw";
21159
21559
  const lineNumber = statementNode.loc?.start.line ?? 0;
21160
21560
  context.report({
21161
21561
  data: {
@@ -21172,7 +21572,7 @@ var rule = {
21172
21572
  const statementNode = node;
21173
21573
  if (openerStack.length === 0)
21174
21574
  return;
21175
- const targetLoop = statementNode.type === AST_NODE_TYPES11.ContinueStatement ? resolveContinueTargetLoop(statementNode) : resolveBreakTargetLoop(statementNode);
21575
+ const targetLoop = statementNode.type === AST_NODE_TYPES13.ContinueStatement ? resolveContinueTargetLoop(statementNode) : resolveBreakTargetLoop(statementNode);
21176
21576
  if (!targetLoop)
21177
21577
  return;
21178
21578
  for (const { node: openerNode, config, opener, loopAncestors } of openerStack) {
@@ -21180,7 +21580,7 @@ var rule = {
21180
21580
  continue;
21181
21581
  const validClosers = getValidClosers(config);
21182
21582
  const closer = validClosers.length === 1 ? validClosers[0] ?? "closer" : validClosers.join("' or '");
21183
- const statementType = statementNode.type === AST_NODE_TYPES11.BreakStatement ? "break" : "continue";
21583
+ const statementType = statementNode.type === AST_NODE_TYPES13.BreakStatement ? "break" : "continue";
21184
21584
  const lineNumber = statementNode.loc?.start.line ?? 0;
21185
21585
  context.report({
21186
21586
  data: {
@@ -21318,7 +21718,7 @@ var rule = {
21318
21718
  continue;
21319
21719
  const validClosers = getValidClosers(config);
21320
21720
  const closer = validClosers.length === 1 ? validClosers[0] ?? "closer" : validClosers.join("' or '");
21321
- const asyncType = asyncNode.type === AST_NODE_TYPES11.AwaitExpression ? "await" : "yield";
21721
+ const asyncType = asyncNode.type === AST_NODE_TYPES13.AwaitExpression ? "await" : "yield";
21322
21722
  context.report({
21323
21723
  data: { asyncType, closer, opener },
21324
21724
  messageId: "asyncViolation",
@@ -21849,8 +22249,8 @@ function resolveRelativeImport(importSource, sourceFile) {
21849
22249
  }
21850
22250
 
21851
22251
  // src/rules/strict-component-boundaries.ts
21852
- function toRegExp(pattern4) {
21853
- return new RegExp(pattern4, "i");
22252
+ function toRegExp(pattern5) {
22253
+ return new RegExp(pattern5, "i");
21854
22254
  }
21855
22255
  function pathSegmentsFromSource(source) {
21856
22256
  return source.split("/").filter((part) => !part.startsWith("."));
@@ -23106,6 +23506,9 @@ function createNoUselessUseSpringOptions(options3 = {}) {
23106
23506
  ...options3
23107
23507
  };
23108
23508
  }
23509
+ function createPreferPatternReplacementsOptions(patterns2 = []) {
23510
+ return { patterns: patterns2 };
23511
+ }
23109
23512
 
23110
23513
  // src/index.ts
23111
23514
  var rules = {
@@ -23127,6 +23530,7 @@ var rules = {
23127
23530
  "prefer-early-return": prefer_early_return_default,
23128
23531
  "prefer-module-scope-constants": prefer_module_scope_constants_default,
23129
23532
  "prefer-pascal-case-enums": prefer_pascal_case_enums_default,
23533
+ "prefer-pattern-replacements": prefer_pattern_replacements_default,
23130
23534
  "prefer-sequence-overloads": prefer_sequence_overloads_default,
23131
23535
  "prefer-singular-enums": prefer_singular_enums_default,
23132
23536
  "prefer-udim2-shorthand": prefer_udim2_shorthand_default,
@@ -23168,12 +23572,14 @@ var plugin = {
23168
23572
  };
23169
23573
  var src_default = plugin;
23170
23574
  export {
23575
+ pattern4 as pattern,
23171
23576
  defaultRobloxProfilePair,
23172
23577
  src_default as default,
23173
23578
  createUseHookAtTopLevelOptions,
23174
23579
  createUseExhaustiveDependenciesOptions,
23175
23580
  createRequirePairedCallsOptions,
23176
23581
  createReactKeysOptions,
23582
+ createPreferPatternReplacementsOptions,
23177
23583
  createPairConfiguration,
23178
23584
  createNoUselessUseSpringOptions,
23179
23585
  createNoShorthandOptions,
@@ -23185,4 +23591,4 @@ export {
23185
23591
  createBanInstancesOptions
23186
23592
  };
23187
23593
 
23188
- //# debugId=CB943D9A894DADAF64756E2164756E21
23594
+ //# debugId=928BD58DAA13C57A64756E2164756E21