@@ -25,22 +25,6 @@ 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- } )
42- ) ;
43-
4428const isEqual = ( d1 : vscode . Diagnostic , d2 : vscode . Diagnostic ) =>
4529 d1 . severity === d2 . severity &&
4630 d1 . source === d2 . source &&
@@ -56,7 +40,7 @@ function assertHasDiagnostic(uri: vscode.Uri, expected: vscode.Diagnostic): vsco
5640 assert . notEqual (
5741 diagnostic ,
5842 undefined ,
59- `Could not find diagnostic matching:\n${ JSON . stringify ( expected ) } `
43+ `Could not find diagnostic matching:\n${ JSON . stringify ( expected ) } \nDiagnostics found:\n ${ JSON . stringify ( diagnostics ) } `
6044 ) ;
6145 return diagnostic ! ;
6246}
@@ -90,9 +74,55 @@ suite("DiagnosticsManager Test Suite", async function () {
9074 let cUri : vscode . Uri ;
9175 let cppUri : vscode . Uri ;
9276 let cppHeaderUri : vscode . Uri ;
77+ let diagnosticWaiterDisposable : vscode . Disposable | undefined ;
78+
79+ // Wait for all the expected diagnostics to be recieved. This may happen over several `onChangeDiagnostics` events.
80+ const waitForDiagnostics = ( expectedDiagnostics : { [ uri : string ] : vscode . Diagnostic [ ] } ) => {
81+ return new Promise < void > ( resolve => {
82+ if ( diagnosticWaiterDisposable ) {
83+ console . warn (
84+ "Wait for diagnostics was called before the previous wait was resolved. Only one waitForDiagnostics should run per test."
85+ ) ;
86+ diagnosticWaiterDisposable ?. dispose ( ) ;
87+ }
88+ // Keep a lookup of diagnostics we haven't encountered yet. When all array values in
89+ // this lookup are empty then we've seen all diagnostics and we can resolve successfully.
90+ const expected = { ...expectedDiagnostics } ;
91+ diagnosticWaiterDisposable = vscode . languages . onDidChangeDiagnostics ( e => {
92+ console . log ( ">>> DiagnosticManager.test.ts: onDidChangeDiagnostics" , e . uris ) ;
93+
94+ const matchingPaths = Object . keys ( expectedDiagnostics ) . filter ( uri =>
95+ e . uris . some ( u => u . fsPath === uri )
96+ ) ;
97+ console . log ( ">>> Got diag for matching paths" , matchingPaths ) ;
98+ for ( const uri of matchingPaths ) {
99+ const actualDiagnostics = vscode . languages . getDiagnostics (
100+ vscode . Uri . parse ( uri )
101+ ) ;
102+ console . log ( ">>> " , uri , "Actual diagnostics" , actualDiagnostics ) ;
103+ console . log ( ">>> " , uri , "before" , expected [ uri ] . length ) ;
104+ expected [ uri ] = expected [ uri ] . filter ( expectedDiagnostic => {
105+ return ! actualDiagnostics . some ( actualDiagnostic =>
106+ isEqual ( actualDiagnostic , expectedDiagnostic )
107+ ) ;
108+ } ) ;
109+ console . log ( ">>> " , uri , "after" , expected [ uri ] . length ) ;
110+ }
111+
112+ const allDiagnosticsFulfilled = Object . values ( expected ) . every (
113+ diagnostics => diagnostics . length === 0
114+ ) ;
115+
116+ if ( allDiagnosticsFulfilled ) {
117+ diagnosticWaiterDisposable ?. dispose ( ) ;
118+ resolve ( ) ;
119+ }
120+ } ) ;
121+ } ) ;
122+ } ;
93123
94124 suiteSetup ( async function ( ) {
95- this . timeout ( 30000 ) ;
125+ this . timeout ( 60000 ) ;
96126
97127 workspaceContext = await globalWorkspaceContextPromise ;
98128 toolchain = workspaceContext . toolchain ;
@@ -111,6 +141,10 @@ suite("DiagnosticsManager Test Suite", async function () {
111141 ) ;
112142 } ) ;
113143
144+ teardown ( ( ) => {
145+ diagnosticWaiterDisposable ?. dispose ( ) ;
146+ } ) ;
147+
114148 suite ( "Parse diagnostics" , async ( ) => {
115149 suite ( "Parse from task output" , async ( ) => {
116150 const expectedWarningDiagnostic = new vscode . Diagnostic (
@@ -152,21 +186,22 @@ suite("DiagnosticsManager Test Suite", async function () {
152186 await swiftConfig . update ( "diagnosticsStyle" , undefined ) ;
153187 } ) ;
154188
155- test ( "default diagnosticsStyle" , async ( ) => {
189+ test . only ( "default diagnosticsStyle" , async ( ) => {
190+ console . log ( ">>> Updating diagnosticsStyle to default" ) ;
156191 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 ( ) ;
163192
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
193+ console . log ( ">>> Running actual task and waiting for diagnostics" ) ;
194+ await Promise . all ( [
195+ executeTaskAndWaitForResult ( createBuildAllTask ( folderContext ) ) ,
196+ waitForDiagnostics ( {
197+ [ mainUri . fsPath ] : [ expectedWarningDiagnostic , expectedMainErrorDiagnostic ] , // Should have parsed correct severity
198+ [ funcUri . fsPath ] : [ expectedFuncErrorDiagnostic ] , // Check parsed for other file
199+ } ) ,
200+ ] ) ;
201+
202+ console . log ( ">>> Waiting for no running tasks" ) ;
203+ await waitForNoRunningTasks ( ) ;
204+ } ) ;
170205
171206 test ( "swift diagnosticsStyle" , async function ( ) {
172207 // This is only supported in swift versions >=5.10.0
@@ -176,31 +211,29 @@ suite("DiagnosticsManager Test Suite", async function () {
176211 return ;
177212 }
178213 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 ;
214+ await Promise . all ( [
215+ executeTaskAndWaitForResult ( createBuildAllTask ( folderContext ) ) ,
216+ waitForDiagnostics ( {
217+ [ mainUri . fsPath ] : [ expectedWarningDiagnostic , expectedMainErrorDiagnostic ] , // Should have parsed correct severity
218+ [ funcUri . fsPath ] : [ expectedFuncErrorDiagnostic ] , // Check parsed for other file
219+ } ) ,
220+ ] ) ;
184221 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
222+ } ) ;
192223
193224 test ( "llvm diagnosticsStyle" , async ( ) => {
194225 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 ;
226+
227+ await Promise . all ( [
228+ executeTaskAndWaitForResult ( createBuildAllTask ( folderContext ) ) ,
229+ waitForDiagnostics ( {
230+ [ mainUri . fsPath ] : [ expectedWarningDiagnostic , expectedMainErrorDiagnostic ] , // Should have parsed correct severity
231+ [ funcUri . fsPath ] : [ expectedFuncErrorDiagnostic ] , // Check parsed for other file
232+ } ) ,
233+ ] ) ;
200234 await waitForNoRunningTasks ( ) ;
201235
202236 // Should have parsed severity
203- assertHasDiagnostic ( mainUri , expectedWarningDiagnostic ) ;
204237 const diagnostic = assertHasDiagnostic ( mainUri , expectedMainErrorDiagnostic ) ;
205238 // Should have parsed related note
206239 assert . equal ( diagnostic . relatedInformation ?. length , 1 ) ;
@@ -215,9 +248,7 @@ suite("DiagnosticsManager Test Suite", async function () {
215248 ) ,
216249 true
217250 ) ;
218- // Check parsed for other file
219- assertHasDiagnostic ( funcUri , expectedFuncErrorDiagnostic ) ;
220- } ) . timeout ( 2 * 60 * 1000 ) ; // Allow 2 minutes to build
251+ } ) ;
221252
222253 test ( "Parses C diagnostics" , async function ( ) {
223254 const swiftVersion = workspaceContext . toolchain . swiftVersion ;
@@ -228,12 +259,6 @@ suite("DiagnosticsManager Test Suite", async function () {
228259 }
229260
230261 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 ( ) ;
237262
238263 // Should have parsed severity
239264 const expectedDiagnostic1 = new vscode . Diagnostic (
@@ -249,8 +274,13 @@ suite("DiagnosticsManager Test Suite", async function () {
249274 ) ;
250275 expectedDiagnostic2 . source = "swiftc" ;
251276
252- assertHasDiagnostic ( cUri , expectedDiagnostic1 ) ;
253- assertHasDiagnostic ( cUri , expectedDiagnostic2 ) ;
277+ await Promise . all ( [
278+ executeTaskAndWaitForResult ( createBuildAllTask ( cFolderContext ) ) ,
279+ waitForDiagnostics ( {
280+ [ cUri . fsPath ] : [ expectedDiagnostic1 , expectedDiagnostic2 ] ,
281+ } ) ,
282+ ] ) ;
283+ await waitForNoRunningTasks ( ) ;
254284 } ) ;
255285
256286 test ( "Parses C++ diagnostics" , async function ( ) {
@@ -262,12 +292,6 @@ suite("DiagnosticsManager Test Suite", async function () {
262292 }
263293
264294 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 ( ) ;
271295
272296 // Should have parsed severity
273297 const expectedDiagnostic1 = new vscode . Diagnostic (
@@ -276,7 +300,6 @@ suite("DiagnosticsManager Test Suite", async function () {
276300 vscode . DiagnosticSeverity . Error
277301 ) ;
278302 expectedDiagnostic1 . source = "swiftc" ;
279- assertHasDiagnostic ( cppUri , expectedDiagnostic1 ) ;
280303
281304 // Should have parsed releated information
282305 const expectedDiagnostic2 = new vscode . Diagnostic (
@@ -285,6 +308,15 @@ suite("DiagnosticsManager Test Suite", async function () {
285308 vscode . DiagnosticSeverity . Error
286309 ) ;
287310 expectedDiagnostic2 . source = "swiftc" ;
311+
312+ await Promise . all ( [
313+ executeTaskAndWaitForResult ( createBuildAllTask ( cppFolderContext ) ) ,
314+ waitForDiagnostics ( {
315+ [ cppUri . fsPath ] : [ expectedDiagnostic1 , expectedDiagnostic2 ] ,
316+ } ) ,
317+ ] ) ;
318+ await waitForNoRunningTasks ( ) ;
319+
288320 const diagnostic = assertHasDiagnostic ( cppUri , expectedDiagnostic2 ) ;
289321 assert . equal (
290322 diagnostic . relatedInformation ! [ 0 ] . location . uri . fsPath ,
@@ -315,7 +347,7 @@ suite("DiagnosticsManager Test Suite", async function () {
315347 test ( "Parse partial line" , async ( ) => {
316348 const fixture = testSwiftTask ( "swift" , [ "build" ] , workspaceFolder , toolchain ) ;
317349 await vscode . tasks . executeTask ( fixture . task ) ;
318- const diagnosticsPromise = waitForDiagnostics ( [ mainUri ] ) ;
350+ const diagnosticsPromise = Promise . resolve ( ) ; // waitForDiagnostics([mainUri]);
319351 // Wait to spawn before writing
320352 fixture . process . write ( `${ mainUri . fsPath } :13:5: err` , "" ) ;
321353 fixture . process . write ( "or: Cannot find 'fo" , "" ) ;
@@ -331,7 +363,7 @@ suite("DiagnosticsManager Test Suite", async function () {
331363 test ( "Ignore duplicates" , async ( ) => {
332364 const fixture = testSwiftTask ( "swift" , [ "build" ] , workspaceFolder , toolchain ) ;
333365 await vscode . tasks . executeTask ( fixture . task ) ;
334- const diagnosticsPromise = waitForDiagnostics ( [ mainUri ] ) ;
366+ const diagnosticsPromise = Promise . resolve ( ) ; // waitForDiagnostics([mainUri]);
335367 // Wait to spawn before writing
336368 const output = `${ mainUri . fsPath } :13:5: error: Cannot find 'foo' in scope` ;
337369 fixture . process . write ( output ) ;
@@ -349,7 +381,7 @@ suite("DiagnosticsManager Test Suite", async function () {
349381 test ( "New set of swiftc diagnostics clear old list" , async ( ) => {
350382 let fixture = testSwiftTask ( "swift" , [ "build" ] , workspaceFolder , toolchain ) ;
351383 await vscode . tasks . executeTask ( fixture . task ) ;
352- let diagnosticsPromise = waitForDiagnostics ( [ mainUri ] ) ;
384+ let diagnosticsPromise = Promise . resolve ( ) ; // waitForDiagnostics([mainUri]);
353385 // Wait to spawn before writing
354386 fixture . process . write ( `${ mainUri . fsPath } :13:5: error: Cannot find 'foo' in scope` ) ;
355387 fixture . process . close ( 1 ) ;
@@ -363,7 +395,7 @@ suite("DiagnosticsManager Test Suite", async function () {
363395 // Run again but no diagnostics returned
364396 fixture = testSwiftTask ( "swift" , [ "build" ] , workspaceFolder , toolchain ) ;
365397 await vscode . tasks . executeTask ( fixture . task ) ;
366- diagnosticsPromise = waitForDiagnostics ( [ mainUri ] ) ;
398+ diagnosticsPromise = Promise . resolve ( ) ; // waitForDiagnostics([mainUri]);
367399 fixture . process . close ( 0 ) ;
368400 await waitForNoRunningTasks ( ) ;
369401 await diagnosticsPromise ;
@@ -920,7 +952,7 @@ suite("DiagnosticsManager Test Suite", async function () {
920952 await executeTaskAndWaitForResult ( task ) ;
921953
922954 // Open file
923- const promise = waitForDiagnostics ( [ mainUri ] , false ) ;
955+ const promise = Promise . resolve ( ) ; // waitForDiagnostics([mainUri], false);
924956 const document = await vscode . workspace . openTextDocument ( mainUri ) ;
925957 await vscode . languages . setTextDocumentLanguage ( document , "swift" ) ;
926958 await vscode . window . showTextDocument ( document ) ;
@@ -961,7 +993,7 @@ suite("DiagnosticsManager Test Suite", async function () {
961993 await executeTaskAndWaitForResult ( task ) ;
962994
963995 // Open file
964- const promise = waitForDiagnostics ( [ cUri ] , false ) ;
996+ const promise = Promise . resolve ( ) ; // waitForDiagnostics([cUri], false);
965997 const document = await vscode . workspace . openTextDocument ( cUri ) ;
966998 await vscode . languages . setTextDocumentLanguage ( document , "c" ) ;
967999 await vscode . window . showTextDocument ( document ) ;
0 commit comments