@flint.fyi/ts 0.23.1 → 0.23.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/index.mjs +93 -134
  2. package/package.json +9 -9
package/dist/index.mjs CHANGED
@@ -1686,9 +1686,7 @@ function isDirectEqualityCheck(node, operators, parameterName) {
1686
1686
  case SyntaxKind.ArrowFunction:
1687
1687
  body = node.body.kind === SyntaxKind.Block ? getDirectReturnExpression(node.body) : node.body;
1688
1688
  break;
1689
- case SyntaxKind.FunctionExpression:
1690
- body = getDirectReturnExpression(node.body);
1691
- break;
1689
+ case SyntaxKind.FunctionExpression: body = getDirectReturnExpression(node.body);
1692
1690
  }
1693
1691
  if (body?.kind !== SyntaxKind.BinaryExpression) return false;
1694
1692
  const { left, operatorToken, right } = body;
@@ -2273,10 +2271,7 @@ var arrayTypes_default = ruleCreator.createRule(typescriptLanguage, {
2273
2271
  if (node.parent.kind === SyntaxKind.TypeOperator && node.parent.operator === SyntaxKind.ReadonlyKeyword) return;
2274
2272
  switch (options.style) {
2275
2273
  case "array": return;
2276
- case "array-simple":
2277
- if (isSimpleType(node.elementType)) return;
2278
- break;
2279
- case "generic": break;
2274
+ case "array-simple": if (isSimpleType(node.elementType)) return;
2280
2275
  }
2281
2276
  context.report({
2282
2277
  message: "preferGenericSyntax",
@@ -2288,10 +2283,7 @@ var arrayTypes_default = ruleCreator.createRule(typescriptLanguage, {
2288
2283
  const arrayType = node.type;
2289
2284
  switch (options.style) {
2290
2285
  case "array": return;
2291
- case "array-simple":
2292
- if (isSimpleType(arrayType.elementType)) return;
2293
- break;
2294
- case "generic": break;
2286
+ case "array-simple": if (isSimpleType(arrayType.elementType)) return;
2295
2287
  }
2296
2288
  context.report({
2297
2289
  message: "preferReadonlyGenericSyntax",
@@ -3053,9 +3045,7 @@ var catchCallbackTypes_default = ruleCreator.createRule(typescriptLanguage, {
3053
3045
  case "catch":
3054
3046
  if (node.arguments.length >= 1) checkCallbackParameter(node.arguments[0], sourceFile, typeChecker);
3055
3047
  break;
3056
- case "then":
3057
- if (node.arguments.length >= 2) checkCallbackParameter(node.arguments[1], sourceFile, typeChecker);
3058
- break;
3048
+ case "then": if (node.arguments.length >= 2) checkCallbackParameter(node.arguments[1], sourceFile, typeChecker);
3059
3049
  }
3060
3050
  } } };
3061
3051
  }
@@ -3437,9 +3427,7 @@ var classMethodsThis_default = ruleCreator.createRule(typescriptLanguage, {
3437
3427
  case SyntaxKind.PropertyDeclaration:
3438
3428
  checkPropertyInitializerFunction(member, node, sourceFile, options);
3439
3429
  break;
3440
- case SyntaxKind.SetAccessor:
3441
- checkAccessor(member, node, sourceFile, options, "setter");
3442
- break;
3430
+ case SyntaxKind.SetAccessor: checkAccessor(member, node, sourceFile, options, "setter");
3443
3431
  }
3444
3432
  }
3445
3433
  return { visitors: {
@@ -3894,12 +3882,10 @@ var dateNowTimestamps_default = ruleCreator.createRule(typescriptLanguage, {
3894
3882
  range: getTSNodeRange(node.parent, sourceFile)
3895
3883
  });
3896
3884
  break;
3897
- case SyntaxKind.PrefixUnaryExpression:
3898
- if (node.parent.operator === SyntaxKind.MinusToken || node.parent.operator === SyntaxKind.PlusToken) context.report({
3899
- message: "preferDateNow",
3900
- range: getTSNodeRange(node, sourceFile)
3901
- });
3902
- break;
3885
+ case SyntaxKind.PrefixUnaryExpression: if (node.parent.operator === SyntaxKind.MinusToken || node.parent.operator === SyntaxKind.PlusToken) context.report({
3886
+ message: "preferDateNow",
3887
+ range: getTSNodeRange(node, sourceFile)
3888
+ });
3903
3889
  }
3904
3890
  }
3905
3891
  } };
@@ -5859,9 +5845,7 @@ var exportUniqueNames_default = ruleCreator.createRule(typescriptLanguage, {
5859
5845
  case SyntaxKind.ExportDeclaration:
5860
5846
  checkExportDeclaration(statement);
5861
5847
  break;
5862
- case SyntaxKind.VariableStatement:
5863
- checkVariableStatement(statement);
5864
- break;
5848
+ case SyntaxKind.VariableStatement: checkVariableStatement(statement);
5865
5849
  }
5866
5850
  } } };
5867
5851
  }
