tstyche 4.0.2 → 4.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -2
- package/build/tstyche.d.ts +20 -4
- package/build/tstyche.js +181 -72
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -70,8 +70,7 @@ Here is the list of all matchers:
|
|
|
70
70
|
- `.toBeApplicable` ensures that the decorator function can be applied,
|
|
71
71
|
- `.toBeCallableWith()` checks whether a function is callable with the given arguments,
|
|
72
72
|
- `.toBeConstructableWith()` checks whether a class is constructable with the given arguments,
|
|
73
|
-
- `.toHaveProperty()` looks up keys on an object type
|
|
74
|
-
- `.toRaiseError()` captures the message or code of a type error.
|
|
73
|
+
- `.toHaveProperty()` looks up keys on an object type.
|
|
75
74
|
|
|
76
75
|
## Runner
|
|
77
76
|
|
package/build/tstyche.d.ts
CHANGED
|
@@ -41,6 +41,7 @@ interface CommandLineOptions {
|
|
|
41
41
|
}
|
|
42
42
|
interface ConfigFileOptions {
|
|
43
43
|
checkSourceFiles?: boolean;
|
|
44
|
+
checkSuppressedErrors?: boolean;
|
|
44
45
|
failFast?: boolean;
|
|
45
46
|
plugins?: Array<string>;
|
|
46
47
|
rejectAnyType?: boolean;
|
|
@@ -231,7 +232,7 @@ declare enum TestTreeNodeFlags {
|
|
|
231
232
|
declare class WhenNode extends TestTreeNode {
|
|
232
233
|
actionNode: ts.CallExpression;
|
|
233
234
|
actionNameNode: ts.PropertyAccessExpression;
|
|
234
|
-
abilityDiagnostics: Set<ts.Diagnostic
|
|
235
|
+
abilityDiagnostics: Set<ts.Diagnostic>;
|
|
235
236
|
target: ts.NodeArray<ts.Expression> | ts.NodeArray<ts.TypeNode>;
|
|
236
237
|
constructor(compiler: typeof ts, brand: TestTreeNodeBrand, node: ts.CallExpression, parent: TestTree | TestTreeNode, flags: TestTreeNodeFlags, actionNode: ts.CallExpression, actionNameNode: ts.PropertyAccessExpression);
|
|
237
238
|
}
|
|
@@ -248,17 +249,28 @@ declare class TestTreeNode {
|
|
|
248
249
|
getDirectiveRanges(compiler: typeof ts): DirectiveRanges | undefined;
|
|
249
250
|
}
|
|
250
251
|
|
|
252
|
+
interface SuppressedError {
|
|
253
|
+
directive: TextRange;
|
|
254
|
+
ignore: boolean;
|
|
255
|
+
argument?: TextRange;
|
|
256
|
+
diagnostics: Array<ts.Diagnostic>;
|
|
257
|
+
}
|
|
258
|
+
type SuppressedErrors = Array<SuppressedError> & {
|
|
259
|
+
sourceFile: ts.SourceFile;
|
|
260
|
+
};
|
|
261
|
+
|
|
251
262
|
declare class TestTree {
|
|
252
263
|
children: Array<TestTreeNode | AssertionNode | WhenNode>;
|
|
253
264
|
diagnostics: Set<ts.Diagnostic>;
|
|
254
265
|
hasOnly: boolean;
|
|
255
266
|
sourceFile: ts.SourceFile;
|
|
267
|
+
suppressedErrors: SuppressedErrors | undefined;
|
|
256
268
|
constructor(diagnostics: Set<ts.Diagnostic>, sourceFile: ts.SourceFile);
|
|
257
269
|
getDirectiveRanges(compiler: typeof ts): DirectiveRanges | undefined;
|
|
258
270
|
}
|
|
259
271
|
|
|
260
272
|
declare class AssertionNode extends TestTreeNode {
|
|
261
|
-
abilityDiagnostics: Set<ts.Diagnostic
|
|
273
|
+
abilityDiagnostics: Set<ts.Diagnostic>;
|
|
262
274
|
isNot: boolean;
|
|
263
275
|
matcherNode: ts.CallExpression | ts.Decorator;
|
|
264
276
|
matcherNameNode: ts.PropertyAccessExpression;
|
|
@@ -759,6 +771,10 @@ declare class Store {
|
|
|
759
771
|
static validateTag(tag: string): Promise<boolean | undefined>;
|
|
760
772
|
}
|
|
761
773
|
|
|
774
|
+
declare class SuppressedService {
|
|
775
|
+
match(suppressedErrors: SuppressedErrors, onDiagnostics: DiagnosticsHandler<Array<Diagnostic>>): void;
|
|
776
|
+
}
|
|
777
|
+
|
|
762
778
|
declare class Version {
|
|
763
779
|
#private;
|
|
764
780
|
static isGreaterThan(source: string, target: string): boolean;
|
|
@@ -794,5 +810,5 @@ declare class WhenService {
|
|
|
794
810
|
action(when: WhenNode): void;
|
|
795
811
|
}
|
|
796
812
|
|
|
797
|
-
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 };
|
|
798
|
-
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, TextRange, TypeChecker, WatchHandler, WatcherOptions };
|
|
813
|
+
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, SuppressedService, 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 };
|
|
814
|
+
export type { CodeFrameOptions, CommandLineOptions, ConfigFileOptions, DiagnosticsHandler, DirectiveRange, DirectiveRanges, EnvironmentOptions, Event, EventHandler, FileWatchHandler, InlineConfig, InputHandler, ItemDefinition, MatchResult, OptionDefinition, Plugin, Reporter, ReporterEvent, ResolvedConfig, ScribblerOptions, SelectHookContext, SuppressedError, SuppressedErrors, TargetResultStatus, TaskResultStatus, TextRange, TypeChecker, WatchHandler, WatcherOptions };
|
package/build/tstyche.js
CHANGED
|
@@ -96,7 +96,7 @@ class Diagnostic {
|
|
|
96
96
|
}
|
|
97
97
|
let related;
|
|
98
98
|
if (diagnostic.relatedInformation != null) {
|
|
99
|
-
related = Diagnostic.fromDiagnostics(diagnostic.relatedInformation
|
|
99
|
+
related = Diagnostic.fromDiagnostics(diagnostic.relatedInformation);
|
|
100
100
|
}
|
|
101
101
|
const text = getDiagnosticMessageText(diagnostic);
|
|
102
102
|
return new Diagnostic(text, DiagnosticCategory.Error, origin).add({ code, related });
|
|
@@ -910,6 +910,12 @@ class Options {
|
|
|
910
910
|
group: OptionGroup.ConfigFile,
|
|
911
911
|
name: "checkSourceFiles",
|
|
912
912
|
},
|
|
913
|
+
{
|
|
914
|
+
brand: OptionBrand.Boolean,
|
|
915
|
+
description: "Check errors silenced by '// @ts-expect-error' directives.",
|
|
916
|
+
group: OptionGroup.ConfigFile,
|
|
917
|
+
name: "checkSuppressedErrors",
|
|
918
|
+
},
|
|
913
919
|
{
|
|
914
920
|
brand: OptionBrand.String,
|
|
915
921
|
description: "The path to a TSTyche configuration file.",
|
|
@@ -1394,6 +1400,7 @@ class ConfigParser {
|
|
|
1394
1400
|
|
|
1395
1401
|
const defaultOptions = {
|
|
1396
1402
|
checkSourceFiles: true,
|
|
1403
|
+
checkSuppressedErrors: false,
|
|
1397
1404
|
failFast: false,
|
|
1398
1405
|
plugins: [],
|
|
1399
1406
|
rejectAnyType: true,
|
|
@@ -3030,7 +3037,7 @@ class TestTreeNode {
|
|
|
3030
3037
|
}
|
|
3031
3038
|
|
|
3032
3039
|
class AssertionNode extends TestTreeNode {
|
|
3033
|
-
abilityDiagnostics;
|
|
3040
|
+
abilityDiagnostics = new Set();
|
|
3034
3041
|
isNot;
|
|
3035
3042
|
matcherNode;
|
|
3036
3043
|
matcherNameNode;
|
|
@@ -3072,12 +3079,51 @@ class AbilityLayer {
|
|
|
3072
3079
|
#nodes = [];
|
|
3073
3080
|
#projectService;
|
|
3074
3081
|
#resolvedConfig;
|
|
3082
|
+
#suppressedErrorsMap;
|
|
3075
3083
|
#text = "";
|
|
3076
3084
|
constructor(compiler, projectService, resolvedConfig) {
|
|
3077
3085
|
this.#compiler = compiler;
|
|
3078
3086
|
this.#projectService = projectService;
|
|
3079
3087
|
this.#resolvedConfig = resolvedConfig;
|
|
3080
3088
|
}
|
|
3089
|
+
#addRanges(node, ranges) {
|
|
3090
|
+
this.#nodes.push(node);
|
|
3091
|
+
for (const range of ranges) {
|
|
3092
|
+
const rangeText = range.replacement != null
|
|
3093
|
+
? `${range.replacement}${this.#getErasedRangeText(range).slice(range.replacement.length)}`
|
|
3094
|
+
: this.#getErasedRangeText(range);
|
|
3095
|
+
this.#text = `${this.#text.slice(0, range.start)}${rangeText}${this.#text.slice(range.end)}`;
|
|
3096
|
+
}
|
|
3097
|
+
}
|
|
3098
|
+
#belongsToNode(diagnostic) {
|
|
3099
|
+
for (const node of this.#nodes) {
|
|
3100
|
+
if (diagnosticBelongsToNode(diagnostic, "matcherNode" in node ? node.matcherNode : node.actionNode)) {
|
|
3101
|
+
node.abilityDiagnostics.add(diagnostic);
|
|
3102
|
+
return true;
|
|
3103
|
+
}
|
|
3104
|
+
}
|
|
3105
|
+
return false;
|
|
3106
|
+
}
|
|
3107
|
+
#belongsToDirective(diagnostic) {
|
|
3108
|
+
if (!isDiagnosticWithLocation(diagnostic)) {
|
|
3109
|
+
return;
|
|
3110
|
+
}
|
|
3111
|
+
const { file, start } = diagnostic;
|
|
3112
|
+
const lineMap = file.getLineStarts();
|
|
3113
|
+
let line = this.#compiler.getLineAndCharacterOfPosition(file, start).line - 1;
|
|
3114
|
+
while (line >= 0) {
|
|
3115
|
+
const suppressedError = this.#suppressedErrorsMap?.get(line);
|
|
3116
|
+
if (suppressedError != null) {
|
|
3117
|
+
suppressedError.diagnostics.push(diagnostic);
|
|
3118
|
+
break;
|
|
3119
|
+
}
|
|
3120
|
+
const lineText = file.text.slice(lineMap[line], lineMap[line + 1]).trim();
|
|
3121
|
+
if (lineText !== "" && !lineText.startsWith("//")) {
|
|
3122
|
+
break;
|
|
3123
|
+
}
|
|
3124
|
+
line--;
|
|
3125
|
+
}
|
|
3126
|
+
}
|
|
3081
3127
|
#collectSuppressedErrors() {
|
|
3082
3128
|
const ranges = [];
|
|
3083
3129
|
for (const match of this.#text.matchAll(this.#expectErrorRegex)) {
|
|
@@ -3086,12 +3132,13 @@ class AbilityLayer {
|
|
|
3086
3132
|
const ignoreText = match?.[3];
|
|
3087
3133
|
const argumentSeparatorText = match?.[4];
|
|
3088
3134
|
const argumentText = match?.[5]?.split(/--+/)[0]?.trimEnd();
|
|
3089
|
-
if (typeof offsetText !== "string" || !directiveText
|
|
3135
|
+
if (typeof offsetText !== "string" || !directiveText) {
|
|
3090
3136
|
continue;
|
|
3091
3137
|
}
|
|
3092
3138
|
const start = match.index + offsetText.length;
|
|
3093
3139
|
const range = {
|
|
3094
3140
|
directive: { start, end: start + directiveText.length, text: directiveText },
|
|
3141
|
+
ignore: ignoreText === "!",
|
|
3095
3142
|
diagnostics: [],
|
|
3096
3143
|
};
|
|
3097
3144
|
if (typeof argumentSeparatorText === "string" && typeof argumentText === "string") {
|
|
@@ -3102,52 +3149,24 @@ class AbilityLayer {
|
|
|
3102
3149
|
}
|
|
3103
3150
|
return ranges;
|
|
3104
3151
|
}
|
|
3105
|
-
#getErasedRangeText(range) {
|
|
3106
|
-
if (this.#text.indexOf("\n", range.start) >= range.end) {
|
|
3107
|
-
return " ".repeat(range.end - range.start);
|
|
3108
|
-
}
|
|
3109
|
-
const text = [];
|
|
3110
|
-
for (let index = range.start; index < range.end; index++) {
|
|
3111
|
-
const character = this.#text.charAt(index);
|
|
3112
|
-
switch (character) {
|
|
3113
|
-
case "\n":
|
|
3114
|
-
case "\r":
|
|
3115
|
-
text.push(character);
|
|
3116
|
-
break;
|
|
3117
|
-
default:
|
|
3118
|
-
text.push(" ");
|
|
3119
|
-
}
|
|
3120
|
-
}
|
|
3121
|
-
return text.join("");
|
|
3122
|
-
}
|
|
3123
|
-
#addRanges(node, ranges) {
|
|
3124
|
-
this.#nodes.push(node);
|
|
3125
|
-
for (const range of ranges) {
|
|
3126
|
-
const rangeText = range.replacement != null
|
|
3127
|
-
? `${range.replacement}${this.#getErasedRangeText(range).slice(range.replacement.length)}`
|
|
3128
|
-
: this.#getErasedRangeText(range);
|
|
3129
|
-
this.#text = `${this.#text.slice(0, range.start)}${rangeText}${this.#text.slice(range.end)}`;
|
|
3130
|
-
}
|
|
3131
|
-
}
|
|
3132
3152
|
close() {
|
|
3133
|
-
if (this.#nodes.length > 0) {
|
|
3153
|
+
if (this.#nodes.length > 0 || this.#suppressedErrorsMap != null) {
|
|
3134
3154
|
this.#projectService.openFile(this.#filePath, this.#text, this.#resolvedConfig.rootPath);
|
|
3135
3155
|
const languageService = this.#projectService.getLanguageService(this.#filePath);
|
|
3136
|
-
const diagnostics =
|
|
3137
|
-
|
|
3156
|
+
const diagnostics = languageService?.getSemanticDiagnostics(this.#filePath);
|
|
3157
|
+
if (diagnostics != null) {
|
|
3158
|
+
this.#nodes.reverse();
|
|
3138
3159
|
for (const diagnostic of diagnostics) {
|
|
3139
|
-
if (
|
|
3140
|
-
|
|
3141
|
-
node.abilityDiagnostics = new Set();
|
|
3142
|
-
}
|
|
3143
|
-
node.abilityDiagnostics.add(diagnostic);
|
|
3144
|
-
diagnostics.delete(diagnostic);
|
|
3160
|
+
if (this.#belongsToNode(diagnostic)) {
|
|
3161
|
+
continue;
|
|
3145
3162
|
}
|
|
3163
|
+
this.#belongsToDirective(diagnostic);
|
|
3146
3164
|
}
|
|
3147
3165
|
}
|
|
3148
3166
|
}
|
|
3149
3167
|
this.#filePath = "";
|
|
3150
3168
|
this.#nodes = [];
|
|
3169
|
+
this.#suppressedErrorsMap = undefined;
|
|
3151
3170
|
this.#text = "";
|
|
3152
3171
|
}
|
|
3153
3172
|
#eraseTrailingComma(node, parent) {
|
|
@@ -3155,24 +3174,23 @@ class AbilityLayer {
|
|
|
3155
3174
|
this.#addRanges(parent, [{ start: node.end - 1, end: node.end }]);
|
|
3156
3175
|
}
|
|
3157
3176
|
}
|
|
3158
|
-
|
|
3159
|
-
|
|
3160
|
-
|
|
3161
|
-
|
|
3162
|
-
const
|
|
3163
|
-
|
|
3164
|
-
|
|
3165
|
-
|
|
3166
|
-
|
|
3167
|
-
|
|
3168
|
-
|
|
3169
|
-
|
|
3170
|
-
|
|
3171
|
-
|
|
3172
|
-
|
|
3173
|
-
]);
|
|
3174
|
-
break;
|
|
3177
|
+
#getErasedRangeText(range) {
|
|
3178
|
+
if (this.#text.indexOf("\n", range.start) >= range.end) {
|
|
3179
|
+
return " ".repeat(range.end - range.start);
|
|
3180
|
+
}
|
|
3181
|
+
const text = [];
|
|
3182
|
+
for (let index = range.start; index < range.end; index++) {
|
|
3183
|
+
const character = this.#text.charAt(index);
|
|
3184
|
+
switch (character) {
|
|
3185
|
+
case "\n":
|
|
3186
|
+
case "\r":
|
|
3187
|
+
text.push(character);
|
|
3188
|
+
break;
|
|
3189
|
+
default:
|
|
3190
|
+
text.push(" ");
|
|
3191
|
+
}
|
|
3175
3192
|
}
|
|
3193
|
+
return text.join("");
|
|
3176
3194
|
}
|
|
3177
3195
|
handleAssertion(assertionNode) {
|
|
3178
3196
|
const expectStart = assertionNode.node.getStart();
|
|
@@ -3210,18 +3228,45 @@ class AbilityLayer {
|
|
|
3210
3228
|
break;
|
|
3211
3229
|
}
|
|
3212
3230
|
}
|
|
3213
|
-
#handleSuppressedErrors() {
|
|
3231
|
+
#handleSuppressedErrors(testTree) {
|
|
3214
3232
|
const suppressedErrors = this.#collectSuppressedErrors();
|
|
3233
|
+
if (this.#resolvedConfig.checkSuppressedErrors) {
|
|
3234
|
+
testTree.suppressedErrors = Object.assign(suppressedErrors, { sourceFile: testTree.sourceFile });
|
|
3235
|
+
this.#suppressedErrorsMap = new Map();
|
|
3236
|
+
}
|
|
3215
3237
|
for (const suppressedError of suppressedErrors) {
|
|
3216
3238
|
const { start, end } = suppressedError.directive;
|
|
3217
3239
|
const rangeText = this.#getErasedRangeText({ start: start + 2, end });
|
|
3218
3240
|
this.#text = `${this.#text.slice(0, start + 2)}${rangeText}${this.#text.slice(end)}`;
|
|
3241
|
+
if (this.#suppressedErrorsMap != null) {
|
|
3242
|
+
const { line } = testTree.sourceFile.getLineAndCharacterOfPosition(start);
|
|
3243
|
+
this.#suppressedErrorsMap.set(line, suppressedError);
|
|
3244
|
+
}
|
|
3245
|
+
}
|
|
3246
|
+
}
|
|
3247
|
+
handleWhen(whenNode) {
|
|
3248
|
+
const whenStart = whenNode.node.getStart();
|
|
3249
|
+
const whenExpressionEnd = whenNode.node.expression.getEnd();
|
|
3250
|
+
const whenEnd = whenNode.node.getEnd();
|
|
3251
|
+
const actionNameEnd = whenNode.actionNameNode.getEnd();
|
|
3252
|
+
switch (whenNode.actionNameNode.name.text) {
|
|
3253
|
+
case "isCalledWith":
|
|
3254
|
+
this.#eraseTrailingComma(whenNode.target, whenNode);
|
|
3255
|
+
this.#addRanges(whenNode, [
|
|
3256
|
+
{
|
|
3257
|
+
start: whenStart,
|
|
3258
|
+
end: whenExpressionEnd,
|
|
3259
|
+
replacement: nodeIsChildOfExpressionStatement(this.#compiler, whenNode.actionNode) ? ";" : "",
|
|
3260
|
+
},
|
|
3261
|
+
{ start: whenEnd, end: actionNameEnd },
|
|
3262
|
+
]);
|
|
3263
|
+
break;
|
|
3219
3264
|
}
|
|
3220
3265
|
}
|
|
3221
|
-
open(
|
|
3222
|
-
this.#filePath = sourceFile.fileName;
|
|
3223
|
-
this.#text = sourceFile.text;
|
|
3224
|
-
this.#handleSuppressedErrors();
|
|
3266
|
+
open(testTree) {
|
|
3267
|
+
this.#filePath = testTree.sourceFile.fileName;
|
|
3268
|
+
this.#text = testTree.sourceFile.text;
|
|
3269
|
+
this.#handleSuppressedErrors(testTree);
|
|
3225
3270
|
}
|
|
3226
3271
|
}
|
|
3227
3272
|
|
|
@@ -3348,6 +3393,7 @@ class TestTree {
|
|
|
3348
3393
|
diagnostics;
|
|
3349
3394
|
hasOnly = false;
|
|
3350
3395
|
sourceFile;
|
|
3396
|
+
suppressedErrors;
|
|
3351
3397
|
constructor(diagnostics, sourceFile) {
|
|
3352
3398
|
this.diagnostics = diagnostics;
|
|
3353
3399
|
this.sourceFile = sourceFile;
|
|
@@ -3360,7 +3406,7 @@ class TestTree {
|
|
|
3360
3406
|
class WhenNode extends TestTreeNode {
|
|
3361
3407
|
actionNode;
|
|
3362
3408
|
actionNameNode;
|
|
3363
|
-
abilityDiagnostics;
|
|
3409
|
+
abilityDiagnostics = new Set();
|
|
3364
3410
|
target;
|
|
3365
3411
|
constructor(compiler, brand, node, parent, flags, actionNode, actionNameNode) {
|
|
3366
3412
|
super(compiler, brand, node, parent, flags);
|
|
@@ -3459,7 +3505,7 @@ class CollectService {
|
|
|
3459
3505
|
createTestTree(sourceFile, semanticDiagnostics = []) {
|
|
3460
3506
|
const testTree = new TestTree(new Set(semanticDiagnostics), sourceFile);
|
|
3461
3507
|
EventEmitter.dispatch(["collect:start", { tree: testTree }]);
|
|
3462
|
-
this.#abilityLayer.open(
|
|
3508
|
+
this.#abilityLayer.open(testTree);
|
|
3463
3509
|
this.#identifierLookup.open();
|
|
3464
3510
|
this.#collectTestTreeNodes(sourceFile, testTree, testTree);
|
|
3465
3511
|
this.#abilityLayer.close();
|
|
@@ -3596,6 +3642,9 @@ class ProjectService {
|
|
|
3596
3642
|
defaultCompilerOptions.allowImportingTsExtensions = true;
|
|
3597
3643
|
defaultCompilerOptions.verbatimModuleSyntax = true;
|
|
3598
3644
|
}
|
|
3645
|
+
if (Version.isSatisfiedWith(this.#compiler.version, "5.6")) {
|
|
3646
|
+
defaultCompilerOptions.noUncheckedSideEffectImports = true;
|
|
3647
|
+
}
|
|
3599
3648
|
return defaultCompilerOptions;
|
|
3600
3649
|
}
|
|
3601
3650
|
getDefaultProject(filePath) {
|
|
@@ -3669,6 +3718,60 @@ class ProjectService {
|
|
|
3669
3718
|
}
|
|
3670
3719
|
}
|
|
3671
3720
|
|
|
3721
|
+
class SuppressedDiagnosticText {
|
|
3722
|
+
static directiveRequires() {
|
|
3723
|
+
return [
|
|
3724
|
+
"Directive requires an argument.",
|
|
3725
|
+
"Add a fragment of the expected error message after the directive.",
|
|
3726
|
+
"To ignore the directive, append a '!' character after it.",
|
|
3727
|
+
];
|
|
3728
|
+
}
|
|
3729
|
+
static messageDidNotMatch() {
|
|
3730
|
+
return "The diagnostic message did not match.";
|
|
3731
|
+
}
|
|
3732
|
+
static onlySingleError() {
|
|
3733
|
+
return "Only a single error can be suppressed.";
|
|
3734
|
+
}
|
|
3735
|
+
static suppressedError(count = 1) {
|
|
3736
|
+
return `The suppressed error${count === 1 ? "" : "s"}:`;
|
|
3737
|
+
}
|
|
3738
|
+
}
|
|
3739
|
+
|
|
3740
|
+
class SuppressedService {
|
|
3741
|
+
match(suppressedErrors, onDiagnostics) {
|
|
3742
|
+
for (const suppressedError of suppressedErrors) {
|
|
3743
|
+
if (suppressedError.diagnostics.length === 0 || suppressedError.ignore) {
|
|
3744
|
+
continue;
|
|
3745
|
+
}
|
|
3746
|
+
if (!suppressedError.argument?.text) {
|
|
3747
|
+
const text = SuppressedDiagnosticText.directiveRequires();
|
|
3748
|
+
const origin = new DiagnosticOrigin(suppressedError.directive.start, suppressedError.directive.end, suppressedErrors.sourceFile);
|
|
3749
|
+
onDiagnostics([Diagnostic.error(text, origin)]);
|
|
3750
|
+
continue;
|
|
3751
|
+
}
|
|
3752
|
+
const related = [
|
|
3753
|
+
Diagnostic.error(SuppressedDiagnosticText.suppressedError(suppressedError.diagnostics.length)),
|
|
3754
|
+
...Diagnostic.fromDiagnostics(suppressedError.diagnostics, suppressedErrors.sourceFile),
|
|
3755
|
+
];
|
|
3756
|
+
if (suppressedError.diagnostics.length > 1) {
|
|
3757
|
+
const text = [SuppressedDiagnosticText.onlySingleError()];
|
|
3758
|
+
const origin = new DiagnosticOrigin(suppressedError.directive.start, suppressedError.directive.end, suppressedErrors.sourceFile);
|
|
3759
|
+
onDiagnostics([Diagnostic.error(text, origin).add({ related })]);
|
|
3760
|
+
continue;
|
|
3761
|
+
}
|
|
3762
|
+
let messageText = getDiagnosticMessageText(suppressedError.diagnostics[0]);
|
|
3763
|
+
if (Array.isArray(messageText)) {
|
|
3764
|
+
messageText = messageText.join("\n");
|
|
3765
|
+
}
|
|
3766
|
+
if (!messageText.includes(suppressedError.argument.text)) {
|
|
3767
|
+
const text = [SuppressedDiagnosticText.messageDidNotMatch()];
|
|
3768
|
+
const origin = new DiagnosticOrigin(suppressedError.argument.start, suppressedError.argument.end, suppressedErrors.sourceFile);
|
|
3769
|
+
onDiagnostics([Diagnostic.error(text, origin).add({ related })]);
|
|
3770
|
+
}
|
|
3771
|
+
}
|
|
3772
|
+
}
|
|
3773
|
+
}
|
|
3774
|
+
|
|
3672
3775
|
var RunMode;
|
|
3673
3776
|
(function (RunMode) {
|
|
3674
3777
|
RunMode[RunMode["Normal"] = 0] = "Normal";
|
|
@@ -4153,7 +4256,7 @@ class ToBeApplicable {
|
|
|
4153
4256
|
#explain(matchWorker, sourceNode) {
|
|
4154
4257
|
const targetText = this.#resolveTargetText(matchWorker.assertion.matcherNode.parent);
|
|
4155
4258
|
const diagnostics = [];
|
|
4156
|
-
if (matchWorker.assertion.abilityDiagnostics) {
|
|
4259
|
+
if (matchWorker.assertion.abilityDiagnostics.size > 0) {
|
|
4157
4260
|
for (const diagnostic of matchWorker.assertion.abilityDiagnostics) {
|
|
4158
4261
|
const text = [ExpectDiagnosticText.cannotBeApplied(targetText), getDiagnosticMessageText(diagnostic)];
|
|
4159
4262
|
const origin = DiagnosticOrigin.fromNode(sourceNode);
|
|
@@ -4179,7 +4282,7 @@ class ToBeApplicable {
|
|
|
4179
4282
|
}
|
|
4180
4283
|
return {
|
|
4181
4284
|
explain: () => this.#explain(matchWorker, sourceNode),
|
|
4182
|
-
isMatch:
|
|
4285
|
+
isMatch: matchWorker.assertion.abilityDiagnostics.size === 0,
|
|
4183
4286
|
};
|
|
4184
4287
|
}
|
|
4185
4288
|
}
|
|
@@ -4224,7 +4327,7 @@ class AbilityMatcherBase {
|
|
|
4224
4327
|
const isExpression = nodeBelongsToArgumentList(this.compiler, sourceNode);
|
|
4225
4328
|
const targetText = this.#resolveTargetText(targetNodes);
|
|
4226
4329
|
const diagnostics = [];
|
|
4227
|
-
if (matchWorker.assertion.abilityDiagnostics) {
|
|
4330
|
+
if (matchWorker.assertion.abilityDiagnostics.size > 0) {
|
|
4228
4331
|
for (const diagnostic of matchWorker.assertion.abilityDiagnostics) {
|
|
4229
4332
|
let origin;
|
|
4230
4333
|
const text = [];
|
|
@@ -4289,7 +4392,7 @@ class ToBeCallableWith extends AbilityMatcherBase {
|
|
|
4289
4392
|
}
|
|
4290
4393
|
return {
|
|
4291
4394
|
explain: () => this.explain(matchWorker, sourceNode, targetNodes),
|
|
4292
|
-
isMatch:
|
|
4395
|
+
isMatch: matchWorker.assertion.abilityDiagnostics.size === 0,
|
|
4293
4396
|
};
|
|
4294
4397
|
}
|
|
4295
4398
|
}
|
|
@@ -4324,7 +4427,7 @@ class ToBeConstructableWith extends AbilityMatcherBase {
|
|
|
4324
4427
|
}
|
|
4325
4428
|
return {
|
|
4326
4429
|
explain: () => this.explain(matchWorker, sourceNode, targetNodes),
|
|
4327
|
-
isMatch:
|
|
4430
|
+
isMatch: matchWorker.assertion.abilityDiagnostics.size === 0,
|
|
4328
4431
|
};
|
|
4329
4432
|
}
|
|
4330
4433
|
}
|
|
@@ -4631,7 +4734,7 @@ class WhenService {
|
|
|
4631
4734
|
this.#onActionIsNotSupported(actionNameText, when, this.#onDiagnostics);
|
|
4632
4735
|
return;
|
|
4633
4736
|
}
|
|
4634
|
-
if (when.abilityDiagnostics
|
|
4737
|
+
if (when.abilityDiagnostics.size > 0) {
|
|
4635
4738
|
const diagnostics = [];
|
|
4636
4739
|
for (const diagnostic of when.abilityDiagnostics) {
|
|
4637
4740
|
if (isDiagnosticWithLocation(diagnostic)) {
|
|
@@ -4827,8 +4930,9 @@ class TestTreeWalker {
|
|
|
4827
4930
|
class TaskRunner {
|
|
4828
4931
|
#collectService;
|
|
4829
4932
|
#compiler;
|
|
4830
|
-
#resolvedConfig;
|
|
4831
4933
|
#projectService;
|
|
4934
|
+
#resolvedConfig;
|
|
4935
|
+
#suppressedService = new SuppressedService();
|
|
4832
4936
|
constructor(compiler, resolvedConfig) {
|
|
4833
4937
|
this.#compiler = compiler;
|
|
4834
4938
|
this.#resolvedConfig = resolvedConfig;
|
|
@@ -4869,6 +4973,11 @@ class TaskRunner {
|
|
|
4869
4973
|
if (inlineConfig?.if?.target != null && !Version.isIncluded(this.#compiler.version, inlineConfig.if.target)) {
|
|
4870
4974
|
runMode |= RunMode.Skip;
|
|
4871
4975
|
}
|
|
4976
|
+
if (testTree.suppressedErrors != null) {
|
|
4977
|
+
this.#suppressedService.match(testTree.suppressedErrors, (diagnostics) => {
|
|
4978
|
+
this.#onDiagnostics(diagnostics, taskResult);
|
|
4979
|
+
});
|
|
4980
|
+
}
|
|
4872
4981
|
if (inlineConfig?.template) {
|
|
4873
4982
|
if (semanticDiagnostics != null && semanticDiagnostics.length > 0) {
|
|
4874
4983
|
this.#onDiagnostics(Diagnostic.fromDiagnostics(semanticDiagnostics), taskResult);
|
|
@@ -4913,7 +5022,7 @@ class TaskRunner {
|
|
|
4913
5022
|
class Runner {
|
|
4914
5023
|
#eventEmitter = new EventEmitter();
|
|
4915
5024
|
#resolvedConfig;
|
|
4916
|
-
static version = "4.0
|
|
5025
|
+
static version = "4.1.0";
|
|
4917
5026
|
constructor(resolvedConfig) {
|
|
4918
5027
|
this.#resolvedConfig = resolvedConfig;
|
|
4919
5028
|
}
|
|
@@ -5113,4 +5222,4 @@ class Cli {
|
|
|
5113
5222
|
}
|
|
5114
5223
|
}
|
|
5115
5224
|
|
|
5116
|
-
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 };
|
|
5225
|
+
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, SuppressedService, 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 };
|