Skip to content

Commit 0473f45

Browse files
committed
Allow to specify expected diagnostic codes in matchers
1 parent e533ed7 commit 0473f45

File tree

7 files changed

+67
-40
lines changed

7 files changed

+67
-40
lines changed

src/transformation/utils/diagnostics.ts

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,18 +2,25 @@ import * as ts from "typescript";
22
import { LuaTarget } from "../../CompilerOptions";
33
import { AnnotationKind } from "./annotations";
44

5-
const createDiagnosticFactory = <TArgs extends any[]>(
5+
let diagnosticCodeCounter = 100000;
6+
const createDiagnosticFactory = <TArgs extends any[] = []>(
67
message: string | ((...args: TArgs) => string),
78
category = ts.DiagnosticCategory.Error
8-
) => (node: ts.Node, ...args: TArgs): ts.Diagnostic => ({
9-
file: node.getSourceFile(),
10-
start: node.getStart(),
11-
length: node.getWidth(),
12-
category,
13-
code: 0,
14-
source: "typescript-to-lua",
15-
messageText: typeof message === "string" ? message : message(...args),
16-
});
9+
) => {
10+
const code = diagnosticCodeCounter++;
11+
return Object.assign(
12+
(node: ts.Node, ...args: TArgs): ts.Diagnostic => ({
13+
file: node.getSourceFile(),
14+
start: node.getStart(),
15+
length: node.getWidth(),
16+
category,
17+
code,
18+
source: "typescript-to-lua",
19+
messageText: typeof message === "string" ? message : message(...args),
20+
}),
21+
{ code }
22+
);
23+
};
1724

1825
export const forbiddenForIn = createDiagnosticFactory(`Iterating over arrays with 'for ... in' is not allowed.`);
1926

test/setup.ts

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,13 @@ import * as tstl from "../src";
44
declare global {
55
namespace jest {
66
interface Matchers<R, T> {
7-
toHaveDiagnostics(): R;
7+
toHaveDiagnostics(expected?: number[]): R;
88
}
99
}
1010
}
1111