@@ -6001,7 +5985,6 @@ var fetchMethodBodies_default = ruleCreator.createRule(typescriptLanguage, {
6001
5985
  case "method":
6002
5986
  if (property.initializer.kind !== SyntaxKind.StringLiteral) return;
6003
5987
  methodText = property.initializer.text;
6004
- break;
6005
5988
  }
6006
5989
  break;
6007
5990
  case SyntaxKind.SpreadAssignment: return;
@@ -6750,9 +6733,7 @@ function getCalleeName(node) {
6750
6733
  if (node.expression.kind === SyntaxKind.Identifier && globalCandidates.has(node.expression.text) && node.argumentExpression.kind === SyntaxKind.StringLiteral) return node.argumentExpression.text;
6751
6734
  break;
6752
6735
  case SyntaxKind.Identifier: return node.text;
6753
- case SyntaxKind.PropertyAccessExpression:
6754
- if (node.expression.kind === SyntaxKind.Identifier && globalCandidates.has(node.expression.text)) return node.name.text;
6755
- break;
6736
+ case SyntaxKind.PropertyAccessExpression: if (node.expression.kind === SyntaxKind.Identifier && globalCandidates.has(node.expression.text)) return node.name.text;
6756
6737
  }
6757
6738
  }
6758
6739
  function isBind(node) {
@@ -6842,9 +6823,7 @@ var impliedEvals_default = ruleCreator.createRule(typescriptLanguage, {
6842
6823
  checkCalleeFunction(node, services);
6843
6824
  break;
6844
6825
  case void 0: return;
6845
- default:
6846
- checkCalleeEval(node, calleeName, services);
6847
- break;
6826
+ default: checkCalleeEval(node, calleeName, services);
6848
6827
  }
6849
6828
  }
6850
6829
  return { visitors: {
@@ -8604,13 +8583,11 @@ var nonNullAssertionPlacement_default = ruleCreator.createRule(typescriptLanguag
8604
8583
  suggestions
8605
8584
  });
8606
8585
  break;
8607
- default:
8608
- context.report({
8609
- message: "confusingEqual",
8610
- range,
8611
- suggestions
8612
- });
8613
- break;
8586
+ default: context.report({
8587
+ message: "confusingEqual",
8588
+ range,
8589
+ suggestions
8590
+ });
8614
8591
  }
8615
8592
  } } };
8616
8593
  }
@@ -9254,12 +9231,10 @@ var numericErasingOperations_default = ruleCreator.createRule(typescriptLanguage
9254
9231
  range: getTSNodeRange(node, sourceFile)
9255
9232
  });
9256
9233
  break;
9257
- case SyntaxKind.SlashToken:
9258
- if (isZeroLiteral(node.left) && !isZeroLiteral(node.right)) context.report({
9259
- message: "erasingOperation",
9260
- range: getTSNodeRange(node, sourceFile)
9261
- });
9262
- break;
9234
+ case SyntaxKind.SlashToken: if (isZeroLiteral(node.left) && !isZeroLiteral(node.right)) context.report({
9235
+ message: "erasingOperation",
9236
+ range: getTSNodeRange(node, sourceFile)
9237
+ });
9263
9238
  }
