tstyche 4.0.0-rc.0 → 4.0.0-rc.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/tstyche.d.ts +134 -102
- package/build/tstyche.js +323 -191
- package/package.json +1 -1
package/build/tstyche.d.ts
CHANGED
|
@@ -20,60 +20,6 @@ declare class Cli {
|
|
|
20
20
|
run(commandLine: Array<string>, cancellationToken?: CancellationToken): Promise<void>;
|
|
21
21
|
}
|
|
22
22
|
|
|
23
|
-
declare enum TestTreeNodeBrand {
|
|
24
|
-
Describe = "describe",
|
|
25
|
-
Test = "test",
|
|
26
|
-
Expect = "expect",
|
|
27
|
-
When = "when"
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
declare enum TestTreeNodeFlags {
|
|
31
|
-
None = 0,
|
|
32
|
-
Fail = 1,
|
|
33
|
-
Only = 2,
|
|
34
|
-
Skip = 4,
|
|
35
|
-
Todo = 8
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
declare class WhenNode extends TestTreeNode {
|
|
39
|
-
actionNode: ts.CallExpression;
|
|
40
|
-
actionNameNode: ts.PropertyAccessExpression;
|
|
41
|
-
abilityDiagnostics: Set<ts.Diagnostic> | undefined;
|
|
42
|
-
target: ts.NodeArray<ts.Expression> | ts.NodeArray<ts.TypeNode>;
|
|
43
|
-
constructor(compiler: typeof ts, brand: TestTreeNodeBrand, node: ts.CallExpression, parent: TestTree | TestTreeNode, flags: TestTreeNodeFlags, actionNode: ts.CallExpression, actionNameNode: ts.PropertyAccessExpression);
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
declare class TestTreeNode {
|
|
47
|
-
brand: TestTreeNodeBrand;
|
|
48
|
-
children: Array<TestTreeNode | AssertionNode | WhenNode>;
|
|
49
|
-
diagnostics: Set<ts.Diagnostic>;
|
|
50
|
-
flags: TestTreeNodeFlags;
|
|
51
|
-
name: string;
|
|
52
|
-
node: ts.CallExpression;
|
|
53
|
-
parent: TestTree | TestTreeNode;
|
|
54
|
-
constructor(compiler: typeof ts, brand: TestTreeNodeBrand, node: ts.CallExpression, parent: TestTree | TestTreeNode, flags: TestTreeNodeFlags);
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
declare class TestTree {
|
|
58
|
-
children: Array<TestTreeNode | AssertionNode | WhenNode>;
|
|
59
|
-
diagnostics: Set<ts.Diagnostic>;
|
|
60
|
-
hasOnly: boolean;
|
|
61
|
-
sourceFile: ts.SourceFile;
|
|
62
|
-
constructor(diagnostics: Set<ts.Diagnostic>, sourceFile: ts.SourceFile);
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
declare class AssertionNode extends TestTreeNode {
|
|
66
|
-
abilityDiagnostics: Set<ts.Diagnostic> | undefined;
|
|
67
|
-
isNot: boolean;
|
|
68
|
-
matcherNode: ts.CallExpression | ts.Decorator;
|
|
69
|
-
matcherNameNode: ts.PropertyAccessExpression;
|
|
70
|
-
modifierNode: ts.PropertyAccessExpression;
|
|
71
|
-
notNode: ts.PropertyAccessExpression | undefined;
|
|
72
|
-
source: ts.NodeArray<ts.Expression> | ts.NodeArray<ts.TypeNode>;
|
|
73
|
-
target: ts.NodeArray<ts.Expression> | ts.NodeArray<ts.TypeNode> | undefined;
|
|
74
|
-
constructor(compiler: typeof ts, brand: TestTreeNodeBrand, node: ts.CallExpression, parent: TestTree | TestTreeNode, flags: TestTreeNodeFlags, matcherNode: ts.CallExpression | ts.Decorator, matcherNameNode: ts.PropertyAccessExpression, modifierNode: ts.PropertyAccessExpression, notNode?: ts.PropertyAccessExpression);
|
|
75
|
-
}
|
|
76
|
-
|
|
77
23
|
declare enum OptionBrand {
|
|
78
24
|
String = "string",
|
|
79
25
|
Number = "number",
|
|
@@ -100,52 +46,6 @@ declare class ConfigDiagnosticText {
|
|
|
100
46
|
static watchCannotBeEnabled(): string;
|
|
101
47
|
}
|
|
102
48
|
|
|
103
|
-
/**
|
|
104
|
-
* Options loaded from the configuration file.
|
|
105
|
-
*/
|
|
106
|
-
interface ConfigFileOptions {
|
|
107
|
-
/**
|
|
108
|
-
* Enable type error reporting for source files.
|
|
109
|
-
*/
|
|
110
|
-
checkSourceFiles?: boolean;
|
|
111
|
-
/**
|
|
112
|
-
* Stop running tests after the first failed assertion.
|
|
113
|
-
*/
|
|
114
|
-
failFast?: boolean;
|
|
115
|
-
/**
|
|
116
|
-
* The list of plugins to use.
|
|
117
|
-
*/
|
|
118
|
-
plugins?: Array<string>;
|
|
119
|
-
/**
|
|
120
|
-
* Reject the 'any' type passed as an argument to the 'expect()' function or a matcher.
|
|
121
|
-
*/
|
|
122
|
-
rejectAnyType?: boolean;
|
|
123
|
-
/**
|
|
124
|
-
* Reject the 'never' type passed as an argument to the 'expect()' function or a matcher.
|
|
125
|
-
*/
|
|
126
|
-
rejectNeverType?: boolean;
|
|
127
|
-
/**
|
|
128
|
-
* The list of reporters to use.
|
|
129
|
-
*/
|
|
130
|
-
reporters?: Array<string>;
|
|
131
|
-
/**
|
|
132
|
-
* The path to a directory containing files of a test project.
|
|
133
|
-
*/
|
|
134
|
-
rootPath?: string;
|
|
135
|
-
/**
|
|
136
|
-
* The list of TypeScript versions to be tested on.
|
|
137
|
-
*/
|
|
138
|
-
target?: Array<string>;
|
|
139
|
-
/**
|
|
140
|
-
* The list of glob patterns matching the test files.
|
|
141
|
-
*/
|
|
142
|
-
testFileMatch?: Array<string>;
|
|
143
|
-
/**
|
|
144
|
-
* The look up strategy to be used to find the TSConfig file.
|
|
145
|
-
*/
|
|
146
|
-
tsconfig?: string;
|
|
147
|
-
}
|
|
148
|
-
|
|
149
49
|
/**
|
|
150
50
|
* Options passed through the command line.
|
|
151
51
|
*/
|
|
@@ -220,6 +120,58 @@ interface CommandLineOptions {
|
|
|
220
120
|
watch?: boolean;
|
|
221
121
|
}
|
|
222
122
|
|
|
123
|
+
/**
|
|
124
|
+
* Options loaded from the configuration file.
|
|
125
|
+
*/
|
|
126
|
+
interface ConfigFileOptions {
|
|
127
|
+
/**
|
|
128
|
+
* Enable type error reporting for source files.
|
|
129
|
+
*/
|
|
130
|
+
checkSourceFiles?: boolean;
|
|
131
|
+
/**
|
|
132
|
+
* Stop running tests after the first failed assertion.
|
|
133
|
+
*/
|
|
134
|
+
failFast?: boolean;
|
|
135
|
+
/**
|
|
136
|
+
* The list of plugins to use.
|
|
137
|
+
*/
|
|
138
|
+
plugins?: Array<string>;
|
|
139
|
+
/**
|
|
140
|
+
* Reject the 'any' type passed as an argument to the 'expect()' function or a matcher.
|
|
141
|
+
*/
|
|
142
|
+
rejectAnyType?: boolean;
|
|
143
|
+
/**
|
|
144
|
+
* Reject the 'never' type passed as an argument to the 'expect()' function or a matcher.
|
|
145
|
+
*/
|
|
146
|
+
rejectNeverType?: boolean;
|
|
147
|
+
/**
|
|
148
|
+
* The list of reporters to use.
|
|
149
|
+
*/
|
|
150
|
+
reporters?: Array<string>;
|
|
151
|
+
/**
|
|
152
|
+
* The path to a directory containing files of a test project.
|
|
153
|
+
*/
|
|
154
|
+
rootPath?: string;
|
|
155
|
+
/**
|
|
156
|
+
* The list of TypeScript versions to be tested on.
|
|
157
|
+
*/
|
|
158
|
+
target?: Array<string>;
|
|
159
|
+
/**
|
|
160
|
+
* The list of glob patterns matching the test files.
|
|
161
|
+
*/
|
|
162
|
+
testFileMatch?: Array<string>;
|
|
163
|
+
/**
|
|
164
|
+
* The look up strategy to be used to find the TSConfig file.
|
|
165
|
+
*/
|
|
166
|
+
tsconfig?: string;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
interface InlineConfig {
|
|
170
|
+
if?: {
|
|
171
|
+
target?: Array<string>;
|
|
172
|
+
};
|
|
173
|
+
template?: boolean;
|
|
174
|
+
}
|
|
223
175
|
interface ResolvedConfig extends Omit<CommandLineOptions, "config" | keyof ConfigFileOptions>, Required<ConfigFileOptions> {
|
|
224
176
|
/**
|
|
225
177
|
* The path to a TSTyche configuration file.
|
|
@@ -230,6 +182,7 @@ interface ResolvedConfig extends Omit<CommandLineOptions, "config" | keyof Confi
|
|
|
230
182
|
*/
|
|
231
183
|
pathMatch: Array<string>;
|
|
232
184
|
}
|
|
185
|
+
|
|
233
186
|
declare class Config {
|
|
234
187
|
#private;
|
|
235
188
|
static parseCommandLine(commandLine: Array<string>): Promise<{
|
|
@@ -249,6 +202,25 @@ declare class Config {
|
|
|
249
202
|
static resolveConfigFilePath(filePath?: string): string;
|
|
250
203
|
}
|
|
251
204
|
|
|
205
|
+
interface TextRange {
|
|
206
|
+
start: number;
|
|
207
|
+
end: number;
|
|
208
|
+
text: string;
|
|
209
|
+
}
|
|
210
|
+
interface DirectiveRange {
|
|
211
|
+
namespace: TextRange;
|
|
212
|
+
directive?: TextRange;
|
|
213
|
+
argument?: TextRange;
|
|
214
|
+
}
|
|
215
|
+
type DirectiveRanges = Array<DirectiveRange> & {
|
|
216
|
+
sourceFile: ts.SourceFile;
|
|
217
|
+
};
|
|
218
|
+
declare class Directive {
|
|
219
|
+
#private;
|
|
220
|
+
static getDirectiveRanges(compiler: typeof ts, sourceFile: ts.SourceFile, position?: number): DirectiveRanges | undefined;
|
|
221
|
+
static getInlineConfig(ranges: DirectiveRanges | undefined): Promise<InlineConfig | undefined>;
|
|
222
|
+
}
|
|
223
|
+
|
|
252
224
|
declare enum DiagnosticCategory {
|
|
253
225
|
Error = "error",
|
|
254
226
|
Warning = "warning"
|
|
@@ -304,6 +276,7 @@ type DiagnosticsHandler<T extends Diagnostic | Array<Diagnostic> = Diagnostic> =
|
|
|
304
276
|
declare enum OptionGroup {
|
|
305
277
|
CommandLine = 2,
|
|
306
278
|
ConfigFile = 4,
|
|
279
|
+
InlineConditions = 8,
|
|
307
280
|
ResolvedConfig = 6
|
|
308
281
|
}
|
|
309
282
|
|
|
@@ -334,6 +307,62 @@ declare class Options {
|
|
|
334
307
|
|
|
335
308
|
declare const defaultOptions: Required<ConfigFileOptions>;
|
|
336
309
|
|
|
310
|
+
declare enum TestTreeNodeBrand {
|
|
311
|
+
Describe = "describe",
|
|
312
|
+
Test = "test",
|
|
313
|
+
Expect = "expect",
|
|
314
|
+
When = "when"
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
declare enum TestTreeNodeFlags {
|
|
318
|
+
None = 0,
|
|
319
|
+
Fail = 1,
|
|
320
|
+
Only = 2,
|
|
321
|
+
Skip = 4,
|
|
322
|
+
Todo = 8
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
declare class WhenNode extends TestTreeNode {
|
|
326
|
+
actionNode: ts.CallExpression;
|
|
327
|
+
actionNameNode: ts.PropertyAccessExpression;
|
|
328
|
+
abilityDiagnostics: Set<ts.Diagnostic> | undefined;
|
|
329
|
+
target: ts.NodeArray<ts.Expression> | ts.NodeArray<ts.TypeNode>;
|
|
330
|
+
constructor(compiler: typeof ts, brand: TestTreeNodeBrand, node: ts.CallExpression, parent: TestTree | TestTreeNode, flags: TestTreeNodeFlags, actionNode: ts.CallExpression, actionNameNode: ts.PropertyAccessExpression);
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
declare class TestTreeNode {
|
|
334
|
+
brand: TestTreeNodeBrand;
|
|
335
|
+
children: Array<TestTreeNode | AssertionNode | WhenNode>;
|
|
336
|
+
diagnostics: Set<ts.Diagnostic>;
|
|
337
|
+
flags: TestTreeNodeFlags;
|
|
338
|
+
name: string;
|
|
339
|
+
node: ts.CallExpression;
|
|
340
|
+
parent: TestTree | TestTreeNode;
|
|
341
|
+
constructor(compiler: typeof ts, brand: TestTreeNodeBrand, node: ts.CallExpression, parent: TestTree | TestTreeNode, flags: TestTreeNodeFlags);
|
|
342
|
+
getDirectiveRanges(compiler: typeof ts): DirectiveRanges | undefined;
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
declare class TestTree {
|
|
346
|
+
children: Array<TestTreeNode | AssertionNode | WhenNode>;
|
|
347
|
+
diagnostics: Set<ts.Diagnostic>;
|
|
348
|
+
hasOnly: boolean;
|
|
349
|
+
sourceFile: ts.SourceFile;
|
|
350
|
+
constructor(diagnostics: Set<ts.Diagnostic>, sourceFile: ts.SourceFile);
|
|
351
|
+
getDirectiveRanges(compiler: typeof ts): DirectiveRanges | undefined;
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
declare class AssertionNode extends TestTreeNode {
|
|
355
|
+
abilityDiagnostics: Set<ts.Diagnostic> | undefined;
|
|
356
|
+
isNot: boolean;
|
|
357
|
+
matcherNode: ts.CallExpression | ts.Decorator;
|
|
358
|
+
matcherNameNode: ts.PropertyAccessExpression;
|
|
359
|
+
modifierNode: ts.PropertyAccessExpression;
|
|
360
|
+
notNode: ts.PropertyAccessExpression | undefined;
|
|
361
|
+
source: ts.NodeArray<ts.Expression> | ts.NodeArray<ts.TypeNode>;
|
|
362
|
+
target: ts.NodeArray<ts.Expression> | ts.NodeArray<ts.TypeNode> | undefined;
|
|
363
|
+
constructor(compiler: typeof ts, brand: TestTreeNodeBrand, node: ts.CallExpression, parent: TestTree | TestTreeNode, flags: TestTreeNodeFlags, matcherNode: ts.CallExpression | ts.Decorator, matcherNameNode: ts.PropertyAccessExpression, modifierNode: ts.PropertyAccessExpression, notNode: ts.PropertyAccessExpression | undefined);
|
|
364
|
+
}
|
|
365
|
+
|
|
337
366
|
declare class ProjectService {
|
|
338
367
|
#private;
|
|
339
368
|
constructor(compiler: typeof ts, resolvedConfig: ResolvedConfig);
|
|
@@ -546,6 +575,8 @@ type Event = ["config:error", {
|
|
|
546
575
|
result: TaskResult;
|
|
547
576
|
}] | ["task:end", {
|
|
548
577
|
result: TaskResult;
|
|
578
|
+
}] | ["directive:error", {
|
|
579
|
+
diagnostics: Array<Diagnostic>;
|
|
549
580
|
}] | ["collect:start", {
|
|
550
581
|
tree: TestTree;
|
|
551
582
|
}] | ["collect:error", {
|
|
@@ -855,6 +886,7 @@ declare class Store {
|
|
|
855
886
|
declare class Version {
|
|
856
887
|
#private;
|
|
857
888
|
static isGreaterThan(source: string, target: string): boolean;
|
|
889
|
+
static isIncluded(source: string, range: Array<string>): boolean;
|
|
858
890
|
static isSatisfiedWith(source: string, target: string): boolean;
|
|
859
891
|
}
|
|
860
892
|
|
|
@@ -886,5 +918,5 @@ declare class WhenService {
|
|
|
886
918
|
action(when: WhenNode): void;
|
|
887
919
|
}
|
|
888
920
|
|
|
889
|
-
export { AssertionNode, BaseReporter, CancellationHandler, CancellationReason, CancellationToken, Cli, CollectService, Color, Config, ConfigDiagnosticText, DescribeResult, Diagnostic, DiagnosticCategory, DiagnosticOrigin, EventEmitter, ExitCodeHandler, ExpectResult, ExpectService, FileWatcher, InputService, Line, ListReporter, OptionBrand, OptionGroup, Options, OutputService, Path, PluginService, ProjectResult, ProjectService, Reject, Result, ResultCount, ResultHandler, ResultStatus, ResultTiming, Runner, Scribbler, ScribblerJsx, Select, SelectDiagnosticText, SetupReporter, SourceFile, Store, SummaryReporter, TargetResult, Task, TaskResult, TestResult, TestTree, TestTreeNode, TestTreeNodeBrand, TestTreeNodeFlags, Text, Version, WatchReporter, WatchService, Watcher, WhenNode, WhenService, addsPackageText, argumentIsProvided, argumentOrTypeArgumentIsProvided, defaultOptions, describeNameText, diagnosticBelongsToNode, diagnosticText, environmentOptions, fileViewText, formattedText, getDiagnosticMessageText, getTextSpanEnd, helpText, isDiagnosticWithLocation, nodeBelongsToArgumentList, summaryText, taskStatusText, testNameText, usesCompilerText, waitingForFileChangesText, watchUsageText };
|
|
890
|
-
export type { CodeFrameOptions, CommandLineOptions, ConfigFileOptions, DiagnosticsHandler, EnvironmentOptions, Event, EventHandler, FileWatchHandler, InputHandler, ItemDefinition, MatchResult, OptionDefinition, Plugin, Reporter, ReporterEvent, ResolvedConfig, ScribblerOptions, SelectHookContext, TargetResultStatus, TaskResultStatus, TypeChecker, WatchHandler, WatcherOptions };
|
|
921
|
+
export { AssertionNode, BaseReporter, CancellationHandler, CancellationReason, CancellationToken, Cli, CollectService, Color, Config, ConfigDiagnosticText, DescribeResult, Diagnostic, DiagnosticCategory, DiagnosticOrigin, Directive, EventEmitter, ExitCodeHandler, ExpectResult, ExpectService, FileWatcher, InputService, Line, ListReporter, OptionBrand, OptionGroup, Options, OutputService, Path, PluginService, ProjectResult, ProjectService, Reject, Result, ResultCount, ResultHandler, ResultStatus, ResultTiming, Runner, Scribbler, ScribblerJsx, Select, SelectDiagnosticText, SetupReporter, SourceFile, Store, SummaryReporter, TargetResult, Task, TaskResult, TestResult, TestTree, TestTreeNode, TestTreeNodeBrand, TestTreeNodeFlags, Text, Version, WatchReporter, WatchService, Watcher, WhenNode, WhenService, addsPackageText, argumentIsProvided, argumentOrTypeArgumentIsProvided, defaultOptions, describeNameText, diagnosticBelongsToNode, diagnosticText, environmentOptions, fileViewText, formattedText, getDiagnosticMessageText, getTextSpanEnd, helpText, isDiagnosticWithLocation, nodeBelongsToArgumentList, summaryText, taskStatusText, testNameText, usesCompilerText, waitingForFileChangesText, watchUsageText };
|
|
922
|
+
export type { CodeFrameOptions, CommandLineOptions, ConfigFileOptions, DiagnosticsHandler, DirectiveRange, DirectiveRanges, EnvironmentOptions, Event, EventHandler, FileWatchHandler, InlineConfig, InputHandler, ItemDefinition, MatchResult, OptionDefinition, Plugin, Reporter, ReporterEvent, ResolvedConfig, ScribblerOptions, SelectHookContext, TargetResultStatus, TaskResultStatus, TypeChecker, WatchHandler, WatcherOptions };
|
package/build/tstyche.js
CHANGED
|
@@ -292,6 +292,7 @@ var OptionGroup;
|
|
|
292
292
|
(function (OptionGroup) {
|
|
293
293
|
OptionGroup[OptionGroup["CommandLine"] = 2] = "CommandLine";
|
|
294
294
|
OptionGroup[OptionGroup["ConfigFile"] = 4] = "ConfigFile";
|
|
295
|
+
OptionGroup[OptionGroup["InlineConditions"] = 8] = "InlineConditions";
|
|
295
296
|
OptionGroup[OptionGroup["ResolvedConfig"] = 6] = "ResolvedConfig";
|
|
296
297
|
})(OptionGroup || (OptionGroup = {}));
|
|
297
298
|
|
|
@@ -376,6 +377,9 @@ class Version {
|
|
|
376
377
|
static isGreaterThan(source, target) {
|
|
377
378
|
return !(source === target) && Version.#satisfies(source, target);
|
|
378
379
|
}
|
|
380
|
+
static isIncluded(source, range) {
|
|
381
|
+
return range.some((target) => source.startsWith(target));
|
|
382
|
+
}
|
|
379
383
|
static isSatisfiedWith(source, target) {
|
|
380
384
|
return source === target || Version.#satisfies(source, target);
|
|
381
385
|
}
|
|
@@ -1004,7 +1008,7 @@ class Options {
|
|
|
1004
1008
|
{
|
|
1005
1009
|
brand: OptionBrand.List,
|
|
1006
1010
|
description: "The list of TypeScript versions to be tested on.",
|
|
1007
|
-
group: OptionGroup.CommandLine | OptionGroup.ConfigFile,
|
|
1011
|
+
group: OptionGroup.CommandLine | OptionGroup.ConfigFile | OptionGroup.InlineConditions,
|
|
1008
1012
|
items: {
|
|
1009
1013
|
brand: OptionBrand.String,
|
|
1010
1014
|
name: "target",
|
|
@@ -1239,146 +1243,18 @@ class CommandLineParser {
|
|
|
1239
1243
|
}
|
|
1240
1244
|
}
|
|
1241
1245
|
|
|
1242
|
-
class
|
|
1243
|
-
origin;
|
|
1244
|
-
text;
|
|
1245
|
-
constructor(text, origin) {
|
|
1246
|
-
this.origin = origin;
|
|
1247
|
-
this.text = text;
|
|
1248
|
-
}
|
|
1249
|
-
getValue(options) {
|
|
1250
|
-
if (this.text == null) {
|
|
1251
|
-
return undefined;
|
|
1252
|
-
}
|
|
1253
|
-
if (/^['"]/.test(this.text)) {
|
|
1254
|
-
return this.text.slice(1, -1);
|
|
1255
|
-
}
|
|
1256
|
-
if (options?.expectsIdentifier) {
|
|
1257
|
-
return this.text;
|
|
1258
|
-
}
|
|
1259
|
-
if (this.text === "true") {
|
|
1260
|
-
return true;
|
|
1261
|
-
}
|
|
1262
|
-
if (this.text === "false") {
|
|
1263
|
-
return false;
|
|
1264
|
-
}
|
|
1265
|
-
if (/^\d/.test(this.text)) {
|
|
1266
|
-
return Number.parseFloat(this.text);
|
|
1267
|
-
}
|
|
1268
|
-
return undefined;
|
|
1269
|
-
}
|
|
1270
|
-
}
|
|
1271
|
-
|
|
1272
|
-
class JsonScanner {
|
|
1273
|
-
#currentPosition = 0;
|
|
1274
|
-
#previousPosition = 0;
|
|
1275
|
-
#sourceFile;
|
|
1276
|
-
constructor(sourceFile) {
|
|
1277
|
-
this.#sourceFile = sourceFile;
|
|
1278
|
-
}
|
|
1279
|
-
#getOrigin() {
|
|
1280
|
-
return new DiagnosticOrigin(this.#previousPosition, this.#currentPosition, this.#sourceFile);
|
|
1281
|
-
}
|
|
1282
|
-
isRead() {
|
|
1283
|
-
return !(this.#currentPosition < this.#sourceFile.text.length);
|
|
1284
|
-
}
|
|
1285
|
-
#peekCharacter() {
|
|
1286
|
-
return this.#sourceFile.text.charAt(this.#currentPosition);
|
|
1287
|
-
}
|
|
1288
|
-
#peekNextCharacter() {
|
|
1289
|
-
return this.#sourceFile.text.charAt(this.#currentPosition + 1);
|
|
1290
|
-
}
|
|
1291
|
-
peekToken(token) {
|
|
1292
|
-
this.#skipTrivia();
|
|
1293
|
-
return this.#peekCharacter() === token;
|
|
1294
|
-
}
|
|
1295
|
-
read() {
|
|
1296
|
-
this.#skipTrivia();
|
|
1297
|
-
this.#previousPosition = this.#currentPosition;
|
|
1298
|
-
if (/[\s,:\]}]/.test(this.#peekCharacter())) {
|
|
1299
|
-
return new JsonNode(undefined, this.#getOrigin());
|
|
1300
|
-
}
|
|
1301
|
-
let text = "";
|
|
1302
|
-
let closingTokenText = "";
|
|
1303
|
-
if (/[[{'"]/.test(this.#peekCharacter())) {
|
|
1304
|
-
text += this.#readCharacter();
|
|
1305
|
-
switch (text) {
|
|
1306
|
-
case "[":
|
|
1307
|
-
closingTokenText = "]";
|
|
1308
|
-
break;
|
|
1309
|
-
case "{":
|
|
1310
|
-
closingTokenText = "}";
|
|
1311
|
-
break;
|
|
1312
|
-
default:
|
|
1313
|
-
closingTokenText = text;
|
|
1314
|
-
}
|
|
1315
|
-
}
|
|
1316
|
-
while (!this.isRead()) {
|
|
1317
|
-
text += this.#readCharacter();
|
|
1318
|
-
if (text.slice(-1) === closingTokenText || (!closingTokenText && /[\s,:\]}]/.test(this.#peekCharacter()))) {
|
|
1319
|
-
break;
|
|
1320
|
-
}
|
|
1321
|
-
}
|
|
1322
|
-
return new JsonNode(text, this.#getOrigin());
|
|
1323
|
-
}
|
|
1324
|
-
#readCharacter() {
|
|
1325
|
-
return this.#sourceFile.text.charAt(this.#currentPosition++);
|
|
1326
|
-
}
|
|
1327
|
-
readToken(token) {
|
|
1328
|
-
this.#skipTrivia();
|
|
1329
|
-
this.#previousPosition = this.#currentPosition;
|
|
1330
|
-
if (this.#peekCharacter() === token) {
|
|
1331
|
-
this.#currentPosition++;
|
|
1332
|
-
return new JsonNode(token, this.#getOrigin());
|
|
1333
|
-
}
|
|
1334
|
-
return new JsonNode(undefined, this.#getOrigin());
|
|
1335
|
-
}
|
|
1336
|
-
#skipTrivia() {
|
|
1337
|
-
while (!this.isRead()) {
|
|
1338
|
-
if (/\s/.test(this.#peekCharacter())) {
|
|
1339
|
-
this.#currentPosition++;
|
|
1340
|
-
continue;
|
|
1341
|
-
}
|
|
1342
|
-
if (this.#peekCharacter() === "/") {
|
|
1343
|
-
if (this.#peekNextCharacter() === "/") {
|
|
1344
|
-
this.#currentPosition += 2;
|
|
1345
|
-
while (!this.isRead()) {
|
|
1346
|
-
if (this.#readCharacter() === "\n") {
|
|
1347
|
-
break;
|
|
1348
|
-
}
|
|
1349
|
-
}
|
|
1350
|
-
continue;
|
|
1351
|
-
}
|
|
1352
|
-
if (this.#peekNextCharacter() === "*") {
|
|
1353
|
-
this.#currentPosition += 2;
|
|
1354
|
-
while (!this.isRead()) {
|
|
1355
|
-
if (this.#peekCharacter() === "*" && this.#peekNextCharacter() === "/") {
|
|
1356
|
-
this.#currentPosition += 2;
|
|
1357
|
-
break;
|
|
1358
|
-
}
|
|
1359
|
-
this.#currentPosition++;
|
|
1360
|
-
}
|
|
1361
|
-
continue;
|
|
1362
|
-
}
|
|
1363
|
-
}
|
|
1364
|
-
break;
|
|
1365
|
-
}
|
|
1366
|
-
this.#previousPosition = this.#currentPosition;
|
|
1367
|
-
}
|
|
1368
|
-
}
|
|
1369
|
-
|
|
1370
|
-
class ConfigFileParser {
|
|
1246
|
+
class ConfigParser {
|
|
1371
1247
|
#configFileOptions;
|
|
1372
1248
|
#jsonScanner;
|
|
1373
1249
|
#onDiagnostics;
|
|
1374
1250
|
#options;
|
|
1375
1251
|
#sourceFile;
|
|
1376
|
-
constructor(
|
|
1377
|
-
this.#configFileOptions =
|
|
1378
|
-
this.#
|
|
1252
|
+
constructor(configOptions, optionGroup, sourceFile, jsonScanner, onDiagnostics) {
|
|
1253
|
+
this.#configFileOptions = configOptions;
|
|
1254
|
+
this.#jsonScanner = jsonScanner;
|
|
1379
1255
|
this.#onDiagnostics = onDiagnostics;
|
|
1380
|
-
this.#
|
|
1381
|
-
this.#
|
|
1256
|
+
this.#sourceFile = sourceFile;
|
|
1257
|
+
this.#options = Options.for(optionGroup);
|
|
1382
1258
|
}
|
|
1383
1259
|
#onRequiresValue(optionDefinition, jsonNode, isListItem) {
|
|
1384
1260
|
const text = isListItem
|
|
@@ -1471,9 +1347,8 @@ class ConfigFileParser {
|
|
|
1471
1347
|
if (!optionDefinition) {
|
|
1472
1348
|
const text = ConfigDiagnosticText.unknownOption(optionName);
|
|
1473
1349
|
this.#onDiagnostics(Diagnostic.error(text, optionNameNode.origin));
|
|
1474
|
-
|
|
1475
|
-
|
|
1476
|
-
}
|
|
1350
|
+
this.#jsonScanner.readToken(":");
|
|
1351
|
+
this.#jsonScanner.read();
|
|
1477
1352
|
const commaToken = this.#jsonScanner.readToken(",");
|
|
1478
1353
|
if (!commaToken.text) {
|
|
1479
1354
|
break;
|
|
@@ -1507,6 +1382,138 @@ class ConfigFileParser {
|
|
|
1507
1382
|
}
|
|
1508
1383
|
}
|
|
1509
1384
|
|
|
1385
|
+
class JsonNode {
|
|
1386
|
+
origin;
|
|
1387
|
+
text;
|
|
1388
|
+
constructor(text, origin) {
|
|
1389
|
+
this.origin = origin;
|
|
1390
|
+
this.text = text;
|
|
1391
|
+
}
|
|
1392
|
+
getValue(options) {
|
|
1393
|
+
if (this.text == null) {
|
|
1394
|
+
return undefined;
|
|
1395
|
+
}
|
|
1396
|
+
if (/^['"]/.test(this.text)) {
|
|
1397
|
+
return this.text.slice(1, -1);
|
|
1398
|
+
}
|
|
1399
|
+
if (options?.expectsIdentifier) {
|
|
1400
|
+
return this.text;
|
|
1401
|
+
}
|
|
1402
|
+
if (this.text === "true") {
|
|
1403
|
+
return true;
|
|
1404
|
+
}
|
|
1405
|
+
if (this.text === "false") {
|
|
1406
|
+
return false;
|
|
1407
|
+
}
|
|
1408
|
+
if (/^\d/.test(this.text)) {
|
|
1409
|
+
return Number.parseFloat(this.text);
|
|
1410
|
+
}
|
|
1411
|
+
return undefined;
|
|
1412
|
+
}
|
|
1413
|
+
}
|
|
1414
|
+
|
|
1415
|
+
class JsonScanner {
|
|
1416
|
+
#end;
|
|
1417
|
+
#position;
|
|
1418
|
+
#previousPosition;
|
|
1419
|
+
#sourceFile;
|
|
1420
|
+
constructor(sourceFile, options) {
|
|
1421
|
+
this.#end = options?.end ?? sourceFile.text.length;
|
|
1422
|
+
this.#position = options?.start ?? 0;
|
|
1423
|
+
this.#previousPosition = options?.start ?? 0;
|
|
1424
|
+
this.#sourceFile = sourceFile;
|
|
1425
|
+
}
|
|
1426
|
+
#getOrigin() {
|
|
1427
|
+
return new DiagnosticOrigin(this.#previousPosition, this.#position, this.#sourceFile);
|
|
1428
|
+
}
|
|
1429
|
+
isRead() {
|
|
1430
|
+
return !(this.#position < this.#end);
|
|
1431
|
+
}
|
|
1432
|
+
#peekCharacter() {
|
|
1433
|
+
return this.#sourceFile.text.charAt(this.#position);
|
|
1434
|
+
}
|
|
1435
|
+
#peekNextCharacter() {
|
|
1436
|
+
return this.#sourceFile.text.charAt(this.#position + 1);
|
|
1437
|
+
}
|
|
1438
|
+
peekToken(token) {
|
|
1439
|
+
this.#skipTrivia();
|
|
1440
|
+
return this.#peekCharacter() === token;
|
|
1441
|
+
}
|
|
1442
|
+
read() {
|
|
1443
|
+
this.#skipTrivia();
|
|
1444
|
+
this.#previousPosition = this.#position;
|
|
1445
|
+
if (/[\s,:\]}]/.test(this.#peekCharacter())) {
|
|
1446
|
+
return new JsonNode(undefined, this.#getOrigin());
|
|
1447
|
+
}
|
|
1448
|
+
let text = "";
|
|
1449
|
+
let closingTokenText = "";
|
|
1450
|
+
if (/[[{'"]/.test(this.#peekCharacter())) {
|
|
1451
|
+
text += this.#readCharacter();
|
|
1452
|
+
switch (text) {
|
|
1453
|
+
case "[":
|
|
1454
|
+
closingTokenText = "]";
|
|
1455
|
+
break;
|
|
1456
|
+
case "{":
|
|
1457
|
+
closingTokenText = "}";
|
|
1458
|
+
break;
|
|
1459
|
+
default:
|
|
1460
|
+
closingTokenText = text;
|
|
1461
|
+
}
|
|
1462
|
+
}
|
|
1463
|
+
while (!this.isRead()) {
|
|
1464
|
+
text += this.#readCharacter();
|
|
1465
|
+
if (text.slice(-1) === closingTokenText || (!closingTokenText && /[\s,:\]}]/.test(this.#peekCharacter()))) {
|
|
1466
|
+
break;
|
|
1467
|
+
}
|
|
1468
|
+
}
|
|
1469
|
+
return new JsonNode(text, this.#getOrigin());
|
|
1470
|
+
}
|
|
1471
|
+
#readCharacter() {
|
|
1472
|
+
return this.#sourceFile.text.charAt(this.#position++);
|
|
1473
|
+
}
|
|
1474
|
+
readToken(token) {
|
|
1475
|
+
this.#skipTrivia();
|
|
1476
|
+
this.#previousPosition = this.#position;
|
|
1477
|
+
if (this.#peekCharacter() === token) {
|
|
1478
|
+
this.#position++;
|
|
1479
|
+
return new JsonNode(token, this.#getOrigin());
|
|
1480
|
+
}
|
|
1481
|
+
return new JsonNode(undefined, this.#getOrigin());
|
|
1482
|
+
}
|
|
1483
|
+
#skipTrivia() {
|
|
1484
|
+
while (!this.isRead()) {
|
|
1485
|
+
if (/\s/.test(this.#peekCharacter())) {
|
|
1486
|
+
this.#position++;
|
|
1487
|
+
continue;
|
|
1488
|
+
}
|
|
1489
|
+
if (this.#peekCharacter() === "/") {
|
|
1490
|
+
if (this.#peekNextCharacter() === "/") {
|
|
1491
|
+
this.#position += 2;
|
|
1492
|
+
while (!this.isRead()) {
|
|
1493
|
+
if (this.#readCharacter() === "\n") {
|
|
1494
|
+
break;
|
|
1495
|
+
}
|
|
1496
|
+
}
|
|
1497
|
+
continue;
|
|
1498
|
+
}
|
|
1499
|
+
if (this.#peekNextCharacter() === "*") {
|
|
1500
|
+
this.#position += 2;
|
|
1501
|
+
while (!this.isRead()) {
|
|
1502
|
+
if (this.#peekCharacter() === "*" && this.#peekNextCharacter() === "/") {
|
|
1503
|
+
this.#position += 2;
|
|
1504
|
+
break;
|
|
1505
|
+
}
|
|
1506
|
+
this.#position++;
|
|
1507
|
+
}
|
|
1508
|
+
continue;
|
|
1509
|
+
}
|
|
1510
|
+
}
|
|
1511
|
+
break;
|
|
1512
|
+
}
|
|
1513
|
+
this.#previousPosition = this.#position;
|
|
1514
|
+
}
|
|
1515
|
+
}
|
|
1516
|
+
|
|
1510
1517
|
const defaultOptions = {
|
|
1511
1518
|
checkSourceFiles: true,
|
|
1512
1519
|
failFast: false,
|
|
@@ -1544,7 +1551,7 @@ class Config {
|
|
|
1544
1551
|
encoding: "utf8",
|
|
1545
1552
|
});
|
|
1546
1553
|
const sourceFile = new SourceFile(configFilePath, configFileText);
|
|
1547
|
-
const configFileParser = new
|
|
1554
|
+
const configFileParser = new ConfigParser(configFileOptions, OptionGroup.ConfigFile, sourceFile, new JsonScanner(sourceFile), Config.#onDiagnostics);
|
|
1548
1555
|
await configFileParser.parse();
|
|
1549
1556
|
if (configFileOptions.target != null) {
|
|
1550
1557
|
configFileOptions.target = await Target.expand(configFileOptions.target);
|
|
@@ -1570,6 +1577,114 @@ class Config {
|
|
|
1570
1577
|
}
|
|
1571
1578
|
}
|
|
1572
1579
|
|
|
1580
|
+
class DirectiveDiagnosticText {
|
|
1581
|
+
static doesNotTakeArgument(directiveName) {
|
|
1582
|
+
return `Directive '${directiveName}' does not take an argument.`;
|
|
1583
|
+
}
|
|
1584
|
+
static isNotSupported(directive) {
|
|
1585
|
+
return `The '${directive}' directive is not supported.`;
|
|
1586
|
+
}
|
|
1587
|
+
static requiresArgument(directiveName) {
|
|
1588
|
+
return `Directive '${directiveName}' requires an argument.`;
|
|
1589
|
+
}
|
|
1590
|
+
}
|
|
1591
|
+
|
|
1592
|
+
class Directive {
|
|
1593
|
+
static #commentSeparatorRegex = /--+/;
|
|
1594
|
+
static #directiveRegex = /^(\/\/\s*@tstyche)(\s*|-)?(\S*)?(\s*)?(.*)?/i;
|
|
1595
|
+
static getDirectiveRanges(compiler, sourceFile, position = 0) {
|
|
1596
|
+
const comments = compiler.getLeadingCommentRanges(sourceFile.text, position);
|
|
1597
|
+
if (!comments || comments.length === 0) {
|
|
1598
|
+
return;
|
|
1599
|
+
}
|
|
1600
|
+
const ranges = Object.assign([], { sourceFile });
|
|
1601
|
+
for (const comment of comments) {
|
|
1602
|
+
if (comment.kind !== compiler.SyntaxKind.SingleLineCommentTrivia) {
|
|
1603
|
+
continue;
|
|
1604
|
+
}
|
|
1605
|
+
const range = Directive.#getRange(sourceFile, comment);
|
|
1606
|
+
if (range != null) {
|
|
1607
|
+
ranges.push(range);
|
|
1608
|
+
}
|
|
1609
|
+
}
|
|
1610
|
+
return ranges;
|
|
1611
|
+
}
|
|
1612
|
+
static async getInlineConfig(ranges) {
|
|
1613
|
+
if (!ranges) {
|
|
1614
|
+
return;
|
|
1615
|
+
}
|
|
1616
|
+
const inlineConfig = {};
|
|
1617
|
+
for (const range of ranges) {
|
|
1618
|
+
await Directive.#parse(inlineConfig, ranges.sourceFile, range);
|
|
1619
|
+
}
|
|
1620
|
+
return inlineConfig;
|
|
1621
|
+
}
|
|
1622
|
+
static #getRange(sourceFile, comment) {
|
|
1623
|
+
const [text] = sourceFile.text.substring(comment.pos, comment.end).split(Directive.#commentSeparatorRegex);
|
|
1624
|
+
const found = text?.match(Directive.#directiveRegex);
|
|
1625
|
+
const namespaceText = found?.[1];
|
|
1626
|
+
if (!namespaceText) {
|
|
1627
|
+
return;
|
|
1628
|
+
}
|
|
1629
|
+
const ranges = {
|
|
1630
|
+
namespace: { start: comment.pos, end: comment.pos + namespaceText.length, text: namespaceText },
|
|
1631
|
+
};
|
|
1632
|
+
const directiveSeparatorText = found?.[2];
|
|
1633
|
+
const directiveText = found?.[3];
|
|
1634
|
+
if (directiveText != null && directiveText.length > 0) {
|
|
1635
|
+
const start = ranges.namespace.end + (directiveSeparatorText?.length ?? 0);
|
|
1636
|
+
ranges.directive = { start, end: start + directiveText.length, text: directiveText };
|
|
1637
|
+
}
|
|
1638
|
+
const argumentSeparatorText = found?.[4];
|
|
1639
|
+
const argumentText = found?.[5]?.trimEnd();
|
|
1640
|
+
if (ranges.directive != null && argumentText != null && argumentText.length > 0) {
|
|
1641
|
+
const start = ranges.directive.end + (argumentSeparatorText?.length ?? 0);
|
|
1642
|
+
ranges.argument = { start, end: start + argumentText.length, text: argumentText };
|
|
1643
|
+
}
|
|
1644
|
+
return ranges;
|
|
1645
|
+
}
|
|
1646
|
+
static #onDiagnostics(diagnostic) {
|
|
1647
|
+
EventEmitter.dispatch(["directive:error", { diagnostics: [diagnostic] }]);
|
|
1648
|
+
}
|
|
1649
|
+
static async #parse(inlineConfig, sourceFile, ranges) {
|
|
1650
|
+
switch (ranges.directive?.text) {
|
|
1651
|
+
case "if":
|
|
1652
|
+
{
|
|
1653
|
+
if (!ranges.argument?.text) {
|
|
1654
|
+
const text = DirectiveDiagnosticText.requiresArgument(ranges.directive.text);
|
|
1655
|
+
const origin = new DiagnosticOrigin(ranges.directive.start, ranges.directive.end, sourceFile);
|
|
1656
|
+
Directive.#onDiagnostics(Diagnostic.error(text, origin));
|
|
1657
|
+
return;
|
|
1658
|
+
}
|
|
1659
|
+
const value = await Directive.#parseJson(sourceFile, ranges.argument.start, ranges.argument.end);
|
|
1660
|
+
inlineConfig.if = value;
|
|
1661
|
+
}
|
|
1662
|
+
return;
|
|
1663
|
+
case "template":
|
|
1664
|
+
if (ranges.argument?.text != null) {
|
|
1665
|
+
const text = DirectiveDiagnosticText.doesNotTakeArgument(ranges.directive.text);
|
|
1666
|
+
const origin = new DiagnosticOrigin(ranges.directive.start, ranges.directive.end, sourceFile);
|
|
1667
|
+
Directive.#onDiagnostics(Diagnostic.error(text, origin));
|
|
1668
|
+
}
|
|
1669
|
+
inlineConfig.template = true;
|
|
1670
|
+
return;
|
|
1671
|
+
}
|
|
1672
|
+
const target = ranges?.directive ?? ranges.namespace;
|
|
1673
|
+
const text = DirectiveDiagnosticText.isNotSupported(target.text);
|
|
1674
|
+
const origin = new DiagnosticOrigin(target.start, target.end, sourceFile);
|
|
1675
|
+
Directive.#onDiagnostics(Diagnostic.error(text, origin));
|
|
1676
|
+
}
|
|
1677
|
+
static async #parseJson(sourceFile, start, end) {
|
|
1678
|
+
const inlineOptions = {};
|
|
1679
|
+
const configParser = new ConfigParser(inlineOptions, OptionGroup.InlineConditions, sourceFile, new JsonScanner(sourceFile, { start, end }), Directive.#onDiagnostics);
|
|
1680
|
+
await configParser.parse();
|
|
1681
|
+
if ("target" in inlineOptions) {
|
|
1682
|
+
inlineOptions["target"] = await Target.expand(inlineOptions["target"]);
|
|
1683
|
+
}
|
|
1684
|
+
return inlineOptions;
|
|
1685
|
+
}
|
|
1686
|
+
}
|
|
1687
|
+
|
|
1573
1688
|
class CancellationHandler {
|
|
1574
1689
|
#cancellationToken;
|
|
1575
1690
|
#cancellationReason;
|
|
@@ -1777,6 +1892,7 @@ class ResultHandler {
|
|
|
1777
1892
|
this.#taskResult.timing.start = Date.now();
|
|
1778
1893
|
break;
|
|
1779
1894
|
case "task:error":
|
|
1895
|
+
case "directive:error":
|
|
1780
1896
|
case "collect:error":
|
|
1781
1897
|
this.#targetResult.status = ResultStatus.Failed;
|
|
1782
1898
|
this.#taskResult.status = ResultStatus.Failed;
|
|
@@ -2380,6 +2496,7 @@ class ListReporter extends BaseReporter {
|
|
|
2380
2496
|
this.#hasReportedError = false;
|
|
2381
2497
|
break;
|
|
2382
2498
|
case "task:error":
|
|
2499
|
+
case "directive:error":
|
|
2383
2500
|
case "collect:error":
|
|
2384
2501
|
for (const diagnostic of payload.diagnostics) {
|
|
2385
2502
|
this.#fileView.addMessage(diagnosticText(diagnostic));
|
|
@@ -2895,6 +3012,9 @@ class TestTreeNode {
|
|
|
2895
3012
|
}
|
|
2896
3013
|
}
|
|
2897
3014
|
}
|
|
3015
|
+
getDirectiveRanges(compiler) {
|
|
3016
|
+
return Directive.getDirectiveRanges(compiler, this.node.getSourceFile(), this.node.getFullStart());
|
|
3017
|
+
}
|
|
2898
3018
|
}
|
|
2899
3019
|
|
|
2900
3020
|
class AssertionNode extends TestTreeNode {
|
|
@@ -3185,6 +3305,9 @@ class TestTree {
|
|
|
3185
3305
|
this.diagnostics = diagnostics;
|
|
3186
3306
|
this.sourceFile = sourceFile;
|
|
3187
3307
|
}
|
|
3308
|
+
getDirectiveRanges(compiler) {
|
|
3309
|
+
return Directive.getDirectiveRanges(compiler, this.sourceFile);
|
|
3310
|
+
}
|
|
3188
3311
|
}
|
|
3189
3312
|
|
|
3190
3313
|
class WhenNode extends TestTreeNode {
|
|
@@ -4529,6 +4652,7 @@ class WhenService {
|
|
|
4529
4652
|
|
|
4530
4653
|
class TestTreeWalker {
|
|
4531
4654
|
#cancellationToken;
|
|
4655
|
+
#compiler;
|
|
4532
4656
|
#expectService;
|
|
4533
4657
|
#hasOnly;
|
|
4534
4658
|
#onTaskDiagnostics;
|
|
@@ -4536,6 +4660,7 @@ class TestTreeWalker {
|
|
|
4536
4660
|
#resolvedConfig;
|
|
4537
4661
|
#whenService;
|
|
4538
4662
|
constructor(compiler, typeChecker, resolvedConfig, onTaskDiagnostics, options) {
|
|
4663
|
+
this.#compiler = compiler;
|
|
4539
4664
|
this.#resolvedConfig = resolvedConfig;
|
|
4540
4665
|
this.#onTaskDiagnostics = onTaskDiagnostics;
|
|
4541
4666
|
this.#cancellationToken = options.cancellationToken;
|
|
@@ -4545,43 +4670,46 @@ class TestTreeWalker {
|
|
|
4545
4670
|
this.#expectService = new ExpectService(compiler, typeChecker, reject);
|
|
4546
4671
|
this.#whenService = new WhenService(reject, onTaskDiagnostics);
|
|
4547
4672
|
}
|
|
4548
|
-
#resolveRunMode(mode,
|
|
4549
|
-
|
|
4673
|
+
async #resolveRunMode(mode, node) {
|
|
4674
|
+
const directiveRanges = node.getDirectiveRanges(this.#compiler);
|
|
4675
|
+
const inlineConfig = await Directive.getInlineConfig(directiveRanges);
|
|
4676
|
+
if (inlineConfig?.if?.target != null && !Version.isIncluded(this.#compiler.version, inlineConfig.if.target)) {
|
|
4677
|
+
mode |= RunMode.Skip;
|
|
4678
|
+
}
|
|
4679
|
+
if (node.flags & TestTreeNodeFlags.Fail) {
|
|
4550
4680
|
mode |= RunMode.Fail;
|
|
4551
4681
|
}
|
|
4552
|
-
if (
|
|
4553
|
-
(this.#resolvedConfig.only != null &&
|
|
4554
|
-
testNode.name.toLowerCase().includes(this.#resolvedConfig.only.toLowerCase()))) {
|
|
4682
|
+
if (node.flags & TestTreeNodeFlags.Only ||
|
|
4683
|
+
(this.#resolvedConfig.only != null && node.name.toLowerCase().includes(this.#resolvedConfig.only.toLowerCase()))) {
|
|
4555
4684
|
mode |= RunMode.Only;
|
|
4556
4685
|
}
|
|
4557
|
-
if (
|
|
4558
|
-
(this.#resolvedConfig.skip != null &&
|
|
4559
|
-
testNode.name.toLowerCase().includes(this.#resolvedConfig.skip.toLowerCase()))) {
|
|
4686
|
+
if (node.flags & TestTreeNodeFlags.Skip ||
|
|
4687
|
+
(this.#resolvedConfig.skip != null && node.name.toLowerCase().includes(this.#resolvedConfig.skip.toLowerCase()))) {
|
|
4560
4688
|
mode |= RunMode.Skip;
|
|
4561
4689
|
}
|
|
4562
|
-
if (
|
|
4690
|
+
if (node.flags & TestTreeNodeFlags.Todo) {
|
|
4563
4691
|
mode |= RunMode.Todo;
|
|
4564
4692
|
}
|
|
4565
|
-
if (this.#position != null &&
|
|
4693
|
+
if (this.#position != null && node.node.getStart() === this.#position) {
|
|
4566
4694
|
mode |= RunMode.Only;
|
|
4567
4695
|
mode &= ~RunMode.Skip;
|
|
4568
4696
|
}
|
|
4569
4697
|
return mode;
|
|
4570
4698
|
}
|
|
4571
|
-
visit(nodes, runMode, parentResult) {
|
|
4699
|
+
async visit(nodes, runMode, parentResult) {
|
|
4572
4700
|
for (const node of nodes) {
|
|
4573
4701
|
if (this.#cancellationToken?.isCancellationRequested) {
|
|
4574
4702
|
break;
|
|
4575
4703
|
}
|
|
4576
4704
|
switch (node.brand) {
|
|
4577
4705
|
case TestTreeNodeBrand.Describe:
|
|
4578
|
-
this.#visitDescribe(node, runMode, parentResult);
|
|
4706
|
+
await this.#visitDescribe(node, runMode, parentResult);
|
|
4579
4707
|
break;
|
|
4580
4708
|
case TestTreeNodeBrand.Test:
|
|
4581
|
-
this.#visitTest(node, runMode, parentResult);
|
|
4709
|
+
await this.#visitTest(node, runMode, parentResult);
|
|
4582
4710
|
break;
|
|
4583
4711
|
case TestTreeNodeBrand.Expect:
|
|
4584
|
-
this.#visitAssertion(node, runMode, parentResult);
|
|
4712
|
+
await this.#visitAssertion(node, runMode, parentResult);
|
|
4585
4713
|
break;
|
|
4586
4714
|
case TestTreeNodeBrand.When:
|
|
4587
4715
|
this.#visitWhen(node);
|
|
@@ -4589,11 +4717,11 @@ class TestTreeWalker {
|
|
|
4589
4717
|
}
|
|
4590
4718
|
}
|
|
4591
4719
|
}
|
|
4592
|
-
#visitAssertion(assertion, runMode, parentResult) {
|
|
4593
|
-
this.visit(assertion.children, runMode, parentResult);
|
|
4720
|
+
async #visitAssertion(assertion, runMode, parentResult) {
|
|
4721
|
+
await this.visit(assertion.children, runMode, parentResult);
|
|
4594
4722
|
const expectResult = new ExpectResult(assertion, parentResult);
|
|
4595
4723
|
EventEmitter.dispatch(["expect:start", { result: expectResult }]);
|
|
4596
|
-
runMode = this.#resolveRunMode(runMode, assertion);
|
|
4724
|
+
runMode = await this.#resolveRunMode(runMode, assertion);
|
|
4597
4725
|
if (runMode & RunMode.Skip || (this.#hasOnly && !(runMode & RunMode.Only))) {
|
|
4598
4726
|
EventEmitter.dispatch(["expect:skip", { result: expectResult }]);
|
|
4599
4727
|
return;
|
|
@@ -4629,23 +4757,23 @@ class TestTreeWalker {
|
|
|
4629
4757
|
EventEmitter.dispatch(["expect:fail", { diagnostics: matchResult.explain(), result: expectResult }]);
|
|
4630
4758
|
}
|
|
4631
4759
|
}
|
|
4632
|
-
#visitDescribe(describe, runMode, parentResult) {
|
|
4760
|
+
async #visitDescribe(describe, runMode, parentResult) {
|
|
4633
4761
|
const describeResult = new DescribeResult(describe, parentResult);
|
|
4634
4762
|
EventEmitter.dispatch(["describe:start", { result: describeResult }]);
|
|
4635
|
-
runMode = this.#resolveRunMode(runMode, describe);
|
|
4763
|
+
runMode = await this.#resolveRunMode(runMode, describe);
|
|
4636
4764
|
if (!(runMode & RunMode.Skip || (this.#hasOnly && !(runMode & RunMode.Only)) || runMode & RunMode.Todo) &&
|
|
4637
4765
|
describe.diagnostics.size > 0) {
|
|
4638
4766
|
this.#onTaskDiagnostics(Diagnostic.fromDiagnostics([...describe.diagnostics]));
|
|
4639
4767
|
}
|
|
4640
4768
|
else {
|
|
4641
|
-
this.visit(describe.children, runMode, describeResult);
|
|
4769
|
+
await this.visit(describe.children, runMode, describeResult);
|
|
4642
4770
|
}
|
|
4643
4771
|
EventEmitter.dispatch(["describe:end", { result: describeResult }]);
|
|
4644
4772
|
}
|
|
4645
|
-
#visitTest(test, runMode, parentResult) {
|
|
4773
|
+
async #visitTest(test, runMode, parentResult) {
|
|
4646
4774
|
const testResult = new TestResult(test, parentResult);
|
|
4647
4775
|
EventEmitter.dispatch(["test:start", { result: testResult }]);
|
|
4648
|
-
runMode = this.#resolveRunMode(runMode, test);
|
|
4776
|
+
runMode = await this.#resolveRunMode(runMode, test);
|
|
4649
4777
|
if (runMode & RunMode.Todo) {
|
|
4650
4778
|
EventEmitter.dispatch(["test:todo", { result: testResult }]);
|
|
4651
4779
|
return;
|
|
@@ -4660,7 +4788,7 @@ class TestTreeWalker {
|
|
|
4660
4788
|
]);
|
|
4661
4789
|
return;
|
|
4662
4790
|
}
|
|
4663
|
-
this.visit(test.children, runMode, testResult);
|
|
4791
|
+
await this.visit(test.children, runMode, testResult);
|
|
4664
4792
|
if (runMode & RunMode.Skip || (this.#hasOnly && !(runMode & RunMode.Only))) {
|
|
4665
4793
|
EventEmitter.dispatch(["test:skip", { result: testResult }]);
|
|
4666
4794
|
return;
|
|
@@ -4702,21 +4830,27 @@ class TaskRunner {
|
|
|
4702
4830
|
EventEmitter.dispatch(["task:end", { result: taskResult }]);
|
|
4703
4831
|
this.#projectService.closeFile(task.filePath);
|
|
4704
4832
|
}
|
|
4705
|
-
async #
|
|
4706
|
-
|
|
4707
|
-
this.#onDiagnostics([Diagnostic.error(`Test file '${task.filePath}' does not exist.`)], taskResult);
|
|
4708
|
-
return;
|
|
4709
|
-
}
|
|
4710
|
-
let languageService = this.#projectService.getLanguageService(task.filePath);
|
|
4833
|
+
async #resolveTaskFacts(task, taskResult, runMode = RunMode.Normal) {
|
|
4834
|
+
const languageService = this.#projectService.getLanguageService(task.filePath);
|
|
4711
4835
|
const syntacticDiagnostics = languageService?.getSyntacticDiagnostics(task.filePath);
|
|
4712
4836
|
if (syntacticDiagnostics != null && syntacticDiagnostics.length > 0) {
|
|
4713
4837
|
this.#onDiagnostics(Diagnostic.fromDiagnostics(syntacticDiagnostics), taskResult);
|
|
4714
4838
|
return;
|
|
4715
4839
|
}
|
|
4716
|
-
|
|
4717
|
-
|
|
4718
|
-
|
|
4719
|
-
|
|
4840
|
+
const semanticDiagnostics = languageService?.getSemanticDiagnostics(task.filePath);
|
|
4841
|
+
const program = languageService?.getProgram();
|
|
4842
|
+
const typeChecker = program?.getTypeChecker();
|
|
4843
|
+
const sourceFile = program?.getSourceFile(task.filePath);
|
|
4844
|
+
if (!sourceFile) {
|
|
4845
|
+
return;
|
|
4846
|
+
}
|
|
4847
|
+
const testTree = this.#collectService.createTestTree(sourceFile, semanticDiagnostics);
|
|
4848
|
+
const directiveRanges = testTree.getDirectiveRanges(this.#compiler);
|
|
4849
|
+
const inlineConfig = await Directive.getInlineConfig(directiveRanges);
|
|
4850
|
+
if (inlineConfig?.if?.target != null && !Version.isIncluded(this.#compiler.version, inlineConfig.if.target)) {
|
|
4851
|
+
runMode |= RunMode.Skip;
|
|
4852
|
+
}
|
|
4853
|
+
if (inlineConfig?.template) {
|
|
4720
4854
|
if (semanticDiagnostics != null && semanticDiagnostics.length > 0) {
|
|
4721
4855
|
this.#onDiagnostics(Diagnostic.fromDiagnostics(semanticDiagnostics), taskResult);
|
|
4722
4856
|
return;
|
|
@@ -4728,41 +4862,39 @@ class TaskRunner {
|
|
|
4728
4862
|
return;
|
|
4729
4863
|
}
|
|
4730
4864
|
this.#projectService.openFile(task.filePath, testText, this.#resolvedConfig.rootPath);
|
|
4731
|
-
|
|
4732
|
-
const syntacticDiagnostics = languageService?.getSyntacticDiagnostics(task.filePath);
|
|
4733
|
-
if (syntacticDiagnostics != null && syntacticDiagnostics.length > 0) {
|
|
4734
|
-
this.#onDiagnostics(Diagnostic.fromDiagnostics(syntacticDiagnostics), taskResult);
|
|
4735
|
-
return;
|
|
4736
|
-
}
|
|
4737
|
-
semanticDiagnostics = languageService?.getSemanticDiagnostics(task.filePath);
|
|
4738
|
-
program = languageService?.getProgram();
|
|
4739
|
-
sourceFile = program?.getSourceFile(task.filePath);
|
|
4865
|
+
return this.#resolveTaskFacts(task, taskResult, runMode);
|
|
4740
4866
|
}
|
|
4741
|
-
|
|
4867
|
+
return { runMode, testTree, typeChecker };
|
|
4868
|
+
}
|
|
4869
|
+
async #run(task, taskResult, cancellationToken) {
|
|
4870
|
+
if (!existsSync(task.filePath)) {
|
|
4871
|
+
this.#onDiagnostics([Diagnostic.error(`Test file '${task.filePath}' does not exist.`)], taskResult);
|
|
4742
4872
|
return;
|
|
4743
4873
|
}
|
|
4744
|
-
const
|
|
4745
|
-
if (
|
|
4746
|
-
|
|
4874
|
+
const facts = await this.#resolveTaskFacts(task, taskResult);
|
|
4875
|
+
if (!facts) {
|
|
4876
|
+
return;
|
|
4877
|
+
}
|
|
4878
|
+
if (facts.testTree.diagnostics.size > 0) {
|
|
4879
|
+
this.#onDiagnostics(Diagnostic.fromDiagnostics([...facts.testTree.diagnostics]), taskResult);
|
|
4747
4880
|
return;
|
|
4748
4881
|
}
|
|
4749
|
-
const typeChecker = program?.getTypeChecker();
|
|
4750
4882
|
const onTaskDiagnostics = (diagnostics) => {
|
|
4751
4883
|
this.#onDiagnostics(diagnostics, taskResult);
|
|
4752
4884
|
};
|
|
4753
|
-
const testTreeWalker = new TestTreeWalker(this.#compiler, typeChecker, this.#resolvedConfig, onTaskDiagnostics, {
|
|
4885
|
+
const testTreeWalker = new TestTreeWalker(this.#compiler, facts.typeChecker, this.#resolvedConfig, onTaskDiagnostics, {
|
|
4754
4886
|
cancellationToken,
|
|
4755
|
-
hasOnly: testTree.hasOnly,
|
|
4887
|
+
hasOnly: facts.testTree.hasOnly,
|
|
4756
4888
|
position: task.position,
|
|
4757
4889
|
});
|
|
4758
|
-
testTreeWalker.visit(testTree.children,
|
|
4890
|
+
await testTreeWalker.visit(facts.testTree.children, facts.runMode, undefined);
|
|
4759
4891
|
}
|
|
4760
4892
|
}
|
|
4761
4893
|
|
|
4762
4894
|
class Runner {
|
|
4763
4895
|
#eventEmitter = new EventEmitter();
|
|
4764
4896
|
#resolvedConfig;
|
|
4765
|
-
static version = "4.0.0-rc.
|
|
4897
|
+
static version = "4.0.0-rc.1";
|
|
4766
4898
|
constructor(resolvedConfig) {
|
|
4767
4899
|
this.#resolvedConfig = resolvedConfig;
|
|
4768
4900
|
}
|
|
@@ -4962,4 +5094,4 @@ class Cli {
|
|
|
4962
5094
|
}
|
|
4963
5095
|
}
|
|
4964
5096
|
|
|
4965
|
-
export { AssertionNode, BaseReporter, CancellationHandler, CancellationReason, CancellationToken, Cli, CollectService, Color, Config, ConfigDiagnosticText, DescribeResult, Diagnostic, DiagnosticCategory, DiagnosticOrigin, EventEmitter, ExitCodeHandler, ExpectResult, ExpectService, FileWatcher, InputService, Line, ListReporter, OptionBrand, OptionGroup, Options, OutputService, Path, PluginService, ProjectResult, ProjectService, Reject, Result, ResultCount, ResultHandler, ResultStatus, ResultTiming, Runner, Scribbler, Select, SelectDiagnosticText, SetupReporter, SourceFile, Store, SummaryReporter, TargetResult, Task, TaskResult, TestResult, TestTree, TestTreeNode, TestTreeNodeBrand, TestTreeNodeFlags, Text, Version, WatchReporter, WatchService, Watcher, WhenNode, WhenService, addsPackageText, argumentIsProvided, argumentOrTypeArgumentIsProvided, defaultOptions, describeNameText, diagnosticBelongsToNode, diagnosticText, environmentOptions, fileViewText, formattedText, getDiagnosticMessageText, getTextSpanEnd, helpText, isDiagnosticWithLocation, nodeBelongsToArgumentList, summaryText, taskStatusText, testNameText, usesCompilerText, waitingForFileChangesText, watchUsageText };
|
|
5097
|
+
export { AssertionNode, BaseReporter, CancellationHandler, CancellationReason, CancellationToken, Cli, CollectService, Color, Config, ConfigDiagnosticText, DescribeResult, Diagnostic, DiagnosticCategory, DiagnosticOrigin, Directive, EventEmitter, ExitCodeHandler, ExpectResult, ExpectService, FileWatcher, InputService, Line, ListReporter, OptionBrand, OptionGroup, Options, OutputService, Path, PluginService, ProjectResult, ProjectService, Reject, Result, ResultCount, ResultHandler, ResultStatus, ResultTiming, Runner, Scribbler, Select, SelectDiagnosticText, SetupReporter, SourceFile, Store, SummaryReporter, TargetResult, Task, TaskResult, TestResult, TestTree, TestTreeNode, TestTreeNodeBrand, TestTreeNodeFlags, Text, Version, WatchReporter, WatchService, Watcher, WhenNode, WhenService, addsPackageText, argumentIsProvided, argumentOrTypeArgumentIsProvided, defaultOptions, describeNameText, diagnosticBelongsToNode, diagnosticText, environmentOptions, fileViewText, formattedText, getDiagnosticMessageText, getTextSpanEnd, helpText, isDiagnosticWithLocation, nodeBelongsToArgumentList, summaryText, taskStatusText, testNameText, usesCompilerText, waitingForFileChangesText, watchUsageText };
|