Merge pull request #192589 from microsoft/joh/personal-snipe

more `ensureNoDisposablesAreLeakedInTestSuite` work
This commit is contained in:
Johannes Rieken
2023-09-08 17:56:50 +02:00
committed by GitHub
9 changed files with 208 additions and 153 deletions

View File

@@ -6,6 +6,7 @@ import * as assert from 'assert';
import { CancellationToken } from 'vs/base/common/cancellation'; import { CancellationToken } from 'vs/base/common/cancellation';
import { DisposableStore } from 'vs/base/common/lifecycle'; import { DisposableStore } from 'vs/base/common/lifecycle';
import { URI } from 'vs/base/common/uri'; import { URI } from 'vs/base/common/uri';
import { ensureNoDisposablesAreLeakedInTestSuite } from 'vs/base/test/common/utils';
import { Range } from 'vs/editor/common/core/range'; import { Range } from 'vs/editor/common/core/range';
import { LanguageFeatureRegistry } from 'vs/editor/common/languageFeatureRegistry'; import { LanguageFeatureRegistry } from 'vs/editor/common/languageFeatureRegistry';
import * as languages from 'vs/editor/common/languages'; import * as languages from 'vs/editor/common/languages';
@@ -105,6 +106,8 @@ suite('CodeAction', () => {
disposables.clear(); disposables.clear();
}); });
ensureNoDisposablesAreLeakedInTestSuite();
test('CodeActions are sorted by type, #38623', async () => { test('CodeActions are sorted by type, #38623', async () => {
const provider = staticCodeActionProvider( const provider = staticCodeActionProvider(
@@ -130,7 +133,7 @@ suite('CodeAction', () => {
new CodeActionItem(testData.tsLint.abc, provider) new CodeActionItem(testData.tsLint.abc, provider)
]; ];
const { validActions: actions } = await getCodeActions(registry, model, new Range(1, 1, 2, 1), { type: languages.CodeActionTriggerType.Invoke, triggerAction: CodeActionTriggerSource.Default }, Progress.None, CancellationToken.None); const { validActions: actions } = disposables.add(await getCodeActions(registry, model, new Range(1, 1, 2, 1), { type: languages.CodeActionTriggerType.Invoke, triggerAction: CodeActionTriggerSource.Default }, Progress.None, CancellationToken.None));
assert.strictEqual(actions.length, 6); assert.strictEqual(actions.length, 6);
assert.deepStrictEqual(actions, expected); assert.deepStrictEqual(actions, expected);
}); });
@@ -145,20 +148,20 @@ suite('CodeAction', () => {
disposables.add(registry.register('fooLang', provider)); disposables.add(registry.register('fooLang', provider));
{ {
const { validActions: actions } = await getCodeActions(registry, model, new Range(1, 1, 2, 1), { type: languages.CodeActionTriggerType.Auto, triggerAction: CodeActionTriggerSource.Default, filter: { include: new CodeActionKind('a') } }, Progress.None, CancellationToken.None); const { validActions: actions } = disposables.add(await getCodeActions(registry, model, new Range(1, 1, 2, 1), { type: languages.CodeActionTriggerType.Auto, triggerAction: CodeActionTriggerSource.Default, filter: { include: new CodeActionKind('a') } }, Progress.None, CancellationToken.None));
assert.strictEqual(actions.length, 2); assert.strictEqual(actions.length, 2);
assert.strictEqual(actions[0].action.title, 'a'); assert.strictEqual(actions[0].action.title, 'a');
assert.strictEqual(actions[1].action.title, 'a.b'); assert.strictEqual(actions[1].action.title, 'a.b');
} }
{ {
const { validActions: actions } = await getCodeActions(registry, model, new Range(1, 1, 2, 1), { type: languages.CodeActionTriggerType.Auto, triggerAction: CodeActionTriggerSource.Default, filter: { include: new CodeActionKind('a.b') } }, Progress.None, CancellationToken.None); const { validActions: actions } = disposables.add(await getCodeActions(registry, model, new Range(1, 1, 2, 1), { type: languages.CodeActionTriggerType.Auto, triggerAction: CodeActionTriggerSource.Default, filter: { include: new CodeActionKind('a.b') } }, Progress.None, CancellationToken.None));
assert.strictEqual(actions.length, 1); assert.strictEqual(actions.length, 1);
assert.strictEqual(actions[0].action.title, 'a.b'); assert.strictEqual(actions[0].action.title, 'a.b');
} }
{ {
const { validActions: actions } = await getCodeActions(registry, model, new Range(1, 1, 2, 1), { type: languages.CodeActionTriggerType.Auto, triggerAction: CodeActionTriggerSource.Default, filter: { include: new CodeActionKind('a.b.c') } }, Progress.None, CancellationToken.None); const { validActions: actions } = disposables.add(await getCodeActions(registry, model, new Range(1, 1, 2, 1), { type: languages.CodeActionTriggerType.Auto, triggerAction: CodeActionTriggerSource.Default, filter: { include: new CodeActionKind('a.b.c') } }, Progress.None, CancellationToken.None));
assert.strictEqual(actions.length, 0); assert.strictEqual(actions.length, 0);
} }
}); });
@@ -177,7 +180,7 @@ suite('CodeAction', () => {
disposables.add(registry.register('fooLang', provider)); disposables.add(registry.register('fooLang', provider));
const { validActions: actions } = await getCodeActions(registry, model, new Range(1, 1, 2, 1), { type: languages.CodeActionTriggerType.Auto, triggerAction: CodeActionTriggerSource.Default, filter: { include: new CodeActionKind('a') } }, Progress.None, CancellationToken.None); const { validActions: actions } = disposables.add(await getCodeActions(registry, model, new Range(1, 1, 2, 1), { type: languages.CodeActionTriggerType.Auto, triggerAction: CodeActionTriggerSource.Default, filter: { include: new CodeActionKind('a') } }, Progress.None, CancellationToken.None));
assert.strictEqual(actions.length, 1); assert.strictEqual(actions.length, 1);
assert.strictEqual(actions[0].action.title, 'a'); assert.strictEqual(actions[0].action.title, 'a');
}); });
@@ -191,13 +194,13 @@ suite('CodeAction', () => {
disposables.add(registry.register('fooLang', provider)); disposables.add(registry.register('fooLang', provider));
{ {
const { validActions: actions } = await getCodeActions(registry, model, new Range(1, 1, 2, 1), { type: languages.CodeActionTriggerType.Auto, triggerAction: CodeActionTriggerSource.SourceAction }, Progress.None, CancellationToken.None); const { validActions: actions } = disposables.add(await getCodeActions(registry, model, new Range(1, 1, 2, 1), { type: languages.CodeActionTriggerType.Auto, triggerAction: CodeActionTriggerSource.SourceAction }, Progress.None, CancellationToken.None));
assert.strictEqual(actions.length, 1); assert.strictEqual(actions.length, 1);
assert.strictEqual(actions[0].action.title, 'b'); assert.strictEqual(actions[0].action.title, 'b');
} }
{ {
const { validActions: actions } = await getCodeActions(registry, model, new Range(1, 1, 2, 1), { type: languages.CodeActionTriggerType.Auto, triggerAction: CodeActionTriggerSource.Default, filter: { include: CodeActionKind.Source, includeSourceActions: true } }, Progress.None, CancellationToken.None); const { validActions: actions } = disposables.add(await getCodeActions(registry, model, new Range(1, 1, 2, 1), { type: languages.CodeActionTriggerType.Auto, triggerAction: CodeActionTriggerSource.Default, filter: { include: CodeActionKind.Source, includeSourceActions: true } }, Progress.None, CancellationToken.None));
assert.strictEqual(actions.length, 1); assert.strictEqual(actions.length, 1);
assert.strictEqual(actions[0].action.title, 'a'); assert.strictEqual(actions[0].action.title, 'a');
} }
@@ -213,13 +216,13 @@ suite('CodeAction', () => {
disposables.add(registry.register('fooLang', provider)); disposables.add(registry.register('fooLang', provider));
{ {
const { validActions: actions } = await getCodeActions(registry, model, new Range(1, 1, 2, 1), { const { validActions: actions } = disposables.add(await getCodeActions(registry, model, new Range(1, 1, 2, 1), {
type: languages.CodeActionTriggerType.Auto, triggerAction: CodeActionTriggerSource.SourceAction, filter: { type: languages.CodeActionTriggerType.Auto, triggerAction: CodeActionTriggerSource.SourceAction, filter: {
include: CodeActionKind.Source.append('test'), include: CodeActionKind.Source.append('test'),
excludes: [CodeActionKind.Source], excludes: [CodeActionKind.Source],
includeSourceActions: true, includeSourceActions: true,
} }
}, Progress.None, CancellationToken.None); }, Progress.None, CancellationToken.None));
assert.strictEqual(actions.length, 1); assert.strictEqual(actions.length, 1);
assert.strictEqual(actions[0].action.title, 'b'); assert.strictEqual(actions[0].action.title, 'b');
} }
@@ -250,12 +253,12 @@ suite('CodeAction', () => {
})); }));
{ {
const { validActions: actions } = await getCodeActions(registry, model, new Range(1, 1, 2, 1), { const { validActions: actions } = disposables.add(await getCodeActions(registry, model, new Range(1, 1, 2, 1), {
type: languages.CodeActionTriggerType.Auto, triggerAction: CodeActionTriggerSource.Refactor, filter: { type: languages.CodeActionTriggerType.Auto, triggerAction: CodeActionTriggerSource.Refactor, filter: {
include: baseType, include: baseType,
excludes: [subType], excludes: [subType],
} }
}, Progress.None, CancellationToken.None); }, Progress.None, CancellationToken.None));
assert.strictEqual(didInvoke, false); assert.strictEqual(didInvoke, false);
assert.strictEqual(actions.length, 1); assert.strictEqual(actions.length, 1);
assert.strictEqual(actions[0].action.title, 'a'); assert.strictEqual(actions[0].action.title, 'a');
@@ -275,12 +278,12 @@ suite('CodeAction', () => {
disposables.add(registry.register('fooLang', provider)); disposables.add(registry.register('fooLang', provider));
const { validActions: actions } = await getCodeActions(registry, model, new Range(1, 1, 2, 1), { const { validActions: actions } = disposables.add(await getCodeActions(registry, model, new Range(1, 1, 2, 1), {
type: languages.CodeActionTriggerType.Auto, triggerAction: CodeActionTriggerSource.Refactor, type: languages.CodeActionTriggerType.Auto, triggerAction: CodeActionTriggerSource.Refactor,
filter: { filter: {
include: CodeActionKind.QuickFix include: CodeActionKind.QuickFix
} }
}, Progress.None, CancellationToken.None); }, Progress.None, CancellationToken.None));
assert.strictEqual(actions.length, 0); assert.strictEqual(actions.length, 0);
assert.strictEqual(wasInvoked, false); assert.strictEqual(wasInvoked, false);
}); });

View File

