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