9264
9239
  } } };
9265
9240
  }
@@ -11202,9 +11177,7 @@ function elementsToCharacterClass(elements) {
11202
11177
  case "CharacterClassRange":
11203
11178
  case "CharacterSet":
11204
11179
  case "ClassStringDisjunction":
11205
- case "ExpressionCharacterClass":
11206
- parts.push(element.raw);
11207
- break;
11180
+ case "ExpressionCharacterClass": parts.push(element.raw);
11208
11181
  }
11209
11182
  if (!parts.length) return "[]";
11210
11183
  if (parts[0]?.[0] === "^") parts[0] = `\\${parts[0]}`;
@@ -11428,7 +11401,9 @@ function processCharacterClass(node) {
11428
11401
  } else continue;
11429
11402
  const group = groups.find((gp) => {
11430
11403
  if (!(gp.min.value - 1 <= data.max.value && data.min.value <= gp.max.value + 1)) return false;
11431
- return inRange(ALPHANUMERIC_RANGES, Math.min(gp.min.value, data.min.value), Math.max(gp.max.value, data.max.value));
11404
+ const min = Math.min(gp.min.value, data.min.value);
11405
+ const max = Math.max(gp.max.value, data.max.value);
11406
+ return inRange(ALPHANUMERIC_RANGES, min, max);
11432
11407
  });