@@ -62,6 +62,7 @@ import { IExtHostTelemetry } from 'vs/workbench/api/common/extHostTelemetry';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { TestConfigurationService } from 'vs/platform/configuration/test/common/testConfigurationService'; import { TestConfigurationService } from 'vs/platform/configuration/test/common/testConfigurationService';
import { IEnvironmentService } from 'vs/platform/environment/common/environment'; import { IEnvironmentService } from 'vs/platform/environment/common/environment';
import { ensureFileSystemProviderError } from 'vs/platform/files/common/files';
function assertRejects(fn: () => Promise<any>, message: string = 'Expected rejection') { function assertRejects(fn: () => Promise<any>, message: string = 'Expected rejection') {
return fn().then(() => assert.ok(false, message), _err => assert.ok(true)); return fn().then(() => assert.ok(false, message), _err => assert.ok(true));
@@ -203,6 +204,8 @@ suite('ExtHostLanguageFeatureCommands', function () {
return rpcProtocol.sync(); return rpcProtocol.sync();
}); });
ensureFileSystemProviderError();
// --- workspace symbols // --- workspace symbols
test('WorkspaceSymbols, invalid arguments', function () { test('WorkspaceSymbols, invalid arguments', function () {

View File

@@ -8,6 +8,7 @@ import { timeout } from 'vs/base/common/async';
import { CancellationToken } from 'vs/base/common/cancellation'; import { CancellationToken } from 'vs/base/common/cancellation';
import { URI } from 'vs/base/common/uri'; import { URI } from 'vs/base/common/uri';
import { mock } from 'vs/base/test/common/mock'; import { mock } from 'vs/base/test/common/mock';
import { ensureNoDisposablesAreLeakedInTestSuite } from 'vs/base/test/common/utils';
import { NullLogService } from 'vs/platform/log/common/log'; import { NullLogService } from 'vs/platform/log/common/log';
import { MainThreadDecorationsShape } from 'vs/workbench/api/common/extHost.protocol'; import { MainThreadDecorationsShape } from 'vs/workbench/api/common/extHost.protocol';
import { ExtHostDecorations } from 'vs/workbench/api/common/extHostDecorations'; import { ExtHostDecorations } from 'vs/workbench/api/common/extHostDecorations';
@@ -20,6 +21,8 @@ suite('ExtHostDecorations', function () {
let extHostDecorations: ExtHostDecorations; let extHostDecorations: ExtHostDecorations;
const providers = new Set<number>(); const providers = new Set<number>();
ensureNoDisposablesAreLeakedInTestSuite();
setup(function () { setup(function () {
providers.clear(); providers.clear();
@@ -79,6 +82,9 @@ suite('ExtHostDecorations', function () {
const secondResult = await Promise.race([second, timeout(30).then(() => false)]); const secondResult = await Promise.race([second, timeout(30).then(() => false)]);
assert.strictEqual(typeof secondResult, 'object'); assert.strictEqual(typeof secondResult, 'object');
await timeout(30);
}); });
}); });

View File

@@ -13,6 +13,7 @@ import { IModelChangedEvent } from 'vs/editor/common/model/mirrorTextModel';
import { mock } from 'vs/base/test/common/mock'; import { mock } from 'vs/base/test/common/mock';
import * as perfData from './extHostDocumentData.test.perf-data'; import * as perfData from './extHostDocumentData.test.perf-data';
import { setDefaultGetWordAtTextConfig } from 'vs/editor/common/core/wordHelper'; import { setDefaultGetWordAtTextConfig } from 'vs/editor/common/core/wordHelper';
import { ensureNoDisposablesAreLeakedInTestSuite } from 'vs/base/test/common/utils';
suite('ExtHostDocumentData', () => { suite('ExtHostDocumentData', () => {
@@ -39,6 +40,8 @@ suite('ExtHostDocumentData', () => {
], '\n', 1, 'text', false); ], '\n', 1, 'text', false);
}); });
ensureNoDisposablesAreLeakedInTestSuite();
test('readonly-ness', () => { test('readonly-ness', () => {
assert.throws(() => (data as any).document.uri = null); assert.throws(() => (data as any).document.uri = null);
assert.throws(() => (data as any).document.fileName = 'foofile'); assert.throws(() => (data as any).document.fileName = 'foofile');

View File

@@ -8,6 +8,7 @@ import { URI } from 'vs/base/common/uri';
import { ExtHostDocumentsAndEditors } from 'vs/workbench/api/common/extHostDocumentsAndEditors'; import { ExtHostDocumentsAndEditors } from 'vs/workbench/api/common/extHostDocumentsAndEditors';
import { TestRPCProtocol } from 'vs/workbench/api/test/common/testRPCProtocol'; import { TestRPCProtocol } from 'vs/workbench/api/test/common/testRPCProtocol';
import { NullLogService } from 'vs/platform/log/common/log'; import { NullLogService } from 'vs/platform/log/common/log';
import { ensureNoDisposablesAreLeakedInTestSuite } from 'vs/base/test/common/utils';
suite('ExtHostDocumentsAndEditors', () => { suite('ExtHostDocumentsAndEditors', () => {
@@ -17,6 +18,8 @@ suite('ExtHostDocumentsAndEditors', () => {
editors = new ExtHostDocumentsAndEditors(new TestRPCProtocol(), new NullLogService()); editors = new ExtHostDocumentsAndEditors(new TestRPCProtocol(), new NullLogService());
}); });
ensureNoDisposablesAreLeakedInTestSuite();
test('The value of TextDocument.isClosed is incorrect when a text document is closed, #27949', () => { test('The value of TextDocument.isClosed is incorrect when a text document is closed, #27949', () => {
editors.$acceptDocumentsAndEditorsDelta({ editors.$acceptDocumentsAndEditorsDelta({
@@ -35,7 +38,7 @@ suite('ExtHostDocumentsAndEditors', () => {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
editors.onDidRemoveDocuments(e => { const d = editors.onDidRemoveDocuments(e => {
try { try {
for (const data of e) { for (const data of e) {
@@ -44,6 +47,8 @@ suite('ExtHostDocumentsAndEditors', () => {
resolve(undefined); resolve(undefined);
} catch (e) { } catch (e) {
reject(e); reject(e);
} finally {
d.dispose();
} }
}); });

View File

@@ -6,9 +6,12 @@ import * as assert from 'assert';
import { ExtHostFileSystemEventService } from 'vs/workbench/api/common/extHostFileSystemEventService'; import { ExtHostFileSystemEventService } from 'vs/workbench/api/common/extHostFileSystemEventService';
import { IMainContext } from 'vs/workbench/api/common/extHost.protocol'; import { IMainContext } from 'vs/workbench/api/common/extHost.protocol';
import { NullLogService } from 'vs/platform/log/common/log'; import { NullLogService } from 'vs/platform/log/common/log';
import { ensureNoDisposablesAreLeakedInTestSuite } from 'vs/base/test/common/utils';
suite('ExtHostFileSystemEventService', () => { suite('ExtHostFileSystemEventService', () => {
ensureNoDisposablesAreLeakedInTestSuite();
test('FileSystemWatcher ignore events properties are reversed #26851', function () { test('FileSystemWatcher ignore events properties are reversed #26851', function () {
const protocol: IMainContext = { const protocol: IMainContext = {
@@ -23,11 +26,13 @@ suite('ExtHostFileSystemEventService', () => {
assert.strictEqual(watcher1.ignoreChangeEvents, false); assert.strictEqual(watcher1.ignoreChangeEvents, false);
assert.strictEqual(watcher1.ignoreCreateEvents, false); assert.strictEqual(watcher1.ignoreCreateEvents, false);
assert.strictEqual(watcher1.ignoreDeleteEvents, false); assert.strictEqual(watcher1.ignoreDeleteEvents, false);
watcher1.dispose();
const watcher2 = new ExtHostFileSystemEventService(protocol, new NullLogService(), undefined!).createFileSystemWatcher(undefined!, undefined!, '**/somethingBoring', true, true, true); const watcher2 = new ExtHostFileSystemEventService(protocol, new NullLogService(), undefined!).createFileSystemWatcher(undefined!, undefined!, '**/somethingBoring', true, true, true);
assert.strictEqual(watcher2.ignoreChangeEvents, true); assert.strictEqual(watcher2.ignoreChangeEvents, true);
assert.strictEqual(watcher2.ignoreCreateEvents, true); assert.strictEqual(watcher2.ignoreCreateEvents, true);
assert.strictEqual(watcher2.ignoreDeleteEvents, true); assert.strictEqual(watcher2.ignoreDeleteEvents, true);
watcher2.dispose();
}); });
}); });

View File

@@ -44,7 +44,7 @@ import { nullExtensionDescription as defaultExtension } from 'vs/workbench/servi
import { provideSelectionRanges } from 'vs/editor/contrib/smartSelect/browser/smartSelect'; import { provideSelectionRanges } from 'vs/editor/contrib/smartSelect/browser/smartSelect';
import { mock } from 'vs/base/test/common/mock'; import { mock } from 'vs/base/test/common/mock';
import { IEditorWorkerService } from 'vs/editor/common/services/editorWorker'; import { IEditorWorkerService } from 'vs/editor/common/services/editorWorker';
import { dispose } from 'vs/base/common/lifecycle'; import { DisposableStore } from 'vs/base/common/lifecycle';
import { NullApiDeprecationService } from 'vs/workbench/api/common/extHostApiDeprecationService'; import { NullApiDeprecationService } from 'vs/workbench/api/common/extHostApiDeprecationService';
import { Progress } from 'vs/platform/progress/common/progress'; import { Progress } from 'vs/platform/progress/common/progress';
import { IExtHostFileSystemInfo } from 'vs/workbench/api/common/extHostFileSystemInfo'; import { IExtHostFileSystemInfo } from 'vs/workbench/api/common/extHostFileSystemInfo';
@@ -55,6 +55,7 @@ import { LanguageFeaturesService } from 'vs/editor/common/services/languageFeatu
import { CodeActionTriggerSource } from 'vs/editor/contrib/codeAction/common/types'; import { CodeActionTriggerSource } from 'vs/editor/contrib/codeAction/common/types';
import { IUriIdentityService } from 'vs/platform/uriIdentity/common/uriIdentity'; import { IUriIdentityService } from 'vs/platform/uriIdentity/common/uriIdentity';
import { IExtHostTelemetry } from 'vs/workbench/api/common/extHostTelemetry'; import { IExtHostTelemetry } from 'vs/workbench/api/common/extHostTelemetry';
import { ensureNoDisposablesAreLeakedInTestSuite } from 'vs/base/test/common/utils';
suite('ExtHostLanguageFeatures', function () { suite('ExtHostLanguageFeatures', function () {
@@ -62,7 +63,7 @@ suite('ExtHostLanguageFeatures', function () {
let model: ITextModel; let model: ITextModel;
let extHost: ExtHostLanguageFeatures; let extHost: ExtHostLanguageFeatures;
let mainThread: MainThreadLanguageFeatures; let mainThread: MainThreadLanguageFeatures;
let disposables: vscode.Disposable[] = []; const disposables = new DisposableStore();
let rpcProtocol: TestRPCProtocol; let rpcProtocol: TestRPCProtocol;
let languageFeaturesService: ILanguageFeaturesService; let languageFeaturesService: ILanguageFeaturesService;
let originalErrorHandler: (e: any) => any; let originalErrorHandler: (e: any) => any;
@@ -121,7 +122,7 @@ suite('ExtHostLanguageFeatures', function () {
} }
}); });
rpcProtocol.set(ExtHostContext.ExtHostCommands, commands); rpcProtocol.set(ExtHostContext.ExtHostCommands, commands);
rpcProtocol.set(MainContext.MainThreadCommands, inst.createInstance(MainThreadCommands, rpcProtocol)); rpcProtocol.set(MainContext.MainThreadCommands, disposables.add(inst.createInstance(MainThreadCommands, rpcProtocol)));
const diagnostics = new ExtHostDiagnostics(rpcProtocol, new NullLogService(), new class extends mock<IExtHostFileSystemInfo>() { }, extHostDocumentsAndEditors); const diagnostics = new ExtHostDiagnostics(rpcProtocol, new NullLogService(), new class extends mock<IExtHostFileSystemInfo>() { }, extHostDocumentsAndEditors);
rpcProtocol.set(ExtHostContext.ExtHostDiagnostics, diagnostics); rpcProtocol.set(ExtHostContext.ExtHostDiagnostics, diagnostics);
@@ -133,7 +134,7 @@ suite('ExtHostLanguageFeatures', function () {
}); });
rpcProtocol.set(ExtHostContext.ExtHostLanguageFeatures, extHost); rpcProtocol.set(ExtHostContext.ExtHostLanguageFeatures, extHost);
mainThread = rpcProtocol.set(MainContext.MainThreadLanguageFeatures, inst.createInstance(MainThreadLanguageFeatures, rpcProtocol)); mainThread = rpcProtocol.set(MainContext.MainThreadLanguageFeatures, disposables.add(inst.createInstance(MainThreadLanguageFeatures, rpcProtocol)));
}); });
suiteTeardown(() => { suiteTeardown(() => {
@@ -144,10 +145,12 @@ suite('ExtHostLanguageFeatures', function () {
}); });
teardown(() => { teardown(() => {
disposables = dispose(disposables); disposables.clear();
return rpcProtocol.sync(); return rpcProtocol.sync();
}); });
ensureNoDisposablesAreLeakedInTestSuite();
// --- outline // --- outline
test('DocumentSymbols, register/deregister', async () => { test('DocumentSymbols, register/deregister', async () => {
@@ -166,12 +169,12 @@ suite('ExtHostLanguageFeatures', function () {
}); });
test('DocumentSymbols, evil provider', async () => { test('DocumentSymbols, evil provider', async () => {
disposables.push(extHost.registerDocumentSymbolProvider(defaultExtension, defaultSelector, new class implements vscode.DocumentSymbolProvider { disposables.add(extHost.registerDocumentSymbolProvider(defaultExtension, defaultSelector, new class implements vscode.DocumentSymbolProvider {
provideDocumentSymbols(): any { provideDocumentSymbols(): any {
throw new Error('evil document symbol provider'); throw new Error('evil document symbol provider');
} }
})); }));
disposables.push(extHost.registerDocumentSymbolProvider(defaultExtension, defaultSelector, new class implements vscode.DocumentSymbolProvider { disposables.add(extHost.registerDocumentSymbolProvider(defaultExtension, defaultSelector, new class implements vscode.DocumentSymbolProvider {
provideDocumentSymbols(): any { provideDocumentSymbols(): any {
return [new types.SymbolInformation('test', types.SymbolKind.Field, new types.Range(0, 0, 0, 0))]; return [new types.SymbolInformation('test', types.SymbolKind.Field, new types.Range(0, 0, 0, 0))];
} }
@@ -183,7 +186,7 @@ suite('ExtHostLanguageFeatures', function () {
}); });
test('DocumentSymbols, data conversion', async () => { test('DocumentSymbols, data conversion', async () => {
disposables.push(extHost.registerDocumentSymbolProvider(defaultExtension, defaultSelector, new class implements vscode.DocumentSymbolProvider { disposables.add(extHost.registerDocumentSymbolProvider(defaultExtension, defaultSelector, new class implements vscode.DocumentSymbolProvider {
provideDocumentSymbols(): any { provideDocumentSymbols(): any {
return [new types.SymbolInformation('test', types.SymbolKind.Field, new types.Range(0, 0, 0, 0))]; return [new types.SymbolInformation('test', types.SymbolKind.Field, new types.Range(0, 0, 0, 0))];
} }
@@ -207,7 +210,7 @@ suite('ExtHostLanguageFeatures', function () {
{ name: 'containerPort', range: { startLineNumber: 4, startColumn: 9, endLineNumber: 4, endColumn: 26 } } { name: 'containerPort', range: { startLineNumber: 4, startColumn: 9, endLineNumber: 4, endColumn: 26 } }
]; ];
extHost.registerDocumentSymbolProvider(defaultExtension, defaultSelector, { disposables.add(extHost.registerDocumentSymbolProvider(defaultExtension, defaultSelector, {
provideDocumentSymbols: (doc, token): any => { provideDocumentSymbols: (doc, token): any => {
return symbols.map(s => { return symbols.map(s => {
return new types.SymbolInformation( return new types.SymbolInformation(
@@ -217,7 +220,7 @@ suite('ExtHostLanguageFeatures', function () {
); );
}); });
} }
}); }));
await rpcProtocol.sync(); await rpcProtocol.sync();
@@ -231,12 +234,12 @@ suite('ExtHostLanguageFeatures', function () {
test('CodeLens, evil provider', async () => { test('CodeLens, evil provider', async () => {
disposables.push(extHost.registerCodeLensProvider(defaultExtension, defaultSelector, new class implements vscode.CodeLensProvider { disposables.add(extHost.registerCodeLensProvider(defaultExtension, defaultSelector, new class implements vscode.CodeLensProvider {
provideCodeLenses(): any { provideCodeLenses(): any {
throw new Error('evil'); throw new Error('evil');
} }
})); }));
disposables.push(extHost.registerCodeLensProvider(defaultExtension, defaultSelector, new class implements vscode.CodeLensProvider { disposables.add(extHost.registerCodeLensProvider(defaultExtension, defaultSelector, new class implements vscode.CodeLensProvider {
provideCodeLenses() { provideCodeLenses() {
return [new types.CodeLens(new types.Range(0, 0, 0, 0))]; return [new types.CodeLens(new types.Range(0, 0, 0, 0))];
} }
@@ -245,11 +248,12 @@ suite('ExtHostLanguageFeatures', function () {
await rpcProtocol.sync(); await rpcProtocol.sync();
const value = await getCodeLensModel(languageFeaturesService.codeLensProvider, model, CancellationToken.None); const value = await getCodeLensModel(languageFeaturesService.codeLensProvider, model, CancellationToken.None);
assert.strictEqual(value.lenses.length, 1); assert.strictEqual(value.lenses.length, 1);
value.dispose();
}); });
test('CodeLens, do not resolve a resolved lens', async () => { test('CodeLens, do not resolve a resolved lens', async () => {
disposables.push(extHost.registerCodeLensProvider(defaultExtension, defaultSelector, new class implements vscode.CodeLensProvider { disposables.add(extHost.registerCodeLensProvider(defaultExtension, defaultSelector, new class implements vscode.CodeLensProvider {
provideCodeLenses(): any { provideCodeLenses(): any {
return [new types.CodeLens( return [new types.CodeLens(
new types.Range(0, 0, 0, 0), new types.Range(0, 0, 0, 0),
@@ -267,11 +271,12 @@ suite('ExtHostLanguageFeatures', function () {
const symbol = await Promise.resolve(data.provider.resolveCodeLens!(model, data.symbol, CancellationToken.None)); const symbol = await Promise.resolve(data.provider.resolveCodeLens!(model, data.symbol, CancellationToken.None));
assert.strictEqual(symbol!.command!.id, 'id'); assert.strictEqual(symbol!.command!.id, 'id');
assert.strictEqual(symbol!.command!.title, 'Title'); assert.strictEqual(symbol!.command!.title, 'Title');
value.dispose();
}); });
test('CodeLens, missing command', async () => { test('CodeLens, missing command', async () => {
disposables.push(extHost.registerCodeLensProvider(defaultExtension, defaultSelector, new class implements vscode.CodeLensProvider { disposables.add(extHost.registerCodeLensProvider(defaultExtension, defaultSelector, new class implements vscode.CodeLensProvider {
provideCodeLenses() { provideCodeLenses() {
return [new types.CodeLens(new types.Range(0, 0, 0, 0))]; return [new types.CodeLens(new types.Range(0, 0, 0, 0))];
} }
@@ -284,13 +289,14 @@ suite('ExtHostLanguageFeatures', function () {
const symbol = await Promise.resolve(data.provider.resolveCodeLens!(model, data.symbol, CancellationToken.None)); const symbol = await Promise.resolve(data.provider.resolveCodeLens!(model, data.symbol, CancellationToken.None));
assert.strictEqual(symbol!.command!.id, 'missing'); assert.strictEqual(symbol!.command!.id, 'missing');
assert.strictEqual(symbol!.command!.title, '!!MISSING: command!!'); assert.strictEqual(symbol!.command!.title, '!!MISSING: command!!');
value.dispose();
}); });
// --- definition // --- definition
test('Definition, data conversion', async () => { test('Definition, data conversion', async () => {
disposables.push(extHost.registerDefinitionProvider(defaultExtension, defaultSelector, new class implements vscode.DefinitionProvider { disposables.add(extHost.registerDefinitionProvider(defaultExtension, defaultSelector, new class implements vscode.DefinitionProvider {
provideDefinition(): any { provideDefinition(): any {
return [new types.Location(model.uri, new types.Range(1, 2, 3, 4))]; return [new types.Location(model.uri, new types.Range(1, 2, 3, 4))];
} }
@@ -306,12 +312,12 @@ suite('ExtHostLanguageFeatures', function () {
test('Definition, one or many', async () => { test('Definition, one or many', async () => {
disposables.push(extHost.registerDefinitionProvider(defaultExtension, defaultSelector, new class implements vscode.DefinitionProvider { disposables.add(extHost.registerDefinitionProvider(defaultExtension, defaultSelector, new class implements vscode.DefinitionProvider {
provideDefinition(): any { provideDefinition(): any {
return [new types.Location(model.uri, new types.Range(1, 1, 1, 1))]; return [new types.Location(model.uri, new types.Range(1, 1, 1, 1))];
} }
})); }));
disposables.push(extHost.registerDefinitionProvider(defaultExtension, defaultSelector, new class implements vscode.DefinitionProvider { disposables.add(extHost.registerDefinitionProvider(defaultExtension, defaultSelector, new class implements vscode.DefinitionProvider {
provideDefinition(): any { provideDefinition(): any {
return new types.Location(model.uri, new types.Range(2, 1, 1, 1)); return new types.Location(model.uri, new types.Range(2, 1, 1, 1));
} }
@@ -324,13 +330,13 @@ suite('ExtHostLanguageFeatures', function () {
test('Definition, registration order', async () => { test('Definition, registration order', async () => {
disposables.push(extHost.registerDefinitionProvider(defaultExtension, defaultSelector, new class implements vscode.DefinitionProvider { disposables.add(extHost.registerDefinitionProvider(defaultExtension, defaultSelector, new class implements vscode.DefinitionProvider {
provideDefinition(): any { provideDefinition(): any {
return [new types.Location(URI.parse('far://first'), new types.Range(2, 3, 4, 5))]; return [new types.Location(URI.parse('far://first'), new types.Range(2, 3, 4, 5))];
} }
})); }));
disposables.push(extHost.registerDefinitionProvider(defaultExtension, defaultSelector, new class implements vscode.DefinitionProvider { disposables.add(extHost.registerDefinitionProvider(defaultExtension, defaultSelector, new class implements vscode.DefinitionProvider {
provideDefinition(): any { provideDefinition(): any {
return new types.Location(URI.parse('far://second'), new types.Range(1, 2, 3, 4)); return new types.Location(URI.parse('far://second'), new types.Range(1, 2, 3, 4));
} }
@@ -346,12 +352,12 @@ suite('ExtHostLanguageFeatures', function () {
test('Definition, evil provider', async () => { test('Definition, evil provider', async () => {
disposables.push(extHost.registerDefinitionProvider(defaultExtension, defaultSelector, new class implements vscode.DefinitionProvider { disposables.add(extHost.registerDefinitionProvider(defaultExtension, defaultSelector, new class implements vscode.DefinitionProvider {
provideDefinition(): any { provideDefinition(): any {
throw new Error('evil provider'); throw new Error('evil provider');
} }
})); }));
disposables.push(extHost.registerDefinitionProvider(defaultExtension, defaultSelector, new class implements vscode.DefinitionProvider { disposables.add(extHost.registerDefinitionProvider(defaultExtension, defaultSelector, new class implements vscode.DefinitionProvider {
provideDefinition(): any { provideDefinition(): any {
return new types.Location(model.uri, new types.Range(1, 1, 1, 1)); return new types.Location(model.uri, new types.Range(1, 1, 1, 1));
} }
@@ -366,7 +372,7 @@ suite('ExtHostLanguageFeatures', function () {
test('Declaration, data conversion', async () => { test('Declaration, data conversion', async () => {
disposables.push(extHost.registerDeclarationProvider(defaultExtension, defaultSelector, new class implements vscode.DeclarationProvider { disposables.add(extHost.registerDeclarationProvider(defaultExtension, defaultSelector, new class implements vscode.DeclarationProvider {
provideDeclaration(): any { provideDeclaration(): any {
return [new types.Location(model.uri, new types.Range(1, 2, 3, 4))]; return [new types.Location(model.uri, new types.Range(1, 2, 3, 4))];
} }
@@ -384,7 +390,7 @@ suite('ExtHostLanguageFeatures', function () {
test('Implementation, data conversion', async () => { test('Implementation, data conversion', async () => {
disposables.push(extHost.registerImplementationProvider(defaultExtension, defaultSelector, new class implements vscode.ImplementationProvider { disposables.add(extHost.registerImplementationProvider(defaultExtension, defaultSelector, new class implements vscode.ImplementationProvider {
provideImplementation(): any { provideImplementation(): any {
return [new types.Location(model.uri, new types.Range(1, 2, 3, 4))]; return [new types.Location(model.uri, new types.Range(1, 2, 3, 4))];
} }
@@ -402,7 +408,7 @@ suite('ExtHostLanguageFeatures', function () {
test('Type Definition, data conversion', async () => { test('Type Definition, data conversion', async () => {
disposables.push(extHost.registerTypeDefinitionProvider(defaultExtension, defaultSelector, new class implements vscode.TypeDefinitionProvider { disposables.add(extHost.registerTypeDefinitionProvider(defaultExtension, defaultSelector, new class implements vscode.TypeDefinitionProvider {
provideTypeDefinition(): any { provideTypeDefinition(): any {
return [new types.Location(model.uri, new types.Range(1, 2, 3, 4))]; return [new types.Location(model.uri, new types.Range(1, 2, 3, 4))];
} }
@@ -420,7 +426,7 @@ suite('ExtHostLanguageFeatures', function () {
test('HoverProvider, word range at pos', async () => { test('HoverProvider, word range at pos', async () => {
disposables.push(extHost.registerHoverProvider(defaultExtension, defaultSelector, new class implements vscode.HoverProvider { disposables.add(extHost.registerHoverProvider(defaultExtension, defaultSelector, new class implements vscode.HoverProvider {
provideHover(): any { provideHover(): any {
return new types.Hover('Hello'); return new types.Hover('Hello');
} }
@@ -436,7 +442,7 @@ suite('ExtHostLanguageFeatures', function () {
test('HoverProvider, given range', async () => { test('HoverProvider, given range', async () => {
disposables.push(extHost.registerHoverProvider(defaultExtension, defaultSelector, new class implements vscode.HoverProvider { disposables.add(extHost.registerHoverProvider(defaultExtension, defaultSelector, new class implements vscode.HoverProvider {
provideHover(): any { provideHover(): any {
return new types.Hover('Hello', new types.Range(3, 0, 8, 7)); return new types.Hover('Hello', new types.Range(3, 0, 8, 7));
} }
@@ -451,14 +457,14 @@ suite('ExtHostLanguageFeatures', function () {
test('HoverProvider, registration order', async () => { test('HoverProvider, registration order', async () => {
disposables.push(extHost.registerHoverProvider(defaultExtension, defaultSelector, new class implements vscode.HoverProvider { disposables.add(extHost.registerHoverProvider(defaultExtension, defaultSelector, new class implements vscode.HoverProvider {
provideHover(): any { provideHover(): any {
return new types.Hover('registered first'); return new types.Hover('registered first');
} }
})); }));
disposables.push(extHost.registerHoverProvider(defaultExtension, defaultSelector, new class implements vscode.HoverProvider { disposables.add(extHost.registerHoverProvider(defaultExtension, defaultSelector, new class implements vscode.HoverProvider {
provideHover(): any { provideHover(): any {
return new types.Hover('registered second'); return new types.Hover('registered second');
} }
@@ -475,12 +481,12 @@ suite('ExtHostLanguageFeatures', function () {
test('HoverProvider, evil provider', async () => { test('HoverProvider, evil provider', async () => {
disposables.push(extHost.registerHoverProvider(defaultExtension, defaultSelector, new class implements vscode.HoverProvider { disposables.add(extHost.registerHoverProvider(defaultExtension, defaultSelector, new class implements vscode.HoverProvider {
provideHover(): any { provideHover(): any {
throw new Error('evil'); throw new Error('evil');
} }
})); }));
disposables.push(extHost.registerHoverProvider(defaultExtension, defaultSelector, new class implements vscode.HoverProvider { disposables.add(extHost.registerHoverProvider(defaultExtension, defaultSelector, new class implements vscode.HoverProvider {
provideHover(): any { provideHover(): any {
return new types.Hover('Hello'); return new types.Hover('Hello');
} }
@@ -495,7 +501,7 @@ suite('ExtHostLanguageFeatures', function () {
test('Occurrences, data conversion', async () => { test('Occurrences, data conversion', async () => {
disposables.push(extHost.registerDocumentHighlightProvider(defaultExtension, defaultSelector, new class implements vscode.DocumentHighlightProvider { disposables.add(extHost.registerDocumentHighlightProvider(defaultExtension, defaultSelector, new class implements vscode.DocumentHighlightProvider {
provideDocumentHighlights(): any { provideDocumentHighlights(): any {
return [new types.DocumentHighlight(new types.Range(0, 0, 0, 4))]; return [new types.DocumentHighlight(new types.Range(0, 0, 0, 4))];
} }
@@ -511,12 +517,12 @@ suite('ExtHostLanguageFeatures', function () {
test('Occurrences, order 1/2', async () => { test('Occurrences, order 1/2', async () => {
disposables.push(extHost.registerDocumentHighlightProvider(defaultExtension, defaultSelector, new class implements vscode.DocumentHighlightProvider { disposables.add(extHost.registerDocumentHighlightProvider(defaultExtension, defaultSelector, new class implements vscode.DocumentHighlightProvider {
provideDocumentHighlights(): any { provideDocumentHighlights(): any {
return []; return [];
} }
})); }));
disposables.push(extHost.registerDocumentHighlightProvider(defaultExtension, '*', new class implements vscode.DocumentHighlightProvider { disposables.add(extHost.registerDocumentHighlightProvider(defaultExtension, '*', new class implements vscode.DocumentHighlightProvider {
provideDocumentHighlights(): any { provideDocumentHighlights(): any {
return [new types.DocumentHighlight(new types.Range(0, 0, 0, 4))]; return [new types.DocumentHighlight(new types.Range(0, 0, 0, 4))];
} }
@@ -532,12 +538,12 @@ suite('ExtHostLanguageFeatures', function () {
test('Occurrences, order 2/2', async () => { test('Occurrences, order 2/2', async () => {
disposables.push(extHost.registerDocumentHighlightProvider(defaultExtension, defaultSelector, new class implements vscode.DocumentHighlightProvider { disposables.add(extHost.registerDocumentHighlightProvider(defaultExtension, defaultSelector, new class implements vscode.DocumentHighlightProvider {
provideDocumentHighlights(): any { provideDocumentHighlights(): any {
return [new types.DocumentHighlight(new types.Range(0, 0, 0, 2))]; return [new types.DocumentHighlight(new types.Range(0, 0, 0, 2))];
} }
})); }));
disposables.push(extHost.registerDocumentHighlightProvider(defaultExtension, '*', new class implements vscode.DocumentHighlightProvider { disposables.add(extHost.registerDocumentHighlightProvider(defaultExtension, '*', new class implements vscode.DocumentHighlightProvider {
provideDocumentHighlights(): any { provideDocumentHighlights(): any {
return [new types.DocumentHighlight(new types.Range(0, 0, 0, 4))]; return [new types.DocumentHighlight(new types.Range(0, 0, 0, 4))];
} }
@@ -553,13 +559,13 @@ suite('ExtHostLanguageFeatures', function () {
test('Occurrences, evil provider', async () => { test('Occurrences, evil provider', async () => {
disposables.push(extHost.registerDocumentHighlightProvider(defaultExtension, defaultSelector, new class implements vscode.DocumentHighlightProvider { disposables.add(extHost.registerDocumentHighlightProvider(defaultExtension, defaultSelector, new class implements vscode.DocumentHighlightProvider {
provideDocumentHighlights(): any { provideDocumentHighlights(): any {
throw new Error('evil'); throw new Error('evil');
} }
})); }));
disposables.push(extHost.registerDocumentHighlightProvider(defaultExtension, defaultSelector, new class implements vscode.DocumentHighlightProvider { disposables.add(extHost.registerDocumentHighlightProvider(defaultExtension, defaultSelector, new class implements vscode.DocumentHighlightProvider {
provideDocumentHighlights(): any { provideDocumentHighlights(): any {
return [new types.DocumentHighlight(new types.Range(0, 0, 0, 4))]; return [new types.DocumentHighlight(new types.Range(0, 0, 0, 4))];
} }
@@ -574,13 +580,13 @@ suite('ExtHostLanguageFeatures', function () {
test('References, registration order', async () => { test('References, registration order', async () => {
disposables.push(extHost.registerReferenceProvider(defaultExtension, defaultSelector, new class implements vscode.ReferenceProvider { disposables.add(extHost.registerReferenceProvider(defaultExtension, defaultSelector, new class implements vscode.ReferenceProvider {
provideReferences(): any { provideReferences(): any {
return [new types.Location(URI.parse('far://register/first'), new types.Range(0, 0, 0, 0))]; return [new types.Location(URI.parse('far://register/first'), new types.Range(0, 0, 0, 0))];
} }
})); }));
disposables.push(extHost.registerReferenceProvider(defaultExtension, defaultSelector, new class implements vscode.ReferenceProvider { disposables.add(extHost.registerReferenceProvider(defaultExtension, defaultSelector, new class implements vscode.ReferenceProvider {
provideReferences(): any { provideReferences(): any {
return [new types.Location(URI.parse('far://register/second'), new types.Range(0, 0, 0, 0))]; return [new types.Location(URI.parse('far://register/second'), new types.Range(0, 0, 0, 0))];
} }
@@ -596,7 +602,7 @@ suite('ExtHostLanguageFeatures', function () {
test('References, data conversion', async () => { test('References, data conversion', async () => {
disposables.push(extHost.registerReferenceProvider(defaultExtension, defaultSelector, new class implements vscode.ReferenceProvider { disposables.add(extHost.registerReferenceProvider(defaultExtension, defaultSelector, new class implements vscode.ReferenceProvider {
provideReferences(): any { provideReferences(): any {
return [new types.Location(model.uri, new types.Position(0, 0))]; return [new types.Location(model.uri, new types.Position(0, 0))];
} }
@@ -612,12 +618,12 @@ suite('ExtHostLanguageFeatures', function () {
test('References, evil provider', async () => { test('References, evil provider', async () => {
disposables.push(extHost.registerReferenceProvider(defaultExtension, defaultSelector, new class implements vscode.ReferenceProvider { disposables.add(extHost.registerReferenceProvider(defaultExtension, defaultSelector, new class implements vscode.ReferenceProvider {
provideReferences(): any { provideReferences(): any {
throw new Error('evil'); throw new Error('evil');
} }
})); }));
disposables.push(extHost.registerReferenceProvider(defaultExtension, defaultSelector, new class implements vscode.ReferenceProvider { disposables.add(extHost.registerReferenceProvider(defaultExtension, defaultSelector, new class implements vscode.ReferenceProvider {
provideReferences(): any { provideReferences(): any {
return [new types.Location(model.uri, new types.Range(0, 0, 0, 0))]; return [new types.Location(model.uri, new types.Range(0, 0, 0, 0))];
} }
@@ -632,7 +638,7 @@ suite('ExtHostLanguageFeatures', function () {
test('Quick Fix, command data conversion', async () => { test('Quick Fix, command data conversion', async () => {
disposables.push(extHost.registerCodeActionProvider(defaultExtension, defaultSelector, { disposables.add(extHost.registerCodeActionProvider(defaultExtension, defaultSelector, {
provideCodeActions(): vscode.Command[] { provideCodeActions(): vscode.Command[] {
return [ return [
{ command: 'test1', title: 'Testing1' }, { command: 'test1', title: 'Testing1' },
@@ -642,18 +648,20 @@ suite('ExtHostLanguageFeatures', function () {
})); }));
await rpcProtocol.sync(); await rpcProtocol.sync();
const { validActions: actions } = await getCodeActions(languageFeaturesService.codeActionProvider, model, model.getFullModelRange(), { type: languages.CodeActionTriggerType.Invoke, triggerAction: CodeActionTriggerSource.QuickFix }, Progress.None, CancellationToken.None); const value = await getCodeActions(languageFeaturesService.codeActionProvider, model, model.getFullModelRange(), { type: languages.CodeActionTriggerType.Invoke, triggerAction: CodeActionTriggerSource.QuickFix }, Progress.None, CancellationToken.None);
const { validActions: actions } = value;
assert.strictEqual(actions.length, 2); assert.strictEqual(actions.length, 2);
const [first, second] = actions; const [first, second] = actions;
assert.strictEqual(first.action.title, 'Testing1'); assert.strictEqual(first.action.title, 'Testing1');
assert.strictEqual(first.action.command!.id, 'test1'); assert.strictEqual(first.action.command!.id, 'test1');
assert.strictEqual(second.action.title, 'Testing2'); assert.strictEqual(second.action.title, 'Testing2');
assert.strictEqual(second.action.command!.id, 'test2'); assert.strictEqual(second.action.command!.id, 'test2');
value.dispose();
}); });
test('Quick Fix, code action data conversion', async () => { test('Quick Fix, code action data conversion', async () => {
disposables.push(extHost.registerCodeActionProvider(defaultExtension, defaultSelector, { disposables.add(extHost.registerCodeActionProvider(defaultExtension, defaultSelector, {
provideCodeActions(): vscode.CodeAction[] { provideCodeActions(): vscode.CodeAction[] {
return [ return [
{ {
@@ -666,19 +674,21 @@ suite('ExtHostLanguageFeatures', function () {
})); }));
await rpcProtocol.sync(); await rpcProtocol.sync();
const { validActions: actions } = await getCodeActions(languageFeaturesService.codeActionProvider, model, model.getFullModelRange(), { type: languages.CodeActionTriggerType.Invoke, triggerAction: CodeActionTriggerSource.Default }, Progress.None, CancellationToken.None); const value = await getCodeActions(languageFeaturesService.codeActionProvider, model, model.getFullModelRange(), { type: languages.CodeActionTriggerType.Invoke, triggerAction: CodeActionTriggerSource.Default }, Progress.None, CancellationToken.None);
const { validActions: actions } = value;
assert.strictEqual(actions.length, 1); assert.strictEqual(actions.length, 1);
const [first] = actions; const [first] = actions;
assert.strictEqual(first.action.title, 'Testing1'); assert.strictEqual(first.action.title, 'Testing1');
assert.strictEqual(first.action.command!.title, 'Testing1Command'); assert.strictEqual(first.action.command!.title, 'Testing1Command');
assert.strictEqual(first.action.command!.id, 'test1'); assert.strictEqual(first.action.command!.id, 'test1');
assert.strictEqual(first.action.kind, 'test.scope'); assert.strictEqual(first.action.kind, 'test.scope');
value.dispose();
}); });
test('Cannot read property \'id\' of undefined, #29469', async () => { test('Cannot read property \'id\' of undefined, #29469', async () => {
disposables.push(extHost.registerCodeActionProvider(defaultExtension, defaultSelector, new class implements vscode.CodeActionProvider { disposables.add(extHost.registerCodeActionProvider(defaultExtension, defaultSelector, new class implements vscode.CodeActionProvider {
provideCodeActions(): any { provideCodeActions(): any {
return [ return [
undefined, undefined,
@@ -689,39 +699,43 @@ suite('ExtHostLanguageFeatures', function () {
})); }));
await rpcProtocol.sync(); await rpcProtocol.sync();
const { validActions: actions } = await getCodeActions(languageFeaturesService.codeActionProvider, model, model.getFullModelRange(), { type: languages.CodeActionTriggerType.Invoke, triggerAction: CodeActionTriggerSource.Default }, Progress.None, CancellationToken.None); const value = await getCodeActions(languageFeaturesService.codeActionProvider, model, model.getFullModelRange(), { type: languages.CodeActionTriggerType.Invoke, triggerAction: CodeActionTriggerSource.Default }, Progress.None, CancellationToken.None);
const { validActions: actions } = value;
assert.strictEqual(actions.length, 1); assert.strictEqual(actions.length, 1);
value.dispose();
}); });
test('Quick Fix, evil provider', async () => { test('Quick Fix, evil provider', async () => {
disposables.push(extHost.registerCodeActionProvider(defaultExtension, defaultSelector, new class implements vscode.CodeActionProvider { disposables.add(extHost.registerCodeActionProvider(defaultExtension, defaultSelector, new class implements vscode.CodeActionProvider {
provideCodeActions(): any { provideCodeActions(): any {
throw new Error('evil'); throw new Error('evil');
} }
})); }));
disposables.push(extHost.registerCodeActionProvider(defaultExtension, defaultSelector, new class implements vscode.CodeActionProvider { disposables.add(extHost.registerCodeActionProvider(defaultExtension, defaultSelector, new class implements vscode.CodeActionProvider {
provideCodeActions(): any { provideCodeActions(): any {
return [{ command: 'test', title: 'Testing' }]; return [{ command: 'test', title: 'Testing' }];
} }
})); }));
await rpcProtocol.sync(); await rpcProtocol.sync();
const { validActions: actions } = await getCodeActions(languageFeaturesService.codeActionProvider, model, model.getFullModelRange(), { type: languages.CodeActionTriggerType.Invoke, triggerAction: CodeActionTriggerSource.QuickFix }, Progress.None, CancellationToken.None); const value = await getCodeActions(languageFeaturesService.codeActionProvider, model, model.getFullModelRange(), { type: languages.CodeActionTriggerType.Invoke, triggerAction: CodeActionTriggerSource.QuickFix }, Progress.None, CancellationToken.None);
const { validActions: actions } = value;
assert.strictEqual(actions.length, 1); assert.strictEqual(actions.length, 1);
value.dispose();
}); });
// --- navigate types // --- navigate types
test('Navigate types, evil provider', async () => { test('Navigate types, evil provider', async () => {
disposables.push(extHost.registerWorkspaceSymbolProvider(defaultExtension, new class implements vscode.WorkspaceSymbolProvider { disposables.add(extHost.registerWorkspaceSymbolProvider(defaultExtension, new class implements vscode.WorkspaceSymbolProvider {
provideWorkspaceSymbols(): any { provideWorkspaceSymbols(): any {
throw new Error('evil'); throw new Error('evil');
} }
})); }));
disposables.push(extHost.registerWorkspaceSymbolProvider(defaultExtension, new class implements vscode.WorkspaceSymbolProvider { disposables.add(extHost.registerWorkspaceSymbolProvider(defaultExtension, new class implements vscode.WorkspaceSymbolProvider {
provideWorkspaceSymbols(): any { provideWorkspaceSymbols(): any {
return [new types.SymbolInformation('testing', types.SymbolKind.Array, new types.Range(0, 0, 1, 1))]; return [new types.SymbolInformation('testing', types.SymbolKind.Array, new types.Range(0, 0, 1, 1))];
} }
@@ -736,19 +750,19 @@ suite('ExtHostLanguageFeatures', function () {
test('Navigate types, de-duplicate results', async () => { test('Navigate types, de-duplicate results', async () => {
const uri = URI.from({ scheme: 'foo', path: '/some/path' }); const uri = URI.from({ scheme: 'foo', path: '/some/path' });
disposables.push(extHost.registerWorkspaceSymbolProvider(defaultExtension, new class implements vscode.WorkspaceSymbolProvider { disposables.add(extHost.registerWorkspaceSymbolProvider(defaultExtension, new class implements vscode.WorkspaceSymbolProvider {
provideWorkspaceSymbols(): any { provideWorkspaceSymbols(): any {
return [new types.SymbolInformation('ONE', types.SymbolKind.Array, undefined, new types.Location(uri, new types.Range(0, 0, 1, 1)))]; return [new types.SymbolInformation('ONE', types.SymbolKind.Array, undefined, new types.Location(uri, new types.Range(0, 0, 1, 1)))];
} }
})); }));
disposables.push(extHost.registerWorkspaceSymbolProvider(defaultExtension, new class implements vscode.WorkspaceSymbolProvider { disposables.add(extHost.registerWorkspaceSymbolProvider(defaultExtension, new class implements vscode.WorkspaceSymbolProvider {
provideWorkspaceSymbols(): any { provideWorkspaceSymbols(): any {
return [new types.SymbolInformation('ONE', types.SymbolKind.Array, undefined, new types.Location(uri, new types.Range(0, 0, 1, 1)))]; // get de-duped return [new types.SymbolInformation('ONE', types.SymbolKind.Array, undefined, new types.Location(uri, new types.Range(0, 0, 1, 1)))]; // get de-duped
} }
})); }));
disposables.push(extHost.registerWorkspaceSymbolProvider(defaultExtension, new class implements vscode.WorkspaceSymbolProvider { disposables.add(extHost.registerWorkspaceSymbolProvider(defaultExtension, new class implements vscode.WorkspaceSymbolProvider {
provideWorkspaceSymbols(): any { provideWorkspaceSymbols(): any {
return [new types.SymbolInformation('ONE', types.SymbolKind.Array, undefined, new types.Location(uri, undefined!))]; // NO dedupe because of resolve return [new types.SymbolInformation('ONE', types.SymbolKind.Array, undefined, new types.Location(uri, undefined!))]; // NO dedupe because of resolve
} }
@@ -757,7 +771,7 @@ suite('ExtHostLanguageFeatures', function () {
} }
})); }));
disposables.push(extHost.registerWorkspaceSymbolProvider(defaultExtension, new class implements vscode.WorkspaceSymbolProvider { disposables.add(extHost.registerWorkspaceSymbolProvider(defaultExtension, new class implements vscode.WorkspaceSymbolProvider {
provideWorkspaceSymbols(): any { provideWorkspaceSymbols(): any {
return [new types.SymbolInformation('ONE', types.SymbolKind.Struct, undefined, new types.Location(uri, new types.Range(0, 0, 1, 1)))]; // NO dedupe because of kind return [new types.SymbolInformation('ONE', types.SymbolKind.Struct, undefined, new types.Location(uri, new types.Range(0, 0, 1, 1)))]; // NO dedupe because of kind
} }
@@ -772,7 +786,7 @@ suite('ExtHostLanguageFeatures', function () {
test('Rename, evil provider 0/2', async () => { test('Rename, evil provider 0/2', async () => {
disposables.push(extHost.registerRenameProvider(defaultExtension, defaultSelector, new class implements vscode.RenameProvider { disposables.add(extHost.registerRenameProvider(defaultExtension, defaultSelector, new class implements vscode.RenameProvider {
provideRenameEdits(): any { provideRenameEdits(): any {
throw new class Foo { }; throw new class Foo { };
} }
@@ -790,7 +804,7 @@ suite('ExtHostLanguageFeatures', function () {
test('Rename, evil provider 1/2', async () => { test('Rename, evil provider 1/2', async () => {
disposables.push(extHost.registerRenameProvider(defaultExtension, defaultSelector, new class implements vscode.RenameProvider { disposables.add(extHost.registerRenameProvider(defaultExtension, defaultSelector, new class implements vscode.RenameProvider {
provideRenameEdits(): any { provideRenameEdits(): any {
throw Error('evil'); throw Error('evil');
} }
@@ -803,13 +817,13 @@ suite('ExtHostLanguageFeatures', function () {
test('Rename, evil provider 2/2', async () => { test('Rename, evil provider 2/2', async () => {
disposables.push(extHost.registerRenameProvider(defaultExtension, '*', new class implements vscode.RenameProvider { disposables.add(extHost.registerRenameProvider(defaultExtension, '*', new class implements vscode.RenameProvider {
provideRenameEdits(): any { provideRenameEdits(): any {
throw Error('evil'); throw Error('evil');
} }
})); }));
disposables.push(extHost.registerRenameProvider(defaultExtension, defaultSelector, new class implements vscode.RenameProvider { disposables.add(extHost.registerRenameProvider(defaultExtension, defaultSelector, new class implements vscode.RenameProvider {
provideRenameEdits(): any { provideRenameEdits(): any {
const edit = new types.WorkspaceEdit(); const edit = new types.WorkspaceEdit();
edit.replace(model.uri, new types.Range(0, 0, 0, 0), 'testing'); edit.replace(model.uri, new types.Range(0, 0, 0, 0), 'testing');
@@ -824,7 +838,7 @@ suite('ExtHostLanguageFeatures', function () {
test('Rename, ordering', async () => { test('Rename, ordering', async () => {
disposables.push(extHost.registerRenameProvider(defaultExtension, '*', new class implements vscode.RenameProvider { disposables.add(extHost.registerRenameProvider(defaultExtension, '*', new class implements vscode.RenameProvider {
provideRenameEdits(): any { provideRenameEdits(): any {
const edit = new types.WorkspaceEdit(); const edit = new types.WorkspaceEdit();
edit.replace(model.uri, new types.Range(0, 0, 0, 0), 'testing'); edit.replace(model.uri, new types.Range(0, 0, 0, 0), 'testing');
@@ -833,7 +847,7 @@ suite('ExtHostLanguageFeatures', function () {
} }
})); }));
disposables.push(extHost.registerRenameProvider(defaultExtension, defaultSelector, new class implements vscode.RenameProvider { disposables.add(extHost.registerRenameProvider(defaultExtension, defaultSelector, new class implements vscode.RenameProvider {
provideRenameEdits(): any { provideRenameEdits(): any {
return; return;
} }
@@ -849,7 +863,7 @@ suite('ExtHostLanguageFeatures', function () {
const called = [false, false, false, false]; const called = [false, false, false, false];
disposables.push(extHost.registerRenameProvider(defaultExtension, defaultSelector, new class implements vscode.RenameProvider { disposables.add(extHost.registerRenameProvider(defaultExtension, defaultSelector, new class implements vscode.RenameProvider {
prepareRename(document: vscode.TextDocument, position: vscode.Position,): vscode.ProviderResult<vscode.Range> { prepareRename(document: vscode.TextDocument, position: vscode.Position,): vscode.ProviderResult<vscode.Range> {
called[0] = true; called[0] = true;
const range = document.getWordRangeAtPosition(position); const range = document.getWordRangeAtPosition(position);
@@ -862,7 +876,7 @@ suite('ExtHostLanguageFeatures', function () {
} }
})); }));
disposables.push(extHost.registerRenameProvider(defaultExtension, defaultSelector, new class implements vscode.RenameProvider { disposables.add(extHost.registerRenameProvider(defaultExtension, defaultSelector, new class implements vscode.RenameProvider {
prepareRename(document: vscode.TextDocument, position: vscode.Position,): vscode.ProviderResult<vscode.Range> { prepareRename(document: vscode.TextDocument, position: vscode.Position,): vscode.ProviderResult<vscode.Range> {
called[2] = true; called[2] = true;
return Promise.reject('Cannot rename this symbol2.'); return Promise.reject('Cannot rename this symbol2.');
@@ -883,7 +897,7 @@ suite('ExtHostLanguageFeatures', function () {
const called = [false, false, false]; const called = [false, false, false];
disposables.push(extHost.registerRenameProvider(defaultExtension, defaultSelector, new class implements vscode.RenameProvider { disposables.add(extHost.registerRenameProvider(defaultExtension, defaultSelector, new class implements vscode.RenameProvider {
prepareRename(document: vscode.TextDocument, position: vscode.Position,): vscode.ProviderResult<vscode.Range> { prepareRename(document: vscode.TextDocument, position: vscode.Position,): vscode.ProviderResult<vscode.Range> {
called[0] = true; called[0] = true;
const range = document.getWordRangeAtPosition(position); const range = document.getWordRangeAtPosition(position);
@@ -896,7 +910,7 @@ suite('ExtHostLanguageFeatures', function () {
} }
})); }));
disposables.push(extHost.registerRenameProvider(defaultExtension, defaultSelector, new class implements vscode.RenameProvider { disposables.add(extHost.registerRenameProvider(defaultExtension, defaultSelector, new class implements vscode.RenameProvider {
provideRenameEdits(document: vscode.TextDocument, position: vscode.Position, newName: string,): vscode.ProviderResult<vscode.WorkspaceEdit> { provideRenameEdits(document: vscode.TextDocument, position: vscode.Position, newName: string,): vscode.ProviderResult<vscode.WorkspaceEdit> {
called[2] = true; called[2] = true;
@@ -915,13 +929,13 @@ suite('ExtHostLanguageFeatures', function () {
test('Parameter Hints, order', async () => { test('Parameter Hints, order', async () => {
disposables.push(extHost.registerSignatureHelpProvider(defaultExtension, defaultSelector, new class implements vscode.SignatureHelpProvider { disposables.add(extHost.registerSignatureHelpProvider(defaultExtension, defaultSelector, new class implements vscode.SignatureHelpProvider {
provideSignatureHelp(): any { provideSignatureHelp(): any {
return undefined; return undefined;
} }
}, [])); }, []));
disposables.push(extHost.registerSignatureHelpProvider(defaultExtension, defaultSelector, new class implements vscode.SignatureHelpProvider { disposables.add(extHost.registerSignatureHelpProvider(defaultExtension, defaultSelector, new class implements vscode.SignatureHelpProvider {
provideSignatureHelp(): vscode.SignatureHelp { provideSignatureHelp(): vscode.SignatureHelp {
return { return {
signatures: [], signatures: [],
@@ -938,7 +952,7 @@ suite('ExtHostLanguageFeatures', function () {
test('Parameter Hints, evil provider', async () => { test('Parameter Hints, evil provider', async () => {
disposables.push(extHost.registerSignatureHelpProvider(defaultExtension, defaultSelector, new class implements vscode.SignatureHelpProvider { disposables.add(extHost.registerSignatureHelpProvider(defaultExtension, defaultSelector, new class implements vscode.SignatureHelpProvider {
provideSignatureHelp(): any { provideSignatureHelp(): any {
throw new Error('evil'); throw new Error('evil');
} }
@@ -953,74 +967,77 @@ suite('ExtHostLanguageFeatures', function () {
test('Suggest, order 1/3', async () => { test('Suggest, order 1/3', async () => {
disposables.push(extHost.registerCompletionItemProvider(defaultExtension, '*', new class implements vscode.CompletionItemProvider { disposables.add(extHost.registerCompletionItemProvider(defaultExtension, '*', new class implements vscode.CompletionItemProvider {
provideCompletionItems(): any { provideCompletionItems(): any {
return [new types.CompletionItem('testing1')]; return [new types.CompletionItem('testing1')];
} }
}, [])); }, []));
disposables.push(extHost.registerCompletionItemProvider(defaultExtension, defaultSelector, new class implements vscode.CompletionItemProvider { disposables.add(extHost.registerCompletionItemProvider(defaultExtension, defaultSelector, new class implements vscode.CompletionItemProvider {
provideCompletionItems(): any { provideCompletionItems(): any {
return [new types.CompletionItem('testing2')]; return [new types.CompletionItem('testing2')];
} }
}, [])); }, []));
await rpcProtocol.sync(); await rpcProtocol.sync();
const { items } = await provideSuggestionItems(languageFeaturesService.completionProvider, model, new EditorPosition(1, 1), new CompletionOptions(undefined, new Set<languages.CompletionItemKind>().add(languages.CompletionItemKind.Snippet))); const value = await provideSuggestionItems(languageFeaturesService.completionProvider, model, new EditorPosition(1, 1), new CompletionOptions(undefined, new Set<languages.CompletionItemKind>().add(languages.CompletionItemKind.Snippet)));
assert.strictEqual(items.length, 1); assert.strictEqual(value.items.length, 1);
assert.strictEqual(items[0].completion.insertText, 'testing2'); assert.strictEqual(value.items[0].completion.insertText, 'testing2');
value.disposable.dispose();
}); });
test('Suggest, order 2/3', async () => { test('Suggest, order 2/3', async () => {
disposables.push(extHost.registerCompletionItemProvider(defaultExtension, '*', new class implements vscode.CompletionItemProvider { disposables.add(extHost.registerCompletionItemProvider(defaultExtension, '*', new class implements vscode.CompletionItemProvider {
provideCompletionItems(): any { provideCompletionItems(): any {
return [new types.CompletionItem('weak-selector')]; // weaker selector but result return [new types.CompletionItem('weak-selector')]; // weaker selector but result
} }
}, [])); }, []));
disposables.push(extHost.registerCompletionItemProvider(defaultExtension, defaultSelector, new class implements vscode.CompletionItemProvider { disposables.add(extHost.registerCompletionItemProvider(defaultExtension, defaultSelector, new class implements vscode.CompletionItemProvider {
provideCompletionItems(): any { provideCompletionItems(): any {
return []; // stronger selector but not a good result; return []; // stronger selector but not a good result;
} }
}, [])); }, []));
await rpcProtocol.sync(); await rpcProtocol.sync();
const { items } = await provideSuggestionItems(languageFeaturesService.completionProvider, model, new EditorPosition(1, 1), new CompletionOptions(undefined, new Set<languages.CompletionItemKind>().add(languages.CompletionItemKind.Snippet))); const value = await provideSuggestionItems(languageFeaturesService.completionProvider, model, new EditorPosition(1, 1), new CompletionOptions(undefined, new Set<languages.CompletionItemKind>().add(languages.CompletionItemKind.Snippet)));
assert.strictEqual(items.length, 1); assert.strictEqual(value.items.length, 1);
assert.strictEqual(items[0].completion.insertText, 'weak-selector'); assert.strictEqual(value.items[0].completion.insertText, 'weak-selector');
value.disposable.dispose();
}); });
test('Suggest, order 3/3', async () => { test('Suggest, order 3/3', async () => {
disposables.push(extHost.registerCompletionItemProvider(defaultExtension, defaultSelector, new class implements vscode.CompletionItemProvider { disposables.add(extHost.registerCompletionItemProvider(defaultExtension, defaultSelector, new class implements vscode.CompletionItemProvider {
provideCompletionItems(): any { provideCompletionItems(): any {
return [new types.CompletionItem('strong-1')]; return [new types.CompletionItem('strong-1')];
} }
}, [])); }, []));
disposables.push(extHost.registerCompletionItemProvider(defaultExtension, defaultSelector, new class implements vscode.CompletionItemProvider { disposables.add(extHost.registerCompletionItemProvider(defaultExtension, defaultSelector, new class implements vscode.CompletionItemProvider {
provideCompletionItems(): any { provideCompletionItems(): any {
return [new types.CompletionItem('strong-2')]; return [new types.CompletionItem('strong-2')];
} }
}, [])); }, []));
await rpcProtocol.sync(); await rpcProtocol.sync();
const { items } = await provideSuggestionItems(languageFeaturesService.completionProvider, model, new EditorPosition(1, 1), new CompletionOptions(undefined, new Set<languages.CompletionItemKind>().add(languages.CompletionItemKind.Snippet))); const value = await provideSuggestionItems(languageFeaturesService.completionProvider, model, new EditorPosition(1, 1), new CompletionOptions(undefined, new Set<languages.CompletionItemKind>().add(languages.CompletionItemKind.Snippet)));
assert.strictEqual(items.length, 2); assert.strictEqual(value.items.length, 2);
assert.strictEqual(items[0].completion.insertText, 'strong-1'); // sort by label assert.strictEqual(value.items[0].completion.insertText, 'strong-1'); // sort by label
assert.strictEqual(items[1].completion.insertText, 'strong-2'); assert.strictEqual(value.items[1].completion.insertText, 'strong-2');
value.disposable.dispose();
}); });
test('Suggest, evil provider', async () => { test('Suggest, evil provider', async () => {
disposables.push(extHost.registerCompletionItemProvider(defaultExtension, defaultSelector, new class implements vscode.CompletionItemProvider { disposables.add(extHost.registerCompletionItemProvider(defaultExtension, defaultSelector, new class implements vscode.CompletionItemProvider {
provideCompletionItems(): any { provideCompletionItems(): any {
throw new Error('evil'); throw new Error('evil');
} }
}, [])); }, []));
disposables.push(extHost.registerCompletionItemProvider(defaultExtension, defaultSelector, new class implements vscode.CompletionItemProvider { disposables.add(extHost.registerCompletionItemProvider(defaultExtension, defaultSelector, new class implements vscode.CompletionItemProvider {
provideCompletionItems(): any { provideCompletionItems(): any {
return [new types.CompletionItem('testing')]; return [new types.CompletionItem('testing')];
} }
@@ -1028,13 +1045,15 @@ suite('ExtHostLanguageFeatures', function () {
await rpcProtocol.sync(); await rpcProtocol.sync();
const { items } = await provideSuggestionItems(languageFeaturesService.completionProvider, model, new EditorPosition(1, 1), new CompletionOptions(undefined, new Set<languages.CompletionItemKind>().add(languages.CompletionItemKind.Snippet))); const value = await provideSuggestionItems(languageFeaturesService.completionProvider, model, new EditorPosition(1, 1), new CompletionOptions(undefined, new Set<languages.CompletionItemKind>().add(languages.CompletionItemKind.Snippet)));
assert.strictEqual(items[0].container.incomplete, false); assert.strictEqual(value.items[0].container.incomplete, false);
value.disposable.dispose();
}); });
test('Suggest, CompletionList', async () => { test('Suggest, CompletionList', async () => {
disposables.push(extHost.registerCompletionItemProvider(defaultExtension, defaultSelector, new class implements vscode.CompletionItemProvider { disposables.add(extHost.registerCompletionItemProvider(defaultExtension, defaultSelector, new class implements vscode.CompletionItemProvider {
provideCompletionItems(): any { provideCompletionItems(): any {
return new types.CompletionList([<any>new types.CompletionItem('hello')], true); return new types.CompletionList([<any>new types.CompletionItem('hello')], true);
} }
@@ -1043,6 +1062,7 @@ suite('ExtHostLanguageFeatures', function () {
await rpcProtocol.sync(); await rpcProtocol.sync();
await provideSuggestionItems(languageFeaturesService.completionProvider, model, new EditorPosition(1, 1), new CompletionOptions(undefined, new Set<languages.CompletionItemKind>().add(languages.CompletionItemKind.Snippet))).then(model => { await provideSuggestionItems(languageFeaturesService.completionProvider, model, new EditorPosition(1, 1), new CompletionOptions(undefined, new Set<languages.CompletionItemKind>().add(languages.CompletionItemKind.Snippet))).then(model => {
assert.strictEqual(model.items[0].container.incomplete, true); assert.strictEqual(model.items[0].container.incomplete, true);
model.disposable.dispose();
}); });
}); });
@@ -1055,7 +1075,7 @@ suite('ExtHostLanguageFeatures', function () {
}; };
test('Format Doc, data conversion', async () => { test('Format Doc, data conversion', async () => {
disposables.push(extHost.registerDocumentFormattingEditProvider(defaultExtension, defaultSelector, new class implements vscode.DocumentFormattingEditProvider { disposables.add(extHost.registerDocumentFormattingEditProvider(defaultExtension, defaultSelector, new class implements vscode.DocumentFormattingEditProvider {
provideDocumentFormattingEdits(): any { provideDocumentFormattingEdits(): any {
return [new types.TextEdit(new types.Range(0, 0, 0, 0), 'testing'), types.TextEdit.setEndOfLine(types.EndOfLine.LF)]; return [new types.TextEdit(new types.Range(0, 0, 0, 0), 'testing'), types.TextEdit.setEndOfLine(types.EndOfLine.LF)];
} }
@@ -1073,7 +1093,7 @@ suite('ExtHostLanguageFeatures', function () {
}); });
test('Format Doc, evil provider', async () => { test('Format Doc, evil provider', async () => {
disposables.push(extHost.registerDocumentFormattingEditProvider(defaultExtension, defaultSelector, new class implements vscode.DocumentFormattingEditProvider { disposables.add(extHost.registerDocumentFormattingEditProvider(defaultExtension, defaultSelector, new class implements vscode.DocumentFormattingEditProvider {
provideDocumentFormattingEdits(): any { provideDocumentFormattingEdits(): any {
throw new Error('evil'); throw new Error('evil');
} }
@@ -1085,19 +1105,19 @@ suite('ExtHostLanguageFeatures', function () {
test('Format Doc, order', async () => { test('Format Doc, order', async () => {
disposables.push(extHost.registerDocumentFormattingEditProvider(defaultExtension, defaultSelector, new class implements vscode.DocumentFormattingEditProvider { disposables.add(extHost.registerDocumentFormattingEditProvider(defaultExtension, defaultSelector, new class implements vscode.DocumentFormattingEditProvider {
provideDocumentFormattingEdits(): any { provideDocumentFormattingEdits(): any {
return undefined; return undefined;
} }
})); }));
disposables.push(extHost.registerDocumentFormattingEditProvider(defaultExtension, defaultSelector, new class implements vscode.DocumentFormattingEditProvider { disposables.add(extHost.registerDocumentFormattingEditProvider(defaultExtension, defaultSelector, new class implements vscode.DocumentFormattingEditProvider {
provideDocumentFormattingEdits(): any { provideDocumentFormattingEdits(): any {
return [new types.TextEdit(new types.Range(0, 0, 0, 0), 'testing')]; return [new types.TextEdit(new types.Range(0, 0, 0, 0), 'testing')];
} }
})); }));
disposables.push(extHost.registerDocumentFormattingEditProvider(defaultExtension, defaultSelector, new class implements vscode.DocumentFormattingEditProvider { disposables.add(extHost.registerDocumentFormattingEditProvider(defaultExtension, defaultSelector, new class implements vscode.DocumentFormattingEditProvider {
provideDocumentFormattingEdits(): any { provideDocumentFormattingEdits(): any {
return undefined; return undefined;
} }
@@ -1112,7 +1132,7 @@ suite('ExtHostLanguageFeatures', function () {
}); });
test('Format Range, data conversion', async () => { test('Format Range, data conversion', async () => {
disposables.push(extHost.registerDocumentRangeFormattingEditProvider(defaultExtension, defaultSelector, new class implements vscode.DocumentRangeFormattingEditProvider { disposables.add(extHost.registerDocumentRangeFormattingEditProvider(defaultExtension, defaultSelector, new class implements vscode.DocumentRangeFormattingEditProvider {
provideDocumentRangeFormattingEdits(): any { provideDocumentRangeFormattingEdits(): any {
return [new types.TextEdit(new types.Range(0, 0, 0, 0), 'testing')]; return [new types.TextEdit(new types.Range(0, 0, 0, 0), 'testing')];
} }
@@ -1127,17 +1147,17 @@ suite('ExtHostLanguageFeatures', function () {
}); });
test('Format Range, + format_doc', async () => { test('Format Range, + format_doc', async () => {
disposables.push(extHost.registerDocumentRangeFormattingEditProvider(defaultExtension, defaultSelector, new class implements vscode.DocumentRangeFormattingEditProvider { disposables.add(extHost.registerDocumentRangeFormattingEditProvider(defaultExtension, defaultSelector, new class implements vscode.DocumentRangeFormattingEditProvider {
provideDocumentRangeFormattingEdits(): any { provideDocumentRangeFormattingEdits(): any {
return [new types.TextEdit(new types.Range(0, 0, 0, 0), 'range')]; return [new types.TextEdit(new types.Range(0, 0, 0, 0), 'range')];
} }
})); }));
disposables.push(extHost.registerDocumentRangeFormattingEditProvider(defaultExtension, defaultSelector, new class implements vscode.DocumentRangeFormattingEditProvider { disposables.add(extHost.registerDocumentRangeFormattingEditProvider(defaultExtension, defaultSelector, new class implements vscode.DocumentRangeFormattingEditProvider {
provideDocumentRangeFormattingEdits(): any { provideDocumentRangeFormattingEdits(): any {
return [new types.TextEdit(new types.Range(2, 3, 4, 5), 'range2')]; return [new types.TextEdit(new types.Range(2, 3, 4, 5), 'range2')];
} }
})); }));
disposables.push(extHost.registerDocumentFormattingEditProvider(defaultExtension, defaultSelector, new class implements vscode.DocumentFormattingEditProvider { disposables.add(extHost.registerDocumentFormattingEditProvider(defaultExtension, defaultSelector, new class implements vscode.DocumentFormattingEditProvider {
provideDocumentFormattingEdits(): any { provideDocumentFormattingEdits(): any {
return [new types.TextEdit(new types.Range(0, 0, 1, 1), 'doc')]; return [new types.TextEdit(new types.Range(0, 0, 1, 1), 'doc')];
} }
@@ -1154,7 +1174,7 @@ suite('ExtHostLanguageFeatures', function () {
}); });
test('Format Range, evil provider', async () => { test('Format Range, evil provider', async () => {
disposables.push(extHost.registerDocumentRangeFormattingEditProvider(defaultExtension, defaultSelector, new class implements vscode.DocumentRangeFormattingEditProvider { disposables.add(extHost.registerDocumentRangeFormattingEditProvider(defaultExtension, defaultSelector, new class implements vscode.DocumentRangeFormattingEditProvider {
provideDocumentRangeFormattingEdits(): any { provideDocumentRangeFormattingEdits(): any {
throw new Error('evil'); throw new Error('evil');
} }
@@ -1166,7 +1186,7 @@ suite('ExtHostLanguageFeatures', function () {
test('Format on Type, data conversion', async () => { test('Format on Type, data conversion', async () => {
disposables.push(extHost.registerOnTypeFormattingEditProvider(defaultExtension, defaultSelector, new class implements vscode.OnTypeFormattingEditProvider { disposables.add(extHost.registerOnTypeFormattingEditProvider(defaultExtension, defaultSelector, new class implements vscode.OnTypeFormattingEditProvider {
provideOnTypeFormattingEdits(): any { provideOnTypeFormattingEdits(): any {
return [new types.TextEdit(new types.Range(0, 0, 0, 0), arguments[2])]; return [new types.TextEdit(new types.Range(0, 0, 0, 0), arguments[2])];
} }
@@ -1182,7 +1202,7 @@ suite('ExtHostLanguageFeatures', function () {
test('Links, data conversion', async () => { test('Links, data conversion', async () => {
disposables.push(extHost.registerDocumentLinkProvider(defaultExtension, defaultSelector, new class implements vscode.DocumentLinkProvider { disposables.add(extHost.registerDocumentLinkProvider(defaultExtension, defaultSelector, new class implements vscode.DocumentLinkProvider {
provideDocumentLinks() { provideDocumentLinks() {
const link = new types.DocumentLink(new types.Range(0, 0, 1, 1), URI.parse('foo:bar#3')); const link = new types.DocumentLink(new types.Range(0, 0, 1, 1), URI.parse('foo:bar#3'));
link.tooltip = 'tooltip'; link.tooltip = 'tooltip';
@@ -1191,7 +1211,7 @@ suite('ExtHostLanguageFeatures', function () {
})); }));
await rpcProtocol.sync(); await rpcProtocol.sync();
const { links } = await getLinks(languageFeaturesService.linkProvider, model, CancellationToken.None); const { links } = disposables.add(await getLinks(languageFeaturesService.linkProvider, model, CancellationToken.None));
assert.strictEqual(links.length, 1); assert.strictEqual(links.length, 1);
const [first] = links; const [first] = links;
assert.strictEqual(first.url?.toString(), 'foo:bar#3'); assert.strictEqual(first.url?.toString(), 'foo:bar#3');
@@ -1201,20 +1221,20 @@ suite('ExtHostLanguageFeatures', function () {
test('Links, evil provider', async () => { test('Links, evil provider', async () => {
disposables.push(extHost.registerDocumentLinkProvider(defaultExtension, defaultSelector, new class implements vscode.DocumentLinkProvider { disposables.add(extHost.registerDocumentLinkProvider(defaultExtension, defaultSelector, new class implements vscode.DocumentLinkProvider {
provideDocumentLinks() { provideDocumentLinks() {
return [new types.DocumentLink(new types.Range(0, 0, 1, 1), URI.parse('foo:bar#3'))]; return [new types.DocumentLink(new types.Range(0, 0, 1, 1), URI.parse('foo:bar#3'))];
} }
})); }));
disposables.push(extHost.registerDocumentLinkProvider(defaultExtension, defaultSelector, new class implements vscode.DocumentLinkProvider { disposables.add(extHost.registerDocumentLinkProvider(defaultExtension, defaultSelector, new class implements vscode.DocumentLinkProvider {
provideDocumentLinks(): any { provideDocumentLinks(): any {
throw new Error(); throw new Error();
} }
})); }));
await rpcProtocol.sync(); await rpcProtocol.sync();
const { links } = await getLinks(languageFeaturesService.linkProvider, model, CancellationToken.None); const { links } = disposables.add(await getLinks(languageFeaturesService.linkProvider, model, CancellationToken.None));
assert.strictEqual(links.length, 1); assert.strictEqual(links.length, 1);
const [first] = links; const [first] = links;
assert.strictEqual(first.url?.toString(), 'foo:bar#3'); assert.strictEqual(first.url?.toString(), 'foo:bar#3');
@@ -1223,7 +1243,7 @@ suite('ExtHostLanguageFeatures', function () {
test('Document colors, data conversion', async () => { test('Document colors, data conversion', async () => {
disposables.push(extHost.registerColorProvider(defaultExtension, defaultSelector, new class implements vscode.DocumentColorProvider { disposables.add(extHost.registerColorProvider(defaultExtension, defaultSelector, new class implements vscode.DocumentColorProvider {
provideDocumentColors(): vscode.ColorInformation[] { provideDocumentColors(): vscode.ColorInformation[] {
return [new types.ColorInformation(new types.Range(0, 0, 0, 20), new types.Color(0.1, 0.2, 0.3, 0.4))]; return [new types.ColorInformation(new types.Range(0, 0, 0, 20), new types.Color(0.1, 0.2, 0.3, 0.4))];
} }
@@ -1243,7 +1263,7 @@ suite('ExtHostLanguageFeatures', function () {
// -- selection ranges // -- selection ranges
test('Selection Ranges, data conversion', async () => { test('Selection Ranges, data conversion', async () => {
disposables.push(extHost.registerSelectionRangeProvider(defaultExtension, defaultSelector, new class implements vscode.SelectionRangeProvider { disposables.add(extHost.registerSelectionRangeProvider(defaultExtension, defaultSelector, new class implements vscode.SelectionRangeProvider {
provideSelectionRanges() { provideSelectionRanges() {
return [ return [
new types.SelectionRange(new types.Range(0, 10, 0, 18), new types.SelectionRange(new types.Range(0, 2, 0, 20))), new types.SelectionRange(new types.Range(0, 10, 0, 18), new types.SelectionRange(new types.Range(0, 2, 0, 20))),

View File

@@ -31,6 +31,7 @@ import { TestLanguageConfigurationService } from 'vs/editor/test/common/modes/te
import { TextModel } from 'vs/editor/common/model/textModel'; import { TextModel } from 'vs/editor/common/model/textModel';
import { LanguageService } from 'vs/editor/common/services/languageService'; import { LanguageService } from 'vs/editor/common/services/languageService';
import { DisposableStore } from 'vs/base/common/lifecycle'; import { DisposableStore } from 'vs/base/common/lifecycle';
import { ensureNoDisposablesAreLeakedInTestSuite } from 'vs/base/test/common/utils';
suite('MainThreadDocumentsAndEditors', () => { suite('MainThreadDocumentsAndEditors', () => {
@@ -120,10 +121,12 @@ suite('MainThreadDocumentsAndEditors', () => {
disposables.dispose(); disposables.dispose();
}); });
ensureNoDisposablesAreLeakedInTestSuite();
test('Model#add', () => { test('Model#add', () => {
deltas.length = 0; deltas.length = 0;
modelService.createModel('farboo', null); disposables.add(modelService.createModel('farboo', null));
assert.strictEqual(deltas.length, 1); assert.strictEqual(deltas.length, 1);
const [delta] = deltas; const [delta] = deltas;
@@ -143,6 +146,7 @@ suite('MainThreadDocumentsAndEditors', () => {
TextModel._MODEL_SYNC_LIMIT = largeModelString.length / 2; TextModel._MODEL_SYNC_LIMIT = largeModelString.length / 2;
const model = modelService.createModel(largeModelString, null); const model = modelService.createModel(largeModelString, null);
disposables.add(model);
assert.ok(model.isTooLargeForSyncing()); assert.ok(model.isTooLargeForSyncing());
assert.strictEqual(deltas.length, 1); assert.strictEqual(deltas.length, 1);
@@ -172,6 +176,7 @@ suite('MainThreadDocumentsAndEditors', () => {
deltas.length = 0; deltas.length = 0;
assert.strictEqual(deltas.length, 0); assert.strictEqual(deltas.length, 0);
editor.dispose(); editor.dispose();
model.dispose();
} finally { } finally {
TextModel._MODEL_SYNC_LIMIT = oldLimit; TextModel._MODEL_SYNC_LIMIT = oldLimit;
@@ -182,6 +187,7 @@ suite('MainThreadDocumentsAndEditors', () => {
this.timeout(1000 * 60); // increase timeout for this one test this.timeout(1000 * 60); // increase timeout for this one test
const model = modelService.createModel('test', null, undefined, true); const model = modelService.createModel('test', null, undefined, true);
disposables.add(model);
assert.ok(model.isForSimpleWidget); assert.ok(model.isForSimpleWidget);
assert.strictEqual(deltas.length, 1); assert.strictEqual(deltas.length, 1);
@@ -227,10 +233,10 @@ suite('MainThreadDocumentsAndEditors', () => {
assert.strictEqual(second.newActiveEditor, undefined); assert.strictEqual(second.newActiveEditor, undefined);
editor.dispose(); editor.dispose();
model.dispose();
}); });
test('editor with dispos-ed/-ing model', () => { test('editor with dispos-ed/-ing model', () => {
modelService.createModel('foobar', null);
const model = modelService.createModel('farboo', null); const model = modelService.createModel('farboo', null);
const editor = myCreateTestCodeEditor(model); const editor = myCreateTestCodeEditor(model);
@@ -248,5 +254,6 @@ suite('MainThreadDocumentsAndEditors', () => {
assert.strictEqual(first.addedEditors, undefined); assert.strictEqual(first.addedEditors, undefined);
editor.dispose(); editor.dispose();
model.dispose();
}); });
}); });

View File

@@ -16,6 +16,7 @@ import { EditOperation } from 'vs/editor/common/core/editOperation';
import { TestInstantiationService } from 'vs/platform/instantiation/test/common/instantiationServiceMock'; import { TestInstantiationService } from 'vs/platform/instantiation/test/common/instantiationServiceMock';
import { ILanguageService } from 'vs/editor/common/languages/language'; import { ILanguageService } from 'vs/editor/common/languages/language';
import { generateUuid } from 'vs/base/common/uuid'; import { generateUuid } from 'vs/base/common/uuid';
import { ensureNoDisposablesAreLeakedInTestSuite } from 'vs/base/test/common/utils';
class SimpleSnippetService implements ISnippetsService { class SimpleSnippetService implements ISnippetsService {
declare readonly _serviceBrand: undefined; declare readonly _serviceBrand: undefined;
@@ -83,9 +84,11 @@ suite('SnippetsService', function () {
disposables.dispose(); disposables.dispose();
}); });
ensureNoDisposablesAreLeakedInTestSuite();
test('snippet completions - simple', function () { test('snippet completions - simple', function () {
const provider = new SnippetCompletionProvider(languageService, snippetService, new TestLanguageConfigurationService()); const provider = new SnippetCompletionProvider(languageService, snippetService, disposables.add(new TestLanguageConfigurationService()));
const model = disposables.add(instantiateTextModel(instantiationService, '', 'fooLang')); const model = disposables.add(instantiateTextModel(instantiationService, '', 'fooLang'));
return provider.provideCompletionItems(model, new Position(1, 1), context)!.then(result => { return provider.provideCompletionItems(model, new Position(1, 1), context)!.then(result => {
@@ -96,7 +99,7 @@ suite('SnippetsService', function () {
test('snippet completions - simple 2', async function () { test('snippet completions - simple 2', async function () {
const provider = new SnippetCompletionProvider(languageService, snippetService, new TestLanguageConfigurationService()); const provider = new SnippetCompletionProvider(languageService, snippetService, disposables.add(new TestLanguageConfigurationService()));
const model = disposables.add(instantiateTextModel(instantiationService, 'hello ', 'fooLang')); const model = disposables.add(instantiateTextModel(instantiationService, 'hello ', 'fooLang'));
await provider.provideCompletionItems(model, new Position(1, 6) /* hello| */, context)!.then(result => { await provider.provideCompletionItems(model, new Position(1, 6) /* hello| */, context)!.then(result => {
@@ -112,7 +115,7 @@ suite('SnippetsService', function () {
test('snippet completions - with prefix', function () { test('snippet completions - with prefix', function () {
const provider = new SnippetCompletionProvider(languageService, snippetService, new TestLanguageConfigurationService()); const provider = new SnippetCompletionProvider(languageService, snippetService, disposables.add(new TestLanguageConfigurationService()));
const model = disposables.add(instantiateTextModel(instantiationService, 'bar', 'fooLang')); const model = disposables.add(instantiateTextModel(instantiationService, 'bar', 'fooLang'));
return provider.provideCompletionItems(model, new Position(1, 4), context)!.then(result => { return provider.provideCompletionItems(model, new Position(1, 4), context)!.then(result => {
@@ -150,7 +153,7 @@ suite('SnippetsService', function () {
generateUuid() generateUuid()
)]); )]);
const provider = new SnippetCompletionProvider(languageService, snippetService, new TestLanguageConfigurationService()); const provider = new SnippetCompletionProvider(languageService, snippetService, disposables.add(new TestLanguageConfigurationService()));
const model = disposables.add(instantiateTextModel(instantiationService, 'bar-bar', 'fooLang')); const model = disposables.add(instantiateTextModel(instantiationService, 'bar-bar', 'fooLang'));
await provider.provideCompletionItems(model, new Position(1, 3), context)!.then(result => { await provider.provideCompletionItems(model, new Position(1, 3), context)!.then(result => {
@@ -222,7 +225,7 @@ suite('SnippetsService', function () {
generateUuid() generateUuid()
)]); )]);
const provider = new SnippetCompletionProvider(languageService, snippetService, new TestLanguageConfigurationService()); const provider = new SnippetCompletionProvider(languageService, snippetService, disposables.add(new TestLanguageConfigurationService()));
let model = instantiateTextModel(instantiationService, '\t<?php', 'fooLang'); let model = instantiateTextModel(instantiationService, '\t<?php', 'fooLang');
return provider.provideCompletionItems(model, new Position(1, 7), context)!.then(result => { return provider.provideCompletionItems(model, new Position(1, 7), context)!.then(result => {
@@ -259,7 +262,7 @@ suite('SnippetsService', function () {
generateUuid() generateUuid()
)]); )]);
const provider = new SnippetCompletionProvider(languageService, snippetService, new TestLanguageConfigurationService()); const provider = new SnippetCompletionProvider(languageService, snippetService, disposables.add(new TestLanguageConfigurationService()));
const model = disposables.add(instantiateTextModel(instantiationService, '<head>\n\t\n>/head>', 'fooLang')); const model = disposables.add(instantiateTextModel(instantiationService, '<head>\n\t\n>/head>', 'fooLang'));
return provider.provideCompletionItems(model, new Position(1, 1), context)!.then(result => { return provider.provideCompletionItems(model, new Position(1, 1), context)!.then(result => {
@@ -293,7 +296,7 @@ suite('SnippetsService', function () {
generateUuid() generateUuid()
)]); )]);
const provider = new SnippetCompletionProvider(languageService, snippetService, new TestLanguageConfigurationService()); const provider = new SnippetCompletionProvider(languageService, snippetService, disposables.add(new TestLanguageConfigurationService()));
const model = disposables.add(instantiateTextModel(instantiationService, '', 'fooLang')); const model = disposables.add(instantiateTextModel(instantiationService, '', 'fooLang'));
return provider.provideCompletionItems(model, new Position(1, 1), context)!.then(result => { return provider.provideCompletionItems(model, new Position(1, 1), context)!.then(result => {
@@ -322,7 +325,7 @@ suite('SnippetsService', function () {
SnippetSource.User, SnippetSource.User,
generateUuid() generateUuid()
)]); )]);
const provider = new SnippetCompletionProvider(languageService, snippetService, new TestLanguageConfigurationService()); const provider = new SnippetCompletionProvider(languageService, snippetService, disposables.add(new TestLanguageConfigurationService()));
const model = disposables.add(instantiateTextModel(instantiationService, 'p-', 'fooLang')); const model = disposables.add(instantiateTextModel(instantiationService, 'p-', 'fooLang'));
@@ -349,7 +352,7 @@ suite('SnippetsService', function () {
generateUuid() generateUuid()
)]); )]);
const provider = new SnippetCompletionProvider(languageService, snippetService, new TestLanguageConfigurationService()); const provider = new SnippetCompletionProvider(languageService, snippetService, disposables.add(new TestLanguageConfigurationService()));
const model = disposables.add(instantiateTextModel(instantiationService, 'Thisisaverylonglinegoingwithmore100bcharactersandthismakesintellisensebecomea Thisisaverylonglinegoingwithmore100bcharactersandthismakesintellisensebecomea b', 'fooLang')); const model = disposables.add(instantiateTextModel(instantiationService, 'Thisisaverylonglinegoingwithmore100bcharactersandthismakesintellisensebecomea Thisisaverylonglinegoingwithmore100bcharactersandthismakesintellisensebecomea b', 'fooLang'));
const result = await provider.provideCompletionItems(model, new Position(1, 158), context)!; const result = await provider.provideCompletionItems(model, new Position(1, 158), context)!;
@@ -370,7 +373,7 @@ suite('SnippetsService', function () {
generateUuid() generateUuid()
)]); )]);
const provider = new SnippetCompletionProvider(languageService, snippetService, new TestLanguageConfigurationService()); const provider = new SnippetCompletionProvider(languageService, snippetService, disposables.add(new TestLanguageConfigurationService()));
const model = disposables.add(instantiateTextModel(instantiationService, ':', 'fooLang')); const model = disposables.add(instantiateTextModel(instantiationService, ':', 'fooLang'));
const result = await provider.provideCompletionItems(model, new Position(1, 2), context)!; const result = await provider.provideCompletionItems(model, new Position(1, 2), context)!;
@@ -391,7 +394,7 @@ suite('SnippetsService', function () {
generateUuid() generateUuid()
)]); )]);
const provider = new SnippetCompletionProvider(languageService, snippetService, new TestLanguageConfigurationService()); const provider = new SnippetCompletionProvider(languageService, snippetService, disposables.add(new TestLanguageConfigurationService()));
const model = disposables.add(instantiateTextModel(instantiationService, 'template', 'fooLang')); const model = disposables.add(instantiateTextModel(instantiationService, 'template', 'fooLang'));
const result = await provider.provideCompletionItems(model, new Position(1, 9), context)!; const result = await provider.provideCompletionItems(model, new Position(1, 9), context)!;
@@ -416,7 +419,7 @@ suite('SnippetsService', function () {
generateUuid() generateUuid()
)]); )]);
const provider = new SnippetCompletionProvider(languageService, snippetService, new TestLanguageConfigurationService()); const provider = new SnippetCompletionProvider(languageService, snippetService, disposables.add(new TestLanguageConfigurationService()));
const model = disposables.add(instantiateTextModel(instantiationService, 'Thisisaverylonglinegoingwithmore100bcharactersandthismakesintellisensebecomea Thisisaverylonglinegoingwithmore100bcharactersandthismakesintellisensebecomea b text_after_b', 'fooLang')); const model = disposables.add(instantiateTextModel(instantiationService, 'Thisisaverylonglinegoingwithmore100bcharactersandthismakesintellisensebecomea Thisisaverylonglinegoingwithmore100bcharactersandthismakesintellisensebecomea b text_after_b', 'fooLang'));
const result = await provider.provideCompletionItems(model, new Position(1, 158), context)!; const result = await provider.provideCompletionItems(model, new Position(1, 158), context)!;
@@ -425,7 +428,7 @@ suite('SnippetsService', function () {
}); });
test('issue #61296: VS code freezes when editing CSS file with emoji', async function () { test('issue #61296: VS code freezes when editing CSS file with emoji', async function () {
const languageConfigurationService = new TestLanguageConfigurationService(); const languageConfigurationService = disposables.add(new TestLanguageConfigurationService());
disposables.add(languageConfigurationService.register('fooLang', { disposables.add(languageConfigurationService.register('fooLang', {
wordPattern: /(#?-?\d*\.\d\w*%?)|(::?[\w-]*(?=[^,{;]*[,{]))|(([@#.!])?[\w-?]+%?|[@#!.])/g wordPattern: /(#?-?\d*\.\d\w*%?)|(::?[\w-]*(?=[^,{;]*[,{]))|(([@#.!])?[\w-?]+%?|[@#!.])/g
})); }));
@@ -463,7 +466,7 @@ suite('SnippetsService', function () {
generateUuid() generateUuid()
)]); )]);
const provider = new SnippetCompletionProvider(languageService, snippetService, new TestLanguageConfigurationService()); const provider = new SnippetCompletionProvider(languageService, snippetService, disposables.add(new TestLanguageConfigurationService()));
const model = disposables.add(instantiateTextModel(instantiationService, 'a ', 'fooLang')); const model = disposables.add(instantiateTextModel(instantiationService, 'a ', 'fooLang'));
const result = await provider.provideCompletionItems(model, new Position(1, 3), context)!; const result = await provider.provideCompletionItems(model, new Position(1, 3), context)!;
@@ -494,7 +497,7 @@ suite('SnippetsService', function () {
generateUuid() generateUuid()
)]); )]);
const provider = new SnippetCompletionProvider(languageService, snippetService, new TestLanguageConfigurationService()); const provider = new SnippetCompletionProvider(languageService, snippetService, disposables.add(new TestLanguageConfigurationService()));
let model = instantiateTextModel(instantiationService, ' <', 'fooLang'); let model = instantiateTextModel(instantiationService, ' <', 'fooLang');
let result = await provider.provideCompletionItems(model, new Position(1, 3), context)!; let result = await provider.provideCompletionItems(model, new Position(1, 3), context)!;
@@ -526,7 +529,7 @@ suite('SnippetsService', function () {
generateUuid() generateUuid()
)]); )]);
const provider = new SnippetCompletionProvider(languageService, snippetService, new TestLanguageConfigurationService()); const provider = new SnippetCompletionProvider(languageService, snippetService, disposables.add(new TestLanguageConfigurationService()));
let model = instantiateTextModel(instantiationService, 'not wordFoo bar', 'fooLang'); let model = instantiateTextModel(instantiationService, 'not wordFoo bar', 'fooLang');
let result = await provider.provideCompletionItems(model, new Position(1, 3), context)!; let result = await provider.provideCompletionItems(model, new Position(1, 3), context)!;
@@ -570,7 +573,7 @@ suite('SnippetsService', function () {
generateUuid() generateUuid()
)]); )]);
const provider = new SnippetCompletionProvider(languageService, snippetService, new TestLanguageConfigurationService()); const provider = new SnippetCompletionProvider(languageService, snippetService, disposables.add(new TestLanguageConfigurationService()));
const model = instantiateTextModel(instantiationService, 'filler e KEEP ng filler', 'fooLang'); const model = instantiateTextModel(instantiationService, 'filler e KEEP ng filler', 'fooLang');
const result = await provider.provideCompletionItems(model, new Position(1, 9), context)!; const result = await provider.provideCompletionItems(model, new Position(1, 9), context)!;
@@ -583,7 +586,7 @@ suite('SnippetsService', function () {
}); });
test('Snippet will replace auto-closing pair if specified in prefix', async function () { test('Snippet will replace auto-closing pair if specified in prefix', async function () {
const languageConfigurationService = new TestLanguageConfigurationService(); const languageConfigurationService = disposables.add(new TestLanguageConfigurationService());
disposables.add(languageConfigurationService.register('fooLang', { disposables.add(languageConfigurationService.register('fooLang', {
brackets: [ brackets: [
['{', '}'], ['{', '}'],
@@ -631,7 +634,7 @@ suite('SnippetsService', function () {
generateUuid() generateUuid()
)]); )]);
const provider = new SnippetCompletionProvider(languageService, snippetService, new TestLanguageConfigurationService()); const provider = new SnippetCompletionProvider(languageService, snippetService, disposables.add(new TestLanguageConfigurationService()));
const model = instantiateTextModel(instantiationService, ' ci', 'fooLang'); const model = instantiateTextModel(instantiationService, ' ci', 'fooLang');
const result = await provider.provideCompletionItems(model, new Position(1, 4), context)!; const result = await provider.provideCompletionItems(model, new Position(1, 4), context)!;
@@ -652,7 +655,7 @@ suite('SnippetsService', function () {
// new Snippet(['fooLang'], '\'ccc', '\'ccc', '', 'value', '', SnippetSource.User, generateUuid()) // new Snippet(['fooLang'], '\'ccc', '\'ccc', '', 'value', '', SnippetSource.User, generateUuid())
]); ]);
const provider = new SnippetCompletionProvider(languageService, snippetService, new TestLanguageConfigurationService()); const provider = new SnippetCompletionProvider(languageService, snippetService, disposables.add(new TestLanguageConfigurationService()));
const model = instantiateTextModel(instantiationService, '\'\'', 'fooLang'); const model = instantiateTextModel(instantiationService, '\'\'', 'fooLang');
const result = await provider.provideCompletionItems( const result = await provider.provideCompletionItems(
@@ -674,7 +677,7 @@ suite('SnippetsService', function () {
new Snippet(false, ['fooLang'], '\'ccc', '\'ccc', '', 'value', '', SnippetSource.User, generateUuid()) new Snippet(false, ['fooLang'], '\'ccc', '\'ccc', '', 'value', '', SnippetSource.User, generateUuid())
]); ]);
const provider = new SnippetCompletionProvider(languageService, snippetService, new TestLanguageConfigurationService()); const provider = new SnippetCompletionProvider(languageService, snippetService, disposables.add(new TestLanguageConfigurationService()));
const model = instantiateTextModel(instantiationService, '\'\'', 'fooLang'); const model = instantiateTextModel(instantiationService, '\'\'', 'fooLang');
@@ -695,7 +698,7 @@ suite('SnippetsService', function () {
new Snippet(false, ['fooLang'], '^y', '^y', '', 'value', '', SnippetSource.User, generateUuid()), new Snippet(false, ['fooLang'], '^y', '^y', '', 'value', '', SnippetSource.User, generateUuid()),
]); ]);
const provider = new SnippetCompletionProvider(languageService, snippetService, new TestLanguageConfigurationService()); const provider = new SnippetCompletionProvider(languageService, snippetService, disposables.add(new TestLanguageConfigurationService()));
const model = instantiateTextModel(instantiationService, '\'hellot\'', 'fooLang'); const model = instantiateTextModel(instantiationService, '\'hellot\'', 'fooLang');
const result = await provider.provideCompletionItems( const result = await provider.provideCompletionItems(
@@ -716,7 +719,7 @@ suite('SnippetsService', function () {
new Snippet(false, ['fooLang'], '^y', '^y', '', 'value', '', SnippetSource.User, generateUuid()), new Snippet(false, ['fooLang'], '^y', '^y', '', 'value', '', SnippetSource.User, generateUuid()),
]); ]);
const provider = new SnippetCompletionProvider(languageService, snippetService, new TestLanguageConfigurationService()); const provider = new SnippetCompletionProvider(languageService, snippetService, disposables.add(new TestLanguageConfigurationService()));
const model = instantiateTextModel(instantiationService, ')*&^', 'fooLang'); const model = instantiateTextModel(instantiationService, ')*&^', 'fooLang');
const result = await provider.provideCompletionItems( const result = await provider.provideCompletionItems(
@@ -736,7 +739,7 @@ suite('SnippetsService', function () {
new Snippet(false, ['fooLang'], 'foobarrrrrr', 'foobarrrrrr', '', 'value', '', SnippetSource.User, generateUuid()), new Snippet(false, ['fooLang'], 'foobarrrrrr', 'foobarrrrrr', '', 'value', '', SnippetSource.User, generateUuid()),
]); ]);
const provider = new SnippetCompletionProvider(languageService, snippetService, new TestLanguageConfigurationService()); const provider = new SnippetCompletionProvider(languageService, snippetService, disposables.add(new TestLanguageConfigurationService()));
const model = instantiateTextModel(instantiationService, 'foobar', 'fooLang'); const model = instantiateTextModel(instantiationService, 'foobar', 'fooLang');
const result = await provider.provideCompletionItems( const result = await provider.provideCompletionItems(
@@ -756,7 +759,7 @@ suite('SnippetsService', function () {
]); ]);
const provider = new SnippetCompletionProvider(languageService, snippetService, new TestLanguageConfigurationService()); const provider = new SnippetCompletionProvider(languageService, snippetService, disposables.add(new TestLanguageConfigurationService()));
const model = instantiateTextModel(instantiationService, 'function abc(w)', 'fooLang'); const model = instantiateTextModel(instantiationService, 'function abc(w)', 'fooLang');
const result = await provider.provideCompletionItems( const result = await provider.provideCompletionItems(
model, model,
@@ -775,7 +778,7 @@ suite('SnippetsService', function () {
new Snippet(false, ['fooLang'], 'div#', 'div#', '', 'div#', '', SnippetSource.User, generateUuid()), new Snippet(false, ['fooLang'], 'div#', 'div#', '', 'div#', '', SnippetSource.User, generateUuid()),
]); ]);
const provider = new SnippetCompletionProvider(languageService, snippetService, new TestLanguageConfigurationService()); const provider = new SnippetCompletionProvider(languageService, snippetService, disposables.add(new TestLanguageConfigurationService()));
const model = instantiateTextModel(instantiationService, 'di', 'fooLang'); const model = instantiateTextModel(instantiationService, 'di', 'fooLang');
const result = await provider.provideCompletionItems( const result = await provider.provideCompletionItems(
model, model,
@@ -804,8 +807,8 @@ suite('SnippetsService', function () {
snippetService = new SimpleSnippetService([ snippetService = new SimpleSnippetService([
new Snippet(false, ['fooLang'], 'foo', 'Foo- Bar', '', 'Foo', '', SnippetSource.User, generateUuid()), new Snippet(false, ['fooLang'], 'foo', 'Foo- Bar', '', 'Foo', '', SnippetSource.User, generateUuid()),
]); ]);
const model = instantiateTextModel(instantiationService, ' bar', 'fooLang'); const model = disposables.add(instantiateTextModel(instantiationService, ' bar', 'fooLang'));
const provider = new SnippetCompletionProvider(languageService, snippetService, new TestLanguageConfigurationService()); const provider = new SnippetCompletionProvider(languageService, snippetService, disposables.add(new TestLanguageConfigurationService()));
const result = await provider.provideCompletionItems( const result = await provider.provideCompletionItems(
model, model,
new Position(1, 8), new Position(1, 8),