From 503090856a291232cc564e397d258e7a2ae03f4f Mon Sep 17 00:00:00 2001 From: Anthony Dresser Date: Fri, 4 Sep 2020 18:04:08 -0700 Subject: [PATCH] Strict null scripting (#12126) * strict null scripting * fix compile * fix tests * fix icon --- src/sql/azdata.d.ts | 6 +- .../common/capabilitiesService.ts | 3 + .../connection/common/connectionProfile.ts | 22 +- .../common/connectionStatusManager.ts | 4 +- src/sql/platform/connection/common/utils.ts | 4 +- .../test/common/connectionProfile.test.ts | 2 +- .../common/providerConnectionInfo.test.ts | 4 +- .../browser/editor/profiler/dashboardInput.ts | 2 +- src/sql/workbench/browser/scriptingActions.ts | 24 +- src/sql/workbench/browser/scriptingUtils.ts | 31 +-- .../browser/connectionViewletPanel.ts | 4 +- .../browser/dataExplorerViewlet.ts | 8 +- .../objectExplorer/browser/serverTreeView.ts | 206 +++++++-------- .../scripting/browser/scriptingActions.ts | 234 ++++++++++-------- .../test/browser/scriptingActions.test.ts | 5 +- .../connection/common/connectionContextKey.ts | 2 +- .../browser/asyncServerTreeDataSource.ts | 2 +- .../browser/asyncServerTreeDragAndDrop.ts | 20 +- .../asyncServerTreeIdentityProvider.ts | 2 +- .../browser/asyncServerTreeRenderer.ts | 51 ++-- .../browser/dragAndDropController.ts | 36 +-- .../objectExplorer/browser/iconRenderer.ts | 26 +- .../browser/recentConnectionDataSource.ts | 6 +- .../browser/serverTreeController.ts | 2 +- .../browser/serverTreeDataSource.ts | 10 +- .../browser/serverTreeRenderer.ts | 35 +-- .../browser/treeCreationUtils.ts | 2 +- .../asyncServerTreeDragAndDrop.test.ts | 2 +- .../browser/dragAndDropController.test.ts | 2 +- .../test/browser/testObjectExplorerService.ts | 44 ++-- .../queryHistory/common/queryHistoryInfo.ts | 2 +- .../restore/browser/restoreServiceImpl.ts | 2 +- .../services/tasks/common/tasksService.ts | 2 +- src/sql/workbench/test/treeMock.ts | 22 +- src/tsconfig.vscode.json | 1 - 35 files changed, 427 insertions(+), 403 deletions(-) diff --git a/src/sql/azdata.d.ts b/src/sql/azdata.d.ts index 3b0b0259a8..239798e319 100644 --- a/src/sql/azdata.d.ts +++ b/src/sql/azdata.d.ts @@ -322,7 +322,7 @@ declare module 'azdata' { export interface IConnectionProfile extends ConnectionInfo { connectionName?: string; serverName: string; - databaseName: string; + databaseName?: string; userName: string; password: string; authenticationType: string; @@ -413,7 +413,7 @@ declare module 'azdata' { /** * database name */ - databaseName: string; + databaseName?: string; /** * user name */ @@ -749,7 +749,7 @@ declare module 'azdata' { } export interface ScriptingParamDetails { - filePath: string; + filePath?: string; scriptCompatibilityOption: string; targetDatabaseEngineEdition: string; targetDatabaseEngineType: string; diff --git a/src/sql/platform/capabilities/common/capabilitiesService.ts b/src/sql/platform/capabilities/common/capabilitiesService.ts index f9da677ca1..4e1f57683d 100644 --- a/src/sql/platform/capabilities/common/capabilitiesService.ts +++ b/src/sql/platform/capabilities/common/capabilitiesService.ts @@ -8,6 +8,8 @@ import * as azdata from 'azdata'; import { Event } from 'vs/base/common/event'; import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; import type { IDisposable } from 'vs/base/common/lifecycle'; +import { URI } from 'vs/base/common/uri'; +import { IconPath } from 'sql/platform/connection/common/connectionProfile'; export const SERVICE_ID = 'capabilitiesService'; export const HOST_NAME = 'azdata'; @@ -20,6 +22,7 @@ export const clientCapabilities = { export interface ConnectionProviderProperties { providerId: string; + iconPath?: URI | IconPath | { id: string, path: IconPath }[] displayName: string; notebookKernelAlias?: string; azureResource?: string; diff --git a/src/sql/platform/connection/common/connectionProfile.ts b/src/sql/platform/connection/common/connectionProfile.ts index 55664c29a4..e5a9acbbad 100644 --- a/src/sql/platform/connection/common/connectionProfile.ts +++ b/src/sql/platform/connection/common/connectionProfile.ts @@ -13,7 +13,13 @@ import { ICapabilitiesService } from 'sql/platform/capabilities/common/capabilit import { isString } from 'vs/base/common/types'; import { deepClone } from 'vs/base/common/objects'; import * as Constants from 'sql/platform/connection/common/constants'; -import { find } from 'vs/base/common/arrays'; +import { URI } from 'vs/base/common/uri'; + +export interface IconPath { + light: URI; + dark: URI; +} + // Concrete implementation of the IConnectionProfile interface @@ -29,6 +35,8 @@ export class ConnectionProfile extends ProviderConnectionInfo implements interfa public groupId?: string; public saveProfile: boolean; + public iconPath?: IconPath; + public isDisconnecting: boolean = false; public constructor( @@ -49,7 +57,7 @@ export class ConnectionProfile extends ProviderConnectionInfo implements interfa let capabilities = this.capabilitiesService.getCapabilities(model.providerName); if (capabilities && capabilities.connection && capabilities.connection.connectionOptions) { const options = capabilities.connection.connectionOptions; - let appNameOption = find(options, option => option.specialValueType === interfaces.ConnectionOptionSpecialType.appName); + let appNameOption = options.find(option => option.specialValueType === interfaces.ConnectionOptionSpecialType.appName); if (appNameOption) { let appNameKey = appNameOption.name; this.options[appNameKey] = Constants.applicationName; @@ -87,9 +95,13 @@ export class ConnectionProfile extends ProviderConnectionInfo implements interfa } - private static nullCheckEqualsIgnoreCase(a: string, b: string) { - let bothNull: boolean = !a && !b; - return bothNull ? bothNull : equalsIgnoreCase(a, b); + private static nullCheckEqualsIgnoreCase(a?: string, b?: string) { + if (a && !b || b && !a) { + return false; + } else { + let bothNull: boolean = !a && !b; + return bothNull ? bothNull : equalsIgnoreCase(a!, b!); + } } public generateNewId() { diff --git a/src/sql/platform/connection/common/connectionStatusManager.ts b/src/sql/platform/connection/common/connectionStatusManager.ts index 7574549cc3..807e847bfa 100644 --- a/src/sql/platform/connection/common/connectionStatusManager.ts +++ b/src/sql/platform/connection/common/connectionStatusManager.ts @@ -152,7 +152,7 @@ export class ConnectionStatusManager { //Check if the existing connection database name is different the one in the summary if (connection.connectionProfile.databaseName !== summary.connectionSummary.databaseName) { //Add the ownerUri with database name to the map if not already exists - connection.connectionProfile.databaseName = summary.connectionSummary.databaseName; + connection.connectionProfile.databaseName = summary.connectionSummary.databaseName!; let prefix = Utils.getUriPrefix(summary.ownerUri); let ownerUriWithDbName = Utils.generateUriWithPrefix(connection.connectionProfile, prefix); if (!(ownerUriWithDbName in this._connections)) { @@ -186,7 +186,7 @@ export class ConnectionStatusManager { let connection = this._connections[changedConnInfo.connectionUri]; if (connection && connection.connectionProfile) { connection.connectionProfile.serverName = changedConnInfo.connection.serverName; - connection.connectionProfile.databaseName = changedConnInfo.connection.databaseName; + connection.connectionProfile.databaseName = changedConnInfo.connection.databaseName!; connection.connectionProfile.userName = changedConnInfo.connection.userName; return connection.connectionProfile; } diff --git a/src/sql/platform/connection/common/utils.ts b/src/sql/platform/connection/common/utils.ts index 79f0ab9b58..feccd95b10 100644 --- a/src/sql/platform/connection/common/utils.ts +++ b/src/sql/platform/connection/common/utils.ts @@ -137,6 +137,6 @@ export function findProfileInGroup(og: IConnectionProfile, groups: ConnectionPro export function isMaster(profile: IConnectionProfile): boolean { // TODO: the connection profile should have a property to indicate whether the connection is a server connection or database connection // created issue to track the problem: https://github.com/Microsoft/azuredatastudio/issues/5193. - return (profile.providerName === mssqlProviderName && profile.databaseName.toLowerCase() === 'master') - || (profile.providerName.toLowerCase() === 'pgsql' && profile.databaseName.toLowerCase() === 'postgres'); + return (profile.providerName === mssqlProviderName && profile.databaseName?.toLowerCase() === 'master') + || (profile.providerName.toLowerCase() === 'pgsql' && profile.databaseName?.toLowerCase() === 'postgres'); } diff --git a/src/sql/platform/connection/test/common/connectionProfile.test.ts b/src/sql/platform/connection/test/common/connectionProfile.test.ts index ec534858eb..efcdb91cb1 100644 --- a/src/sql/platform/connection/test/common/connectionProfile.test.ts +++ b/src/sql/platform/connection/test/common/connectionProfile.test.ts @@ -138,7 +138,7 @@ suite('SQL ConnectionProfileInfo tests', () => { assert.equal(conn.serverName, undefined); conn.connectionName = connectionProfile.connectionName!; conn.serverName = connectionProfile.serverName; - conn.databaseName = connectionProfile.databaseName; + conn.databaseName = connectionProfile.databaseName!; conn.authenticationType = connectionProfile.authenticationType; conn.password = connectionProfile.password; conn.userName = connectionProfile.userName; diff --git a/src/sql/platform/connection/test/common/providerConnectionInfo.test.ts b/src/sql/platform/connection/test/common/providerConnectionInfo.test.ts index dff79df6ce..0749946f8e 100644 --- a/src/sql/platform/connection/test/common/providerConnectionInfo.test.ts +++ b/src/sql/platform/connection/test/common/providerConnectionInfo.test.ts @@ -141,7 +141,7 @@ suite('SQL ProviderConnectionInfo tests', () => { assert.equal(conn.serverName, undefined); conn.connectionName = connectionProfile.connectionName!; conn.serverName = connectionProfile.serverName; - conn.databaseName = connectionProfile.databaseName; + conn.databaseName = connectionProfile.databaseName!; conn.authenticationType = connectionProfile.authenticationType; conn.password = connectionProfile.password; conn.userName = connectionProfile.userName; @@ -157,7 +157,7 @@ suite('SQL ProviderConnectionInfo tests', () => { let conn = new ProviderConnectionInfo(capabilitiesService, mssqlProviderName); assert.equal(conn.serverName, undefined); conn.serverName = connectionProfile.serverName; - conn.databaseName = connectionProfile.databaseName; + conn.databaseName = connectionProfile.databaseName!; conn.authenticationType = connectionProfile.authenticationType; conn.password = connectionProfile.password; conn.userName = connectionProfile.userName; diff --git a/src/sql/workbench/browser/editor/profiler/dashboardInput.ts b/src/sql/workbench/browser/editor/profiler/dashboardInput.ts index 31c9a5dfc4..406295bf95 100644 --- a/src/sql/workbench/browser/editor/profiler/dashboardInput.ts +++ b/src/sql/workbench/browser/editor/profiler/dashboardInput.ts @@ -95,7 +95,7 @@ export class DashboardInput extends EditorInput { private isMasterMssql(): boolean { return this.connectionProfile.providerName === mssqlProviderName - && this.connectionProfile.databaseName.toLowerCase() === 'master'; + && this.connectionProfile.databaseName?.toLowerCase() === 'master'; } public get uri(): string | undefined { diff --git a/src/sql/workbench/browser/scriptingActions.ts b/src/sql/workbench/browser/scriptingActions.ts index 7a9aed35e5..525859a4ae 100644 --- a/src/sql/workbench/browser/scriptingActions.ts +++ b/src/sql/workbench/browser/scriptingActions.ts @@ -27,8 +27,8 @@ export class ScriptSelectAction extends Action { public async run(actionContext: BaseActionContext): Promise { return scriptSelect( - actionContext.profile, - actionContext.object, + actionContext.profile!, + actionContext.object!, this._connectionManagementService, this._queryEditorService, this._scriptingService @@ -52,8 +52,8 @@ export class ScriptExecuteAction extends Action { public async run(actionContext: BaseActionContext): Promise { return script( - actionContext.profile, - actionContext.object, + actionContext.profile!, + actionContext.object!, this._connectionManagementService, this._queryEditorService, this._scriptingService, @@ -79,8 +79,8 @@ export class ScriptAlterAction extends Action { public async run(actionContext: BaseActionContext): Promise { return script( - actionContext.profile, - actionContext.object, + actionContext.profile!, + actionContext.object!, this._connectionManagementService, this._queryEditorService, this._scriptingService, @@ -105,8 +105,8 @@ export class EditDataAction extends Action { public async run(actionContext: BaseActionContext): Promise { return scriptEditSelect( - actionContext.profile, - actionContext.object, + actionContext.profile!, + actionContext.object!, this._connectionManagementService, this._queryEditorService, this._scriptingService @@ -130,8 +130,8 @@ export class ScriptCreateAction extends Action { public async run(actionContext: BaseActionContext): Promise { return script( - actionContext.profile, - actionContext.object, + actionContext.profile!, + actionContext.object!, this._connectionManagementService, this._queryEditorService, this._scriptingService, @@ -157,8 +157,8 @@ export class ScriptDeleteAction extends Action { public async run(actionContext: BaseActionContext): Promise { return script( - actionContext.profile, - actionContext.object, + actionContext.profile!, + actionContext.object!, this._connectionManagementService, this._queryEditorService, this._scriptingService, diff --git a/src/sql/workbench/browser/scriptingUtils.ts b/src/sql/workbench/browser/scriptingUtils.ts index 4ebf081b4e..321914c5ff 100644 --- a/src/sql/workbench/browser/scriptingUtils.ts +++ b/src/sql/workbench/browser/scriptingUtils.ts @@ -42,7 +42,7 @@ const targetDatabaseEngineEditionMap = { */ export async function scriptSelect(connectionProfile: IConnectionProfile, metadata: azdata.ObjectMetadata, connectionService: IConnectionManagementService, queryEditorService: IQueryEditorService, scriptingService: IScriptingService): Promise { const connectionResult = await connectionService.connectIfNotConnected(connectionProfile); - let paramDetails: azdata.ScriptingParamDetails = getScriptingParamDetails(connectionService, connectionResult, metadata); + let paramDetails = getScriptingParamDetails(connectionService, connectionResult, metadata)!; const result = await scriptingService.script(connectionResult, metadata, ScriptOperation.Select, paramDetails); if (result && result.script) { const owner = await queryEditorService.newSqlEditor({ initalContent: result.script }, connectionProfile?.providerName); @@ -68,8 +68,8 @@ export async function scriptSelect(connectionProfile: IConnectionProfile, metada */ export async function scriptEditSelect(connectionProfile: IConnectionProfile, metadata: azdata.ObjectMetadata, connectionService: IConnectionManagementService, queryEditorService: IQueryEditorService, scriptingService: IScriptingService): Promise { const connectionResult = await connectionService.connectIfNotConnected(connectionProfile); - let paramDetails: azdata.ScriptingParamDetails = getScriptingParamDetails(connectionService, connectionResult, metadata); - const result = await scriptingService.script(connectionResult, metadata, ScriptOperation.Select, paramDetails); + let paramDetails = getScriptingParamDetails(connectionService, connectionResult, metadata); + const result = await scriptingService.script(connectionResult, metadata, ScriptOperation.Select, paramDetails!); if (result && result.script) { const owner = await queryEditorService.newEditDataEditor(metadata.schema, metadata.name, result.script); // Connect our editor @@ -120,7 +120,7 @@ export async function script(connectionProfile: IConnectionProfile, metadata: az operation: ScriptOperation, errorMessageService: IErrorMessageService): Promise { const connectionResult = await connectionService.connectIfNotConnected(connectionProfile); - let paramDetails = getScriptingParamDetails(connectionService, connectionResult, metadata); + let paramDetails = getScriptingParamDetails(connectionService, connectionResult, metadata)!; const result = await scriptingService.script(connectionResult, metadata, operation, paramDetails); if (result) { let script: string = result.script; @@ -160,18 +160,21 @@ export async function script(connectionProfile: IConnectionProfile, metadata: az } } -function getScriptingParamDetails(connectionService: IConnectionManagementService, ownerUri: string, metadata: azdata.ObjectMetadata): azdata.ScriptingParamDetails { - let serverInfo: azdata.ServerInfo = getServerInfo(connectionService, ownerUri); - let paramDetails: azdata.ScriptingParamDetails = { - filePath: undefined, - scriptCompatibilityOption: scriptCompatibilityOptionMap[serverInfo.serverMajorVersion], - targetDatabaseEngineEdition: targetDatabaseEngineEditionMap[serverInfo.engineEditionId], - targetDatabaseEngineType: serverInfo.isCloud ? 'SqlAzure' : 'SingleInstance' - }; - return paramDetails; +function getScriptingParamDetails(connectionService: IConnectionManagementService, ownerUri: string, metadata: azdata.ObjectMetadata): azdata.ScriptingParamDetails | undefined { + let serverInfo: azdata.ServerInfo | undefined = getServerInfo(connectionService, ownerUri); + if (serverInfo) { + let paramDetails: azdata.ScriptingParamDetails = { + filePath: undefined, + scriptCompatibilityOption: scriptCompatibilityOptionMap[serverInfo.serverMajorVersion as keyof typeof scriptCompatibilityOptionMap], + targetDatabaseEngineEdition: targetDatabaseEngineEditionMap[serverInfo.engineEditionId as keyof typeof targetDatabaseEngineEditionMap], + targetDatabaseEngineType: serverInfo.isCloud ? 'SqlAzure' : 'SingleInstance' + }; + return paramDetails; + } + return undefined; } -function getServerInfo(connectionService: IConnectionManagementService, ownerUri: string): azdata.ServerInfo { +function getServerInfo(connectionService: IConnectionManagementService, ownerUri: string): azdata.ServerInfo | undefined { let connection: ConnectionManagementInfo = connectionService.getConnectionInfo(ownerUri); return connection.serverInfo; } diff --git a/src/sql/workbench/contrib/dataExplorer/browser/connectionViewletPanel.ts b/src/sql/workbench/contrib/dataExplorer/browser/connectionViewletPanel.ts index 79a6ecd388..0e6946fba7 100644 --- a/src/sql/workbench/contrib/dataExplorer/browser/connectionViewletPanel.ts +++ b/src/sql/workbench/contrib/dataExplorer/browser/connectionViewletPanel.ts @@ -31,7 +31,7 @@ export class ConnectionViewletPanel extends ViewPane { public static readonly ID = 'dataExplorer.servers'; - private _root: HTMLElement; + private _root?: HTMLElement; private _serverTreeView: ServerTreeView; private _addServerAction: IAction; private _addServerGroupAction: IAction; @@ -89,7 +89,7 @@ export class ConnectionViewletPanel extends ViewPane { layoutBody(size: number): void { this._serverTreeView.layout(size); - DOM.toggleClass(this._root, 'narrow', this._root.clientWidth < 300); + DOM.toggleClass(this._root!, 'narrow', this._root!.clientWidth < 300); } show(): void { diff --git a/src/sql/workbench/contrib/dataExplorer/browser/dataExplorerViewlet.ts b/src/sql/workbench/contrib/dataExplorer/browser/dataExplorerViewlet.ts index aee74b6487..1ec0f4a5dd 100644 --- a/src/sql/workbench/contrib/dataExplorer/browser/dataExplorerViewlet.ts +++ b/src/sql/workbench/contrib/dataExplorer/browser/dataExplorerViewlet.ts @@ -87,9 +87,9 @@ export class DataExplorerViewlet extends Viewlet { } export class DataExplorerViewPaneContainer extends ViewPaneContainer { - private root: HTMLElement; + private root?: HTMLElement; - private dataSourcesBox: HTMLElement; + private dataSourcesBox?: HTMLElement; constructor( @IWorkbenchLayoutService layoutService: IWorkbenchLayoutService, @@ -125,7 +125,7 @@ export class DataExplorerViewPaneContainer extends ViewPaneContainer { } layout(dimension: Dimension): void { - toggleClass(this.root, 'narrow', dimension.width <= 300); + toggleClass(this.root!, 'narrow', dimension.width <= 300); super.layout(new Dimension(dimension.width, dimension.height)); } @@ -135,7 +135,7 @@ export class DataExplorerViewPaneContainer extends ViewPaneContainer { getSecondaryActions(): IAction[] { let menu = this.menuService.createMenu(MenuId.DataExplorerAction, this.contextKeyService); - let actions = []; + let actions: IAction[] = []; menu.getActions({}).forEach(group => { if (group[0] === 'secondary') { actions.push(...group[1]); diff --git a/src/sql/workbench/contrib/objectExplorer/browser/serverTreeView.ts b/src/sql/workbench/contrib/objectExplorer/browser/serverTreeView.ts index 4b1af93209..2b5dc18d7f 100644 --- a/src/sql/workbench/contrib/objectExplorer/browser/serverTreeView.ts +++ b/src/sql/workbench/contrib/objectExplorer/browser/serverTreeView.ts @@ -9,7 +9,7 @@ import { IInstantiationService, ServicesAccessor } from 'vs/platform/instantiati import Severity from 'vs/base/common/severity'; import { IThemeService } from 'vs/platform/theme/common/themeService'; import { attachListStyler } from 'vs/platform/theme/common/styler'; -import { ITree } from 'vs/base/parts/tree/browser/tree'; +import { ISelectionEvent, ITree } from 'vs/base/parts/tree/browser/tree'; import { Disposable } from 'vs/base/common/lifecycle'; import { localize } from 'vs/nls'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; @@ -29,31 +29,30 @@ import { IConnectionProfile } from 'sql/platform/connection/common/interfaces'; import { Button } from 'sql/base/browser/ui/button/button'; import { attachButtonStyler } from 'sql/platform/theme/common/styler'; import { TreeNode, TreeItemCollapsibleState } from 'sql/workbench/services/objectExplorer/common/treeNode'; -import { SERVER_GROUP_AUTOEXPAND_CONFIG } from 'sql/workbench/contrib/objectExplorer/common/serverGroup.contribution'; import { IErrorMessageService } from 'sql/platform/errorMessage/common/errorMessageService'; import { ServerTreeActionProvider } from 'sql/workbench/services/objectExplorer/browser/serverTreeActionProvider'; import { ICapabilitiesService } from 'sql/platform/capabilities/common/capabilitiesService'; import { isHidden } from 'sql/base/browser/dom'; import { CommandsRegistry } from 'vs/platform/commands/common/commands'; -import { startsWith } from 'vs/base/common/strings'; import { SERVER_GROUP_CONFIG } from 'sql/workbench/services/serverGroup/common/interfaces'; import { horizontalScrollingKey } from 'vs/platform/list/browser/listService'; -import { ITreeContextMenuEvent } from 'vs/base/browser/ui/tree/tree'; +import { ITreeContextMenuEvent, ITreeEvent } from 'vs/base/browser/ui/tree/tree'; import { ObjectExplorerActionsContext } from 'sql/workbench/services/objectExplorer/browser/objectExplorerActions'; import { IContextMenuService } from 'vs/platform/contextview/browser/contextView'; import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; import { AsyncServerTree, ServerTreeElement } from 'sql/workbench/services/objectExplorer/browser/asyncServerTree'; +import { coalesce } from 'vs/base/common/arrays'; /** * ServerTreeview implements the dynamic tree view. */ export class ServerTreeView extends Disposable implements IServerTreeView { - public messages: HTMLElement; - private _buttonSection: HTMLElement; + public messages?: HTMLElement; + private _buttonSection?: HTMLElement; private _treeSelectionHandler: TreeSelectionHandler; private _activeConnectionsFilterAction: ActiveConnectionsFilterAction; - private _tree: ITree | AsyncServerTree; + private _tree?: ITree | AsyncServerTree; private _onSelectionOrFocusChange: Emitter; private _actionProvider: ServerTreeActionProvider; @@ -81,7 +80,7 @@ export class ServerTreeView extends Disposable implements IServerTreeView { if (this._tree instanceof AsyncServerTree) { // Refresh the tree input now that the capabilities are registered so that we can // get the full ConnectionProfiles with the server info updated properly - const treeInput = TreeUpdateUtils.getTreeInput(this._connectionManagementService); + const treeInput = TreeUpdateUtils.getTreeInput(this._connectionManagementService)!; await this._tree.setInput(treeInput); this._treeSelectionHandler.onTreeActionStateChange(false); } else { @@ -113,7 +112,7 @@ export class ServerTreeView extends Disposable implements IServerTreeView { } public get tree(): ITree | AsyncServerTree { - return this._tree; + return this._tree!; } /** @@ -159,14 +158,14 @@ export class ServerTreeView extends Disposable implements IServerTreeView { const horizontalScrollEnabled: boolean = this._configurationService.getValue(horizontalScrollingKey) || false; this._tree = this._register(TreeCreationUtils.createServersTree(container, this._instantiationService, this._configurationService, horizontalScrollEnabled)); - this._register(this._tree.onDidChangeSelection((event) => this.onSelected(event))); + this._register(this._tree.onDidChangeSelection((event: ISelectionEvent | ITreeEvent) => this.onSelected(event))); this._register(this._tree.onDidBlur(() => this._onSelectionOrFocusChange.fire())); this._register(this._tree.onDidChangeFocus(() => this._onSelectionOrFocusChange.fire())); if (this._tree instanceof AsyncServerTree) { this._register(this._tree.onContextMenu(e => this.onContextMenu(e))); this._register(this._tree.onMouseDblClick(e => { // Open dashboard on double click for server and database nodes - let connectionProfile: ConnectionProfile; + let connectionProfile: ConnectionProfile | undefined; if (e.element instanceof ConnectionProfile) { connectionProfile = e.element; } else if (e.element instanceof TreeNode) { @@ -212,16 +211,16 @@ export class ServerTreeView extends Disposable implements IServerTreeView { return new Promise(async (resolve, reject) => { await this.refreshTree(); - const root = this._tree.getInput(); + const root = this._tree!.getInput(); - const expandGroups: boolean = this._configurationService.getValue(SERVER_GROUP_CONFIG)[SERVER_GROUP_AUTOEXPAND_CONFIG]; + const expandGroups = this._configurationService.getValue<{ autoExpand: boolean }>(SERVER_GROUP_CONFIG).autoExpand; if (expandGroups) { if (this._tree instanceof AsyncServerTree) { await Promise.all(ConnectionProfileGroup.getSubgroups(root).map(subgroup => { - return this._tree.expand(subgroup); + return this._tree!.expand(subgroup); })); } else { - await this._tree.expandAll(ConnectionProfileGroup.getSubgroups(root)); + await this._tree!.expandAll(ConnectionProfileGroup.getSubgroups(root)); } } @@ -238,7 +237,7 @@ export class ServerTreeView extends Disposable implements IServerTreeView { public isObjectExplorerConnectionUri(uri: string): boolean { let isBackupRestoreUri: boolean = uri.indexOf(ConnectionUtils.ConnectionUriBackupIdAttributeName) >= 0 || uri.indexOf(ConnectionUtils.ConnectionUriRestoreIdAttributeName) >= 0; - return uri && startsWith(uri, ConnectionUtils.uriPrefixes.default) && !isBackupRestoreUri; + return !!uri && uri.startsWith(ConnectionUtils.uriPrefixes.default) && !isBackupRestoreUri; } private async handleAddConnectionProfile(newProfile?: IConnectionProfile): Promise { @@ -277,16 +276,16 @@ export class ServerTreeView extends Disposable implements IServerTreeView { } } - const currentSelections = this._tree.getSelection(); + const currentSelections = this._tree!.getSelection(); const currentSelectedElement = currentSelections && currentSelections.length >= 1 ? currentSelections[0] : undefined; const newProfileIsSelected = currentSelectedElement && newProfile ? currentSelectedElement.id === newProfile.id : false; if (newProfile && currentSelectedElement && !newProfileIsSelected) { - this._tree.clearSelection(); + this._tree!.clearSelection(); } await this.refreshTree(); if (newProfile && !newProfileIsSelected) { - await this._tree.reveal(newProfile); - this._tree.select(newProfile); + await this._tree!.reveal(newProfile); + this._tree!.select(newProfile); } } @@ -304,11 +303,11 @@ export class ServerTreeView extends Disposable implements IServerTreeView { */ private getConnectionInTreeInput(connectionId: string): ConnectionProfile | undefined { if (this._tree instanceof AsyncServerTree) { - const root = this._tree.getInput(); + const root = this._tree.getInput()!; const connections = ConnectionProfileGroup.getConnectionsInGroup(root); return connections.find(conn => conn.id === connectionId); } else { - const root = TreeUpdateUtils.getTreeInput(this._connectionManagementService); + const root = TreeUpdateUtils.getTreeInput(this._connectionManagementService)!; const connections = ConnectionProfileGroup.getConnectionsInGroup(root); const results = connections.filter(con => { if (connectionId === con.id) { @@ -330,16 +329,16 @@ export class ServerTreeView extends Disposable implements IServerTreeView { if (this._tree instanceof AsyncServerTree) { this._tree.rerender(element); } else { - await this._tree.refresh(element); + await this._tree!.refresh(element); } - await this._tree.expand(element); - await this._tree.reveal(element, 0.5); + await this._tree!.expand(element); + await this._tree!.reveal(element, 0.5); this._treeSelectionHandler.onTreeActionStateChange(false); } } public addObjectExplorerNodeAndRefreshTree(connection: IConnectionProfile): void { - hide(this.messages); + hide(this.messages!); if (!this._objectExplorerService.getObjectExplorerNode(connection)) { this._objectExplorerService.updateObjectExplorerNodes(connection).catch(e => errors.onUnexpectedError(e)); } @@ -356,35 +355,35 @@ export class ServerTreeView extends Disposable implements IServerTreeView { this._tree.collapse(conn); await this.refreshTree(); } else { - await this._tree.collapse(conn); - return this._tree.refresh(conn); + await this._tree!.collapse(conn); + return this._tree!.refresh(conn); } } } } public async refreshTree(): Promise { - hide(this.messages); + hide(this.messages!); this.clearOtherActions(); - return TreeUpdateUtils.registeredServerUpdate(this._tree, this._connectionManagementService); + return TreeUpdateUtils.registeredServerUpdate(this._tree!, this._connectionManagementService); } public async refreshElement(element: ServerTreeElement): Promise { if (this._tree instanceof AsyncServerTree) { return this._tree.updateChildren(element); } else { - return this._tree.refresh(element); + return this._tree!.refresh(element); } } /** * Filter connections based on view (recent/active) */ - private filterConnections(treeInput: ConnectionProfileGroup[], view: string): ConnectionProfileGroup[] { + private filterConnections(treeInput: ConnectionProfileGroup[] | undefined, view: string): ConnectionProfileGroup[] | undefined { if (!treeInput || treeInput.length === 0) { return undefined; } - const result = treeInput.map(group => { + const result = coalesce(treeInput.map(group => { // Keep active/recent connections and remove the rest if (group.connections) { group.connections = group.connections.filter(con => { @@ -408,7 +407,7 @@ export class ServerTreeView extends Disposable implements IServerTreeView { return group; } return undefined; - }); + })); return result; } @@ -416,35 +415,35 @@ export class ServerTreeView extends Disposable implements IServerTreeView { * Set tree elements based on the view (recent/active) */ public showFilteredTree(view: string): void { - hide(this.messages); + hide(this.messages!); // Clear other action views if user switched between two views this.clearOtherActions(view); const root = TreeUpdateUtils.getTreeInput(this._connectionManagementService); - let treeInput: ConnectionProfileGroup = null; + let treeInput: ConnectionProfileGroup | undefined = undefined; if (root) { // Filter results based on view const filteredResults = this.filterConnections([root], view); if (!filteredResults || !filteredResults[0]) { - show(this.messages); - this.messages.focus(); + show(this.messages!); + this.messages!.focus(); } else { treeInput = filteredResults[0]; } - this._tree.setInput(treeInput).then(async () => { - if (isHidden(this.messages)) { - this._tree.getFocus(); + this._tree!.setInput(treeInput!).then(async () => { + if (isHidden(this.messages!)) { + this._tree!.getFocus(); if (this._tree instanceof AsyncServerTree) { - await Promise.all(ConnectionProfileGroup.getSubgroups(treeInput).map(subgroup => { - this._tree.expand(subgroup); + await Promise.all(ConnectionProfileGroup.getSubgroups(treeInput!).map(subgroup => { + this._tree!.expand(subgroup); })); } else { - await this._tree.expandAll(ConnectionProfileGroup.getSubgroups(treeInput)); + await this._tree!.expandAll(ConnectionProfileGroup.getSubgroups(treeInput!)); } } else { if (this._tree instanceof AsyncServerTree) { this._tree.setFocus([]); } else { - this._tree.clearFocus(); + this._tree!.clearFocus(); } } }, errors.onUnexpectedError); @@ -460,33 +459,33 @@ export class ServerTreeView extends Disposable implements IServerTreeView { if (!searchString) { return; } - hide(this.messages); + hide(this.messages!); // Clear other actions if user searched during other views this.clearOtherActions(); // Filter connections based on search const filteredResults = this.searchConnections(searchString); if (!filteredResults || filteredResults.length === 0) { - show(this.messages); - this.messages.focus(); + show(this.messages!); + this.messages!.focus(); } // Add all connections to tree root and set tree input const treeInput = new ConnectionProfileGroup('searchroot', undefined, 'searchroot', undefined, undefined); treeInput.addConnections(filteredResults); - this._tree.setInput(treeInput).then(async () => { - if (isHidden(this.messages)) { - this._tree.getFocus(); + this._tree!.setInput(treeInput).then(async () => { + if (isHidden(this.messages!)) { + this._tree!.getFocus(); if (this._tree instanceof AsyncServerTree) { await Promise.all(ConnectionProfileGroup.getSubgroups(treeInput).map(subgroup => { - this._tree.expand(subgroup); + this._tree!.expand(subgroup); })); } else { - await this._tree.expandAll(ConnectionProfileGroup.getSubgroups(treeInput)); + await this._tree!.expandAll(ConnectionProfileGroup.getSubgroups(treeInput)); } } else { if (this._tree instanceof AsyncServerTree) { this._tree.setFocus([]); } else { - this._tree.clearFocus(); + this._tree!.clearFocus(); } } }, errors.onUnexpectedError); @@ -497,7 +496,7 @@ export class ServerTreeView extends Disposable implements IServerTreeView { */ private searchConnections(searchString: string): ConnectionProfile[] { - const root = TreeUpdateUtils.getTreeInput(this._connectionManagementService); + const root = TreeUpdateUtils.getTreeInput(this._connectionManagementService)!; const connections = ConnectionProfileGroup.getConnectionsInGroup(root); const results = connections.filter(con => { if (searchString && (searchString.length > 0)) { @@ -542,7 +541,7 @@ export class ServerTreeView extends Disposable implements IServerTreeView { } private onSelected(event: any): void { - this._treeSelectionHandler.onTreeSelect(event, this._tree, this._connectionManagementService, this._objectExplorerService, () => this._onSelectionOrFocusChange.fire()); + this._treeSelectionHandler.onTreeSelect(event, this._tree!, this._connectionManagementService, this._objectExplorerService, () => this._onSelectionOrFocusChange.fire()); this._onSelectionOrFocusChange.fire(); } @@ -550,21 +549,21 @@ export class ServerTreeView extends Disposable implements IServerTreeView { * set the layout of the view */ public layout(height: number): void { - this._tree.layout(height); + this._tree!.layout(height); } /** * Get the list of selected nodes in the tree */ public getSelection(): any[] { - return this._tree.getSelection(); + return this._tree!.getSelection(); } /** * Get whether the tree view currently has focus */ public isFocused(): boolean { - return this._tree.getHTMLElement() === document.activeElement; + return this._tree!.getHTMLElement() === document.activeElement; } /** @@ -572,9 +571,9 @@ export class ServerTreeView extends Disposable implements IServerTreeView { */ public async setExpandedState(element: ServerTreeElement, expandedState?: TreeItemCollapsibleState): Promise { if (expandedState === TreeItemCollapsibleState.Collapsed) { - return this._tree.collapse(element); + return this._tree!.collapse(element); } else if (expandedState === TreeItemCollapsibleState.Expanded) { - return this._tree.expand(element); + return this._tree!.expand(element); } } @@ -582,7 +581,7 @@ export class ServerTreeView extends Disposable implements IServerTreeView { * Reveal the given element in the tree */ public async reveal(element: ServerTreeElement): Promise { - return this._tree.reveal(element); + return this._tree!.reveal(element); } /** @@ -593,7 +592,7 @@ export class ServerTreeView extends Disposable implements IServerTreeView { if (this._tree instanceof AsyncServerTree) { this._tree.setSelection([]); } else { - this._tree.clearSelection(); + this._tree!.clearSelection(); } } @@ -602,14 +601,14 @@ export class ServerTreeView extends Disposable implements IServerTreeView { this._tree.setSelection(this._tree.getSelection().concat(element)); this._tree.reveal(element); } else { - this._tree.select(element); - return this._tree.reveal(element); + this._tree!.select(element); + return this._tree!.reveal(element); } } else { if (this._tree instanceof AsyncServerTree) { this._tree.setSelection(this._tree.getSelection().filter(item => item !== element)); } else { - this._tree.deselect(element); + this._tree!.deselect(element); } } } @@ -621,7 +620,7 @@ export class ServerTreeView extends Disposable implements IServerTreeView { if (this._tree instanceof AsyncServerTree) { return !this._tree.getNode(element).collapsed; } else { - return this._tree.isExpanded(element); + return this._tree!.isExpanded(element); } } @@ -630,42 +629,45 @@ export class ServerTreeView extends Disposable implements IServerTreeView { * Return actions in the context menu */ private onContextMenu(e: ITreeContextMenuEvent): boolean { - e.browserEvent.preventDefault(); - e.browserEvent.stopPropagation(); - this._tree.setSelection([e.element]); + if (e.element) { + e.browserEvent.preventDefault(); + e.browserEvent.stopPropagation(); + this._tree!.setSelection([e.element]); - let actionContext: any; - if (e.element instanceof TreeNode) { - let context = new ObjectExplorerActionsContext(); - context.nodeInfo = e.element.toNodeInfo(); - // Note: getting DB name before, but intentionally not using treeUpdateUtils.getConnectionProfile as it replaces - // the connection ID with a new one. This breaks a number of internal tasks - context.connectionProfile = e.element.getConnectionProfile().toIConnectionProfile(); - context.connectionProfile.databaseName = e.element.getDatabaseName(); - actionContext = context; - } else if (e.element instanceof ConnectionProfile) { - let context = new ObjectExplorerActionsContext(); - context.connectionProfile = e.element.toIConnectionProfile(); - context.isConnectionNode = true; - actionContext = context; - } else { - // TODO: because the connection group is used as a context object and isn't serializable, - // the Group-level context menu is not currently extensible - actionContext = e.element; + let actionContext: any; + if (e.element instanceof TreeNode) { + let context = new ObjectExplorerActionsContext(); + context.nodeInfo = e.element.toNodeInfo(); + // Note: getting DB name before, but intentionally not using treeUpdateUtils.getConnectionProfile as it replaces + // the connection ID with a new one. This breaks a number of internal tasks + context.connectionProfile = e.element.getConnectionProfile()!.toIConnectionProfile(); + context.connectionProfile.databaseName = e.element.getDatabaseName(); + actionContext = context; + } else if (e.element instanceof ConnectionProfile) { + let context = new ObjectExplorerActionsContext(); + context.connectionProfile = e.element.toIConnectionProfile(); + context.isConnectionNode = true; + actionContext = context; + } else { + // TODO: because the connection group is used as a context object and isn't serializable, + // the Group-level context menu is not currently extensible + actionContext = e.element; + } + + this._contextMenuService.showContextMenu({ + getAnchor: () => e.anchor, + getActions: () => this._actionProvider.getActions(this._tree!, e.element!), + getKeyBinding: (action) => this._keybindingService.lookupKeybinding(action.id), + onHide: (wasCancelled?: boolean) => { + if (wasCancelled) { + this._tree!.domFocus(); + } + }, + getActionsContext: () => (actionContext) + }); + + return true; } - - this._contextMenuService.showContextMenu({ - getAnchor: () => e.anchor, - getActions: () => this._actionProvider.getActions(this._tree, e.element), - getKeyBinding: (action) => this._keybindingService.lookupKeybinding(action.id), - onHide: (wasCancelled?: boolean) => { - if (wasCancelled) { - this._tree.domFocus(); - } - }, - getActionsContext: () => (actionContext) - }); - - return true; + return false; } } diff --git a/src/sql/workbench/contrib/scripting/browser/scriptingActions.ts b/src/sql/workbench/contrib/scripting/browser/scriptingActions.ts index 685d416bff..1fae6c91f7 100644 --- a/src/sql/workbench/contrib/scripting/browser/scriptingActions.ts +++ b/src/sql/workbench/contrib/scripting/browser/scriptingActions.ts @@ -40,130 +40,148 @@ export const EDIT_DATA_COMMAND_ID = 'dataExplorer.scriptAsEdit'; // Script as Create CommandsRegistry.registerCommand({ id: SCRIPT_AS_CREATE_COMMAND_ID, - handler: async (accessor, args: TreeViewItemHandleArg) => { - const capabilitiesService = accessor.get(ICapabilitiesService); - const oeShimService = accessor.get(IOEShimService); - const queryEditorService = accessor.get(IQueryEditorService); - const connectionManagementService = accessor.get(IConnectionManagementService); - const scriptingService = accessor.get(IScriptingService); - const errorMessageService = accessor.get(IErrorMessageService); - const progressService = accessor.get(IProgressService); - const profile = new ConnectionProfile(capabilitiesService, args.$treeItem.payload); - const baseContext: BaseActionContext = { - profile: profile, - object: oeShimService.getNodeInfoForTreeItem(args.$treeItem).metadata - }; - const scriptCreateAction = new ScriptCreateAction(ScriptCreateAction.ID, ScriptCreateAction.LABEL, - queryEditorService, connectionManagementService, scriptingService, errorMessageService); - return progressService.withProgress({ location: VIEWLET_ID }, () => scriptCreateAction.run(baseContext)); + handler: async (accessor, args: TreeViewItemHandleArg): Promise => { + if (args.$treeItem?.payload) { + const capabilitiesService = accessor.get(ICapabilitiesService); + const oeShimService = accessor.get(IOEShimService); + const queryEditorService = accessor.get(IQueryEditorService); + const connectionManagementService = accessor.get(IConnectionManagementService); + const scriptingService = accessor.get(IScriptingService); + const errorMessageService = accessor.get(IErrorMessageService); + const progressService = accessor.get(IProgressService); + const profile = new ConnectionProfile(capabilitiesService, args.$treeItem.payload); + const baseContext: BaseActionContext = { + profile: profile, + object: oeShimService.getNodeInfoForTreeItem(args.$treeItem)!.metadata + }; + const scriptCreateAction = new ScriptCreateAction(ScriptCreateAction.ID, ScriptCreateAction.LABEL, + queryEditorService, connectionManagementService, scriptingService, errorMessageService); + return progressService.withProgress({ location: VIEWLET_ID }, () => scriptCreateAction.run(baseContext)); + } + return undefined; } }); // Script as Delete CommandsRegistry.registerCommand({ id: SCRIPT_AS_DELETE_COMMAND_ID, - handler: async (accessor, args: TreeViewItemHandleArg) => { - const capabilitiesService = accessor.get(ICapabilitiesService); - const oeShimService = accessor.get(IOEShimService); - const queryEditorService = accessor.get(IQueryEditorService); - const connectionManagementService = accessor.get(IConnectionManagementService); - const scriptingService = accessor.get(IScriptingService); - const errorMessageService = accessor.get(IErrorMessageService); - const progressService = accessor.get(IProgressService); - const profile = new ConnectionProfile(capabilitiesService, args.$treeItem.payload); - const baseContext: BaseActionContext = { - profile: profile, - object: oeShimService.getNodeInfoForTreeItem(args.$treeItem).metadata - }; - const scriptDeleteAction = new ScriptDeleteAction(ScriptDeleteAction.ID, ScriptDeleteAction.LABEL, - queryEditorService, connectionManagementService, scriptingService, errorMessageService); - return progressService.withProgress({ location: VIEWLET_ID }, () => scriptDeleteAction.run(baseContext)); + handler: async (accessor, args: TreeViewItemHandleArg): Promise => { + if (args.$treeItem?.payload) { + const capabilitiesService = accessor.get(ICapabilitiesService); + const oeShimService = accessor.get(IOEShimService); + const queryEditorService = accessor.get(IQueryEditorService); + const connectionManagementService = accessor.get(IConnectionManagementService); + const scriptingService = accessor.get(IScriptingService); + const errorMessageService = accessor.get(IErrorMessageService); + const progressService = accessor.get(IProgressService); + const profile = new ConnectionProfile(capabilitiesService, args.$treeItem.payload); + const baseContext: BaseActionContext = { + profile: profile, + object: oeShimService.getNodeInfoForTreeItem(args.$treeItem)!.metadata + }; + const scriptDeleteAction = new ScriptDeleteAction(ScriptDeleteAction.ID, ScriptDeleteAction.LABEL, + queryEditorService, connectionManagementService, scriptingService, errorMessageService); + return progressService.withProgress({ location: VIEWLET_ID }, () => scriptDeleteAction.run(baseContext)); + } + return undefined; } }); // Script as Select CommandsRegistry.registerCommand({ id: SCRIPT_AS_SELECT_COMMAND_ID, - handler: async (accessor, args: TreeViewItemHandleArg) => { - const capabilitiesService = accessor.get(ICapabilitiesService); - const oeShimService = accessor.get(IOEShimService); - const queryEditorService = accessor.get(IQueryEditorService); - const connectionManagementService = accessor.get(IConnectionManagementService); - const scriptingService = accessor.get(IScriptingService); - const progressService = accessor.get(IProgressService); - const profile = new ConnectionProfile(capabilitiesService, args.$treeItem.payload); - const baseContext: BaseActionContext = { - profile: profile, - object: oeShimService.getNodeInfoForTreeItem(args.$treeItem).metadata - }; - const scriptSelectAction = new ScriptSelectAction(ScriptSelectAction.ID, ScriptSelectAction.LABEL, - queryEditorService, connectionManagementService, scriptingService); - return progressService.withProgress({ location: VIEWLET_ID }, () => scriptSelectAction.run(baseContext)); + handler: async (accessor, args: TreeViewItemHandleArg): Promise => { + if (args.$treeItem?.payload) { + const capabilitiesService = accessor.get(ICapabilitiesService); + const oeShimService = accessor.get(IOEShimService); + const queryEditorService = accessor.get(IQueryEditorService); + const connectionManagementService = accessor.get(IConnectionManagementService); + const scriptingService = accessor.get(IScriptingService); + const progressService = accessor.get(IProgressService); + const profile = new ConnectionProfile(capabilitiesService, args.$treeItem.payload); + const baseContext: BaseActionContext = { + profile: profile, + object: oeShimService.getNodeInfoForTreeItem(args.$treeItem)!.metadata + }; + const scriptSelectAction = new ScriptSelectAction(ScriptSelectAction.ID, ScriptSelectAction.LABEL, + queryEditorService, connectionManagementService, scriptingService); + return progressService.withProgress({ location: VIEWLET_ID }, () => scriptSelectAction.run(baseContext)); + } + return undefined; } }); // Script as Execute CommandsRegistry.registerCommand({ id: SCRIPT_AS_EXECUTE_COMMAND_ID, - handler: async (accessor, args: TreeViewItemHandleArg) => { - const capabilitiesService = accessor.get(ICapabilitiesService); - const oeShimService = accessor.get(IOEShimService); - const queryEditorService = accessor.get(IQueryEditorService); - const connectionManagementService = accessor.get(IConnectionManagementService); - const scriptingService = accessor.get(IScriptingService); - const progressService = accessor.get(IProgressService); - const errorMessageService = accessor.get(IErrorMessageService); - const profile = new ConnectionProfile(capabilitiesService, args.$treeItem.payload); - const baseContext: BaseActionContext = { - profile: profile, - object: oeShimService.getNodeInfoForTreeItem(args.$treeItem).metadata - }; - const scriptExecuteAction = new ScriptExecuteAction(ScriptExecuteAction.ID, ScriptExecuteAction.LABEL, - queryEditorService, connectionManagementService, scriptingService, errorMessageService); - return progressService.withProgress({ location: VIEWLET_ID }, () => scriptExecuteAction.run(baseContext)); + handler: async (accessor, args: TreeViewItemHandleArg): Promise => { + if (args.$treeItem?.payload) { + const capabilitiesService = accessor.get(ICapabilitiesService); + const oeShimService = accessor.get(IOEShimService); + const queryEditorService = accessor.get(IQueryEditorService); + const connectionManagementService = accessor.get(IConnectionManagementService); + const scriptingService = accessor.get(IScriptingService); + const progressService = accessor.get(IProgressService); + const errorMessageService = accessor.get(IErrorMessageService); + const profile = new ConnectionProfile(capabilitiesService, args.$treeItem.payload); + const baseContext: BaseActionContext = { + profile: profile, + object: oeShimService.getNodeInfoForTreeItem(args.$treeItem)!.metadata + }; + const scriptExecuteAction = new ScriptExecuteAction(ScriptExecuteAction.ID, ScriptExecuteAction.LABEL, + queryEditorService, connectionManagementService, scriptingService, errorMessageService); + return progressService.withProgress({ location: VIEWLET_ID }, () => scriptExecuteAction.run(baseContext)); + } + return undefined; } }); // Script as Alter CommandsRegistry.registerCommand({ id: SCRIPT_AS_ALTER_COMMAND_ID, - handler: async (accessor, args: TreeViewItemHandleArg) => { - const capabilitiesService = accessor.get(ICapabilitiesService); - const oeShimService = accessor.get(IOEShimService); - const queryEditorService = accessor.get(IQueryEditorService); - const connectionManagementService = accessor.get(IConnectionManagementService); - const scriptingService = accessor.get(IScriptingService); - const progressService = accessor.get(IProgressService); - const errorMessageService = accessor.get(IErrorMessageService); - const profile = new ConnectionProfile(capabilitiesService, args.$treeItem.payload); - const baseContext: BaseActionContext = { - profile: profile, - object: oeShimService.getNodeInfoForTreeItem(args.$treeItem).metadata - }; - const scriptAlterAction = new ScriptAlterAction(ScriptAlterAction.ID, ScriptAlterAction.LABEL, - queryEditorService, connectionManagementService, scriptingService, errorMessageService); - return progressService.withProgress({ location: VIEWLET_ID }, () => scriptAlterAction.run(baseContext)); + handler: async (accessor, args: TreeViewItemHandleArg): Promise => { + if (args.$treeItem?.payload) { + const capabilitiesService = accessor.get(ICapabilitiesService); + const oeShimService = accessor.get(IOEShimService); + const queryEditorService = accessor.get(IQueryEditorService); + const connectionManagementService = accessor.get(IConnectionManagementService); + const scriptingService = accessor.get(IScriptingService); + const progressService = accessor.get(IProgressService); + const errorMessageService = accessor.get(IErrorMessageService); + const profile = new ConnectionProfile(capabilitiesService, args.$treeItem.payload); + const baseContext: BaseActionContext = { + profile: profile, + object: oeShimService.getNodeInfoForTreeItem(args.$treeItem)!.metadata + }; + const scriptAlterAction = new ScriptAlterAction(ScriptAlterAction.ID, ScriptAlterAction.LABEL, + queryEditorService, connectionManagementService, scriptingService, errorMessageService); + return progressService.withProgress({ location: VIEWLET_ID }, () => scriptAlterAction.run(baseContext)); + } + return undefined; } }); // Edit Data CommandsRegistry.registerCommand({ id: EDIT_DATA_COMMAND_ID, - handler: async (accessor, args: TreeViewItemHandleArg) => { - const capabilitiesService = accessor.get(ICapabilitiesService); - const oeShimService = accessor.get(IOEShimService); - const queryEditorService = accessor.get(IQueryEditorService); - const connectionManagementService = accessor.get(IConnectionManagementService); - const scriptingService = accessor.get(IScriptingService); - const progressService = accessor.get(IProgressService); - const profile = new ConnectionProfile(capabilitiesService, args.$treeItem.payload); - const baseContext: BaseActionContext = { - profile: profile, - object: oeShimService.getNodeInfoForTreeItem(args.$treeItem).metadata - }; - const editDataAction = new EditDataAction(EditDataAction.ID, EditDataAction.LABEL, - queryEditorService, connectionManagementService, scriptingService); - return progressService.withProgress({ location: VIEWLET_ID }, () => editDataAction.run(baseContext)); + handler: async (accessor, args: TreeViewItemHandleArg): Promise => { + if (args.$treeItem?.payload) { + const capabilitiesService = accessor.get(ICapabilitiesService); + const oeShimService = accessor.get(IOEShimService); + const queryEditorService = accessor.get(IQueryEditorService); + const connectionManagementService = accessor.get(IConnectionManagementService); + const scriptingService = accessor.get(IScriptingService); + const progressService = accessor.get(IProgressService); + const profile = new ConnectionProfile(capabilitiesService, args.$treeItem.payload); + const baseContext: BaseActionContext = { + profile: profile, + object: oeShimService.getNodeInfoForTreeItem(args.$treeItem)!.metadata + }; + const editDataAction = new EditDataAction(EditDataAction.ID, EditDataAction.LABEL, + queryEditorService, connectionManagementService, scriptingService); + return progressService.withProgress({ location: VIEWLET_ID }, () => editDataAction.run(baseContext)); + } + return undefined; } }); //#endregion @@ -186,9 +204,9 @@ CommandsRegistry.registerCommand({ const connectionManagementService = accessor.get(IConnectionManagementService); const objectExplorerService = accessor.get(IObjectExplorerService); const selectionHandler = instantiationService.createInstance(TreeSelectionHandler); - const node = await getTreeNode(args, objectExplorerService); + const node = (await getTreeNode(args, objectExplorerService))!; selectionHandler.onTreeActionStateChange(true); - let connectionProfile = TreeUpdateUtils.getConnectionProfile(node); + let connectionProfile = TreeUpdateUtils.getConnectionProfile(node)!; let ownerUri = connectionManagementService.getConnectionUri(connectionProfile); ownerUri = connectionManagementService.getFormattedUri(ownerUri, connectionProfile); let metadata = node.metadata; @@ -207,7 +225,7 @@ CommandsRegistry.registerCommand({ const instantiationService = accessor.get(IInstantiationService); const objectExplorerService = accessor.get(IObjectExplorerService); const selectionHandler = instantiationService.createInstance(TreeSelectionHandler); - const node = await getTreeNode(args, objectExplorerService); + const node = (await getTreeNode(args, objectExplorerService))!; selectionHandler.onTreeActionStateChange(true); let connectionProfile = TreeUpdateUtils.getConnectionProfile(node); let metadata = node.metadata; @@ -227,9 +245,9 @@ CommandsRegistry.registerCommand({ const connectionManagementService = accessor.get(IConnectionManagementService); const objectExplorerService = accessor.get(IObjectExplorerService); const selectionHandler = instantiationService.createInstance(TreeSelectionHandler); - const node = await getTreeNode(args, objectExplorerService); + const node = (await getTreeNode(args, objectExplorerService))!; selectionHandler.onTreeActionStateChange(true); - let connectionProfile = TreeUpdateUtils.getConnectionProfile(node); + let connectionProfile = TreeUpdateUtils.getConnectionProfile(node)!; let metadata = node.metadata; let ownerUri = connectionManagementService.getConnectionUri(connectionProfile); ownerUri = connectionManagementService.getFormattedUri(ownerUri, connectionProfile); @@ -249,9 +267,9 @@ CommandsRegistry.registerCommand({ const connectionManagementService = accessor.get(IConnectionManagementService); const objectExplorerService = accessor.get(IObjectExplorerService); const selectionHandler = instantiationService.createInstance(TreeSelectionHandler); - const node = await getTreeNode(args, objectExplorerService); + const node = (await getTreeNode(args, objectExplorerService))!; selectionHandler.onTreeActionStateChange(true); - let connectionProfile = TreeUpdateUtils.getConnectionProfile(node); + let connectionProfile = TreeUpdateUtils.getConnectionProfile(node)!; let metadata = node.metadata; let ownerUri = connectionManagementService.getConnectionUri(connectionProfile); ownerUri = connectionManagementService.getFormattedUri(ownerUri, connectionProfile); @@ -271,9 +289,9 @@ CommandsRegistry.registerCommand({ const connectionManagementService = accessor.get(IConnectionManagementService); const objectExplorerService = accessor.get(IObjectExplorerService); const selectionHandler = instantiationService.createInstance(TreeSelectionHandler); - const node = await getTreeNode(args, objectExplorerService); + const node = (await getTreeNode(args, objectExplorerService))!; selectionHandler.onTreeActionStateChange(true); - let connectionProfile = TreeUpdateUtils.getConnectionProfile(node); + let connectionProfile = TreeUpdateUtils.getConnectionProfile(node)!; let metadata = node.metadata; let ownerUri = connectionManagementService.getConnectionUri(connectionProfile); ownerUri = connectionManagementService.getFormattedUri(ownerUri, connectionProfile); @@ -297,8 +315,8 @@ CommandsRegistry.registerCommand({ //set objectExplorerTreeNode for context menu clicks const node = await getTreeNode(args, objectExplorerService); selectionHandler.onTreeActionStateChange(true); - const connectionProfile = TreeUpdateUtils.getConnectionProfile(node); - const metadata = node.metadata; + const connectionProfile = TreeUpdateUtils.getConnectionProfile(node)!; + const metadata = node!.metadata; let ownerUri = connectionManagementService.getConnectionUri(connectionProfile); ownerUri = connectionManagementService.getFormattedUri(ownerUri, connectionProfile); @@ -320,9 +338,9 @@ export async function handleOeRefreshCommand(accessor: ServicesAccessor, args: O const logService = accessor.get(ILogService); const notificationService = accessor.get(INotificationService); const treeNode = await getTreeNode(args, objectExplorerService); - const tree = objectExplorerService.getServerTreeView().tree; + const tree = objectExplorerService.getServerTreeView()!.tree; try { - await objectExplorerService.refreshTreeNode(treeNode.getSession(), treeNode); + await objectExplorerService.refreshTreeNode(treeNode!.getSession()!, treeNode!); if (tree instanceof AsyncServerTree) { await tree.updateChildren(treeNode); } else { @@ -330,7 +348,7 @@ export async function handleOeRefreshCommand(accessor: ServicesAccessor, args: O } } catch (err) { // Display message to the user but also log the entire error to the console for the stack trace - notificationService.error(localize('refreshError', "An error occurred refreshing node '{0}': {1}", args.nodeInfo.label, getErrorMessage(err))); + notificationService.error(localize('refreshError', "An error occurred refreshing node '{0}': {1}", args.nodeInfo?.label, getErrorMessage(err))); logService.error(err); } } diff --git a/src/sql/workbench/contrib/scripting/test/browser/scriptingActions.test.ts b/src/sql/workbench/contrib/scripting/test/browser/scriptingActions.test.ts index 0f3a7e9370..5533627ee0 100644 --- a/src/sql/workbench/contrib/scripting/test/browser/scriptingActions.test.ts +++ b/src/sql/workbench/contrib/scripting/test/browser/scriptingActions.test.ts @@ -20,7 +20,6 @@ import { NodeType } from 'sql/workbench/services/objectExplorer/common/nodeType' import { ServerTreeView } from 'sql/workbench/contrib/objectExplorer/browser/serverTreeView'; import { createObjectExplorerServiceMock } from 'sql/workbench/services/objectExplorer/test/browser/testObjectExplorerService'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; -import { ITree } from 'vs/base/parts/tree/browser/tree'; import { TestTree } from 'sql/workbench/test/treeMock'; import { TestConnectionManagementService } from 'sql/platform/connection/test/common/testConnectionManagementService'; @@ -56,7 +55,7 @@ const oeActionArgs: ObjectExplorerActionsContext = { connectionProfile: connecti let instantiationService: IInstantiationService; let logServiceMock: TypeMoq.Mock; -let treeMock: TypeMoq.Mock; +let treeMock: TypeMoq.Mock; suite('Scripting Actions', () => { @@ -68,7 +67,7 @@ suite('Scripting Actions', () => { const serverTreeViewMock = TypeMoq.Mock.ofType(ServerTreeView, TypeMoq.MockBehavior.Loose, connectionManagementServiceMock.object, instantiationService, undefined, undefined, undefined, undefined, capabilitiesService); treeMock = TypeMoq.Mock.ofType(TestTree); serverTreeViewMock.setup(x => x.tree).returns(() => treeMock.object); - collection.set(IObjectExplorerService, createObjectExplorerServiceMock({ serverTreeView: serverTreeViewMock.object, treeNode: treeNode }).object); + collection.set(IObjectExplorerService, createObjectExplorerServiceMock({ serverTreeView: serverTreeViewMock.object, treeNode: treeNode })); logServiceMock = TypeMoq.Mock.ofInstance(new NullLogService()); collection.set(ILogService, logServiceMock.object); collection.set(INotificationService, new TestNotificationService()); diff --git a/src/sql/workbench/services/connection/common/connectionContextKey.ts b/src/sql/workbench/services/connection/common/connectionContextKey.ts index 4f950941ec..5af65d0915 100644 --- a/src/sql/workbench/services/connection/common/connectionContextKey.ts +++ b/src/sql/workbench/services/connection/common/connectionContextKey.ts @@ -18,7 +18,7 @@ export class ConnectionContextKey implements IContextKey { private _providerKey: IContextKey; private _serverKey: IContextKey; - private _databaseKey: IContextKey; + private _databaseKey: IContextKey; private _connectionKey: IContextKey; private _isQueryProviderKey: IContextKey; private _canOpenInAzurePortal: IContextKey; diff --git a/src/sql/workbench/services/objectExplorer/browser/asyncServerTreeDataSource.ts b/src/sql/workbench/services/objectExplorer/browser/asyncServerTreeDataSource.ts index 5cd182cd11..51d0977705 100644 --- a/src/sql/workbench/services/objectExplorer/browser/asyncServerTreeDataSource.ts +++ b/src/sql/workbench/services/objectExplorer/browser/asyncServerTreeDataSource.ts @@ -52,7 +52,7 @@ export class AsyncServerTreeDataSource implements IAsyncDataSourceoriginalEvent); + return this._dragAndDrop.onDragStart(this._tree!, dragAndDropData, originalEvent); } - public onDragOver(data: IDragAndDropData, targetElement: ServerTreeElement, targetIndex: number, originalEvent: DragEvent): boolean | ITreeDragOverReaction { + public onDragOver(data: IDragAndDropData, targetElement: ServerTreeElement | undefined, targetIndex: number, originalEvent: DragEvent): boolean | ITreeDragOverReaction { // Dropping onto an empty space (undefined targetElement) we treat as wanting to move into the root connection group if (!targetElement) { targetElement = this._tree?.getInput(); } // Force the event cast while in preview - we don't use any of the mouse properties on the // implementation so this is fine for now - const canDragOver = this._dragAndDrop.onDragOver(this._tree, data, targetElement, originalEvent); + const canDragOver = this._dragAndDrop.onDragOver(this._tree!, data, targetElement, originalEvent); if (canDragOver.accept) { return TreeDragOverReactions.acceptBubbleDown(canDragOver.autoExpand); @@ -76,14 +76,14 @@ export class AsyncServerTreeDragAndDrop implements ITreeDragAndDroporiginalEvent); + this._dragAndDrop.drop(this._tree!, data, targetElement, originalEvent); } public onDragEnd(originalEvent: DragEvent): void { @@ -102,7 +102,7 @@ export class AsyncRecentConnectionsDragAndDrop implements ITreeDragAndDropelement).id; } else if (element instanceof ConnectionProfileGroup) { - return (element).id; + return (element).id ?? null; } return null; } @@ -117,7 +117,7 @@ export class AsyncRecentConnectionsDragAndDrop implements ITreeDragAndDrop { getId(element: ServerTreeElement): { toString(): string; } { - return element.id; + return element.id!; } } diff --git a/src/sql/workbench/services/objectExplorer/browser/asyncServerTreeRenderer.ts b/src/sql/workbench/services/objectExplorer/browser/asyncServerTreeRenderer.ts index d0a77d9b87..48572f7cc8 100644 --- a/src/sql/workbench/services/objectExplorer/browser/asyncServerTreeRenderer.ts +++ b/src/sql/workbench/services/objectExplorer/browser/asyncServerTreeRenderer.ts @@ -8,7 +8,7 @@ import 'vs/css!./media/objectTypes/objecttypes'; import * as dom from 'vs/base/browser/dom'; import { localize } from 'vs/nls'; import { ConnectionProfileGroup } from 'sql/platform/connection/common/connectionProfileGroup'; -import { ConnectionProfile } from 'sql/platform/connection/common/connectionProfile'; +import { ConnectionProfile, IconPath } from 'sql/platform/connection/common/connectionProfile'; import { IConnectionManagementService } from 'sql/platform/connection/common/connectionManagement'; import { TreeNode } from 'sql/workbench/services/objectExplorer/common/treeNode'; import { iconRenderer } from 'sql/workbench/services/objectExplorer/browser/iconRenderer'; @@ -22,6 +22,7 @@ import { IListAccessibilityProvider } from 'vs/base/browser/ui/list/listWidget'; import { ServerTreeRenderer } from 'sql/workbench/services/objectExplorer/browser/serverTreeRenderer'; import { ServerTreeElement } from 'sql/workbench/services/objectExplorer/browser/asyncServerTree'; import { DefaultServerGroupColor } from 'sql/workbench/services/serverGroup/common/serverGroupViewModel'; +import { withNullAsUndefined } from 'vs/base/common/types'; class ConnectionProfileGroupTemplate extends Disposable { private _root: HTMLElement; @@ -31,7 +32,7 @@ class ConnectionProfileGroupTemplate extends Disposable { container: HTMLElement ) { super(); - container.parentElement.classList.add('server-group'); + container.parentElement!.classList.add('server-group'); container.classList.add('server-group'); this._root = dom.append(container, dom.$('.server-group')); this._nameContainer = dom.append(this._root, dom.$('span.name')); @@ -89,7 +90,7 @@ class ConnectionProfileTemplate extends Disposable { @IConnectionManagementService private _connectionManagementService: IConnectionManagementService ) { super(); - container.parentElement.classList.add('connection-profile'); + container.parentElement!.classList.add('connection-profile'); this._root = dom.append(container, dom.$('.connection-tile')); this._icon = dom.append(this._root, dom.$('div.icon server-page')); this._connectionStatusBadge = dom.append(this._icon, dom.$('div.connection-status-badge')); @@ -98,16 +99,15 @@ class ConnectionProfileTemplate extends Disposable { set(element: ConnectionProfile) { if (!this._isCompact) { - let iconPath: IconPath = getIconPath(element, this._connectionManagementService); + let iconPath: IconPath | undefined = getIconPath(element, this._connectionManagementService); if (this._connectionManagementService.isConnected(undefined, element)) { this._connectionStatusBadge.classList.remove('disconnected'); this._connectionStatusBadge.classList.add('connected'); - renderServerIcon(this._icon, iconPath); } else { this._connectionStatusBadge.classList.remove('connected'); this._connectionStatusBadge.classList.add('disconnected'); - renderServerIcon(this._icon, iconPath); } + renderServerIcon(this._icon, iconPath); } let label = element.title; @@ -156,7 +156,7 @@ class TreeNodeTemplate extends Disposable { set(element: TreeNode) { // Use an explicitly defined iconType first. If not defined, fall back to using nodeType and // other compount indicators instead. - let iconName: string = undefined; + let iconName: string | undefined = undefined; if (element.iconType) { iconName = (typeof element.iconType === 'string') ? element.iconType : element.iconType.id; } else { @@ -171,7 +171,7 @@ class TreeNodeTemplate extends Disposable { let tokens: string[] = []; for (let index = 1; index < this._icon.classList.length; index++) { - tokens.push(this._icon.classList.item(index)); + tokens.push(this._icon.classList.item(index)!); } this._icon.classList.remove(...tokens); this._icon.classList.add('icon'); @@ -229,7 +229,7 @@ export class ServerTreeAccessibilityProvider implements IListAccessibilityProvid getAriaLabel(element: ServerTreeElement): string | null { if (element instanceof ConnectionProfileGroup) { - return element.fullName; + return element.fullName ?? null; } else if (element instanceof ConnectionProfile) { return element.title; } @@ -240,22 +240,22 @@ export class ServerTreeAccessibilityProvider implements IListAccessibilityProvid /** * Returns the first parent which contains the className */ -function findParentElement(container: HTMLElement, className: string): HTMLElement { - let currentElement = container; +function findParentElement(container: HTMLElement, className: string): HTMLElement | undefined { + let currentElement: HTMLElement | null = container; while (currentElement) { if (currentElement.className.indexOf(className) > -1) { break; } currentElement = currentElement.parentElement; } - return currentElement; + return withNullAsUndefined(currentElement); } -function getIconPath(connection: ConnectionProfile, connectionManagementService: IConnectionManagementService): IconPath { +function getIconPath(connection: ConnectionProfile, connectionManagementService: IConnectionManagementService): IconPath | undefined { if (!connection) { return undefined; } - if (connection['iconPath']) { - return connection['iconPath']; + if (connection.iconPath) { + return connection.iconPath; } let iconId = connectionManagementService.getConnectionIconId(connection.id); @@ -264,8 +264,8 @@ function getIconPath(connection: ConnectionProfile, connectionManagementService: let providerProperties = connectionManagementService.getProviderProperties(connection.providerName); if (!providerProperties) { return undefined; } - let iconPath: IconPath = undefined; - let pathConfig: URI | IconPath | { id: string, path: IconPath }[] = providerProperties['iconPath']; + let iconPath: IconPath | undefined = undefined; + let pathConfig: URI | IconPath | { id: string, path: IconPath }[] | undefined = providerProperties['iconPath']; if (Array.isArray(pathConfig)) { for (const e of pathConfig) { if (!e.id || e.id === iconId) { @@ -274,25 +274,18 @@ function getIconPath(connection: ConnectionProfile, connectionManagementService: break; } } - } else if (pathConfig['light']) { - iconPath = pathConfig as IconPath; - connection['iconPath'] = iconPath; + } else if (URI.isUri(pathConfig)) { + iconPath = { light: pathConfig, dark: pathConfig }; + connection.iconPath = iconPath; } else { - let singlePath = pathConfig as URI; - iconPath = { light: singlePath, dark: singlePath }; - connection['iconPath'] = iconPath; + connection.iconPath = pathConfig; } return iconPath; } -function renderServerIcon(element: HTMLElement, iconPath: IconPath): void { +function renderServerIcon(element: HTMLElement, iconPath?: IconPath): void { if (!element) { return; } if (iconPath) { iconRenderer.putIcon(element, iconPath); } } - -interface IconPath { - light: URI; - dark: URI; -} diff --git a/src/sql/workbench/services/objectExplorer/browser/dragAndDropController.ts b/src/sql/workbench/services/objectExplorer/browser/dragAndDropController.ts index 835f658fb5..519df88b31 100644 --- a/src/sql/workbench/services/objectExplorer/browser/dragAndDropController.ts +++ b/src/sql/workbench/services/objectExplorer/browser/dragAndDropController.ts @@ -28,6 +28,8 @@ export function supportsFolderNodeNameDrop(nodeId: string, label: string): boole return false; } +function escapeString(input: string): string; +function escapeString(input: undefined): undefined; function escapeString(input: string | undefined): string | undefined { return input?.replace(/]/g, ']]'); } @@ -46,22 +48,22 @@ export class ServerTreeDragAndDrop implements IDragAndDrop { * Returns a uri if the given element should be allowed to drag. * Returns null, otherwise. */ - public getDragURI(tree: AsyncServerTree | ITree, element: any): string { + public getDragURI(tree: AsyncServerTree | ITree, element: any): string | null { if (element) { if (element instanceof ConnectionProfile) { - return (element).id; + return element.id; } else if (element instanceof ConnectionProfileGroup) { - return (element).id; + return element.id ?? null; } else if (supportsNodeNameDrop(element.nodeTypeId)) { return (element).id; } else if (supportsFolderNodeNameDrop(element.nodeTypeId, element.label) && element.children) { return (element).id; } else { - return undefined; + return null; } } else { - return undefined; + return null; } } @@ -78,11 +80,11 @@ export class ServerTreeDragAndDrop implements IDragAndDrop { return elements[0].label; } else { - return undefined; + return ''; } } else { - return undefined; + return ''; } } @@ -125,7 +127,7 @@ export class ServerTreeDragAndDrop implements IDragAndDrop { return element.connection.providerName; } - return this.getProviderNameFromElement(element.parent); + return this.getProviderNameFromElement(element.parent!); } @@ -133,7 +135,7 @@ export class ServerTreeDragAndDrop implements IDragAndDrop { let canDragOver: boolean = true; if (source instanceof ConnectionProfile) { - if (!this._connectionManagementService.canChangeConnectionConfig(source, targetConnectionProfileGroup.id)) { + if (!this._connectionManagementService.canChangeConnectionConfig(source, targetConnectionProfileGroup.id!)) { canDragOver = false; } } else if (source instanceof ConnectionProfileGroup) { @@ -158,7 +160,7 @@ export class ServerTreeDragAndDrop implements IDragAndDrop { // Verify if the connection can be moved to the target group const source = data.getData()[0]; if (source instanceof ConnectionProfile) { - if (!this._connectionManagementService.canChangeConnectionConfig(source, targetConnectionProfileGroup.id)) { + if (!this._connectionManagementService.canChangeConnectionConfig(source, targetConnectionProfileGroup.id!)) { canDragOver = false; } } else if (source instanceof ConnectionProfileGroup) { @@ -201,7 +203,7 @@ export class ServerTreeDragAndDrop implements IDragAndDrop { if (source instanceof ConnectionProfile) { // Change group id of profile - this._connectionManagementService.changeGroupIdForConnection(source, targetConnectionProfileGroup.id).then(() => { + this._connectionManagementService.changeGroupIdForConnection(source, targetConnectionProfileGroup.id!).then(() => { if (tree) { TreeUpdateUtils.registeredServerUpdate(tree, self._connectionManagementService, targetConnectionProfileGroup); } @@ -224,13 +226,13 @@ export class ServerTreeDragAndDrop implements IDragAndDrop { TreeUpdateUtils.isInDragAndDrop = false; } - private getTargetGroup(targetElement: any): ConnectionProfileGroup { + private getTargetGroup(targetElement: ConnectionProfileGroup | ConnectionProfile): ConnectionProfileGroup { let targetConnectionProfileGroup: ConnectionProfileGroup; if (targetElement instanceof ConnectionProfile) { - targetConnectionProfileGroup = (targetElement).getParent(); + targetConnectionProfileGroup = targetElement.getParent()!; } else { - targetConnectionProfileGroup = targetElement; + targetConnectionProfileGroup = targetElement; } return targetConnectionProfileGroup; @@ -256,12 +258,12 @@ export class RecentConnectionsDragAndDrop implements IDragAndDrop { * Returns a uri if the given element should be allowed to drag. * Returns null, otherwise. */ - public getDragURI(tree: ITree, element: any): string { + public getDragURI(tree: ITree, element: any): string | null { if (element instanceof ConnectionProfile) { return (element).id; } else if (element instanceof ConnectionProfileGroup) { - return (element).id; + return (element).id ?? null; } return null; } @@ -276,7 +278,7 @@ export class RecentConnectionsDragAndDrop implements IDragAndDrop { else if (elements[0] instanceof ConnectionProfileGroup) { return (elements[0]).name; } - return undefined; + return ''; } /** diff --git a/src/sql/workbench/services/objectExplorer/browser/iconRenderer.ts b/src/sql/workbench/services/objectExplorer/browser/iconRenderer.ts index 7b9e5be74f..aaf96d34b4 100644 --- a/src/sql/workbench/services/objectExplorer/browser/iconRenderer.ts +++ b/src/sql/workbench/services/objectExplorer/browser/iconRenderer.ts @@ -10,11 +10,11 @@ import { URI } from 'vs/base/common/uri'; class IconRenderer { private iconRegistered: Set = new Set(); - public registerIcon(path: URI | IconPath): string { + public registerIcon(path: URI | IconPath): string | undefined { if (!path) { return undefined; } let iconPath: IconPath = this.toIconPath(path); - let iconUid: string = this.getIconUid(iconPath); - if (!this.iconRegistered.has(iconUid)) { + let iconUid: string | undefined = this.getIconUid(iconPath); + if (iconUid && !this.iconRegistered.has(iconUid)) { createCSSRule(`.icon#${iconUid}`, `background: ${asCSSUrl(iconPath.light || iconPath.dark)} center center no-repeat`); createCSSRule(`.vs-dark .icon#${iconUid}, .hc-black .icon#${iconUid}`, `background: ${asCSSUrl(iconPath.dark)} center center no-repeat`); this.iconRegistered.add(iconUid); @@ -22,30 +22,30 @@ class IconRenderer { return iconUid; } - public getIconUid(path: URI | IconPath): string { + public getIconUid(path: URI | IconPath): string | undefined { if (!path) { return undefined; } let iconPath: IconPath = this.toIconPath(path); return `icon${hash(iconPath.light.toString() + iconPath.dark.toString())}`; } private toIconPath(path: URI | IconPath): IconPath { - if (path['light']) { - return path as IconPath; - } else { - let singlePath = path as URI; + if (URI.isUri(path)) { + let singlePath = path; return { light: singlePath, dark: singlePath }; + } else { + return path; } } public putIcon(element: HTMLElement, path: URI | IconPath): void { if (!element || !path) { return undefined; } - let iconUid: string = this.registerIcon(path); - element.id = iconUid; + let iconUid: string | undefined = this.registerIcon(path); + element.id = iconUid ?? ''; } public removeIcon(element: HTMLElement): void { if (!element) { return undefined; } - element.id = undefined; + element.id = ''; } } @@ -117,9 +117,9 @@ class BadgeRenderer { public removeBadge(element: HTMLElement, badgeClass: string): void { let children: HTMLCollection = element.children; - let current = children[0]; + let current: Element | null = children[0]; while (current) { - let next = current.nextElementSibling; + let next: Element | null = current.nextElementSibling; if (current.classList.contains(badgeClass)) { current.remove(); break; diff --git a/src/sql/workbench/services/objectExplorer/browser/recentConnectionDataSource.ts b/src/sql/workbench/services/objectExplorer/browser/recentConnectionDataSource.ts index adb37d2d57..e12700c7e7 100644 --- a/src/sql/workbench/services/objectExplorer/browser/recentConnectionDataSource.ts +++ b/src/sql/workbench/services/objectExplorer/browser/recentConnectionDataSource.ts @@ -19,10 +19,8 @@ export class RecentConnectionDataSource implements IDataSource { public getId(tree: ITree, element: any): string { if (element instanceof ConnectionProfile) { return (element).id; - } else if (element instanceof ConnectionProfileGroup) { - return (element).id; } else { - return undefined; + return (element).id!; } } @@ -63,4 +61,4 @@ export class RecentConnectionDataSource implements IDataSource { return Promise.resolve(null); } } -} \ No newline at end of file +} diff --git a/src/sql/workbench/services/objectExplorer/browser/serverTreeController.ts b/src/sql/workbench/services/objectExplorer/browser/serverTreeController.ts index b6b301fa39..0a83397e4a 100644 --- a/src/sql/workbench/services/objectExplorer/browser/serverTreeController.ts +++ b/src/sql/workbench/services/objectExplorer/browser/serverTreeController.ts @@ -74,7 +74,7 @@ export class ServerTreeController extends treedefaults.DefaultController { context.nodeInfo = element.toNodeInfo(); // Note: getting DB name before, but intentionally not using treeUpdateUtils.getConnectionProfile as it replaces // the connection ID with a new one. This breaks a number of internal tasks - context.connectionProfile = element.getConnectionProfile().toIConnectionProfile(); + context.connectionProfile = element.getConnectionProfile()!.toIConnectionProfile(); context.connectionProfile.databaseName = element.getDatabaseName(); actionContext = context; } else if (element instanceof ConnectionProfile) { diff --git a/src/sql/workbench/services/objectExplorer/browser/serverTreeDataSource.ts b/src/sql/workbench/services/objectExplorer/browser/serverTreeDataSource.ts index bdac74bbca..e7a4d27f1a 100644 --- a/src/sql/workbench/services/objectExplorer/browser/serverTreeDataSource.ts +++ b/src/sql/workbench/services/objectExplorer/browser/serverTreeDataSource.ts @@ -30,13 +30,7 @@ export class ServerTreeDataSource implements IDataSource { * No more than one element may use a given identifier. */ public getId(tree: ITree, element: any): string { - if (element instanceof ConnectionProfile - || element instanceof ConnectionProfileGroup - || element instanceof TreeNode) { - return element.id; - } else { - return undefined; - } + return element.id; } /** @@ -67,7 +61,7 @@ export class ServerTreeDataSource implements IDataSource { return node.children; } else { try { - return this._objectExplorerService.resolveTreeNodeChildren(node.getSession(), node); + return this._objectExplorerService.resolveTreeNodeChildren(node.getSession()!, node); } catch (expandError) { await node.setExpandedState(TreeItemCollapsibleState.Collapsed); node.errorStateMessage = expandError; diff --git a/src/sql/workbench/services/objectExplorer/browser/serverTreeRenderer.ts b/src/sql/workbench/services/objectExplorer/browser/serverTreeRenderer.ts index 980c821f90..473701eea2 100644 --- a/src/sql/workbench/services/objectExplorer/browser/serverTreeRenderer.ts +++ b/src/sql/workbench/services/objectExplorer/browser/serverTreeRenderer.ts @@ -16,6 +16,7 @@ import { InputBox } from 'vs/base/browser/ui/inputbox/inputBox'; import { badgeRenderer, iconRenderer } from 'sql/workbench/services/objectExplorer/browser/iconRenderer'; import { URI } from 'vs/base/common/uri'; import { DefaultServerGroupColor } from 'sql/workbench/services/serverGroup/common/serverGroupViewModel'; +import { withNullAsUndefined } from 'vs/base/common/types'; export interface IConnectionTemplateData { root: HTMLElement; @@ -132,7 +133,7 @@ export class ServerTreeRenderer implements IRenderer { private renderObjectExplorer(treeNode: TreeNode, templateData: IObjectExplorerTemplateData): void { // Use an explicitly defined iconType first. If not defined, fall back to using nodeType and // other compount indicators instead. - let iconName: string = undefined; + let iconName: string | undefined = undefined; if (treeNode.iconType) { iconName = (typeof treeNode.iconType === 'string') ? treeNode.iconType : treeNode.iconType.id; } else { @@ -147,7 +148,7 @@ export class ServerTreeRenderer implements IRenderer { let tokens: string[] = []; for (let index = 1; index < templateData.icon.classList.length; index++) { - tokens.push(templateData.icon.classList.item(index)); + tokens.push(templateData.icon.classList.item(index)!); } templateData.icon.classList.remove(...tokens); templateData.icon.classList.add('icon'); @@ -162,11 +163,11 @@ export class ServerTreeRenderer implements IRenderer { templateData.root.title = treeNode.label; } - private getIconPath(connection: ConnectionProfile): IconPath { + private getIconPath(connection: ConnectionProfile): IconPath | undefined { if (!connection) { return undefined; } - if (connection['iconPath']) { - return connection['iconPath']; + if (connection.iconPath) { + return connection.iconPath; } let iconId = this._connectionManagementService.getConnectionIconId(connection.id); @@ -175,8 +176,8 @@ export class ServerTreeRenderer implements IRenderer { let providerProperties = this._connectionManagementService.getProviderProperties(connection.providerName); if (!providerProperties) { return undefined; } - let iconPath: IconPath = undefined; - let pathConfig: URI | IconPath | { id: string, path: IconPath }[] = providerProperties['iconPath']; + let iconPath: IconPath | undefined = undefined; + let pathConfig: URI | IconPath | { id: string, path: IconPath }[] | undefined = providerProperties.iconPath; if (Array.isArray(pathConfig)) { for (const e of pathConfig) { if (!e.id || e.id === iconId) { @@ -185,18 +186,18 @@ export class ServerTreeRenderer implements IRenderer { break; } } - } else if (pathConfig['light']) { - iconPath = pathConfig as IconPath; - connection['iconPath'] = iconPath; - } else { + } else if (URI.isUri(pathConfig)) { let singlePath = pathConfig as URI; iconPath = { light: singlePath, dark: singlePath }; - connection['iconPath'] = iconPath; + connection.iconPath = iconPath; + } else { + iconPath = pathConfig as IconPath; + connection.iconPath = iconPath; } return iconPath; } - private renderServerIcon(element: HTMLElement, iconPath: IconPath, isConnected: boolean): void { + private renderServerIcon(element: HTMLElement, iconPath: IconPath | undefined, isConnected: boolean): void { if (!element) { return; } if (iconPath) { iconRenderer.putIcon(element, iconPath); @@ -209,7 +210,7 @@ export class ServerTreeRenderer implements IRenderer { private renderConnection(connection: ConnectionProfile, templateData: IConnectionTemplateData): void { if (!this._isCompact) { - let iconPath: IconPath = this.getIconPath(connection); + let iconPath = this.getIconPath(connection); if (this._connectionManagementService.isConnected(undefined, connection)) { templateData.icon.classList.remove('disconnected'); templateData.icon.classList.add('connected'); @@ -252,15 +253,15 @@ export class ServerTreeRenderer implements IRenderer { /** * Returns the first parent which contains the className */ - private findParentElement(container: HTMLElement, className: string): HTMLElement { - let currentElement = container; + private findParentElement(container: HTMLElement, className: string): HTMLElement | undefined { + let currentElement: HTMLElement | null = container; while (currentElement) { if (currentElement.className.indexOf(className) > -1) { break; } currentElement = currentElement.parentElement; } - return currentElement; + return withNullAsUndefined(currentElement); } public disposeTemplate(tree: ITree, templateId: string, templateData: any): void { diff --git a/src/sql/workbench/services/objectExplorer/browser/treeCreationUtils.ts b/src/sql/workbench/services/objectExplorer/browser/treeCreationUtils.ts index 0e9b2490db..1c8ff151e3 100644 --- a/src/sql/workbench/services/objectExplorer/browser/treeCreationUtils.ts +++ b/src/sql/workbench/services/objectExplorer/browser/treeCreationUtils.ts @@ -142,5 +142,5 @@ export class TreeCreationUtils { } function useAsyncServerTree(configurationService: IConfigurationService): boolean { - return configurationService.getValue('workbench.enablePreviewFeatures') && configurationService.getValue('serverTree.useAsyncServerTree'); + return configurationService.getValue('workbench.enablePreviewFeatures') && configurationService.getValue('serverTree.useAsyncServerTree'); } diff --git a/src/sql/workbench/services/objectExplorer/test/browser/asyncServerTreeDragAndDrop.test.ts b/src/sql/workbench/services/objectExplorer/test/browser/asyncServerTreeDragAndDrop.test.ts index d7b552305f..57e8ef96c7 100644 --- a/src/sql/workbench/services/objectExplorer/test/browser/asyncServerTreeDragAndDrop.test.ts +++ b/src/sql/workbench/services/objectExplorer/test/browser/asyncServerTreeDragAndDrop.test.ts @@ -98,7 +98,7 @@ suite('AsyncServerTreeDragAndDrop', () => { assert.equal(treeNodeArray[0].label, labelTreeNode); let labelUndefined = serverTreeDragAndDrop.getDragLabel(undefined); - assert.equal(undefined, labelUndefined); + assert.equal('', labelUndefined); }); diff --git a/src/sql/workbench/services/objectExplorer/test/browser/dragAndDropController.test.ts b/src/sql/workbench/services/objectExplorer/test/browser/dragAndDropController.test.ts index 5998b0f44d..b0c530a88f 100644 --- a/src/sql/workbench/services/objectExplorer/test/browser/dragAndDropController.test.ts +++ b/src/sql/workbench/services/objectExplorer/test/browser/dragAndDropController.test.ts @@ -103,7 +103,7 @@ suite('SQL Drag And Drop Controller tests', () => { assert.equal(treeNodeArray[0].label, labelTreeNode); let labelUndefined = serverTreeDragAndDrop.getDragLabel(testTree, null); - assert.equal(undefined, labelUndefined); + assert.equal('', labelUndefined); }); diff --git a/src/sql/workbench/services/objectExplorer/test/browser/testObjectExplorerService.ts b/src/sql/workbench/services/objectExplorer/test/browser/testObjectExplorerService.ts index 2be77a8d3c..09e07d08a4 100644 --- a/src/sql/workbench/services/objectExplorer/test/browser/testObjectExplorerService.ts +++ b/src/sql/workbench/services/objectExplorer/test/browser/testObjectExplorerService.ts @@ -26,18 +26,18 @@ export type ObjectExplorerServiceMockOptions = { * * @param options Options to use for setting up functions on the mock to return various values */ -export function createObjectExplorerServiceMock(options: ObjectExplorerServiceMockOptions): TypeMoq.Mock { +export function createObjectExplorerServiceMock(options: ObjectExplorerServiceMockOptions): IObjectExplorerService { const objectExplorerService = TypeMoq.Mock.ofType(TestObjectExplorerService); if (options.treeNode) { - objectExplorerService.setup(x => x.getTreeNode(TypeMoq.It.isAny(), TypeMoq.It.isAny())).returns(() => Promise.resolve(options.treeNode)); + objectExplorerService.setup(x => x.getTreeNode(TypeMoq.It.isAny(), TypeMoq.It.isAny())).returns(() => Promise.resolve(options.treeNode!)); } if (options.serverTreeView) { - objectExplorerService.setup(x => x.getServerTreeView()).returns(() => options.serverTreeView); + objectExplorerService.setup(x => x.getServerTreeView()).returns(() => options.serverTreeView!); } - return objectExplorerService; + return objectExplorerService.object; } /** @@ -49,13 +49,13 @@ export class TestObjectExplorerService implements IObjectExplorerService { constructor() { } - public getSession(sessionId: string): azdata.ObjectExplorerSession { return undefined; } + public getSession(sessionId: string): azdata.ObjectExplorerSession { throw new Error('Method not implemented'); } public providerRegistered(providerId: string): boolean { return true; } - public get onUpdateObjectExplorerNodes(): Event { return undefined; } + public get onUpdateObjectExplorerNodes(): Event { throw new Error('Method not implemented'); } - public get onSelectionOrFocusChange(): Event { return undefined; } + public get onSelectionOrFocusChange(): Event { throw new Error('Method not implemented'); } public async updateObjectExplorerNodes(connection: IConnectionProfile): Promise { } @@ -67,41 +67,41 @@ export class TestObjectExplorerService implements IObjectExplorerService { public async onSessionDisconnected(handle: number, session: azdata.ObjectExplorerSession): Promise { } - public getObjectExplorerNode(connection: IConnectionProfile): TreeNode { return undefined; } + public getObjectExplorerNode(connection: IConnectionProfile): TreeNode { throw new Error('Method not implemented'); } - public async createNewSession(providerId: string, connection: ConnectionProfile): Promise { return undefined; } + public async createNewSession(providerId: string, connection: ConnectionProfile): Promise { throw new Error('Method not implemented'); } - public async expandNode(providerId: string, session: azdata.ObjectExplorerSession, nodePath: string): Promise { return undefined; } + public async expandNode(providerId: string, session: azdata.ObjectExplorerSession, nodePath: string): Promise { throw new Error('Method not implemented'); } - public async refreshNode(providerId: string, session: azdata.ObjectExplorerSession, nodePath: string): Promise { return undefined; } + public async refreshNode(providerId: string, session: azdata.ObjectExplorerSession, nodePath: string): Promise { throw new Error('Method not implemented'); } - public async closeSession(providerId: string, session: azdata.ObjectExplorerSession): Promise { return undefined; } + public async closeSession(providerId: string, session: azdata.ObjectExplorerSession): Promise { throw new Error('Method not implemented'); } public registerProvider(providerId: string, provider: azdata.ObjectExplorerProvider): void { } public registerNodeProvider(nodeProvider: azdata.ObjectExplorerNodeProvider): void { } - public async resolveTreeNodeChildren(session: azdata.ObjectExplorerSession, parentTree: TreeNode): Promise { return undefined; } + public async resolveTreeNodeChildren(session: azdata.ObjectExplorerSession, parentTree: TreeNode): Promise { throw new Error('Method not implemented'); } - public async refreshTreeNode(session: azdata.ObjectExplorerSession, parentTree: TreeNode): Promise { return undefined; } + public async refreshTreeNode(session: azdata.ObjectExplorerSession, parentTree: TreeNode): Promise { throw new Error('Method not implemented'); } public registerServerTreeView(view: IServerTreeView): void { } - public getSelectedProfileAndDatabase(): { profile: ConnectionProfile, databaseName: string } { return undefined; } + public getSelectedProfileAndDatabase(): { profile: ConnectionProfile, databaseName: string } | undefined { return undefined; } public isFocused(): boolean { return true; } - public getServerTreeView(): IServerTreeView { return undefined; } + public getServerTreeView(): IServerTreeView { throw new Error('Method not implemented'); } - public async findNodes(connectionId: string, type: string, schema: string, name: string, database: string, parentObjectNames?: string[]): Promise { return undefined; } + public async findNodes(connectionId: string, type: string, schema: string, name: string, database: string, parentObjectNames?: string[]): Promise { throw new Error('Method not implemented'); } - public getActiveConnectionNodes(): TreeNode[] { return undefined; } + public getActiveConnectionNodes(): TreeNode[] { throw new Error('Method not implemented'); } - public async getNodeActions(connectionId: string, nodePath: string): Promise { return undefined; } + public async getNodeActions(connectionId: string, nodePath: string): Promise { throw new Error('Method not implemented'); } - public async refreshNodeInView(connectionId: string, nodePath: string): Promise { return undefined; } + public async refreshNodeInView(connectionId: string, nodePath: string): Promise { throw new Error('Method not implemented'); } - public getSessionConnectionProfile(sessionId: string): azdata.IConnectionProfile { return undefined; } + public getSessionConnectionProfile(sessionId: string): azdata.IConnectionProfile { throw new Error('Method not implemented'); } - public async getTreeNode(connectionId: string, nodePath: string): Promise { return undefined; } + public async getTreeNode(connectionId: string, nodePath: string): Promise { throw new Error('Method not implemented'); } } diff --git a/src/sql/workbench/services/queryHistory/common/queryHistoryInfo.ts b/src/sql/workbench/services/queryHistory/common/queryHistoryInfo.ts index f6f3d12ff2..bbb5d8a212 100644 --- a/src/sql/workbench/services/queryHistory/common/queryHistoryInfo.ts +++ b/src/sql/workbench/services/queryHistory/common/queryHistoryInfo.ts @@ -28,7 +28,7 @@ export class QueryHistoryInfo { public connectionProfile: IConnectionProfile, public startTime: Date, status?: QueryStatus) { - this.database = connectionProfile ? connectionProfile.databaseName : ''; + this.database = connectionProfile?.databaseName ?? ''; this.status = status; } } diff --git a/src/sql/workbench/services/restore/browser/restoreServiceImpl.ts b/src/sql/workbench/services/restore/browser/restoreServiceImpl.ts index c88548e303..d389b615ab 100644 --- a/src/sql/workbench/services/restore/browser/restoreServiceImpl.ts +++ b/src/sql/workbench/services/restore/browser/restoreServiceImpl.ts @@ -319,7 +319,7 @@ export class RestoreDialogController implements IRestoreDialogController { if (this._currentProvider === ConnectionConstants.mssqlProviderName) { let restoreDialog = this._restoreDialogs[this._currentProvider] as RestoreDialog; - restoreDialog.viewModel.resetRestoreOptions(connection.databaseName); + restoreDialog.viewModel.resetRestoreOptions(connection.databaseName!); this.getMssqlRestoreConfigInfo().then(() => { restoreDialog.open(connection.serverName, this._ownerUri!); restoreDialog.validateRestore(); diff --git a/src/sql/workbench/services/tasks/common/tasksService.ts b/src/sql/workbench/services/tasks/common/tasksService.ts index bf4b362d3a..6e2535c497 100644 --- a/src/sql/workbench/services/tasks/common/tasksService.ts +++ b/src/sql/workbench/services/tasks/common/tasksService.ts @@ -77,7 +77,7 @@ export class TaskService implements ITaskService { } public createNewTask(taskInfo: azdata.TaskInfo) { - let databaseName: string = taskInfo.databaseName; + let databaseName: string | undefined = taskInfo.databaseName; let serverName: string = taskInfo.serverName; if (taskInfo && taskInfo.connection) { let connectionProfile = this.connectionManagementService.getConnectionProfile(taskInfo.connection.connectionId); diff --git a/src/sql/workbench/test/treeMock.ts b/src/sql/workbench/test/treeMock.ts index 5c4472051b..395424736d 100644 --- a/src/sql/workbench/test/treeMock.ts +++ b/src/sql/workbench/test/treeMock.ts @@ -12,24 +12,24 @@ import { IItemExpandEvent, IItemCollapseEvent } from 'vs/base/parts/tree/browser */ export class TestTree implements ITree { - readonly onDidChangeFocus: Event; - readonly onDidChangeSelection: Event; - readonly onDidChangeHighlight: Event; - readonly onDidExpandItem: Event; - readonly onDidCollapseItem: Event; - readonly onDidDispose: Event; + readonly onDidChangeFocus: Event = Event.None; + readonly onDidChangeSelection: Event = Event.None; + readonly onDidChangeHighlight: Event = Event.None; + readonly onDidExpandItem: Event = Event.None; + readonly onDidCollapseItem: Event = Event.None; + readonly onDidDispose: Event = Event.None; constructor() { } public style(styles: ITreeStyles): void { } - get onDidFocus(): Event { return undefined; } + get onDidFocus(): Event { return Event.None; } - get onDidBlur(): Event { return undefined; } + get onDidBlur(): Event { return Event.None; } - get onDidScroll(): Event { return undefined; } + get onDidScroll(): Event { return Event.None; } - public getHTMLElement(): HTMLElement { return undefined; } + public getHTMLElement(): HTMLElement { throw new Error('Method not implemented'); } public layout(height?: number, width?: number): void { } @@ -113,7 +113,7 @@ export class TestTree implements ITree { public deselect(element: any, eventPayload?: any): void { } - getNavigator(fromElement?: any, subTreeOnly?: boolean): INavigator { return undefined; } + getNavigator(fromElement?: any, subTreeOnly?: boolean): INavigator { throw new Error('Method not implemented'); } public dispose(): void { } } diff --git a/src/tsconfig.vscode.json b/src/tsconfig.vscode.json index f2dbced6fb..10e8141203 100644 --- a/src/tsconfig.vscode.json +++ b/src/tsconfig.vscode.json @@ -72,7 +72,6 @@ "./sql/workbench/contrib/profiler/**/*.ts", // 100 errors "./sql/workbench/contrib/query/**/*.ts", // 3077 errors "./sql/workbench/contrib/queryHistory/**/*.ts", // 290 errors - "./sql/workbench/contrib/scripting/**/*.ts", // 179 errors "./sql/workbench/contrib/welcome/**/*.ts", // 66 errors "./sql/workbench/services/connection/**/*.ts", // 3130 errors "./sql/workbench/services/dialog/**/*.ts", // 2995 errors