11433
11408
  if (group) {
11434
11409
  if (data.min.value < group.min.value) group.min = data.min;
@@ -12103,17 +12078,19 @@ function findIssues$2(pattern, flags) {
12103
12078
  const groups = [];
12104
12079
  for (const element of ccNode.elements) {
12105
12080
  let data;
12106
- if (element.type === "Character") if (checkInAllowedRange(element.value)) data = {
12107
- max: element,
12108
- min: element
12109
- };
12110
- else continue;
12111
- else if (element.type === "CharacterClassRange") if (checkInAllowedRange(element.min.value, element.min.value, element.max.value)) data = {
12112
- max: element.max,
12113
- min: element.min
12114
- };
12115
- else continue;
12116
- else continue;
12081
+ if (element.type === "Character") {
12082
+ if (checkInAllowedRange(element.value)) data = {
12083
+ max: element,
12084
+ min: element
12085
+ };
12086
+ else continue;
12087
+ } else if (element.type === "CharacterClassRange") {
12088
+ if (checkInAllowedRange(element.min.value, element.min.value, element.max.value)) data = {
12089
+ max: element.max,
12090
+ min: element.min
12091
+ };
12092
+ else continue;
12093
+ } else continue;
12117
12094
  const group = groups.find((gp) => {
12118
12095
  if (!(gp.min.value - 1 <= data.max.value && data.min.value <= gp.max.value + 1)) return false;
12119
12096
  const min = Math.min(gp.min.value, data.min.value);
@@ -12456,9 +12433,10 @@ function findEmptyAlternativesInGroup(pattern, groupStart, groupEnd, results) {
12456
12433
  "?!",
12457
12434
  "?:",
12458
12435
  "?="
12459
- ].includes(pattern.slice(groupStart, groupStart + 2)) || ["?<!", "?<="].includes(pattern.slice(groupStart, groupStart + 3))) if (pattern.slice(groupStart, groupStart + 3).startsWith("?<")) contentStart = groupStart + 3;
12460
- else contentStart = groupStart + 2;
12461
- else if (pattern[groupStart] === "?" && pattern[groupStart + 1] === "<") {
12436
+ ].includes(pattern.slice(groupStart, groupStart + 2)) || ["?<!", "?<="].includes(pattern.slice(groupStart, groupStart + 3))) {
12437
+ if (pattern.slice(groupStart, groupStart + 3).startsWith("?<")) contentStart = groupStart + 3;
12438
+ else contentStart = groupStart + 2;
12439
+ } else if (pattern[groupStart] === "?" && pattern[groupStart + 1] === "<") {
12462
12440
  const closeAngle = pattern.indexOf(">", groupStart + 2);
12463
12441
  if (closeAngle !== -1 && closeAngle < groupEnd) contentStart = closeAngle + 1;
12464
12442
  }
@@ -12475,9 +12453,7 @@ function findEmptyAlternativesInGroup(pattern, groupStart, groupEnd, results) {
12475
12453
  case "\\":
12476
12454
  i++;
12477
12455
  break;
12478
- case "|":
12479
- pipePositions.push(i);
12480
- break;
12456
+ case "|": pipePositions.push(i);
12481
12457
  }
12482
12458
  if (!pipePositions.length) return;
12483
12459
  const alternativeBoundaries = [];
@@ -12768,14 +12744,11 @@ function* extractLazyEndQuantifiers(alternatives) {
12768
12744
  case "Group":
12769
12745
  yield* extractLazyEndQuantifiers(last.alternatives);
12770
12746
  break;
12771
- case "Quantifier":
12772
- if (!last.greedy && last.min !== last.max) yield last;
12773
- else if (last.max === 1) {
12774
- const element = last.element;
12775
- if (element.type === "Group" || element.type === "CapturingGroup") yield* extractLazyEndQuantifiers(element.alternatives);
12776
- }
12777
- break;
12778
- default: break;
12747
+ case "Quantifier": if (!last.greedy && last.min !== last.max) yield last;
12748
+ else if (last.max === 1) {
12749
+ const element = last.element;
12750
+ if (element.type === "Group" || element.type === "CapturingGroup") yield* extractLazyEndQuantifiers(element.alternatives);
12751
+ }
12779
12752
  }
12780
12753
  }
12781
12754
  }
@@ -13233,9 +13206,10 @@ function simplifyCharacterClass(pattern, charClass) {
13233
13206
  const elements = charClass.elements;
13234
13207
  const keptCharacters = /* @__PURE__ */ new Set();
13235
13208
  const rangesToKeep = [];
13236
- for (const element of elements) if (element.type === "Character") if (isLetter$1(element.value)) keptCharacters.add(toLowerCase(element.value));
13237
- else keptCharacters.add(element.value);
13238
- else if (element.type === "CharacterClassRange") {
13209
+ for (const element of elements) if (element.type === "Character") {
13210
+ if (isLetter$1(element.value)) keptCharacters.add(toLowerCase(element.value));
13211
+ else keptCharacters.add(element.value);
13212
+ } else if (element.type === "CharacterClassRange") {
13239
13213
  const min = element.min.value;
13240
13214
  const max = element.max.value;
13241
13215
  const minIsUpper = min >= 65 && min <= 90;
@@ -13504,9 +13478,7 @@ function checkPattern(pattern, flags) {
13504
13478
  checkHexadecimalEscape(charNode);
13505
13479
  break;
13506
13480
  case "unicode":
13507
- case "unicodeCodePoint":
13508
- checkUnicodeEscape(charNode);
13509
- break;
13481
+ case "unicodeCodePoint": checkUnicodeEscape(charNode);
13510
13482
  }
13511
13483
  }
13512
13484
  });
@@ -13602,9 +13574,7 @@ function escapeForRegexLiteral(pattern) {
13602
13574
  result += char;
13603
13575
  escaped = true;
13604
13576
  break;
13605
- default:
13606
- result += char;
13607
- break;
13577
+ default: result += char;
13608
13578
  }
13609
13579
  }
13610
13580
  return result;
@@ -13816,9 +13786,7 @@ function* extractInvalidQuantifiers(alternatives, kind) {
13816
13786
  case "Group":
13817
13787
  yield* extractInvalidQuantifiers(last.alternatives, kind);
13818
13788
  break;
13819
- case "Quantifier":
13820
- if (last.min !== last.max && !hasCapturingGroupDescendant(last.element)) yield last;
13821
- break;
13789
+ case "Quantifier": if (last.min !== last.max && !hasCapturingGroupDescendant(last.element)) yield last;
13822
13790
  }
13823
13791
  }
13824
13792
  }
@@ -13933,17 +13901,14 @@ function isMatchAnyCharacterClass(node, flags) {
13933
13901
  type: "CharacterSet"
13934
13902
  });
