tstyche 3.1.1 → 3.3.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/build/tstyche.js CHANGED
@@ -75,6 +75,12 @@ class ConfigDiagnosticText {
75
75
  }
76
76
  }
77
77
 
78
+ var DiagnosticCategory;
79
+ (function (DiagnosticCategory) {
80
+ DiagnosticCategory["Error"] = "error";
81
+ DiagnosticCategory["Warning"] = "warning";
82
+ })(DiagnosticCategory || (DiagnosticCategory = {}));
83
+
78
84
  class DiagnosticOrigin {
79
85
  assertion;
80
86
  end;
@@ -116,40 +122,42 @@ class Diagnostic {
116
122
  return this;
117
123
  }
118
124
  static error(text, origin) {
119
- return new Diagnostic(text, "error", origin);
125
+ return new Diagnostic(text, DiagnosticCategory.Error, origin);
120
126
  }
121
127
  extendWith(text, origin) {
122
128
  return new Diagnostic([this.text, text].flat(), this.category, origin ?? this.origin);
123
129
  }
124
- static fromDiagnostics(diagnostics, compiler) {
130
+ static fromDiagnostics(diagnostics) {
125
131
  return diagnostics.map((diagnostic) => {
126
132
  const code = `ts(${diagnostic.code})`;
127
133
  let origin;
128
- if (Diagnostic.#isTsDiagnosticWithLocation(diagnostic)) {
134
+ if (diagnostic.file != null && diagnostic.start != null && diagnostic.length != null) {
129
135
  origin = new DiagnosticOrigin(diagnostic.start, diagnostic.start + diagnostic.length, diagnostic.file);
130
136
  }
131
137
  let related;
132
138
  if (diagnostic.relatedInformation != null) {
133
- related = Diagnostic.fromDiagnostics(diagnostic.relatedInformation, compiler);
139
+ related = Diagnostic.fromDiagnostics(diagnostic.relatedInformation);
134
140
  }
135
- const text = compiler.flattenDiagnosticMessageText(diagnostic.messageText, "\n");
136
- return new Diagnostic(text, "error", origin).add({ code, related });
141
+ const text = typeof diagnostic.messageText === "string"
142
+ ? diagnostic.messageText
143
+ : Diagnostic.#toMessageText(diagnostic.messageText);
144
+ return new Diagnostic(text, DiagnosticCategory.Error, origin).add({ code, related });
137
145
  });
138
146
  }
139
- static #isTsDiagnosticWithLocation(diagnostic) {
140
- return diagnostic.file != null && diagnostic.start != null && diagnostic.length != null;
147
+ static #toMessageText(chain) {
148
+ const result = [chain.messageText];
149
+ if (chain.next != null) {
150
+ for (const nextChain of chain.next) {
151
+ result.push(...Diagnostic.#toMessageText(nextChain));
152
+ }
153
+ }
154
+ return result;
141
155
  }
142
156
  static warning(text, origin) {
143
- return new Diagnostic(text, "warning", origin);
157
+ return new Diagnostic(text, DiagnosticCategory.Warning, origin);
144
158
  }
145
159
  }
146
160
 
147
- var DiagnosticCategory;
148
- (function (DiagnosticCategory) {
149
- DiagnosticCategory["Error"] = "error";
150
- DiagnosticCategory["Warning"] = "warning";
151
- })(DiagnosticCategory || (DiagnosticCategory = {}));
152
-
153
161
  class SourceFile {
154
162
  fileName;
155
163
  #lineMap;
@@ -255,6 +263,22 @@ class Path {
255
263
  }
256
264
  }
257
265
 
266
+ var OptionBrand;
267
+ (function (OptionBrand) {
268
+ OptionBrand["String"] = "string";
269
+ OptionBrand["Number"] = "number";
270
+ OptionBrand["Boolean"] = "boolean";
271
+ OptionBrand["BareTrue"] = "bareTrue";
272
+ OptionBrand["List"] = "list";
273
+ })(OptionBrand || (OptionBrand = {}));
274
+
275
+ var OptionGroup;
276
+ (function (OptionGroup) {
277
+ OptionGroup[OptionGroup["CommandLine"] = 2] = "CommandLine";
278
+ OptionGroup[OptionGroup["ConfigFile"] = 4] = "ConfigFile";
279
+ OptionGroup[OptionGroup["ResolvedConfig"] = 6] = "ResolvedConfig";
280
+ })(OptionGroup || (OptionGroup = {}));
281
+
258
282
  class Environment {
259
283
  static resolve() {
260
284
  return {
@@ -864,151 +888,157 @@ class Target {
864
888
  class Options {
865
889
  static #definitions = [
866
890
  {
867
- brand: "string",
891
+ brand: OptionBrand.String,
868
892
  description: "The Url to the config file validation schema.",
869
- group: 4,
893
+ group: OptionGroup.ConfigFile,
870
894
  name: "$schema",
871
895
  },
872
896
  {
873
- brand: "string",
897
+ brand: OptionBrand.Boolean,
898
+ description: "Enable type error reporting for source files.",
899
+ group: OptionGroup.ConfigFile,
900
+ name: "checkSourceFiles",
901
+ },
902
+ {
903
+ brand: OptionBrand.String,
874
904
  description: "The path to a TSTyche configuration file.",
875
- group: 2,
905
+ group: OptionGroup.CommandLine,
876
906
  name: "config",
877
907
  },
878
908
  {
879
- brand: "boolean",
909
+ brand: OptionBrand.Boolean,
880
910
  description: "Stop running tests after the first failed assertion.",
881
- group: 4 | 2,
911
+ group: OptionGroup.ConfigFile | OptionGroup.CommandLine,
882
912
  name: "failFast",
883
913
  },
884
914
  {
885
- brand: "bareTrue",
915
+ brand: OptionBrand.BareTrue,
886
916
  description: "Print the list of command line options with brief descriptions and exit.",
887
- group: 2,
917
+ group: OptionGroup.CommandLine,
888
918
  name: "help",
889
919
  },
890
920
  {
891
- brand: "bareTrue",
921
+ brand: OptionBrand.BareTrue,
892
922
  description: "Install specified versions of the 'typescript' package and exit.",
893
- group: 2,
923
+ group: OptionGroup.CommandLine,
894
924
  name: "install",
895
925
  },
896
926
  {
897
- brand: "bareTrue",
927
+ brand: OptionBrand.BareTrue,
898
928
  description: "Print the list of supported versions of the 'typescript' package and exit.",
899
- group: 2,
929
+ group: OptionGroup.CommandLine,
900
930
  name: "list",
901
931
  },
902
932
  {
903
- brand: "bareTrue",
933
+ brand: OptionBrand.BareTrue,
904
934
  description: "Print the list of the selected test files and exit.",
905
- group: 2,
935
+ group: OptionGroup.CommandLine,
906
936
  name: "listFiles",
907
937
  },
908
938
  {
909
- brand: "string",
939
+ brand: OptionBrand.String,
910
940
  description: "Only run tests with matching name.",
911
- group: 2,
941
+ group: OptionGroup.CommandLine,
912
942
  name: "only",
913
943
  },
914
944
  {
915
- brand: "list",
945
+ brand: OptionBrand.List,
916
946
  description: "The list of plugins to use.",
917
- group: 2 | 4,
947
+ group: OptionGroup.CommandLine | OptionGroup.ConfigFile,
918
948
  items: {
919
- brand: "string",
949
+ brand: OptionBrand.String,
920
950
  name: "plugins",
921
951
  },
922
952
  name: "plugins",
923
953
  },
924
954
  {
925
- brand: "bareTrue",
955
+ brand: OptionBrand.BareTrue,
926
956
  description: "Remove all installed versions of the 'typescript' package and exit.",
927
- group: 2,
957
+ group: OptionGroup.CommandLine,
928
958
  name: "prune",
929
959
  },
930
960
  {
931
- brand: "boolean",
961
+ brand: OptionBrand.Boolean,
932
962
  description: "Reject the 'any' type passed as an argument to the 'expect()' function or a matcher.",
933
- group: 4,
963
+ group: OptionGroup.ConfigFile,
934
964
  name: "rejectAnyType",
935
965
  },
936
966
  {
937
- brand: "boolean",
967
+ brand: OptionBrand.Boolean,
938
968
  description: "Reject the 'never' type passed as an argument to the 'expect()' function or a matcher.",
939
- group: 4,
969
+ group: OptionGroup.ConfigFile,
940
970
  name: "rejectNeverType",
941
971
  },
942
972
  {
943
- brand: "list",
973
+ brand: OptionBrand.List,
944
974
  description: "The list of reporters to use.",
945
- group: 2 | 4,
975
+ group: OptionGroup.CommandLine | OptionGroup.ConfigFile,
946
976
  items: {
947
- brand: "string",
977
+ brand: OptionBrand.String,
948
978
  name: "reporters",
949
979
  },
950
980
  name: "reporters",
951
981
  },
952
982
  {
953
- brand: "string",
983
+ brand: OptionBrand.String,
954
984
  description: "The path to a directory containing files of a test project.",
955
- group: 4,
985
+ group: OptionGroup.ConfigFile,
956
986
  name: "rootPath",
957
987
  },
958
988
  {
959
- brand: "bareTrue",
989
+ brand: OptionBrand.BareTrue,
960
990
  description: "Print the resolved configuration and exit.",
961
- group: 2,
991
+ group: OptionGroup.CommandLine,
962
992
  name: "showConfig",
963
993
  },
964
994
  {
965
- brand: "string",
995
+ brand: OptionBrand.String,
966
996
  description: "Skip tests with matching name.",
967
- group: 2,
997
+ group: OptionGroup.CommandLine,
968
998
  name: "skip",
969
999
  },
970
1000
  {
971
- brand: "list",
1001
+ brand: OptionBrand.List,
972
1002
  description: "The list of TypeScript versions to be tested on.",
973
- group: 2 | 4,
1003
+ group: OptionGroup.CommandLine | OptionGroup.ConfigFile,
974
1004
  items: {
975
- brand: "string",
1005
+ brand: OptionBrand.String,
976
1006
  name: "target",
977
1007
  },
978
1008
  name: "target",
979
1009
  },
980
1010
  {
981
- brand: "list",
1011
+ brand: OptionBrand.List,
982
1012
  description: "The list of glob patterns matching the test files.",
983
- group: 4,
1013
+ group: OptionGroup.ConfigFile,
984
1014
  items: {
985
- brand: "string",
1015
+ brand: OptionBrand.String,
986
1016
  name: "testFileMatch",
987
1017
  },
988
1018
  name: "testFileMatch",
989
1019
  },
990
1020
  {
991
- brand: "string",
1021
+ brand: OptionBrand.String,
992
1022
  description: "The look up strategy to be used to find the TSConfig file.",
993
- group: 2 | 4,
1023
+ group: OptionGroup.CommandLine | OptionGroup.ConfigFile,
994
1024
  name: "tsconfig",
995
1025
  },
996
1026
  {
997
- brand: "bareTrue",
1027
+ brand: OptionBrand.BareTrue,
998
1028
  description: "Fetch the 'typescript' package metadata from the registry and exit.",
999
- group: 2,
1029
+ group: OptionGroup.CommandLine,
1000
1030
  name: "update",
1001
1031
  },
1002
1032
  {
1003
- brand: "bareTrue",
1033
+ brand: OptionBrand.BareTrue,
1004
1034
  description: "Print the version number and exit.",
1005
- group: 2,
1035
+ group: OptionGroup.CommandLine,
1006
1036
  name: "version",
1007
1037
  },
1008
1038
  {
1009
- brand: "bareTrue",
1039
+ brand: OptionBrand.BareTrue,
1010
1040
  description: "Watch for changes and rerun related test files.",
1011
- group: 2,
1041
+ group: OptionGroup.CommandLine,
1012
1042
  name: "watch",
1013
1043
  },
1014
1044
  ];
@@ -1125,7 +1155,7 @@ class CommandLineParser {
1125
1155
  this.#commandLineOptions = commandLine;
1126
1156
  this.#pathMatch = pathMatch;
1127
1157
  this.#onDiagnostics = onDiagnostics;
1128
- this.#options = Options.for(2);
1158
+ this.#options = Options.for(OptionGroup.CommandLine);
1129
1159
  }
1130
1160
  async #onExpectsValue(optionName, optionBrand) {
1131
1161
  const text = [
@@ -1160,18 +1190,18 @@ class CommandLineParser {
1160
1190
  async #parseOptionValue(commandLineArgs, index, optionName, optionDefinition) {
1161
1191
  let optionValue = this.#resolveOptionValue(commandLineArgs[index]);
1162
1192
  switch (optionDefinition.brand) {
1163
- case "bareTrue":
1193
+ case OptionBrand.BareTrue:
1164
1194
  await Options.validate(optionName, optionValue, optionDefinition.brand, this.#onDiagnostics);
1165
1195
  this.#commandLineOptions[optionDefinition.name] = true;
1166
1196
  break;
1167
- case "boolean":
1197
+ case OptionBrand.Boolean:
1168
1198
  await Options.validate(optionName, optionValue, optionDefinition.brand, this.#onDiagnostics);
1169
1199
  this.#commandLineOptions[optionDefinition.name] = optionValue !== "false";
1170
1200
  if (optionValue === "false" || optionValue === "true") {
1171
1201
  index++;
1172
1202
  }
1173
1203
  break;
1174
- case "list":
1204
+ case OptionBrand.List:
1175
1205
  if (optionValue !== "") {
1176
1206
  const optionValues = optionValue
1177
1207
  .split(",")
@@ -1187,7 +1217,7 @@ class CommandLineParser {
1187
1217
  }
1188
1218
  await this.#onExpectsValue(optionName, optionDefinition.brand);
1189
1219
  break;
1190
- case "string":
1220
+ case OptionBrand.String:
1191
1221
  if (optionValue !== "") {
1192
1222
  optionValue = Options.resolve(optionName, optionValue);
1193
1223
  await Options.validate(optionName, optionValue, optionDefinition.brand, this.#onDiagnostics);
@@ -1343,7 +1373,7 @@ class ConfigFileParser {
1343
1373
  this.#configFileOptions = configFileOptions;
1344
1374
  this.#sourceFile = sourceFile;
1345
1375
  this.#onDiagnostics = onDiagnostics;
1346
- this.#options = Options.for(4);
1376
+ this.#options = Options.for(OptionGroup.ConfigFile);
1347
1377
  this.#jsonScanner = new JsonScanner(this.#sourceFile);
1348
1378
  }
1349
1379
  #onRequiresValue(optionDefinition, jsonNode, isListItem) {
@@ -1356,7 +1386,7 @@ class ConfigFileParser {
1356
1386
  let jsonNode;
1357
1387
  let optionValue;
1358
1388
  switch (optionDefinition.brand) {
1359
- case "boolean": {
1389
+ case OptionBrand.Boolean: {
1360
1390
  jsonNode = this.#jsonScanner.read();
1361
1391
  optionValue = jsonNode.getValue();
1362
1392
  if (typeof optionValue !== "boolean") {
@@ -1365,7 +1395,7 @@ class ConfigFileParser {
1365
1395
  }
1366
1396
  break;
1367
1397
  }
1368
- case "string": {
1398
+ case OptionBrand.String: {
1369
1399
  jsonNode = this.#jsonScanner.read();
1370
1400
  optionValue = jsonNode.getValue();
1371
1401
  if (typeof optionValue !== "string") {
@@ -1377,7 +1407,7 @@ class ConfigFileParser {
1377
1407
  await Options.validate(optionDefinition.name, optionValue, optionDefinition.brand, this.#onDiagnostics, jsonNode.origin);
1378
1408
  break;
1379
1409
  }
1380
- case "list": {
1410
+ case OptionBrand.List: {
1381
1411
  optionValue = [];
1382
1412
  const leftBracketToken = this.#jsonScanner.readToken("[");
1383
1413
  if (!leftBracketToken.text) {
@@ -1474,6 +1504,7 @@ class ConfigFileParser {
1474
1504
  }
1475
1505
 
1476
1506
  const defaultOptions = {
1507
+ checkSourceFiles: false,
1477
1508
  failFast: false,
1478
1509
  plugins: [],
1479
1510
  rejectAnyType: false,
@@ -1535,22 +1566,6 @@ class Config {
1535
1566
  }
1536
1567
  }
1537
1568
 
1538
- var OptionBrand;
1539
- (function (OptionBrand) {
1540
- OptionBrand["String"] = "string";
1541
- OptionBrand["Number"] = "number";
1542
- OptionBrand["Boolean"] = "boolean";
1543
- OptionBrand["BareTrue"] = "bareTrue";
1544
- OptionBrand["List"] = "list";
1545
- })(OptionBrand || (OptionBrand = {}));
1546
-
1547
- var OptionGroup;
1548
- (function (OptionGroup) {
1549
- OptionGroup[OptionGroup["CommandLine"] = 2] = "CommandLine";
1550
- OptionGroup[OptionGroup["ConfigFile"] = 4] = "ConfigFile";
1551
- OptionGroup[OptionGroup["ResolvedConfig"] = 6] = "ResolvedConfig";
1552
- })(OptionGroup || (OptionGroup = {}));
1553
-
1554
1569
  class CancellationHandler {
1555
1570
  #cancellationToken;
1556
1571
  #cancellationReason;
@@ -1560,7 +1575,7 @@ class CancellationHandler {
1560
1575
  }
1561
1576
  on([, payload]) {
1562
1577
  if ("diagnostics" in payload) {
1563
- if (payload.diagnostics.some((diagnostic) => diagnostic.category === "error")) {
1578
+ if (payload.diagnostics.some((diagnostic) => diagnostic.category === DiagnosticCategory.Error)) {
1564
1579
  this.#cancellationToken.cancel(this.#cancellationReason);
1565
1580
  }
1566
1581
  }
@@ -1574,7 +1589,7 @@ class ExitCodeHandler {
1574
1589
  return;
1575
1590
  }
1576
1591
  if ("diagnostics" in payload) {
1577
- if (payload.diagnostics.some((diagnostic) => diagnostic.category === "error")) {
1592
+ if (payload.diagnostics.some((diagnostic) => diagnostic.category === DiagnosticCategory.Error)) {
1578
1593
  this.#setCode(1);
1579
1594
  }
1580
1595
  }
@@ -1606,11 +1621,20 @@ class DescribeResult {
1606
1621
  }
1607
1622
  }
1608
1623
 
1624
+ var ResultStatus;
1625
+ (function (ResultStatus) {
1626
+ ResultStatus["Runs"] = "runs";
1627
+ ResultStatus["Passed"] = "passed";
1628
+ ResultStatus["Failed"] = "failed";
1629
+ ResultStatus["Skipped"] = "skipped";
1630
+ ResultStatus["Todo"] = "todo";
1631
+ })(ResultStatus || (ResultStatus = {}));
1632
+
1609
1633
  class ExpectResult {
1610
1634
  assertion;
1611
1635
  diagnostics = [];
1612
1636
  parent;
1613
- status = "runs";
1637
+ status = ResultStatus.Runs;
1614
1638
  timing = new ResultTiming();
1615
1639
  constructor(assertion, parent) {
1616
1640
  this.assertion = assertion;
@@ -1654,18 +1678,9 @@ class Result {
1654
1678
  }
1655
1679
  }
1656
1680
 
1657
- var ResultStatus;
1658
- (function (ResultStatus) {
1659
- ResultStatus["Runs"] = "runs";
1660
- ResultStatus["Passed"] = "passed";
1661
- ResultStatus["Failed"] = "failed";
1662
- ResultStatus["Skipped"] = "skipped";
1663
- ResultStatus["Todo"] = "todo";
1664
- })(ResultStatus || (ResultStatus = {}));
1665
-
1666
1681
  class TargetResult {
1667
1682
  results = new Map();
1668
- status = "runs";
1683
+ status = ResultStatus.Runs;
1669
1684
  target;
1670
1685
  tasks;
1671
1686
  timing = new ResultTiming();
@@ -1679,7 +1694,7 @@ class TaskResult {
1679
1694
  diagnostics = [];
1680
1695
  expectCount = new ResultCount();
1681
1696
  results = [];
1682
- status = "runs";
1697
+ status = ResultStatus.Runs;
1683
1698
  task;
1684
1699
  testCount = new ResultCount();
1685
1700
  timing = new ResultTiming();
@@ -1693,7 +1708,7 @@ class TestResult {
1693
1708
  expectCount = new ResultCount();
1694
1709
  parent;
1695
1710
  results = [];
1696
- status = "runs";
1711
+ status = ResultStatus.Runs;
1697
1712
  test;
1698
1713
  timing = new ResultTiming();
1699
1714
  constructor(test, parent) {
@@ -1726,19 +1741,19 @@ class ResultHandler {
1726
1741
  this.#targetResult.timing.start = Date.now();
1727
1742
  break;
1728
1743
  case "target:end":
1729
- if (this.#targetResult.status === "failed") {
1744
+ if (this.#targetResult.status === ResultStatus.Failed) {
1730
1745
  this.#result.targetCount.failed++;
1731
1746
  }
1732
1747
  else {
1733
1748
  this.#result.targetCount.passed++;
1734
- this.#targetResult.status = "passed";
1749
+ this.#targetResult.status = ResultStatus.Passed;
1735
1750
  }
1736
1751
  this.#targetResult.timing.end = Date.now();
1737
1752
  this.#targetResult = undefined;
1738
1753
  break;
1739
1754
  case "store:error":
1740
- if (payload.diagnostics.some(({ category }) => category === "error")) {
1741
- this.#targetResult.status = "failed";
1755
+ if (payload.diagnostics.some(({ category }) => category === DiagnosticCategory.Error)) {
1756
+ this.#targetResult.status = ResultStatus.Failed;
1742
1757
  }
1743
1758
  break;
1744
1759
  case "project:uses": {
@@ -1751,7 +1766,7 @@ class ResultHandler {
1751
1766
  break;
1752
1767
  }
1753
1768
  case "project:error":
1754
- this.#targetResult.status = "failed";
1769
+ this.#targetResult.status = ResultStatus.Failed;
1755
1770
  this.#projectResult.diagnostics.push(...payload.diagnostics);
1756
1771
  break;
1757
1772
  case "task:start":
@@ -1760,21 +1775,21 @@ class ResultHandler {
1760
1775
  this.#taskResult.timing.start = Date.now();
1761
1776
  break;
1762
1777
  case "task:error":
1763
- this.#targetResult.status = "failed";
1764
- this.#taskResult.status = "failed";
1778
+ this.#targetResult.status = ResultStatus.Failed;
1779
+ this.#taskResult.status = ResultStatus.Failed;
1765
1780
  this.#taskResult.diagnostics.push(...payload.diagnostics);
1766
1781
  break;
1767
1782
  case "task:end":
1768
- if (this.#taskResult.status === "failed" ||
1783
+ if (this.#taskResult.status === ResultStatus.Failed ||
1769
1784
  this.#taskResult.expectCount.failed > 0 ||
1770
1785
  this.#taskResult.testCount.failed > 0) {
1771
1786
  this.#result.fileCount.failed++;
1772
- this.#targetResult.status = "failed";
1773
- this.#taskResult.status = "failed";
1787
+ this.#targetResult.status = ResultStatus.Failed;
1788
+ this.#taskResult.status = ResultStatus.Failed;
1774
1789
  }
1775
1790
  else {
1776
1791
  this.#result.fileCount.passed++;
1777
- this.#taskResult.status = "passed";
1792
+ this.#taskResult.status = ResultStatus.Passed;
1778
1793
  }
1779
1794
  this.#taskResult.timing.end = Date.now();
1780
1795
  this.#taskResult = undefined;
@@ -1806,7 +1821,7 @@ class ResultHandler {
1806
1821
  case "test:error":
1807
1822
  this.#result.testCount.failed++;
1808
1823
  this.#taskResult.testCount.failed++;
1809
- this.#testResult.status = "failed";
1824
+ this.#testResult.status = ResultStatus.Failed;
1810
1825
  this.#testResult.diagnostics.push(...payload.diagnostics);
1811
1826
  this.#testResult.timing.end = Date.now();
1812
1827
  this.#testResult = undefined;
@@ -1814,28 +1829,28 @@ class ResultHandler {
1814
1829
  case "test:fail":
1815
1830
  this.#result.testCount.failed++;
1816
1831
  this.#taskResult.testCount.failed++;
1817
- this.#testResult.status = "failed";
1832
+ this.#testResult.status = ResultStatus.Failed;
1818
1833
  this.#testResult.timing.end = Date.now();
1819
1834
  this.#testResult = undefined;
1820
1835
  break;
1821
1836
  case "test:pass":
1822
1837
  this.#result.testCount.passed++;
1823
1838
  this.#taskResult.testCount.passed++;
1824
- this.#testResult.status = "passed";
1839
+ this.#testResult.status = ResultStatus.Passed;
1825
1840
  this.#testResult.timing.end = Date.now();
1826
1841
  this.#testResult = undefined;
1827
1842
  break;
1828
1843
  case "test:skip":
1829
1844
  this.#result.testCount.skipped++;
1830
1845
  this.#taskResult.testCount.skipped++;
1831
- this.#testResult.status = "skipped";
1846
+ this.#testResult.status = ResultStatus.Skipped;
1832
1847
  this.#testResult.timing.end = Date.now();
1833
1848
  this.#testResult = undefined;
1834
1849
  break;
1835
1850
  case "test:todo":
1836
1851
  this.#result.testCount.todo++;
1837
1852
  this.#taskResult.testCount.todo++;
1838
- this.#testResult.status = "todo";
1853
+ this.#testResult.status = ResultStatus.Todo;
1839
1854
  this.#testResult.timing.end = Date.now();
1840
1855
  this.#testResult = undefined;
1841
1856
  break;
@@ -1855,7 +1870,7 @@ class ResultHandler {
1855
1870
  if (this.#testResult) {
1856
1871
  this.#testResult.expectCount.failed++;
1857
1872
  }
1858
- this.#expectResult.status = "failed";
1873
+ this.#expectResult.status = ResultStatus.Failed;
1859
1874
  this.#expectResult.diagnostics.push(...payload.diagnostics);
1860
1875
  this.#expectResult.timing.end = Date.now();
1861
1876
  this.#expectResult = undefined;
@@ -1866,7 +1881,7 @@ class ResultHandler {
1866
1881
  if (this.#testResult) {
1867
1882
  this.#testResult.expectCount.failed++;
1868
1883
  }
1869
- this.#expectResult.status = "failed";
1884
+ this.#expectResult.status = ResultStatus.Failed;
1870
1885
  this.#expectResult.timing.end = Date.now();
1871
1886
  this.#expectResult = undefined;
1872
1887
  break;
@@ -1876,7 +1891,7 @@ class ResultHandler {
1876
1891
  if (this.#testResult) {
1877
1892
  this.#testResult.expectCount.passed++;
1878
1893
  }
1879
- this.#expectResult.status = "passed";
1894
+ this.#expectResult.status = ResultStatus.Passed;
1880
1895
  this.#expectResult.timing.end = Date.now();
1881
1896
  this.#expectResult = undefined;
1882
1897
  break;
@@ -1886,7 +1901,7 @@ class ResultHandler {
1886
1901
  if (this.#testResult) {
1887
1902
  this.#testResult.expectCount.skipped++;
1888
1903
  }
1889
- this.#expectResult.status = "skipped";
1904
+ this.#expectResult.status = ResultStatus.Skipped;
1890
1905
  this.#expectResult.timing.end = Date.now();
1891
1906
  this.#expectResult = undefined;
1892
1907
  break;
@@ -1915,7 +1930,7 @@ function Text({ children, color, indent }) {
1915
1930
  if (color != null) {
1916
1931
  ansiEscapes.push(color);
1917
1932
  }
1918
- return (jsx("text", { indent: indent ?? 0, children: [ansiEscapes.length > 0 ? jsx("ansi", { escapes: ansiEscapes }) : undefined, children, ansiEscapes.length > 0 ? jsx("ansi", { escapes: "0" }) : undefined] }));
1933
+ return (jsx("text", { indent: indent ?? 0, children: [ansiEscapes.length > 0 ? jsx("ansi", { escapes: ansiEscapes }) : undefined, children, ansiEscapes.length > 0 ? jsx("ansi", { escapes: Color.Reset }) : undefined] }));
1919
1934
  }
1920
1935
 
1921
1936
  function Line({ children, color, indent }) {
@@ -1976,7 +1991,7 @@ class Scribbler {
1976
1991
  }
1977
1992
 
1978
1993
  function addsPackageText(packageVersion, packagePath) {
1979
- return (jsx(Line, { children: [jsx(Text, { color: "90", children: "adds" }), " TypeScript ", packageVersion, jsx(Text, { color: "90", children: [" to ", packagePath] })] }));
1994
+ return (jsx(Line, { children: [jsx(Text, { color: Color.Gray, children: "adds" }), " TypeScript ", packageVersion, jsx(Text, { color: Color.Gray, children: [" to ", packagePath] })] }));
1980
1995
  }
1981
1996
 
1982
1997
  function describeNameText(name, indent = 0) {
@@ -1990,13 +2005,13 @@ function BreadcrumbsText({ ancestor }) {
1990
2005
  ancestor = ancestor.parent;
1991
2006
  }
1992
2007
  text.push("");
1993
- return jsx(Text, { color: "90", children: text.reverse().join(" ❭ ") });
2008
+ return jsx(Text, { color: Color.Gray, children: text.reverse().join(" ❭ ") });
1994
2009
  }
1995
- function CodeLineText({ gutterWidth, lineNumber, lineNumberColor = "90", lineText }) {
1996
- return (jsx(Line, { children: [jsx(Text, { color: lineNumberColor, children: lineNumber.toString().padStart(gutterWidth) }), jsx(Text, { color: "90", children: " | " }), lineText] }));
2010
+ function CodeLineText({ gutterWidth, lineNumber, lineNumberColor = Color.Gray, lineText }) {
2011
+ return (jsx(Line, { children: [jsx(Text, { color: lineNumberColor, children: lineNumber.toString().padStart(gutterWidth) }), jsx(Text, { color: Color.Gray, children: " | " }), lineText] }));
1997
2012
  }
1998
2013
  function SquiggleLineText({ gutterWidth, indentWidth = 0, squiggleColor, squiggleWidth }) {
1999
- return (jsx(Line, { children: [" ".repeat(gutterWidth), jsx(Text, { color: "90", children: " | " }), " ".repeat(indentWidth), jsx(Text, { color: squiggleColor, children: "~".repeat(squiggleWidth === 0 ? 1 : squiggleWidth) })] }));
2014
+ return (jsx(Line, { children: [" ".repeat(gutterWidth), jsx(Text, { color: Color.Gray, children: " | " }), " ".repeat(indentWidth), jsx(Text, { color: squiggleColor, children: "~".repeat(squiggleWidth === 0 ? 1 : squiggleWidth) })] }));
2000
2015
  }
2001
2016
  function CodeSpanText({ diagnosticCategory, diagnosticOrigin }) {
2002
2017
  const lineMap = diagnosticOrigin.sourceFile.getLineStarts();
@@ -2007,11 +2022,11 @@ function CodeSpanText({ diagnosticCategory, diagnosticOrigin }) {
2007
2022
  const gutterWidth = (lastLine + 1).toString().length + 2;
2008
2023
  let highlightColor;
2009
2024
  switch (diagnosticCategory) {
2010
- case "error":
2011
- highlightColor = "31";
2025
+ case DiagnosticCategory.Error:
2026
+ highlightColor = Color.Red;
2012
2027
  break;
2013
- case "warning":
2014
- highlightColor = "33";
2028
+ case DiagnosticCategory.Warning:
2029
+ highlightColor = Color.Yellow;
2015
2030
  break;
2016
2031
  }
2017
2032
  const codeSpan = [];
@@ -2038,14 +2053,14 @@ function CodeSpanText({ diagnosticCategory, diagnosticOrigin }) {
2038
2053
  codeSpan.push(jsx(CodeLineText, { gutterWidth: gutterWidth, lineNumber: index + 1, lineText: lineText }));
2039
2054
  }
2040
2055
  }
2041
- const location = (jsx(Line, { children: [" ".repeat(gutterWidth + 2), jsx(Text, { color: "90", children: " at " }), jsx(Text, { color: "36", children: Path.relative("", diagnosticOrigin.sourceFile.fileName) }), jsx(Text, { color: "90", children: `:${firstMarkedLine + 1}:${firstMarkedLineCharacter + 1}` }), diagnosticOrigin.assertion && jsx(BreadcrumbsText, { ancestor: diagnosticOrigin.assertion.parent })] }));
2056
+ const location = (jsx(Line, { children: [" ".repeat(gutterWidth + 2), jsx(Text, { color: Color.Gray, children: " at " }), jsx(Text, { color: Color.Cyan, children: Path.relative("", diagnosticOrigin.sourceFile.fileName) }), jsx(Text, { color: Color.Gray, children: `:${firstMarkedLine + 1}:${firstMarkedLineCharacter + 1}` }), diagnosticOrigin.assertion && jsx(BreadcrumbsText, { ancestor: diagnosticOrigin.assertion.parent })] }));
2042
2057
  return (jsx(Text, { children: [codeSpan, jsx(Line, {}), location] }));
2043
2058
  }
2044
2059
 
2045
2060
  function DiagnosticText({ diagnostic }) {
2046
- const code = diagnostic.code ? jsx(Text, { color: "90", children: [" ", diagnostic.code] }) : undefined;
2061
+ const code = diagnostic.code ? jsx(Text, { color: Color.Gray, children: [" ", diagnostic.code] }) : undefined;
2047
2062
  const text = Array.isArray(diagnostic.text) ? diagnostic.text : [diagnostic.text];
2048
- const message = text.map((text, index) => (jsx(Text, { children: [index === 1 ? jsx(Line, {}) : undefined, jsx(Line, { children: [text, code] })] })));
2063
+ const message = text.map((text, index) => (jsx(Text, { children: [index === 1 ? jsx(Line, {}) : undefined, jsx(Line, { children: [text, index === 0 ? code : undefined] })] })));
2049
2064
  const related = diagnostic.related?.map((relatedDiagnostic) => jsx(DiagnosticText, { diagnostic: relatedDiagnostic }));
2050
2065
  const codeSpan = diagnostic.origin ? (jsx(Text, { children: [jsx(Line, {}), jsx(CodeSpanText, { diagnosticCategory: diagnostic.category, diagnosticOrigin: diagnostic.origin })] })) : undefined;
2051
2066
  return (jsx(Text, { children: [message, codeSpan, jsx(Line, {}), jsx(Text, { indent: 2, children: related })] }));
@@ -2053,11 +2068,11 @@ function DiagnosticText({ diagnostic }) {
2053
2068
  function diagnosticText(diagnostic) {
2054
2069
  let prefix;
2055
2070
  switch (diagnostic.category) {
2056
- case "error":
2057
- prefix = jsx(Text, { color: "31", children: "Error: " });
2071
+ case DiagnosticCategory.Error:
2072
+ prefix = jsx(Text, { color: Color.Red, children: "Error: " });
2058
2073
  break;
2059
- case "warning":
2060
- prefix = jsx(Text, { color: "33", children: "Warning: " });
2074
+ case DiagnosticCategory.Warning:
2075
+ prefix = jsx(Text, { color: Color.Yellow, children: "Warning: " });
2061
2076
  break;
2062
2077
  }
2063
2078
  return (jsx(Text, { children: [prefix, jsx(DiagnosticText, { diagnostic: diagnostic })] }));
@@ -2068,22 +2083,22 @@ function FileNameText({ filePath }) {
2068
2083
  const lastPathSeparator = relativePath.lastIndexOf("/");
2069
2084
  const directoryNameText = relativePath.slice(0, lastPathSeparator + 1);
2070
2085
  const fileNameText = relativePath.slice(lastPathSeparator + 1);
2071
- return (jsx(Text, { children: [jsx(Text, { color: "90", children: directoryNameText }), fileNameText] }));
2086
+ return (jsx(Text, { children: [jsx(Text, { color: Color.Gray, children: directoryNameText }), fileNameText] }));
2072
2087
  }
2073
2088
  function taskStatusText(status, task) {
2074
2089
  let statusColor;
2075
2090
  let statusText;
2076
2091
  switch (status) {
2077
- case "runs":
2078
- statusColor = "33";
2092
+ case ResultStatus.Runs:
2093
+ statusColor = Color.Yellow;
2079
2094
  statusText = "runs";
2080
2095
  break;
2081
- case "passed":
2082
- statusColor = "32";
2096
+ case ResultStatus.Passed:
2097
+ statusColor = Color.Green;
2083
2098
  statusText = "pass";
2084
2099
  break;
2085
- case "failed":
2086
- statusColor = "31";
2100
+ case ResultStatus.Failed:
2101
+ statusColor = Color.Red;
2087
2102
  statusText = "fail";
2088
2103
  break;
2089
2104
  }
@@ -2113,13 +2128,13 @@ function formattedText(input) {
2113
2128
  }
2114
2129
 
2115
2130
  function HintText({ children }) {
2116
- return (jsx(Text, { indent: 1, color: "90", children: children }));
2131
+ return (jsx(Text, { indent: 1, color: Color.Gray, children: children }));
2117
2132
  }
2118
2133
  function HelpHeaderText({ tstycheVersion }) {
2119
2134
  return (jsx(Line, { children: ["The TSTyche Type Test Runner", jsx(HintText, { children: tstycheVersion })] }));
2120
2135
  }
2121
2136
  function CommandText({ hint, text }) {
2122
- return (jsx(Line, { indent: 1, children: [jsx(Text, { color: "34", children: text }), hint && jsx(HintText, { children: hint })] }));
2137
+ return (jsx(Line, { indent: 1, children: [jsx(Text, { color: Color.Blue, children: text }), hint && jsx(HintText, { children: hint })] }));
2123
2138
  }
2124
2139
  function OptionDescriptionText({ text }) {
2125
2140
  return jsx(Line, { indent: 1, children: text });
@@ -2137,7 +2152,7 @@ function CommandLineOptionNameText({ text }) {
2137
2152
  return jsx(Text, { children: `--${text}` });
2138
2153
  }
2139
2154
  function CommandLineOptionHintText({ definition }) {
2140
- if (definition.brand === "list") {
2155
+ if (definition.brand === OptionBrand.List) {
2141
2156
  return jsx(Text, { children: `${definition.brand} of ${definition.items.brand}s` });
2142
2157
  }
2143
2158
  return jsx(Text, { children: definition.brand });
@@ -2146,7 +2161,7 @@ function CommandLineOptionsText({ optionDefinitions }) {
2146
2161
  const definitions = [...optionDefinitions.values()];
2147
2162
  const optionsText = definitions.map((definition) => {
2148
2163
  let hint;
2149
- if (definition.brand !== "bareTrue") {
2164
+ if (definition.brand !== OptionBrand.BareTrue) {
2150
2165
  hint = jsx(CommandLineOptionHintText, { definition: definition });
2151
2166
  }
2152
2167
  return (jsx(Text, { children: [jsx(CommandText, { text: jsx(CommandLineOptionNameText, { text: definition.name }), hint: hint }), jsx(OptionDescriptionText, { text: definition.description }), jsx(Line, {})] }));
@@ -2196,7 +2211,7 @@ function RowText({ label, text }) {
2196
2211
  return (jsx(Line, { children: [`${label}:`.padEnd(12), text] }));
2197
2212
  }
2198
2213
  function CountText({ failed, passed, skipped, todo, total }) {
2199
- return (jsx(Text, { children: [failed > 0 ? (jsx(Text, { children: [jsx(Text, { color: "31", children: [failed, " failed"] }), jsx(Text, { children: ", " })] })) : undefined, skipped > 0 ? (jsx(Text, { children: [jsx(Text, { color: "33", children: [skipped, " skipped"] }), jsx(Text, { children: ", " })] })) : undefined, todo > 0 ? (jsx(Text, { children: [jsx(Text, { color: "35", children: [todo, " todo"] }), jsx(Text, { children: ", " })] })) : undefined, passed > 0 ? (jsx(Text, { children: [jsx(Text, { color: "32", children: [passed, " passed"] }), jsx(Text, { children: ", " })] })) : undefined, jsx(Text, { children: [total, " total"] })] }));
2214
+ return (jsx(Text, { children: [failed > 0 ? (jsx(Text, { children: [jsx(Text, { color: Color.Red, children: [failed, " failed"] }), jsx(Text, { children: ", " })] })) : undefined, skipped > 0 ? (jsx(Text, { children: [jsx(Text, { color: Color.Yellow, children: [skipped, " skipped"] }), jsx(Text, { children: ", " })] })) : undefined, todo > 0 ? (jsx(Text, { children: [jsx(Text, { color: Color.Magenta, children: [todo, " todo"] }), jsx(Text, { children: ", " })] })) : undefined, passed > 0 ? (jsx(Text, { children: [jsx(Text, { color: Color.Green, children: [passed, " passed"] }), jsx(Text, { children: ", " })] })) : undefined, jsx(Text, { children: [total, " total"] })] }));
2200
2215
  }
2201
2216
  function DurationText({ seconds }) {
2202
2217
  return jsx(Text, { children: `${Math.round(seconds * 10) / 10}s` });
@@ -2209,24 +2224,24 @@ function MatchText({ text }) {
2209
2224
  return jsx(Text, { children: ["'", ...text, "'"] });
2210
2225
  }
2211
2226
  const lastItem = text.pop();
2212
- return (jsx(Text, { children: [text.map((match, index, list) => (jsx(Text, { children: ["'", match, "'", index === list.length - 1 ? jsx(Text, { children: " " }) : jsx(Text, { color: "90", children: ", " })] }))), jsx(Text, { color: "90", children: "or" }), " '", lastItem, "'"] }));
2227
+ return (jsx(Text, { children: [text.map((match, index, list) => (jsx(Text, { children: ["'", match, "'", index === list.length - 1 ? jsx(Text, { children: " " }) : jsx(Text, { color: Color.Gray, children: ", " })] }))), jsx(Text, { color: Color.Gray, children: "or" }), " '", lastItem, "'"] }));
2213
2228
  }
2214
2229
  function RanFilesText({ onlyMatch, pathMatch, skipMatch }) {
2215
2230
  const testNameMatchText = [];
2216
2231
  if (onlyMatch != null) {
2217
- testNameMatchText.push(jsx(Text, { children: [jsx(Text, { color: "90", children: "matching " }), jsx(MatchText, { text: onlyMatch })] }));
2232
+ testNameMatchText.push(jsx(Text, { children: [jsx(Text, { color: Color.Gray, children: "matching " }), jsx(MatchText, { text: onlyMatch })] }));
2218
2233
  }
2219
2234
  if (skipMatch != null) {
2220
- testNameMatchText.push(jsx(Text, { children: [onlyMatch && jsx(Text, { color: "90", children: " and " }), jsx(Text, { color: "90", children: "not matching " }), jsx(MatchText, { text: skipMatch })] }));
2235
+ testNameMatchText.push(jsx(Text, { children: [onlyMatch && jsx(Text, { color: Color.Gray, children: " and " }), jsx(Text, { color: Color.Gray, children: "not matching " }), jsx(MatchText, { text: skipMatch })] }));
2221
2236
  }
2222
2237
  let pathMatchText;
2223
2238
  if (pathMatch.length > 0) {
2224
- pathMatchText = (jsx(Text, { children: [jsx(Text, { color: "90", children: "test files matching " }), jsx(MatchText, { text: pathMatch }), jsx(Text, { color: "90", children: "." })] }));
2239
+ pathMatchText = (jsx(Text, { children: [jsx(Text, { color: Color.Gray, children: "test files matching " }), jsx(MatchText, { text: pathMatch }), jsx(Text, { color: Color.Gray, children: "." })] }));
2225
2240
  }
2226
2241
  else {
2227
- pathMatchText = jsx(Text, { color: "90", children: "all test files." });
2242
+ pathMatchText = jsx(Text, { color: Color.Gray, children: "all test files." });
2228
2243
  }
2229
- return (jsx(Line, { children: [jsx(Text, { color: "90", children: "Ran " }), testNameMatchText.length > 0 ? jsx(Text, { color: "90", children: "tests " }) : undefined, testNameMatchText, testNameMatchText.length > 0 ? jsx(Text, { color: "90", children: " in " }) : undefined, pathMatchText] }));
2244
+ return (jsx(Line, { children: [jsx(Text, { color: Color.Gray, children: "Ran " }), testNameMatchText.length > 0 ? jsx(Text, { color: Color.Gray, children: "tests " }) : undefined, testNameMatchText, testNameMatchText.length > 0 ? jsx(Text, { color: Color.Gray, children: " in " }) : undefined, pathMatchText] }));
2230
2245
  }
2231
2246
  function summaryText({ duration, expectCount, fileCount, onlyMatch, pathMatch, skipMatch, targetCount, testCount, }) {
2232
2247
  const targetCountText = (jsx(RowText, { label: "Targets", text: jsx(CountText, { failed: targetCount.failed, passed: targetCount.passed, skipped: targetCount.skipped, todo: targetCount.todo, total: targetCount.total }) }));
@@ -2239,25 +2254,25 @@ function summaryText({ duration, expectCount, fileCount, onlyMatch, pathMatch, s
2239
2254
  function StatusText({ status }) {
2240
2255
  switch (status) {
2241
2256
  case "fail":
2242
- return jsx(Text, { color: "31", children: "\u00D7" });
2257
+ return jsx(Text, { color: Color.Red, children: "\u00D7" });
2243
2258
  case "pass":
2244
- return jsx(Text, { color: "32", children: "+" });
2259
+ return jsx(Text, { color: Color.Green, children: "+" });
2245
2260
  case "skip":
2246
- return jsx(Text, { color: "33", children: "- skip" });
2261
+ return jsx(Text, { color: Color.Yellow, children: "- skip" });
2247
2262
  case "todo":
2248
- return jsx(Text, { color: "35", children: "- todo" });
2263
+ return jsx(Text, { color: Color.Magenta, children: "- todo" });
2249
2264
  }
2250
2265
  }
2251
2266
  function testNameText(status, name, indent = 0) {
2252
- return (jsx(Line, { indent: indent + 1, children: [jsx(StatusText, { status: status }), " ", jsx(Text, { color: "90", children: name })] }));
2267
+ return (jsx(Line, { indent: indent + 1, children: [jsx(StatusText, { status: status }), " ", jsx(Text, { color: Color.Gray, children: name })] }));
2253
2268
  }
2254
2269
 
2255
2270
  function usesCompilerText(compilerVersion, projectConfigFilePath, options) {
2256
2271
  let projectConfigPathText;
2257
2272
  if (projectConfigFilePath != null) {
2258
- projectConfigPathText = (jsx(Text, { color: "90", children: [" with ", Path.relative("", projectConfigFilePath)] }));
2273
+ projectConfigPathText = (jsx(Text, { color: Color.Gray, children: [" with ", Path.relative("", projectConfigFilePath)] }));
2259
2274
  }
2260
- return (jsx(Text, { children: [options?.prependEmptyLine ? jsx(Line, {}) : undefined, jsx(Line, { children: [jsx(Text, { color: "34", children: "uses" }), " TypeScript ", compilerVersion, projectConfigPathText] }), jsx(Line, {})] }));
2275
+ return (jsx(Text, { children: [options?.prependEmptyLine ? jsx(Line, {}) : undefined, jsx(Line, { children: [jsx(Text, { color: Color.Blue, children: "uses" }), " TypeScript ", compilerVersion, projectConfigPathText] }), jsx(Line, {})] }));
2261
2276
  }
2262
2277
 
2263
2278
  function waitingForFileChangesText() {
@@ -2270,7 +2285,7 @@ function watchUsageText() {
2270
2285
  ["x", "to exit."],
2271
2286
  ];
2272
2287
  const usageText = usage.map(([keyText, actionText]) => {
2273
- return (jsx(Line, { children: [jsx(Text, { color: "90", children: "Press" }), jsx(Text, { children: ` ${keyText} ` }), jsx(Text, { color: "90", children: actionText })] }));
2288
+ return (jsx(Line, { children: [jsx(Text, { color: Color.Gray, children: "Press" }), jsx(Text, { children: ` ${keyText} ` }), jsx(Text, { color: Color.Gray, children: actionText })] }));
2274
2289
  });
2275
2290
  return jsx(Text, { children: usageText });
2276
2291
  }
@@ -2335,12 +2350,11 @@ class FileView {
2335
2350
  }
2336
2351
 
2337
2352
  class ListReporter extends BaseReporter {
2338
- #currentCompilerVersion;
2339
- #currentProjectConfigFilePath;
2340
2353
  #fileCount = 0;
2341
2354
  #fileView = new FileView();
2342
2355
  #hasReportedAdds = false;
2343
2356
  #hasReportedError = false;
2357
+ #hasReportedUses = false;
2344
2358
  #isFileViewExpanded = false;
2345
2359
  #seenDeprecations = new Set();
2346
2360
  get #isLastFile() {
@@ -2371,21 +2385,14 @@ class ListReporter extends BaseReporter {
2371
2385
  break;
2372
2386
  case "target:start":
2373
2387
  this.#fileCount = payload.result.tasks.length;
2374
- break;
2375
- case "target:end":
2376
- this.#currentCompilerVersion = undefined;
2377
- this.#currentProjectConfigFilePath = undefined;
2388
+ this.#hasReportedUses = false;
2378
2389
  break;
2379
2390
  case "project:uses":
2380
- if (this.#currentCompilerVersion !== payload.compilerVersion ||
2381
- this.#currentProjectConfigFilePath !== payload.projectConfigFilePath) {
2382
- OutputService.writeMessage(usesCompilerText(payload.compilerVersion, payload.projectConfigFilePath, {
2383
- prependEmptyLine: this.#currentCompilerVersion != null && !this.#hasReportedAdds && !this.#hasReportedError,
2384
- }));
2385
- this.#hasReportedAdds = false;
2386
- this.#currentCompilerVersion = payload.compilerVersion;
2387
- this.#currentProjectConfigFilePath = payload.projectConfigFilePath;
2388
- }
2391
+ OutputService.writeMessage(usesCompilerText(payload.compilerVersion, payload.projectConfigFilePath, {
2392
+ prependEmptyLine: this.#hasReportedUses && !this.#hasReportedAdds && !this.#hasReportedError,
2393
+ }));
2394
+ this.#hasReportedAdds = false;
2395
+ this.#hasReportedUses = true;
2389
2396
  break;
2390
2397
  case "project:error":
2391
2398
  for (const diagnostic of payload.diagnostics) {
@@ -2474,10 +2481,10 @@ class SetupReporter {
2474
2481
  if ("diagnostics" in payload) {
2475
2482
  for (const diagnostic of payload.diagnostics) {
2476
2483
  switch (diagnostic.category) {
2477
- case "error":
2484
+ case DiagnosticCategory.Error:
2478
2485
  OutputService.writeError(diagnosticText(diagnostic));
2479
2486
  break;
2480
- case "warning":
2487
+ case DiagnosticCategory.Warning:
2481
2488
  OutputService.writeWarning(diagnosticText(diagnostic));
2482
2489
  break;
2483
2490
  }
@@ -2841,7 +2848,7 @@ class WatchService {
2841
2848
  case "\u001B":
2842
2849
  case "q":
2843
2850
  case "x":
2844
- onClose("watchClose");
2851
+ onClose(CancellationReason.WatchClose);
2845
2852
  break;
2846
2853
  case "\u000D":
2847
2854
  case "\u0020":
@@ -2876,7 +2883,7 @@ class WatchService {
2876
2883
  };
2877
2884
  this.#watchers.push(new Watcher(this.#resolvedConfig.rootPath, onChangedFile, onRemovedFile, { recursive: true }));
2878
2885
  const onChangedConfigFile = () => {
2879
- onClose("configChange");
2886
+ onClose(CancellationReason.ConfigChange);
2880
2887
  };
2881
2888
  this.#watchers.push(new FileWatcher(this.#resolvedConfig.configFilePath, onChangedConfigFile));
2882
2889
  for (const watcher of this.#watchers) {
@@ -2891,6 +2898,13 @@ class WatchService {
2891
2898
  }
2892
2899
  }
2893
2900
 
2901
+ var TestMemberBrand;
2902
+ (function (TestMemberBrand) {
2903
+ TestMemberBrand["Describe"] = "describe";
2904
+ TestMemberBrand["Test"] = "test";
2905
+ TestMemberBrand["Expect"] = "expect";
2906
+ })(TestMemberBrand || (TestMemberBrand = {}));
2907
+
2894
2908
  class TestMember {
2895
2909
  brand;
2896
2910
  #compiler;
@@ -2932,17 +2946,17 @@ class TestMember {
2932
2946
  return node.parent;
2933
2947
  };
2934
2948
  switch (this.brand) {
2935
- case "describe":
2949
+ case TestMemberBrand.Describe:
2936
2950
  for (const member of this.members) {
2937
- if (member.brand === "expect") {
2951
+ if (member.brand === TestMemberBrand.Expect) {
2938
2952
  diagnostics.push(Diagnostic.error(getText(member.node), DiagnosticOrigin.fromNode(getParentCallExpression(member.node))));
2939
2953
  }
2940
2954
  }
2941
2955
  break;
2942
- case "test":
2943
- case "expect":
2956
+ case TestMemberBrand.Test:
2957
+ case TestMemberBrand.Expect:
2944
2958
  for (const member of this.members) {
2945
- if (member.brand !== "expect") {
2959
+ if (member.brand !== TestMemberBrand.Expect) {
2946
2960
  diagnostics.push(Diagnostic.error(getText(member.node), DiagnosticOrigin.fromNode(member.node)));
2947
2961
  }
2948
2962
  }
@@ -2977,6 +2991,15 @@ class Assertion extends TestMember {
2977
2991
  }
2978
2992
  }
2979
2993
 
2994
+ var TestMemberFlags;
2995
+ (function (TestMemberFlags) {
2996
+ TestMemberFlags[TestMemberFlags["None"] = 0] = "None";
2997
+ TestMemberFlags[TestMemberFlags["Fail"] = 1] = "Fail";
2998
+ TestMemberFlags[TestMemberFlags["Only"] = 2] = "Only";
2999
+ TestMemberFlags[TestMemberFlags["Skip"] = 4] = "Skip";
3000
+ TestMemberFlags[TestMemberFlags["Todo"] = 8] = "Todo";
3001
+ })(TestMemberFlags || (TestMemberFlags = {}));
3002
+
2980
3003
  class IdentifierLookup {
2981
3004
  #compiler;
2982
3005
  #identifiers;
@@ -3021,7 +3044,7 @@ class IdentifierLookup {
3021
3044
  }
3022
3045
  }
3023
3046
  resolveTestMemberMeta(node) {
3024
- let flags = 0;
3047
+ let flags = TestMemberFlags.None;
3025
3048
  let expression = node.expression;
3026
3049
  while (this.#compiler.isPropertyAccessExpression(expression)) {
3027
3050
  if (expression.expression.getText() === this.#identifiers.namespace) {
@@ -3029,16 +3052,16 @@ class IdentifierLookup {
3029
3052
  }
3030
3053
  switch (expression.name.getText()) {
3031
3054
  case "fail":
3032
- flags |= 1;
3055
+ flags |= TestMemberFlags.Fail;
3033
3056
  break;
3034
3057
  case "only":
3035
- flags |= 2;
3058
+ flags |= TestMemberFlags.Only;
3036
3059
  break;
3037
3060
  case "skip":
3038
- flags |= 4;
3061
+ flags |= TestMemberFlags.Skip;
3039
3062
  break;
3040
3063
  case "todo":
3041
- flags |= 8;
3064
+ flags |= TestMemberFlags.Todo;
3042
3065
  break;
3043
3066
  }
3044
3067
  expression = expression.expression;
@@ -3056,12 +3079,12 @@ class IdentifierLookup {
3056
3079
  }
3057
3080
  switch (identifierName) {
3058
3081
  case "describe":
3059
- return { brand: "describe", flags };
3082
+ return { brand: TestMemberBrand.Describe, flags };
3060
3083
  case "it":
3061
3084
  case "test":
3062
- return { brand: "test", flags };
3085
+ return { brand: TestMemberBrand.Test, flags };
3063
3086
  case "expect":
3064
- return { brand: "expect", flags };
3087
+ return { brand: TestMemberBrand.Expect, flags };
3065
3088
  }
3066
3089
  return;
3067
3090
  }
@@ -3077,7 +3100,7 @@ class TestTree {
3077
3100
  }
3078
3101
  get hasOnly() {
3079
3102
  function hasOnly(root) {
3080
- return root.members.some((branch) => branch.flags & 2 || ("members" in branch && hasOnly(branch)));
3103
+ return root.members.some((branch) => branch.flags & TestMemberFlags.Only || ("members" in branch && hasOnly(branch)));
3081
3104
  }
3082
3105
  return hasOnly(this);
3083
3106
  }
@@ -3091,7 +3114,7 @@ class CollectService {
3091
3114
  #collectTestMembers(node, identifiers, parent) {
3092
3115
  if (this.#compiler.isCallExpression(node)) {
3093
3116
  const meta = identifiers.resolveTestMemberMeta(node);
3094
- if (meta != null && (meta.brand === "describe" || meta.brand === "test")) {
3117
+ if (meta != null && (meta.brand === TestMemberBrand.Describe || meta.brand === TestMemberBrand.Test)) {
3095
3118
  const testMember = new TestMember(this.#compiler, meta.brand, node, parent, meta.flags);
3096
3119
  parent.members.push(testMember);
3097
3120
  this.#compiler.forEachChild(node, (node) => {
@@ -3099,7 +3122,7 @@ class CollectService {
3099
3122
  });
3100
3123
  return;
3101
3124
  }
3102
- if (meta != null && meta.brand === "expect") {
3125
+ if (meta != null && meta.brand === TestMemberBrand.Expect) {
3103
3126
  const modifierNode = this.#getChainedNode(node, "type");
3104
3127
  if (!modifierNode) {
3105
3128
  return;
@@ -3144,25 +3167,11 @@ class CollectService {
3144
3167
  }
3145
3168
  }
3146
3169
 
3147
- var TestMemberBrand;
3148
- (function (TestMemberBrand) {
3149
- TestMemberBrand["Describe"] = "describe";
3150
- TestMemberBrand["Test"] = "test";
3151
- TestMemberBrand["Expect"] = "expect";
3152
- })(TestMemberBrand || (TestMemberBrand = {}));
3153
-
3154
- var TestMemberFlags;
3155
- (function (TestMemberFlags) {
3156
- TestMemberFlags[TestMemberFlags["None"] = 0] = "None";
3157
- TestMemberFlags[TestMemberFlags["Fail"] = 1] = "Fail";
3158
- TestMemberFlags[TestMemberFlags["Only"] = 2] = "Only";
3159
- TestMemberFlags[TestMemberFlags["Skip"] = 4] = "Skip";
3160
- TestMemberFlags[TestMemberFlags["Todo"] = 8] = "Todo";
3161
- })(TestMemberFlags || (TestMemberFlags = {}));
3162
-
3163
3170
  class ProjectService {
3164
3171
  #compiler;
3172
+ #lastSeenProject = "";
3165
3173
  #resolvedConfig;
3174
+ #seenPrograms = new WeakSet();
3166
3175
  #service;
3167
3176
  constructor(resolvedConfig, compiler) {
3168
3177
  this.#resolvedConfig = resolvedConfig;
@@ -3237,7 +3246,12 @@ class ProjectService {
3237
3246
  return defaultCompilerOptions;
3238
3247
  }
3239
3248
  getDefaultProject(filePath) {
3240
- return this.#service.getDefaultProjectForFile(this.#compiler.server.toNormalizedPath(filePath), true);
3249
+ const project = this.#service.getDefaultProjectForFile(this.#compiler.server.toNormalizedPath(filePath), true);
3250
+ const compilerOptions = project?.getCompilerOptions();
3251
+ if (this.#resolvedConfig.checkSourceFiles && compilerOptions?.skipLibCheck) {
3252
+ project?.setCompilerOptions({ ...compilerOptions, skipLibCheck: false });
3253
+ }
3254
+ return project;
3241
3255
  }
3242
3256
  getLanguageService(filePath) {
3243
3257
  const project = this.getDefaultProject(filePath);
@@ -3245,19 +3259,56 @@ class ProjectService {
3245
3259
  }
3246
3260
  openFile(filePath, sourceText, projectRootPath) {
3247
3261
  const { configFileErrors, configFileName } = this.#service.openClientFile(filePath, sourceText, undefined, projectRootPath);
3248
- EventEmitter.dispatch([
3249
- "project:uses",
3250
- { compilerVersion: this.#compiler.version, projectConfigFilePath: configFileName },
3251
- ]);
3262
+ if (configFileName !== this.#lastSeenProject) {
3263
+ this.#lastSeenProject = configFileName;
3264
+ EventEmitter.dispatch([
3265
+ "project:uses",
3266
+ { compilerVersion: this.#compiler.version, projectConfigFilePath: configFileName },
3267
+ ]);
3268
+ }
3252
3269
  if (configFileErrors && configFileErrors.length > 0) {
3253
3270
  EventEmitter.dispatch([
3254
3271
  "project:error",
3255
- { diagnostics: Diagnostic.fromDiagnostics(configFileErrors, this.#compiler) },
3272
+ { diagnostics: Diagnostic.fromDiagnostics(configFileErrors) },
3256
3273
  ]);
3257
3274
  }
3275
+ if (this.#resolvedConfig.checkSourceFiles) {
3276
+ const languageService = this.getLanguageService(filePath);
3277
+ const program = languageService?.getProgram();
3278
+ if (!program || this.#seenPrograms.has(program)) {
3279
+ return;
3280
+ }
3281
+ this.#seenPrograms.add(program);
3282
+ const filesToCheck = [];
3283
+ for (const sourceFile of program.getSourceFiles()) {
3284
+ if (program.isSourceFileFromExternalLibrary(sourceFile) || program.isSourceFileDefaultLibrary(sourceFile)) {
3285
+ continue;
3286
+ }
3287
+ if (!Select.isTestFile(sourceFile.fileName, { ...this.#resolvedConfig, pathMatch: [] })) {
3288
+ filesToCheck.push(sourceFile);
3289
+ }
3290
+ }
3291
+ const diagnostics = [];
3292
+ for (const sourceFile of filesToCheck) {
3293
+ diagnostics.push(...program.getSyntacticDiagnostics(sourceFile), ...program.getSemanticDiagnostics(sourceFile));
3294
+ }
3295
+ if (diagnostics.length > 0) {
3296
+ EventEmitter.dispatch(["project:error", { diagnostics: Diagnostic.fromDiagnostics(diagnostics) }]);
3297
+ return;
3298
+ }
3299
+ }
3258
3300
  }
3259
3301
  }
3260
3302
 
3303
+ var RunMode;
3304
+ (function (RunMode) {
3305
+ RunMode[RunMode["Normal"] = 0] = "Normal";
3306
+ RunMode[RunMode["Fail"] = 1] = "Fail";
3307
+ RunMode[RunMode["Only"] = 2] = "Only";
3308
+ RunMode[RunMode["Skip"] = 4] = "Skip";
3309
+ RunMode[RunMode["Todo"] = 8] = "Todo";
3310
+ })(RunMode || (RunMode = {}));
3311
+
3261
3312
  class Format {
3262
3313
  static capitalize(text) {
3263
3314
  return text.replace(/^./, text.charAt(0).toUpperCase());
@@ -3425,7 +3476,13 @@ class MatchWorker {
3425
3476
  #checkIsRelatedTo(sourceNode, targetNode, relation) {
3426
3477
  const sourceType = this.getType(sourceNode);
3427
3478
  const targetType = this.getType(targetNode);
3428
- return this.#typeChecker.isTypeRelatedTo(sourceType, targetType, relation);
3479
+ let result = this.#typeChecker.isTypeRelatedTo(sourceType, targetType, relation);
3480
+ if (!result &&
3481
+ relation === this.#typeChecker.relation.identity &&
3482
+ (sourceType.isIntersection() || sourceType.isUnion())) {
3483
+ result = sourceType.types.every((type) => this.#typeChecker.isTypeRelatedTo(type, targetType, relation));
3484
+ }
3485
+ return result;
3429
3486
  }
3430
3487
  extendsObjectType(type) {
3431
3488
  const nonPrimitiveType = { flags: this.#compiler.TypeFlags.NonPrimitive };
@@ -3830,7 +3887,7 @@ class ToRaiseError {
3830
3887
  const text = ExpectDiagnosticText.typeRaisedError(isTypeNode, count, targetNodes.length);
3831
3888
  const related = [
3832
3889
  Diagnostic.error(ExpectDiagnosticText.raisedTypeError(count)),
3833
- ...Diagnostic.fromDiagnostics([...matchWorker.assertion.diagnostics], this.#compiler),
3890
+ ...Diagnostic.fromDiagnostics([...matchWorker.assertion.diagnostics]),
3834
3891
  ];
3835
3892
  return [Diagnostic.error(text, origin).add({ related })];
3836
3893
  }
@@ -3844,7 +3901,7 @@ class ToRaiseError {
3844
3901
  const origin = DiagnosticOrigin.fromNode(targetNode, matchWorker.assertion);
3845
3902
  const related = [
3846
3903
  Diagnostic.error(ExpectDiagnosticText.raisedTypeError()),
3847
- ...Diagnostic.fromDiagnostics([diagnostic], this.#compiler),
3904
+ ...Diagnostic.fromDiagnostics([diagnostic]),
3848
3905
  ];
3849
3906
  accumulator.push(Diagnostic.error(text, origin).add({ related }));
3850
3907
  }
@@ -4063,23 +4120,23 @@ class TestTreeWalker {
4063
4120
  this.#expectService = new ExpectService(compiler, typeChecker, this.#resolvedConfig);
4064
4121
  }
4065
4122
  #resolveRunMode(mode, member) {
4066
- if (member.flags & 1) {
4067
- mode |= 1;
4123
+ if (member.flags & TestMemberFlags.Fail) {
4124
+ mode |= RunMode.Fail;
4068
4125
  }
4069
- if (member.flags & 2 ||
4126
+ if (member.flags & TestMemberFlags.Only ||
4070
4127
  (this.#resolvedConfig.only != null && member.name.toLowerCase().includes(this.#resolvedConfig.only.toLowerCase()))) {
4071
- mode |= 2;
4128
+ mode |= RunMode.Only;
4072
4129
  }
4073
- if (member.flags & 4 ||
4130
+ if (member.flags & TestMemberFlags.Skip ||
4074
4131
  (this.#resolvedConfig.skip != null && member.name.toLowerCase().includes(this.#resolvedConfig.skip.toLowerCase()))) {
4075
- mode |= 4;
4132
+ mode |= RunMode.Skip;
4076
4133
  }
4077
- if (member.flags & 8) {
4078
- mode |= 8;
4134
+ if (member.flags & TestMemberFlags.Todo) {
4135
+ mode |= RunMode.Todo;
4079
4136
  }
4080
4137
  if (this.#position != null && member.node.getStart() === this.#position) {
4081
- mode |= 2;
4082
- mode &= ~4;
4138
+ mode |= RunMode.Only;
4139
+ mode &= ~RunMode.Skip;
4083
4140
  }
4084
4141
  return mode;
4085
4142
  }
@@ -4094,13 +4151,13 @@ class TestTreeWalker {
4094
4151
  break;
4095
4152
  }
4096
4153
  switch (member.brand) {
4097
- case "describe":
4154
+ case TestMemberBrand.Describe:
4098
4155
  this.#visitDescribe(member, runMode, parentResult);
4099
4156
  break;
4100
- case "test":
4157
+ case TestMemberBrand.Test:
4101
4158
  this.#visitTest(member, runMode, parentResult);
4102
4159
  break;
4103
- case "expect":
4160
+ case TestMemberBrand.Expect:
4104
4161
  this.#visitAssertion(member, runMode, parentResult);
4105
4162
  break;
4106
4163
  }
@@ -4111,7 +4168,7 @@ class TestTreeWalker {
4111
4168
  const expectResult = new ExpectResult(assertion, parentResult);
4112
4169
  EventEmitter.dispatch(["expect:start", { result: expectResult }]);
4113
4170
  runMode = this.#resolveRunMode(runMode, assertion);
4114
- if (runMode & 4 || (this.#hasOnly && !(runMode & 2))) {
4171
+ if (runMode & RunMode.Skip || (this.#hasOnly && !(runMode & RunMode.Only))) {
4115
4172
  EventEmitter.dispatch(["expect:skip", { result: expectResult }]);
4116
4173
  return;
4117
4174
  }
@@ -4122,7 +4179,7 @@ class TestTreeWalker {
4122
4179
  ]);
4123
4180
  };
4124
4181
  if (assertion.diagnostics.size > 0 && assertion.matcherName.getText() !== "toRaiseError") {
4125
- onExpectDiagnostics(Diagnostic.fromDiagnostics([...assertion.diagnostics], this.#compiler));
4182
+ onExpectDiagnostics(Diagnostic.fromDiagnostics([...assertion.diagnostics]));
4126
4183
  return;
4127
4184
  }
4128
4185
  const matchResult = this.#expectService.match(assertion, onExpectDiagnostics);
@@ -4130,7 +4187,7 @@ class TestTreeWalker {
4130
4187
  return;
4131
4188
  }
4132
4189
  if (assertion.isNot ? !matchResult.isMatch : matchResult.isMatch) {
4133
- if (runMode & 1) {
4190
+ if (runMode & RunMode.Fail) {
4134
4191
  const text = ["The assertion was supposed to fail, but it passed.", "Consider removing the '.fail' flag."];
4135
4192
  const origin = DiagnosticOrigin.fromNode(assertion.node.expression.name);
4136
4193
  onExpectDiagnostics(Diagnostic.error(text, origin));
@@ -4139,7 +4196,7 @@ class TestTreeWalker {
4139
4196
  EventEmitter.dispatch(["expect:pass", { result: expectResult }]);
4140
4197
  }
4141
4198
  }
4142
- else if (runMode & 1) {
4199
+ else if (runMode & RunMode.Fail) {
4143
4200
  EventEmitter.dispatch(["expect:pass", { result: expectResult }]);
4144
4201
  }
4145
4202
  else {
@@ -4150,12 +4207,12 @@ class TestTreeWalker {
4150
4207
  const describeResult = new DescribeResult(describe, parentResult);
4151
4208
  EventEmitter.dispatch(["describe:start", { result: describeResult }]);
4152
4209
  runMode = this.#resolveRunMode(runMode, describe);
4153
- if (!(runMode & 4 || (this.#hasOnly && !(runMode & 2)) || runMode & 8) &&
4210
+ if (!(runMode & RunMode.Skip || (this.#hasOnly && !(runMode & RunMode.Only)) || runMode & RunMode.Todo) &&
4154
4211
  describe.diagnostics.size > 0) {
4155
4212
  EventEmitter.dispatch([
4156
4213
  "task:error",
4157
4214
  {
4158
- diagnostics: Diagnostic.fromDiagnostics([...describe.diagnostics], this.#compiler),
4215
+ diagnostics: Diagnostic.fromDiagnostics([...describe.diagnostics]),
4159
4216
  result: this.#taskResult,
4160
4217
  },
4161
4218
  ]);
@@ -4169,22 +4226,22 @@ class TestTreeWalker {
4169
4226
  const testResult = new TestResult(test, parentResult);
4170
4227
  EventEmitter.dispatch(["test:start", { result: testResult }]);
4171
4228
  runMode = this.#resolveRunMode(runMode, test);
4172
- if (runMode & 8) {
4229
+ if (runMode & RunMode.Todo) {
4173
4230
  EventEmitter.dispatch(["test:todo", { result: testResult }]);
4174
4231
  return;
4175
4232
  }
4176
- if (!(runMode & 4 || (this.#hasOnly && !(runMode & 2))) && test.diagnostics.size > 0) {
4233
+ if (!(runMode & RunMode.Skip || (this.#hasOnly && !(runMode & RunMode.Only))) && test.diagnostics.size > 0) {
4177
4234
  EventEmitter.dispatch([
4178
4235
  "test:error",
4179
4236
  {
4180
- diagnostics: Diagnostic.fromDiagnostics([...test.diagnostics], this.#compiler),
4237
+ diagnostics: Diagnostic.fromDiagnostics([...test.diagnostics]),
4181
4238
  result: testResult,
4182
4239
  },
4183
4240
  ]);
4184
4241
  return;
4185
4242
  }
4186
4243
  this.visit(test.members, runMode, testResult);
4187
- if (runMode & 4 || (this.#hasOnly && !(runMode & 2))) {
4244
+ if (runMode & RunMode.Skip || (this.#hasOnly && !(runMode & RunMode.Only))) {
4188
4245
  EventEmitter.dispatch(["test:skip", { result: testResult }]);
4189
4246
  return;
4190
4247
  }
@@ -4235,7 +4292,7 @@ class TaskRunner {
4235
4292
  if (syntacticDiagnostics.length > 0) {
4236
4293
  EventEmitter.dispatch([
4237
4294
  "task:error",
4238
- { diagnostics: Diagnostic.fromDiagnostics(syntacticDiagnostics, this.#compiler), result: taskResult },
4295
+ { diagnostics: Diagnostic.fromDiagnostics(syntacticDiagnostics), result: taskResult },
4239
4296
  ]);
4240
4297
  return;
4241
4298
  }
@@ -4252,7 +4309,7 @@ class TaskRunner {
4252
4309
  if (testTree.diagnostics.size > 0) {
4253
4310
  EventEmitter.dispatch([
4254
4311
  "task:error",
4255
- { diagnostics: Diagnostic.fromDiagnostics([...testTree.diagnostics], this.#compiler), result: taskResult },
4312
+ { diagnostics: Diagnostic.fromDiagnostics([...testTree.diagnostics]), result: taskResult },
4256
4313
  ]);
4257
4314
  return;
4258
4315
  }
@@ -4263,14 +4320,14 @@ class TaskRunner {
4263
4320
  hasOnly: testTree.hasOnly,
4264
4321
  position: task.position,
4265
4322
  });
4266
- testTreeWalker.visit(testTree.members, 0, undefined);
4323
+ testTreeWalker.visit(testTree.members, RunMode.Normal, undefined);
4267
4324
  }
4268
4325
  }
4269
4326
 
4270
4327
  class Runner {
4271
4328
  #eventEmitter = new EventEmitter();
4272
4329
  #resolvedConfig;
4273
- static version = "3.1.1";
4330
+ static version = "3.3.0";
4274
4331
  constructor(resolvedConfig) {
4275
4332
  this.#resolvedConfig = resolvedConfig;
4276
4333
  }
@@ -4305,7 +4362,7 @@ class Runner {
4305
4362
  this.#eventEmitter.addHandler(resultHandler);
4306
4363
  await this.#addReporters();
4307
4364
  if (this.#resolvedConfig.failFast) {
4308
- const cancellationHandler = new CancellationHandler(cancellationToken, "failFast");
4365
+ const cancellationHandler = new CancellationHandler(cancellationToken, CancellationReason.FailFast);
4309
4366
  this.#eventEmitter.addHandler(cancellationHandler);
4310
4367
  }
4311
4368
  await this.#run(tasks, cancellationToken);
@@ -4331,7 +4388,7 @@ class Runner {
4331
4388
  EventEmitter.dispatch(["target:end", { result: targetResult }]);
4332
4389
  }
4333
4390
  EventEmitter.dispatch(["run:end", { result }]);
4334
- if (cancellationToken.reason === "failFast") {
4391
+ if (cancellationToken.reason === CancellationReason.FailFast) {
4335
4392
  cancellationToken.reset();
4336
4393
  }
4337
4394
  }
@@ -4346,14 +4403,14 @@ class Runner {
4346
4403
  class Cli {
4347
4404
  #eventEmitter = new EventEmitter();
4348
4405
  async run(commandLine, cancellationToken = new CancellationToken()) {
4349
- const cancellationHandler = new CancellationHandler(cancellationToken, "configError");
4406
+ const cancellationHandler = new CancellationHandler(cancellationToken, CancellationReason.ConfigError);
4350
4407
  this.#eventEmitter.addHandler(cancellationHandler);
4351
4408
  const exitCodeHandler = new ExitCodeHandler();
4352
4409
  this.#eventEmitter.addHandler(exitCodeHandler);
4353
4410
  const setupReporter = new SetupReporter();
4354
4411
  this.#eventEmitter.addReporter(setupReporter);
4355
4412
  if (commandLine.includes("--help")) {
4356
- const options = Options.for(2);
4413
+ const options = Options.for(OptionGroup.CommandLine);
4357
4414
  OutputService.writeMessage(helpText(options, Runner.version));
4358
4415
  return;
4359
4416
  }
@@ -4381,7 +4438,7 @@ class Cli {
4381
4438
  return;
4382
4439
  }
4383
4440
  do {
4384
- if (cancellationToken.reason === "configChange") {
4441
+ if (cancellationToken.reason === CancellationReason.ConfigChange) {
4385
4442
  cancellationToken.reset();
4386
4443
  exitCodeHandler.resetCode();
4387
4444
  OutputService.clearTerminal();
@@ -4436,7 +4493,7 @@ class Cli {
4436
4493
  const runner = new Runner(resolvedConfig);
4437
4494
  await runner.run(testFiles, cancellationToken);
4438
4495
  PluginService.removeHandlers();
4439
- } while (cancellationToken.reason === "configChange");
4496
+ } while (cancellationToken.reason === CancellationReason.ConfigChange);
4440
4497
  this.#eventEmitter.removeHandlers();
4441
4498
  }
4442
4499
  #waitForChangedFiles(resolvedConfig, cancellationToken) {
@@ -4445,7 +4502,7 @@ class Cli {
4445
4502
  cancellationToken.reset();
4446
4503
  OutputService.writeMessage(waitingForFileChangesText());
4447
4504
  const onChanged = () => {
4448
- cancellationToken.cancel("configChange");
4505
+ cancellationToken.cancel(CancellationReason.ConfigChange);
4449
4506
  for (const watcher of watchers) {
4450
4507
  watcher.close();
4451
4508
  }