@@ -25,27 +25,14 @@ import { Version } from "../../src/utilities/version";
2525import { folderContextPromise , globalWorkspaceContextPromise } from "./extension.test" ;
2626import { 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
5037const 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,53 @@ 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+ | {
83+ [ uri : string ] : vscode . Diagnostic [ ] ;
84+ }
85+ | undefined ;
86+
87+ // Wait for all the expected diagnostics to be recieved. This may happen over several `onChangeDiagnostics` events.
88+ const waitForDiagnostics = ( expectedDiagnostics : { [ uri : string ] : vscode . Diagnostic [ ] } ) => {
89+ return new Promise < void > ( resolve => {
90+ if ( diagnosticWaiterDisposable ) {
91+ console . warn (
92+ "Wait for diagnostics was called before the previous wait was resolved. Only one waitForDiagnostics should run per test."
93+ ) ;
94+ diagnosticWaiterDisposable ?. dispose ( ) ;
95+ }
96+ // Keep a lookup of diagnostics we haven't encountered yet. When all array values in
97+ // this lookup are empty then we've seen all diagnostics and we can resolve successfully.
98+ const expected = { ...expectedDiagnostics } ;
99+ diagnosticWaiterDisposable = vscode . languages . onDidChangeDiagnostics ( e => {
100+ const matchingPaths = Object . keys ( expectedDiagnostics ) . filter ( uri =>
101+ e . uris . some ( u => u . fsPath === uri )
102+ ) ;
103+ for ( const uri of matchingPaths ) {
104+ const actualDiagnostics = vscode . languages . getDiagnostics ( vscode . Uri . file ( uri ) ) ;
105+ expected [ uri ] = expected [ uri ] . filter ( expectedDiagnostic => {
106+ return ! actualDiagnostics . some ( actualDiagnostic =>
107+ isEqual ( actualDiagnostic , expectedDiagnostic )
108+ ) ;
109+ } ) ;
110+ remainingExpectedDiagnostics = expected ;
111+ }
112+
113+ const allDiagnosticsFulfilled = Object . values ( expected ) . every (
114+ diagnostics => diagnostics . length === 0
115+ ) ;
116+
117+ if ( allDiagnosticsFulfilled ) {
118+ diagnosticWaiterDisposable ?. dispose ( ) ;
119+ resolve ( ) ;
120+ }
121+ } ) ;
122+ } ) ;
123+ } ;
93124
94125 suiteSetup ( async function ( ) {
95- this . timeout ( 30000 ) ;
126+ this . timeout ( 60000 ) ;
96127
97128 workspaceContext = await globalWorkspaceContextPromise ;
98129 toolchain = workspaceContext . toolchain ;
@@ -111,7 +142,24 @@ suite("DiagnosticsManager Test Suite", async function () {
111142 ) ;
112143 } ) ;
113144
114- suite ( "Parse diagnostics" , async ( ) => {
145+ teardown ( function ( ) {
146+ diagnosticWaiterDisposable ?. dispose ( ) ;
147+ const allDiagnosticsFulfilled = Object . values ( remainingExpectedDiagnostics ?? { } ) . every (
148+ diagnostics => diagnostics . length === 0
149+ ) ;
150+ if ( ! allDiagnosticsFulfilled ) {
151+ const title = this . currentTest ?. fullTitle ( ) ?? "<unknown test>" ;
152+ const remainingDiagnostics = Object . entries ( remainingExpectedDiagnostics ?? { } ) . filter (
153+ ( [ _uri , diagnostics ] ) => diagnostics . length > 0
154+ ) ;
155+ console . error (
156+ `${ title } - Not all diagnostics were fulfilled` ,
157+ JSON . stringify ( remainingDiagnostics , undefined , " " )
158+ ) ;
159+ }
160+ } ) ;
161+
162+ suite . only ( "Parse diagnostics" , async ( ) => {
115163 suite ( "Parse from task output" , async ( ) => {
116164 const expectedWarningDiagnostic = new vscode . Diagnostic (
117165 new vscode . Range ( new vscode . Position ( 1 , 8 ) , new vscode . Position ( 1 , 8 ) ) ,
@@ -154,19 +202,17 @@ suite("DiagnosticsManager Test Suite", async function () {
154202
155203 test ( "default diagnosticsStyle" , async ( ) => {
156204 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 ( ) ;
163205
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
206+ await Promise . all ( [
207+ executeTaskAndWaitForResult ( createBuildAllTask ( folderContext ) ) ,
208+ waitForDiagnostics ( {
209+ [ mainUri . fsPath ] : [ expectedWarningDiagnostic , expectedMainErrorDiagnostic ] , // Should have parsed correct severity
210+ [ funcUri . fsPath ] : [ expectedFuncErrorDiagnostic ] , // Check parsed for other file
211+ } ) ,
212+ ] ) ;
213+
214+ await waitForNoRunningTasks ( ) ;
215+ } ) ;
170216
171217 test ( "swift diagnosticsStyle" , async function ( ) {
172218 // This is only supported in swift versions >=5.10.0
@@ -176,31 +222,29 @@ suite("DiagnosticsManager Test Suite", async function () {
176222 return ;
177223 }
178224 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 ;
225+ await Promise . all ( [
226+ executeTaskAndWaitForResult ( createBuildAllTask ( folderContext ) ) ,
227+ waitForDiagnostics ( {
228+ [ mainUri . fsPath ] : [ expectedWarningDiagnostic , expectedMainErrorDiagnostic ] , // Should have parsed correct severity
229+ [ funcUri . fsPath ] : [ expectedFuncErrorDiagnostic ] , // Check parsed for other file
230+ } ) ,
231+ ] ) ;
184232 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
233+ } ) ;
192234
193235 test ( "llvm diagnosticsStyle" , async ( ) => {
194236 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 ;
237+
238+ await Promise . all ( [
239+ executeTaskAndWaitForResult ( createBuildAllTask ( folderContext ) ) ,
240+ waitForDiagnostics ( {
241+ [ mainUri . fsPath ] : [ expectedWarningDiagnostic , expectedMainErrorDiagnostic ] , // Should have parsed correct severity
242+ [ funcUri . fsPath ] : [ expectedFuncErrorDiagnostic ] , // Check parsed for other file
243+ } ) ,
244+ ] ) ;
200245 await waitForNoRunningTasks ( ) ;
201246
202247 // Should have parsed severity
203- assertHasDiagnostic ( mainUri , expectedWarningDiagnostic ) ;
204248 const diagnostic = assertHasDiagnostic ( mainUri , expectedMainErrorDiagnostic ) ;
205249 // Should have parsed related note
206250 assert . equal ( diagnostic . relatedInformation ?. length , 1 ) ;
@@ -215,9 +259,7 @@ suite("DiagnosticsManager Test Suite", async function () {
215259 ) ,
216260 true
217261 ) ;
218- // Check parsed for other file
219- assertHasDiagnostic ( funcUri , expectedFuncErrorDiagnostic ) ;
220- } ) . timeout ( 2 * 60 * 1000 ) ; // Allow 2 minutes to build
262+ } ) ;
221263
222264 test ( "Parses C diagnostics" , async function ( ) {
223265 const swiftVersion = workspaceContext . toolchain . swiftVersion ;
@@ -228,12 +270,6 @@ suite("DiagnosticsManager Test Suite", async function () {
228270 }
229271
230272 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 ( ) ;
237273
238274 // Should have parsed severity
239275 const expectedDiagnostic1 = new vscode . Diagnostic (
@@ -249,8 +285,13 @@ suite("DiagnosticsManager Test Suite", async function () {
249285 ) ;
250286 expectedDiagnostic2 . source = "swiftc" ;
251287
252- assertHasDiagnostic ( cUri , expectedDiagnostic1 ) ;
253- assertHasDiagnostic ( cUri , expectedDiagnostic2 ) ;
288+ await Promise . all ( [
289+ executeTaskAndWaitForResult ( createBuildAllTask ( cFolderContext ) ) ,
290+ waitForDiagnostics ( {
291+ [ cUri . fsPath ] : [ expectedDiagnostic1 , expectedDiagnostic2 ] ,
292+ } ) ,
293+ ] ) ;
294+ await waitForNoRunningTasks ( ) ;
254295 } ) ;
255296
256297 test ( "Parses C++ diagnostics" , async function ( ) {
@@ -262,12 +303,6 @@ suite("DiagnosticsManager Test Suite", async function () {
262303 }
263304
264305 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 ( ) ;
271306
272307 // Should have parsed severity
273308 const expectedDiagnostic1 = new vscode . Diagnostic (
@@ -276,7 +311,6 @@ suite("DiagnosticsManager Test Suite", async function () {
276311 vscode . DiagnosticSeverity . Error
277312 ) ;
278313 expectedDiagnostic1 . source = "swiftc" ;
279- assertHasDiagnostic ( cppUri , expectedDiagnostic1 ) ;
280314
281315 // Should have parsed releated information
282316 const expectedDiagnostic2 = new vscode . Diagnostic (
@@ -285,6 +319,15 @@ suite("DiagnosticsManager Test Suite", async function () {
285319 vscode . DiagnosticSeverity . Error
286320 ) ;
287321 expectedDiagnostic2 . source = "swiftc" ;
322+
323+ await Promise . all ( [
324+ executeTaskAndWaitForResult ( createBuildAllTask ( cppFolderContext ) ) ,
325+ waitForDiagnostics ( {
326+ [ cppUri . fsPath ] : [ expectedDiagnostic1 , expectedDiagnostic2 ] ,
327+ } ) ,
328+ ] ) ;
329+ await waitForNoRunningTasks ( ) ;
330+
288331 const diagnostic = assertHasDiagnostic ( cppUri , expectedDiagnostic2 ) ;
289332 assert . equal (
290333 diagnostic . relatedInformation ! [ 0 ] . location . uri . fsPath ,
@@ -315,7 +358,7 @@ suite("DiagnosticsManager Test Suite", async function () {
315358 test ( "Parse partial line" , async ( ) => {
316359 const fixture = testSwiftTask ( "swift" , [ "build" ] , workspaceFolder , toolchain ) ;
317360 await vscode . tasks . executeTask ( fixture . task ) ;
318- const diagnosticsPromise = waitForDiagnostics ( [ mainUri ] ) ;
361+ const diagnosticsPromise = Promise . resolve ( ) ; // waitForDiagnostics([mainUri]);
319362 // Wait to spawn before writing
320363 fixture . process . write ( `${ mainUri . fsPath } :13:5: err` , "" ) ;
321364 fixture . process . write ( "or: Cannot find 'fo" , "" ) ;
@@ -331,7 +374,7 @@ suite("DiagnosticsManager Test Suite", async function () {
331374 test ( "Ignore duplicates" , async ( ) => {
332375 const fixture = testSwiftTask ( "swift" , [ "build" ] , workspaceFolder , toolchain ) ;
333376 await vscode . tasks . executeTask ( fixture . task ) ;
334- const diagnosticsPromise = waitForDiagnostics ( [ mainUri ] ) ;
377+ const diagnosticsPromise = Promise . resolve ( ) ; // waitForDiagnostics([mainUri]);
335378 // Wait to spawn before writing
336379 const output = `${ mainUri . fsPath } :13:5: error: Cannot find 'foo' in scope` ;
337380 fixture . process . write ( output ) ;
@@ -349,7 +392,7 @@ suite("DiagnosticsManager Test Suite", async function () {
349392 test ( "New set of swiftc diagnostics clear old list" , async ( ) => {
350393 let fixture = testSwiftTask ( "swift" , [ "build" ] , workspaceFolder , toolchain ) ;
351394 await vscode . tasks . executeTask ( fixture . task ) ;
352- let diagnosticsPromise = waitForDiagnostics ( [ mainUri ] ) ;
395+ let diagnosticsPromise = Promise . resolve ( ) ; // waitForDiagnostics([mainUri]);
353396 // Wait to spawn before writing
354397 fixture . process . write ( `${ mainUri . fsPath } :13:5: error: Cannot find 'foo' in scope` ) ;
355398 fixture . process . close ( 1 ) ;
@@ -363,7 +406,7 @@ suite("DiagnosticsManager Test Suite", async function () {
363406 // Run again but no diagnostics returned
364407 fixture = testSwiftTask ( "swift" , [ "build" ] , workspaceFolder , toolchain ) ;
365408 await vscode . tasks . executeTask ( fixture . task ) ;
366- diagnosticsPromise = waitForDiagnostics ( [ mainUri ] ) ;
409+ diagnosticsPromise = Promise . resolve ( ) ; // waitForDiagnostics([mainUri]);
367410 fixture . process . close ( 0 ) ;
368411 await waitForNoRunningTasks ( ) ;
369412 await diagnosticsPromise ;
@@ -920,7 +963,7 @@ suite("DiagnosticsManager Test Suite", async function () {
920963 await executeTaskAndWaitForResult ( task ) ;
921964
922965 // Open file
923- const promise = waitForDiagnostics ( [ mainUri ] , false ) ;
966+ const promise = Promise . resolve ( ) ; // waitForDiagnostics([mainUri], false);
924967 const document = await vscode . workspace . openTextDocument ( mainUri ) ;
925968 await vscode . languages . setTextDocumentLanguage ( document , "swift" ) ;
926969 await vscode . window . showTextDocument ( document ) ;
@@ -961,7 +1004,7 @@ suite("DiagnosticsManager Test Suite", async function () {
9611004 await executeTaskAndWaitForResult ( task ) ;
9621005
9631006 // Open file
964- const promise = waitForDiagnostics ( [ cUri ] , false ) ;
1007+ const promise = Promise . resolve ( ) ; // waitForDiagnostics([cUri], false);
9651008 const document = await vscode . workspace . openTextDocument ( cUri ) ;
9661009 await vscode . languages . setTextDocumentLanguage ( document , "c" ) ;
9671010 await vscode . window . showTextDocument ( document ) ;
0 commit comments