More layering and strictness (#9004)

* move handling generated files to the serilization classes

* remove unneeded methods

* add more folders to strictire compile, add more strict compile options

* update ci

* wip

* add more layering and fix issues

* add more strictness

* remove unnecessary assertion

* add missing checks

* fix indentation

* wip

* remove jsdoc

* fix layering

* fix compile

* fix compile errors

* wip

* wip

* finish layering

* fix css

* more layering

* remove no longer good parts

* fix issues with startup

* another try

* fix startup
This commit is contained in:
Anthony Dresser
2020-02-11 00:47:17 -06:00
committed by GitHub
parent 3a8b74a311
commit 0f934081e1
97 changed files with 489 additions and 214 deletions

View File

@@ -1,229 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as azdata from 'azdata';
import { TreeNode } from 'sql/workbench/contrib/objectExplorer/common/treeNode';
import { ICapabilitiesService } from 'sql/platform/capabilities/common/capabilitiesService';
import { IConnectionManagementService } from 'sql/platform/connection/common/connectionManagement';
import { ConnectionProfile } from 'sql/platform/connection/common/connectionProfile';
import { ITreeItem } from 'sql/workbench/common/views';
import { IObjectExplorerService } from 'sql/workbench/services/objectExplorer/browser/objectExplorerService';
import { hash } from 'vs/base/common/hash';
import { Disposable } from 'vs/base/common/lifecycle';
import { generateUuid } from 'vs/base/common/uuid';
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
import { TreeItemCollapsibleState } from 'vs/workbench/common/views';
import { localize } from 'vs/nls';
import { NodeType } from 'sql/workbench/contrib/objectExplorer/common/nodeType';
import { UserCancelledConnectionError } from 'sql/base/common/errors';
import { assign } from 'vs/base/common/objects';
export const SERVICE_ID = 'oeShimService';
export const IOEShimService = createDecorator<IOEShimService>(SERVICE_ID);
export interface IOEShimService {
_serviceBrand: undefined;
getChildren(node: ITreeItem, viewId: string): Promise<ITreeItem[]>;
disconnectNode(viewId: string, node: ITreeItem): Promise<boolean>;
providerExists(providerId: string): boolean;
isNodeConnected(viewId: string, node: ITreeItem): boolean;
getNodeInfoForTreeItem(treeItem: ITreeItem): azdata.NodeInfo;
}
export class OEShimService extends Disposable implements IOEShimService {
_serviceBrand: undefined;
private sessionMap = new Map<number, string>();
private nodeHandleMap = new Map<number, string>();
private nodeInfoMap = new Map<ITreeItem, azdata.NodeInfo>();
constructor(
@IObjectExplorerService private oe: IObjectExplorerService,
@IConnectionManagementService private cm: IConnectionManagementService,
@ICapabilitiesService private capabilities: ICapabilitiesService
) {
super();
}
private async createSession(viewId: string, providerId: string, node: ITreeItem): Promise<string> {
let connProfile = new ConnectionProfile(this.capabilities, node.payload);
connProfile.saveProfile = false;
if (this.cm.providerRegistered(providerId)) {
connProfile = await this.connectOrPrompt(connProfile);
} else {
// Throw and expect upstream handler to notify about the error
// TODO: In the future should use extension recommendations to prompt for correct extension
throw new Error(localize('noProviderFound', "Cannot expand as the required connection provider '{0}' was not found", providerId));
}
let sessionResp = await this.oe.createNewSession(providerId, connProfile);
let sessionId = sessionResp.sessionId;
await new Promise((resolve, reject) => {
let listener = this.oe.onUpdateObjectExplorerNodes(e => {
if (e.connection.id === connProfile.id) {
if (e.errorMessage) {
listener.dispose();
reject(new Error(e.errorMessage));
return;
}
let rootNode = this.oe.getSession(sessionResp.sessionId).rootNode;
// this is how we know it was shimmed
if (rootNode.nodePath) {
this.nodeHandleMap.set(generateNodeMapKey(viewId, node), rootNode.nodePath);
}
}
listener.dispose();
resolve(sessionResp.sessionId);
});
});
return sessionId;
}
private async connectOrPrompt(connProfile: ConnectionProfile): Promise<ConnectionProfile> {
connProfile = await new Promise(async (resolve, reject) => {
let result = await this.cm.connect(connProfile, undefined, { showConnectionDialogOnError: true, showFirewallRuleOnError: true, saveTheConnection: false, showDashboard: false, params: undefined }, {
onConnectSuccess: async (e, profile) => {
let existingConnection = this.cm.findExistingConnection(profile);
connProfile = new ConnectionProfile(this.capabilities, existingConnection);
connProfile = <ConnectionProfile>await this.cm.addSavedPassword(connProfile);
resolve(connProfile);
},
onConnectCanceled: () => {
reject(new UserCancelledConnectionError(localize('loginCanceled', "User canceled")));
},
onConnectReject: undefined,
onConnectStart: undefined,
onDisconnect: undefined
});
// connection cancelled from firewall dialog
if (!result) {
reject(new UserCancelledConnectionError(localize('firewallCanceled', "Firewall dialog canceled")));
}
});
return connProfile;
}
public async disconnectNode(viewId: string, node: ITreeItem): Promise<boolean> {
// we assume only nodes with payloads can be connected
// check to make sure we have an existing connection
let key = generateSessionMapKey(viewId, node);
let session = this.sessionMap.get(key);
if (session) {
let closed = (await this.oe.closeSession(node.childProvider, this.oe.getSession(session))).success;
if (closed) {
this.sessionMap.delete(key);
}
return closed;
}
return Promise.resolve(false);
}
private async getOrCreateSession(viewId: string, node: ITreeItem): Promise<string> {
// verify the map is correct
let key = generateSessionMapKey(viewId, node);
if (!this.sessionMap.has(key)) {
this.sessionMap.set(key, await this.createSession(viewId, node.childProvider, node));
}
return this.sessionMap.get(key);
}
public async getChildren(node: ITreeItem, viewId: string): Promise<ITreeItem[]> {
if (node.payload) {
let sessionId = await this.getOrCreateSession(viewId, node);
let requestHandle = this.nodeHandleMap.get(generateNodeMapKey(viewId, node)) || node.handle;
let treeNode = new TreeNode(undefined, undefined, undefined, requestHandle, undefined, undefined, undefined, undefined, undefined, undefined);
treeNode.connection = new ConnectionProfile(this.capabilities, node.payload);
return this.oe.resolveTreeNodeChildren({
success: undefined,
sessionId,
rootNode: undefined,
errorMessage: undefined
}, treeNode).then(e => e.map(n => this.treeNodeToITreeItem(viewId, n, node)));
} else {
return Promise.resolve([]);
}
}
private treeNodeToITreeItem(viewId: string, node: TreeNode, parentNode: ITreeItem): ITreeItem {
let handle = generateUuid();
let icon: string = '';
let nodePath = node.nodePath;
if (node.iconType) {
icon = (typeof node.iconType === 'string') ? node.iconType : node.iconType.id;
} else {
icon = node.nodeTypeId;
if (node.nodeStatus) {
icon = node.nodeTypeId + '_' + node.nodeStatus;
}
if (node.nodeSubType) {
icon = node.nodeTypeId + '_' + node.nodeSubType;
}
}
icon = icon.toLowerCase();
// Change the database if the node has a different database
// than its parent
let databaseChanged = false;
let updatedPayload: azdata.IConnectionProfile | any = {};
if (node.nodeTypeId === NodeType.Database) {
const database = node.getDatabaseName();
if (database) {
databaseChanged = true;
updatedPayload = assign(updatedPayload, parentNode.payload);
updatedPayload.databaseName = node.getDatabaseName();
}
}
const nodeInfo: azdata.NodeInfo = {
nodePath: nodePath,
nodeType: node.nodeTypeId,
nodeSubType: node.nodeSubType,
nodeStatus: node.nodeStatus,
label: node.label,
isLeaf: node.isAlwaysLeaf,
metadata: node.metadata,
errorMessage: node.errorStateMessage,
iconType: icon,
childProvider: node.childProvider || parentNode.childProvider,
payload: node.payload || (databaseChanged ? updatedPayload : parentNode.payload)
};
let newTreeItem: ITreeItem = {
parentHandle: node.parent.id,
handle,
collapsibleState: node.isAlwaysLeaf ? TreeItemCollapsibleState.None : TreeItemCollapsibleState.Collapsed,
label: {
label: node.label
},
childProvider: node.childProvider || parentNode.childProvider,
providerHandle: parentNode.childProvider,
payload: node.payload || (databaseChanged ? updatedPayload : parentNode.payload),
contextValue: node.nodeTypeId,
sqlIcon: icon
};
this.nodeHandleMap.set(generateNodeMapKey(viewId, newTreeItem), nodePath);
this.nodeInfoMap.set(newTreeItem, nodeInfo);
return newTreeItem;
}
public providerExists(providerId: string): boolean {
return this.oe.providerRegistered(providerId);
}
public isNodeConnected(viewId: string, node: ITreeItem): boolean {
return this.sessionMap.has(generateSessionMapKey(viewId, node));
}
public getNodeInfoForTreeItem(treeItem: ITreeItem): azdata.NodeInfo {
if (this.nodeInfoMap.has(treeItem)) {
return this.nodeInfoMap.get(treeItem);
}
return undefined;
}
}
function generateSessionMapKey(viewId: string, node: ITreeItem): number {
return hash([viewId, node.childProvider, node.payload]);
}
function generateNodeMapKey(viewId: string, node: ITreeItem): number {
return hash([viewId, node.handle]);
}

View File

@@ -14,13 +14,13 @@ import {
DeleteConnectionAction, RefreshAction, EditServerGroupAction
} from 'sql/workbench/contrib/objectExplorer/browser/connectionTreeAction';
import { TreeNode } from 'sql/workbench/contrib/objectExplorer/common/treeNode';
import { NodeType } from 'sql/workbench/contrib/objectExplorer/common/nodeType';
import { NodeType } from 'sql/workbench/services/objectExplorer/common/nodeType';
import { ConnectionProfileGroup } from 'sql/platform/connection/common/connectionProfileGroup';
import { ConnectionProfile } from 'sql/platform/connection/common/connectionProfile';
import { TreeUpdateUtils } from 'sql/workbench/contrib/objectExplorer/browser/treeUpdateUtils';
import { IConnectionManagementService } from 'sql/platform/connection/common/connectionManagement';
import { MenuId, IMenuService } from 'vs/platform/actions/common/actions';
import { ConnectionContextKey } from 'sql/workbench/contrib/connection/common/connectionContextKey';
import { ConnectionContextKey } from 'sql/workbench/services/connection/common/connectionContextKey';
import { TreeNodeContextKey } from 'sql/workbench/contrib/objectExplorer/common/treeNodeContextKey';
import { IQueryManagementService } from 'sql/workbench/services/query/common/queryManagement';
import { ServerInfoContextKey } from 'sql/workbench/contrib/connection/common/serverInfoContextKey';

View File

@@ -8,7 +8,7 @@ import { IConnectionManagementService, IConnectionCompletionOptions, IConnection
import { ITree } from 'vs/base/parts/tree/browser/tree';
import { ConnectionProfile } from 'sql/platform/connection/common/connectionProfile';
import { IObjectExplorerService } from 'sql/workbench/services/objectExplorer/browser/objectExplorerService';
import { NodeType } from 'sql/workbench/contrib/objectExplorer/common/nodeType';
import { NodeType } from 'sql/workbench/services/objectExplorer/common/nodeType';
import { TreeNode } from 'sql/workbench/contrib/objectExplorer/common/treeNode';
import * as errors from 'vs/base/common/errors';

View File

@@ -1,104 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
export class NodeType {
public static Folder = 'Folder';
public static Root = 'root';
public static Database = 'Database';
public static Server = 'Server';
public static ScalarValuedFunction = 'ScalarValuedFunction';
public static TableValuedFunction = 'TableValuedFunction';
public static AggregateFunction = 'AggregateFunction';
public static FileGroup = 'FileGroup';
public static StoredProcedure = 'StoredProcedure';
public static UserDefinedTableType = 'UserDefinedTableType';
public static View = 'View';
public static Table = 'Table';
public static HistoryTable = 'HistoryTable';
public static ServerLevelLinkedServerLogin = 'ServerLevelLinkedServerLogin';
public static ServerLevelServerAudit = 'ServerLevelServerAudit';
public static ServerLevelCryptographicProvider = 'ServerLevelCryptographicProvider';
public static ServerLevelCredential = 'ServerLevelCredential';
public static ServerLevelServerRole = 'ServerLevelServerRole';
public static ServerLevelLogin = 'ServerLevelLogin';
public static ServerLevelServerAuditSpecification = 'ServerLevelServerAuditSpecification';
public static ServerLevelServerTrigger = 'ServerLevelServerTrigger';
public static ServerLevelLinkedServer = 'ServerLevelLinkedServer';
public static ServerLevelEndpoint = 'ServerLevelEndpoint';
public static Synonym = 'Synonym';
public static DatabaseTrigger = 'DatabaseTrigger';
public static Assembly = 'Assembly';
public static MessageType = 'MessageType';
public static Contract = 'Contract';
public static Queue = 'Queue';
public static Service = 'Service';
public static Route = 'Route';
public static DatabaseAndQueueEventNotification = 'DatabaseAndQueueEventNotification';
public static RemoteServiceBinding = 'RemoteServiceBinding';
public static BrokerPriority = 'BrokerPriority';
public static FullTextCatalog = 'FullTextCatalog';
public static FullTextStopList = 'FullTextStopList';
public static SqlLogFile = 'SqlLogFile';
public static PartitionFunction = 'PartitionFunction';
public static PartitionScheme = 'PartitionScheme';
public static SearchPropertyList = 'SearchPropertyList';
public static User = 'User';
public static Schema = 'Schema';
public static AsymmetricKey = 'AsymmetricKey';
public static Certificate = 'Certificate';
public static SymmetricKey = 'SymmetricKey';
public static DatabaseEncryptionKey = 'DatabaseEncryptionKey';
public static MasterKey = 'MasterKey';
public static DatabaseAuditSpecification = 'DatabaseAuditSpecification';
public static Column = 'Column';
public static Key = 'Key';
public static Constraint = 'Constraint';
public static Trigger = 'Trigger';
public static Index = 'Index';
public static Statistic = 'Statistic';
public static UserDefinedDataType = 'UserDefinedDataType';
public static UserDefinedType = 'UserDefinedType';
public static XmlSchemaCollection = 'XmlSchemaCollection';
public static SystemExactNumeric = 'SystemExactNumeric';
public static SystemApproximateNumeric = 'SystemApproximateNumeric';
public static SystemDateAndTime = 'SystemDateAndTime';
public static SystemCharacterString = 'SystemCharacterString';
public static SystemUnicodeCharacterString = 'SystemUnicodeCharacterString';
public static SystemBinaryString = 'SystemBinaryString';
public static SystemOtherDataType = 'SystemOtherDataType';
public static SystemClrDataType = 'SystemClrDataType';
public static SystemSpatialDataType = 'SystemSpatialDataType';
public static UserDefinedTableTypeColumn = 'UserDefinedTableTypeColumn';
public static UserDefinedTableTypeKey = 'UserDefinedTableTypeKey';
public static UserDefinedTableTypeConstraint = 'UserDefinedTableTypeConstraint';
public static StoredProcedureParameter = 'StoredProcedureParameter';
public static TableValuedFunctionParameter = 'TableValuedFunctionParameter';
public static ScalarValuedFunctionParameter = 'ScalarValuedFunctionParameter';
public static AggregateFunctionParameter = 'AggregateFunctionParameter';
public static DatabaseRole = 'DatabaseRole';
public static ApplicationRole = 'ApplicationRole';
public static FileGroupFile = 'FileGroupFile';
public static SystemMessageType = 'SystemMessageType';
public static SystemContract = 'SystemContract';
public static SystemService = 'SystemService';
public static SystemQueue = 'SystemQueue';
public static Sequence = 'Sequence';
public static SecurityPolicy = 'SecurityPolicy';
public static DatabaseScopedCredential = 'DatabaseScopedCredential';
public static ExternalResource = 'ExternalResource';
public static ExternalDataSource = 'ExternalDataSource';
public static ExternalFileFormat = 'ExternalFileFormat';
public static ExternalTable = 'ExternalTable';
public static ColumnMasterKey = 'ColumnMasterKey';
public static ColumnEncryptionKey = 'ColumnEncryptionKey';
public static readonly SCRIPTABLE_OBJECTS = [NodeType.Table, NodeType.View, NodeType.Schema, NodeType.User, NodeType.UserDefinedTableType,
NodeType.StoredProcedure, NodeType.AggregateFunction, NodeType.PartitionFunction, NodeType.ScalarValuedFunction,
NodeType.TableValuedFunction];
}
export interface SqlThemeIcon {
readonly id: string;
}

View File

@@ -4,7 +4,7 @@
*--------------------------------------------------------------------------------------------*/
import { ConnectionProfile } from 'sql/platform/connection/common/connectionProfile';
import { NodeType, SqlThemeIcon } from 'sql/workbench/contrib/objectExplorer/common/nodeType';
import { NodeType, SqlThemeIcon } from 'sql/workbench/services/objectExplorer/common/nodeType';
import * as azdata from 'azdata';
import * as UUID from 'vs/base/common/uuid';

View File

@@ -19,7 +19,7 @@ import { ServerTreeView } from 'sql/workbench/contrib/objectExplorer/browser/ser
import * as LocalizedConstants from 'sql/workbench/contrib/connection/common/localizedConstants';
import { ObjectExplorerService, ObjectExplorerNodeEventArgs } from 'sql/workbench/services/objectExplorer/browser/objectExplorerService';
import { TreeNode } from 'sql/workbench/contrib/objectExplorer/common/treeNode';
import { NodeType } from 'sql/workbench/contrib/objectExplorer/common/nodeType';
import { NodeType } from 'sql/workbench/services/objectExplorer/common/nodeType';
import { Tree } from 'vs/base/parts/tree/browser/treeImpl';
import { ServerTreeDataSource } from 'sql/workbench/contrib/objectExplorer/browser/serverTreeDataSource';
import { Emitter, Event } from 'vs/base/common/event';