mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-02-16 10:58:30 -05:00
Add API for extensions to get data protocol providers (#1518)
This commit is contained in:
31
src/sql/sqlops.proposed.d.ts
vendored
31
src/sql/sqlops.proposed.d.ts
vendored
@@ -697,4 +697,35 @@ declare module 'sqlops' {
|
||||
*/
|
||||
readonly retainContextWhenHidden?: boolean;
|
||||
}
|
||||
|
||||
export enum DataProviderType {
|
||||
ConnectionProvider = 'ConnectionProvider',
|
||||
BackupProvider = 'BackupProvider',
|
||||
RestoreProvider = 'RestoreProvider',
|
||||
ScriptingProvider = 'ScriptingProvider',
|
||||
ObjectExplorerProvider = 'ObjectExplorerProvider',
|
||||
TaskServicesProvider = 'TaskServicesProvider',
|
||||
FileBrowserProvider = 'FileBrowserProvider',
|
||||
ProfilerProvider = 'ProfilerProvider',
|
||||
MetadataProvider = 'MetadataProvider',
|
||||
QueryProvider = 'QueryProvider',
|
||||
AdminServicesProvider = 'AdminServicesProvider',
|
||||
AgentServicesProvider = 'AgentServicesProvider',
|
||||
CapabilitiesProvider = 'CapabilitiesProvider'
|
||||
}
|
||||
|
||||
export namespace dataprotocol {
|
||||
/**
|
||||
* Get the provider corresponding to the given provider ID and type
|
||||
* @param providerId The ID that the provider was registered with
|
||||
* @param providerType The type of the provider
|
||||
*/
|
||||
export function getProvider<T extends DataProvider>(providerId: string, providerType: DataProviderType): T;
|
||||
|
||||
/**
|
||||
* Get all registered providers of the given type
|
||||
* @param providerType The type of the providers
|
||||
*/
|
||||
export function getProvidersByType<T extends DataProvider>(providerType: DataProviderType): T[];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -166,3 +166,18 @@ export interface ActionDescriptor {
|
||||
callbackData?: any;
|
||||
}
|
||||
|
||||
export enum DataProviderType {
|
||||
ConnectionProvider = 'ConnectionProvider',
|
||||
BackupProvider = 'BackupProvider',
|
||||
RestoreProvider = 'RestoreProvider',
|
||||
ScriptingProvider = 'ScriptingProvider',
|
||||
ObjectExplorerProvider = 'ObjectExplorerProvider',
|
||||
TaskServicesProvider = 'TaskServicesProvider',
|
||||
FileBrowserProvider = 'FileBrowserProvider',
|
||||
ProfilerProvider = 'ProfilerProvider',
|
||||
MetadataProvider = 'MetadataProvider',
|
||||
QueryProvider = 'QueryProvider',
|
||||
AdminServicesProvider = 'AdminServicesProvider',
|
||||
AgentServicesProvider = 'AgentServicesProvider',
|
||||
CapabilitiesProvider = 'CapabilitiesProvider'
|
||||
}
|
||||
|
||||
@@ -4,12 +4,13 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
'use strict';
|
||||
|
||||
import Event, { Emitter } from 'vs/base/common/event';
|
||||
import { IMainContext } from 'vs/workbench/api/node/extHost.protocol';
|
||||
import { SqlMainContext, MainThreadDataProtocolShape, ExtHostDataProtocolShape } from 'sql/workbench/api/node/sqlExtHost.protocol';
|
||||
import * as vscode from 'vscode';
|
||||
import * as sqlops from 'sqlops';
|
||||
import Event, { Emitter } from 'vs/base/common/event';
|
||||
import { IMainContext } from 'vs/workbench/api/node/extHost.protocol';
|
||||
import { Disposable } from 'vs/workbench/api/node/extHostTypes';
|
||||
import { SqlMainContext, MainThreadDataProtocolShape, ExtHostDataProtocolShape } from 'sql/workbench/api/node/sqlExtHost.protocol';
|
||||
import { DataProviderType } from 'sql/workbench/api/common/sqlExtHostTypes';
|
||||
|
||||
export class ExtHostDataProtocol extends ExtHostDataProtocolShape {
|
||||
|
||||
@@ -21,6 +22,7 @@ export class ExtHostDataProtocol extends ExtHostDataProtocolShape {
|
||||
|
||||
private static _handlePool: number = 0;
|
||||
private _adapter = new Map<number, sqlops.DataProvider>();
|
||||
private _providersByType = new Map<sqlops.DataProviderType, sqlops.DataProvider[]>();
|
||||
|
||||
constructor(
|
||||
mainContext: IMainContext
|
||||
@@ -49,86 +51,106 @@ export class ExtHostDataProtocol extends ExtHostDataProtocolShape {
|
||||
}
|
||||
}
|
||||
|
||||
private registerProvider(provider: sqlops.DataProvider): vscode.Disposable {
|
||||
private registerProvider(provider: sqlops.DataProvider, providerType: DataProviderType): vscode.Disposable {
|
||||
provider.handle = this._nextHandle();
|
||||
this._adapter.set(provider.handle, provider);
|
||||
let providersForType = this._providersByType.get(providerType);
|
||||
if (!providersForType) {
|
||||
providersForType = [provider];
|
||||
} else {
|
||||
providersForType.push(provider);
|
||||
}
|
||||
this._providersByType.set(providerType, providersForType);
|
||||
return this._createDisposable(provider.handle);
|
||||
}
|
||||
|
||||
public getProvider<T extends sqlops.DataProvider>(providerId: string, providerType: sqlops.DataProviderType): T {
|
||||
let providersForType = this._providersByType.get(providerType);
|
||||
if (!providersForType) {
|
||||
return undefined;
|
||||
}
|
||||
return providersForType.find(provider => provider.providerId === providerId) as T;
|
||||
}
|
||||
|
||||
public getProvidersByType<T extends sqlops.DataProvider>(providerType: sqlops.DataProviderType): T[] {
|
||||
let providersForType = this._providersByType.get(providerType);
|
||||
return (providersForType || []) as T[];
|
||||
}
|
||||
|
||||
$registerConnectionProvider(provider: sqlops.ConnectionProvider): vscode.Disposable {
|
||||
let rt = this.registerProvider(provider);
|
||||
let rt = this.registerProvider(provider, DataProviderType.ConnectionProvider);
|
||||
this._proxy.$registerConnectionProvider(provider.providerId, provider.handle);
|
||||
return rt;
|
||||
}
|
||||
|
||||
$registerBackupProvider(provider: sqlops.BackupProvider): vscode.Disposable {
|
||||
let rt = this.registerProvider(provider);
|
||||
let rt = this.registerProvider(provider, DataProviderType.BackupProvider);
|
||||
this._proxy.$registerBackupProvider(provider.providerId, provider.handle);
|
||||
return rt;
|
||||
}
|
||||
|
||||
$registerRestoreProvider(provider: sqlops.RestoreProvider): vscode.Disposable {
|
||||
let rt = this.registerProvider(provider);
|
||||
let rt = this.registerProvider(provider, DataProviderType.RestoreProvider);
|
||||
this._proxy.$registerRestoreProvider(provider.providerId, provider.handle);
|
||||
return rt;
|
||||
}
|
||||
|
||||
$registerScriptingProvider(provider: sqlops.ScriptingProvider): vscode.Disposable {
|
||||
let rt = this.registerProvider(provider);
|
||||
let rt = this.registerProvider(provider, DataProviderType.ScriptingProvider);
|
||||
this._proxy.$registerScriptingProvider(provider.providerId, provider.handle);
|
||||
return rt;
|
||||
}
|
||||
|
||||
$registerQueryProvider(provider: sqlops.QueryProvider): vscode.Disposable {
|
||||
let rt = this.registerProvider(provider);
|
||||
let rt = this.registerProvider(provider, DataProviderType.QueryProvider);
|
||||
this._proxy.$registerQueryProvider(provider.providerId, provider.handle);
|
||||
return rt;
|
||||
}
|
||||
|
||||
$registerMetadataProvider(provider: sqlops.MetadataProvider): vscode.Disposable {
|
||||
let rt = this.registerProvider(provider);
|
||||
let rt = this.registerProvider(provider, DataProviderType.MetadataProvider);
|
||||
this._proxy.$registerMetadataProvider(provider.providerId, provider.handle);
|
||||
return rt;
|
||||
}
|
||||
|
||||
$registerTaskServicesProvider(provider: sqlops.TaskServicesProvider): vscode.Disposable {
|
||||
let rt = this.registerProvider(provider);
|
||||
let rt = this.registerProvider(provider, DataProviderType.TaskServicesProvider);
|
||||
this._proxy.$registerTaskServicesProvider(provider.providerId, provider.handle);
|
||||
return rt;
|
||||
}
|
||||
|
||||
$registerFileBrowserProvider(provider: sqlops.FileBrowserProvider): vscode.Disposable {
|
||||
let rt = this.registerProvider(provider);
|
||||
let rt = this.registerProvider(provider, DataProviderType.FileBrowserProvider);
|
||||
this._proxy.$registerFileBrowserProvider(provider.providerId, provider.handle);
|
||||
return rt;
|
||||
}
|
||||
|
||||
$registerObjectExplorerProvider(provider: sqlops.ObjectExplorerProvider): vscode.Disposable {
|
||||
let rt = this.registerProvider(provider);
|
||||
let rt = this.registerProvider(provider, DataProviderType.ObjectExplorerProvider);
|
||||
this._proxy.$registerObjectExplorerProvider(provider.providerId, provider.handle);
|
||||
return rt;
|
||||
}
|
||||
|
||||
$registerProfilerProvider(provider: sqlops.ProfilerProvider): vscode.Disposable {
|
||||
let rt = this.registerProvider(provider);
|
||||
let rt = this.registerProvider(provider, DataProviderType.ProfilerProvider);
|
||||
this._proxy.$registerProfilerProvider(provider.providerId, provider.handle);
|
||||
return rt;
|
||||
}
|
||||
|
||||
$registerAdminServicesProvider(provider: sqlops.AdminServicesProvider): vscode.Disposable {
|
||||
let rt = this.registerProvider(provider);
|
||||
let rt = this.registerProvider(provider, DataProviderType.AdminServicesProvider);
|
||||
this._proxy.$registerAdminServicesProvider(provider.providerId, provider.handle);
|
||||
return rt;
|
||||
}
|
||||
|
||||
$registerAgentServiceProvider(provider: sqlops.AgentServicesProvider): vscode.Disposable {
|
||||
let rt = this.registerProvider(provider);
|
||||
let rt = this.registerProvider(provider, DataProviderType.AgentServicesProvider);
|
||||
this._proxy.$registerAgentServicesProvider(provider.providerId, provider.handle);
|
||||
return rt;
|
||||
}
|
||||
|
||||
$registerCapabilitiesServiceProvider(provider: sqlops.CapabilitiesProvider): vscode.Disposable {
|
||||
let rt = this.registerProvider(provider);
|
||||
let rt = this.registerProvider(provider, DataProviderType.CapabilitiesProvider);
|
||||
this._proxy.$registerCapabilitiesServiceProvider(provider.providerId, provider.handle);
|
||||
return rt;
|
||||
}
|
||||
|
||||
@@ -281,6 +281,12 @@ export function createApiFactory(
|
||||
registerCapabilitiesServiceProvider,
|
||||
onDidChangeLanguageFlavor(listener: (e: sqlops.DidChangeLanguageFlavorParams) => any, thisArgs?: any, disposables?: extHostTypes.Disposable[]) {
|
||||
return extHostDataProvider.onDidChangeLanguageFlavor(listener, thisArgs, disposables);
|
||||
},
|
||||
getProvider<T extends sqlops.DataProvider>(providerId: string, providerType: sqlops.DataProviderType) {
|
||||
return extHostDataProvider.getProvider<T>(providerId, providerType);
|
||||
},
|
||||
getProvidersByType<T extends sqlops.DataProvider>(providerType: sqlops.DataProviderType) {
|
||||
return extHostDataProvider.getProvidersByType<T>(providerType);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -362,6 +368,7 @@ export function createApiFactory(
|
||||
resources,
|
||||
serialization,
|
||||
dataprotocol,
|
||||
DataProviderType: sqlExtHostTypes.DataProviderType,
|
||||
ServiceOptionType: sqlExtHostTypes.ServiceOptionType,
|
||||
ConnectionOptionSpecialType: sqlExtHostTypes.ConnectionOptionSpecialType,
|
||||
EditRowState: sqlExtHostTypes.EditRowState,
|
||||
|
||||
@@ -6,105 +6,60 @@
|
||||
'use strict';
|
||||
|
||||
import * as assert from 'assert';
|
||||
import { TestInstantiationService } from 'vs/platform/instantiation/test/common/instantiationServiceMock';
|
||||
import { setUnexpectedErrorHandler, errorHandler } from 'vs/base/common/errors';
|
||||
import URI from 'vs/base/common/uri';
|
||||
import * as EditorCommon from 'vs/editor/common/editorCommon';
|
||||
import { TextModel as EditorModel } from 'vs/editor/common/model/textModel';
|
||||
import { TestRPCProtocol } from 'vs/workbench/test/electron-browser/api/testRPCProtocol';
|
||||
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { IMarkerService } from 'vs/platform/markers/common/markers';
|
||||
import { MarkerService } from 'vs/platform/markers/common/markerService';
|
||||
import { IRPCProtocol } from 'vs/workbench/services/extensions/node/proxyIdentifier';
|
||||
import { ExtHostCommands } from 'vs/workbench/api/node/extHostCommands';
|
||||
import { MainThreadCommands } from 'vs/workbench/api/electron-browser/mainThreadCommands';
|
||||
import { IHeapService } from 'vs/workbench/api/electron-browser/mainThreadHeapService';
|
||||
import { ExtHostDocuments } from 'vs/workbench/api/node/extHostDocuments';
|
||||
import { ExtHostDocumentsAndEditors } from 'vs/workbench/api/node/extHostDocumentsAndEditors';
|
||||
import { DocumentSymbolProviderRegistry } from 'vs/editor/common/modes';
|
||||
import { MainContext, ExtHostContext } from 'vs/workbench/api/node/extHost.protocol';
|
||||
import { ExtHostDiagnostics } from 'vs/workbench/api/node/extHostDiagnostics';
|
||||
import { ExtHostHeapService } from 'vs/workbench/api/node/extHostHeapService';
|
||||
import * as vscode from 'vscode';
|
||||
|
||||
import { Mock } from 'typemoq';
|
||||
import * as sqlops from 'sqlops';
|
||||
import { ExtHostDataProtocol } from 'sql/workbench/api/node/extHostDataProtocol';
|
||||
import { SqlExtHostContext } from 'sql/workbench/api/node/sqlExtHost.protocol';
|
||||
import { DataProviderType } from 'sql/workbench/api/common/sqlExtHostTypes';
|
||||
import { ProxyAuthHandler } from 'vs/code/electron-main/auth';
|
||||
import { MainThreadDataProtocolShape } from 'sql/workbench/api/node/sqlExtHost.protocol';
|
||||
|
||||
const IRPCProtocol = createDecorator<IRPCProtocol>('rpcProtocol');
|
||||
suite('ExtHostDataProtocol', () => {
|
||||
|
||||
const model = EditorModel.createFromString(
|
||||
[
|
||||
'This is the first line',
|
||||
'This is the second line',
|
||||
'This is the third line',
|
||||
].join('\n'),
|
||||
undefined,
|
||||
undefined,
|
||||
URI.parse('far://testing/file.a'));
|
||||
let extHostDataProtocol: ExtHostDataProtocol;
|
||||
|
||||
let extHost: ExtHostDataProtocol;
|
||||
let disposables: vscode.Disposable[] = [];
|
||||
let threadService: TestRPCProtocol;
|
||||
let originalErrorHandler: (e: any) => any;
|
||||
|
||||
suite('ExtHostDataProtocol', function () {
|
||||
|
||||
suiteSetup(() => {
|
||||
|
||||
// threadService = new TestThreadService();
|
||||
// let instantiationService = new TestInstantiationService();
|
||||
// instantiationService.stub(IThreadService, threadService);
|
||||
// instantiationService.stub(IMarkerService, MarkerService);
|
||||
// instantiationService.stub(IHeapService, {
|
||||
// _serviceBrand: undefined,
|
||||
// trackRecursive(args) {
|
||||
// // nothing
|
||||
// return args;
|
||||
// }
|
||||
// });
|
||||
|
||||
// originalErrorHandler = errorHandler.getUnexpectedErrorHandler();
|
||||
// setUnexpectedErrorHandler(() => { });
|
||||
|
||||
// const extHostDocumentsAndEditors = new ExtHostDocumentsAndEditors(threadService);
|
||||
// extHostDocumentsAndEditors.$acceptDocumentsAndEditorsDelta({
|
||||
// addedDocuments: [{
|
||||
// isDirty: false,
|
||||
// versionId: model.getVersionId(),
|
||||
// modeId: model.getLanguageIdentifier().language,
|
||||
// url: model.uri,
|
||||
// lines: model.getValue().split(model.getEOL()),
|
||||
// EOL: model.getEOL(),
|
||||
// }]
|
||||
// });
|
||||
// const extHostDocuments = new ExtHostDocuments(threadService, extHostDocumentsAndEditors);
|
||||
// threadService.set(ExtHostContext.ExtHostDocuments, extHostDocuments);
|
||||
|
||||
// const heapService = new ExtHostHeapService();
|
||||
|
||||
// const commands = new ExtHostCommands(threadService, heapService);
|
||||
// threadService.set(ExtHostContext.ExtHostCommands, commands);
|
||||
// threadService.setTestInstance(MainContext.MainThreadCommands, instantiationService.createInstance(MainThreadCommands));
|
||||
|
||||
// const diagnostics = new ExtHostDiagnostics(threadService);
|
||||
// threadService.set(ExtHostContext.ExtHostDiagnostics, diagnostics);
|
||||
|
||||
// extHost = new ExtHostDataProtocol(threadService);
|
||||
// threadService.set(SqlExtHostContext.ExtHostDataProtocol, extHost);
|
||||
setup(() => {
|
||||
extHostDataProtocol = new ExtHostDataProtocol({
|
||||
getProxy: identifier => {
|
||||
return {
|
||||
$registerMetadataProvider: (providerId, handle) => Promise.resolve(),
|
||||
$registerConnectionProvider: (providerId, handle) => Promise.resolve()
|
||||
} as any;
|
||||
}
|
||||
} as any);
|
||||
});
|
||||
|
||||
suiteTeardown(() => {
|
||||
// setUnexpectedErrorHandler(originalErrorHandler);
|
||||
// model.dispose();
|
||||
});
|
||||
test('Providers are exposed to other extensions', () => {
|
||||
let extension1Id = 'provider1';
|
||||
let extension1MetadataMock = Mock.ofInstance({
|
||||
getMetadata: () => undefined,
|
||||
getDatabases: () => undefined,
|
||||
getTableInfo: () => undefined,
|
||||
getViewInfo: () => undefined,
|
||||
providerId: extension1Id
|
||||
} as sqlops.MetadataProvider);
|
||||
|
||||
teardown(function () {
|
||||
// while (disposables.length) {
|
||||
// disposables.pop().dispose();
|
||||
// }
|
||||
// return threadService.sync();
|
||||
});
|
||||
let extension2Id = 'provider2';
|
||||
let extension2MetadataMock = Mock.ofInstance({
|
||||
getMetadata: () => undefined,
|
||||
getDatabases: () => undefined,
|
||||
getTableInfo: () => undefined,
|
||||
getViewInfo: () => undefined,
|
||||
providerId: extension2Id
|
||||
} as sqlops.MetadataProvider);
|
||||
|
||||
// --- outline
|
||||
// If I register both providers and then get them using the getProvider API
|
||||
extHostDataProtocol.$registerMetadataProvider(extension1MetadataMock.object);
|
||||
extHostDataProtocol.$registerMetadataProvider(extension2MetadataMock.object);
|
||||
extHostDataProtocol.$registerConnectionProvider({} as sqlops.ConnectionProvider);
|
||||
let retrievedProvider1 = extHostDataProtocol.getProvider<sqlops.MetadataProvider>(extension1Id, DataProviderType.MetadataProvider);
|
||||
let retrievedProvider2 = extHostDataProtocol.getProvider<sqlops.MetadataProvider>(extension2Id, DataProviderType.MetadataProvider);
|
||||
let allProviders = extHostDataProtocol.getProvidersByType<sqlops.MetadataProvider>(DataProviderType.MetadataProvider);
|
||||
|
||||
// Then each provider was retrieved successfully
|
||||
assert.equal(retrievedProvider1, extension1MetadataMock.object, 'Expected metadata provider was not retrieved for extension 1');
|
||||
assert.equal(retrievedProvider2, extension2MetadataMock.object, 'Expected metadata provider was not retrieved for extension 2');
|
||||
assert.equal(allProviders.length, 2, 'All metadata providers had unexpected length');
|
||||
assert.equal(allProviders.some(provider => provider === extension1MetadataMock.object), true, 'All metadata providers did not include extension 1 metadata provider');
|
||||
assert.equal(allProviders.some(provider => provider === extension2MetadataMock.object), true, 'All metadata providers did not include extension 2 metadata provider');
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user