@@ -37,6 +37,7 @@ export class TestExplorer {
37
37
private lspTestDiscovery : LSPTestDiscovery ;
38
38
private subscriptions : { dispose ( ) : unknown } [ ] ;
39
39
private testFileEdited = true ;
40
+ private tokenSource = new vscode . CancellationTokenSource ( ) ;
40
41
41
42
// Emits after the `vscode.TestController` has been updated.
42
43
private onTestItemsDidChangeEmitter = new vscode . EventEmitter < vscode . TestController > ( ) ;
@@ -56,7 +57,7 @@ export class TestExplorer {
56
57
57
58
this . controller . resolveHandler = async item => {
58
59
if ( ! item ) {
59
- await this . discoverTestsInWorkspace ( ) ;
60
+ await this . discoverTestsInWorkspace ( this . tokenSource . token ) ;
60
61
}
61
62
} ;
62
63
@@ -86,7 +87,7 @@ export class TestExplorer {
86
87
this . testFileEdited = false ;
87
88
// only run discover tests if the library has tests
88
89
if ( this . folderContext . swiftPackage . getTargets ( TargetType . test ) . length > 0 ) {
89
- this . discoverTestsInWorkspace ( ) ;
90
+ this . discoverTestsInWorkspace ( this . tokenSource . token ) ;
90
91
}
91
92
}
92
93
} ) ;
@@ -99,6 +100,7 @@ export class TestExplorer {
99
100
} ) ;
100
101
101
102
this . subscriptions = [
103
+ this . tokenSource ,
102
104
fileWatcher ,
103
105
onDidEndTask ,
104
106
this . controller ,
@@ -110,6 +112,9 @@ export class TestExplorer {
110
112
}
111
113
112
114
dispose ( ) {
115
+ this . controller . refreshHandler = undefined ;
116
+ this . controller . resolveHandler = undefined ;
117
+ this . tokenSource . cancel ( ) ;
113
118
this . subscriptions . forEach ( element => element . dispose ( ) ) ;
114
119
}
115
120
@@ -120,47 +125,64 @@ export class TestExplorer {
120
125
* @returns Observer disposable
121
126
*/
122
127
static observeFolders ( workspaceContext : WorkspaceContext ) : vscode . Disposable {
123
- return workspaceContext . onDidChangeFolders ( ( { folder, operation, workspace } ) => {
124
- switch ( operation ) {
125
- case FolderOperation . add :
126
- if ( folder ) {
127
- if ( folder . swiftPackage . getTargets ( TargetType . test ) . length > 0 ) {
128
- folder . addTestExplorer ( ) ;
129
- // discover tests in workspace but only if disableAutoResolve is not on.
130
- // discover tests will kick off a resolve if required
131
- if ( ! configuration . folder ( folder . workspaceFolder ) . disableAutoResolve ) {
132
- folder . testExplorer ?. discoverTestsInWorkspace ( ) ;
128
+ const tokenSource = new vscode . CancellationTokenSource ( ) ;
129
+ const disposable = workspaceContext . onDidChangeFolders (
130
+ ( { folder, operation, workspace } ) => {
131
+ switch ( operation ) {
132
+ case FolderOperation . add :
133
+ if ( folder ) {
134
+ if ( folder . swiftPackage . getTargets ( TargetType . test ) . length > 0 ) {
135
+ folder . addTestExplorer ( ) ;
136
+ // discover tests in workspace but only if disableAutoResolve is not on.
137
+ // discover tests will kick off a resolve if required
138
+ if (
139
+ ! configuration . folder ( folder . workspaceFolder ) . disableAutoResolve
140
+ ) {
141
+ folder . testExplorer ?. discoverTestsInWorkspace (
142
+ tokenSource . token
143
+ ) ;
144
+ }
133
145
}
134
146
}
135
- }
136
- break ;
137
- case FolderOperation . packageUpdated :
138
- if ( folder ) {
139
- const hasTestTargets =
140
- folder . swiftPackage . getTargets ( TargetType . test ) . length > 0 ;
141
- if ( hasTestTargets && ! folder . hasTestExplorer ( ) ) {
142
- folder . addTestExplorer ( ) ;
143
- // discover tests in workspace but only if disableAutoResolve is not on.
144
- // discover tests will kick off a resolve if required
145
- if ( ! configuration . folder ( folder . workspaceFolder ) . disableAutoResolve ) {
146
- folder . testExplorer ?. discoverTestsInWorkspace ( ) ;
147
+ break ;
148
+ case FolderOperation . packageUpdated :
149
+ if ( folder ) {
150
+ const hasTestTargets =
151
+ folder . swiftPackage . getTargets ( TargetType . test ) . length > 0 ;
152
+ if ( hasTestTargets && ! folder . hasTestExplorer ( ) ) {
153
+ folder . addTestExplorer ( ) ;
154
+ // discover tests in workspace but only if disableAutoResolve is not on.
155
+ // discover tests will kick off a resolve if required
156
+ if (
157
+ ! configuration . folder ( folder . workspaceFolder ) . disableAutoResolve
158
+ ) {
159
+ folder . testExplorer ?. discoverTestsInWorkspace (
160
+ tokenSource . token
161
+ ) ;
162
+ }
163
+ } else if ( ! hasTestTargets && folder . hasTestExplorer ( ) ) {
164
+ folder . removeTestExplorer ( ) ;
165
+ } else if ( folder . hasTestExplorer ( ) ) {
166
+ folder . refreshTestExplorer ( ) ;
147
167
}
148
- } else if ( ! hasTestTargets && folder . hasTestExplorer ( ) ) {
149
- folder . removeTestExplorer ( ) ;
150
- } else if ( folder . hasTestExplorer ( ) ) {
151
- folder . refreshTestExplorer ( ) ;
152
168
}
153
- }
154
- break ;
155
- case FolderOperation . focus :
156
- if ( folder ) {
157
- workspace . languageClientManager . documentSymbolWatcher = (
158
- document ,
159
- symbols
160
- ) => TestExplorer . onDocumentSymbols ( folder , document , symbols ) ;
161
- }
169
+ break ;
170
+ case FolderOperation . focus :
171
+ if ( folder ) {
172
+ workspace . languageClientManager . documentSymbolWatcher = (
173
+ document ,
174
+ symbols
175
+ ) => TestExplorer . onDocumentSymbols ( folder , document , symbols ) ;
176
+ }
177
+ }
162
178
}
163
- } ) ;
179
+ ) ;
180
+ return {
181
+ dispose : ( ) => {
182
+ tokenSource . dispose ( ) ;
183
+ disposable . dispose ( ) ;
184
+ } ,
185
+ } ;
164
186
}
165
187
166
188
/**
@@ -224,25 +246,25 @@ export class TestExplorer {
224
246
/**
225
247
* Discover tests
226
248
*/
227
- async discoverTestsInWorkspace ( ) {
249
+ async discoverTestsInWorkspace ( token : vscode . CancellationToken ) {
228
250
try {
229
251
// If the LSP cannot produce a list of tests it throws and
230
252
// we fall back to discovering tests with SPM.
231
- await this . discoverTestsInWorkspaceLSP ( ) ;
253
+ await this . discoverTestsInWorkspaceLSP ( token ) ;
232
254
} catch {
233
255
this . folderContext . workspaceContext . outputChannel . logDiagnostic (
234
256
"workspace/tests LSP request not supported, falling back to SPM to discover tests." ,
235
257
"Test Discovery"
236
258
) ;
237
- await this . discoverTestsInWorkspaceSPM ( ) ;
259
+ await this . discoverTestsInWorkspaceSPM ( token ) ;
238
260
}
239
261
}
240
262
241
263
/**
242
264
* Discover tests
243
265
* Uses `swift test --list-tests` to get the list of tests
244
266
*/
245
- async discoverTestsInWorkspaceSPM ( ) {
267
+ async discoverTestsInWorkspaceSPM ( token : vscode . CancellationToken ) {
246
268
async function runDiscover ( explorer : TestExplorer , firstTry : boolean ) {
247
269
try {
248
270
const toolchain = explorer . folderContext . workspaceContext . toolchain ;
@@ -263,6 +285,11 @@ export class TestExplorer {
263
285
return ;
264
286
}
265
287
}
288
+
289
+ if ( token . isCancellationRequested ) {
290
+ return ;
291
+ }
292
+
266
293
// get list of tests from `swift test --list-tests`
267
294
let listTestArguments : string [ ] ;
268
295
if ( toolchain . swiftVersion . isGreaterThanOrEqual ( new Version ( 5 , 8 , 0 ) ) ) {
@@ -284,7 +311,7 @@ export class TestExplorer {
284
311
explorer . updateTests ( explorer . controller , tests ) ;
285
312
}
286
313
) ;
287
- await explorer . folderContext . taskQueue . queueOperation ( listTestsOperation ) ;
314
+ await explorer . folderContext . taskQueue . queueOperation ( listTestsOperation , token ) ;
288
315
} catch ( error ) {
289
316
// If a test list fails its possible the tests have not been built.
290
317
// Build them and try again, and if we still fail then notify the user.
@@ -336,10 +363,14 @@ export class TestExplorer {
336
363
/**
337
364
* Discover tests
338
365
*/
339
- async discoverTestsInWorkspaceLSP ( ) {
366
+ async discoverTestsInWorkspaceLSP ( token : vscode . CancellationToken ) {
340
367
const tests = await this . lspTestDiscovery . getWorkspaceTests (
341
368
this . folderContext . swiftPackage
342
369
) ;
370
+ if ( token . isCancellationRequested ) {
371
+ return ;
372
+ }
373
+
343
374
TestDiscovery . updateTestsFromClasses (
344
375
this . controller ,
345
376
this . folderContext . swiftPackage ,
0 commit comments