diff --git a/extensions/mssql/package.json b/extensions/mssql/package.json index 3626ebdb05..3315cdbdc2 100644 --- a/extensions/mssql/package.json +++ b/extensions/mssql/package.json @@ -17,6 +17,14 @@ "compile": "gulp compile-extension:mssql-client", "update-grammar": "node ../../build/npm/update-grammar.js Microsoft/vscode-mssql syntaxes/SQL.plist ./syntaxes/sql.tmLanguage.json" }, + "dependencies": { + "dataprotocol-client": "github:Microsoft/sqlops-dataprotocolclient#0.2.6", + "opener": "^1.4.3", + "service-downloader": "github:anthonydresser/service-downloader#0.1.4", + "vscode-extension-telemetry": "^0.0.15" + }, + "devDependencies": { + }, "contributes": { "languages": [ { @@ -656,13 +664,5 @@ } ] } - }, - "dependencies": { - "dataprotocol-client": "github:Microsoft/sqlops-dataprotocolclient#0.2.5", - "opener": "^1.4.3", - "service-downloader": "github:anthonydresser/service-downloader#0.1.4", - "vscode-extension-telemetry": "^0.0.15" - }, - "devDependencies": { } } diff --git a/extensions/mssql/src/config.json b/extensions/mssql/src/config.json index 60784d1a59..dd0aea67df 100644 --- a/extensions/mssql/src/config.json +++ b/extensions/mssql/src/config.json @@ -1,6 +1,6 @@ { "downloadUrl": "https://github.com/Microsoft/sqltoolsservice/releases/download/v{#version#}/microsoft.sqltools.servicelayer-{#fileName#}", - "version": "1.5.0-alpha.27", + "version": "1.5.0-alpha.28", "downloadFileNames": { "Windows_86": "win-x86-netcoreapp2.1.zip", "Windows_64": "win-x64-netcoreapp2.1.zip", diff --git a/extensions/mssql/yarn.lock b/extensions/mssql/yarn.lock index 5976a32b4b..981aafc4f6 100644 --- a/extensions/mssql/yarn.lock +++ b/extensions/mssql/yarn.lock @@ -64,9 +64,9 @@ core-util-is@~1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" -"dataprotocol-client@github:Microsoft/sqlops-dataprotocolclient#0.2.5": - version "0.2.5" - resolved "https://codeload.github.com/Microsoft/sqlops-dataprotocolclient/tar.gz/6aca9c6850d2b2e1e59f09d67e15922f5acec5ea" +"dataprotocol-client@github:Microsoft/sqlops-dataprotocolclient#0.2.6": + version "0.2.6" + resolved "https://codeload.github.com/Microsoft/sqlops-dataprotocolclient/tar.gz/b40358cdf33fbc4076a5621363d95350ab08d882" dependencies: vscode-languageclient "3.5.1" diff --git a/src/sql/base/browser/ui/modal/modal.ts b/src/sql/base/browser/ui/modal/modal.ts index 7fab27544f..2c657d04e0 100644 --- a/src/sql/base/browser/ui/modal/modal.ts +++ b/src/sql/base/browser/ui/modal/modal.ts @@ -135,7 +135,7 @@ export abstract class Modal extends Disposable implements IThemable { private _name: string, private _partService: IPartService, private _telemetryService: ITelemetryService, - private _contextKeyService: IContextKeyService, + _contextKeyService: IContextKeyService, options?: IModalOptions ) { super(); diff --git a/src/sql/parts/connection/common/connection.contribution.ts b/src/sql/parts/connection/common/connection.contribution.ts index 89bc79a5a6..f82196cbbc 100644 --- a/src/sql/parts/connection/common/connection.contribution.ts +++ b/src/sql/parts/connection/common/connection.contribution.ts @@ -92,5 +92,10 @@ configurationRegistry.registerConfiguration({ 'description': localize('sql.defaultEngineDescription', 'Default SQL Engine to use. This drives default language provider in .sql files and the default to use when creating a new connection. Valid option is currently MSSQL'), 'default': 'MSSQL' }, + 'connection.parseClipboardForConnectionString': { + 'type': 'boolean', + 'default': true, + 'description': localize('connection.parseClipboardForConnectionStringDescription', 'Attempt to parse the contents of the clipboard when the connection dialog is opened or a paste is performed.') + } } -}); \ No newline at end of file +}); diff --git a/src/sql/parts/connection/common/connectionManagement.ts b/src/sql/parts/connection/common/connectionManagement.ts index a2aa2c6818..d2234ad5b9 100644 --- a/src/sql/parts/connection/common/connectionManagement.ts +++ b/src/sql/parts/connection/common/connectionManagement.ts @@ -266,6 +266,11 @@ export interface IConnectionManagementService { * Get the connection string for the provided connection profile */ getConnectionString(ownerUri: string, includePassword: boolean): Thenable; + + /** + * Serialize connection string with optional provider + */ + buildConnectionInfo(connectionString: string, provider?: string): Thenable; } export const IConnectionDialogService = createDecorator('connectionDialogService'); diff --git a/src/sql/parts/connection/common/connectionManagementService.ts b/src/sql/parts/connection/common/connectionManagementService.ts index db2561e6fc..15bb2a3a35 100644 --- a/src/sql/parts/connection/common/connectionManagementService.ts +++ b/src/sql/parts/connection/common/connectionManagementService.ts @@ -1366,4 +1366,14 @@ export class ConnectionManagementService extends Disposable implements IConnecti }); }); } + + /** + * Serialize connection with options provider + * TODO this could be a map reduce operation + */ + public buildConnectionInfo(connectionString: string, provider: string): Thenable { + return this._providers.get(provider).onReady.then(e => { + return e.buildConnectionInfo(connectionString); + }); + } } diff --git a/src/sql/parts/connection/connectionDialog/connectionDialogWidget.ts b/src/sql/parts/connection/connectionDialog/connectionDialogWidget.ts index 4f6aa8007d..d319836be7 100644 --- a/src/sql/parts/connection/connectionDialog/connectionDialogWidget.ts +++ b/src/sql/parts/connection/connectionDialog/connectionDialogWidget.ts @@ -34,7 +34,6 @@ import { ITree } from 'vs/base/parts/tree/browser/tree'; import { IContextMenuService, IContextViewService } from 'vs/platform/contextview/browser/contextView'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import * as styler from 'vs/platform/theme/common/styler'; -import { TPromise } from 'vs/base/common/winjs.base'; import * as DOM from 'vs/base/browser/dom'; import { ActionBar } from 'vs/base/browser/ui/actionbar/actionbar'; @@ -376,6 +375,7 @@ export class ConnectionDialogWidget extends Modal { */ public open(recentConnections: boolean) { this._panel.showTab(this._recentConnectionTabId); + this.show(); if (recentConnections) { this._noRecentConnectionBuilder.hide(); diff --git a/src/sql/parts/connection/connectionDialog/connectionWidget.ts b/src/sql/parts/connection/connectionDialog/connectionWidget.ts index a3b145127c..1509a994ea 100644 --- a/src/sql/parts/connection/connectionDialog/connectionWidget.ts +++ b/src/sql/parts/connection/connectionDialog/connectionWidget.ts @@ -19,6 +19,9 @@ import * as Constants from 'sql/parts/connection/common/constants'; import { ConnectionProfileGroup, IConnectionProfileGroup } from 'sql/parts/connection/common/connectionProfileGroup'; import { attachInputBoxStyler, attachButtonStyler, attachEditableDropdownStyler } from 'sql/common/theme/styler'; import { Dropdown } from 'sql/base/browser/ui/editableDropdown/dropdown'; +import { IConnectionManagementService } from 'sql/parts/connection/common/connectionManagement'; +import { ICapabilitiesService } from 'sql/services/capabilities/capabilitiesService'; +import { ConnectionProfile } from '../common/connectionProfile'; import * as sqlops from 'sqlops'; @@ -32,6 +35,8 @@ import { OS, OperatingSystem } from 'vs/base/common/platform'; import { Builder, $ } from 'vs/base/browser/builder'; import { MessageType } from 'vs/base/browser/ui/inputbox/inputBox'; import { endsWith, startsWith } from 'vs/base/common/strings'; +import { IClipboardService } from 'vs/platform/clipboard/common/clipboardService'; +import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; export class ConnectionWidget { private _builder: Builder; @@ -85,7 +90,12 @@ export class ConnectionWidget { callbacks: IConnectionComponentCallbacks, providerName: string, @IThemeService private _themeService: IThemeService, - @IContextViewService private _contextViewService: IContextViewService) { + @IContextViewService private _contextViewService: IContextViewService, + @IConnectionManagementService private _connectionManagementService: IConnectionManagementService, + @ICapabilitiesService private _capabilitiesService: ICapabilitiesService, + @IClipboardService private _clipboardService: IClipboardService, + @IConfigurationService private _configurationService: IConfigurationService + ) { this._callbacks = callbacks; this._toDispose = []; this._optionsMaps = {}; @@ -120,9 +130,29 @@ export class ConnectionWidget { if (this._authTypeSelectBox) { this.onAuthTypeSelected(this._authTypeSelectBox.value); } + + DOM.addDisposableListener(container, 'paste', e => { + this._handleClipboard(); + }); + DOM.append(container, this._builder.getHTMLElement()); } + private _handleClipboard(): void { + if (this._configurationService.getValue('connection.parseClipboardForConnectionString')) { + let paste = this._clipboardService.readText(); + this._connectionManagementService.buildConnectionInfo(paste, this._providerName).then(e => { + if (e) { + let profile = new ConnectionProfile(this._capabilitiesService, this._providerName); + profile.options = e.options; + if (profile.serverName) { + this.initDialog(profile); + } + } + }); + } + } + private fillInConnectionForm(): void { let serverNameOption = this._optionsMaps[ConnectionOptionSpecialType.serverName]; let serverNameBuilder = DialogHelper.appendRow(this._tableContainer, serverNameOption.displayName, 'connection-label', 'connection-input'); @@ -130,7 +160,7 @@ export class ConnectionWidget { validationOptions: { validation: (value: string) => { if (!value) { - return ({ type: MessageType.ERROR, content: localize('connectionWidget.missingRequireField', '{0} is required.', serverNameOption.displayName)}); + return ({ type: MessageType.ERROR, content: localize('connectionWidget.missingRequireField', '{0} is required.', serverNameOption.displayName) }); } else if (startsWith(value, ' ') || endsWith(value, ' ')) { return ({ type: MessageType.WARNING, content: localize('connectionWidget.fieldWillBeTrimmed', '{0} will be trimmed.', serverNameOption.displayName) }); } @@ -354,6 +384,7 @@ export class ConnectionWidget { } public focusOnOpen(): void { + this._handleClipboard(); this._serverNameInputBox.focus(); this.focusPasswordIfNeeded(); this.clearValidationMessages(); diff --git a/src/sql/sqlops.d.ts b/src/sql/sqlops.d.ts index e24c601848..0ab39faa66 100644 --- a/src/sql/sqlops.d.ts +++ b/src/sql/sqlops.d.ts @@ -327,7 +327,9 @@ declare module 'sqlops' { rebuildIntelliSenseCache(connectionUri: string): Thenable; - getConnectionString(connectionUri: string, includePassword: boolean): Thenable ; + getConnectionString(connectionUri: string, includePassword: boolean): Thenable; + + buildConnectionInfo?(connectionString: string): Thenable; registerOnConnectionComplete(handler: (connSummary: ConnectionInfoSummary) => any): void; diff --git a/src/sql/workbench/api/node/extHostDataProtocol.ts b/src/sql/workbench/api/node/extHostDataProtocol.ts index f915d6e7bc..95bd9d950a 100644 --- a/src/sql/workbench/api/node/extHostDataProtocol.ts +++ b/src/sql/workbench/api/node/extHostDataProtocol.ts @@ -11,6 +11,7 @@ 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'; +import { TPromise } from 'vs/base/common/winjs.base'; export class ExtHostDataProtocol extends ExtHostDataProtocolShape { @@ -185,6 +186,15 @@ export class ExtHostDataProtocol extends ExtHostDataProtocolShape { return this._resolveProvider(handle).getConnectionString(connectionUri, includePassword); } + $buildConnectionInfo(handle: number, connectionString: string): Thenable { + let provider = this._resolveProvider(handle); + if (provider.buildConnectionInfo) { + return provider.buildConnectionInfo(connectionString); + } else { + return TPromise.as(undefined); + } + } + $rebuildIntelliSenseCache(handle: number, connectionUri: string): Thenable { return this._resolveProvider(handle).rebuildIntelliSenseCache(connectionUri); } @@ -617,7 +627,7 @@ export class ExtHostDataProtocol extends ExtHostDataProtocolShape { /** * Get Agent Proxies list */ - $getProxies(handle: number, ownerUri: string): Thenable { + $getProxies(handle: number, ownerUri: string): Thenable { return this._resolveProvider(handle).getProxies(ownerUri); } diff --git a/src/sql/workbench/api/node/mainThreadDataProtocol.ts b/src/sql/workbench/api/node/mainThreadDataProtocol.ts index 485cf62be6..ba8fa88f2e 100644 --- a/src/sql/workbench/api/node/mainThreadDataProtocol.ts +++ b/src/sql/workbench/api/node/mainThreadDataProtocol.ts @@ -27,7 +27,6 @@ import { ISerializationService } from 'sql/services/serialization/serializationS import { IFileBrowserService } from 'sql/parts/fileBrowser/common/interfaces'; import { IExtHostContext } from 'vs/workbench/api/node/extHost.protocol'; import { extHostNamedCustomer } from 'vs/workbench/api/electron-browser/extHostCustomers'; -import severity from 'vs/base/common/severity'; /** * Main thread class for handling data protocol management registration. @@ -91,6 +90,9 @@ export class MainThreadDataProtocol implements MainThreadDataProtocolShape { getConnectionString(connectionUri: string, includePassword: boolean): Thenable { return self._proxy.$getConnectionString(handle, connectionUri, includePassword); }, + buildConnectionInfo(connectionString: string): Thenable { + return self._proxy.$buildConnectionInfo(handle, connectionString); + }, rebuildIntelliSenseCache(connectionUri: string): Thenable { return self._proxy.$rebuildIntelliSenseCache(handle, connectionUri); } @@ -343,7 +345,7 @@ export class MainThreadDataProtocol implements MainThreadDataProtocolShape { public $registerAgentServicesProvider(providerId: string, handle: number): TPromise { const self = this; - this._jobManagementService.registerProvider(providerId, { + this._jobManagementService.registerProvider(providerId, { providerId: providerId, getJobs(connectionUri: string): Thenable { return self._proxy.$getJobs(handle, connectionUri); diff --git a/src/sql/workbench/api/node/sqlExtHost.protocol.ts b/src/sql/workbench/api/node/sqlExtHost.protocol.ts index a035009c69..d12bdb90b0 100644 --- a/src/sql/workbench/api/node/sqlExtHost.protocol.ts +++ b/src/sql/workbench/api/node/sqlExtHost.protocol.ts @@ -22,7 +22,6 @@ import { IItemConfig, ModelComponentTypes, IComponentShape, IModelViewDialogDetails, IModelViewTabDetails, IModelViewButtonDetails, IModelViewWizardDetails, IModelViewWizardPageDetails } from 'sql/workbench/api/common/sqlExtHostTypes'; -import { Event, Emitter } from 'vs/base/common/event'; export abstract class ExtHostAccountManagementShape { $autoOAuthCancelled(handle: number): Thenable { throw ni(); } @@ -73,6 +72,13 @@ export abstract class ExtHostDataProtocolShape { */ $getConnectionString(handle: number, connectionUri: string, includePassword: boolean): Thenable { throw ni(); } + /** + * Serialize connection string + * @param handle the handle to use when looking up a provider + * @param connectionString the connection string to serialize + */ + $buildConnectionInfo(handle: number, connectionString: string): Thenable { throw ni(); } + /** * Notifies all listeners on the Extension Host side that a language change occurred * for a dataprotocol language. The sub-flavor is the specific implementation used for query @@ -609,7 +615,7 @@ export interface ExtHostModelViewTreeViewsShape { $getChildren(treeViewId: string, treeItemHandle?: string): TPromise; $createTreeView(handle: number, componentId: string, options: { treeDataProvider: vscode.TreeDataProvider }): sqlops.TreeComponentView; $onNodeCheckedChanged(treeViewId: string, treeItemHandle?: string, checked?: boolean): void; - $onNodeSelected(treeViewId: string, nodes: string[]): void; + $onNodeSelected(treeViewId: string, nodes: string[]): void; } export interface ExtHostBackgroundTaskManagementShape { diff --git a/src/sqltest/stubs/connectionManagementService.test.ts b/src/sqltest/stubs/connectionManagementService.test.ts index 2b1206ed36..ebb864b29f 100644 --- a/src/sqltest/stubs/connectionManagementService.test.ts +++ b/src/sqltest/stubs/connectionManagementService.test.ts @@ -257,4 +257,8 @@ export class TestConnectionManagementService implements IConnectionManagementSer getConnectionString(ownerUri: string): Thenable { return undefined; } + + buildConnectionInfo(connectionString: string, provider?: string): Thenable { + return undefined; + } } \ No newline at end of file