Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
microsoft
GitHub Repository: microsoft/vscode
Path: blob/main/src/vs/workbench/api/test/browser/extHostApiCommands.test.ts
3296 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 '../../../../editor/contrib/codeAction/browser/codeAction.js';
7
import '../../../../editor/contrib/codelens/browser/codelens.js';
8
import '../../../../editor/contrib/colorPicker/browser/colorPickerContribution.js';
9
import '../../../../editor/contrib/format/browser/format.js';
10
import '../../../../editor/contrib/gotoSymbol/browser/goToCommands.js';
11
import '../../../../editor/contrib/documentSymbols/browser/documentSymbols.js';
12
import '../../../../editor/contrib/hover/browser/getHover.js';
13
import '../../../../editor/contrib/links/browser/getLinks.js';
14
import '../../../../editor/contrib/parameterHints/browser/provideSignatureHelp.js';
15
import '../../../../editor/contrib/smartSelect/browser/smartSelect.js';
16
import '../../../../editor/contrib/suggest/browser/suggest.js';
17
import '../../../../editor/contrib/rename/browser/rename.js';
18
import '../../../../editor/contrib/inlayHints/browser/inlayHintsController.js';
19
20
import assert from 'assert';
21
import { setUnexpectedErrorHandler, errorHandler } from '../../../../base/common/errors.js';
22
import { URI } from '../../../../base/common/uri.js';
23
import { Event } from '../../../../base/common/event.js';
24
import * as types from '../../common/extHostTypes.js';
25
import { createTextModel } from '../../../../editor/test/common/testTextModel.js';
26
import { TestRPCProtocol } from '../common/testRPCProtocol.js';
27
import { MarkerService } from '../../../../platform/markers/common/markerService.js';
28
import { IMarkerService } from '../../../../platform/markers/common/markers.js';
29
import { ICommandService, CommandsRegistry } from '../../../../platform/commands/common/commands.js';
30
import { IModelService } from '../../../../editor/common/services/model.js';
31
import { ExtHostLanguageFeatures } from '../../common/extHostLanguageFeatures.js';
32
import { MainThreadLanguageFeatures } from '../../browser/mainThreadLanguageFeatures.js';
33
import { ExtHostApiCommands } from '../../common/extHostApiCommands.js';
34
import { ExtHostCommands } from '../../common/extHostCommands.js';
35
import { MainThreadCommands } from '../../browser/mainThreadCommands.js';
36
import { ExtHostDocuments } from '../../common/extHostDocuments.js';
37
import { ExtHostDocumentsAndEditors } from '../../common/extHostDocumentsAndEditors.js';
38
import { MainContext, ExtHostContext } from '../../common/extHost.protocol.js';
39
import { ExtHostDiagnostics } from '../../common/extHostDiagnostics.js';
40
import type * as vscode from 'vscode';
41
import '../../../contrib/search/browser/search.contribution.js';
42
import { ILogService, NullLogService } from '../../../../platform/log/common/log.js';
43
import { ITextModel } from '../../../../editor/common/model.js';
44
import { nullExtensionDescription, IExtensionService } from '../../../services/extensions/common/extensions.js';
45
import { dispose, ImmortalReference } from '../../../../base/common/lifecycle.js';
46
import { IEditorWorkerService } from '../../../../editor/common/services/editorWorker.js';
47
import { mock } from '../../../../base/test/common/mock.js';
48
import { NullApiDeprecationService } from '../../common/extHostApiDeprecationService.js';
49
import { ServiceCollection } from '../../../../platform/instantiation/common/serviceCollection.js';
50
import { SyncDescriptor } from '../../../../platform/instantiation/common/descriptors.js';
51
import { IResolvedTextEditorModel, ITextModelService } from '../../../../editor/common/services/resolverService.js';
52
import { IExtHostFileSystemInfo } from '../../common/extHostFileSystemInfo.js';
53
import { URITransformerService } from '../../common/extHostUriTransformerService.js';
54
import { IOutlineModelService, OutlineModelService } from '../../../../editor/contrib/documentSymbols/browser/outlineModel.js';
55
import { ILanguageFeatureDebounceService, LanguageFeatureDebounceService } from '../../../../editor/common/services/languageFeatureDebounce.js';
56
import { ILanguageFeaturesService } from '../../../../editor/common/services/languageFeatures.js';
57
import { LanguageFeaturesService } from '../../../../editor/common/services/languageFeaturesService.js';
58
import { assertType } from '../../../../base/common/types.js';
59
import { IUriIdentityService } from '../../../../platform/uriIdentity/common/uriIdentity.js';
60
import { IExtHostTelemetry } from '../../common/extHostTelemetry.js';
61
import { IConfigurationService } from '../../../../platform/configuration/common/configuration.js';
62
import { TestConfigurationService } from '../../../../platform/configuration/test/common/testConfigurationService.js';
63
import { IEnvironmentService } from '../../../../platform/environment/common/environment.js';
64
import { TestInstantiationService } from '../../../../platform/instantiation/test/common/instantiationServiceMock.js';
65
import { ensureNoDisposablesAreLeakedInTestSuite } from '../../../../base/test/common/utils.js';
66
import { runWithFakedTimers } from '../../../../base/test/common/timeTravelScheduler.js';
67
import { timeout } from '../../../../base/common/async.js';
68
69
function assertRejects(fn: () => Promise<any>, message: string = 'Expected rejection') {
70
return fn().then(() => assert.ok(false, message), _err => assert.ok(true));
71
}
72
73
function isLocation(value: vscode.Location | vscode.LocationLink): value is vscode.Location {
74
const candidate = value as vscode.Location;
75
return candidate && candidate.uri instanceof URI && candidate.range instanceof types.Range;
76
}
77
78
suite('ExtHostLanguageFeatureCommands', function () {
79
const defaultSelector = { scheme: 'far' };
80
let model: ITextModel;
81
82
let insta: TestInstantiationService;
83
let rpcProtocol: TestRPCProtocol;
84
let extHost: ExtHostLanguageFeatures;
85
let mainThread: MainThreadLanguageFeatures;
86
let commands: ExtHostCommands;
87
let disposables: vscode.Disposable[] = [];
88
89
let originalErrorHandler: (e: any) => any;
90
91
suiteSetup(() => {
92
model = createTextModel(
93
[
94
'This is the first line',
95
'This is the second line',
96
'This is the third line',
97
].join('\n'),
98
undefined,
99
undefined,
100
URI.parse('far://testing/file.b'));
101
originalErrorHandler = errorHandler.getUnexpectedErrorHandler();
102
setUnexpectedErrorHandler(() => { });
103
104
// Use IInstantiationService to get typechecking when instantiating
105
rpcProtocol = new TestRPCProtocol();
106
const services = new ServiceCollection();
107
services.set(IUriIdentityService, new class extends mock<IUriIdentityService>() {
108
override asCanonicalUri(uri: URI): URI {
109
return uri;
110
}
111
});
112
services.set(ILanguageFeaturesService, new SyncDescriptor(LanguageFeaturesService));
113
services.set(IExtensionService, new class extends mock<IExtensionService>() {
114
override async activateByEvent() {
115
116
}
117
override activationEventIsDone(activationEvent: string): boolean {
118
return true;
119
}
120
});
121
services.set(ICommandService, new SyncDescriptor(class extends mock<ICommandService>() {
122
123
override executeCommand(id: string, ...args: any): any {
124
const command = CommandsRegistry.getCommands().get(id);
125
if (!command) {
126
return Promise.reject(new Error(id + ' NOT known'));
127
}
128
const { handler } = command;
129
return Promise.resolve(insta.invokeFunction(handler, ...args));
130
}
131
}));
132
services.set(IEnvironmentService, new class extends mock<IEnvironmentService>() {
133
override isBuilt: boolean = true;
134
override isExtensionDevelopment: boolean = false;
135
});
136
services.set(IMarkerService, new MarkerService());
137
services.set(ILogService, new SyncDescriptor(NullLogService));
138
services.set(ILanguageFeatureDebounceService, new SyncDescriptor(LanguageFeatureDebounceService));
139
services.set(IModelService, new class extends mock<IModelService>() {
140
override getModel() { return model; }
141
override onModelRemoved = Event.None;
142
});
143
services.set(ITextModelService, new class extends mock<ITextModelService>() {
144
override async createModelReference() {
145
return new ImmortalReference<IResolvedTextEditorModel>(new class extends mock<IResolvedTextEditorModel>() {
146
override textEditorModel = model;
147
});
148
}
149
});
150
services.set(IEditorWorkerService, new class extends mock<IEditorWorkerService>() {
151
override async computeMoreMinimalEdits(_uri: any, edits: any) {
152
return edits || undefined;
153
}
154
});
155
services.set(ILanguageFeatureDebounceService, new SyncDescriptor(LanguageFeatureDebounceService));
156
services.set(IOutlineModelService, new SyncDescriptor(OutlineModelService));
157
services.set(IConfigurationService, new TestConfigurationService());
158
159
insta = new TestInstantiationService(services);
160
161
const extHostDocumentsAndEditors = new ExtHostDocumentsAndEditors(rpcProtocol, new NullLogService());
162
extHostDocumentsAndEditors.$acceptDocumentsAndEditorsDelta({
163
addedDocuments: [{
164
isDirty: false,
165
versionId: model.getVersionId(),
166
languageId: model.getLanguageId(),
167
uri: model.uri,
168
lines: model.getValue().split(model.getEOL()),
169
EOL: model.getEOL(),
170
encoding: 'utf8'
171
}]
172
});
173
const extHostDocuments = new ExtHostDocuments(rpcProtocol, extHostDocumentsAndEditors);
174
rpcProtocol.set(ExtHostContext.ExtHostDocuments, extHostDocuments);
175
176
commands = new ExtHostCommands(rpcProtocol, new NullLogService(), new class extends mock<IExtHostTelemetry>() {
177
override onExtensionError(): boolean {
178
return true;
179
}
180
});
181
rpcProtocol.set(ExtHostContext.ExtHostCommands, commands);
182
rpcProtocol.set(MainContext.MainThreadCommands, insta.createInstance(MainThreadCommands, rpcProtocol));
183
ExtHostApiCommands.register(commands);
184
185
const diagnostics = new ExtHostDiagnostics(rpcProtocol, new NullLogService(), new class extends mock<IExtHostFileSystemInfo>() { }, extHostDocumentsAndEditors);
186
rpcProtocol.set(ExtHostContext.ExtHostDiagnostics, diagnostics);
187
188
extHost = new ExtHostLanguageFeatures(rpcProtocol, new URITransformerService(null), extHostDocuments, commands, diagnostics, new NullLogService(), NullApiDeprecationService, new class extends mock<IExtHostTelemetry>() {
189
override onExtensionError(): boolean {
190
return true;
191
}
192
});
193
rpcProtocol.set(ExtHostContext.ExtHostLanguageFeatures, extHost);
194
195
mainThread = rpcProtocol.set(MainContext.MainThreadLanguageFeatures, insta.createInstance(MainThreadLanguageFeatures, rpcProtocol));
196
197
// forcefully create the outline service so that `ensureNoDisposablesAreLeakedInTestSuite` doesn't bark
198
insta.get(IOutlineModelService);
199
200
return rpcProtocol.sync();
201
});
202
203
suiteTeardown(() => {
204
setUnexpectedErrorHandler(originalErrorHandler);
205
model.dispose();
206
mainThread.dispose();
207
208
(<OutlineModelService>insta.get(IOutlineModelService)).dispose();
209
insta.dispose();
210
});
211
212
teardown(() => {
213
disposables = dispose(disposables);
214
return rpcProtocol.sync();
215
});
216
217
ensureNoDisposablesAreLeakedInTestSuite();
218
219
// --- workspace symbols
220
221
function testApiCmd(name: string, fn: () => Promise<any>) {
222
test(name, async function () {
223
await runWithFakedTimers({}, async () => {
224
await fn();
225
await timeout(10000); // API commands for things that allow commands dispose their result delay. This is to be nice
226
// because otherwise properties like command are disposed too early
227
});
228
});
229
230
}
231
232
test('WorkspaceSymbols, invalid arguments', function () {
233
const promises = [
234
assertRejects(() => commands.executeCommand('vscode.executeWorkspaceSymbolProvider')),
235
assertRejects(() => commands.executeCommand('vscode.executeWorkspaceSymbolProvider', null)),
236
assertRejects(() => commands.executeCommand('vscode.executeWorkspaceSymbolProvider', undefined)),
237
assertRejects(() => commands.executeCommand('vscode.executeWorkspaceSymbolProvider', true))
238
];
239
return Promise.all(promises);
240
});
241
242
test('WorkspaceSymbols, back and forth', function () {
243
244
disposables.push(extHost.registerWorkspaceSymbolProvider(nullExtensionDescription, <vscode.WorkspaceSymbolProvider>{
245
provideWorkspaceSymbols(query): any {
246
return [
247
new types.SymbolInformation(query, types.SymbolKind.Array, new types.Range(0, 0, 1, 1), URI.parse('far://testing/first')),
248
new types.SymbolInformation(query, types.SymbolKind.Array, new types.Range(0, 0, 1, 1), URI.parse('far://testing/second'))
249
];
250
}
251
}));
252
253
disposables.push(extHost.registerWorkspaceSymbolProvider(nullExtensionDescription, <vscode.WorkspaceSymbolProvider>{
254
provideWorkspaceSymbols(query): any {
255
return [
256
new types.SymbolInformation(query, types.SymbolKind.Array, new types.Range(0, 0, 1, 1), URI.parse('far://testing/first'))
257
];
258
}
259
}));
260
261
return rpcProtocol.sync().then(() => {
262
return commands.executeCommand<vscode.SymbolInformation[]>('vscode.executeWorkspaceSymbolProvider', 'testing').then(value => {
263
264
assert.strictEqual(value.length, 2); // de-duped
265
for (const info of value) {
266
assert.strictEqual(info instanceof types.SymbolInformation, true);
267
assert.strictEqual(info.name, 'testing');
268
assert.strictEqual(info.kind, types.SymbolKind.Array);
269
}
270
});
271
});
272
});
273
274
test('executeWorkspaceSymbolProvider should accept empty string, #39522', async function () {
275
276
disposables.push(extHost.registerWorkspaceSymbolProvider(nullExtensionDescription, {
277
provideWorkspaceSymbols(): vscode.SymbolInformation[] {
278
return [new types.SymbolInformation('hello', types.SymbolKind.Array, new types.Range(0, 0, 0, 0), URI.parse('foo:bar')) as vscode.SymbolInformation];
279
}
280
}));
281
282
await rpcProtocol.sync();
283
let symbols = await commands.executeCommand<vscode.SymbolInformation[]>('vscode.executeWorkspaceSymbolProvider', '');
284
assert.strictEqual(symbols.length, 1);
285
286
await rpcProtocol.sync();
287
symbols = await commands.executeCommand<vscode.SymbolInformation[]>('vscode.executeWorkspaceSymbolProvider', '*');
288
assert.strictEqual(symbols.length, 1);
289
});
290
291
// --- formatting
292
test('executeFormatDocumentProvider, back and forth', async function () {
293
294
disposables.push(extHost.registerDocumentFormattingEditProvider(nullExtensionDescription, defaultSelector, new class implements vscode.DocumentFormattingEditProvider {
295
provideDocumentFormattingEdits() {
296
return [types.TextEdit.insert(new types.Position(0, 0), '42')];
297
}
298
}));
299
300
await rpcProtocol.sync();
301
const edits = await commands.executeCommand<vscode.SymbolInformation[]>('vscode.executeFormatDocumentProvider', model.uri);
302
assert.strictEqual(edits.length, 1);
303
});
304
305
306
// --- rename
307
test('vscode.prepareRename', async function () {
308
disposables.push(extHost.registerRenameProvider(nullExtensionDescription, defaultSelector, new class implements vscode.RenameProvider {
309
310
prepareRename(document: vscode.TextDocument, position: vscode.Position) {
311
return {
312
range: new types.Range(0, 12, 0, 24),
313
placeholder: 'foooPlaceholder'
314
};
315
}
316
317
provideRenameEdits(document: vscode.TextDocument, position: vscode.Position, newName: string) {
318
const edit = new types.WorkspaceEdit();
319
edit.insert(document.uri, <types.Position>position, newName);
320
return edit;
321
}
322
}));
323
324
await rpcProtocol.sync();
325
326
const data = await commands.executeCommand<{ range: vscode.Range; placeholder: string }>('vscode.prepareRename', model.uri, new types.Position(0, 12));
327
328
assert.ok(data);
329
assert.strictEqual(data.placeholder, 'foooPlaceholder');
330
assert.strictEqual(data.range.start.line, 0);
331
assert.strictEqual(data.range.start.character, 12);
332
assert.strictEqual(data.range.end.line, 0);
333
assert.strictEqual(data.range.end.character, 24);
334
335
});
336
337
test('vscode.executeDocumentRenameProvider', async function () {
338
disposables.push(extHost.registerRenameProvider(nullExtensionDescription, defaultSelector, new class implements vscode.RenameProvider {
339
provideRenameEdits(document: vscode.TextDocument, position: vscode.Position, newName: string) {
340
const edit = new types.WorkspaceEdit();
341
edit.insert(document.uri, <types.Position>position, newName);
342
return edit;
343
}
344
}));
345
346
await rpcProtocol.sync();
347
348
const edit = await commands.executeCommand<vscode.WorkspaceEdit>('vscode.executeDocumentRenameProvider', model.uri, new types.Position(0, 12), 'newNameOfThis');
349
350
assert.ok(edit);
351
assert.strictEqual(edit.has(model.uri), true);
352
const textEdits = edit.get(model.uri);
353
assert.strictEqual(textEdits.length, 1);
354
assert.strictEqual(textEdits[0].newText, 'newNameOfThis');
355
});
356
357
// --- definition
358
359
test('Definition, invalid arguments', function () {
360
const promises = [
361
assertRejects(() => commands.executeCommand('vscode.executeDefinitionProvider')),
362
assertRejects(() => commands.executeCommand('vscode.executeDefinitionProvider', null)),
363
assertRejects(() => commands.executeCommand('vscode.executeDefinitionProvider', undefined)),
364
assertRejects(() => commands.executeCommand('vscode.executeDefinitionProvider', true, false))
365
];
366
367
return Promise.all(promises);
368
});
369
370
test('Definition, back and forth', function () {
371
372
disposables.push(extHost.registerDefinitionProvider(nullExtensionDescription, defaultSelector, <vscode.DefinitionProvider>{
373
provideDefinition(doc: any): any {
374
return new types.Location(doc.uri, new types.Range(1, 0, 0, 0));
375
}
376
}));
377
disposables.push(extHost.registerDefinitionProvider(nullExtensionDescription, defaultSelector, <vscode.DefinitionProvider>{
378
provideDefinition(doc: any): any {
379
// duplicate result will get removed
380
return new types.Location(doc.uri, new types.Range(1, 0, 0, 0));
381
}
382
}));
383
disposables.push(extHost.registerDefinitionProvider(nullExtensionDescription, defaultSelector, <vscode.DefinitionProvider>{
384
provideDefinition(doc: any): any {
385
return [
386
new types.Location(doc.uri, new types.Range(2, 0, 0, 0)),
387
new types.Location(doc.uri, new types.Range(3, 0, 0, 0)),
388
new types.Location(doc.uri, new types.Range(4, 0, 0, 0)),
389
];
390
}
391
}));
392
393
return rpcProtocol.sync().then(() => {
394
return commands.executeCommand<vscode.Location[]>('vscode.executeDefinitionProvider', model.uri, new types.Position(0, 0)).then(values => {
395
assert.strictEqual(values.length, 4);
396
for (const v of values) {
397
assert.ok(v.uri instanceof URI);
398
assert.ok(v.range instanceof types.Range);
399
}
400
});
401
});
402
});
403
404
405
test('Definition, back and forth (sorting & de-deduping)', function () {
406
407
disposables.push(extHost.registerDefinitionProvider(nullExtensionDescription, defaultSelector, <vscode.DefinitionProvider>{
408
provideDefinition(doc: any): any {
409
return new types.Location(URI.parse('file:///b'), new types.Range(1, 0, 0, 0));
410
}
411
}));
412
disposables.push(extHost.registerDefinitionProvider(nullExtensionDescription, defaultSelector, <vscode.DefinitionProvider>{
413
provideDefinition(doc: any): any {
414
// duplicate result will get removed
415
return new types.Location(URI.parse('file:///b'), new types.Range(1, 0, 0, 0));
416
}
417
}));
418
disposables.push(extHost.registerDefinitionProvider(nullExtensionDescription, defaultSelector, <vscode.DefinitionProvider>{
419
provideDefinition(doc: any): any {
420
return [
421
new types.Location(URI.parse('file:///a'), new types.Range(2, 0, 0, 0)),
422
new types.Location(URI.parse('file:///c'), new types.Range(3, 0, 0, 0)),
423
new types.Location(URI.parse('file:///d'), new types.Range(4, 0, 0, 0)),
424
];
425
}
426
}));
427
428
return rpcProtocol.sync().then(() => {
429
return commands.executeCommand<vscode.Location[]>('vscode.executeDefinitionProvider', model.uri, new types.Position(0, 0)).then(values => {
430
assert.strictEqual(values.length, 4);
431
432
assert.strictEqual(values[0].uri.path, '/a');
433
assert.strictEqual(values[1].uri.path, '/b');
434
assert.strictEqual(values[2].uri.path, '/c');
435
assert.strictEqual(values[3].uri.path, '/d');
436
});
437
});
438
});
439
440
test('Definition Link', () => {
441
disposables.push(extHost.registerDefinitionProvider(nullExtensionDescription, defaultSelector, <vscode.DefinitionProvider>{
442
provideDefinition(doc: any): (vscode.Location | vscode.LocationLink)[] {
443
return [
444
new types.Location(doc.uri, new types.Range(0, 0, 0, 0)),
445
{ targetUri: doc.uri, targetRange: new types.Range(1, 0, 0, 0), targetSelectionRange: new types.Range(1, 1, 1, 1), originSelectionRange: new types.Range(2, 2, 2, 2) }
446
];
447
}
448
}));
449
450
return rpcProtocol.sync().then(() => {
451
return commands.executeCommand<(vscode.Location | vscode.LocationLink)[]>('vscode.executeDefinitionProvider', model.uri, new types.Position(0, 0)).then(values => {
452
assert.strictEqual(values.length, 2);
453
for (const v of values) {
454
if (isLocation(v)) {
455
assert.ok(v.uri instanceof URI);
456
assert.ok(v.range instanceof types.Range);
457
} else {
458
assert.ok(v.targetUri instanceof URI);
459
assert.ok(v.targetRange instanceof types.Range);
460
assert.ok(v.targetSelectionRange instanceof types.Range);
461
assert.ok(v.originSelectionRange instanceof types.Range);
462
}
463
}
464
});
465
});
466
});
467
468
// --- declaration
469
470
test('Declaration, back and forth', function () {
471
472
disposables.push(extHost.registerDeclarationProvider(nullExtensionDescription, defaultSelector, <vscode.DeclarationProvider>{
473
provideDeclaration(doc: any): any {
474
return new types.Location(doc.uri, new types.Range(1, 0, 0, 0));
475
}
476
}));
477
disposables.push(extHost.registerDeclarationProvider(nullExtensionDescription, defaultSelector, <vscode.DeclarationProvider>{
478
provideDeclaration(doc: any): any {
479
// duplicate result will get removed
480
return new types.Location(doc.uri, new types.Range(1, 0, 0, 0));
481
}
482
}));
483
disposables.push(extHost.registerDeclarationProvider(nullExtensionDescription, defaultSelector, <vscode.DeclarationProvider>{
484
provideDeclaration(doc: any): any {
485
return [
486
new types.Location(doc.uri, new types.Range(2, 0, 0, 0)),
487
new types.Location(doc.uri, new types.Range(3, 0, 0, 0)),
488
new types.Location(doc.uri, new types.Range(4, 0, 0, 0)),
489
];
490
}
491
}));
492
493
return rpcProtocol.sync().then(() => {
494
return commands.executeCommand<vscode.Location[]>('vscode.executeDeclarationProvider', model.uri, new types.Position(0, 0)).then(values => {
495
assert.strictEqual(values.length, 4);
496
for (const v of values) {
497
assert.ok(v.uri instanceof URI);
498
assert.ok(v.range instanceof types.Range);
499
}
500
});
501
});
502
});
503
504
test('Declaration Link', () => {
505
disposables.push(extHost.registerDeclarationProvider(nullExtensionDescription, defaultSelector, <vscode.DeclarationProvider>{
506
provideDeclaration(doc: any): (vscode.Location | vscode.LocationLink)[] {
507
return [
508
new types.Location(doc.uri, new types.Range(0, 0, 0, 0)),
509
{ targetUri: doc.uri, targetRange: new types.Range(1, 0, 0, 0), targetSelectionRange: new types.Range(1, 1, 1, 1), originSelectionRange: new types.Range(2, 2, 2, 2) }
510
];
511
}
512
}));
513
514
return rpcProtocol.sync().then(() => {
515
return commands.executeCommand<(vscode.Location | vscode.LocationLink)[]>('vscode.executeDeclarationProvider', model.uri, new types.Position(0, 0)).then(values => {
516
assert.strictEqual(values.length, 2);
517
for (const v of values) {
518
if (isLocation(v)) {
519
assert.ok(v.uri instanceof URI);
520
assert.ok(v.range instanceof types.Range);
521
} else {
522
assert.ok(v.targetUri instanceof URI);
523
assert.ok(v.targetRange instanceof types.Range);
524
assert.ok(v.targetSelectionRange instanceof types.Range);
525
assert.ok(v.originSelectionRange instanceof types.Range);
526
}
527
}
528
});
529
});
530
});
531
532
// --- type definition
533
534
test('Type Definition, invalid arguments', function () {
535
const promises = [
536
assertRejects(() => commands.executeCommand('vscode.executeTypeDefinitionProvider')),
537
assertRejects(() => commands.executeCommand('vscode.executeTypeDefinitionProvider', null)),
538
assertRejects(() => commands.executeCommand('vscode.executeTypeDefinitionProvider', undefined)),
539
assertRejects(() => commands.executeCommand('vscode.executeTypeDefinitionProvider', true, false))
540
];
541
542
return Promise.all(promises);
543
});
544
545
test('Type Definition, back and forth', function () {
546
547
disposables.push(extHost.registerTypeDefinitionProvider(nullExtensionDescription, defaultSelector, <vscode.TypeDefinitionProvider>{
548
provideTypeDefinition(doc: any): any {
549
return new types.Location(doc.uri, new types.Range(1, 0, 0, 0));
550
}
551
}));
552
disposables.push(extHost.registerTypeDefinitionProvider(nullExtensionDescription, defaultSelector, <vscode.TypeDefinitionProvider>{
553
provideTypeDefinition(doc: any): any {
554
// duplicate result will get removed
555
return new types.Location(doc.uri, new types.Range(1, 0, 0, 0));
556
}
557
}));
558
disposables.push(extHost.registerTypeDefinitionProvider(nullExtensionDescription, defaultSelector, <vscode.TypeDefinitionProvider>{
559
provideTypeDefinition(doc: any): any {
560
return [
561
new types.Location(doc.uri, new types.Range(2, 0, 0, 0)),
562
new types.Location(doc.uri, new types.Range(3, 0, 0, 0)),
563
new types.Location(doc.uri, new types.Range(4, 0, 0, 0)),
564
];
565
}
566
}));
567
568
return rpcProtocol.sync().then(() => {
569
return commands.executeCommand<vscode.Location[]>('vscode.executeTypeDefinitionProvider', model.uri, new types.Position(0, 0)).then(values => {
570
assert.strictEqual(values.length, 4);
571
for (const v of values) {
572
assert.ok(v.uri instanceof URI);
573
assert.ok(v.range instanceof types.Range);
574
}
575
});
576
});
577
});
578
579
test('Type Definition Link', () => {
580
disposables.push(extHost.registerTypeDefinitionProvider(nullExtensionDescription, defaultSelector, <vscode.TypeDefinitionProvider>{
581
provideTypeDefinition(doc: any): (vscode.Location | vscode.LocationLink)[] {
582
return [
583
new types.Location(doc.uri, new types.Range(0, 0, 0, 0)),
584
{ targetUri: doc.uri, targetRange: new types.Range(1, 0, 0, 0), targetSelectionRange: new types.Range(1, 1, 1, 1), originSelectionRange: new types.Range(2, 2, 2, 2) }
585
];
586
}
587
}));
588
589
return rpcProtocol.sync().then(() => {
590
return commands.executeCommand<(vscode.Location | vscode.LocationLink)[]>('vscode.executeTypeDefinitionProvider', model.uri, new types.Position(0, 0)).then(values => {
591
assert.strictEqual(values.length, 2);
592
for (const v of values) {
593
if (isLocation(v)) {
594
assert.ok(v.uri instanceof URI);
595
assert.ok(v.range instanceof types.Range);
596
} else {
597
assert.ok(v.targetUri instanceof URI);
598
assert.ok(v.targetRange instanceof types.Range);
599
assert.ok(v.targetSelectionRange instanceof types.Range);
600
assert.ok(v.originSelectionRange instanceof types.Range);
601
}
602
}
603
});
604
});
605
});
606
607
// --- implementation
608
609
test('Implementation, invalid arguments', function () {
610
const promises = [
611
assertRejects(() => commands.executeCommand('vscode.executeImplementationProvider')),
612
assertRejects(() => commands.executeCommand('vscode.executeImplementationProvider', null)),
613
assertRejects(() => commands.executeCommand('vscode.executeImplementationProvider', undefined)),
614
assertRejects(() => commands.executeCommand('vscode.executeImplementationProvider', true, false))
615
];
616
617
return Promise.all(promises);
618
});
619
620
test('Implementation, back and forth', function () {
621
622
disposables.push(extHost.registerImplementationProvider(nullExtensionDescription, defaultSelector, <vscode.ImplementationProvider>{
623
provideImplementation(doc: any): any {
624
return new types.Location(doc.uri, new types.Range(1, 0, 0, 0));
625
}
626
}));
627
disposables.push(extHost.registerImplementationProvider(nullExtensionDescription, defaultSelector, <vscode.ImplementationProvider>{
628
provideImplementation(doc: any): any {
629
// duplicate result will get removed
630
return new types.Location(doc.uri, new types.Range(1, 0, 0, 0));
631
}
632
}));
633
disposables.push(extHost.registerImplementationProvider(nullExtensionDescription, defaultSelector, <vscode.ImplementationProvider>{
634
provideImplementation(doc: any): any {
635
return [
636
new types.Location(doc.uri, new types.Range(2, 0, 0, 0)),
637
new types.Location(doc.uri, new types.Range(3, 0, 0, 0)),
638
new types.Location(doc.uri, new types.Range(4, 0, 0, 0)),
639
];
640
}
641
}));
642
643
return rpcProtocol.sync().then(() => {
644
return commands.executeCommand<vscode.Location[]>('vscode.executeImplementationProvider', model.uri, new types.Position(0, 0)).then(values => {
645
assert.strictEqual(values.length, 4);
646
for (const v of values) {
647
assert.ok(v.uri instanceof URI);
648
assert.ok(v.range instanceof types.Range);
649
}
650
});
651
});
652
});
653
654
test('Implementation Definition Link', () => {
655
disposables.push(extHost.registerImplementationProvider(nullExtensionDescription, defaultSelector, <vscode.ImplementationProvider>{
656
provideImplementation(doc: any): (vscode.Location | vscode.LocationLink)[] {
657
return [
658
new types.Location(doc.uri, new types.Range(0, 0, 0, 0)),
659
{ targetUri: doc.uri, targetRange: new types.Range(1, 0, 0, 0), targetSelectionRange: new types.Range(1, 1, 1, 1), originSelectionRange: new types.Range(2, 2, 2, 2) }
660
];
661
}
662
}));
663
664
return rpcProtocol.sync().then(() => {
665
return commands.executeCommand<(vscode.Location | vscode.LocationLink)[]>('vscode.executeImplementationProvider', model.uri, new types.Position(0, 0)).then(values => {
666
assert.strictEqual(values.length, 2);
667
for (const v of values) {
668
if (isLocation(v)) {
669
assert.ok(v.uri instanceof URI);
670
assert.ok(v.range instanceof types.Range);
671
} else {
672
assert.ok(v.targetUri instanceof URI);
673
assert.ok(v.targetRange instanceof types.Range);
674
assert.ok(v.targetSelectionRange instanceof types.Range);
675
assert.ok(v.originSelectionRange instanceof types.Range);
676
}
677
}
678
});
679
});
680
});
681
682
// --- references
683
684
test('reference search, back and forth', function () {
685
686
disposables.push(extHost.registerReferenceProvider(nullExtensionDescription, defaultSelector, <vscode.ReferenceProvider>{
687
provideReferences() {
688
return [
689
new types.Location(URI.parse('some:uri/path'), new types.Range(0, 1, 0, 5))
690
];
691
}
692
}));
693
694
return commands.executeCommand<vscode.Location[]>('vscode.executeReferenceProvider', model.uri, new types.Position(0, 0)).then(values => {
695
assert.strictEqual(values.length, 1);
696
const [first] = values;
697
assert.strictEqual(first.uri.toString(), 'some:uri/path');
698
assert.strictEqual(first.range.start.line, 0);
699
assert.strictEqual(first.range.start.character, 1);
700
assert.strictEqual(first.range.end.line, 0);
701
assert.strictEqual(first.range.end.character, 5);
702
});
703
});
704
705
// --- document highlights
706
707
test('"vscode.executeDocumentHighlights" API has stopped returning DocumentHighlight[]#200056', async function () {
708
709
710
disposables.push(extHost.registerDocumentHighlightProvider(nullExtensionDescription, defaultSelector, <vscode.DocumentHighlightProvider>{
711
provideDocumentHighlights() {
712
return [
713
new types.DocumentHighlight(new types.Range(0, 17, 0, 25), types.DocumentHighlightKind.Read)
714
];
715
}
716
}));
717
718
await rpcProtocol.sync();
719
720
return commands.executeCommand<vscode.DocumentHighlight[]>('vscode.executeDocumentHighlights', model.uri, new types.Position(0, 0)).then(values => {
721
assert.ok(Array.isArray(values));
722
assert.strictEqual(values.length, 1);
723
const [first] = values;
724
assert.strictEqual(first.range.start.line, 0);
725
assert.strictEqual(first.range.start.character, 17);
726
assert.strictEqual(first.range.end.line, 0);
727
assert.strictEqual(first.range.end.character, 25);
728
});
729
730
});
731
732
// --- outline
733
734
test('Outline, back and forth', function () {
735
disposables.push(extHost.registerDocumentSymbolProvider(nullExtensionDescription, defaultSelector, <vscode.DocumentSymbolProvider>{
736
provideDocumentSymbols(): any {
737
return [
738
new types.SymbolInformation('testing1', types.SymbolKind.Enum, new types.Range(1, 0, 1, 0)),
739
new types.SymbolInformation('testing2', types.SymbolKind.Enum, new types.Range(0, 1, 0, 3)),
740
];
741
}
742
}));
743
744
return rpcProtocol.sync().then(() => {
745
return commands.executeCommand<vscode.SymbolInformation[]>('vscode.executeDocumentSymbolProvider', model.uri).then(values => {
746
assert.strictEqual(values.length, 2);
747
const [first, second] = values;
748
assert.strictEqual(first instanceof types.SymbolInformation, true);
749
assert.strictEqual(second instanceof types.SymbolInformation, true);
750
assert.strictEqual(first.name, 'testing2');
751
assert.strictEqual(second.name, 'testing1');
752
});
753
});
754
});
755
756
test('vscode.executeDocumentSymbolProvider command only returns SymbolInformation[] rather than DocumentSymbol[] #57984', function () {
757
disposables.push(extHost.registerDocumentSymbolProvider(nullExtensionDescription, defaultSelector, <vscode.DocumentSymbolProvider>{
758
provideDocumentSymbols(): any {
759
return [
760
new types.SymbolInformation('SymbolInformation', types.SymbolKind.Enum, new types.Range(1, 0, 1, 0))
761
];
762
}
763
}));
764
disposables.push(extHost.registerDocumentSymbolProvider(nullExtensionDescription, defaultSelector, <vscode.DocumentSymbolProvider>{
765
provideDocumentSymbols(): any {
766
const root = new types.DocumentSymbol('DocumentSymbol', 'DocumentSymbol#detail', types.SymbolKind.Enum, new types.Range(1, 0, 1, 0), new types.Range(1, 0, 1, 0));
767
root.children = [new types.DocumentSymbol('DocumentSymbol#child', 'DocumentSymbol#detail#child', types.SymbolKind.Enum, new types.Range(1, 0, 1, 0), new types.Range(1, 0, 1, 0))];
768
return [root];
769
}
770
}));
771
772
return rpcProtocol.sync().then(() => {
773
return commands.executeCommand<(vscode.SymbolInformation & vscode.DocumentSymbol)[]>('vscode.executeDocumentSymbolProvider', model.uri).then(values => {
774
assert.strictEqual(values.length, 2);
775
const [first, second] = values;
776
assert.strictEqual(first instanceof types.SymbolInformation, true);
777
assert.strictEqual(first instanceof types.DocumentSymbol, false);
778
assert.strictEqual(second instanceof types.SymbolInformation, true);
779
assert.strictEqual(first.name, 'DocumentSymbol');
780
assert.strictEqual(first.children.length, 1);
781
assert.strictEqual(second.name, 'SymbolInformation');
782
});
783
});
784
});
785
786
// --- suggest
787
788
testApiCmd('triggerCharacter is null when completion provider is called programmatically #159914', async function () {
789
790
let actualContext: vscode.CompletionContext | undefined;
791
792
disposables.push(extHost.registerCompletionItemProvider(nullExtensionDescription, defaultSelector, <vscode.CompletionItemProvider>{
793
provideCompletionItems(_doc, _pos, _tok, context): any {
794
actualContext = context;
795
return [];
796
}
797
}, []));
798
799
await rpcProtocol.sync();
800
801
await commands.executeCommand<vscode.CompletionList>('vscode.executeCompletionItemProvider', model.uri, new types.Position(0, 4));
802
803
assert.ok(actualContext);
804
assert.deepStrictEqual(actualContext, { triggerKind: types.CompletionTriggerKind.Invoke, triggerCharacter: undefined });
805
806
});
807
808
testApiCmd('Suggest, back and forth', async function () {
809
810
disposables.push(extHost.registerCompletionItemProvider(nullExtensionDescription, defaultSelector, <vscode.CompletionItemProvider>{
811
provideCompletionItems(): any {
812
const a = new types.CompletionItem('item1');
813
a.documentation = new types.MarkdownString('hello_md_string');
814
const b = new types.CompletionItem('item2');
815
b.textEdit = types.TextEdit.replace(new types.Range(0, 4, 0, 8), 'foo'); // overwite after
816
const c = new types.CompletionItem('item3');
817
c.textEdit = types.TextEdit.replace(new types.Range(0, 1, 0, 6), 'foobar'); // overwite before & after
818
819
// snippet string!
820
const d = new types.CompletionItem('item4');
821
d.range = new types.Range(0, 1, 0, 4);// overwite before
822
d.insertText = new types.SnippetString('foo$0bar');
823
return [a, b, c, d];
824
}
825
}, []));
826
827
await rpcProtocol.sync();
828
829
const list = await commands.executeCommand<vscode.CompletionList>('vscode.executeCompletionItemProvider', model.uri, new types.Position(0, 4));
830
assert.ok(list instanceof types.CompletionList);
831
const values = list.items;
832
assert.ok(Array.isArray(values));
833
assert.strictEqual(values.length, 4);
834
const [first, second, third, fourth] = values;
835
assert.strictEqual(first.label, 'item1');
836
assert.strictEqual(first.textEdit, undefined); // no text edit, default ranges
837
assert.ok(!types.Range.isRange(first.range));
838
assert.strictEqual((<types.MarkdownString>first.documentation).value, 'hello_md_string');
839
assert.strictEqual(second.label, 'item2');
840
assert.strictEqual(second.textEdit!.newText, 'foo');
841
assert.strictEqual(second.textEdit!.range.start.line, 0);
842
assert.strictEqual(second.textEdit!.range.start.character, 4);
843
assert.strictEqual(second.textEdit!.range.end.line, 0);
844
assert.strictEqual(second.textEdit!.range.end.character, 8);
845
assert.strictEqual(third.label, 'item3');
846
assert.strictEqual(third.textEdit!.newText, 'foobar');
847
assert.strictEqual(third.textEdit!.range.start.line, 0);
848
assert.strictEqual(third.textEdit!.range.start.character, 1);
849
assert.strictEqual(third.textEdit!.range.end.line, 0);
850
assert.strictEqual(third.textEdit!.range.end.character, 6);
851
assert.strictEqual(fourth.label, 'item4');
852
assert.strictEqual(fourth.textEdit, undefined);
853
const range: any = fourth.range!;
854
assert.ok(types.Range.isRange(range));
855
assert.strictEqual(range.start.line, 0);
856
assert.strictEqual(range.start.character, 1);
857
assert.strictEqual(range.end.line, 0);
858
assert.strictEqual(range.end.character, 4);
859
assert.ok(fourth.insertText instanceof types.SnippetString);
860
assert.strictEqual((<types.SnippetString>fourth.insertText).value, 'foo$0bar');
861
862
});
863
864
testApiCmd('Suggest, return CompletionList !array', async function () {
865
866
disposables.push(extHost.registerCompletionItemProvider(nullExtensionDescription, defaultSelector, <vscode.CompletionItemProvider>{
867
provideCompletionItems(): any {
868
const a = new types.CompletionItem('item1');
869
const b = new types.CompletionItem('item2');
870
return new types.CompletionList(<any>[a, b], true);
871
}
872
}, []));
873
874
await rpcProtocol.sync();
875
876
const list = await commands.executeCommand<vscode.CompletionList>('vscode.executeCompletionItemProvider', model.uri, new types.Position(0, 4));
877
878
assert.ok(list instanceof types.CompletionList);
879
assert.strictEqual(list.isIncomplete, true);
880
});
881
882
testApiCmd('Suggest, resolve completion items', async function () {
883
884
885
let resolveCount = 0;
886
887
disposables.push(extHost.registerCompletionItemProvider(nullExtensionDescription, defaultSelector, <vscode.CompletionItemProvider>{
888
provideCompletionItems(): any {
889
const a = new types.CompletionItem('item1');
890
const b = new types.CompletionItem('item2');
891
const c = new types.CompletionItem('item3');
892
const d = new types.CompletionItem('item4');
893
return new types.CompletionList([a, b, c, d], false);
894
},
895
resolveCompletionItem(item) {
896
resolveCount += 1;
897
return item;
898
}
899
}, []));
900
901
await rpcProtocol.sync();
902
903
const list = await commands.executeCommand<vscode.CompletionList>(
904
'vscode.executeCompletionItemProvider',
905
model.uri,
906
new types.Position(0, 4),
907
undefined,
908
2 // maxItemsToResolve
909
);
910
911
assert.ok(list instanceof types.CompletionList);
912
assert.strictEqual(resolveCount, 2);
913
914
});
915
916
testApiCmd('"vscode.executeCompletionItemProvider" doesnot return a preselect field #53749', async function () {
917
918
919
920
disposables.push(extHost.registerCompletionItemProvider(nullExtensionDescription, defaultSelector, <vscode.CompletionItemProvider>{
921
provideCompletionItems(): any {
922
const a = new types.CompletionItem('item1');
923
a.preselect = true;
924
const b = new types.CompletionItem('item2');
925
const c = new types.CompletionItem('item3');
926
c.preselect = true;
927
const d = new types.CompletionItem('item4');
928
return new types.CompletionList([a, b, c, d], false);
929
}
930
}, []));
931
932
await rpcProtocol.sync();
933
934
const list = await commands.executeCommand<vscode.CompletionList>(
935
'vscode.executeCompletionItemProvider',
936
model.uri,
937
new types.Position(0, 4),
938
undefined
939
);
940
941
assert.ok(list instanceof types.CompletionList);
942
assert.strictEqual(list.items.length, 4);
943
944
const [a, b, c, d] = list.items;
945
assert.strictEqual(a.preselect, true);
946
assert.strictEqual(b.preselect, undefined);
947
assert.strictEqual(c.preselect, true);
948
assert.strictEqual(d.preselect, undefined);
949
});
950
951
testApiCmd('executeCompletionItemProvider doesn\'t capture commitCharacters #58228', async function () {
952
disposables.push(extHost.registerCompletionItemProvider(nullExtensionDescription, defaultSelector, <vscode.CompletionItemProvider>{
953
provideCompletionItems(): any {
954
const a = new types.CompletionItem('item1');
955
a.commitCharacters = ['a', 'b'];
956
const b = new types.CompletionItem('item2');
957
return new types.CompletionList([a, b], false);
958
}
959
}, []));
960
961
await rpcProtocol.sync();
962
963
const list = await commands.executeCommand<vscode.CompletionList>(
964
'vscode.executeCompletionItemProvider',
965
model.uri,
966
new types.Position(0, 4),
967
undefined
968
);
969
970
assert.ok(list instanceof types.CompletionList);
971
assert.strictEqual(list.items.length, 2);
972
973
const [a, b] = list.items;
974
assert.deepStrictEqual(a.commitCharacters, ['a', 'b']);
975
assert.strictEqual(b.commitCharacters, undefined);
976
});
977
978
testApiCmd('vscode.executeCompletionItemProvider returns the wrong CompletionItemKinds in insiders #95715', async function () {
979
disposables.push(extHost.registerCompletionItemProvider(nullExtensionDescription, defaultSelector, <vscode.CompletionItemProvider>{
980
provideCompletionItems(): any {
981
return [
982
new types.CompletionItem('My Method', types.CompletionItemKind.Method),
983
new types.CompletionItem('My Property', types.CompletionItemKind.Property),
984
];
985
}
986
}, []));
987
988
await rpcProtocol.sync();
989
990
const list = await commands.executeCommand<vscode.CompletionList>(
991
'vscode.executeCompletionItemProvider',
992
model.uri,
993
new types.Position(0, 4),
994
undefined
995
);
996
997
assert.ok(list instanceof types.CompletionList);
998
assert.strictEqual(list.items.length, 2);
999
1000
const [a, b] = list.items;
1001
assert.strictEqual(a.kind, types.CompletionItemKind.Method);
1002
assert.strictEqual(b.kind, types.CompletionItemKind.Property);
1003
});
1004
1005
// --- signatureHelp
1006
1007
test('Parameter Hints, back and forth', async () => {
1008
disposables.push(extHost.registerSignatureHelpProvider(nullExtensionDescription, defaultSelector, new class implements vscode.SignatureHelpProvider {
1009
provideSignatureHelp(_document: vscode.TextDocument, _position: vscode.Position, _token: vscode.CancellationToken, context: vscode.SignatureHelpContext): vscode.SignatureHelp {
1010
return {
1011
activeSignature: 0,
1012
activeParameter: 1,
1013
signatures: [
1014
{
1015
label: 'abc',
1016
documentation: `${context.triggerKind === 1 /* vscode.SignatureHelpTriggerKind.Invoke */ ? 'invoked' : 'unknown'} ${context.triggerCharacter}`,
1017
parameters: []
1018
}
1019
]
1020
};
1021
}
1022
}, []));
1023
1024
await rpcProtocol.sync();
1025
1026
const firstValue = await commands.executeCommand<vscode.SignatureHelp>('vscode.executeSignatureHelpProvider', model.uri, new types.Position(0, 1), ',');
1027
assert.strictEqual(firstValue.activeSignature, 0);
1028
assert.strictEqual(firstValue.activeParameter, 1);
1029
assert.strictEqual(firstValue.signatures.length, 1);
1030
assert.strictEqual(firstValue.signatures[0].label, 'abc');
1031
assert.strictEqual(firstValue.signatures[0].documentation, 'invoked ,');
1032
});
1033
1034
// --- quickfix
1035
1036
testApiCmd('QuickFix, back and forth', function () {
1037
disposables.push(extHost.registerCodeActionProvider(nullExtensionDescription, defaultSelector, {
1038
provideCodeActions(): vscode.Command[] {
1039
return [{ command: 'testing', title: 'Title', arguments: [1, 2, true] }];
1040
}
1041
}));
1042
1043
return rpcProtocol.sync().then(() => {
1044
return commands.executeCommand<vscode.Command[]>('vscode.executeCodeActionProvider', model.uri, new types.Range(0, 0, 1, 1)).then(value => {
1045
assert.strictEqual(value.length, 1);
1046
const [first] = value;
1047
assert.strictEqual(first.title, 'Title');
1048
assert.strictEqual(first.command, 'testing');
1049
assert.deepStrictEqual(first.arguments, [1, 2, true]);
1050
});
1051
});
1052
});
1053
1054
testApiCmd('vscode.executeCodeActionProvider results seem to be missing their `command` property #45124', function () {
1055
disposables.push(extHost.registerCodeActionProvider(nullExtensionDescription, defaultSelector, {
1056
provideCodeActions(document, range): vscode.CodeAction[] {
1057
return [{
1058
command: {
1059
arguments: [document, range],
1060
command: 'command',
1061
title: 'command_title',
1062
},
1063
kind: types.CodeActionKind.Empty.append('foo'),
1064
title: 'title',
1065
}];
1066
}
1067
}));
1068
1069
return rpcProtocol.sync().then(() => {
1070
return commands.executeCommand<vscode.CodeAction[]>('vscode.executeCodeActionProvider', model.uri, new types.Range(0, 0, 1, 1)).then(value => {
1071
assert.strictEqual(value.length, 1);
1072
const [first] = value;
1073
assert.ok(first.command);
1074
assert.strictEqual(first.command.command, 'command');
1075
assert.strictEqual(first.command.title, 'command_title');
1076
assert.strictEqual(first.kind!.value, 'foo');
1077
assert.strictEqual(first.title, 'title');
1078
1079
});
1080
});
1081
});
1082
1083
testApiCmd('vscode.executeCodeActionProvider passes Range to provider although Selection is passed in #77997', function () {
1084
disposables.push(extHost.registerCodeActionProvider(nullExtensionDescription, defaultSelector, {
1085
provideCodeActions(document, rangeOrSelection): vscode.CodeAction[] {
1086
return [{
1087
command: {
1088
arguments: [document, rangeOrSelection],
1089
command: 'command',
1090
title: 'command_title',
1091
},
1092
kind: types.CodeActionKind.Empty.append('foo'),
1093
title: 'title',
1094
}];
1095
}
1096
}));
1097
1098
const selection = new types.Selection(0, 0, 1, 1);
1099
1100
return rpcProtocol.sync().then(() => {
1101
return commands.executeCommand<vscode.CodeAction[]>('vscode.executeCodeActionProvider', model.uri, selection).then(value => {
1102
assert.strictEqual(value.length, 1);
1103
const [first] = value;
1104
assert.ok(first.command);
1105
assert.ok(first.command.arguments![1] instanceof types.Selection);
1106
assert.ok(first.command.arguments![1].isEqual(selection));
1107
});
1108
});
1109
});
1110
1111
testApiCmd('vscode.executeCodeActionProvider results seem to be missing their `isPreferred` property #78098', function () {
1112
disposables.push(extHost.registerCodeActionProvider(nullExtensionDescription, defaultSelector, {
1113
provideCodeActions(document, rangeOrSelection): vscode.CodeAction[] {
1114
return [{
1115
command: {
1116
arguments: [document, rangeOrSelection],
1117
command: 'command',
1118
title: 'command_title',
1119
},
1120
kind: types.CodeActionKind.Empty.append('foo'),
1121
title: 'title',
1122
isPreferred: true
1123
}];
1124
}
1125
}));
1126
1127
const selection = new types.Selection(0, 0, 1, 1);
1128
1129
return rpcProtocol.sync().then(() => {
1130
return commands.executeCommand<vscode.CodeAction[]>('vscode.executeCodeActionProvider', model.uri, selection).then(value => {
1131
assert.strictEqual(value.length, 1);
1132
const [first] = value;
1133
assert.strictEqual(first.isPreferred, true);
1134
});
1135
});
1136
});
1137
1138
testApiCmd('resolving code action', async function () {
1139
1140
let didCallResolve = 0;
1141
class MyAction extends types.CodeAction { }
1142
1143
disposables.push(extHost.registerCodeActionProvider(nullExtensionDescription, defaultSelector, {
1144
provideCodeActions(document, rangeOrSelection): vscode.CodeAction[] {
1145
return [new MyAction('title', types.CodeActionKind.Empty.append('foo'))];
1146
},
1147
resolveCodeAction(action): vscode.CodeAction {
1148
assert.ok(action instanceof MyAction);
1149
1150
didCallResolve += 1;
1151
action.title = 'resolved title';
1152
action.edit = new types.WorkspaceEdit();
1153
return action;
1154
}
1155
}));
1156
1157
const selection = new types.Selection(0, 0, 1, 1);
1158
1159
await rpcProtocol.sync();
1160
1161
const value = await commands.executeCommand<vscode.CodeAction[]>('vscode.executeCodeActionProvider', model.uri, selection, undefined, 1000);
1162
assert.strictEqual(didCallResolve, 1);
1163
assert.strictEqual(value.length, 1);
1164
1165
const [first] = value;
1166
assert.strictEqual(first.title, 'title'); // does NOT change
1167
assert.ok(first.edit); // is set
1168
});
1169
1170
// --- code lens
1171
1172
testApiCmd('CodeLens, back and forth', function () {
1173
1174
const complexArg = {
1175
foo() { },
1176
bar() { },
1177
big: extHost
1178
};
1179
1180
disposables.push(extHost.registerCodeLensProvider(nullExtensionDescription, defaultSelector, <vscode.CodeLensProvider>{
1181
provideCodeLenses(): any {
1182
return [new types.CodeLens(new types.Range(0, 0, 1, 1), { title: 'Title', command: 'cmd', arguments: [1, true, complexArg] })];
1183
}
1184
}));
1185
1186
return rpcProtocol.sync().then(() => {
1187
return commands.executeCommand<vscode.CodeLens[]>('vscode.executeCodeLensProvider', model.uri).then(value => {
1188
assert.strictEqual(value.length, 1);
1189
const [first] = value;
1190
1191
assert.strictEqual(first.command!.title, 'Title');
1192
assert.strictEqual(first.command!.command, 'cmd');
1193
assert.strictEqual(first.command!.arguments![0], 1);
1194
assert.strictEqual(first.command!.arguments![1], true);
1195
assert.strictEqual(first.command!.arguments![2], complexArg);
1196
});
1197
});
1198
});
1199
1200
testApiCmd('CodeLens, resolve', async function () {
1201
1202
let resolveCount = 0;
1203
1204
disposables.push(extHost.registerCodeLensProvider(nullExtensionDescription, defaultSelector, <vscode.CodeLensProvider>{
1205
provideCodeLenses(): any {
1206
return [
1207
new types.CodeLens(new types.Range(0, 0, 1, 1)),
1208
new types.CodeLens(new types.Range(0, 0, 1, 1)),
1209
new types.CodeLens(new types.Range(0, 0, 1, 1)),
1210
new types.CodeLens(new types.Range(0, 0, 1, 1), { title: 'Already resolved', command: 'fff' })
1211
];
1212
},
1213
resolveCodeLens(codeLens: types.CodeLens) {
1214
codeLens.command = { title: resolveCount.toString(), command: 'resolved' };
1215
resolveCount += 1;
1216
return codeLens;
1217
}
1218
}));
1219
1220
await rpcProtocol.sync();
1221
1222
let value = await commands.executeCommand<vscode.CodeLens[]>('vscode.executeCodeLensProvider', model.uri, 2);
1223
1224
assert.strictEqual(value.length, 3); // the resolve argument defines the number of results being returned
1225
assert.strictEqual(resolveCount, 2);
1226
1227
resolveCount = 0;
1228
value = await commands.executeCommand<vscode.CodeLens[]>('vscode.executeCodeLensProvider', model.uri);
1229
1230
assert.strictEqual(value.length, 4);
1231
assert.strictEqual(resolveCount, 0);
1232
});
1233
1234
testApiCmd('Links, back and forth', function () {
1235
1236
disposables.push(extHost.registerDocumentLinkProvider(nullExtensionDescription, defaultSelector, <vscode.DocumentLinkProvider>{
1237
provideDocumentLinks(): any {
1238
return [new types.DocumentLink(new types.Range(0, 0, 0, 20), URI.parse('foo:bar'))];
1239
}
1240
}));
1241
1242
return rpcProtocol.sync().then(() => {
1243
return commands.executeCommand<vscode.DocumentLink[]>('vscode.executeLinkProvider', model.uri).then(value => {
1244
assert.strictEqual(value.length, 1);
1245
const [first] = value;
1246
1247
assert.strictEqual(first.target + '', 'foo:bar');
1248
assert.strictEqual(first.range.start.line, 0);
1249
assert.strictEqual(first.range.start.character, 0);
1250
assert.strictEqual(first.range.end.line, 0);
1251
assert.strictEqual(first.range.end.character, 20);
1252
});
1253
});
1254
});
1255
1256
testApiCmd('What\'s the condition for DocumentLink target to be undefined? #106308', async function () {
1257
disposables.push(extHost.registerDocumentLinkProvider(nullExtensionDescription, defaultSelector, <vscode.DocumentLinkProvider>{
1258
provideDocumentLinks(): any {
1259
return [new types.DocumentLink(new types.Range(0, 0, 0, 20), undefined)];
1260
},
1261
resolveDocumentLink(link) {
1262
link.target = URI.parse('foo:bar');
1263
return link;
1264
}
1265
}));
1266
1267
await rpcProtocol.sync();
1268
1269
const links1 = await commands.executeCommand<vscode.DocumentLink[]>('vscode.executeLinkProvider', model.uri);
1270
assert.strictEqual(links1.length, 1);
1271
assert.strictEqual(links1[0].target, undefined);
1272
1273
const links2 = await commands.executeCommand<vscode.DocumentLink[]>('vscode.executeLinkProvider', model.uri, 1000);
1274
assert.strictEqual(links2.length, 1);
1275
assert.strictEqual(links2[0].target!.toString(), URI.parse('foo:bar').toString());
1276
1277
});
1278
1279
testApiCmd('DocumentLink[] vscode.executeLinkProvider returns lack tooltip #213970', async function () {
1280
disposables.push(extHost.registerDocumentLinkProvider(nullExtensionDescription, defaultSelector, <vscode.DocumentLinkProvider>{
1281
provideDocumentLinks(): any {
1282
const link = new types.DocumentLink(new types.Range(0, 0, 0, 20), URI.parse('foo:bar'));
1283
link.tooltip = 'Link Tooltip';
1284
return [link];
1285
}
1286
}));
1287
1288
await rpcProtocol.sync();
1289
1290
const links1 = await commands.executeCommand<vscode.DocumentLink[]>('vscode.executeLinkProvider', model.uri);
1291
assert.strictEqual(links1.length, 1);
1292
assert.strictEqual(links1[0].tooltip, 'Link Tooltip');
1293
});
1294
1295
1296
test('Color provider', function () {
1297
1298
disposables.push(extHost.registerColorProvider(nullExtensionDescription, defaultSelector, <vscode.DocumentColorProvider>{
1299
provideDocumentColors(): vscode.ColorInformation[] {
1300
return [new types.ColorInformation(new types.Range(0, 0, 0, 20), new types.Color(0.1, 0.2, 0.3, 0.4))];
1301
},
1302
provideColorPresentations(): vscode.ColorPresentation[] {
1303
const cp = new types.ColorPresentation('#ABC');
1304
cp.textEdit = types.TextEdit.replace(new types.Range(1, 0, 1, 20), '#ABC');
1305
cp.additionalTextEdits = [types.TextEdit.insert(new types.Position(2, 20), '*')];
1306
return [cp];
1307
}
1308
}));
1309
1310
return rpcProtocol.sync().then(() => {
1311
return commands.executeCommand<vscode.ColorInformation[]>('vscode.executeDocumentColorProvider', model.uri).then(value => {
1312
assert.strictEqual(value.length, 1);
1313
const [first] = value;
1314
1315
assert.strictEqual(first.color.red, 0.1);
1316
assert.strictEqual(first.color.green, 0.2);
1317
assert.strictEqual(first.color.blue, 0.3);
1318
assert.strictEqual(first.color.alpha, 0.4);
1319
assert.strictEqual(first.range.start.line, 0);
1320
assert.strictEqual(first.range.start.character, 0);
1321
assert.strictEqual(first.range.end.line, 0);
1322
assert.strictEqual(first.range.end.character, 20);
1323
});
1324
}).then(() => {
1325
const color = new types.Color(0.5, 0.6, 0.7, 0.8);
1326
const range = new types.Range(0, 0, 0, 20);
1327
return commands.executeCommand<vscode.ColorPresentation[]>('vscode.executeColorPresentationProvider', color, { uri: model.uri, range }).then(value => {
1328
assert.strictEqual(value.length, 1);
1329
const [first] = value;
1330
1331
assert.strictEqual(first.label, '#ABC');
1332
assert.strictEqual(first.textEdit!.newText, '#ABC');
1333
assert.strictEqual(first.textEdit!.range.start.line, 1);
1334
assert.strictEqual(first.textEdit!.range.start.character, 0);
1335
assert.strictEqual(first.textEdit!.range.end.line, 1);
1336
assert.strictEqual(first.textEdit!.range.end.character, 20);
1337
assert.strictEqual(first.additionalTextEdits!.length, 1);
1338
assert.strictEqual(first.additionalTextEdits![0].range.start.line, 2);
1339
assert.strictEqual(first.additionalTextEdits![0].range.start.character, 20);
1340
assert.strictEqual(first.additionalTextEdits![0].range.end.line, 2);
1341
assert.strictEqual(first.additionalTextEdits![0].range.end.character, 20);
1342
});
1343
});
1344
});
1345
1346
test('"TypeError: e.onCancellationRequested is not a function" calling hover provider in Insiders #54174', function () {
1347
1348
disposables.push(extHost.registerHoverProvider(nullExtensionDescription, defaultSelector, <vscode.HoverProvider>{
1349
provideHover(): any {
1350
return new types.Hover('fofofofo');
1351
}
1352
}));
1353
1354
return rpcProtocol.sync().then(() => {
1355
return commands.executeCommand<vscode.Hover[]>('vscode.executeHoverProvider', model.uri, new types.Position(1, 1)).then(value => {
1356
assert.strictEqual(value.length, 1);
1357
assert.strictEqual(value[0].contents.length, 1);
1358
});
1359
});
1360
});
1361
1362
// --- inline hints
1363
1364
testApiCmd('Inlay Hints, back and forth', async function () {
1365
disposables.push(extHost.registerInlayHintsProvider(nullExtensionDescription, defaultSelector, <vscode.InlayHintsProvider>{
1366
provideInlayHints() {
1367
return [new types.InlayHint(new types.Position(0, 1), 'Foo')];
1368
}
1369
}));
1370
1371
await rpcProtocol.sync();
1372
1373
const value = await commands.executeCommand<vscode.InlayHint[]>('vscode.executeInlayHintProvider', model.uri, new types.Range(0, 0, 20, 20));
1374
assert.strictEqual(value.length, 1);
1375
1376
const [first] = value;
1377
assert.strictEqual(first.label, 'Foo');
1378
assert.strictEqual(first.position.line, 0);
1379
assert.strictEqual(first.position.character, 1);
1380
});
1381
1382
testApiCmd('Inline Hints, merge', async function () {
1383
disposables.push(extHost.registerInlayHintsProvider(nullExtensionDescription, defaultSelector, <vscode.InlayHintsProvider>{
1384
provideInlayHints() {
1385
const part = new types.InlayHintLabelPart('Bar');
1386
part.tooltip = 'part_tooltip';
1387
part.command = { command: 'cmd', title: 'part' };
1388
const hint = new types.InlayHint(new types.Position(10, 11), [part]);
1389
hint.tooltip = 'hint_tooltip';
1390
hint.paddingLeft = true;
1391
hint.paddingRight = false;
1392
return [hint];
1393
}
1394
}));
1395
1396
disposables.push(extHost.registerInlayHintsProvider(nullExtensionDescription, defaultSelector, <vscode.InlayHintsProvider>{
1397
provideInlayHints() {
1398
const hint = new types.InlayHint(new types.Position(0, 1), 'Foo', types.InlayHintKind.Parameter);
1399
hint.textEdits = [types.TextEdit.insert(new types.Position(0, 0), 'Hello')];
1400
return [hint];
1401
}
1402
}));
1403
1404
await rpcProtocol.sync();
1405
1406
const value = await commands.executeCommand<vscode.InlayHint[]>('vscode.executeInlayHintProvider', model.uri, new types.Range(0, 0, 20, 20));
1407
assert.strictEqual(value.length, 2);
1408
1409
const [first, second] = value;
1410
assert.strictEqual(first.label, 'Foo');
1411
assert.strictEqual(first.position.line, 0);
1412
assert.strictEqual(first.position.character, 1);
1413
assert.strictEqual(first.textEdits?.length, 1);
1414
assert.strictEqual(first.textEdits[0].newText, 'Hello');
1415
1416
assert.strictEqual(second.position.line, 10);
1417
assert.strictEqual(second.position.character, 11);
1418
assert.strictEqual(second.paddingLeft, true);
1419
assert.strictEqual(second.paddingRight, false);
1420
assert.strictEqual(second.tooltip, 'hint_tooltip');
1421
1422
const label = (<types.InlayHintLabelPart[]>second.label)[0];
1423
assertType(label instanceof types.InlayHintLabelPart);
1424
assert.strictEqual(label.value, 'Bar');
1425
assert.strictEqual(label.tooltip, 'part_tooltip');
1426
assert.strictEqual(label.command?.command, 'cmd');
1427
assert.strictEqual(label.command?.title, 'part');
1428
});
1429
1430
testApiCmd('Inline Hints, bad provider', async function () {
1431
disposables.push(extHost.registerInlayHintsProvider(nullExtensionDescription, defaultSelector, <vscode.InlayHintsProvider>{
1432
provideInlayHints() {
1433
return [new types.InlayHint(new types.Position(0, 1), 'Foo')];
1434
}
1435
}));
1436
disposables.push(extHost.registerInlayHintsProvider(nullExtensionDescription, defaultSelector, <vscode.InlayHintsProvider>{
1437
provideInlayHints() {
1438
throw new Error();
1439
}
1440
}));
1441
1442
await rpcProtocol.sync();
1443
1444
const value = await commands.executeCommand<vscode.InlayHint[]>('vscode.executeInlayHintProvider', model.uri, new types.Range(0, 0, 20, 20));
1445
assert.strictEqual(value.length, 1);
1446
1447
const [first] = value;
1448
assert.strictEqual(first.label, 'Foo');
1449
assert.strictEqual(first.position.line, 0);
1450
assert.strictEqual(first.position.character, 1);
1451
});
1452
1453
// --- selection ranges
1454
1455
test('Selection Range, back and forth', async function () {
1456
1457
disposables.push(extHost.registerSelectionRangeProvider(nullExtensionDescription, defaultSelector, <vscode.SelectionRangeProvider>{
1458
provideSelectionRanges() {
1459
return [
1460
new types.SelectionRange(new types.Range(0, 10, 0, 18), new types.SelectionRange(new types.Range(0, 2, 0, 20))),
1461
];
1462
}
1463
}));
1464
1465
await rpcProtocol.sync();
1466
const value = await commands.executeCommand<vscode.SelectionRange[]>('vscode.executeSelectionRangeProvider', model.uri, [new types.Position(0, 10)]);
1467
assert.strictEqual(value.length, 1);
1468
assert.ok(value[0].parent);
1469
});
1470
1471
// --- call hierarchy
1472
1473
test('CallHierarchy, back and forth', async function () {
1474
1475
disposables.push(extHost.registerCallHierarchyProvider(nullExtensionDescription, defaultSelector, new class implements vscode.CallHierarchyProvider {
1476
1477
prepareCallHierarchy(document: vscode.TextDocument, position: vscode.Position,): vscode.ProviderResult<vscode.CallHierarchyItem> {
1478
return new types.CallHierarchyItem(types.SymbolKind.Constant, 'ROOT', 'ROOT', document.uri, new types.Range(0, 0, 0, 0), new types.Range(0, 0, 0, 0));
1479
}
1480
1481
provideCallHierarchyIncomingCalls(item: vscode.CallHierarchyItem, token: vscode.CancellationToken): vscode.ProviderResult<vscode.CallHierarchyIncomingCall[]> {
1482
1483
return [new types.CallHierarchyIncomingCall(
1484
new types.CallHierarchyItem(types.SymbolKind.Constant, 'INCOMING', 'INCOMING', item.uri, new types.Range(0, 0, 0, 0), new types.Range(0, 0, 0, 0)),
1485
[new types.Range(0, 0, 0, 0)]
1486
)];
1487
}
1488
1489
provideCallHierarchyOutgoingCalls(item: vscode.CallHierarchyItem, token: vscode.CancellationToken): vscode.ProviderResult<vscode.CallHierarchyOutgoingCall[]> {
1490
return [new types.CallHierarchyOutgoingCall(
1491
new types.CallHierarchyItem(types.SymbolKind.Constant, 'OUTGOING', 'OUTGOING', item.uri, new types.Range(0, 0, 0, 0), new types.Range(0, 0, 0, 0)),
1492
[new types.Range(0, 0, 0, 0)]
1493
)];
1494
}
1495
}));
1496
1497
await rpcProtocol.sync();
1498
1499
const root = await commands.executeCommand<vscode.CallHierarchyItem[]>('vscode.prepareCallHierarchy', model.uri, new types.Position(0, 0));
1500
1501
assert.ok(Array.isArray(root));
1502
assert.strictEqual(root.length, 1);
1503
assert.strictEqual(root[0].name, 'ROOT');
1504
1505
const incoming = await commands.executeCommand<vscode.CallHierarchyIncomingCall[]>('vscode.provideIncomingCalls', root[0]);
1506
assert.strictEqual(incoming.length, 1);
1507
assert.strictEqual(incoming[0].from.name, 'INCOMING');
1508
1509
const outgoing = await commands.executeCommand<vscode.CallHierarchyOutgoingCall[]>('vscode.provideOutgoingCalls', root[0]);
1510
assert.strictEqual(outgoing.length, 1);
1511
assert.strictEqual(outgoing[0].to.name, 'OUTGOING');
1512
});
1513
1514
test('prepareCallHierarchy throws TypeError if clangd returns empty result #137415', async function () {
1515
1516
disposables.push(extHost.registerCallHierarchyProvider(nullExtensionDescription, defaultSelector, new class implements vscode.CallHierarchyProvider {
1517
prepareCallHierarchy(document: vscode.TextDocument, position: vscode.Position,): vscode.ProviderResult<vscode.CallHierarchyItem[]> {
1518
return [];
1519
}
1520
provideCallHierarchyIncomingCalls(item: vscode.CallHierarchyItem, token: vscode.CancellationToken): vscode.ProviderResult<vscode.CallHierarchyIncomingCall[]> {
1521
return [];
1522
}
1523
provideCallHierarchyOutgoingCalls(item: vscode.CallHierarchyItem, token: vscode.CancellationToken): vscode.ProviderResult<vscode.CallHierarchyOutgoingCall[]> {
1524
return [];
1525
}
1526
}));
1527
1528
await rpcProtocol.sync();
1529
1530
const root = await commands.executeCommand<vscode.CallHierarchyItem[]>('vscode.prepareCallHierarchy', model.uri, new types.Position(0, 0));
1531
1532
assert.ok(Array.isArray(root));
1533
assert.strictEqual(root.length, 0);
1534
});
1535
1536
// --- type hierarchy
1537
1538
test('TypeHierarchy, back and forth', async function () {
1539
1540
1541
disposables.push(extHost.registerTypeHierarchyProvider(nullExtensionDescription, defaultSelector, new class implements vscode.TypeHierarchyProvider {
1542
prepareTypeHierarchy(document: vscode.TextDocument, position: vscode.Position, token: vscode.CancellationToken): vscode.ProviderResult<vscode.TypeHierarchyItem[]> {
1543
return [new types.TypeHierarchyItem(types.SymbolKind.Constant, 'ROOT', 'ROOT', document.uri, new types.Range(0, 0, 0, 0), new types.Range(0, 0, 0, 0))];
1544
}
1545
provideTypeHierarchySupertypes(item: vscode.TypeHierarchyItem, token: vscode.CancellationToken): vscode.ProviderResult<vscode.TypeHierarchyItem[]> {
1546
return [new types.TypeHierarchyItem(types.SymbolKind.Constant, 'SUPER', 'SUPER', item.uri, new types.Range(0, 0, 0, 0), new types.Range(0, 0, 0, 0))];
1547
}
1548
provideTypeHierarchySubtypes(item: vscode.TypeHierarchyItem, token: vscode.CancellationToken): vscode.ProviderResult<vscode.TypeHierarchyItem[]> {
1549
return [new types.TypeHierarchyItem(types.SymbolKind.Constant, 'SUB', 'SUB', item.uri, new types.Range(0, 0, 0, 0), new types.Range(0, 0, 0, 0))];
1550
}
1551
}));
1552
1553
await rpcProtocol.sync();
1554
1555
const root = await commands.executeCommand<vscode.TypeHierarchyItem[]>('vscode.prepareTypeHierarchy', model.uri, new types.Position(0, 0));
1556
1557
assert.ok(Array.isArray(root));
1558
assert.strictEqual(root.length, 1);
1559
assert.strictEqual(root[0].name, 'ROOT');
1560
1561
const incoming = await commands.executeCommand<vscode.TypeHierarchyItem[]>('vscode.provideSupertypes', root[0]);
1562
assert.strictEqual(incoming.length, 1);
1563
assert.strictEqual(incoming[0].name, 'SUPER');
1564
1565
const outgoing = await commands.executeCommand<vscode.TypeHierarchyItem[]>('vscode.provideSubtypes', root[0]);
1566
assert.strictEqual(outgoing.length, 1);
1567
assert.strictEqual(outgoing[0].name, 'SUB');
1568
});
1569
1570
test('selectionRangeProvider on inner array always returns outer array #91852', async function () {
1571
1572
disposables.push(extHost.registerSelectionRangeProvider(nullExtensionDescription, defaultSelector, <vscode.SelectionRangeProvider>{
1573
provideSelectionRanges(_doc, positions) {
1574
const [first] = positions;
1575
return [
1576
new types.SelectionRange(new types.Range(first.line, first.character, first.line, first.character)),
1577
];
1578
}
1579
}));
1580
1581
await rpcProtocol.sync();
1582
const value = await commands.executeCommand<vscode.SelectionRange[]>('vscode.executeSelectionRangeProvider', model.uri, [new types.Position(0, 10)]);
1583
assert.strictEqual(value.length, 1);
1584
assert.strictEqual(value[0].range.start.line, 0);
1585
assert.strictEqual(value[0].range.start.character, 10);
1586
assert.strictEqual(value[0].range.end.line, 0);
1587
assert.strictEqual(value[0].range.end.character, 10);
1588
});
1589
1590
test('more element test of selectionRangeProvider on inner array always returns outer array #91852', async function () {
1591
1592
disposables.push(extHost.registerSelectionRangeProvider(nullExtensionDescription, defaultSelector, <vscode.SelectionRangeProvider>{
1593
provideSelectionRanges(_doc, positions) {
1594
const [first, second] = positions;
1595
return [
1596
new types.SelectionRange(new types.Range(first.line, first.character, first.line, first.character)),
1597
new types.SelectionRange(new types.Range(second.line, second.character, second.line, second.character)),
1598
];
1599
}
1600
}));
1601
1602
await rpcProtocol.sync();
1603
const value = await commands.executeCommand<vscode.SelectionRange[]>(
1604
'vscode.executeSelectionRangeProvider',
1605
model.uri,
1606
[new types.Position(0, 0), new types.Position(0, 10)]
1607
);
1608
assert.strictEqual(value.length, 2);
1609
assert.strictEqual(value[0].range.start.line, 0);
1610
assert.strictEqual(value[0].range.start.character, 0);
1611
assert.strictEqual(value[0].range.end.line, 0);
1612
assert.strictEqual(value[0].range.end.character, 0);
1613
assert.strictEqual(value[1].range.start.line, 0);
1614
assert.strictEqual(value[1].range.start.character, 10);
1615
assert.strictEqual(value[1].range.end.line, 0);
1616
assert.strictEqual(value[1].range.end.character, 10);
1617
});
1618
});
1619
1620