Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
microsoft
GitHub Repository: microsoft/vscode
Path: blob/main/src/vs/workbench/api/test/browser/extHostWorkspace.test.ts
5240 views
1
/*---------------------------------------------------------------------------------------------
2
* Copyright (c) Microsoft Corporation. All rights reserved.
3
* Licensed under the MIT License. See License.txt in the project root for license information.
4
*--------------------------------------------------------------------------------------------*/
5
6
import assert from 'assert';
7
import { CancellationToken } from '../../../../base/common/cancellation.js';
8
import { basename } from '../../../../base/common/path.js';
9
import { URI, UriComponents } from '../../../../base/common/uri.js';
10
import { ExtensionIdentifier } from '../../../../platform/extensions/common/extensions.js';
11
import { ILogService, NullLogService } from '../../../../platform/log/common/log.js';
12
import { IWorkspaceFolderData } from '../../../../platform/workspace/common/workspace.js';
13
import { MainThreadWorkspace } from '../../browser/mainThreadWorkspace.js';
14
import { IMainContext, IWorkspaceData, MainContext, ITextSearchComplete } from '../../common/extHost.protocol.js';
15
import { RelativePattern } from '../../common/extHostTypes.js';
16
import { ExtHostWorkspace } from '../../common/extHostWorkspace.js';
17
import { mock } from '../../../../base/test/common/mock.js';
18
import { TestRPCProtocol } from '../common/testRPCProtocol.js';
19
import { ExtHostRpcService } from '../../common/extHostRpcService.js';
20
import { IExtHostInitDataService } from '../../common/extHostInitDataService.js';
21
import { IFileQueryBuilderOptions, ITextQueryBuilderOptions } from '../../../services/search/common/queryBuilder.js';
22
import { IPatternInfo } from '../../../services/search/common/search.js';
23
import { isLinux, isWindows } from '../../../../base/common/platform.js';
24
import { IExtHostFileSystemInfo } from '../../common/extHostFileSystemInfo.js';
25
import { FileSystemProviderCapabilities } from '../../../../platform/files/common/files.js';
26
import { nullExtensionDescription as extensionDescriptor } from '../../../services/extensions/common/extensions.js';
27
import { IURITransformerService } from '../../common/extHostUriTransformerService.js';
28
import { ensureNoDisposablesAreLeakedInTestSuite } from '../../../../base/test/common/utils.js';
29
import { ExcludeSettingOptions } from '../../../services/search/common/searchExtTypes.js';
30
31
function createExtHostWorkspace(mainContext: IMainContext, data: IWorkspaceData, logService: ILogService): ExtHostWorkspace {
32
const result = new ExtHostWorkspace(
33
new ExtHostRpcService(mainContext),
34
new class extends mock<IExtHostInitDataService>() { override workspace = data; },
35
new class extends mock<IExtHostFileSystemInfo>() { override getCapabilities() { return isLinux ? FileSystemProviderCapabilities.PathCaseSensitive : undefined; } },
36
logService,
37
new class extends mock<IURITransformerService>() { }
38
);
39
result.$initializeWorkspace(data, true);
40
return result;
41
}
42
43
suite('ExtHostWorkspace', function () {
44
45
ensureNoDisposablesAreLeakedInTestSuite();
46
47
function assertAsRelativePath(workspace: ExtHostWorkspace, input: string, expected: string, includeWorkspace?: boolean) {
48
const actual = workspace.getRelativePath(input, includeWorkspace);
49
assert.strictEqual(actual, expected);
50
}
51
52
test('asRelativePath', () => {
53
54
const ws = createExtHostWorkspace(new TestRPCProtocol(), { id: 'foo', folders: [aWorkspaceFolderData(URI.file('/Coding/Applications/NewsWoWBot'), 0)], name: 'Test' }, new NullLogService());
55
56
assertAsRelativePath(ws, '/Coding/Applications/NewsWoWBot/bernd/das/brot', 'bernd/das/brot');
57
assertAsRelativePath(ws, '/Apps/DartPubCache/hosted/pub.dartlang.org/convert-2.0.1/lib/src/hex.dart',
58
'/Apps/DartPubCache/hosted/pub.dartlang.org/convert-2.0.1/lib/src/hex.dart');
59
60
assertAsRelativePath(ws, '', '');
61
assertAsRelativePath(ws, '/foo/bar', '/foo/bar');
62
assertAsRelativePath(ws, 'in/out', 'in/out');
63
});
64
65
test('asRelativePath, same paths, #11402', function () {
66
const root = '/home/aeschli/workspaces/samples/docker';
67
const input = '/home/aeschli/workspaces/samples/docker';
68
const ws = createExtHostWorkspace(new TestRPCProtocol(), { id: 'foo', folders: [aWorkspaceFolderData(URI.file(root), 0)], name: 'Test' }, new NullLogService());
69
70
assertAsRelativePath(ws, input, input);
71
72
const input2 = '/home/aeschli/workspaces/samples/docker/a.file';
73
assertAsRelativePath(ws, input2, 'a.file');
74
});
75
76
test('asRelativePath, no workspace', function () {
77
const ws = createExtHostWorkspace(new TestRPCProtocol(), null!, new NullLogService());
78
assertAsRelativePath(ws, '', '');
79
assertAsRelativePath(ws, '/foo/bar', '/foo/bar');
80
});
81
82
test('asRelativePath, multiple folders', function () {
83
const ws = createExtHostWorkspace(new TestRPCProtocol(), { id: 'foo', folders: [aWorkspaceFolderData(URI.file('/Coding/One'), 0), aWorkspaceFolderData(URI.file('/Coding/Two'), 1)], name: 'Test' }, new NullLogService());
84
assertAsRelativePath(ws, '/Coding/One/file.txt', 'One/file.txt');
85
assertAsRelativePath(ws, '/Coding/Two/files/out.txt', 'Two/files/out.txt');
86
assertAsRelativePath(ws, '/Coding/Two2/files/out.txt', '/Coding/Two2/files/out.txt');
87
});
88
89
test('slightly inconsistent behaviour of asRelativePath and getWorkspaceFolder, #31553', function () {
90
const mrws = createExtHostWorkspace(new TestRPCProtocol(), { id: 'foo', folders: [aWorkspaceFolderData(URI.file('/Coding/One'), 0), aWorkspaceFolderData(URI.file('/Coding/Two'), 1)], name: 'Test' }, new NullLogService());
91
92
assertAsRelativePath(mrws, '/Coding/One/file.txt', 'One/file.txt');
93
assertAsRelativePath(mrws, '/Coding/One/file.txt', 'One/file.txt', true);
94
assertAsRelativePath(mrws, '/Coding/One/file.txt', 'file.txt', false);
95
assertAsRelativePath(mrws, '/Coding/Two/files/out.txt', 'Two/files/out.txt');
96
assertAsRelativePath(mrws, '/Coding/Two/files/out.txt', 'Two/files/out.txt', true);
97
assertAsRelativePath(mrws, '/Coding/Two/files/out.txt', 'files/out.txt', false);
98
assertAsRelativePath(mrws, '/Coding/Two2/files/out.txt', '/Coding/Two2/files/out.txt');
99
assertAsRelativePath(mrws, '/Coding/Two2/files/out.txt', '/Coding/Two2/files/out.txt', true);
100
assertAsRelativePath(mrws, '/Coding/Two2/files/out.txt', '/Coding/Two2/files/out.txt', false);
101
102
const srws = createExtHostWorkspace(new TestRPCProtocol(), { id: 'foo', folders: [aWorkspaceFolderData(URI.file('/Coding/One'), 0)], name: 'Test' }, new NullLogService());
103
assertAsRelativePath(srws, '/Coding/One/file.txt', 'file.txt');
104
assertAsRelativePath(srws, '/Coding/One/file.txt', 'file.txt', false);
105
assertAsRelativePath(srws, '/Coding/One/file.txt', 'One/file.txt', true);
106
assertAsRelativePath(srws, '/Coding/Two2/files/out.txt', '/Coding/Two2/files/out.txt');
107
assertAsRelativePath(srws, '/Coding/Two2/files/out.txt', '/Coding/Two2/files/out.txt', true);
108
assertAsRelativePath(srws, '/Coding/Two2/files/out.txt', '/Coding/Two2/files/out.txt', false);
109
});
110
111
test('getPath, legacy', function () {
112
let ws = createExtHostWorkspace(new TestRPCProtocol(), { id: 'foo', name: 'Test', folders: [] }, new NullLogService());
113
assert.strictEqual(ws.getPath(), undefined);
114
115
ws = createExtHostWorkspace(new TestRPCProtocol(), null!, new NullLogService());
116
assert.strictEqual(ws.getPath(), undefined);
117
118
ws = createExtHostWorkspace(new TestRPCProtocol(), undefined!, new NullLogService());
119
assert.strictEqual(ws.getPath(), undefined);
120
121
ws = createExtHostWorkspace(new TestRPCProtocol(), { id: 'foo', name: 'Test', folders: [aWorkspaceFolderData(URI.file('Folder'), 0), aWorkspaceFolderData(URI.file('Another/Folder'), 1)] }, new NullLogService());
122
assert.strictEqual(ws.getPath()!.replace(/\\/g, '/'), '/Folder');
123
124
ws = createExtHostWorkspace(new TestRPCProtocol(), { id: 'foo', name: 'Test', folders: [aWorkspaceFolderData(URI.file('/Folder'), 0)] }, new NullLogService());
125
assert.strictEqual(ws.getPath()!.replace(/\\/g, '/'), '/Folder');
126
});
127
128
test('WorkspaceFolder has name and index', function () {
129
const ws = createExtHostWorkspace(new TestRPCProtocol(), { id: 'foo', folders: [aWorkspaceFolderData(URI.file('/Coding/One'), 0), aWorkspaceFolderData(URI.file('/Coding/Two'), 1)], name: 'Test' }, new NullLogService());
130
131
const [one, two] = ws.getWorkspaceFolders()!;
132
133
assert.strictEqual(one.name, 'One');
134
assert.strictEqual(one.index, 0);
135
assert.strictEqual(two.name, 'Two');
136
assert.strictEqual(two.index, 1);
137
});
138
139
test('getContainingWorkspaceFolder', () => {
140
const ws = createExtHostWorkspace(new TestRPCProtocol(), {
141
id: 'foo',
142
name: 'Test',
143
folders: [
144
aWorkspaceFolderData(URI.file('/Coding/One'), 0),
145
aWorkspaceFolderData(URI.file('/Coding/Two'), 1),
146
aWorkspaceFolderData(URI.file('/Coding/Two/Nested'), 2)
147
]
148
}, new NullLogService());
149
150
let folder = ws.getWorkspaceFolder(URI.file('/foo/bar'));
151
assert.strictEqual(folder, undefined);
152
153
folder = ws.getWorkspaceFolder(URI.file('/Coding/One/file/path.txt'))!;
154
assert.strictEqual(folder.name, 'One');
155
156
folder = ws.getWorkspaceFolder(URI.file('/Coding/Two/file/path.txt'))!;
157
assert.strictEqual(folder.name, 'Two');
158
159
folder = ws.getWorkspaceFolder(URI.file('/Coding/Two/Nest'))!;
160
assert.strictEqual(folder.name, 'Two');
161
162
folder = ws.getWorkspaceFolder(URI.file('/Coding/Two/Nested/file'))!;
163
assert.strictEqual(folder.name, 'Nested');
164
165
folder = ws.getWorkspaceFolder(URI.file('/Coding/Two/Nested/f'))!;
166
assert.strictEqual(folder.name, 'Nested');
167
168
folder = ws.getWorkspaceFolder(URI.file('/Coding/Two/Nested'), true)!;
169
assert.strictEqual(folder.name, 'Two');
170
171
folder = ws.getWorkspaceFolder(URI.file('/Coding/Two/Nested/'), true)!;
172
assert.strictEqual(folder.name, 'Two');
173
174
folder = ws.getWorkspaceFolder(URI.file('/Coding/Two/Nested'))!;
175
assert.strictEqual(folder.name, 'Nested');
176
177
folder = ws.getWorkspaceFolder(URI.file('/Coding/Two/Nested/'))!;
178
assert.strictEqual(folder.name, 'Nested');
179
180
folder = ws.getWorkspaceFolder(URI.file('/Coding/Two'), true)!;
181
assert.strictEqual(folder, undefined);
182
183
folder = ws.getWorkspaceFolder(URI.file('/Coding/Two'), false)!;
184
assert.strictEqual(folder.name, 'Two');
185
});
186
187
test('Multiroot change event should have a delta, #29641', function (done) {
188
const ws = createExtHostWorkspace(new TestRPCProtocol(), { id: 'foo', name: 'Test', folders: [] }, new NullLogService());
189
190
let finished = false;
191
const finish = (error?: any) => {
192
if (!finished) {
193
finished = true;
194
done(error);
195
}
196
};
197
198
let sub = ws.onDidChangeWorkspace(e => {
199
try {
200
assert.deepStrictEqual(e.added, []);
201
assert.deepStrictEqual(e.removed, []);
202
} catch (error) {
203
finish(error);
204
}
205
});
206
ws.$acceptWorkspaceData({ id: 'foo', name: 'Test', folders: [] });
207
sub.dispose();
208
209
sub = ws.onDidChangeWorkspace(e => {
210
try {
211
assert.deepStrictEqual(e.removed, []);
212
assert.strictEqual(e.added.length, 1);
213
assert.strictEqual(e.added[0].uri.toString(), 'foo:bar');
214
} catch (error) {
215
finish(error);
216
}
217
});
218
ws.$acceptWorkspaceData({ id: 'foo', name: 'Test', folders: [aWorkspaceFolderData(URI.parse('foo:bar'), 0)] });
219
sub.dispose();
220
221
sub = ws.onDidChangeWorkspace(e => {
222
try {
223
assert.deepStrictEqual(e.removed, []);
224
assert.strictEqual(e.added.length, 1);
225
assert.strictEqual(e.added[0].uri.toString(), 'foo:bar2');
226
} catch (error) {
227
finish(error);
228
}
229
});
230
ws.$acceptWorkspaceData({ id: 'foo', name: 'Test', folders: [aWorkspaceFolderData(URI.parse('foo:bar'), 0), aWorkspaceFolderData(URI.parse('foo:bar2'), 1)] });
231
sub.dispose();
232
233
sub = ws.onDidChangeWorkspace(e => {
234
try {
235
assert.strictEqual(e.removed.length, 2);
236
assert.strictEqual(e.removed[0].uri.toString(), 'foo:bar');
237
assert.strictEqual(e.removed[1].uri.toString(), 'foo:bar2');
238
239
assert.strictEqual(e.added.length, 1);
240
assert.strictEqual(e.added[0].uri.toString(), 'foo:bar3');
241
} catch (error) {
242
finish(error);
243
}
244
});
245
ws.$acceptWorkspaceData({ id: 'foo', name: 'Test', folders: [aWorkspaceFolderData(URI.parse('foo:bar3'), 0)] });
246
sub.dispose();
247
finish();
248
});
249
250
test('Multiroot change keeps existing workspaces live', function () {
251
const ws = createExtHostWorkspace(new TestRPCProtocol(), { id: 'foo', name: 'Test', folders: [aWorkspaceFolderData(URI.parse('foo:bar'), 0)] }, new NullLogService());
252
253
const firstFolder = ws.getWorkspaceFolders()![0];
254
ws.$acceptWorkspaceData({ id: 'foo', name: 'Test', folders: [aWorkspaceFolderData(URI.parse('foo:bar2'), 0), aWorkspaceFolderData(URI.parse('foo:bar'), 1, 'renamed')] });
255
256
assert.strictEqual(ws.getWorkspaceFolders()![1], firstFolder);
257
assert.strictEqual(firstFolder.index, 1);
258
assert.strictEqual(firstFolder.name, 'renamed');
259
260
ws.$acceptWorkspaceData({ id: 'foo', name: 'Test', folders: [aWorkspaceFolderData(URI.parse('foo:bar3'), 0), aWorkspaceFolderData(URI.parse('foo:bar2'), 1), aWorkspaceFolderData(URI.parse('foo:bar'), 2)] });
261
assert.strictEqual(ws.getWorkspaceFolders()![2], firstFolder);
262
assert.strictEqual(firstFolder.index, 2);
263
264
ws.$acceptWorkspaceData({ id: 'foo', name: 'Test', folders: [aWorkspaceFolderData(URI.parse('foo:bar3'), 0)] });
265
ws.$acceptWorkspaceData({ id: 'foo', name: 'Test', folders: [aWorkspaceFolderData(URI.parse('foo:bar3'), 0), aWorkspaceFolderData(URI.parse('foo:bar'), 1)] });
266
267
assert.notStrictEqual(firstFolder, ws.workspace!.folders[0]);
268
});
269
270
test('updateWorkspaceFolders - invalid arguments', function () {
271
let ws = createExtHostWorkspace(new TestRPCProtocol(), { id: 'foo', name: 'Test', folders: [] }, new NullLogService());
272
273
assert.strictEqual(false, ws.updateWorkspaceFolders(extensionDescriptor, null!, null!));
274
assert.strictEqual(false, ws.updateWorkspaceFolders(extensionDescriptor, 0, 0));
275
assert.strictEqual(false, ws.updateWorkspaceFolders(extensionDescriptor, 0, 1));
276
assert.strictEqual(false, ws.updateWorkspaceFolders(extensionDescriptor, 1, 0));
277
assert.strictEqual(false, ws.updateWorkspaceFolders(extensionDescriptor, -1, 0));
278
assert.strictEqual(false, ws.updateWorkspaceFolders(extensionDescriptor, -1, -1));
279
280
ws = createExtHostWorkspace(new TestRPCProtocol(), { id: 'foo', name: 'Test', folders: [aWorkspaceFolderData(URI.parse('foo:bar'), 0)] }, new NullLogService());
281
282
assert.strictEqual(false, ws.updateWorkspaceFolders(extensionDescriptor, 1, 1));
283
assert.strictEqual(false, ws.updateWorkspaceFolders(extensionDescriptor, 0, 2));
284
assert.strictEqual(false, ws.updateWorkspaceFolders(extensionDescriptor, 0, 1, asUpdateWorkspaceFolderData(URI.parse('foo:bar'))));
285
});
286
287
test('updateWorkspaceFolders - valid arguments', function (done) {
288
let finished = false;
289
const finish = (error?: any) => {
290
if (!finished) {
291
finished = true;
292
done(error);
293
}
294
};
295
296
const protocol: IMainContext = {
297
getProxy: () => { return undefined!; },
298
set: () => { return undefined!; },
299
dispose: () => { },
300
assertRegistered: () => { },
301
drain: () => { return undefined!; },
302
};
303
304
const ws = createExtHostWorkspace(protocol, { id: 'foo', name: 'Test', folders: [] }, new NullLogService());
305
306
//
307
// Add one folder
308
//
309
310
assert.strictEqual(true, ws.updateWorkspaceFolders(extensionDescriptor, 0, 0, asUpdateWorkspaceFolderData(URI.parse('foo:bar'))));
311
assert.strictEqual(1, ws.workspace!.folders.length);
312
assert.strictEqual(ws.workspace!.folders[0].uri.toString(), URI.parse('foo:bar').toString());
313
314
const firstAddedFolder = ws.getWorkspaceFolders()![0];
315
316
let gotEvent = false;
317
let sub = ws.onDidChangeWorkspace(e => {
318
try {
319
assert.deepStrictEqual(e.removed, []);
320
assert.strictEqual(e.added.length, 1);
321
assert.strictEqual(e.added[0].uri.toString(), 'foo:bar');
322
assert.strictEqual(e.added[0], firstAddedFolder); // verify object is still live
323
gotEvent = true;
324
} catch (error) {
325
finish(error);
326
}
327
});
328
ws.$acceptWorkspaceData({ id: 'foo', name: 'Test', folders: [aWorkspaceFolderData(URI.parse('foo:bar'), 0)] }); // simulate acknowledgement from main side
329
assert.strictEqual(gotEvent, true);
330
sub.dispose();
331
assert.strictEqual(ws.getWorkspaceFolders()![0], firstAddedFolder); // verify object is still live
332
333
//
334
// Add two more folders
335
//
336
337
assert.strictEqual(true, ws.updateWorkspaceFolders(extensionDescriptor, 1, 0, asUpdateWorkspaceFolderData(URI.parse('foo:bar1')), asUpdateWorkspaceFolderData(URI.parse('foo:bar2'))));
338
assert.strictEqual(3, ws.workspace!.folders.length);
339
assert.strictEqual(ws.workspace!.folders[0].uri.toString(), URI.parse('foo:bar').toString());
340
assert.strictEqual(ws.workspace!.folders[1].uri.toString(), URI.parse('foo:bar1').toString());
341
assert.strictEqual(ws.workspace!.folders[2].uri.toString(), URI.parse('foo:bar2').toString());
342
343
const secondAddedFolder = ws.getWorkspaceFolders()![1];
344
const thirdAddedFolder = ws.getWorkspaceFolders()![2];
345
346
gotEvent = false;
347
sub = ws.onDidChangeWorkspace(e => {
348
try {
349
assert.deepStrictEqual(e.removed, []);
350
assert.strictEqual(e.added.length, 2);
351
assert.strictEqual(e.added[0].uri.toString(), 'foo:bar1');
352
assert.strictEqual(e.added[1].uri.toString(), 'foo:bar2');
353
assert.strictEqual(e.added[0], secondAddedFolder);
354
assert.strictEqual(e.added[1], thirdAddedFolder);
355
gotEvent = true;
356
} catch (error) {
357
finish(error);
358
}
359
});
360
ws.$acceptWorkspaceData({ id: 'foo', name: 'Test', folders: [aWorkspaceFolderData(URI.parse('foo:bar'), 0), aWorkspaceFolderData(URI.parse('foo:bar1'), 1), aWorkspaceFolderData(URI.parse('foo:bar2'), 2)] }); // simulate acknowledgement from main side
361
assert.strictEqual(gotEvent, true);
362
sub.dispose();
363
assert.strictEqual(ws.getWorkspaceFolders()![0], firstAddedFolder); // verify object is still live
364
assert.strictEqual(ws.getWorkspaceFolders()![1], secondAddedFolder); // verify object is still live
365
assert.strictEqual(ws.getWorkspaceFolders()![2], thirdAddedFolder); // verify object is still live
366
367
//
368
// Remove one folder
369
//
370
371
assert.strictEqual(true, ws.updateWorkspaceFolders(extensionDescriptor, 2, 1));
372
assert.strictEqual(2, ws.workspace!.folders.length);
373
assert.strictEqual(ws.workspace!.folders[0].uri.toString(), URI.parse('foo:bar').toString());
374
assert.strictEqual(ws.workspace!.folders[1].uri.toString(), URI.parse('foo:bar1').toString());
375
376
gotEvent = false;
377
sub = ws.onDidChangeWorkspace(e => {
378
try {
379
assert.deepStrictEqual(e.added, []);
380
assert.strictEqual(e.removed.length, 1);
381
assert.strictEqual(e.removed[0], thirdAddedFolder);
382
gotEvent = true;
383
} catch (error) {
384
finish(error);
385
}
386
});
387
ws.$acceptWorkspaceData({ id: 'foo', name: 'Test', folders: [aWorkspaceFolderData(URI.parse('foo:bar'), 0), aWorkspaceFolderData(URI.parse('foo:bar1'), 1)] }); // simulate acknowledgement from main side
388
assert.strictEqual(gotEvent, true);
389
sub.dispose();
390
assert.strictEqual(ws.getWorkspaceFolders()![0], firstAddedFolder); // verify object is still live
391
assert.strictEqual(ws.getWorkspaceFolders()![1], secondAddedFolder); // verify object is still live
392
393
//
394
// Rename folder
395
//
396
397
assert.strictEqual(true, ws.updateWorkspaceFolders(extensionDescriptor, 0, 2, asUpdateWorkspaceFolderData(URI.parse('foo:bar'), 'renamed 1'), asUpdateWorkspaceFolderData(URI.parse('foo:bar1'), 'renamed 2')));
398
assert.strictEqual(2, ws.workspace!.folders.length);
399
assert.strictEqual(ws.workspace!.folders[0].uri.toString(), URI.parse('foo:bar').toString());
400
assert.strictEqual(ws.workspace!.folders[1].uri.toString(), URI.parse('foo:bar1').toString());
401
assert.strictEqual(ws.workspace!.folders[0].name, 'renamed 1');
402
assert.strictEqual(ws.workspace!.folders[1].name, 'renamed 2');
403
assert.strictEqual(ws.getWorkspaceFolders()![0].name, 'renamed 1');
404
assert.strictEqual(ws.getWorkspaceFolders()![1].name, 'renamed 2');
405
406
gotEvent = false;
407
sub = ws.onDidChangeWorkspace(e => {
408
try {
409
assert.deepStrictEqual(e.added, []);
410
assert.strictEqual(e.removed.length, 0);
411
gotEvent = true;
412
} catch (error) {
413
finish(error);
414
}
415
});
416
ws.$acceptWorkspaceData({ id: 'foo', name: 'Test', folders: [aWorkspaceFolderData(URI.parse('foo:bar'), 0, 'renamed 1'), aWorkspaceFolderData(URI.parse('foo:bar1'), 1, 'renamed 2')] }); // simulate acknowledgement from main side
417
assert.strictEqual(gotEvent, true);
418
sub.dispose();
419
assert.strictEqual(ws.getWorkspaceFolders()![0], firstAddedFolder); // verify object is still live
420
assert.strictEqual(ws.getWorkspaceFolders()![1], secondAddedFolder); // verify object is still live
421
assert.strictEqual(ws.workspace!.folders[0].name, 'renamed 1');
422
assert.strictEqual(ws.workspace!.folders[1].name, 'renamed 2');
423
assert.strictEqual(ws.getWorkspaceFolders()![0].name, 'renamed 1');
424
assert.strictEqual(ws.getWorkspaceFolders()![1].name, 'renamed 2');
425
426
//
427
// Add and remove folders
428
//
429
430
assert.strictEqual(true, ws.updateWorkspaceFolders(extensionDescriptor, 0, 2, asUpdateWorkspaceFolderData(URI.parse('foo:bar3')), asUpdateWorkspaceFolderData(URI.parse('foo:bar4'))));
431
assert.strictEqual(2, ws.workspace!.folders.length);
432
assert.strictEqual(ws.workspace!.folders[0].uri.toString(), URI.parse('foo:bar3').toString());
433
assert.strictEqual(ws.workspace!.folders[1].uri.toString(), URI.parse('foo:bar4').toString());
434
435
const fourthAddedFolder = ws.getWorkspaceFolders()![0];
436
const fifthAddedFolder = ws.getWorkspaceFolders()![1];
437
438
gotEvent = false;
439
sub = ws.onDidChangeWorkspace(e => {
440
try {
441
assert.strictEqual(e.added.length, 2);
442
assert.strictEqual(e.added[0], fourthAddedFolder);
443
assert.strictEqual(e.added[1], fifthAddedFolder);
444
assert.strictEqual(e.removed.length, 2);
445
assert.strictEqual(e.removed[0], firstAddedFolder);
446
assert.strictEqual(e.removed[1], secondAddedFolder);
447
gotEvent = true;
448
} catch (error) {
449
finish(error);
450
}
451
});
452
ws.$acceptWorkspaceData({ id: 'foo', name: 'Test', folders: [aWorkspaceFolderData(URI.parse('foo:bar3'), 0), aWorkspaceFolderData(URI.parse('foo:bar4'), 1)] }); // simulate acknowledgement from main side
453
assert.strictEqual(gotEvent, true);
454
sub.dispose();
455
assert.strictEqual(ws.getWorkspaceFolders()![0], fourthAddedFolder); // verify object is still live
456
assert.strictEqual(ws.getWorkspaceFolders()![1], fifthAddedFolder); // verify object is still live
457
458
//
459
// Swap folders
460
//
461
462
assert.strictEqual(true, ws.updateWorkspaceFolders(extensionDescriptor, 0, 2, asUpdateWorkspaceFolderData(URI.parse('foo:bar4')), asUpdateWorkspaceFolderData(URI.parse('foo:bar3'))));
463
assert.strictEqual(2, ws.workspace!.folders.length);
464
assert.strictEqual(ws.workspace!.folders[0].uri.toString(), URI.parse('foo:bar4').toString());
465
assert.strictEqual(ws.workspace!.folders[1].uri.toString(), URI.parse('foo:bar3').toString());
466
467
assert.strictEqual(ws.getWorkspaceFolders()![0], fifthAddedFolder); // verify object is still live
468
assert.strictEqual(ws.getWorkspaceFolders()![1], fourthAddedFolder); // verify object is still live
469
470
gotEvent = false;
471
sub = ws.onDidChangeWorkspace(e => {
472
try {
473
assert.strictEqual(e.added.length, 0);
474
assert.strictEqual(e.removed.length, 0);
475
gotEvent = true;
476
} catch (error) {
477
finish(error);
478
}
479
});
480
ws.$acceptWorkspaceData({ id: 'foo', name: 'Test', folders: [aWorkspaceFolderData(URI.parse('foo:bar4'), 0), aWorkspaceFolderData(URI.parse('foo:bar3'), 1)] }); // simulate acknowledgement from main side
481
assert.strictEqual(gotEvent, true);
482
sub.dispose();
483
assert.strictEqual(ws.getWorkspaceFolders()![0], fifthAddedFolder); // verify object is still live
484
assert.strictEqual(ws.getWorkspaceFolders()![1], fourthAddedFolder); // verify object is still live
485
assert.strictEqual(fifthAddedFolder.index, 0);
486
assert.strictEqual(fourthAddedFolder.index, 1);
487
488
//
489
// Add one folder after the other without waiting for confirmation (not supported currently)
490
//
491
492
assert.strictEqual(true, ws.updateWorkspaceFolders(extensionDescriptor, 2, 0, asUpdateWorkspaceFolderData(URI.parse('foo:bar5'))));
493
494
assert.strictEqual(3, ws.workspace!.folders.length);
495
assert.strictEqual(ws.workspace!.folders[0].uri.toString(), URI.parse('foo:bar4').toString());
496
assert.strictEqual(ws.workspace!.folders[1].uri.toString(), URI.parse('foo:bar3').toString());
497
assert.strictEqual(ws.workspace!.folders[2].uri.toString(), URI.parse('foo:bar5').toString());
498
499
const sixthAddedFolder = ws.getWorkspaceFolders()![2];
500
501
gotEvent = false;
502
sub = ws.onDidChangeWorkspace(e => {
503
try {
504
assert.strictEqual(e.added.length, 1);
505
assert.strictEqual(e.added[0], sixthAddedFolder);
506
gotEvent = true;
507
} catch (error) {
508
finish(error);
509
}
510
});
511
ws.$acceptWorkspaceData({
512
id: 'foo', name: 'Test', folders: [
513
aWorkspaceFolderData(URI.parse('foo:bar4'), 0),
514
aWorkspaceFolderData(URI.parse('foo:bar3'), 1),
515
aWorkspaceFolderData(URI.parse('foo:bar5'), 2)
516
]
517
}); // simulate acknowledgement from main side
518
assert.strictEqual(gotEvent, true);
519
sub.dispose();
520
521
assert.strictEqual(ws.getWorkspaceFolders()![0], fifthAddedFolder); // verify object is still live
522
assert.strictEqual(ws.getWorkspaceFolders()![1], fourthAddedFolder); // verify object is still live
523
assert.strictEqual(ws.getWorkspaceFolders()![2], sixthAddedFolder); // verify object is still live
524
525
finish();
526
});
527
528
test('Multiroot change event is immutable', function (done) {
529
let finished = false;
530
const finish = (error?: any) => {
531
if (!finished) {
532
finished = true;
533
done(error);
534
}
535
};
536
537
const ws = createExtHostWorkspace(new TestRPCProtocol(), { id: 'foo', name: 'Test', folders: [] }, new NullLogService());
538
const sub = ws.onDidChangeWorkspace(e => {
539
try {
540
assert.throws(() => {
541
// eslint-disable-next-line local/code-no-any-casts
542
(<any>e).added = [];
543
});
544
// assert.throws(() => {
545
// (<any>e.added)[0] = null;
546
// });
547
} catch (error) {
548
finish(error);
549
}
550
});
551
ws.$acceptWorkspaceData({ id: 'foo', name: 'Test', folders: [] });
552
sub.dispose();
553
finish();
554
});
555
556
test('`vscode.workspace.getWorkspaceFolder(file)` don\'t return workspace folder when file open from command line. #36221', function () {
557
if (isWindows) {
558
559
const ws = createExtHostWorkspace(new TestRPCProtocol(), {
560
id: 'foo', name: 'Test', folders: [
561
aWorkspaceFolderData(URI.file('c:/Users/marek/Desktop/vsc_test/'), 0)
562
]
563
}, new NullLogService());
564
565
assert.ok(ws.getWorkspaceFolder(URI.file('c:/Users/marek/Desktop/vsc_test/a.txt')));
566
assert.ok(ws.getWorkspaceFolder(URI.file('C:/Users/marek/Desktop/vsc_test/b.txt')));
567
}
568
});
569
570
function aWorkspaceFolderData(uri: URI, index: number, name: string = ''): IWorkspaceFolderData {
571
return {
572
uri,
573
index,
574
name: name || basename(uri.path)
575
};
576
}
577
578
function asUpdateWorkspaceFolderData(uri: URI, name?: string): { uri: URI; name?: string } {
579
return { uri, name };
580
}
581
582
suite('findFiles -', function () {
583
test('string include', () => {
584
const root = '/project/foo';
585
const rpcProtocol = new TestRPCProtocol();
586
587
let mainThreadCalled = false;
588
rpcProtocol.set(MainContext.MainThreadWorkspace, new class extends mock<MainThreadWorkspace>() {
589
override $startFileSearch(_includeFolder: UriComponents | null, options: IFileQueryBuilderOptions, token: CancellationToken): Promise<URI[] | null> {
590
mainThreadCalled = true;
591
assert.strictEqual(options.includePattern, 'foo');
592
assert.strictEqual(_includeFolder, null);
593
assert.strictEqual(options.excludePattern, undefined);
594
assert.strictEqual(options.disregardExcludeSettings, false);
595
assert.strictEqual(options.maxResults, 10);
596
return Promise.resolve(null);
597
}
598
});
599
600
const ws = createExtHostWorkspace(rpcProtocol, { id: 'foo', folders: [aWorkspaceFolderData(URI.file(root), 0)], name: 'Test' }, new NullLogService());
601
return ws.findFiles('foo', undefined, 10, new ExtensionIdentifier('test')).then(() => {
602
assert(mainThreadCalled, 'mainThreadCalled');
603
});
604
});
605
606
function testFindFilesInclude(pattern: RelativePattern) {
607
const root = '/project/foo';
608
const rpcProtocol = new TestRPCProtocol();
609
610
let mainThreadCalled = false;
611
rpcProtocol.set(MainContext.MainThreadWorkspace, new class extends mock<MainThreadWorkspace>() {
612
override $startFileSearch(_includeFolder: UriComponents | null, options: IFileQueryBuilderOptions, token: CancellationToken): Promise<URI[] | null> {
613
mainThreadCalled = true;
614
assert.strictEqual(options.includePattern, 'glob/**');
615
assert.deepStrictEqual(_includeFolder ? URI.from(_includeFolder).toJSON() : null, URI.file('/other/folder').toJSON());
616
assert.strictEqual(options.excludePattern, undefined);
617
assert.strictEqual(options.disregardExcludeSettings, false);
618
return Promise.resolve(null);
619
}
620
});
621
622
const ws = createExtHostWorkspace(rpcProtocol, { id: 'foo', folders: [aWorkspaceFolderData(URI.file(root), 0)], name: 'Test' }, new NullLogService());
623
return ws.findFiles(pattern, undefined, 10, new ExtensionIdentifier('test')).then(() => {
624
assert(mainThreadCalled, 'mainThreadCalled');
625
});
626
}
627
628
test('RelativePattern include (string)', () => {
629
return testFindFilesInclude(new RelativePattern('/other/folder', 'glob/**'));
630
});
631
632
test('RelativePattern include (URI)', () => {
633
return testFindFilesInclude(new RelativePattern(URI.file('/other/folder'), 'glob/**'));
634
});
635
636
test('no excludes', () => {
637
const root = '/project/foo';
638
const rpcProtocol = new TestRPCProtocol();
639
640
let mainThreadCalled = false;
641
rpcProtocol.set(MainContext.MainThreadWorkspace, new class extends mock<MainThreadWorkspace>() {
642
override $startFileSearch(_includeFolder: UriComponents | null, options: IFileQueryBuilderOptions, token: CancellationToken): Promise<URI[] | null> {
643
mainThreadCalled = true;
644
assert.strictEqual(options.includePattern, 'glob/**');
645
assert.deepStrictEqual(URI.revive(_includeFolder!).toString(), URI.file('/other/folder').toString());
646
assert.strictEqual(options.excludePattern, undefined);
647
assert.strictEqual(options.disregardExcludeSettings, true);
648
return Promise.resolve(null);
649
}
650
});
651
652
const ws = createExtHostWorkspace(rpcProtocol, { id: 'foo', folders: [aWorkspaceFolderData(URI.file(root), 0)], name: 'Test' }, new NullLogService());
653
return ws.findFiles(new RelativePattern('/other/folder', 'glob/**'), null, 10, new ExtensionIdentifier('test')).then(() => {
654
assert(mainThreadCalled, 'mainThreadCalled');
655
});
656
});
657
658
test('with cancelled token', () => {
659
const root = '/project/foo';
660
const rpcProtocol = new TestRPCProtocol();
661
662
let mainThreadCalled = false;
663
rpcProtocol.set(MainContext.MainThreadWorkspace, new class extends mock<MainThreadWorkspace>() {
664
override $startFileSearch(_includeFolder: UriComponents | null, options: IFileQueryBuilderOptions, token: CancellationToken): Promise<URI[] | null> {
665
mainThreadCalled = true;
666
return Promise.resolve(null);
667
}
668
});
669
670
const ws = createExtHostWorkspace(rpcProtocol, { id: 'foo', folders: [aWorkspaceFolderData(URI.file(root), 0)], name: 'Test' }, new NullLogService());
671
672
const token = CancellationToken.Cancelled;
673
return ws.findFiles(new RelativePattern('/other/folder', 'glob/**'), null, 10, new ExtensionIdentifier('test'), token).then(() => {
674
assert(!mainThreadCalled, '!mainThreadCalled');
675
});
676
});
677
678
test('RelativePattern exclude', () => {
679
const root = '/project/foo';
680
const rpcProtocol = new TestRPCProtocol();
681
682
let mainThreadCalled = false;
683
rpcProtocol.set(MainContext.MainThreadWorkspace, new class extends mock<MainThreadWorkspace>() {
684
override $startFileSearch(_includeFolder: UriComponents | null, options: IFileQueryBuilderOptions, token: CancellationToken): Promise<URI[] | null> {
685
mainThreadCalled = true;
686
assert.strictEqual(options.disregardExcludeSettings, false);
687
assert.strictEqual(options.excludePattern?.length, 1);
688
assert.strictEqual(options.excludePattern[0].pattern, 'glob/**'); // Note that the base portion is ignored, see #52651
689
return Promise.resolve(null);
690
}
691
});
692
693
const ws = createExtHostWorkspace(rpcProtocol, { id: 'foo', folders: [aWorkspaceFolderData(URI.file(root), 0)], name: 'Test' }, new NullLogService());
694
return ws.findFiles('', new RelativePattern(root, 'glob/**'), 10, new ExtensionIdentifier('test')).then(() => {
695
assert(mainThreadCalled, 'mainThreadCalled');
696
});
697
});
698
});
699
700
suite('findFiles2 -', function () {
701
test('string include', () => {
702
const root = '/project/foo';
703
const rpcProtocol = new TestRPCProtocol();
704
705
let mainThreadCalled = false;
706
rpcProtocol.set(MainContext.MainThreadWorkspace, new class extends mock<MainThreadWorkspace>() {
707
override $startFileSearch(_includeFolder: UriComponents | null, options: IFileQueryBuilderOptions, token: CancellationToken): Promise<URI[] | null> {
708
mainThreadCalled = true;
709
assert.strictEqual(options.filePattern, 'foo');
710
assert.strictEqual(options.includePattern, undefined);
711
assert.strictEqual(_includeFolder, null);
712
assert.strictEqual(options.excludePattern, undefined);
713
assert.strictEqual(options.disregardExcludeSettings, false);
714
assert.strictEqual(options.maxResults, 10);
715
return Promise.resolve(null);
716
}
717
});
718
719
const ws = createExtHostWorkspace(rpcProtocol, { id: 'foo', folders: [aWorkspaceFolderData(URI.file(root), 0)], name: 'Test' }, new NullLogService());
720
return ws.findFiles2(['foo'], { maxResults: 10, useExcludeSettings: ExcludeSettingOptions.FilesExclude }, new ExtensionIdentifier('test')).then(() => {
721
assert(mainThreadCalled, 'mainThreadCalled');
722
});
723
});
724
725
function testFindFiles2Include(pattern: RelativePattern[]) {
726
const root = '/project/foo';
727
const rpcProtocol = new TestRPCProtocol();
728
729
let mainThreadCalled = false;
730
rpcProtocol.set(MainContext.MainThreadWorkspace, new class extends mock<MainThreadWorkspace>() {
731
override $startFileSearch(_includeFolder: UriComponents | null, options: IFileQueryBuilderOptions, token: CancellationToken): Promise<URI[] | null> {
732
mainThreadCalled = true;
733
assert.strictEqual(options.filePattern, 'glob/**');
734
assert.strictEqual(options.includePattern, undefined);
735
assert.deepStrictEqual(_includeFolder ? URI.from(_includeFolder).toJSON() : null, URI.file('/other/folder').toJSON());
736
assert.strictEqual(options.excludePattern, undefined);
737
assert.strictEqual(options.disregardExcludeSettings, false);
738
return Promise.resolve(null);
739
}
740
});
741
742
const ws = createExtHostWorkspace(rpcProtocol, { id: 'foo', folders: [aWorkspaceFolderData(URI.file(root), 0)], name: 'Test' }, new NullLogService());
743
return ws.findFiles2(pattern, { maxResults: 10 }, new ExtensionIdentifier('test')).then(() => {
744
assert(mainThreadCalled, 'mainThreadCalled');
745
});
746
}
747
748
test('RelativePattern include (string)', () => {
749
return testFindFiles2Include([new RelativePattern('/other/folder', 'glob/**')]);
750
});
751
752
test('RelativePattern include (URI)', () => {
753
return testFindFiles2Include([new RelativePattern(URI.file('/other/folder'), 'glob/**')]);
754
});
755
756
test('no excludes', () => {
757
const root = '/project/foo';
758
const rpcProtocol = new TestRPCProtocol();
759
760
let mainThreadCalled = false;
761
rpcProtocol.set(MainContext.MainThreadWorkspace, new class extends mock<MainThreadWorkspace>() {
762
override $startFileSearch(_includeFolder: UriComponents | null, options: IFileQueryBuilderOptions, token: CancellationToken): Promise<URI[] | null> {
763
mainThreadCalled = true;
764
assert.strictEqual(options.filePattern, 'glob/**');
765
assert.strictEqual(options.includePattern, undefined);
766
assert.deepStrictEqual(URI.revive(_includeFolder!).toString(), URI.file('/other/folder').toString());
767
assert.strictEqual(options.excludePattern, undefined);
768
assert.strictEqual(options.disregardExcludeSettings, false);
769
return Promise.resolve(null);
770
}
771
});
772
773
const ws = createExtHostWorkspace(rpcProtocol, { id: 'foo', folders: [aWorkspaceFolderData(URI.file(root), 0)], name: 'Test' }, new NullLogService());
774
return ws.findFiles2([new RelativePattern('/other/folder', 'glob/**')], {}, new ExtensionIdentifier('test')).then(() => {
775
assert(mainThreadCalled, 'mainThreadCalled');
776
});
777
});
778
779
test('no dups', () => {
780
const root = '/project/foo';
781
const rpcProtocol = new TestRPCProtocol();
782
783
let mainThreadCalled = false;
784
rpcProtocol.set(MainContext.MainThreadWorkspace, new class extends mock<MainThreadWorkspace>() {
785
override $startFileSearch(_includeFolder: UriComponents | null, options: IFileQueryBuilderOptions, token: CancellationToken): Promise<URI[] | null> {
786
mainThreadCalled = true;
787
assert.strictEqual(options.includePattern, undefined);
788
assert.strictEqual(options.excludePattern, undefined);
789
assert.strictEqual(options.disregardExcludeSettings, false);
790
return Promise.resolve([URI.file(root + '/main.py')]);
791
}
792
});
793
794
// Only add the root directory as a workspace folder - main.py will be a file within it
795
const folders = [aWorkspaceFolderData(URI.file(root), 0)];
796
const ws = createExtHostWorkspace(rpcProtocol, { id: 'foo', folders: folders, name: 'Test' }, new NullLogService());
797
798
return ws.findFiles2(['**/main.py', '**/main.py/**'], {}, new ExtensionIdentifier('test')).then((uris) => {
799
assert(mainThreadCalled, 'mainThreadCalled');
800
assert.equal(uris.length, 1);
801
assert.equal(uris[0].toString(), URI.file(root + '/main.py').toString());
802
});
803
});
804
805
test('with cancelled token', () => {
806
const root = '/project/foo';
807
const rpcProtocol = new TestRPCProtocol();
808
809
let mainThreadCalled = false;
810
rpcProtocol.set(MainContext.MainThreadWorkspace, new class extends mock<MainThreadWorkspace>() {
811
override $startFileSearch(_includeFolder: UriComponents | null, options: IFileQueryBuilderOptions, token: CancellationToken): Promise<URI[] | null> {
812
mainThreadCalled = true;
813
return Promise.resolve(null);
814
}
815
});
816
817
const ws = createExtHostWorkspace(rpcProtocol, { id: 'foo', folders: [aWorkspaceFolderData(URI.file(root), 0)], name: 'Test' }, new NullLogService());
818
819
const token = CancellationToken.Cancelled;
820
return ws.findFiles2([new RelativePattern('/other/folder', 'glob/**')], {}, new ExtensionIdentifier('test'), token).then(() => {
821
assert(!mainThreadCalled, '!mainThreadCalled');
822
});
823
});
824
825
test('RelativePattern exclude', () => {
826
const root = '/project/foo';
827
const rpcProtocol = new TestRPCProtocol();
828
829
let mainThreadCalled = false;
830
rpcProtocol.set(MainContext.MainThreadWorkspace, new class extends mock<MainThreadWorkspace>() {
831
override $startFileSearch(_includeFolder: UriComponents | null, options: IFileQueryBuilderOptions, token: CancellationToken): Promise<URI[] | null> {
832
mainThreadCalled = true;
833
assert.strictEqual(options.disregardExcludeSettings, false);
834
assert.strictEqual(options.excludePattern?.length, 1);
835
assert.strictEqual(options.excludePattern[0].pattern, 'glob/**'); // Note that the base portion is ignored, see #52651
836
return Promise.resolve(null);
837
}
838
});
839
840
const ws = createExtHostWorkspace(rpcProtocol, { id: 'foo', folders: [aWorkspaceFolderData(URI.file(root), 0)], name: 'Test' }, new NullLogService());
841
return ws.findFiles2([''], { exclude: [new RelativePattern(root, 'glob/**')] }, new ExtensionIdentifier('test')).then(() => {
842
assert(mainThreadCalled, 'mainThreadCalled');
843
});
844
});
845
test('useIgnoreFiles', () => {
846
const root = '/project/foo';
847
const rpcProtocol = new TestRPCProtocol();
848
849
let mainThreadCalled = false;
850
rpcProtocol.set(MainContext.MainThreadWorkspace, new class extends mock<MainThreadWorkspace>() {
851
override $startFileSearch(_includeFolder: UriComponents | null, options: IFileQueryBuilderOptions, token: CancellationToken): Promise<URI[] | null> {
852
mainThreadCalled = true;
853
assert.strictEqual(options.disregardExcludeSettings, false);
854
assert.strictEqual(options.disregardIgnoreFiles, false);
855
assert.strictEqual(options.disregardGlobalIgnoreFiles, false);
856
assert.strictEqual(options.disregardParentIgnoreFiles, false);
857
return Promise.resolve(null);
858
}
859
});
860
861
const ws = createExtHostWorkspace(rpcProtocol, { id: 'foo', folders: [aWorkspaceFolderData(URI.file(root), 0)], name: 'Test' }, new NullLogService());
862
return ws.findFiles2([''], { useIgnoreFiles: { local: true, parent: true, global: true } }, new ExtensionIdentifier('test')).then(() => {
863
assert(mainThreadCalled, 'mainThreadCalled');
864
});
865
});
866
867
test('use symlinks', () => {
868
const root = '/project/foo';
869
const rpcProtocol = new TestRPCProtocol();
870
871
let mainThreadCalled = false;
872
rpcProtocol.set(MainContext.MainThreadWorkspace, new class extends mock<MainThreadWorkspace>() {
873
override $startFileSearch(_includeFolder: UriComponents | null, options: IFileQueryBuilderOptions, token: CancellationToken): Promise<URI[] | null> {
874
mainThreadCalled = true;
875
assert.strictEqual(options.ignoreSymlinks, false);
876
return Promise.resolve(null);
877
}
878
});
879
880
const ws = createExtHostWorkspace(rpcProtocol, { id: 'foo', folders: [aWorkspaceFolderData(URI.file(root), 0)], name: 'Test' }, new NullLogService());
881
return ws.findFiles2([''], { followSymlinks: true }, new ExtensionIdentifier('test')).then(() => {
882
assert(mainThreadCalled, 'mainThreadCalled');
883
});
884
});
885
886
// todo: add tests with multiple filePatterns and excludes
887
888
});
889
890
suite('findTextInFiles -', function () {
891
test('no include', async () => {
892
const root = '/project/foo';
893
const rpcProtocol = new TestRPCProtocol();
894
895
let mainThreadCalled = false;
896
rpcProtocol.set(MainContext.MainThreadWorkspace, new class extends mock<MainThreadWorkspace>() {
897
override async $startTextSearch(query: IPatternInfo, folder: UriComponents | null, options: ITextQueryBuilderOptions, requestId: number, token: CancellationToken): Promise<ITextSearchComplete | null> {
898
mainThreadCalled = true;
899
assert.strictEqual(query.pattern, 'foo');
900
assert.strictEqual(folder, null);
901
assert.strictEqual(options.includePattern, undefined);
902
assert.strictEqual(options.excludePattern, undefined);
903
return null;
904
}
905
});
906
907
const ws = createExtHostWorkspace(rpcProtocol, { id: 'foo', folders: [aWorkspaceFolderData(URI.file(root), 0)], name: 'Test' }, new NullLogService());
908
await ws.findTextInFiles({ pattern: 'foo' }, {}, () => { }, new ExtensionIdentifier('test'));
909
assert(mainThreadCalled, 'mainThreadCalled');
910
});
911
912
test('string include', async () => {
913
const root = '/project/foo';
914
const rpcProtocol = new TestRPCProtocol();
915
916
let mainThreadCalled = false;
917
rpcProtocol.set(MainContext.MainThreadWorkspace, new class extends mock<MainThreadWorkspace>() {
918
override async $startTextSearch(query: IPatternInfo, folder: UriComponents | null, options: ITextQueryBuilderOptions, requestId: number, token: CancellationToken): Promise<ITextSearchComplete | null> {
919
mainThreadCalled = true;
920
assert.strictEqual(query.pattern, 'foo');
921
assert.strictEqual(folder, null);
922
assert.strictEqual(options.includePattern, '**/files');
923
assert.strictEqual(options.excludePattern, undefined);
924
return null;
925
}
926
});
927
928
const ws = createExtHostWorkspace(rpcProtocol, { id: 'foo', folders: [aWorkspaceFolderData(URI.file(root), 0)], name: 'Test' }, new NullLogService());
929
await ws.findTextInFiles({ pattern: 'foo' }, { include: '**/files' }, () => { }, new ExtensionIdentifier('test'));
930
assert(mainThreadCalled, 'mainThreadCalled');
931
});
932
933
test('RelativePattern include', async () => {
934
const root = '/project/foo';
935
const rpcProtocol = new TestRPCProtocol();
936
937
let mainThreadCalled = false;
938
rpcProtocol.set(MainContext.MainThreadWorkspace, new class extends mock<MainThreadWorkspace>() {
939
override async $startTextSearch(query: IPatternInfo, folder: UriComponents | null, options: ITextQueryBuilderOptions, requestId: number, token: CancellationToken): Promise<ITextSearchComplete | null> {
940
mainThreadCalled = true;
941
assert.strictEqual(query.pattern, 'foo');
942
assert.deepStrictEqual(URI.revive(folder!).toString(), URI.file('/other/folder').toString());
943
assert.strictEqual(options.includePattern, 'glob/**');
944
assert.strictEqual(options.excludePattern, undefined);
945
return null;
946
}
947
});
948
949
const ws = createExtHostWorkspace(rpcProtocol, { id: 'foo', folders: [aWorkspaceFolderData(URI.file(root), 0)], name: 'Test' }, new NullLogService());
950
await ws.findTextInFiles({ pattern: 'foo' }, { include: new RelativePattern('/other/folder', 'glob/**') }, () => { }, new ExtensionIdentifier('test'));
951
assert(mainThreadCalled, 'mainThreadCalled');
952
});
953
954
test('with cancelled token', async () => {
955
const root = '/project/foo';
956
const rpcProtocol = new TestRPCProtocol();
957
958
let mainThreadCalled = false;
959
rpcProtocol.set(MainContext.MainThreadWorkspace, new class extends mock<MainThreadWorkspace>() {
960
override async $startTextSearch(query: IPatternInfo, folder: UriComponents | null, options: ITextQueryBuilderOptions, requestId: number, token: CancellationToken): Promise<ITextSearchComplete | null> {
961
mainThreadCalled = true;
962
return null;
963
}
964
});
965
966
const ws = createExtHostWorkspace(rpcProtocol, { id: 'foo', folders: [aWorkspaceFolderData(URI.file(root), 0)], name: 'Test' }, new NullLogService());
967
const token = CancellationToken.Cancelled;
968
await ws.findTextInFiles({ pattern: 'foo' }, {}, () => { }, new ExtensionIdentifier('test'), token);
969
assert(!mainThreadCalled, '!mainThreadCalled');
970
});
971
972
test('RelativePattern exclude', async () => {
973
const root = '/project/foo';
974
const rpcProtocol = new TestRPCProtocol();
975
976
let mainThreadCalled = false;
977
rpcProtocol.set(MainContext.MainThreadWorkspace, new class extends mock<MainThreadWorkspace>() {
978
override async $startTextSearch(query: IPatternInfo, folder: UriComponents | null, options: ITextQueryBuilderOptions, requestId: number, token: CancellationToken): Promise<ITextSearchComplete | null> {
979
mainThreadCalled = true;
980
assert.strictEqual(query.pattern, 'foo');
981
assert.deepStrictEqual(folder, null);
982
assert.strictEqual(options.includePattern, undefined);
983
assert.strictEqual(options.excludePattern?.length, 1);
984
assert.strictEqual(options.excludePattern[0].pattern, 'glob/**'); // exclude folder is ignored...
985
return null;
986
}
987
});
988
989
const ws = createExtHostWorkspace(rpcProtocol, { id: 'foo', folders: [aWorkspaceFolderData(URI.file(root), 0)], name: 'Test' }, new NullLogService());
990
await ws.findTextInFiles({ pattern: 'foo' }, { exclude: new RelativePattern('/other/folder', 'glob/**') }, () => { }, new ExtensionIdentifier('test'));
991
assert(mainThreadCalled, 'mainThreadCalled');
992
});
993
});
994
995
suite('findTextInFiles2 -', function () {
996
test('no include', async () => {
997
const root = '/project/foo';
998
const rpcProtocol = new TestRPCProtocol();
999
1000
let mainThreadCalled = false;
1001
rpcProtocol.set(MainContext.MainThreadWorkspace, new class extends mock<MainThreadWorkspace>() {
1002
override async $startTextSearch(query: IPatternInfo, folder: UriComponents | null, options: ITextQueryBuilderOptions, requestId: number, token: CancellationToken): Promise<ITextSearchComplete | null> {
1003
mainThreadCalled = true;
1004
assert.strictEqual(query.pattern, 'foo');
1005
assert.strictEqual(folder, null);
1006
assert.strictEqual(options.includePattern, undefined);
1007
assert.strictEqual(options.excludePattern, undefined);
1008
return null;
1009
}
1010
});
1011
1012
const ws = createExtHostWorkspace(rpcProtocol, { id: 'foo', folders: [aWorkspaceFolderData(URI.file(root), 0)], name: 'Test' }, new NullLogService());
1013
await (ws.findTextInFiles2({ pattern: 'foo' }, {}, new ExtensionIdentifier('test'))).complete;
1014
assert(mainThreadCalled, 'mainThreadCalled');
1015
});
1016
1017
test('string include', async () => {
1018
const root = '/project/foo';
1019
const rpcProtocol = new TestRPCProtocol();
1020
1021
let mainThreadCalled = false;
1022
rpcProtocol.set(MainContext.MainThreadWorkspace, new class extends mock<MainThreadWorkspace>() {
1023
override async $startTextSearch(query: IPatternInfo, folder: UriComponents | null, options: ITextQueryBuilderOptions, requestId: number, token: CancellationToken): Promise<ITextSearchComplete | null> {
1024
mainThreadCalled = true;
1025
assert.strictEqual(query.pattern, 'foo');
1026
assert.strictEqual(folder, null);
1027
assert.strictEqual(options.includePattern, '**/files');
1028
assert.strictEqual(options.excludePattern, undefined);
1029
return null;
1030
}
1031
});
1032
1033
const ws = createExtHostWorkspace(rpcProtocol, { id: 'foo', folders: [aWorkspaceFolderData(URI.file(root), 0)], name: 'Test' }, new NullLogService());
1034
await (ws.findTextInFiles2({ pattern: 'foo' }, { include: ['**/files'] }, new ExtensionIdentifier('test'))).complete;
1035
assert(mainThreadCalled, 'mainThreadCalled');
1036
});
1037
1038
test('RelativePattern include', async () => {
1039
const root = '/project/foo';
1040
const rpcProtocol = new TestRPCProtocol();
1041
1042
let mainThreadCalled = false;
1043
rpcProtocol.set(MainContext.MainThreadWorkspace, new class extends mock<MainThreadWorkspace>() {
1044
override async $startTextSearch(query: IPatternInfo, folder: UriComponents | null, options: ITextQueryBuilderOptions, requestId: number, token: CancellationToken): Promise<ITextSearchComplete | null> {
1045
mainThreadCalled = true;
1046
assert.strictEqual(query.pattern, 'foo');
1047
assert.deepStrictEqual(URI.revive(folder!).toString(), URI.file('/other/folder').toString());
1048
assert.strictEqual(options.includePattern, 'glob/**');
1049
assert.strictEqual(options.excludePattern, undefined);
1050
return null;
1051
}
1052
});
1053
1054
const ws = createExtHostWorkspace(rpcProtocol, { id: 'foo', folders: [aWorkspaceFolderData(URI.file(root), 0)], name: 'Test' }, new NullLogService());
1055
await (ws.findTextInFiles2({ pattern: 'foo' }, { include: [new RelativePattern('/other/folder', 'glob/**')] }, new ExtensionIdentifier('test'))).complete;
1056
assert(mainThreadCalled, 'mainThreadCalled');
1057
});
1058
1059
test('with cancelled token', async () => {
1060
const root = '/project/foo';
1061
const rpcProtocol = new TestRPCProtocol();
1062
1063
let mainThreadCalled = false;
1064
rpcProtocol.set(MainContext.MainThreadWorkspace, new class extends mock<MainThreadWorkspace>() {
1065
override async $startTextSearch(query: IPatternInfo, folder: UriComponents | null, options: ITextQueryBuilderOptions, requestId: number, token: CancellationToken): Promise<ITextSearchComplete | null> {
1066
mainThreadCalled = true;
1067
return null;
1068
}
1069
});
1070
1071
const ws = createExtHostWorkspace(rpcProtocol, { id: 'foo', folders: [aWorkspaceFolderData(URI.file(root), 0)], name: 'Test' }, new NullLogService());
1072
const token = CancellationToken.Cancelled;
1073
await (ws.findTextInFiles2({ pattern: 'foo' }, undefined, new ExtensionIdentifier('test'), token)).complete;
1074
assert(!mainThreadCalled, '!mainThreadCalled');
1075
});
1076
1077
test('RelativePattern exclude', async () => {
1078
const root = '/project/foo';
1079
const rpcProtocol = new TestRPCProtocol();
1080
1081
let mainThreadCalled = false;
1082
rpcProtocol.set(MainContext.MainThreadWorkspace, new class extends mock<MainThreadWorkspace>() {
1083
override async $startTextSearch(query: IPatternInfo, folder: UriComponents | null, options: ITextQueryBuilderOptions, requestId: number, token: CancellationToken): Promise<ITextSearchComplete | null> {
1084
mainThreadCalled = true;
1085
assert.strictEqual(query.pattern, 'foo');
1086
assert.deepStrictEqual(folder, null);
1087
assert.strictEqual(options.includePattern, undefined);
1088
assert.strictEqual(options.excludePattern?.length, 1);
1089
assert.strictEqual(options.excludePattern[0].pattern, 'glob/**'); // exclude folder is ignored...
1090
return null;
1091
}
1092
});
1093
1094
const ws = createExtHostWorkspace(rpcProtocol, { id: 'foo', folders: [aWorkspaceFolderData(URI.file(root), 0)], name: 'Test' }, new NullLogService());
1095
await (ws.findTextInFiles2({ pattern: 'foo' }, { exclude: [new RelativePattern('/other/folder', 'glob/**')] }, new ExtensionIdentifier('test'))).complete;
1096
assert(mainThreadCalled, 'mainThreadCalled');
1097
});
1098
1099
// TODO: test multiple includes/excludess
1100
});
1101
});
1102
1103