tstyche 3.0.0-beta.1 → 3.0.0-beta.3
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/README.md +3 -3
- package/build/index.cjs +2 -0
- package/build/index.d.cts +19 -49
- package/build/index.d.ts +19 -49
- package/build/index.js +1 -1
- package/build/tstyche.d.ts +69 -52
- package/build/tstyche.js +426 -318
- package/package.json +15 -15
package/build/tstyche.js
CHANGED
|
@@ -87,15 +87,6 @@ class DescribeResult {
|
|
|
87
87
|
}
|
|
88
88
|
}
|
|
89
89
|
|
|
90
|
-
var ResultStatus;
|
|
91
|
-
(function (ResultStatus) {
|
|
92
|
-
ResultStatus["Runs"] = "runs";
|
|
93
|
-
ResultStatus["Passed"] = "passed";
|
|
94
|
-
ResultStatus["Failed"] = "failed";
|
|
95
|
-
ResultStatus["Skipped"] = "skipped";
|
|
96
|
-
ResultStatus["Todo"] = "todo";
|
|
97
|
-
})(ResultStatus || (ResultStatus = {}));
|
|
98
|
-
|
|
99
90
|
class ExpectResult {
|
|
100
91
|
assertion;
|
|
101
92
|
diagnostics = [];
|
|
@@ -144,6 +135,15 @@ class Result {
|
|
|
144
135
|
}
|
|
145
136
|
}
|
|
146
137
|
|
|
138
|
+
var ResultStatus;
|
|
139
|
+
(function (ResultStatus) {
|
|
140
|
+
ResultStatus["Runs"] = "runs";
|
|
141
|
+
ResultStatus["Passed"] = "passed";
|
|
142
|
+
ResultStatus["Failed"] = "failed";
|
|
143
|
+
ResultStatus["Skipped"] = "skipped";
|
|
144
|
+
ResultStatus["Todo"] = "todo";
|
|
145
|
+
})(ResultStatus || (ResultStatus = {}));
|
|
146
|
+
|
|
147
147
|
class TargetResult {
|
|
148
148
|
results = new Map();
|
|
149
149
|
status = "runs";
|
|
@@ -193,23 +193,20 @@ class ResultHandler {
|
|
|
193
193
|
#testResult;
|
|
194
194
|
handleEvent([eventName, payload]) {
|
|
195
195
|
switch (eventName) {
|
|
196
|
-
case "run:start":
|
|
196
|
+
case "run:start":
|
|
197
197
|
this.#result = payload.result;
|
|
198
198
|
this.#result.timing.start = Date.now();
|
|
199
199
|
break;
|
|
200
|
-
|
|
201
|
-
case "run:end": {
|
|
200
|
+
case "run:end":
|
|
202
201
|
this.#result.timing.end = Date.now();
|
|
203
202
|
this.#result = undefined;
|
|
204
203
|
break;
|
|
205
|
-
|
|
206
|
-
case "target:start": {
|
|
204
|
+
case "target:start":
|
|
207
205
|
this.#result.results.push(payload.result);
|
|
208
206
|
this.#targetResult = payload.result;
|
|
209
207
|
this.#targetResult.timing.start = Date.now();
|
|
210
208
|
break;
|
|
211
|
-
|
|
212
|
-
case "target:end": {
|
|
209
|
+
case "target:end":
|
|
213
210
|
if (this.#targetResult.status === "failed") {
|
|
214
211
|
this.#result.targetCount.failed++;
|
|
215
212
|
}
|
|
@@ -220,13 +217,11 @@ class ResultHandler {
|
|
|
220
217
|
this.#targetResult.timing.end = Date.now();
|
|
221
218
|
this.#targetResult = undefined;
|
|
222
219
|
break;
|
|
223
|
-
|
|
224
|
-
case "store:error": {
|
|
220
|
+
case "store:error":
|
|
225
221
|
if (payload.diagnostics.some(({ category }) => category === "error")) {
|
|
226
222
|
this.#targetResult.status = "failed";
|
|
227
223
|
}
|
|
228
224
|
break;
|
|
229
|
-
}
|
|
230
225
|
case "project:uses": {
|
|
231
226
|
let projectResult = this.#targetResult.results.get(payload.projectConfigFilePath);
|
|
232
227
|
if (!projectResult) {
|
|
@@ -236,24 +231,21 @@ class ResultHandler {
|
|
|
236
231
|
this.#projectResult = projectResult;
|
|
237
232
|
break;
|
|
238
233
|
}
|
|
239
|
-
case "project:error":
|
|
234
|
+
case "project:error":
|
|
240
235
|
this.#targetResult.status = "failed";
|
|
241
236
|
this.#projectResult.diagnostics.push(...payload.diagnostics);
|
|
242
237
|
break;
|
|
243
|
-
|
|
244
|
-
case "task:start": {
|
|
238
|
+
case "task:start":
|
|
245
239
|
this.#projectResult.results.push(payload.result);
|
|
246
240
|
this.#taskResult = payload.result;
|
|
247
241
|
this.#taskResult.timing.start = Date.now();
|
|
248
242
|
break;
|
|
249
|
-
|
|
250
|
-
case "task:error": {
|
|
243
|
+
case "task:error":
|
|
251
244
|
this.#targetResult.status = "failed";
|
|
252
245
|
this.#taskResult.status = "failed";
|
|
253
246
|
this.#taskResult.diagnostics.push(...payload.diagnostics);
|
|
254
247
|
break;
|
|
255
|
-
|
|
256
|
-
case "task:end": {
|
|
248
|
+
case "task:end":
|
|
257
249
|
if (this.#taskResult.status === "failed" ||
|
|
258
250
|
this.#taskResult.expectCount.failed > 0 ||
|
|
259
251
|
this.#taskResult.testCount.failed > 0) {
|
|
@@ -268,8 +260,7 @@ class ResultHandler {
|
|
|
268
260
|
this.#taskResult.timing.end = Date.now();
|
|
269
261
|
this.#taskResult = undefined;
|
|
270
262
|
break;
|
|
271
|
-
|
|
272
|
-
case "describe:start": {
|
|
263
|
+
case "describe:start":
|
|
273
264
|
if (this.#describeResult) {
|
|
274
265
|
this.#describeResult.results.push(payload.result);
|
|
275
266
|
}
|
|
@@ -279,13 +270,11 @@ class ResultHandler {
|
|
|
279
270
|
this.#describeResult = payload.result;
|
|
280
271
|
this.#describeResult.timing.start = Date.now();
|
|
281
272
|
break;
|
|
282
|
-
|
|
283
|
-
case "describe:end": {
|
|
273
|
+
case "describe:end":
|
|
284
274
|
this.#describeResult.timing.end = Date.now();
|
|
285
275
|
this.#describeResult = this.#describeResult.parent;
|
|
286
276
|
break;
|
|
287
|
-
|
|
288
|
-
case "test:start": {
|
|
277
|
+
case "test:start":
|
|
289
278
|
if (this.#describeResult) {
|
|
290
279
|
this.#describeResult.results.push(payload.result);
|
|
291
280
|
}
|
|
@@ -295,8 +284,7 @@ class ResultHandler {
|
|
|
295
284
|
this.#testResult = payload.result;
|
|
296
285
|
this.#testResult.timing.start = Date.now();
|
|
297
286
|
break;
|
|
298
|
-
|
|
299
|
-
case "test:error": {
|
|
287
|
+
case "test:error":
|
|
300
288
|
this.#result.testCount.failed++;
|
|
301
289
|
this.#taskResult.testCount.failed++;
|
|
302
290
|
this.#testResult.status = "failed";
|
|
@@ -304,40 +292,35 @@ class ResultHandler {
|
|
|
304
292
|
this.#testResult.timing.end = Date.now();
|
|
305
293
|
this.#testResult = undefined;
|
|
306
294
|
break;
|
|
307
|
-
|
|
308
|
-
case "test:fail": {
|
|
295
|
+
case "test:fail":
|
|
309
296
|
this.#result.testCount.failed++;
|
|
310
297
|
this.#taskResult.testCount.failed++;
|
|
311
298
|
this.#testResult.status = "failed";
|
|
312
299
|
this.#testResult.timing.end = Date.now();
|
|
313
300
|
this.#testResult = undefined;
|
|
314
301
|
break;
|
|
315
|
-
|
|
316
|
-
case "test:pass": {
|
|
302
|
+
case "test:pass":
|
|
317
303
|
this.#result.testCount.passed++;
|
|
318
304
|
this.#taskResult.testCount.passed++;
|
|
319
305
|
this.#testResult.status = "passed";
|
|
320
306
|
this.#testResult.timing.end = Date.now();
|
|
321
307
|
this.#testResult = undefined;
|
|
322
308
|
break;
|
|
323
|
-
|
|
324
|
-
case "test:skip": {
|
|
309
|
+
case "test:skip":
|
|
325
310
|
this.#result.testCount.skipped++;
|
|
326
311
|
this.#taskResult.testCount.skipped++;
|
|
327
312
|
this.#testResult.status = "skipped";
|
|
328
313
|
this.#testResult.timing.end = Date.now();
|
|
329
314
|
this.#testResult = undefined;
|
|
330
315
|
break;
|
|
331
|
-
|
|
332
|
-
case "test:todo": {
|
|
316
|
+
case "test:todo":
|
|
333
317
|
this.#result.testCount.todo++;
|
|
334
318
|
this.#taskResult.testCount.todo++;
|
|
335
319
|
this.#testResult.status = "todo";
|
|
336
320
|
this.#testResult.timing.end = Date.now();
|
|
337
321
|
this.#testResult = undefined;
|
|
338
322
|
break;
|
|
339
|
-
|
|
340
|
-
case "expect:start": {
|
|
323
|
+
case "expect:start":
|
|
341
324
|
if (this.#testResult) {
|
|
342
325
|
this.#testResult.results.push(payload.result);
|
|
343
326
|
}
|
|
@@ -347,8 +330,7 @@ class ResultHandler {
|
|
|
347
330
|
this.#expectResult = payload.result;
|
|
348
331
|
this.#expectResult.timing.start = Date.now();
|
|
349
332
|
break;
|
|
350
|
-
|
|
351
|
-
case "expect:error": {
|
|
333
|
+
case "expect:error":
|
|
352
334
|
this.#result.expectCount.failed++;
|
|
353
335
|
this.#taskResult.expectCount.failed++;
|
|
354
336
|
if (this.#testResult) {
|
|
@@ -359,8 +341,7 @@ class ResultHandler {
|
|
|
359
341
|
this.#expectResult.timing.end = Date.now();
|
|
360
342
|
this.#expectResult = undefined;
|
|
361
343
|
break;
|
|
362
|
-
|
|
363
|
-
case "expect:fail": {
|
|
344
|
+
case "expect:fail":
|
|
364
345
|
this.#result.expectCount.failed++;
|
|
365
346
|
this.#taskResult.expectCount.failed++;
|
|
366
347
|
if (this.#testResult) {
|
|
@@ -370,8 +351,7 @@ class ResultHandler {
|
|
|
370
351
|
this.#expectResult.timing.end = Date.now();
|
|
371
352
|
this.#expectResult = undefined;
|
|
372
353
|
break;
|
|
373
|
-
|
|
374
|
-
case "expect:pass": {
|
|
354
|
+
case "expect:pass":
|
|
375
355
|
this.#result.expectCount.passed++;
|
|
376
356
|
this.#taskResult.expectCount.passed++;
|
|
377
357
|
if (this.#testResult) {
|
|
@@ -381,8 +361,7 @@ class ResultHandler {
|
|
|
381
361
|
this.#expectResult.timing.end = Date.now();
|
|
382
362
|
this.#expectResult = undefined;
|
|
383
363
|
break;
|
|
384
|
-
|
|
385
|
-
case "expect:skip": {
|
|
364
|
+
case "expect:skip":
|
|
386
365
|
this.#result.expectCount.skipped++;
|
|
387
366
|
this.#taskResult.expectCount.skipped++;
|
|
388
367
|
if (this.#testResult) {
|
|
@@ -392,7 +371,6 @@ class ResultHandler {
|
|
|
392
371
|
this.#expectResult.timing.end = Date.now();
|
|
393
372
|
this.#expectResult = undefined;
|
|
394
373
|
break;
|
|
395
|
-
}
|
|
396
374
|
}
|
|
397
375
|
}
|
|
398
376
|
}
|
|
@@ -503,11 +481,11 @@ class Path {
|
|
|
503
481
|
return Path.normalizeSlashes(path.join(...filePaths));
|
|
504
482
|
}
|
|
505
483
|
static relative(from, to) {
|
|
506
|
-
|
|
507
|
-
if (
|
|
508
|
-
|
|
484
|
+
const relativePath = Path.normalizeSlashes(path.relative(from, to));
|
|
485
|
+
if (/^\.\.?\//.test(relativePath)) {
|
|
486
|
+
return relativePath;
|
|
509
487
|
}
|
|
510
|
-
return
|
|
488
|
+
return `./${relativePath}`;
|
|
511
489
|
}
|
|
512
490
|
static resolve(...filePaths) {
|
|
513
491
|
return Path.normalizeSlashes(path.resolve(...filePaths));
|
|
@@ -530,29 +508,25 @@ function SquiggleLineText({ gutterWidth, indentWidth = 0, squiggleColor, squiggl
|
|
|
530
508
|
return (jsx(Line, { children: [" ".repeat(gutterWidth), jsx(Text, { color: "90", children: " | " }), " ".repeat(indentWidth), jsx(Text, { color: squiggleColor, children: "~".repeat(squiggleWidth === 0 ? 1 : squiggleWidth) })] }));
|
|
531
509
|
}
|
|
532
510
|
function CodeSpanText({ diagnosticCategory, diagnosticOrigin }) {
|
|
533
|
-
const
|
|
511
|
+
const lineMap = diagnosticOrigin.sourceFile.getLineStarts();
|
|
534
512
|
const { character: firstMarkedLineCharacter, line: firstMarkedLine } = diagnosticOrigin.sourceFile.getLineAndCharacterOfPosition(diagnosticOrigin.start);
|
|
535
513
|
const { character: lastMarkedLineCharacter, line: lastMarkedLine } = diagnosticOrigin.sourceFile.getLineAndCharacterOfPosition(diagnosticOrigin.end);
|
|
536
514
|
const firstLine = Math.max(firstMarkedLine - 2, 0);
|
|
537
|
-
const lastLine = Math.min(firstLine + 5,
|
|
515
|
+
const lastLine = Math.min(firstLine + 5, lineMap.length - 1);
|
|
538
516
|
const gutterWidth = (lastLine + 1).toString().length + 2;
|
|
539
517
|
let highlightColor;
|
|
540
518
|
switch (diagnosticCategory) {
|
|
541
|
-
case "error":
|
|
519
|
+
case "error":
|
|
542
520
|
highlightColor = "31";
|
|
543
521
|
break;
|
|
544
|
-
|
|
545
|
-
case "warning": {
|
|
522
|
+
case "warning":
|
|
546
523
|
highlightColor = "33";
|
|
547
524
|
break;
|
|
548
|
-
}
|
|
549
525
|
}
|
|
550
526
|
const codeSpan = [];
|
|
551
527
|
for (let index = firstLine; index <= lastLine; index++) {
|
|
552
|
-
const lineStart =
|
|
553
|
-
const lineEnd = index ===
|
|
554
|
-
? diagnosticOrigin.sourceFile.text.length
|
|
555
|
-
: diagnosticOrigin.sourceFile.getPositionOfLineAndCharacter(index + 1, 0);
|
|
528
|
+
const lineStart = lineMap[index];
|
|
529
|
+
const lineEnd = index === lineMap.length - 1 ? diagnosticOrigin.sourceFile.text.length : lineMap[index + 1];
|
|
556
530
|
const lineText = diagnosticOrigin.sourceFile.text.slice(lineStart, lineEnd).trimEnd().replace(/\t/g, " ");
|
|
557
531
|
if (index >= firstMarkedLine && index <= lastMarkedLine) {
|
|
558
532
|
codeSpan.push(jsx(CodeLineText, { gutterWidth: gutterWidth, lineNumber: index + 1, lineNumberColor: highlightColor, lineText: lineText }));
|
|
@@ -588,14 +562,12 @@ function DiagnosticText({ diagnostic }) {
|
|
|
588
562
|
function diagnosticText(diagnostic) {
|
|
589
563
|
let prefix;
|
|
590
564
|
switch (diagnostic.category) {
|
|
591
|
-
case "error":
|
|
565
|
+
case "error":
|
|
592
566
|
prefix = jsx(Text, { color: "31", children: "Error: " });
|
|
593
567
|
break;
|
|
594
|
-
|
|
595
|
-
case "warning": {
|
|
568
|
+
case "warning":
|
|
596
569
|
prefix = jsx(Text, { color: "33", children: "Warning: " });
|
|
597
570
|
break;
|
|
598
|
-
}
|
|
599
571
|
}
|
|
600
572
|
return (jsx(Text, { children: [prefix, jsx(DiagnosticText, { diagnostic: diagnostic })] }));
|
|
601
573
|
}
|
|
@@ -611,21 +583,18 @@ function taskStatusText(status, task) {
|
|
|
611
583
|
let statusColor;
|
|
612
584
|
let statusText;
|
|
613
585
|
switch (status) {
|
|
614
|
-
case "runs":
|
|
586
|
+
case "runs":
|
|
615
587
|
statusColor = "33";
|
|
616
588
|
statusText = "runs";
|
|
617
589
|
break;
|
|
618
|
-
|
|
619
|
-
case "passed": {
|
|
590
|
+
case "passed":
|
|
620
591
|
statusColor = "32";
|
|
621
592
|
statusText = "pass";
|
|
622
593
|
break;
|
|
623
|
-
|
|
624
|
-
case "failed": {
|
|
594
|
+
case "failed":
|
|
625
595
|
statusColor = "31";
|
|
626
596
|
statusText = "fail";
|
|
627
597
|
break;
|
|
628
|
-
}
|
|
629
598
|
}
|
|
630
599
|
return (jsx(Line, { children: [jsx(Text, { color: statusColor, children: statusText }), " ", jsx(FileNameText, { filePath: task.filePath })] }));
|
|
631
600
|
}
|
|
@@ -701,8 +670,8 @@ function helpText(optionDefinitions, tstycheVersion) {
|
|
|
701
670
|
}
|
|
702
671
|
|
|
703
672
|
class ConfigDiagnosticText {
|
|
704
|
-
static
|
|
705
|
-
return
|
|
673
|
+
static expected(element) {
|
|
674
|
+
return `Expected ${element}.`;
|
|
706
675
|
}
|
|
707
676
|
static expectsListItemType(optionName, optionBrand) {
|
|
708
677
|
return `Item of the '${optionName}' list must be of type ${optionBrand}.`;
|
|
@@ -722,6 +691,9 @@ class ConfigDiagnosticText {
|
|
|
722
691
|
return optionName;
|
|
723
692
|
}
|
|
724
693
|
}
|
|
694
|
+
static seen(element) {
|
|
695
|
+
return `The ${element} was seen here.`;
|
|
696
|
+
}
|
|
725
697
|
static testFileMatchCannotStartWith(segment) {
|
|
726
698
|
return [
|
|
727
699
|
`A test file match pattern cannot start with '${segment}'.`,
|
|
@@ -761,9 +733,6 @@ class DiagnosticOrigin {
|
|
|
761
733
|
const node = assertion.matcherName;
|
|
762
734
|
return new DiagnosticOrigin(node.getStart(), node.getEnd(), node.getSourceFile(), assertion);
|
|
763
735
|
}
|
|
764
|
-
static fromJsonNode(node, sourceFile, skipTrivia) {
|
|
765
|
-
return new DiagnosticOrigin(skipTrivia(node.pos, sourceFile), node.end, sourceFile);
|
|
766
|
-
}
|
|
767
736
|
static fromNode(node, assertion) {
|
|
768
737
|
return new DiagnosticOrigin(node.getStart(), node.getEnd(), node.getSourceFile(), assertion);
|
|
769
738
|
}
|
|
@@ -824,8 +793,48 @@ var DiagnosticCategory;
|
|
|
824
793
|
DiagnosticCategory["Warning"] = "warning";
|
|
825
794
|
})(DiagnosticCategory || (DiagnosticCategory = {}));
|
|
826
795
|
|
|
796
|
+
class SourceFile {
|
|
797
|
+
fileName;
|
|
798
|
+
#lineMap;
|
|
799
|
+
text;
|
|
800
|
+
constructor(fileName, text) {
|
|
801
|
+
this.fileName = fileName;
|
|
802
|
+
this.text = text;
|
|
803
|
+
this.#lineMap = this.#createLineMap();
|
|
804
|
+
}
|
|
805
|
+
#createLineMap() {
|
|
806
|
+
const result = [0];
|
|
807
|
+
let position = 0;
|
|
808
|
+
while (position < this.text.length) {
|
|
809
|
+
if (this.text.charAt(position - 1) === "\r") {
|
|
810
|
+
position++;
|
|
811
|
+
}
|
|
812
|
+
if (this.text.charAt(position - 1) === "\n") {
|
|
813
|
+
result.push(position);
|
|
814
|
+
}
|
|
815
|
+
position++;
|
|
816
|
+
}
|
|
817
|
+
result.push(position);
|
|
818
|
+
return result;
|
|
819
|
+
}
|
|
820
|
+
getLineStarts() {
|
|
821
|
+
return this.#lineMap;
|
|
822
|
+
}
|
|
823
|
+
getLineAndCharacterOfPosition(position) {
|
|
824
|
+
const line = this.#lineMap.findLastIndex((line) => line <= position);
|
|
825
|
+
const character = position - this.#lineMap[line];
|
|
826
|
+
return { line, character };
|
|
827
|
+
}
|
|
828
|
+
}
|
|
829
|
+
|
|
827
830
|
class OptionDefinitionsMap {
|
|
828
831
|
static #definitions = [
|
|
832
|
+
{
|
|
833
|
+
brand: "string",
|
|
834
|
+
description: "The Url to the config file validation schema.",
|
|
835
|
+
group: 4,
|
|
836
|
+
name: "$schema",
|
|
837
|
+
},
|
|
829
838
|
{
|
|
830
839
|
brand: "string",
|
|
831
840
|
description: "The path to a TSTyche configuration file.",
|
|
@@ -949,14 +958,12 @@ class OptionUsageText {
|
|
|
949
958
|
switch (optionName) {
|
|
950
959
|
case "target": {
|
|
951
960
|
switch (this.#optionGroup) {
|
|
952
|
-
case 2:
|
|
961
|
+
case 2:
|
|
953
962
|
usageText.push("Value for the '--target' option must be a single tag or a comma separated list.", "Usage examples: '--target 4.9', '--target latest', '--target 4.9,5.3.2,current'.");
|
|
954
963
|
break;
|
|
955
|
-
|
|
956
|
-
case 4: {
|
|
964
|
+
case 4:
|
|
957
965
|
usageText.push("Item of the 'target' list must be a supported version tag.");
|
|
958
966
|
break;
|
|
959
|
-
}
|
|
960
967
|
}
|
|
961
968
|
const supportedTags = await this.#storeService.getSupportedTags();
|
|
962
969
|
if (supportedTags != null) {
|
|
@@ -1062,13 +1069,12 @@ class OptionValidator {
|
|
|
1062
1069
|
async check(optionName, optionValue, optionBrand, origin) {
|
|
1063
1070
|
switch (optionName) {
|
|
1064
1071
|
case "config":
|
|
1065
|
-
case "rootPath":
|
|
1072
|
+
case "rootPath":
|
|
1066
1073
|
if (!existsSync(optionValue)) {
|
|
1067
1074
|
this.#onDiagnostics(Diagnostic.error(ConfigDiagnosticText.fileDoesNotExist(optionValue), origin));
|
|
1068
1075
|
}
|
|
1069
1076
|
break;
|
|
1070
|
-
|
|
1071
|
-
case "target": {
|
|
1077
|
+
case "target":
|
|
1072
1078
|
if ((await this.#storeService.validateTag(optionValue)) === false) {
|
|
1073
1079
|
this.#onDiagnostics(Diagnostic.error([
|
|
1074
1080
|
ConfigDiagnosticText.versionIsNotSupported(optionValue),
|
|
@@ -1076,21 +1082,18 @@ class OptionValidator {
|
|
|
1076
1082
|
], origin));
|
|
1077
1083
|
}
|
|
1078
1084
|
break;
|
|
1079
|
-
|
|
1080
|
-
case "testFileMatch": {
|
|
1085
|
+
case "testFileMatch":
|
|
1081
1086
|
for (const segment of ["/", "../"]) {
|
|
1082
1087
|
if (optionValue.startsWith(segment)) {
|
|
1083
1088
|
this.#onDiagnostics(Diagnostic.error(ConfigDiagnosticText.testFileMatchCannotStartWith(segment), origin));
|
|
1084
1089
|
}
|
|
1085
1090
|
}
|
|
1086
1091
|
break;
|
|
1087
|
-
|
|
1088
|
-
case "watch": {
|
|
1092
|
+
case "watch":
|
|
1089
1093
|
if (environmentOptions.isCi) {
|
|
1090
1094
|
this.#onDiagnostics(Diagnostic.error(ConfigDiagnosticText.watchCannotBeEnabled(), origin));
|
|
1091
1095
|
}
|
|
1092
1096
|
break;
|
|
1093
|
-
}
|
|
1094
1097
|
}
|
|
1095
1098
|
}
|
|
1096
1099
|
}
|
|
@@ -1147,20 +1150,18 @@ class CommandLineOptionsWorker {
|
|
|
1147
1150
|
async #parseOptionValue(commandLineArgs, index, optionDefinition) {
|
|
1148
1151
|
let optionValue = this.#resolveOptionValue(commandLineArgs[index]);
|
|
1149
1152
|
switch (optionDefinition.brand) {
|
|
1150
|
-
case "bareTrue":
|
|
1153
|
+
case "bareTrue":
|
|
1151
1154
|
await this.#optionValidator.check(optionDefinition.name, optionValue, optionDefinition.brand);
|
|
1152
1155
|
this.#commandLineOptions[optionDefinition.name] = true;
|
|
1153
1156
|
break;
|
|
1154
|
-
|
|
1155
|
-
case "boolean": {
|
|
1157
|
+
case "boolean":
|
|
1156
1158
|
await this.#optionValidator.check(optionDefinition.name, optionValue, optionDefinition.brand);
|
|
1157
1159
|
this.#commandLineOptions[optionDefinition.name] = optionValue !== "false";
|
|
1158
1160
|
if (optionValue === "false" || optionValue === "true") {
|
|
1159
1161
|
index++;
|
|
1160
1162
|
}
|
|
1161
1163
|
break;
|
|
1162
|
-
|
|
1163
|
-
case "list": {
|
|
1164
|
+
case "list":
|
|
1164
1165
|
if (optionValue !== "") {
|
|
1165
1166
|
const optionValues = optionValue
|
|
1166
1167
|
.split(",")
|
|
@@ -1175,8 +1176,7 @@ class CommandLineOptionsWorker {
|
|
|
1175
1176
|
}
|
|
1176
1177
|
await this.#onExpectsValue(optionDefinition);
|
|
1177
1178
|
break;
|
|
1178
|
-
|
|
1179
|
-
case "string": {
|
|
1179
|
+
case "string":
|
|
1180
1180
|
if (optionValue !== "") {
|
|
1181
1181
|
if (optionDefinition.name === "config") {
|
|
1182
1182
|
optionValue = Path.resolve(optionValue);
|
|
@@ -1188,7 +1188,6 @@ class CommandLineOptionsWorker {
|
|
|
1188
1188
|
}
|
|
1189
1189
|
await this.#onExpectsValue(optionDefinition);
|
|
1190
1190
|
break;
|
|
1191
|
-
}
|
|
1192
1191
|
}
|
|
1193
1192
|
return index;
|
|
1194
1193
|
}
|
|
@@ -1197,150 +1196,277 @@ class CommandLineOptionsWorker {
|
|
|
1197
1196
|
}
|
|
1198
1197
|
}
|
|
1199
1198
|
|
|
1199
|
+
class JsonNode {
|
|
1200
|
+
origin;
|
|
1201
|
+
text;
|
|
1202
|
+
constructor(text, origin) {
|
|
1203
|
+
this.origin = origin;
|
|
1204
|
+
this.text = text;
|
|
1205
|
+
}
|
|
1206
|
+
getValue(options) {
|
|
1207
|
+
if (this.text == null) {
|
|
1208
|
+
return undefined;
|
|
1209
|
+
}
|
|
1210
|
+
if (/^['"]/.test(this.text)) {
|
|
1211
|
+
return this.text.slice(1, -1);
|
|
1212
|
+
}
|
|
1213
|
+
if (options?.expectsIdentifier) {
|
|
1214
|
+
return this.text;
|
|
1215
|
+
}
|
|
1216
|
+
if (this.text === "true") {
|
|
1217
|
+
return true;
|
|
1218
|
+
}
|
|
1219
|
+
if (this.text === "false") {
|
|
1220
|
+
return false;
|
|
1221
|
+
}
|
|
1222
|
+
if (/^\d/.test(this.text)) {
|
|
1223
|
+
return Number.parseFloat(this.text);
|
|
1224
|
+
}
|
|
1225
|
+
return undefined;
|
|
1226
|
+
}
|
|
1227
|
+
}
|
|
1228
|
+
|
|
1229
|
+
class JsonScanner {
|
|
1230
|
+
#currentPosition = 0;
|
|
1231
|
+
#previousPosition = 0;
|
|
1232
|
+
#sourceFile;
|
|
1233
|
+
constructor(sourceFile) {
|
|
1234
|
+
this.#sourceFile = sourceFile;
|
|
1235
|
+
}
|
|
1236
|
+
#getOrigin() {
|
|
1237
|
+
return new DiagnosticOrigin(this.#previousPosition, this.#currentPosition, this.#sourceFile);
|
|
1238
|
+
}
|
|
1239
|
+
isRead() {
|
|
1240
|
+
return !(this.#currentPosition < this.#sourceFile.text.length);
|
|
1241
|
+
}
|
|
1242
|
+
#peekCharacter() {
|
|
1243
|
+
return this.#sourceFile.text.charAt(this.#currentPosition);
|
|
1244
|
+
}
|
|
1245
|
+
#peekNextCharacter() {
|
|
1246
|
+
return this.#sourceFile.text.charAt(this.#currentPosition + 1);
|
|
1247
|
+
}
|
|
1248
|
+
peekToken(token) {
|
|
1249
|
+
this.#skipTrivia();
|
|
1250
|
+
return this.#peekCharacter() === token;
|
|
1251
|
+
}
|
|
1252
|
+
read() {
|
|
1253
|
+
this.#skipTrivia();
|
|
1254
|
+
this.#previousPosition = this.#currentPosition;
|
|
1255
|
+
if (/[\s,:\]}]/.test(this.#peekCharacter())) {
|
|
1256
|
+
return new JsonNode(undefined, this.#getOrigin());
|
|
1257
|
+
}
|
|
1258
|
+
let text = "";
|
|
1259
|
+
let closingTokenText = "";
|
|
1260
|
+
if (/[[{'"]/.test(this.#peekCharacter())) {
|
|
1261
|
+
text += this.#readCharacter();
|
|
1262
|
+
switch (text) {
|
|
1263
|
+
case "[":
|
|
1264
|
+
closingTokenText = "]";
|
|
1265
|
+
break;
|
|
1266
|
+
case "{":
|
|
1267
|
+
closingTokenText = "}";
|
|
1268
|
+
break;
|
|
1269
|
+
default:
|
|
1270
|
+
closingTokenText = text;
|
|
1271
|
+
}
|
|
1272
|
+
}
|
|
1273
|
+
while (!this.isRead()) {
|
|
1274
|
+
text += this.#readCharacter();
|
|
1275
|
+
if (text.slice(-1) === closingTokenText || (!closingTokenText && /[\s,:\]}]/.test(this.#peekCharacter()))) {
|
|
1276
|
+
break;
|
|
1277
|
+
}
|
|
1278
|
+
}
|
|
1279
|
+
return new JsonNode(text, this.#getOrigin());
|
|
1280
|
+
}
|
|
1281
|
+
#readCharacter() {
|
|
1282
|
+
return this.#sourceFile.text.charAt(this.#currentPosition++);
|
|
1283
|
+
}
|
|
1284
|
+
readToken(token) {
|
|
1285
|
+
this.#skipTrivia();
|
|
1286
|
+
this.#previousPosition = this.#currentPosition;
|
|
1287
|
+
if (this.#peekCharacter() === token) {
|
|
1288
|
+
this.#currentPosition++;
|
|
1289
|
+
return new JsonNode(token, this.#getOrigin());
|
|
1290
|
+
}
|
|
1291
|
+
return new JsonNode(undefined, this.#getOrigin());
|
|
1292
|
+
}
|
|
1293
|
+
#skipTrivia() {
|
|
1294
|
+
while (!this.isRead()) {
|
|
1295
|
+
if (/\s/.test(this.#peekCharacter())) {
|
|
1296
|
+
this.#currentPosition++;
|
|
1297
|
+
continue;
|
|
1298
|
+
}
|
|
1299
|
+
if (this.#peekCharacter() === "/") {
|
|
1300
|
+
if (this.#peekNextCharacter() === "/") {
|
|
1301
|
+
this.#currentPosition += 2;
|
|
1302
|
+
while (!this.isRead()) {
|
|
1303
|
+
if (this.#readCharacter() === "\n") {
|
|
1304
|
+
break;
|
|
1305
|
+
}
|
|
1306
|
+
}
|
|
1307
|
+
continue;
|
|
1308
|
+
}
|
|
1309
|
+
if (this.#peekNextCharacter() === "*") {
|
|
1310
|
+
this.#currentPosition += 2;
|
|
1311
|
+
while (!this.isRead()) {
|
|
1312
|
+
if (this.#peekCharacter() === "*" && this.#peekNextCharacter() === "/") {
|
|
1313
|
+
this.#currentPosition += 2;
|
|
1314
|
+
break;
|
|
1315
|
+
}
|
|
1316
|
+
this.#currentPosition++;
|
|
1317
|
+
}
|
|
1318
|
+
continue;
|
|
1319
|
+
}
|
|
1320
|
+
}
|
|
1321
|
+
break;
|
|
1322
|
+
}
|
|
1323
|
+
this.#previousPosition = this.#currentPosition;
|
|
1324
|
+
}
|
|
1325
|
+
}
|
|
1326
|
+
|
|
1200
1327
|
class ConfigFileOptionsWorker {
|
|
1201
|
-
#compiler;
|
|
1202
1328
|
#configFileOptionDefinitions;
|
|
1203
1329
|
#configFileOptions;
|
|
1204
|
-
#
|
|
1330
|
+
#jsonScanner;
|
|
1205
1331
|
#onDiagnostics;
|
|
1206
1332
|
#optionGroup = 4;
|
|
1207
1333
|
#optionValidator;
|
|
1334
|
+
#sourceFile;
|
|
1208
1335
|
#storeService;
|
|
1209
|
-
constructor(
|
|
1210
|
-
this.#compiler = compiler;
|
|
1336
|
+
constructor(configFileOptions, sourceFile, storeService, onDiagnostics) {
|
|
1211
1337
|
this.#configFileOptions = configFileOptions;
|
|
1212
|
-
this.#
|
|
1338
|
+
this.#sourceFile = sourceFile;
|
|
1213
1339
|
this.#storeService = storeService;
|
|
1214
1340
|
this.#onDiagnostics = onDiagnostics;
|
|
1215
1341
|
this.#configFileOptionDefinitions = OptionDefinitionsMap.for(this.#optionGroup);
|
|
1342
|
+
this.#jsonScanner = new JsonScanner(this.#sourceFile);
|
|
1216
1343
|
this.#optionValidator = new OptionValidator(this.#optionGroup, this.#storeService, this.#onDiagnostics);
|
|
1217
1344
|
}
|
|
1218
|
-
#
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
const sourceFile = this.#compiler.parseJsonText(this.#configFilePath, sourceText);
|
|
1224
|
-
if (sourceFile.parseDiagnostics.length > 0) {
|
|
1225
|
-
this.#onDiagnostics(Diagnostic.fromDiagnostics(sourceFile.parseDiagnostics, this.#compiler));
|
|
1226
|
-
return;
|
|
1227
|
-
}
|
|
1228
|
-
const rootExpression = sourceFile.statements[0]?.expression;
|
|
1229
|
-
if (!rootExpression) {
|
|
1230
|
-
return;
|
|
1231
|
-
}
|
|
1232
|
-
if (!this.#compiler.isObjectLiteralExpression(rootExpression)) {
|
|
1233
|
-
const origin = DiagnosticOrigin.fromJsonNode(rootExpression, sourceFile, this.#skipTrivia);
|
|
1234
|
-
this.#onDiagnostics(Diagnostic.error("The root value of a configuration file must be an object literal.", origin));
|
|
1235
|
-
return;
|
|
1236
|
-
}
|
|
1237
|
-
for (const property of rootExpression.properties) {
|
|
1238
|
-
if (this.#compiler.isPropertyAssignment(property)) {
|
|
1239
|
-
if (!this.#isDoubleQuotedString(property.name, sourceFile)) {
|
|
1240
|
-
const origin = DiagnosticOrigin.fromJsonNode(property.name, sourceFile, this.#skipTrivia);
|
|
1241
|
-
this.#onDiagnostics(Diagnostic.error(ConfigDiagnosticText.doubleQuotesExpected(), origin));
|
|
1242
|
-
continue;
|
|
1243
|
-
}
|
|
1244
|
-
const optionName = property.name.text;
|
|
1245
|
-
if (optionName === "$schema") {
|
|
1246
|
-
continue;
|
|
1247
|
-
}
|
|
1248
|
-
const optionDefinition = this.#configFileOptionDefinitions.get(optionName);
|
|
1249
|
-
if (optionDefinition) {
|
|
1250
|
-
this.#configFileOptions[optionDefinition.name] = await this.#parseOptionValue(sourceFile, property.initializer, optionDefinition);
|
|
1251
|
-
}
|
|
1252
|
-
else {
|
|
1253
|
-
const origin = DiagnosticOrigin.fromJsonNode(property.name, sourceFile, this.#skipTrivia);
|
|
1254
|
-
this.#onDiagnostics(Diagnostic.error(ConfigDiagnosticText.unknownOption(optionName), origin));
|
|
1255
|
-
}
|
|
1256
|
-
}
|
|
1257
|
-
}
|
|
1258
|
-
return;
|
|
1345
|
+
#onRequiresValue(optionDefinition, jsonNode, isListItem) {
|
|
1346
|
+
const text = isListItem
|
|
1347
|
+
? ConfigDiagnosticText.expectsListItemType(optionDefinition.name, optionDefinition.brand)
|
|
1348
|
+
: ConfigDiagnosticText.requiresValueType(optionDefinition.name, optionDefinition.brand, this.#optionGroup);
|
|
1349
|
+
this.#onDiagnostics(Diagnostic.error(text, jsonNode.origin));
|
|
1259
1350
|
}
|
|
1260
|
-
async #
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
|
|
1264
|
-
|
|
1351
|
+
async #parseValue(optionDefinition, isListItem = false) {
|
|
1352
|
+
let jsonNode;
|
|
1353
|
+
let optionValue;
|
|
1354
|
+
switch (optionDefinition.brand) {
|
|
1355
|
+
case "boolean": {
|
|
1356
|
+
jsonNode = this.#jsonScanner.read();
|
|
1357
|
+
optionValue = jsonNode.getValue();
|
|
1358
|
+
if (typeof optionValue !== "boolean") {
|
|
1359
|
+
this.#onRequiresValue(optionDefinition, jsonNode, isListItem);
|
|
1360
|
+
break;
|
|
1265
1361
|
}
|
|
1266
1362
|
break;
|
|
1267
1363
|
}
|
|
1268
|
-
case
|
|
1269
|
-
|
|
1270
|
-
|
|
1364
|
+
case "string": {
|
|
1365
|
+
jsonNode = this.#jsonScanner.read();
|
|
1366
|
+
optionValue = jsonNode.getValue();
|
|
1367
|
+
if (typeof optionValue !== "string") {
|
|
1368
|
+
this.#onRequiresValue(optionDefinition, jsonNode, isListItem);
|
|
1369
|
+
break;
|
|
1271
1370
|
}
|
|
1371
|
+
if (optionDefinition.name === "rootPath") {
|
|
1372
|
+
optionValue = Path.resolve(Path.dirname(this.#sourceFile.fileName), optionValue);
|
|
1373
|
+
}
|
|
1374
|
+
await this.#optionValidator.check(optionDefinition.name, optionValue, optionDefinition.brand, jsonNode.origin);
|
|
1272
1375
|
break;
|
|
1273
1376
|
}
|
|
1274
|
-
case
|
|
1275
|
-
|
|
1276
|
-
|
|
1277
|
-
this.#
|
|
1278
|
-
|
|
1377
|
+
case "list": {
|
|
1378
|
+
const leftBracketToken = this.#jsonScanner.readToken("[");
|
|
1379
|
+
if (!leftBracketToken.text) {
|
|
1380
|
+
jsonNode = this.#jsonScanner.read();
|
|
1381
|
+
this.#onRequiresValue(optionDefinition, jsonNode, isListItem);
|
|
1382
|
+
break;
|
|
1279
1383
|
}
|
|
1280
|
-
|
|
1281
|
-
|
|
1282
|
-
if (
|
|
1283
|
-
|
|
1384
|
+
optionValue = [];
|
|
1385
|
+
while (!this.#jsonScanner.isRead()) {
|
|
1386
|
+
if (this.#jsonScanner.peekToken("]")) {
|
|
1387
|
+
break;
|
|
1284
1388
|
}
|
|
1285
|
-
const
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
if (optionDefinition.brand === "list") {
|
|
1293
|
-
const value = [];
|
|
1294
|
-
for (const element of valueExpression.elements) {
|
|
1295
|
-
value.push(await this.#parseOptionValue(sourceFile, element, optionDefinition.items, true));
|
|
1389
|
+
const item = await this.#parseValue(optionDefinition.items, true);
|
|
1390
|
+
if (item != null) {
|
|
1391
|
+
optionValue.push(item);
|
|
1392
|
+
}
|
|
1393
|
+
const commaToken = this.#jsonScanner.readToken(",");
|
|
1394
|
+
if (!commaToken.text) {
|
|
1395
|
+
break;
|
|
1296
1396
|
}
|
|
1297
|
-
|
|
1397
|
+
}
|
|
1398
|
+
const rightBracketToken = this.#jsonScanner.readToken("]");
|
|
1399
|
+
if (!rightBracketToken.text) {
|
|
1400
|
+
const text = ConfigDiagnosticText.expected("closing ']'");
|
|
1401
|
+
const relatedText = ConfigDiagnosticText.seen("opening '['");
|
|
1402
|
+
const diagnostic = Diagnostic.error(text, rightBracketToken.origin).add({
|
|
1403
|
+
related: [Diagnostic.error(relatedText, leftBracketToken.origin)],
|
|
1404
|
+
});
|
|
1405
|
+
this.#onDiagnostics(diagnostic);
|
|
1298
1406
|
}
|
|
1299
1407
|
break;
|
|
1300
1408
|
}
|
|
1301
1409
|
}
|
|
1302
|
-
|
|
1303
|
-
? ConfigDiagnosticText.expectsListItemType(optionDefinition.name, optionDefinition.brand)
|
|
1304
|
-
: ConfigDiagnosticText.requiresValueType(optionDefinition.name, optionDefinition.brand, this.#optionGroup);
|
|
1305
|
-
const origin = DiagnosticOrigin.fromJsonNode(valueExpression, sourceFile, this.#skipTrivia);
|
|
1306
|
-
this.#onDiagnostics(Diagnostic.error(text, origin));
|
|
1307
|
-
return;
|
|
1410
|
+
return optionValue;
|
|
1308
1411
|
}
|
|
1309
|
-
#
|
|
1310
|
-
const
|
|
1311
|
-
|
|
1312
|
-
|
|
1313
|
-
|
|
1314
|
-
|
|
1412
|
+
async #parseObject() {
|
|
1413
|
+
const leftBraceToken = this.#jsonScanner.readToken("{");
|
|
1414
|
+
if (this.#jsonScanner.isRead()) {
|
|
1415
|
+
return;
|
|
1416
|
+
}
|
|
1417
|
+
if (!leftBraceToken.text) {
|
|
1418
|
+
const text = ConfigDiagnosticText.expected("'{'");
|
|
1419
|
+
this.#onDiagnostics(Diagnostic.error(text, leftBraceToken.origin));
|
|
1420
|
+
return;
|
|
1421
|
+
}
|
|
1422
|
+
while (!this.#jsonScanner.isRead()) {
|
|
1423
|
+
if (this.#jsonScanner.peekToken("}")) {
|
|
1424
|
+
break;
|
|
1315
1425
|
}
|
|
1316
|
-
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
|
|
1426
|
+
const optionNameNode = this.#jsonScanner.read();
|
|
1427
|
+
const optionName = optionNameNode.getValue({ expectsIdentifier: true });
|
|
1428
|
+
if (!optionName) {
|
|
1429
|
+
const text = ConfigDiagnosticText.expected("option name");
|
|
1430
|
+
this.#onDiagnostics(Diagnostic.error(text, optionNameNode.origin));
|
|
1431
|
+
return;
|
|
1432
|
+
}
|
|
1433
|
+
const optionDefinition = this.#configFileOptionDefinitions.get(optionName);
|
|
1434
|
+
if (!optionDefinition) {
|
|
1435
|
+
const text = ConfigDiagnosticText.unknownOption(optionName);
|
|
1436
|
+
this.#onDiagnostics(Diagnostic.error(text, optionNameNode.origin));
|
|
1437
|
+
if (this.#jsonScanner.readToken(":")) {
|
|
1438
|
+
this.#jsonScanner.read();
|
|
1326
1439
|
}
|
|
1327
|
-
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
if (text.charAt(position) === "*" && text.charAt(position + 1) === "/") {
|
|
1331
|
-
position += 2;
|
|
1332
|
-
break;
|
|
1333
|
-
}
|
|
1334
|
-
position++;
|
|
1335
|
-
}
|
|
1336
|
-
continue;
|
|
1440
|
+
const commaToken = this.#jsonScanner.readToken(",");
|
|
1441
|
+
if (!commaToken.text) {
|
|
1442
|
+
break;
|
|
1337
1443
|
}
|
|
1338
|
-
position++;
|
|
1339
1444
|
continue;
|
|
1340
1445
|
}
|
|
1341
|
-
|
|
1446
|
+
if (this.#jsonScanner.peekToken(":")) {
|
|
1447
|
+
this.#jsonScanner.readToken(":");
|
|
1448
|
+
}
|
|
1449
|
+
const parsedValue = await this.#parseValue(optionDefinition);
|
|
1450
|
+
if (optionDefinition.name !== "$schema") {
|
|
1451
|
+
this.#configFileOptions[optionDefinition.name] = parsedValue;
|
|
1452
|
+
}
|
|
1453
|
+
const commaToken = this.#jsonScanner.readToken(",");
|
|
1454
|
+
if (!commaToken.text) {
|
|
1455
|
+
break;
|
|
1456
|
+
}
|
|
1342
1457
|
}
|
|
1343
|
-
|
|
1458
|
+
const rightBraceToken = this.#jsonScanner.readToken("}");
|
|
1459
|
+
if (!rightBraceToken.text) {
|
|
1460
|
+
const text = ConfigDiagnosticText.expected("closing '}'");
|
|
1461
|
+
const relatedText = ConfigDiagnosticText.seen("opening '{'");
|
|
1462
|
+
const diagnostic = Diagnostic.error(text, rightBraceToken.origin).add({
|
|
1463
|
+
related: [Diagnostic.error(relatedText, leftBraceToken.origin)],
|
|
1464
|
+
});
|
|
1465
|
+
this.#onDiagnostics(diagnostic);
|
|
1466
|
+
}
|
|
1467
|
+
}
|
|
1468
|
+
async parse() {
|
|
1469
|
+
await this.#parseObject();
|
|
1344
1470
|
}
|
|
1345
1471
|
}
|
|
1346
1472
|
|
|
@@ -1357,7 +1483,7 @@ class ConfigService {
|
|
|
1357
1483
|
#configFilePath = Path.resolve(defaultOptions.rootPath, "./tstyche.config.json");
|
|
1358
1484
|
#pathMatch = [];
|
|
1359
1485
|
#onDiagnostics(diagnostics) {
|
|
1360
|
-
EventEmitter.dispatch(["config:error", { diagnostics:
|
|
1486
|
+
EventEmitter.dispatch(["config:error", { diagnostics: [diagnostics] }]);
|
|
1361
1487
|
}
|
|
1362
1488
|
async parseCommandLine(commandLineArgs, storeService) {
|
|
1363
1489
|
this.#commandLineOptions = {};
|
|
@@ -1379,12 +1505,9 @@ class ConfigService {
|
|
|
1379
1505
|
const configFileText = await fs.readFile(this.#configFilePath, {
|
|
1380
1506
|
encoding: "utf8",
|
|
1381
1507
|
});
|
|
1382
|
-
const
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
}
|
|
1386
|
-
const configFileWorker = new ConfigFileOptionsWorker(compiler, this.#configFileOptions, this.#configFilePath, storeService, this.#onDiagnostics);
|
|
1387
|
-
await configFileWorker.parse(configFileText);
|
|
1508
|
+
const sourceFile = new SourceFile(this.#configFilePath, configFileText);
|
|
1509
|
+
const configFileWorker = new ConfigFileOptionsWorker(this.#configFileOptions, sourceFile, storeService, this.#onDiagnostics);
|
|
1510
|
+
await configFileWorker.parse();
|
|
1388
1511
|
}
|
|
1389
1512
|
resolveConfig() {
|
|
1390
1513
|
return {
|
|
@@ -1406,6 +1529,7 @@ var OptionBrand;
|
|
|
1406
1529
|
OptionBrand["BareTrue"] = "bareTrue";
|
|
1407
1530
|
OptionBrand["List"] = "list";
|
|
1408
1531
|
})(OptionBrand || (OptionBrand = {}));
|
|
1532
|
+
|
|
1409
1533
|
var OptionGroup;
|
|
1410
1534
|
(function (OptionGroup) {
|
|
1411
1535
|
OptionGroup[OptionGroup["CommandLine"] = 2] = "CommandLine";
|
|
@@ -1580,6 +1704,7 @@ class RunReporter extends Reporter {
|
|
|
1580
1704
|
#hasReportedError = false;
|
|
1581
1705
|
#isFileViewExpanded = false;
|
|
1582
1706
|
#resolvedConfig;
|
|
1707
|
+
#seenDeprecations = new Set();
|
|
1583
1708
|
constructor(resolvedConfig, outputService) {
|
|
1584
1709
|
super(outputService);
|
|
1585
1710
|
this.#resolvedConfig = resolvedConfig;
|
|
@@ -1589,31 +1714,35 @@ class RunReporter extends Reporter {
|
|
|
1589
1714
|
}
|
|
1590
1715
|
handleEvent([eventName, payload]) {
|
|
1591
1716
|
switch (eventName) {
|
|
1592
|
-
case "
|
|
1593
|
-
|
|
1717
|
+
case "deprecation:info": {
|
|
1718
|
+
for (const diagnostic of payload.diagnostics) {
|
|
1719
|
+
if (!this.#seenDeprecations.has(diagnostic.text.toString())) {
|
|
1720
|
+
this.#fileView.addMessage(diagnosticText(diagnostic));
|
|
1721
|
+
this.#seenDeprecations.add(diagnostic.text.toString());
|
|
1722
|
+
}
|
|
1723
|
+
}
|
|
1594
1724
|
break;
|
|
1595
1725
|
}
|
|
1596
|
-
case "
|
|
1726
|
+
case "run:start":
|
|
1727
|
+
this.#isFileViewExpanded = payload.result.tasks.length === 1 && this.#resolvedConfig.watch !== true;
|
|
1728
|
+
break;
|
|
1729
|
+
case "store:adds":
|
|
1597
1730
|
this.outputService.writeMessage(addsPackageText(payload.packageVersion, payload.packagePath));
|
|
1598
1731
|
this.#hasReportedAdds = true;
|
|
1599
1732
|
break;
|
|
1600
|
-
|
|
1601
|
-
case "store:error": {
|
|
1733
|
+
case "store:error":
|
|
1602
1734
|
for (const diagnostic of payload.diagnostics) {
|
|
1603
1735
|
this.outputService.writeError(diagnosticText(diagnostic));
|
|
1604
1736
|
}
|
|
1605
1737
|
break;
|
|
1606
|
-
|
|
1607
|
-
case "target:start": {
|
|
1738
|
+
case "target:start":
|
|
1608
1739
|
this.#fileCount = payload.result.tasks.length;
|
|
1609
1740
|
break;
|
|
1610
|
-
|
|
1611
|
-
case "target:end": {
|
|
1741
|
+
case "target:end":
|
|
1612
1742
|
this.#currentCompilerVersion = undefined;
|
|
1613
1743
|
this.#currentProjectConfigFilePath = undefined;
|
|
1614
1744
|
break;
|
|
1615
|
-
|
|
1616
|
-
case "project:uses": {
|
|
1745
|
+
case "project:uses":
|
|
1617
1746
|
if (this.#currentCompilerVersion !== payload.compilerVersion ||
|
|
1618
1747
|
this.#currentProjectConfigFilePath !== payload.projectConfigFilePath) {
|
|
1619
1748
|
this.outputService.writeMessage(usesCompilerText(payload.compilerVersion, payload.projectConfigFilePath, {
|
|
@@ -1624,28 +1753,24 @@ class RunReporter extends Reporter {
|
|
|
1624
1753
|
this.#currentProjectConfigFilePath = payload.projectConfigFilePath;
|
|
1625
1754
|
}
|
|
1626
1755
|
break;
|
|
1627
|
-
|
|
1628
|
-
case "project:error": {
|
|
1756
|
+
case "project:error":
|
|
1629
1757
|
for (const diagnostic of payload.diagnostics) {
|
|
1630
1758
|
this.outputService.writeError(diagnosticText(diagnostic));
|
|
1631
1759
|
}
|
|
1632
1760
|
break;
|
|
1633
|
-
|
|
1634
|
-
case "task:start": {
|
|
1761
|
+
case "task:start":
|
|
1635
1762
|
if (!this.#resolvedConfig.noInteractive) {
|
|
1636
1763
|
this.outputService.writeMessage(taskStatusText(payload.result.status, payload.result.task));
|
|
1637
1764
|
}
|
|
1638
1765
|
this.#fileCount--;
|
|
1639
1766
|
this.#hasReportedError = false;
|
|
1640
1767
|
break;
|
|
1641
|
-
|
|
1642
|
-
case "task:error": {
|
|
1768
|
+
case "task:error":
|
|
1643
1769
|
for (const diagnostic of payload.diagnostics) {
|
|
1644
1770
|
this.#fileView.addMessage(diagnosticText(diagnostic));
|
|
1645
1771
|
}
|
|
1646
1772
|
break;
|
|
1647
|
-
|
|
1648
|
-
case "task:end": {
|
|
1773
|
+
case "task:end":
|
|
1649
1774
|
if (!this.#resolvedConfig.noInteractive) {
|
|
1650
1775
|
this.outputService.eraseLastLine();
|
|
1651
1776
|
}
|
|
@@ -1656,33 +1781,29 @@ class RunReporter extends Reporter {
|
|
|
1656
1781
|
this.#hasReportedError = true;
|
|
1657
1782
|
}
|
|
1658
1783
|
this.#fileView.clear();
|
|
1784
|
+
this.#seenDeprecations.clear();
|
|
1659
1785
|
break;
|
|
1660
|
-
|
|
1661
|
-
case "describe:start": {
|
|
1786
|
+
case "describe:start":
|
|
1662
1787
|
if (this.#isFileViewExpanded) {
|
|
1663
1788
|
this.#fileView.beginDescribe(payload.result.describe.name);
|
|
1664
1789
|
}
|
|
1665
1790
|
break;
|
|
1666
|
-
|
|
1667
|
-
case "describe:end": {
|
|
1791
|
+
case "describe:end":
|
|
1668
1792
|
if (this.#isFileViewExpanded) {
|
|
1669
1793
|
this.#fileView.endDescribe();
|
|
1670
1794
|
}
|
|
1671
1795
|
break;
|
|
1672
|
-
|
|
1673
|
-
case "test:skip": {
|
|
1796
|
+
case "test:skip":
|
|
1674
1797
|
if (this.#isFileViewExpanded) {
|
|
1675
1798
|
this.#fileView.addTest("skip", payload.result.test.name);
|
|
1676
1799
|
}
|
|
1677
1800
|
break;
|
|
1678
|
-
|
|
1679
|
-
case "test:todo": {
|
|
1801
|
+
case "test:todo":
|
|
1680
1802
|
if (this.#isFileViewExpanded) {
|
|
1681
1803
|
this.#fileView.addTest("todo", payload.result.test.name);
|
|
1682
1804
|
}
|
|
1683
1805
|
break;
|
|
1684
|
-
|
|
1685
|
-
case "test:error": {
|
|
1806
|
+
case "test:error":
|
|
1686
1807
|
if (this.#isFileViewExpanded) {
|
|
1687
1808
|
this.#fileView.addTest("fail", payload.result.test.name);
|
|
1688
1809
|
}
|
|
@@ -1690,26 +1811,22 @@ class RunReporter extends Reporter {
|
|
|
1690
1811
|
this.#fileView.addMessage(diagnosticText(diagnostic));
|
|
1691
1812
|
}
|
|
1692
1813
|
break;
|
|
1693
|
-
|
|
1694
|
-
case "test:fail": {
|
|
1814
|
+
case "test:fail":
|
|
1695
1815
|
if (this.#isFileViewExpanded) {
|
|
1696
1816
|
this.#fileView.addTest("fail", payload.result.test.name);
|
|
1697
1817
|
}
|
|
1698
1818
|
break;
|
|
1699
|
-
|
|
1700
|
-
case "test:pass": {
|
|
1819
|
+
case "test:pass":
|
|
1701
1820
|
if (this.#isFileViewExpanded) {
|
|
1702
1821
|
this.#fileView.addTest("pass", payload.result.test.name);
|
|
1703
1822
|
}
|
|
1704
1823
|
break;
|
|
1705
|
-
}
|
|
1706
1824
|
case "expect:error":
|
|
1707
|
-
case "expect:fail":
|
|
1825
|
+
case "expect:fail":
|
|
1708
1826
|
for (const diagnostic of payload.diagnostics) {
|
|
1709
1827
|
this.#fileView.addMessage(diagnosticText(diagnostic));
|
|
1710
1828
|
}
|
|
1711
1829
|
break;
|
|
1712
|
-
}
|
|
1713
1830
|
}
|
|
1714
1831
|
}
|
|
1715
1832
|
}
|
|
@@ -1723,14 +1840,12 @@ class SetupReporter extends Reporter {
|
|
|
1723
1840
|
if ("diagnostics" in payload) {
|
|
1724
1841
|
for (const diagnostic of payload.diagnostics) {
|
|
1725
1842
|
switch (diagnostic.category) {
|
|
1726
|
-
case "error":
|
|
1843
|
+
case "error":
|
|
1727
1844
|
this.outputService.writeError(diagnosticText(diagnostic));
|
|
1728
1845
|
break;
|
|
1729
|
-
|
|
1730
|
-
case "warning": {
|
|
1846
|
+
case "warning":
|
|
1731
1847
|
this.outputService.writeWarning(diagnosticText(diagnostic));
|
|
1732
1848
|
break;
|
|
1733
|
-
}
|
|
1734
1849
|
}
|
|
1735
1850
|
}
|
|
1736
1851
|
}
|
|
@@ -1739,20 +1854,17 @@ class SetupReporter extends Reporter {
|
|
|
1739
1854
|
|
|
1740
1855
|
class SummaryReporter extends Reporter {
|
|
1741
1856
|
handleEvent([eventName, payload]) {
|
|
1742
|
-
|
|
1743
|
-
|
|
1744
|
-
|
|
1745
|
-
|
|
1746
|
-
|
|
1747
|
-
|
|
1748
|
-
|
|
1749
|
-
|
|
1750
|
-
|
|
1751
|
-
|
|
1752
|
-
|
|
1753
|
-
}));
|
|
1754
|
-
break;
|
|
1755
|
-
}
|
|
1857
|
+
if (eventName === "run:end") {
|
|
1858
|
+
this.outputService.writeMessage(summaryText({
|
|
1859
|
+
duration: payload.result.timing.duration,
|
|
1860
|
+
expectCount: payload.result.expectCount,
|
|
1861
|
+
fileCount: payload.result.fileCount,
|
|
1862
|
+
onlyMatch: payload.result.resolvedConfig.only,
|
|
1863
|
+
pathMatch: payload.result.resolvedConfig.pathMatch,
|
|
1864
|
+
skipMatch: payload.result.resolvedConfig.skip,
|
|
1865
|
+
targetCount: payload.result.targetCount,
|
|
1866
|
+
testCount: payload.result.testCount,
|
|
1867
|
+
}));
|
|
1756
1868
|
}
|
|
1757
1869
|
}
|
|
1758
1870
|
}
|
|
@@ -1760,22 +1872,19 @@ class SummaryReporter extends Reporter {
|
|
|
1760
1872
|
class WatchReporter extends Reporter {
|
|
1761
1873
|
handleEvent([eventName, payload]) {
|
|
1762
1874
|
switch (eventName) {
|
|
1763
|
-
case "run:start":
|
|
1875
|
+
case "run:start":
|
|
1764
1876
|
this.outputService.clearTerminal();
|
|
1765
1877
|
break;
|
|
1766
|
-
|
|
1767
|
-
case "run:end": {
|
|
1878
|
+
case "run:end":
|
|
1768
1879
|
this.outputService.writeMessage(watchUsageText());
|
|
1769
1880
|
break;
|
|
1770
|
-
|
|
1771
|
-
case "watch:error": {
|
|
1881
|
+
case "watch:error":
|
|
1772
1882
|
this.outputService.clearTerminal();
|
|
1773
1883
|
for (const diagnostic of payload.diagnostics) {
|
|
1774
1884
|
this.outputService.writeError(diagnosticText(diagnostic));
|
|
1775
1885
|
}
|
|
1776
1886
|
this.outputService.writeMessage(waitingForFileChangesText());
|
|
1777
1887
|
break;
|
|
1778
|
-
}
|
|
1779
1888
|
}
|
|
1780
1889
|
}
|
|
1781
1890
|
}
|
|
@@ -2082,19 +2191,17 @@ class WatchService {
|
|
|
2082
2191
|
case "\u0004":
|
|
2083
2192
|
case "\u001B":
|
|
2084
2193
|
case "q":
|
|
2085
|
-
case "x":
|
|
2194
|
+
case "x":
|
|
2086
2195
|
onClose("watchClose");
|
|
2087
2196
|
break;
|
|
2088
|
-
}
|
|
2089
2197
|
case "\u000D":
|
|
2090
2198
|
case "\u0020":
|
|
2091
|
-
case "a":
|
|
2199
|
+
case "a":
|
|
2092
2200
|
debounce.clearTimeout();
|
|
2093
|
-
if (this.#watchedTestFiles.size
|
|
2201
|
+
if (this.#watchedTestFiles.size > 0) {
|
|
2094
2202
|
debounce.resolveWith([...this.#watchedTestFiles.values()]);
|
|
2095
2203
|
}
|
|
2096
2204
|
break;
|
|
2097
|
-
}
|
|
2098
2205
|
}
|
|
2099
2206
|
};
|
|
2100
2207
|
this.#inputService = new InputService(onInput);
|
|
@@ -2176,23 +2283,21 @@ class TestMember {
|
|
|
2176
2283
|
return node.parent;
|
|
2177
2284
|
};
|
|
2178
2285
|
switch (this.brand) {
|
|
2179
|
-
case "describe":
|
|
2286
|
+
case "describe":
|
|
2180
2287
|
for (const member of this.members) {
|
|
2181
2288
|
if (member.brand === "expect") {
|
|
2182
2289
|
diagnostics.push(Diagnostic.error(getText(member.node), DiagnosticOrigin.fromNode(getParentCallExpression(member.node))));
|
|
2183
2290
|
}
|
|
2184
2291
|
}
|
|
2185
2292
|
break;
|
|
2186
|
-
}
|
|
2187
2293
|
case "test":
|
|
2188
|
-
case "expect":
|
|
2294
|
+
case "expect":
|
|
2189
2295
|
for (const member of this.members) {
|
|
2190
2296
|
if (member.brand !== "expect") {
|
|
2191
2297
|
diagnostics.push(Diagnostic.error(getText(member.node), DiagnosticOrigin.fromNode(member.node)));
|
|
2192
2298
|
}
|
|
2193
2299
|
}
|
|
2194
2300
|
break;
|
|
2195
|
-
}
|
|
2196
2301
|
}
|
|
2197
2302
|
return diagnostics;
|
|
2198
2303
|
}
|
|
@@ -2277,22 +2382,18 @@ class IdentifierLookup {
|
|
|
2277
2382
|
break;
|
|
2278
2383
|
}
|
|
2279
2384
|
switch (expression.name.getText()) {
|
|
2280
|
-
case "fail":
|
|
2385
|
+
case "fail":
|
|
2281
2386
|
flags |= 1;
|
|
2282
2387
|
break;
|
|
2283
|
-
|
|
2284
|
-
case "only": {
|
|
2388
|
+
case "only":
|
|
2285
2389
|
flags |= 2;
|
|
2286
2390
|
break;
|
|
2287
|
-
|
|
2288
|
-
case "skip": {
|
|
2391
|
+
case "skip":
|
|
2289
2392
|
flags |= 4;
|
|
2290
2393
|
break;
|
|
2291
|
-
|
|
2292
|
-
case "todo": {
|
|
2394
|
+
case "todo":
|
|
2293
2395
|
flags |= 8;
|
|
2294
2396
|
break;
|
|
2295
|
-
}
|
|
2296
2397
|
}
|
|
2297
2398
|
expression = expression.expression;
|
|
2298
2399
|
}
|
|
@@ -2403,6 +2504,7 @@ var TestMemberBrand;
|
|
|
2403
2504
|
TestMemberBrand["Test"] = "test";
|
|
2404
2505
|
TestMemberBrand["Expect"] = "expect";
|
|
2405
2506
|
})(TestMemberBrand || (TestMemberBrand = {}));
|
|
2507
|
+
|
|
2406
2508
|
var TestMemberFlags;
|
|
2407
2509
|
(function (TestMemberFlags) {
|
|
2408
2510
|
TestMemberFlags[TestMemberFlags["None"] = 0] = "None";
|
|
@@ -2546,6 +2648,12 @@ class ExpectDiagnosticText {
|
|
|
2546
2648
|
static componentDoesNotAcceptProps(isTypeNode) {
|
|
2547
2649
|
return `${isTypeNode ? "Component type" : "Component"} does not accept props of the given type.`;
|
|
2548
2650
|
}
|
|
2651
|
+
static matcherIsDeprecated(matcherNameText) {
|
|
2652
|
+
return [
|
|
2653
|
+
`The '.${matcherNameText}()' matcher is deprecated and will be removed in TSTyche 4.`,
|
|
2654
|
+
"To learn more, visit https://tstyche.org/releases/tstyche-3",
|
|
2655
|
+
];
|
|
2656
|
+
}
|
|
2549
2657
|
static matcherIsNotSupported(matcherNameText) {
|
|
2550
2658
|
return `The '.${matcherNameText}()' matcher is not supported.`;
|
|
2551
2659
|
}
|
|
@@ -3160,6 +3268,11 @@ class ExpectService {
|
|
|
3160
3268
|
}
|
|
3161
3269
|
match(assertion, onDiagnostics) {
|
|
3162
3270
|
const matcherNameText = assertion.matcherName.getText();
|
|
3271
|
+
if (matcherNameText === "toMatch") {
|
|
3272
|
+
const text = ExpectDiagnosticText.matcherIsDeprecated(matcherNameText);
|
|
3273
|
+
const origin = DiagnosticOrigin.fromNode(assertion.matcherName);
|
|
3274
|
+
EventEmitter.dispatch(["deprecation:info", { diagnostics: [Diagnostic.warning(text, origin)] }]);
|
|
3275
|
+
}
|
|
3163
3276
|
if (!assertion.source[0]) {
|
|
3164
3277
|
this.#onSourceArgumentOrTypeArgumentMustBeProvided(assertion, onDiagnostics);
|
|
3165
3278
|
return;
|
|
@@ -3170,13 +3283,12 @@ class ExpectService {
|
|
|
3170
3283
|
case "toBe":
|
|
3171
3284
|
case "toBeAssignableTo":
|
|
3172
3285
|
case "toBeAssignableWith":
|
|
3173
|
-
case "toMatch":
|
|
3286
|
+
case "toMatch":
|
|
3174
3287
|
if (!assertion.target[0]) {
|
|
3175
3288
|
this.#onTargetArgumentOrTypeArgumentMustBeProvided(assertion, onDiagnostics);
|
|
3176
3289
|
return;
|
|
3177
3290
|
}
|
|
3178
3291
|
return this[matcherNameText].match(matchWorker, assertion.source[0], assertion.target[0], onDiagnostics);
|
|
3179
|
-
}
|
|
3180
3292
|
case "toBeAny":
|
|
3181
3293
|
case "toBeBigInt":
|
|
3182
3294
|
case "toBeBoolean":
|
|
@@ -3188,27 +3300,26 @@ class ExpectService {
|
|
|
3188
3300
|
case "toBeUndefined":
|
|
3189
3301
|
case "toBeUniqueSymbol":
|
|
3190
3302
|
case "toBeUnknown":
|
|
3191
|
-
case "toBeVoid":
|
|
3303
|
+
case "toBeVoid":
|
|
3192
3304
|
return this[matcherNameText].match(matchWorker, assertion.source[0]);
|
|
3193
|
-
|
|
3194
|
-
case "toHaveProperty": {
|
|
3305
|
+
case "toHaveProperty":
|
|
3195
3306
|
if (!assertion.target[0]) {
|
|
3196
3307
|
this.#onTargetArgumentMustBeProvided("key", assertion, onDiagnostics);
|
|
3197
3308
|
return;
|
|
3198
3309
|
}
|
|
3199
3310
|
return this.toHaveProperty.match(matchWorker, assertion.source[0], assertion.target[0], onDiagnostics);
|
|
3200
|
-
|
|
3201
|
-
case "toRaiseError": {
|
|
3311
|
+
case "toRaiseError":
|
|
3202
3312
|
return this.toRaiseError.match(matchWorker, assertion.source[0], [...assertion.target], onDiagnostics);
|
|
3203
|
-
|
|
3204
|
-
|
|
3205
|
-
const text = ExpectDiagnosticText.matcherIsNotSupported(matcherNameText);
|
|
3206
|
-
const origin = DiagnosticOrigin.fromNode(assertion.matcherName);
|
|
3207
|
-
onDiagnostics(Diagnostic.error(text, origin));
|
|
3208
|
-
}
|
|
3313
|
+
default:
|
|
3314
|
+
this.#onMatcherIsNotSupported(matcherNameText, assertion, onDiagnostics);
|
|
3209
3315
|
}
|
|
3210
3316
|
return;
|
|
3211
3317
|
}
|
|
3318
|
+
#onMatcherIsNotSupported(matcherNameText, assertion, onDiagnostics) {
|
|
3319
|
+
const text = ExpectDiagnosticText.matcherIsNotSupported(matcherNameText);
|
|
3320
|
+
const origin = DiagnosticOrigin.fromNode(assertion.matcherName);
|
|
3321
|
+
onDiagnostics(Diagnostic.error(text, origin));
|
|
3322
|
+
}
|
|
3212
3323
|
#onSourceArgumentOrTypeArgumentMustBeProvided(assertion, onDiagnostics) {
|
|
3213
3324
|
const text = ExpectDiagnosticText.argumentOrTypeArgumentMustBeProvided("source", "Source");
|
|
3214
3325
|
const origin = DiagnosticOrigin.fromNode(assertion.node.expression);
|
|
@@ -3275,18 +3386,15 @@ class TestTreeWorker {
|
|
|
3275
3386
|
break;
|
|
3276
3387
|
}
|
|
3277
3388
|
switch (member.brand) {
|
|
3278
|
-
case "describe":
|
|
3389
|
+
case "describe":
|
|
3279
3390
|
this.#visitDescribe(member, runMode, parentResult);
|
|
3280
3391
|
break;
|
|
3281
|
-
|
|
3282
|
-
case "test": {
|
|
3392
|
+
case "test":
|
|
3283
3393
|
this.#visitTest(member, runMode, parentResult);
|
|
3284
3394
|
break;
|
|
3285
|
-
|
|
3286
|
-
case "expect": {
|
|
3395
|
+
case "expect":
|
|
3287
3396
|
this.#visitAssertion(member, runMode, parentResult);
|
|
3288
3397
|
break;
|
|
3289
|
-
}
|
|
3290
3398
|
}
|
|
3291
3399
|
}
|
|
3292
3400
|
}
|
|
@@ -3510,7 +3618,7 @@ class TSTyche {
|
|
|
3510
3618
|
#runner;
|
|
3511
3619
|
#selectService;
|
|
3512
3620
|
#storeService;
|
|
3513
|
-
static version = "3.0.0-beta.
|
|
3621
|
+
static version = "3.0.0-beta.3";
|
|
3514
3622
|
constructor(resolvedConfig, outputService, selectService, storeService) {
|
|
3515
3623
|
this.#resolvedConfig = resolvedConfig;
|
|
3516
3624
|
this.#outputService = outputService;
|
|
@@ -4052,7 +4160,7 @@ class Cli {
|
|
|
4052
4160
|
}
|
|
4053
4161
|
const selectService = new SelectService(resolvedConfig);
|
|
4054
4162
|
let testFiles = [];
|
|
4055
|
-
if (resolvedConfig.testFileMatch.length
|
|
4163
|
+
if (resolvedConfig.testFileMatch.length > 0) {
|
|
4056
4164
|
testFiles = await selectService.selectFiles();
|
|
4057
4165
|
if (testFiles.length === 0) {
|
|
4058
4166
|
if (commandLineArguments.includes("--watch")) {
|
|
@@ -4103,4 +4211,4 @@ class Cli {
|
|
|
4103
4211
|
}
|
|
4104
4212
|
}
|
|
4105
4213
|
|
|
4106
|
-
export { Assertion, CancellationHandler, CancellationReason, CancellationToken, Cli, CollectService, Color, ConfigDiagnosticText, ConfigService, DescribeResult, Diagnostic, DiagnosticCategory, DiagnosticOrigin, EventEmitter, ExitCodeHandler, ExpectResult, ExpectService, FileWatcher, InputService, Line, OptionBrand, OptionDefinitionsMap, OptionGroup, OutputService, Path, ProjectResult, ProjectService, Result, ResultCount, ResultHandler, ResultStatus, ResultTiming, RunReporter, Runner, Scribbler, SelectDiagnosticText, SelectService, SetupReporter, StoreService, SummaryReporter, TSTyche, TargetResult, Task, TaskResult, TestMember, TestMemberBrand, TestMemberFlags, TestResult, TestTree, Text, Version, WatchReporter, WatchService, Watcher, addsPackageText, defaultOptions, describeNameText, diagnosticText, environmentOptions, fileViewText, formattedText, helpText, summaryText, taskStatusText, testNameText, usesCompilerText, waitingForFileChangesText, watchUsageText };
|
|
4214
|
+
export { Assertion, CancellationHandler, CancellationReason, CancellationToken, Cli, CollectService, Color, ConfigDiagnosticText, ConfigService, DescribeResult, Diagnostic, DiagnosticCategory, DiagnosticOrigin, EventEmitter, ExitCodeHandler, ExpectResult, ExpectService, FileWatcher, InputService, Line, OptionBrand, OptionDefinitionsMap, OptionGroup, OutputService, Path, ProjectResult, ProjectService, Result, ResultCount, ResultHandler, ResultStatus, ResultTiming, RunReporter, Runner, Scribbler, SelectDiagnosticText, SelectService, SetupReporter, SourceFile, StoreService, SummaryReporter, TSTyche, TargetResult, Task, TaskResult, TestMember, TestMemberBrand, TestMemberFlags, TestResult, TestTree, Text, Version, WatchReporter, WatchService, Watcher, addsPackageText, defaultOptions, describeNameText, diagnosticText, environmentOptions, fileViewText, formattedText, helpText, summaryText, taskStatusText, testNameText, usesCompilerText, waitingForFileChangesText, watchUsageText };
|