From be8bf7fcdced51a6c39228c9a92a69a7d005012e Mon Sep 17 00:00:00 2001 From: Alan Ren Date: Fri, 9 Sep 2022 14:14:33 -0700 Subject: [PATCH] handle unsupported connection provider (#20577) * handle unknown connection provider * fix error --- .../connection/common/connectionManagement.ts | 7 +++ .../common/testConnectionManagementService.ts | 4 ++ .../browser/mainThreadConnectionManagement.ts | 5 ++ .../dashboard/browser/dashboardActions.ts | 27 +++++----- .../browser/connectionDialogWidget.ts | 49 +++++-------------- .../browser/connectionManagementService.ts | 32 ++++++++++-- .../browser/connectionDialogService.test.ts | 2 +- .../browser/connectionDialogWidget.test.ts | 2 +- .../connectionManagementService.test.ts | 15 +++--- .../browser/testConnectionDialogWidget.ts | 10 +--- 10 files changed, 85 insertions(+), 68 deletions(-) diff --git a/src/sql/platform/connection/common/connectionManagement.ts b/src/sql/platform/connection/common/connectionManagement.ts index 8dd2151bbb..f6b7ae2cd1 100644 --- a/src/sql/platform/connection/common/connectionManagement.ts +++ b/src/sql/platform/connection/common/connectionManagement.ts @@ -321,6 +321,13 @@ export interface IConnectionManagementService { * @returns array of connections */ getConnections(activeConnectionsOnly?: boolean): ConnectionProfile[]; + + /** + * Handle the unsupported provider scenario. + * @param providerName The provider name. + * @returns Promise with a boolean value indicating whether the user has accepted the suggestion. + */ + handleUnsupportedProvider(providerName: string): Promise; } export enum RunQueryOnConnectionMode { diff --git a/src/sql/platform/connection/test/common/testConnectionManagementService.ts b/src/sql/platform/connection/test/common/testConnectionManagementService.ts index 2fd274163b..19588bfe56 100644 --- a/src/sql/platform/connection/test/common/testConnectionManagementService.ts +++ b/src/sql/platform/connection/test/common/testConnectionManagementService.ts @@ -322,4 +322,8 @@ export class TestConnectionManagementService implements IConnectionManagementSer refreshAzureAccountTokenIfNecessary(uri: string): Promise { return undefined; } + + async handleUnsupportedProvider(providerName: string): Promise { + return true; + } } diff --git a/src/sql/workbench/api/browser/mainThreadConnectionManagement.ts b/src/sql/workbench/api/browser/mainThreadConnectionManagement.ts index 13049b6feb..ddf615f870 100644 --- a/src/sql/workbench/api/browser/mainThreadConnectionManagement.ts +++ b/src/sql/workbench/api/browser/mainThreadConnectionManagement.ts @@ -141,6 +141,11 @@ export class MainThreadConnectionManagement extends Disposable implements MainTh } public async $openConnectionDialog(providers: string[], initialConnectionProfile?: IConnectionProfile, connectionCompletionOptions?: azdata.IConnectionCompletionOptions): Promise { + if (initialConnectionProfile?.providerName && this._capabilitiesService.providers[initialConnectionProfile.providerName] === undefined) { + await this._connectionManagementService.handleUnsupportedProvider(initialConnectionProfile.providerName); + return undefined; + } + // Here we default to ConnectionType.editor which saves the connecton in the connection store by default let connectionType = ConnectionType.editor; diff --git a/src/sql/workbench/contrib/dashboard/browser/dashboardActions.ts b/src/sql/workbench/contrib/dashboard/browser/dashboardActions.ts index d956ff03a7..373cddd959 100644 --- a/src/sql/workbench/contrib/dashboard/browser/dashboardActions.ts +++ b/src/sql/workbench/contrib/dashboard/browser/dashboardActions.ts @@ -25,20 +25,25 @@ export const DE_MANAGE_COMMAND_ID = 'dataExplorer.manage'; // Manage CommandsRegistry.registerCommand({ id: DE_MANAGE_COMMAND_ID, - handler: (accessor, args: TreeViewItemHandleArg) => { + handler: async (accessor, args: TreeViewItemHandleArg) => { if (args.$treeItem) { const connectionService = accessor.get(IConnectionManagementService); const capabilitiesService = accessor.get(ICapabilitiesService); - let options = { - showDashboard: true, - saveTheConnection: false, - params: undefined, - showConnectionDialogOnError: true, - showFirewallRuleOnError: true - }; - let profile = new ConnectionProfile(capabilitiesService, args.$treeItem.payload); - let uri = generateUri(profile, 'dashboard'); - return connectionService.connect(new ConnectionProfile(capabilitiesService, args.$treeItem.payload), uri, options); + const providerName = args.$treeItem?.payload?.providerName; + if (providerName && capabilitiesService.providers[providerName] === undefined) { + await connectionService.handleUnsupportedProvider(providerName); + } else { + let options = { + showDashboard: true, + saveTheConnection: false, + params: undefined, + showConnectionDialogOnError: true, + showFirewallRuleOnError: true + }; + let profile = new ConnectionProfile(capabilitiesService, args.$treeItem.payload); + let uri = generateUri(profile, 'dashboard'); + return connectionService.connect(new ConnectionProfile(capabilitiesService, args.$treeItem.payload), uri, options); + } } return Promise.resolve(true); } diff --git a/src/sql/workbench/services/connection/browser/connectionDialogWidget.ts b/src/sql/workbench/services/connection/browser/connectionDialogWidget.ts index 15f3cee01b..2ffb78dc08 100644 --- a/src/sql/workbench/services/connection/browser/connectionDialogWidget.ts +++ b/src/sql/workbench/services/connection/browser/connectionDialogWidget.ts @@ -43,12 +43,8 @@ import { AsyncServerTree } from 'sql/workbench/services/objectExplorer/browser/a import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { ConnectionBrowseTab } from 'sql/workbench/services/connection/browser/connectionBrowseTab'; import { ElementSizeObserver } from 'vs/editor/browser/config/elementSizeObserver'; -import { ConnectionProviderAndExtensionMap, ICapabilitiesService } from 'sql/platform/capabilities/common/capabilitiesService'; -import { INotificationService, Severity } from 'vs/platform/notification/common/notification'; -import { VIEWLET_ID as ExtensionsViewletID } from 'vs/workbench/contrib/extensions/common/extensions'; -import { ICommandService } from 'vs/platform/commands/common/commands'; -import { IPaneCompositePartService } from 'vs/workbench/services/panecomposite/browser/panecomposite'; -import { ViewContainerLocation } from 'vs/workbench/common/views'; +import { ICapabilitiesService } from 'sql/platform/capabilities/common/capabilitiesService'; +import { onUnexpectedError } from 'vs/base/common/errors'; export interface OnShowUIResponse { selectedProviderDisplayName: string; @@ -129,10 +125,7 @@ export class ConnectionDialogWidget extends Modal { @ILogService logService: ILogService, @ITextResourcePropertiesService textResourcePropertiesService: ITextResourcePropertiesService, @IConfigurationService private _configurationService: IConfigurationService, - @ICapabilitiesService private _capabilitiesService: ICapabilitiesService, - @INotificationService private _notificationService: INotificationService, - @IPaneCompositePartService private _paneCompositeService: IPaneCompositePartService, - @ICommandService private _commandService: ICommandService + @ICapabilitiesService private _capabilitiesService: ICapabilitiesService ) { super( localize('connection', "Connection"), @@ -227,7 +220,7 @@ export class ConnectionDialogWidget extends Modal { this._register(this.browsePanel.view.onSelectedConnectionChanged(e => { this._connectionSource = e.source; - this.onConnectionClick(e.connectionProfile, e.connect); + this.onConnectionClick(e.connectionProfile, e.connect).catch(onUnexpectedError); })); this._panel.pushTab(this.browsePanel); @@ -355,7 +348,7 @@ export class ConnectionDialogWidget extends Modal { if (element instanceof ConnectionProfile) { const isDoubleClick = origin === 'mouse' && (eventish as MouseEvent).detail === 2; this._connectionSource = 'recent'; - this.onConnectionClick(element, isDoubleClick); + this.onConnectionClick(element, isDoubleClick).catch(onUnexpectedError); } }; const actionProvider = this.instantiationService.createInstance(RecentConnectionActionsProvider); @@ -377,13 +370,13 @@ export class ConnectionDialogWidget extends Modal { this._recentConnectionTree.onMouseClick(e => { if (e.element instanceof ConnectionProfile) { this._connectionSource = 'recent'; - this.onConnectionClick(e.element, false); + this.onConnectionClick(e.element, false).catch(onUnexpectedError); } }); this._recentConnectionTree.onMouseDblClick(e => { if (e.element instanceof ConnectionProfile) { this._connectionSource = 'recent'; - this.onConnectionClick(e.element, true); + this.onConnectionClick(e.element, true).catch(onUnexpectedError); } }); } @@ -399,9 +392,8 @@ export class ConnectionDialogWidget extends Modal { DOM.append(noRecentConnectionContainer, DOM.$('.no-recent-connections')).innerText = noRecentHistoryLabel; } - private onConnectionClick(element: IConnectionProfile, connect: boolean = false): void { - const isProviderAvailable = this._capabilitiesService.providers[element.providerName] !== undefined; - if (isProviderAvailable) { + private async onConnectionClick(element: IConnectionProfile, connect: boolean = false): Promise { + if (this._capabilitiesService.providers[element.providerName] !== undefined) { if (connect) { this.connect(element); } else { @@ -409,27 +401,8 @@ export class ConnectionDialogWidget extends Modal { } } else { - const extensionId = ConnectionProviderAndExtensionMap.get(element.providerName); - if (extensionId) { - this._notificationService.prompt(Severity.Error, - localize('connectionDialog.extensionNotInstalled', "The extension '{0}' is required in order to connect to this resource. Please install it and try again.", extensionId), - [{ - label: localize('connectionDialog.viewExtension', "View Extension"), - run: async () => { - this.close(); - await this._commandService.executeCommand('extension.open', extensionId); - } - }]); - } else { - this._notificationService.prompt(Severity.Error, - localize('connectionDialog.connectionProviderNotSupported', "The extension that supports provider type '{0}' is not currently installed. Please install it and try again.", element.providerName), - [{ - label: localize('connectionDialog.viewExtensions', "View Extensions"), - run: async () => { - this.close(); - await this._paneCompositeService.openPaneComposite(ExtensionsViewletID, ViewContainerLocation.Sidebar); - } - }]); + if (await this.connectionManagementService.handleUnsupportedProvider(element.providerName)) { + this.close(); } } } diff --git a/src/sql/workbench/services/connection/browser/connectionManagementService.ts b/src/sql/workbench/services/connection/browser/connectionManagementService.ts index 71c1b4303b..fca578b763 100644 --- a/src/sql/workbench/services/connection/browser/connectionManagementService.ts +++ b/src/sql/workbench/services/connection/browser/connectionManagementService.ts @@ -14,7 +14,7 @@ import { ConnectionStore } from 'sql/platform/connection/common/connectionStore' import { ConnectionManagementInfo } from 'sql/platform/connection/common/connectionManagementInfo'; import * as Utils from 'sql/platform/connection/common/utils'; import * as Constants from 'sql/platform/connection/common/constants'; -import { ICapabilitiesService, ConnectionProviderProperties, ProviderFeatures } from 'sql/platform/capabilities/common/capabilitiesService'; +import { ICapabilitiesService, ConnectionProviderProperties, ProviderFeatures, ConnectionProviderAndExtensionMap } from 'sql/platform/capabilities/common/capabilitiesService'; import * as ConnectionContracts from 'sql/workbench/services/connection/browser/connection'; import { ConnectionStatusManager } from 'sql/platform/connection/common/connectionStatusManager'; import { DashboardInput } from 'sql/workbench/browser/editor/profiler/dashboardInput'; @@ -51,6 +51,11 @@ import { toErrorMessage } from 'vs/base/common/errorMessage'; import { IQueryEditorConfiguration } from 'sql/platform/query/common/query'; import { URI } from 'vs/base/common/uri'; import { QueryEditorInput } from 'sql/workbench/common/editor/query/queryEditorInput'; +import { ICommandService } from 'vs/platform/commands/common/commands'; +import { IPaneCompositePartService } from 'vs/workbench/services/panecomposite/browser/panecomposite'; +import { ViewContainerLocation } from 'vs/workbench/common/views'; +import { VIEWLET_ID as ExtensionsViewletID } from 'vs/workbench/contrib/extensions/common/extensions'; +import { IDialogService } from 'vs/platform/dialogs/common/dialogs'; export class ConnectionManagementService extends Disposable implements IConnectionManagementService { @@ -94,7 +99,10 @@ export class ConnectionManagementService extends Disposable implements IConnecti @IAccountManagementService private _accountManagementService: IAccountManagementService, @ILogService private _logService: ILogService, @IStorageService private _storageService: IStorageService, - @IExtensionService private readonly extensionService: IExtensionService + @IExtensionService private readonly _extensionService: IExtensionService, + @ICommandService private readonly _commandService: ICommandService, + @IPaneCompositePartService private readonly _paneCompositePartService: IPaneCompositePartService, + @IDialogService private readonly _dialogService: IDialogService ) { super(); @@ -981,7 +989,7 @@ export class ConnectionManagementService extends Disposable implements IConnecti options: connection.options }); - await this.extensionService.activateByEvent(`onConnect:${connection.providerName}`); + await this._extensionService.activateByEvent(`onConnect:${connection.providerName}`); return this._providers.get(connection.providerName).onReady.then((provider) => { provider.connect(uri, connectionInfo); @@ -1649,4 +1657,22 @@ export class ConnectionManagementService extends Disposable implements IConnecti } return connections; } + + async handleUnsupportedProvider(providerName: string): Promise { + const extensionId = ConnectionProviderAndExtensionMap.get(providerName); + const message = extensionId ? nls.localize('connection.extensionNotInstalled', "The extension '{0}' is required in order to connect to this resource. Do you want to install it?", extensionId) : + nls.localize('connectionDialog.connectionProviderNotSupported', "The extension that supports provider type '{0}' is not currently installed. Do you want to view the extensions?", providerName); + const result = await this._dialogService.confirm({ + message: message, + type: 'question' + }); + if (result.confirmed) { + if (extensionId) { + await this._commandService.executeCommand('extension.open', extensionId); + } else { + await this._paneCompositePartService.openPaneComposite(ExtensionsViewletID, ViewContainerLocation.Sidebar); + } + } + return result.confirmed; + } } diff --git a/src/sql/workbench/services/connection/test/browser/connectionDialogService.test.ts b/src/sql/workbench/services/connection/test/browser/connectionDialogService.test.ts index 5b449c3b8e..b82c6b5d0d 100644 --- a/src/sql/workbench/services/connection/test/browser/connectionDialogService.test.ts +++ b/src/sql/workbench/services/connection/test/browser/connectionDialogService.test.ts @@ -123,7 +123,7 @@ suite('ConnectionDialogService tests', () => { } }; }); - testConnectionDialog = new TestConnectionDialogWidget(providerDisplayNames, providerNameToDisplayMap['MSSQL'], providerNameToDisplayMap, testInstantiationService, mockConnectionManagementService.object, undefined, undefined, viewDescriptorService, new TestThemeService(), new TestLayoutService(), new NullAdsTelemetryService(), new MockContextKeyService(), undefined, new NullLogService(), new TestTextResourcePropertiesService(new TestConfigurationService), new TestConfigurationService(), new TestCapabilitiesService(), undefined, undefined, undefined); + testConnectionDialog = new TestConnectionDialogWidget(providerDisplayNames, providerNameToDisplayMap['MSSQL'], providerNameToDisplayMap, testInstantiationService, mockConnectionManagementService.object, undefined, undefined, viewDescriptorService, new TestThemeService(), new TestLayoutService(), new NullAdsTelemetryService(), new MockContextKeyService(), undefined, new NullLogService(), new TestTextResourcePropertiesService(new TestConfigurationService), new TestConfigurationService(), new TestCapabilitiesService()); testConnectionDialog.render(); testConnectionDialog['renderBody'](DOM.createStyleSheet()); (connectionDialogService as any)._connectionDialog = testConnectionDialog; diff --git a/src/sql/workbench/services/connection/test/browser/connectionDialogWidget.test.ts b/src/sql/workbench/services/connection/test/browser/connectionDialogWidget.test.ts index 61bcba7ee5..a349e9c2ff 100644 --- a/src/sql/workbench/services/connection/test/browser/connectionDialogWidget.test.ts +++ b/src/sql/workbench/services/connection/test/browser/connectionDialogWidget.test.ts @@ -65,7 +65,7 @@ suite('ConnectionDialogWidget tests', () => { new TestCapabilitiesService()); let providerDisplayNames = ['Mock SQL Server']; let providerNameToDisplayMap = { 'MSSQL': 'Mock SQL Server' }; - connectionDialogWidget = new TestConnectionDialogWidget(providerDisplayNames, providerNameToDisplayMap['MSSQL'], providerNameToDisplayMap, cmInstantiationService, mockConnectionManagementService.object, undefined, undefined, viewDescriptorService, new TestThemeService(), new TestLayoutService(), new NullAdsTelemetryService(), new MockContextKeyService(), undefined, new NullLogService(), new TestTextResourcePropertiesService(new TestConfigurationService()), new TestConfigurationService(), new TestCapabilitiesService(), undefined, undefined, undefined); + connectionDialogWidget = new TestConnectionDialogWidget(providerDisplayNames, providerNameToDisplayMap['MSSQL'], providerNameToDisplayMap, cmInstantiationService, mockConnectionManagementService.object, undefined, undefined, viewDescriptorService, new TestThemeService(), new TestLayoutService(), new NullAdsTelemetryService(), new MockContextKeyService(), undefined, new NullLogService(), new TestTextResourcePropertiesService(new TestConfigurationService()), new TestConfigurationService(), new TestCapabilitiesService()); element = DOM.createStyleSheet(); connectionDialogWidget.render(); connectionDialogWidget['renderBody'](element); diff --git a/src/sql/workbench/services/connection/test/browser/connectionManagementService.test.ts b/src/sql/workbench/services/connection/test/browser/connectionManagementService.test.ts index 0f77accbfd..c38a7c00c7 100644 --- a/src/sql/workbench/services/connection/test/browser/connectionManagementService.test.ts +++ b/src/sql/workbench/services/connection/test/browser/connectionManagementService.test.ts @@ -185,7 +185,10 @@ suite('SQL ConnectionManagementService tests', () => { accountManagementService.object, testLogService, // ILogService undefined, // IStorageService - getBasicExtensionService() + getBasicExtensionService(), + undefined, + undefined, + undefined ); return connectionManagementService; } @@ -1573,7 +1576,7 @@ suite('SQL ConnectionManagementService tests', () => { const testInstantiationService = new TestInstantiationService(); testInstantiationService.stub(IStorageService, new TestStorageService()); testInstantiationService.stubCreateInstance(ConnectionStore, connectionStoreMock.object); - const connectionManagementService = new ConnectionManagementService(undefined, testInstantiationService, undefined, undefined, undefined, new TestCapabilitiesService(), undefined, undefined, undefined, undefined, undefined, undefined, undefined, getBasicExtensionService()); + const connectionManagementService = new ConnectionManagementService(undefined, testInstantiationService, undefined, undefined, undefined, new TestCapabilitiesService(), undefined, undefined, undefined, undefined, undefined, undefined, undefined, getBasicExtensionService(), undefined, undefined, undefined); assert.strictEqual(profile.password, '', 'Profile should not have password initially'); assert.strictEqual(profile.options['password'], '', 'Profile options should not have password initially'); // Check for invalid profile id @@ -1603,7 +1606,7 @@ suite('SQL ConnectionManagementService tests', () => { testInstantiationService.stub(IStorageService, new TestStorageService()); testInstantiationService.stubCreateInstance(ConnectionStore, connectionStoreMock.object); - const connectionManagementService = new ConnectionManagementService(undefined, testInstantiationService, undefined, undefined, undefined, new TestCapabilitiesService(), undefined, undefined, undefined, undefined, undefined, undefined, undefined, getBasicExtensionService()); + const connectionManagementService = new ConnectionManagementService(undefined, testInstantiationService, undefined, undefined, undefined, new TestCapabilitiesService(), undefined, undefined, undefined, undefined, undefined, undefined, undefined, getBasicExtensionService(), undefined, undefined, undefined); assert.strictEqual(profile.password, '', 'Profile should not have password initially'); assert.strictEqual(profile.options['password'], '', 'Profile options should not have password initially'); let credentials = await connectionManagementService.getConnectionCredentials(profile.id); @@ -1848,7 +1851,7 @@ suite('SQL ConnectionManagementService tests', () => { createInstanceStub.withArgs(ConnectionStore).returns(connectionStoreMock.object); createInstanceStub.withArgs(ConnectionStatusManager).returns(connectionStatusManagerMock.object); - const connectionManagementService = new ConnectionManagementService(undefined, testInstantiationService, undefined, undefined, undefined, new TestCapabilitiesService(), undefined, undefined, undefined, undefined, undefined, undefined, undefined, getBasicExtensionService()); + const connectionManagementService = new ConnectionManagementService(undefined, testInstantiationService, undefined, undefined, undefined, new TestCapabilitiesService(), undefined, undefined, undefined, undefined, undefined, undefined, undefined, getBasicExtensionService(), undefined, undefined, undefined); // dupe connections have been seeded the numbers below already reflected the de-duped results @@ -1881,7 +1884,7 @@ test('isRecent should evaluate whether a profile was recently connected or not', }); let profile1 = createConnectionProfile('1'); let profile2 = createConnectionProfile('2'); - const connectionManagementService = new ConnectionManagementService(undefined, testInstantiationService, undefined, undefined, undefined, new TestCapabilitiesService(), undefined, undefined, undefined, undefined, undefined, undefined, undefined, getBasicExtensionService()); + const connectionManagementService = new ConnectionManagementService(undefined, testInstantiationService, undefined, undefined, undefined, new TestCapabilitiesService(), undefined, undefined, undefined, undefined, undefined, undefined, undefined, getBasicExtensionService(), undefined, undefined, undefined); assert(connectionManagementService.isRecent(profile1)); assert(!connectionManagementService.isRecent(profile2)); }); @@ -1899,7 +1902,7 @@ test('clearRecentConnection and ConnectionsList should call connectionStore func testInstantiationService.stub(IStorageService, new TestStorageService()); sinon.stub(testInstantiationService, 'createInstance').withArgs(ConnectionStore).returns(connectionStoreMock.object); let profile1 = createConnectionProfile('1'); - const connectionManagementService = new ConnectionManagementService(undefined, testInstantiationService, undefined, undefined, undefined, new TestCapabilitiesService(), undefined, undefined, undefined, undefined, undefined, undefined, undefined, getBasicExtensionService()); + const connectionManagementService = new ConnectionManagementService(undefined, testInstantiationService, undefined, undefined, undefined, new TestCapabilitiesService(), undefined, undefined, undefined, undefined, undefined, undefined, undefined, getBasicExtensionService(), undefined, undefined, undefined); connectionManagementService.clearRecentConnection(profile1); assert(called); called = false; diff --git a/src/sql/workbench/services/connection/test/browser/testConnectionDialogWidget.ts b/src/sql/workbench/services/connection/test/browser/testConnectionDialogWidget.ts index 72644efc7b..12baf8f416 100644 --- a/src/sql/workbench/services/connection/test/browser/testConnectionDialogWidget.ts +++ b/src/sql/workbench/services/connection/test/browser/testConnectionDialogWidget.ts @@ -17,9 +17,6 @@ import { ITextResourcePropertiesService } from 'vs/editor/common/services/textRe import { IViewDescriptorService } from 'vs/workbench/common/views'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { ICapabilitiesService } from 'sql/platform/capabilities/common/capabilitiesService'; -import { INotificationService } from 'vs/platform/notification/common/notification'; -import { ICommandService } from 'vs/platform/commands/common/commands'; -import { IPaneCompositePartService } from 'vs/workbench/services/panecomposite/browser/panecomposite'; export class TestConnectionDialogWidget extends ConnectionDialogWidget { constructor( @@ -39,11 +36,8 @@ export class TestConnectionDialogWidget extends ConnectionDialogWidget { @ILogService logService: ILogService, @ITextResourcePropertiesService textResourcePropertiesService: ITextResourcePropertiesService, @IConfigurationService configurationService: IConfigurationService, - @ICapabilitiesService capabilitiesService: ICapabilitiesService, - @INotificationService notificationService: INotificationService, - @IPaneCompositePartService paneCompositeService: IPaneCompositePartService, - @ICommandService commandService: ICommandService + @ICapabilitiesService capabilitiesService: ICapabilitiesService ) { - super(providerDisplayNameOptions, selectedProviderType, providerNameToDisplayNameMap, _instantiationService, _connectionManagementService, _contextMenuService, _contextViewService, themeService, layoutService, telemetryService, contextKeyService, clipboardService, logService, textResourcePropertiesService, configurationService, capabilitiesService, notificationService, paneCompositeService, commandService); + super(providerDisplayNameOptions, selectedProviderType, providerNameToDisplayNameMap, _instantiationService, _connectionManagementService, _contextMenuService, _contextViewService, themeService, layoutService, telemetryService, contextKeyService, clipboardService, logService, textResourcePropertiesService, configurationService, capabilitiesService); } }