Skip to content

Commit a632861

Browse files
committed
Debug diagnostics tests
1 parent edbf32f commit a632861

File tree

4 files changed

+138
-81
lines changed

4 files changed

+138
-81
lines changed

.vscode-test.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
const { defineConfig } = require("@vscode/test-cli");
1616
const path = require("path");
1717

18-
const isCIBuild = process.env["CI"] === "1";
18+
const isCIBuild = false; // process.env["CI"] === "1";
1919
const isFastTestRun = process.env["FAST_TEST_RUN"] === "1";
2020

2121
// "env" in launch.json doesn't seem to work with vscode-test

src/DiagnosticsManager.ts

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -87,13 +87,19 @@ export class DiagnosticsManager implements vscode.Disposable {
8787
.then(map => {
8888
// Clean up old "swiftc" diagnostics
8989
this.removeSwiftcDiagnostics();
90-
map.forEach((diagnostics, uri) =>
90+
map.forEach((diagnostics, uri) => {
91+
console.log(
92+
">>> PROVIDED DIAGNOSTIC!",
93+
uri,
94+
"::",
95+
JSON.stringify(diagnostics)
96+
);
9197
this.handleDiagnostics(
9298
vscode.Uri.file(uri),
9399
DiagnosticsManager.isSwiftc,
94100
diagnostics
95-
)
96-
);
101+
);
102+
});
97103
})
98104
.catch(e =>
99105
context.outputChannel.log(`${e}`, 'Failed to provide "swiftc" diagnostics')
@@ -319,9 +325,12 @@ export class DiagnosticsManager implements vscode.Disposable {
319325
): ParsedDiagnostic | vscode.DiagnosticRelatedInformation | undefined {
320326
const diagnosticRegex = /^(.*?):(\d+)(?::(\d+))?:\s+(warning|error|note):\s+([^\\[]*)/g;
321327
const match = diagnosticRegex.exec(line);
328+
console.log(">>> CHECK LINE", line);
322329
if (!match) {
330+
console.log(">>> NO MATCH", line);
323331
return;
324332
}
333+
console.log(">>> MATCH", match);
325334
const uri = match[1];
326335
const message = this.capitalize(match[5]).trim();
327336
const range = this.range(match[2], match[3]);

src/tasks/SwiftProcess.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,13 @@ export class SwiftPtyProcess implements SwiftProcess {
9898
// The pty process hangs on Windows when debugging the extension if we use conpty
9999
// See https://github.com/microsoft/node-pty/issues/640
100100
const useConpty = isWindows && process.env["VSCODE_DEBUG"] === "1" ? false : true;
101+
console.log(
102+
">>> COLS: ",
103+
isWindows,
104+
useConpty,
105+
process.env["VSCODE_DEBUG"],
106+
!isWindows || useConpty ? undefined : 2147483647
107+
);
101108
this.spawnedProcess = spawn(this.command, this.args, {
102109
cwd: this.options.cwd,
103110
env: { ...process.env, ...this.options.env },

test/integration-tests/DiagnosticsManager.test.ts

Lines changed: 118 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -25,27 +25,14 @@ import { Version } from "../../src/utilities/version";
2525
import { folderContextPromise, globalWorkspaceContextPromise } from "./extension.test";
2626
import { Workbench } from "../../src/utilities/commands";
2727

28-
const waitForDiagnostics = (uris: vscode.Uri[], allowEmpty: boolean = true) =>
29-
new Promise<void>(res =>
30-
vscode.languages.onDidChangeDiagnostics(e => {
31-
const paths = e.uris.map(u => u.fsPath);
32-
for (const uri of uris) {
33-
if (!paths.includes(uri.fsPath)) {
34-
return;
35-
}
36-
if (!allowEmpty && !vscode.languages.getDiagnostics(uri).length) {
37-
return;
38-
}
39-
}
40-
res();
41-
})
28+
const isEqual = (d1: vscode.Diagnostic, d2: vscode.Diagnostic) => {
29+
return (
30+
d1.severity === d2.severity &&
31+
d1.source === d2.source &&
32+
d1.message === d2.message &&
33+
d1.range.isEqual(d2.range)
4234
);
43-
44-
const isEqual = (d1: vscode.Diagnostic, d2: vscode.Diagnostic) =>
45-
d1.severity === d2.severity &&
46-
d1.source === d2.source &&
47-
d1.message === d2.message &&
48-
d1.range.isEqual(d2.range);
35+
};
4936

5037
const findDiagnostic = (expected: vscode.Diagnostic) => (d: vscode.Diagnostic) =>
5138
isEqual(d, expected);
@@ -56,7 +43,7 @@ function assertHasDiagnostic(uri: vscode.Uri, expected: vscode.Diagnostic): vsco
5643
assert.notEqual(
5744
diagnostic,
5845
undefined,
59-
`Could not find diagnostic matching:\n${JSON.stringify(expected)}`
46+
`Could not find diagnostic matching:\n${JSON.stringify(expected)}\nDiagnostics found:\n${JSON.stringify(diagnostics)}`
6047
);
6148
return diagnostic!;
6249
}
@@ -90,9 +77,51 @@ suite("DiagnosticsManager Test Suite", async function () {
9077
let cUri: vscode.Uri;
9178
let cppUri: vscode.Uri;
9279
let cppHeaderUri: vscode.Uri;
80+
let diagnosticWaiterDisposable: vscode.Disposable | undefined;
81+
let remainingExpectedDiagnostics: {
82+
[uri: string]: vscode.Diagnostic[];
83+
};
84+
85+
// Wait for all the expected diagnostics to be recieved. This may happen over several `onChangeDiagnostics` events.
86+
const waitForDiagnostics = (expectedDiagnostics: { [uri: string]: vscode.Diagnostic[] }) => {
87+
return new Promise<void>(resolve => {
88+
if (diagnosticWaiterDisposable) {
89+
console.warn(
90+
"Wait for diagnostics was called before the previous wait was resolved. Only one waitForDiagnostics should run per test."
91+
);
92+
diagnosticWaiterDisposable?.dispose();
93+
}
94+
// Keep a lookup of diagnostics we haven't encountered yet. When all array values in
95+
// this lookup are empty then we've seen all diagnostics and we can resolve successfully.
96+
const expected = { ...expectedDiagnostics };
97+
diagnosticWaiterDisposable = vscode.languages.onDidChangeDiagnostics(e => {
98+
const matchingPaths = Object.keys(expectedDiagnostics).filter(uri =>
99+
e.uris.some(u => u.fsPath === uri)
100+
);
101+
for (const uri of matchingPaths) {
102+
const actualDiagnostics = vscode.languages.getDiagnostics(vscode.Uri.file(uri));
103+
expected[uri] = expected[uri].filter(expectedDiagnostic => {
104+
return !actualDiagnostics.some(actualDiagnostic =>
105+
isEqual(actualDiagnostic, expectedDiagnostic)
106+
);
107+
});
108+
remainingExpectedDiagnostics = expected;
109+
}
110+
111+
const allDiagnosticsFulfilled = Object.values(expected).every(
112+
diagnostics => diagnostics.length === 0
113+
);
114+
115+
if (allDiagnosticsFulfilled) {
116+
diagnosticWaiterDisposable?.dispose();
117+
resolve();
118+
}
119+
});
120+
});
121+
};
93122

94123
suiteSetup(async function () {
95-
this.timeout(30000);
124+
this.timeout(60000);
96125

97126
workspaceContext = await globalWorkspaceContextPromise;
98127
toolchain = workspaceContext.toolchain;
@@ -111,6 +140,23 @@ suite("DiagnosticsManager Test Suite", async function () {
111140
);
112141
});
113142

143+
teardown(function () {
144+
diagnosticWaiterDisposable?.dispose();
145+
const allDiagnosticsFulfilled = Object.values(remainingExpectedDiagnostics).every(
146+
diagnostics => diagnostics.length === 0
147+
);
148+
if (!allDiagnosticsFulfilled) {
149+
const title = this.currentTest?.fullTitle() ?? "<unknown test>";
150+
const remainingDiagnostics = Object.entries(remainingExpectedDiagnostics).filter(
151+
([_uri, diagnostics]) => diagnostics.length > 0
152+
);
153+
console.error(
154+
`${title} - Not all diagnostics were fulfilled`,
155+
JSON.stringify(remainingDiagnostics, undefined, " ")
156+
);
157+
}
158+
});
159+
114160
suite("Parse diagnostics", async () => {
115161
suite("Parse from task output", async () => {
116162
const expectedWarningDiagnostic = new vscode.Diagnostic(
@@ -152,21 +198,19 @@ suite("DiagnosticsManager Test Suite", async function () {
152198
await swiftConfig.update("diagnosticsStyle", undefined);
153199
});
154200

155-
test("default diagnosticsStyle", async () => {
201+
test.only("default diagnosticsStyle", async () => {
156202
await swiftConfig.update("diagnosticsStyle", "default");
157-
const task = createBuildAllTask(folderContext);
158-
// Run actual task
159-
const promise = waitForDiagnostics([mainUri, funcUri]);
160-
await executeTaskAndWaitForResult(task);
161-
await promise;
162-
await waitForNoRunningTasks();
163203

164-
// Should have parsed correct severity
165-
assertHasDiagnostic(mainUri, expectedWarningDiagnostic);
166-
assertHasDiagnostic(mainUri, expectedMainErrorDiagnostic);
167-
// Check parsed for other file
168-
assertHasDiagnostic(funcUri, expectedFuncErrorDiagnostic);
169-
}).timeout(2 * 60 * 1000); // Allow 2 minutes to build
204+
await Promise.all([
205+
executeTaskAndWaitForResult(createBuildAllTask(folderContext)),
206+
waitForDiagnostics({
207+
[mainUri.fsPath]: [expectedWarningDiagnostic, expectedMainErrorDiagnostic], // Should have parsed correct severity
208+
[funcUri.fsPath]: [expectedFuncErrorDiagnostic], // Check parsed for other file
209+
}),
210+
]);
211+
212+
await waitForNoRunningTasks();
213+
});
170214

171215
test("swift diagnosticsStyle", async function () {
172216
// This is only supported in swift versions >=5.10.0
@@ -176,31 +220,29 @@ suite("DiagnosticsManager Test Suite", async function () {
176220
return;
177221
}
178222
await swiftConfig.update("diagnosticsStyle", "swift");
179-
const task = createBuildAllTask(folderContext);
180-
// Run actual task
181-
const promise = waitForDiagnostics([mainUri, funcUri]);
182-
await executeTaskAndWaitForResult(task);
183-
await promise;
223+
await Promise.all([
224+
executeTaskAndWaitForResult(createBuildAllTask(folderContext)),
225+
waitForDiagnostics({
226+
[mainUri.fsPath]: [expectedWarningDiagnostic, expectedMainErrorDiagnostic], // Should have parsed correct severity
227+
[funcUri.fsPath]: [expectedFuncErrorDiagnostic], // Check parsed for other file
228+
}),
229+
]);
184230
await waitForNoRunningTasks();
185-
186-
// Should have parsed severity
187-
assertHasDiagnostic(mainUri, expectedWarningDiagnostic);
188-
assertHasDiagnostic(mainUri, expectedMainErrorDiagnostic);
189-
// Check parsed for other file
190-
assertHasDiagnostic(funcUri, expectedFuncErrorDiagnostic);
191-
}).timeout(2 * 60 * 1000); // Allow 2 minutes to build
231+
});
192232

193233
test("llvm diagnosticsStyle", async () => {
194234
await swiftConfig.update("diagnosticsStyle", "llvm");
195-
const task = createBuildAllTask(folderContext);
196-
// Run actual task
197-
const promise = waitForDiagnostics([mainUri, funcUri]);
198-
await executeTaskAndWaitForResult(task);
199-
await promise;
235+
236+
await Promise.all([
237+
executeTaskAndWaitForResult(createBuildAllTask(folderContext)),
238+
waitForDiagnostics({
239+
[mainUri.fsPath]: [expectedWarningDiagnostic, expectedMainErrorDiagnostic], // Should have parsed correct severity
240+
[funcUri.fsPath]: [expectedFuncErrorDiagnostic], // Check parsed for other file
241+
}),
242+
]);
200243
await waitForNoRunningTasks();
201244

202245
// Should have parsed severity
203-
assertHasDiagnostic(mainUri, expectedWarningDiagnostic);
204246
const diagnostic = assertHasDiagnostic(mainUri, expectedMainErrorDiagnostic);
205247
// Should have parsed related note
206248
assert.equal(diagnostic.relatedInformation?.length, 1);
@@ -215,9 +257,7 @@ suite("DiagnosticsManager Test Suite", async function () {
215257
),
216258
true
217259
);
218-
// Check parsed for other file
219-
assertHasDiagnostic(funcUri, expectedFuncErrorDiagnostic);
220-
}).timeout(2 * 60 * 1000); // Allow 2 minutes to build
260+
});
221261

222262
test("Parses C diagnostics", async function () {
223263
const swiftVersion = workspaceContext.toolchain.swiftVersion;
@@ -228,12 +268,6 @@ suite("DiagnosticsManager Test Suite", async function () {
228268
}
229269

230270
await swiftConfig.update("diagnosticsStyle", "llvm");
231-
const task = createBuildAllTask(cFolderContext);
232-
// Run actual task
233-
const promise = waitForDiagnostics([cUri]);
234-
await executeTaskAndWaitForResult(task);
235-
await promise;
236-
await waitForNoRunningTasks();
237271

238272
// Should have parsed severity
239273
const expectedDiagnostic1 = new vscode.Diagnostic(
@@ -249,8 +283,13 @@ suite("DiagnosticsManager Test Suite", async function () {
249283
);
250284
expectedDiagnostic2.source = "swiftc";
251285

252-
assertHasDiagnostic(cUri, expectedDiagnostic1);
253-
assertHasDiagnostic(cUri, expectedDiagnostic2);
286+
await Promise.all([
287+
executeTaskAndWaitForResult(createBuildAllTask(cFolderContext)),
288+
waitForDiagnostics({
289+
[cUri.fsPath]: [expectedDiagnostic1, expectedDiagnostic2],
290+
}),
291+
]);
292+
await waitForNoRunningTasks();
254293
});
255294

256295
test("Parses C++ diagnostics", async function () {
@@ -262,12 +301,6 @@ suite("DiagnosticsManager Test Suite", async function () {
262301
}
263302

264303
await swiftConfig.update("diagnosticsStyle", "llvm");
265-
const task = createBuildAllTask(cppFolderContext);
266-
// Run actual task
267-
const promise = waitForDiagnostics([cppUri]);
268-
await executeTaskAndWaitForResult(task);
269-
await promise;
270-
await waitForNoRunningTasks();
271304

272305
// Should have parsed severity
273306
const expectedDiagnostic1 = new vscode.Diagnostic(
@@ -276,7 +309,6 @@ suite("DiagnosticsManager Test Suite", async function () {
276309
vscode.DiagnosticSeverity.Error
277310
);
278311
expectedDiagnostic1.source = "swiftc";
279-
assertHasDiagnostic(cppUri, expectedDiagnostic1);
280312

281313
// Should have parsed releated information
282314
const expectedDiagnostic2 = new vscode.Diagnostic(
@@ -285,6 +317,15 @@ suite("DiagnosticsManager Test Suite", async function () {
285317
vscode.DiagnosticSeverity.Error
286318
);
287319
expectedDiagnostic2.source = "swiftc";
320+
321+
await Promise.all([
322+
executeTaskAndWaitForResult(createBuildAllTask(cppFolderContext)),
323+
waitForDiagnostics({
324+
[cppUri.fsPath]: [expectedDiagnostic1, expectedDiagnostic2],
325+
}),
326+
]);
327+
await waitForNoRunningTasks();
328+
288329
const diagnostic = assertHasDiagnostic(cppUri, expectedDiagnostic2);
289330
assert.equal(
290331
diagnostic.relatedInformation![0].location.uri.fsPath,
@@ -315,7 +356,7 @@ suite("DiagnosticsManager Test Suite", async function () {
315356
test("Parse partial line", async () => {
316357
const fixture = testSwiftTask("swift", ["build"], workspaceFolder, toolchain);
317358
await vscode.tasks.executeTask(fixture.task);
318-
const diagnosticsPromise = waitForDiagnostics([mainUri]);
359+
const diagnosticsPromise = Promise.resolve(); // waitForDiagnostics([mainUri]);
319360
// Wait to spawn before writing
320361
fixture.process.write(`${mainUri.fsPath}:13:5: err`, "");
321362
fixture.process.write("or: Cannot find 'fo", "");
@@ -331,7 +372,7 @@ suite("DiagnosticsManager Test Suite", async function () {
331372
test("Ignore duplicates", async () => {
332373
const fixture = testSwiftTask("swift", ["build"], workspaceFolder, toolchain);
333374
await vscode.tasks.executeTask(fixture.task);
334-
const diagnosticsPromise = waitForDiagnostics([mainUri]);
375+
const diagnosticsPromise = Promise.resolve(); // waitForDiagnostics([mainUri]);
335376
// Wait to spawn before writing
336377
const output = `${mainUri.fsPath}:13:5: error: Cannot find 'foo' in scope`;
337378
fixture.process.write(output);
@@ -349,7 +390,7 @@ suite("DiagnosticsManager Test Suite", async function () {
349390
test("New set of swiftc diagnostics clear old list", async () => {
350391
let fixture = testSwiftTask("swift", ["build"], workspaceFolder, toolchain);
351392
await vscode.tasks.executeTask(fixture.task);
352-
let diagnosticsPromise = waitForDiagnostics([mainUri]);
393+
let diagnosticsPromise = Promise.resolve(); // waitForDiagnostics([mainUri]);
353394
// Wait to spawn before writing
354395
fixture.process.write(`${mainUri.fsPath}:13:5: error: Cannot find 'foo' in scope`);
355396
fixture.process.close(1);
@@ -363,7 +404,7 @@ suite("DiagnosticsManager Test Suite", async function () {
363404
// Run again but no diagnostics returned
364405
fixture = testSwiftTask("swift", ["build"], workspaceFolder, toolchain);
365406
await vscode.tasks.executeTask(fixture.task);
366-
diagnosticsPromise = waitForDiagnostics([mainUri]);
407+
diagnosticsPromise = Promise.resolve(); // waitForDiagnostics([mainUri]);
367408
fixture.process.close(0);
368409
await waitForNoRunningTasks();
369410
await diagnosticsPromise;
@@ -920,7 +961,7 @@ suite("DiagnosticsManager Test Suite", async function () {
920961
await executeTaskAndWaitForResult(task);
921962

922963
// Open file
923-
const promise = waitForDiagnostics([mainUri], false);
964+
const promise = Promise.resolve(); // waitForDiagnostics([mainUri], false);
924965
const document = await vscode.workspace.openTextDocument(mainUri);
925966
await vscode.languages.setTextDocumentLanguage(document, "swift");
926967
await vscode.window.showTextDocument(document);
@@ -961,7 +1002,7 @@ suite("DiagnosticsManager Test Suite", async function () {
9611002
await executeTaskAndWaitForResult(task);
9621003

9631004
// Open file
964-
const promise = waitForDiagnostics([cUri], false);
1005+
const promise = Promise.resolve(); // waitForDiagnostics([cUri], false);
9651006
const document = await vscode.workspace.openTextDocument(cUri);
9661007
await vscode.languages.setTextDocumentLanguage(document, "c");
9671008
await vscode.window.showTextDocument(document);

0 commit comments

Comments
 (0)