13935
13903
  break;
13936
- case "word":
13937
- if (element.negate) negativeElements.push({
13938
- kind: "word",
13939
- type: "CharacterSet"
13940
- });
13941
- else positiveElements.push({
13942
- kind: "word",
13943
- type: "CharacterSet"
13944
- });
13945
- break;
13946
- default: break;
13904
+ case "word": if (element.negate) negativeElements.push({
13905
+ kind: "word",
13906
+ type: "CharacterSet"
13907
+ });
13908
+ else positiveElements.push({
13909
+ kind: "word",
13910
+ type: "CharacterSet"
13911
+ });
13947
13912
  }
13948
13913
  else if (element.type === "CharacterClassRange" && element.min.value === 0 && (element.max.value === 65535 || element.max.value === 1114111 || flags.unicode && element.max.value >= 1114111)) return true;
13949
13914
  for (const positive of positiveElements) if (negativeElements.find((negative) => negative.kind === positive.kind)) return true;
@@ -14376,12 +14341,15 @@ function* findZeroWidthJoins(characters) {
14376
14341
  for (const [index, char] of characters.entries()) {
14377
14342
  const previous = characters[index - 1];
14378
14343
  const next = characters[index + 1];
14379
- if (previous && next && char.value === 8205 && previous.value !== 8205 && next.value !== 8205) if (sequence) if (sequence.at(-1) === previous) sequence.push(char, next);
14380
- else {
14381
- yield sequence;
14382
- sequence = characters.slice(index - 1, index + 2);
14344
+ if (previous && next && char.value === 8205 && previous.value !== 8205 && next.value !== 8205) {
14345
+ if (sequence) {
14346
+ if (sequence.at(-1) === previous) sequence.push(char, next);
14347
+ else {
14348
+ yield sequence;
14349
+ sequence = characters.slice(index - 1, index + 2);
14350
+ }
14351
+ } else sequence = characters.slice(index - 1, index + 2);
14383
14352
  }
14384
- else sequence = characters.slice(index - 1, index + 2);
14385
14353
  }
14386
14354
  if (sequence) yield sequence;
14387
14355
  }
@@ -14429,7 +14397,6 @@ function* iterateCharacterSequence(nodes) {
14429
14397
  sequence.push(node.min);
14430
14398
  yield sequence;
14431
14399
  sequence = [node.max];
14432
- break;
14433
14400
  }
14434
14401
  if (sequence.length) yield sequence;
14435
14402
  }
@@ -15844,9 +15811,7 @@ function findReachableQuantifiers(pattern) {
15844
15811
  case "Group":
15845
15812
  for (const innerAlternative of element.alternatives) walkAlternative(innerAlternative);
15846
15813
  break;
15847
- case "Quantifier":
15848
- if (element.max === Infinity && element.min === 0) quantifiers.push(element);
15849
- break;
15814
+ case "Quantifier": if (element.max === Infinity && element.min === 0) quantifiers.push(element);
15850
15815
  }
15851
15816
  if (!canMatchEmpty(element)) return;
15852
15817
  }
@@ -15865,19 +15830,15 @@ function generateAttackString(quantifier) {
15865
15830
  if (first.type === "Character") character = String.fromCharCode(first.value);
15866
15831
  break;
15867
15832
  }
15868
- case "CharacterSet":
15869
- switch (quantifier.element.kind) {
15870
- case "any":
15871
- character = "x";
15872
- break;
15873
- case "digit":
15874
- character = "0";
15875
- break;
15876
- case "space":
15877
- character = " ";
15878
- break;
15879
- }
15880
- break;
15833
+ case "CharacterSet": switch (quantifier.element.kind) {
15834
+ case "any":
15835
+ character = "x";
15836
+ break;
15837
+ case "digit":
15838
+ character = "0";
15839
+ break;
15840
+ case "space": character = " ";
15841
+ }
15881
15842
  }
15882
15843
  return (character ?? "a").repeat(20);
15883
15844
  }