1212
expect.extend({
13-
toHaveDiagnostics(diagnostics: ts.Diagnostic[]): jest.CustomMatcherResult {
13+
toHaveDiagnostics(diagnostics: ts.Diagnostic[], expected?: number[]): jest.CustomMatcherResult {
1414
expect(diagnostics).toBeInstanceOf(Array);
1515
// @ts-ignore
1616
const matcherHint = this.utils.matcherHint("toHaveDiagnostics", undefined, "", this);
@@ -20,14 +20,24 @@ expect.extend({
2020
{ getCurrentDirectory: () => "", getCanonicalFileName: fileName => fileName, getNewLine: () => "\n" }
2121
);
2222

23+
if (this.isNot && expected !== undefined) {
24+
throw new Error(`expect(actual).not.toHaveDiagnostics(expected) is not supported`);
25+
}
26+
2327
return {
24-
pass: diagnostics.length > 0,
28+
pass: expected
29+
? diagnostics.length === expected.length &&
30+
diagnostics.every((diag, index) => diag.code === expected[index])
31+
: diagnostics.length > 0,
32+
2533
message: () => {
26-
return (
27-
matcherHint +
28-
"\n\n" +
29-
(this.isNot ? diagnosticMessages : `Received: ${this.utils.printReceived(diagnostics)}\n`)
30-
);
34+
const message = this.isNot
35+
? diagnosticMessages
36+
: expected
37+
? `Expected:\n${expected.join("\n")}\nReceived:\n${diagnosticMessages}\n`
38+
: `Received: ${this.utils.printReceived([])}\n`;
39+
40+
return matcherHint + "\n\n" + message;
3141
},
3242
};
3343
},

test/unit/bundle.spec.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ test("LuaLibImportKind.Inline generates a warning", () => {
9090
result.push(3);
9191
`
9292
.setOptions({ luaLibImport: LuaLibImportKind.Inline })
93-
.expectDiagnosticsToMatchSnapshot(true)
93+
.expectDiagnosticsToMatchSnapshot(undefined, true)
9494
.expectToEqual({ result: [1, 2, 3] });
9595
});
9696

@@ -113,9 +113,9 @@ test("cyclic imports", () => {
113113
});
114114

115115
test("no entry point", () => {
116-
util.testBundle``.setOptions({ luaBundleEntry: undefined }).expectDiagnosticsToMatchSnapshot(true);
116+
util.testBundle``.setOptions({ luaBundleEntry: undefined }).expectDiagnosticsToMatchSnapshot(undefined, true);
117117
});
118118

119119
test("luaEntry doesn't exist", () => {
120-
util.testBundle``.setEntryPoint("entry.ts").expectDiagnosticsToMatchSnapshot(true);
120+
util.testBundle``.setEntryPoint("entry.ts").expectDiagnosticsToMatchSnapshot(undefined, true);
121121
});

test/unit/functions/validation/invalidFunctionAssignments.spec.ts

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ test.each(invalidTestFunctionAssignments)(
77
util.testModule`
88
${testFunction.definition || ""}
99
const fn: ${functionType} = ${testFunction.value};
10-
`.expectDiagnosticsToMatchSnapshot(true);
10+
`.expectDiagnosticsToMatchSnapshot(undefined, true);
1111
}
1212
);
1313

@@ -16,47 +16,47 @@ test.each(invalidTestFunctionAssignments)("Invalid function assignment (%p)", (t
1616
${testFunction.definition || ""}
1717
let fn: ${functionType};
1818
fn = ${testFunction.value};
19-
`.expectDiagnosticsToMatchSnapshot(true);
19+
`.expectDiagnosticsToMatchSnapshot(undefined, true);
2020
});
2121

2222
test.each(invalidTestFunctionCasts)("Invalid function assignment with cast (%p)", (testFunction, castedFunction) => {
2323
util.testModule`
2424
${testFunction.definition || ""}
2525
let fn: typeof ${testFunction.value};
2626
fn = ${castedFunction};
27-
`.expectDiagnosticsToMatchSnapshot(true);
27+
`.expectDiagnosticsToMatchSnapshot(undefined, true);
2828
});
2929

3030
test.each(invalidTestFunctionAssignments)("Invalid function argument (%p)", (testFunction, functionType) => {
3131
util.testModule`
3232
${testFunction.definition || ""}
3333
declare function takesFunction(fn: ${functionType});
3434
takesFunction(${testFunction.value});
35-
`.expectDiagnosticsToMatchSnapshot(true);
35+
`.expectDiagnosticsToMatchSnapshot(undefined, true);
3636
});
3737

3838
test("Invalid lua lib function argument", () => {
3939
util.testModule`
4040
declare function foo(this: void, value: string): void;
4141
declare const a: string[];
4242
a.forEach(foo);
43-
`.expectDiagnosticsToMatchSnapshot(true);
43+
`.expectDiagnosticsToMatchSnapshot(undefined, true);
4444
});
4545

4646
test.each(invalidTestFunctionCasts)("Invalid function argument with cast (%p)", (testFunction, castedFunction) => {
4747
util.testModule`
4848
${testFunction.definition || ""}
4949
declare function takesFunction(fn: typeof ${testFunction.value});
5050
takesFunction(${castedFunction});
51-
`.expectDiagnosticsToMatchSnapshot(true);
51+
`.expectDiagnosticsToMatchSnapshot(undefined, true);
5252
});
5353

5454
test.each(invalidTestFunctionAssignments)("Invalid function generic argument (%p)", (testFunction, functionType) => {
5555
util.testModule`
5656
${testFunction.definition || ""}
5757
declare function takesFunction<T extends ${functionType}>(fn: T);
5858
takesFunction(${testFunction.value});
59-
`.expectDiagnosticsToMatchSnapshot(true);
59+
`.expectDiagnosticsToMatchSnapshot(undefined, true);
6060
});
6161

6262
test.each(invalidTestFunctionAssignments)("Invalid function return (%p)", (testFunction, functionType) => {
@@ -65,7 +65,7 @@ test.each(invalidTestFunctionAssignments)("Invalid function return (%p)", (testF
6565
function returnsFunction(): ${functionType} {
6666
return ${testFunction.value};
6767
}
68-
`.expectDiagnosticsToMatchSnapshot(true);
68+
`.expectDiagnosticsToMatchSnapshot(undefined, true);
6969
});
7070

7171
test.each(invalidTestFunctionCasts)("Invalid function return with cast (%p)", (testFunction, castedFunction) => {
@@ -74,7 +74,7 @@ test.each(invalidTestFunctionCasts)("Invalid function return with cast (%p)", (t
7474
function returnsFunction(): typeof ${testFunction.value} {
7575
return ${castedFunction};
7676
}
77-
`.expectDiagnosticsToMatchSnapshot(true);
77+
`.expectDiagnosticsToMatchSnapshot(undefined, true);
7878
});
7979

8080
test("Invalid function tuple assignment", () => {
@@ -83,7 +83,7 @@ test("Invalid function tuple assignment", () => {
8383
interface Meth { (this: {}, s: string): string; }
8484
declare function getTuple(): [number, Meth];
8585
let [i, f]: [number, Func] = getTuple();
86-
`.expectDiagnosticsToMatchSnapshot(true);
86+
`.expectDiagnosticsToMatchSnapshot(undefined, true);
8787
});
8888

8989
test("Invalid method tuple assignment", () => {
@@ -92,7 +92,7 @@ test("Invalid method tuple assignment", () => {
9292
interface Meth { (this: {}, s: string): string; }
9393
declare function getTuple(): [number, Func];
9494
let [i, f]: [number, Meth] = getTuple();
95-
`.expectDiagnosticsToMatchSnapshot(true);
95+
`.expectDiagnosticsToMatchSnapshot(undefined, true);
9696
});
9797

9898
test("Invalid interface method assignment", () => {
@@ -101,7 +101,7 @@ test("Invalid interface method assignment", () => {
101101
interface B { fn(this: void, s: string): string; }
102102
declare const a: A;
103103
const b: B = a;
104-
`.expectDiagnosticsToMatchSnapshot(true);
104+
`.expectDiagnosticsToMatchSnapshot(undefined, true);
105105
});
106106

107107
test.each([
@@ -117,5 +117,5 @@ test.each([
117117
}
118118
declare const o: O;
119119
let f: ${assignType} = o;
120-
`.expectDiagnosticsToMatchSnapshot(true);
120+
`.expectDiagnosticsToMatchSnapshot(undefined, true);
121121
});
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
// Jest Snapshot v1, https://goo.gl/fbAQLP
2+
3+
exports[`doesn't resolve paths out of root dir: code 1`] = `
4+
"local ____exports = {}
5+
local module = require(\\"../module\\")
6+
local ____ = module
7+
return ____exports"
8+
`;
9+
10+
exports[`doesn't resolve paths out of root dir: diagnostics 1`] = `"src/main.ts(2,33): error TSTL: Cannot create require path. Module '../module' does not exist within --rootDir."`;

test/unit/modules/resolution.spec.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ test("doesn't resolve paths out of root dir", () => {
8282
.setMainFileName("src/main.ts")
8383
.setOptions({ rootDir: "./src" })
8484
.disableSemanticCheck()
85-
.expectToHaveDiagnostics();
85+
.expectDiagnosticsToMatchSnapshot();
8686
});
8787

8888
test.each([

test/util.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import * as tstl from "../src";
99

1010
export * from "./legacy-utils";
1111

12-
export const nodeStub = ts.createNode(ts.SyntaxKind.Unknown);
12+
export const nodeStub = ts.createNode(ts.SyntaxKind.Unknown, 0, 0);
1313

1414
export function parseTypeScript(
1515
typescript: string,
@@ -362,11 +362,11 @@ export abstract class TestBuilder {
362362

363363
private diagnosticsChecked = false;
364364

365-
public expectToHaveDiagnostics(): this {
365+
public expectToHaveDiagnostics(expected?: number[]): this {
366366
if (this.diagnosticsChecked) return this;
367367
this.diagnosticsChecked = true;
368368

369-
expect(this.getLuaDiagnostics()).toHaveDiagnostics();
369+
expect(this.getLuaDiagnostics()).toHaveDiagnostics(expected);
370370
return this;
371371
}
372372

@@ -411,8 +411,8 @@ export abstract class TestBuilder {
411411
return this;
412412
}
413413

414-
public expectDiagnosticsToMatchSnapshot(diagnosticsOnly = false): this {
415-
this.expectToHaveDiagnostics();
414+
public expectDiagnosticsToMatchSnapshot(expected?: number[], diagnosticsOnly = false): this {
415+
this.expectToHaveDiagnostics(expected);
416416

417417
const diagnosticMessages = ts.formatDiagnostics(
418418
this.getLuaDiagnostics().map(tstl.prepareDiagnosticForFormatting),

0 commit comments

Comments
 (0)