@@ -17846,9 +17807,7 @@ function isOptionalAssertion(quantifierElement, assertion) {
17846
17807
  }
17847
17808
  }
17848
17809
  break;
17849
- case "Quantifier":
17850
- if (parent !== quantifierElement && parent.max > 1 && canConsumeCharacters(parent.element)) return false;
17851
- break;
17810
+ case "Quantifier": if (parent !== quantifierElement && parent.max > 1 && canConsumeCharacters(parent.element)) return false;
17852
17811
  }
17853
17812
  current = parent;
17854
17813
  }
@@ -20385,15 +20344,13 @@ var tsComments_default = ruleCreator.createRule(typescriptLanguage, {
20385
20344
  case true:
20386
20345
  reportCommentDirective(comment, directive, { directive }, "directiveComment", "preferExpectError");
20387
20346
  return;
20388
- default:
20389
- if (typeof config === "object" && config.descriptionFormat) {
20390
- const format = descriptionFormats.get(directive);
20391
- if (format && !format.test(description)) reportCommentDirective(comment, directive, {
20392
- directive,
20393
- format: format.source
20394
- }, "descriptionNotMatchPattern");
20395
- }
20396
- break;
20347
+ default: if (typeof config === "object" && config.descriptionFormat) {
20348
+ const format = descriptionFormats.get(directive);
20349
+ if (format && !format.test(description)) reportCommentDirective(comment, directive, {
20350
+ directive,
20351
+ format: format.source
20352
+ }, "descriptionNotMatchPattern");
20353
+ }
20397
20354
  }
20398
20355
  }
20399
20356
  } } };
@@ -20475,8 +20432,10 @@ function getImportSpecifiers(node) {
20475
20432
  const specifiers = [];
20476
20433
  if (importClause.name) specifiers.push(importClause.name);
20477
20434
  const namedBindings = importClause.namedBindings;
20478
- if (namedBindings) if (namedBindings.kind === SyntaxKind.NamespaceImport) specifiers.push(namedBindings);
20479
- else specifiers.push(...namedBindings.elements);
20435
+ if (namedBindings) {
20436
+ if (namedBindings.kind === SyntaxKind.NamespaceImport) specifiers.push(namedBindings);
20437
+ else specifiers.push(...namedBindings.elements);
20438
+ }
20480
20439
  return specifiers;
20481
20440
  }
20482
20441
  function getReferencedSymbol(typeChecker, node) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@flint.fyi/ts",
3
- "version": "0.23.1",
3
+ "version": "0.23.2",
4
4
  "description": "[Experimental] TypeScript language plugin for Flint.",
5
5
  "homepage": "https://flint.fyi/rules/ts",
6
6
  "repository": {
@@ -23,20 +23,20 @@
23
23
  ],
24
24
  "dependencies": {
25
25
  "@eslint-community/regexpp": "^4.12.2",
26
+ "@flint.fyi/core": "^0.26.0",
27
+ "@flint.fyi/typescript-language": "^0.20.1",
28
+ "@flint.fyi/utils": "^0.16.0",
26
29
  "regexp-ast-analysis": "^0.7.1",
27
30
  "scslre": "^0.3.0",
28
31
  "ts-api-utils": "^2.4.0",
29
32
  "typescript": "^6.0.0",
30
- "zod": "^4.3.6",
31
- "@flint.fyi/core": "^0.25.0",
32
- "@flint.fyi/utils": "^0.16.0",
33
- "@flint.fyi/typescript-language": "^0.20.0"
33
+ "zod": "^4.3.6"
34
34
  },
35
35
  "devDependencies": {
36
- "tsdown": "0.22.3",
37
- "vitest": "4.1.0",
38
- "@flint.fyi/rule-tester": "^0.19.0",
39
- "@flint.fyi/build": "^0.1.0"
36
+ "@flint.fyi/build": "^0.1.0",
37
+ "@flint.fyi/rule-tester": "^0.19.1",
38
+ "tsdown": "0.22.14",
39
+ "vitest": "4.1.11"
40
40
  },
41
41
  "engines": {
42
42
  "node": ">=26.1.0"