Object Explorer API (#783)

See https://github.com/Microsoft/sqlopsstudio/wiki/Extensibility-API#object-explorer for usage details
This commit is contained in:
Matt Irvine
2018-03-09 15:02:20 -08:00
committed by GitHub
parent fab4185c1f
commit c06ab27d08
13 changed files with 707 additions and 63 deletions

View File

@@ -5,7 +5,7 @@
'use strict';
import { NodeType } from 'sql/parts/registeredServer/common/nodeType';
import { TreeNode } from 'sql/parts/registeredServer/common/treeNode';
import { TreeNode, TreeItemCollapsibleState, ObjectExplorerCallbacks } from 'sql/parts/registeredServer/common/treeNode';
import { ConnectionProfile } from 'sql/parts/connection/common/connectionProfile';
import { IDisposable, dispose } from 'vs/base/common/lifecycle';
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
@@ -20,6 +20,7 @@ import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import { warn, error } from 'sql/base/common/log';
import { ServerTreeView } from 'sql/parts/registeredServer/viewlet/serverTreeView';
import { ICapabilitiesService } from 'sql/services/capabilities/capabilitiesService';
import * as vscode from 'vscode';
export const SERVICE_ID = 'ObjectExplorerService';
@@ -36,7 +37,7 @@ export interface IObjectExplorerService {
refreshNode(providerId: string, session: sqlops.ObjectExplorerSession, nodePath: string): Thenable<sqlops.ObjectExplorerExpandInfo>;
expandTreeNode(session: sqlops.ObjectExplorerSession, parentTree: TreeNode): Thenable<TreeNode[]>;
resolveTreeNodeChildren(session: sqlops.ObjectExplorerSession, parentTree: TreeNode): Thenable<TreeNode[]>;
refreshTreeNode(session: sqlops.ObjectExplorerSession, parentTree: TreeNode): Thenable<TreeNode[]>;
@@ -66,16 +67,19 @@ export interface IObjectExplorerService {
onSelectionOrFocusChange: Event<void>;
getServerTreeView(): ServerTreeView;
getActiveConnectionNodes(): TreeNode[];
getTreeNode(connectionId: string, nodePath: string): Thenable<TreeNode>;
}
interface SessionStatus {
nodes: { [nodePath: string]: NodeStatus };
connection: ConnectionProfile;
}
interface NodeStatus {
expandHandler: (result: sqlops.ObjectExplorerExpandInfo) => void;
expandEmitter: Emitter<sqlops.ObjectExplorerExpandInfo>;
}
export interface ObjectExplorerNodeEventArgs {
@@ -83,6 +87,10 @@ export interface ObjectExplorerNodeEventArgs {
errorMessage: string;
}
export interface NodeInfoWithConnection {
connectionId: string;
nodeInfo: sqlops.NodeInfo;
}
export class ObjectExplorerService implements IObjectExplorerService {
@@ -153,8 +161,8 @@ export class ObjectExplorerService implements IObjectExplorerService {
}
let nodeStatus = this._sessions[expandResponse.sessionId].nodes[expandResponse.nodePath];
if (nodeStatus && nodeStatus.expandHandler) {
nodeStatus.expandHandler(expandResponse);
if (nodeStatus && nodeStatus.expandEmitter) {
nodeStatus.expandEmitter.fire(expandResponse);
} else {
warn(`Cannot find node status for session: ${expandResponse.sessionId} and node path: ${expandResponse.nodePath}`);
}
@@ -268,24 +276,33 @@ export class ObjectExplorerService implements IObjectExplorerService {
let self = this;
return new Promise<sqlops.ObjectExplorerExpandInfo>((resolve, reject) => {
if (session.sessionId in self._sessions && self._sessions[session.sessionId]) {
self._sessions[session.sessionId].nodes[nodePath] = {
expandHandler: ((expandResult) => {
if (expandResult && !expandResult.errorMessage) {
resolve(expandResult);
}
else {
reject(expandResult ? expandResult.errorMessage : undefined);
}
let newRequest = false;
if (!self._sessions[session.sessionId].nodes[nodePath]) {
self._sessions[session.sessionId].nodes[nodePath] = {
expandEmitter: new Emitter<sqlops.ObjectExplorerExpandInfo>()
};
newRequest = true;
}
self._sessions[session.sessionId].nodes[nodePath].expandEmitter.event(((expandResult) => {
if (expandResult && !expandResult.errorMessage) {
resolve(expandResult);
}
else {
reject(expandResult ? expandResult.errorMessage : undefined);
}
if (newRequest) {
delete self._sessions[session.sessionId].nodes[nodePath];
})
};
self.callExpandOrRefreshFromProvider(provider, {
sessionId: session ? session.sessionId : undefined,
nodePath: nodePath
}, refresh).then(result => {
}, error => {
reject(error);
});
}
}));
if (newRequest) {
self.callExpandOrRefreshFromProvider(provider, {
sessionId: session.sessionId,
nodePath: nodePath
}, refresh).then(result => {
}, error => {
reject(error);
});
}
} else {
reject(`session cannot find to expand node. id: ${session.sessionId} nodePath: ${nodePath}`);
}
@@ -323,7 +340,7 @@ export class ObjectExplorerService implements IObjectExplorerService {
this._disposables = dispose(this._disposables);
}
public expandTreeNode(session: sqlops.ObjectExplorerSession, parentTree: TreeNode): Thenable<TreeNode[]> {
public resolveTreeNodeChildren(session: sqlops.ObjectExplorerSession, parentTree: TreeNode): Thenable<TreeNode[]> {
return this.expandOrRefreshTreeNode(session, parentTree);
}
@@ -377,7 +394,12 @@ export class ObjectExplorerService implements IObjectExplorerService {
}
return new TreeNode(nodeInfo.nodeType, nodeInfo.label, isLeaf, nodeInfo.nodePath,
nodeInfo.nodeSubType, nodeInfo.nodeStatus, parent, nodeInfo.metadata);
nodeInfo.nodeSubType, nodeInfo.nodeStatus, parent, nodeInfo.metadata, {
getChildren: treeNode => this.getChildren(treeNode),
isExpanded: treeNode => this.isExpanded(treeNode),
setNodeExpandedState: (treeNode, expandedState) => this.setNodeExpandedState(treeNode, expandedState),
setNodeSelected: (treeNode, selected, clearOtherSelections: boolean = undefined) => this.setNodeSelected(treeNode, selected, clearOtherSelections)
});
}
public registerServerTreeView(view: ServerTreeView): void {
@@ -424,4 +446,96 @@ export class ObjectExplorerService implements IObjectExplorerService {
public getServerTreeView() {
return this._serverTreeView;
}
public getActiveConnectionNodes(): TreeNode[] {
return Object.values(this._activeObjectExplorerNodes);
}
private async setNodeExpandedState(treeNode: TreeNode, expandedState: TreeItemCollapsibleState): Promise<void> {
treeNode = await this.getUpdatedTreeNode(treeNode);
let expandNode = this.getTreeItem(treeNode);
if (expandedState === TreeItemCollapsibleState.Expanded) {
await this._serverTreeView.reveal(expandNode);
}
return this._serverTreeView.setExpandedState(expandNode, expandedState);
}
private async setNodeSelected(treeNode: TreeNode, selected: boolean, clearOtherSelections: boolean = undefined): Promise<void> {
treeNode = await this.getUpdatedTreeNode(treeNode);
let selectNode = this.getTreeItem(treeNode);
if (selected) {
await this._serverTreeView.reveal(selectNode);
}
return this._serverTreeView.setSelected(selectNode, selected, clearOtherSelections);
}
private async getChildren(treeNode: TreeNode): Promise<TreeNode[]> {
treeNode = await this.getUpdatedTreeNode(treeNode);
if (treeNode.isAlwaysLeaf) {
return [];
}
if (!treeNode.children) {
await this.resolveTreeNodeChildren(treeNode.getSession(), treeNode);
}
return treeNode.children;
}
private async isExpanded(treeNode: TreeNode): Promise<boolean> {
treeNode = await this.getUpdatedTreeNode(treeNode);
do {
let expandNode = this.getTreeItem(treeNode);
if (!this._serverTreeView.isExpanded(expandNode)) {
return false;
}
treeNode = treeNode.parent;
} while (treeNode);
return true;
}
private getTreeItem(treeNode: TreeNode): TreeNode | ConnectionProfile {
let rootNode = this._activeObjectExplorerNodes[treeNode.getConnectionProfile().id];
if (treeNode === rootNode) {
return treeNode.connection;
}
return treeNode;
}
private getUpdatedTreeNode(treeNode: TreeNode): Promise<TreeNode> {
return this.getTreeNode(treeNode.getConnectionProfile().id, treeNode.nodePath).then(treeNode => {
if (!treeNode) {
throw new Error(nls.localize('treeNodeNoLongerExists', 'The given tree node no longer exists'));
}
return treeNode;
});
}
public async getTreeNode(connectionId: string, nodePath: string): Promise<TreeNode> {
let parentNode = this._activeObjectExplorerNodes[connectionId];
if (!parentNode) {
return undefined;
}
if (!nodePath) {
return parentNode;
}
let currentNode = parentNode;
while (currentNode.nodePath !== nodePath) {
let nextNode = undefined;
if (!currentNode.isAlwaysLeaf && !currentNode.children) {
await this.resolveTreeNodeChildren(currentNode.getSession(), currentNode);
}
if (currentNode.children) {
// Look at the next node in the path, which is the child object with the longest path where the desired path starts with the child path
let children = currentNode.children.filter(child => nodePath.startsWith(child.nodePath));
if (children.length > 0) {
nextNode = children.reduce((currentMax, candidate) => currentMax.nodePath.length < candidate.nodePath.length ? candidate : currentMax);
}
}
if (!nextNode) {
return undefined;
}
currentNode = nextNode;
}
return currentNode;
}
}

View File

@@ -11,6 +11,19 @@ import * as sqlops from 'sqlops';
import * as UUID from 'vs/base/common/uuid';
export enum TreeItemCollapsibleState {
None = 0,
Collapsed = 1,
Expanded = 2
}
export interface ObjectExplorerCallbacks {
getChildren(treeNode: TreeNode): Thenable<TreeNode[]>;
isExpanded(treeNode: TreeNode): Thenable<boolean>;
setNodeExpandedState(TreeNode: TreeNode, expandedState: TreeItemCollapsibleState): Thenable<void>;
setNodeSelected(TreeNode: TreeNode, selected: boolean, clearOtherSelections?: boolean): Thenable<void>;
}
export class TreeNode {
/**
* id for TreeNode
@@ -59,8 +72,8 @@ export class TreeNode {
public nodeStatus: string;
/**
* Children of this node
*/
* Children of this node
*/
public children: TreeNode[];
@@ -108,8 +121,38 @@ export class TreeNode {
return false;
}
public toNodeInfo(): sqlops.NodeInfo {
return <sqlops.NodeInfo> {
nodePath: this.nodePath,
nodeType: this.nodeTypeId,
nodeSubType: this.nodeSubType,
nodeStatus: this.nodeStatus,
label: this.label,
isLeaf: this.isAlwaysLeaf,
metadata: this.metadata,
errorMessage: this.errorStateMessage
};
}
public getChildren(): Thenable<TreeNode[]> {
return this._objectExplorerCallbacks.getChildren(this);
}
public isExpanded(): Thenable<boolean> {
return this._objectExplorerCallbacks.isExpanded(this);
}
public setExpandedState(expandedState: TreeItemCollapsibleState): Thenable<void> {
return this._objectExplorerCallbacks.setNodeExpandedState(this, expandedState);
}
public setSelected(selected: boolean, clearOtherSelections?: boolean): Thenable<void> {
return this._objectExplorerCallbacks.setNodeSelected(this, selected, clearOtherSelections);
}
constructor(nodeTypeId: string, label: string, isAlwaysLeaf: boolean, nodePath: string,
nodeSubType: string, nodeStatus: string, parent: TreeNode, metadata: sqlops.ObjectMetadata) {
nodeSubType: string, nodeStatus: string, parent: TreeNode, metadata: sqlops.ObjectMetadata,
private _objectExplorerCallbacks: ObjectExplorerCallbacks) {
this.nodeTypeId = nodeTypeId;
this.label = label;
this.isAlwaysLeaf = isAlwaysLeaf;

View File

@@ -74,7 +74,7 @@ export class ServerTreeDataSource implements IDataSource {
if (node.children) {
resolve(node.children);
} else {
this._objectExplorerService.expandTreeNode(node.getSession(), node).then(() => {
this._objectExplorerService.resolveTreeNodeChildren(node.getSession(), node).then(() => {
resolve(node.children);
}, expandError => {
this.showError(expandError);

View File

@@ -28,6 +28,7 @@ import { ICapabilitiesService } from 'sql/services/capabilities/capabilitiesServ
import { Button } from 'sql/base/browser/ui/button/button';
import { attachButtonStyler } from 'sql/common/theme/styler';
import Event, { Emitter } from 'vs/base/common/event';
import { TreeNode, TreeItemCollapsibleState } from 'sql/parts/registeredServer/common/treeNode';
const $ = builder.$;
@@ -428,6 +429,48 @@ export class ServerTreeView {
return this._tree.isDOMFocused();
}
/**
* Set whether the given element is expanded or collapsed
*/
public setExpandedState(element: TreeNode | ConnectionProfile, expandedState: TreeItemCollapsibleState): Thenable<void> {
if (expandedState === TreeItemCollapsibleState.Collapsed) {
return this._tree.collapse(element);
} else if (expandedState === TreeItemCollapsibleState.Expanded) {
return this._tree.expand(element);
}
return Promise.resolve();
}
/**
* Reveal the given element in the tree
*/
public reveal(element: TreeNode | ConnectionProfile): Thenable<void> {
return this._tree.reveal(element);
}
/**
* Select the given element in the tree and clear any other selections
*/
public setSelected(element: TreeNode | ConnectionProfile, selected: boolean, clearOtherSelections: boolean): Thenable<void> {
if (clearOtherSelections || (selected && clearOtherSelections !== false)) {
this._tree.clearSelection();
}
if (selected) {
this._tree.select(element);
return this._tree.reveal(element);
} else {
this._tree.deselect(element);
return Promise.resolve();
}
}
/**
* Check if the given element in the tree is expanded
*/
public isExpanded(element: TreeNode | ConnectionProfile): boolean {
return this._tree.isExpanded(element);
}
/**
* dispose the server tree view
*/

View File

@@ -209,7 +209,7 @@ export class TreeUpdateUtils {
} else {
var rootNode = objectExplorerService.getObjectExplorerNode(connection);
if (rootNode) {
objectExplorerService.expandTreeNode(rootNode.getSession(), rootNode).then(() => {
objectExplorerService.resolveTreeNodeChildren(rootNode.getSession(), rootNode).then(() => {
resolve(rootNode.children);
}, expandError => {
resolve([]);

61
src/sql/sqlops.d.ts vendored
View File

@@ -108,6 +108,67 @@ declare module 'sqlops' {
}
}
/**
* Namespace for interacting with Object Explorer
*/
export namespace objectexplorer {
/**
* Get an Object Explorer node corresponding to the given connection and path. If no path
* is given, it returns the top-level node for the given connection. If there is no node at
* the given path, it returns undefined.
* @param {string} connectionId The id of the connection that the node exists on
* @param {string?} nodePath The path of the node to get
* @returns {ObjectExplorerNode} The node corresponding to the given connection and path,
* or undefined if no such node exists.
*/
export function getNode(connectionId: string, nodePath?: string): Thenable<ObjectExplorerNode>;
/**
* Get all active Object Explorer connection nodes
* @returns {ObjectExplorerNode[]} The Object Explorer nodes for each saved connection
*/
export function getActiveConnectionNodes(): Thenable<ObjectExplorerNode[]>;
/**
* Interface for representing and interacting with items in Object Explorer
*/
export interface ObjectExplorerNode extends NodeInfo {
/**
* The id of the connection that the node exists under
*/
connectionId: string;
/**
* Whether the node is currently expanded in Object Explorer
*/
isExpanded(): Thenable<boolean>;
/**
* Set whether the node is expanded or collapsed
* @param expandedState The new state of the node. If 'None', the node will not be changed
*/
setExpandedState(expandedState: vscode.TreeItemCollapsibleState): Thenable<void>;
/**
* Set whether the node is selected
* @param selected Whether the node should be selected
* @param clearOtherSelections If true, clear any other selections. If false, leave any existing selections.
* Defaults to true when selected is true and false when selected is false.
*/
setSelected(selected: boolean, clearOtherSelections?: boolean): Thenable<void>;
/**
* Get all the child nodes. Returns an empty list if there are no children.
*/
getChildren(): Thenable<ObjectExplorerNode[]>;
/**
* Get the parent node. Returns undefined if there is none.
*/
getParent(): Thenable<ObjectExplorerNode>;
}
}
// EXPORTED INTERFACES /////////////////////////////////////////////////
export interface ConnectionInfo {

View File

@@ -0,0 +1,70 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import { IThreadService } from 'vs/workbench/services/thread/common/threadService';
import { ExtHostObjectExplorerShape, SqlMainContext, MainThreadObjectExplorerShape } from 'sql/workbench/api/node/sqlExtHost.protocol';
import * as sqlops from 'sqlops';
import * as vscode from 'vscode';
export class ExtHostObjectExplorer implements ExtHostObjectExplorerShape {
private _proxy: MainThreadObjectExplorerShape;
constructor(
threadService: IThreadService
) {
this._proxy = threadService.get(SqlMainContext.MainThreadObjectExplorer);
}
public $getNode(connectionId: string, nodePath?: string): Thenable<sqlops.objectexplorer.ObjectExplorerNode> {
return this._proxy.$getNode(connectionId, nodePath).then(nodeInfo => nodeInfo === undefined ? undefined : new ExtHostObjectExplorerNode(nodeInfo, connectionId, this._proxy));
}
public $getActiveConnectionNodes(): Thenable<sqlops.objectexplorer.ObjectExplorerNode[]> {
return this._proxy.$getActiveConnectionNodes().then(results => results.map(result => new ExtHostObjectExplorerNode(result.nodeInfo, result.connectionId, this._proxy)));
}
}
class ExtHostObjectExplorerNode implements sqlops.objectexplorer.ObjectExplorerNode {
public connectionId: string;
public nodePath: string;
public nodeType: string;
public nodeSubType: string;
public nodeStatus: string;
public label: string;
public isLeaf: boolean;
public metadata: sqlops.ObjectMetadata;
public errorMessage: string;
constructor(nodeInfo: sqlops.NodeInfo, connectionId: string, private _proxy: MainThreadObjectExplorerShape) {
Object.entries(nodeInfo).forEach(([key, value]) => this[key] = value);
this.connectionId = connectionId;
}
isExpanded(): Thenable<boolean> {
return this._proxy.$isExpanded(this.connectionId, this.nodePath);
}
setExpandedState(expandedState: vscode.TreeItemCollapsibleState): Thenable<void> {
return this._proxy.$setExpandedState(this.connectionId, this.nodePath, expandedState);
}
setSelected(selected: boolean, clearOtherSelections: boolean = undefined): Thenable<void> {
return this._proxy.$setSelected(this.connectionId, this.nodePath, selected, clearOtherSelections);
}
getChildren(): Thenable<sqlops.objectexplorer.ObjectExplorerNode[]> {
return this._proxy.$getChildren(this.connectionId, this.nodePath).then(children => children.map(nodeInfo => new ExtHostObjectExplorerNode(nodeInfo, this.connectionId, this._proxy)));
}
getParent(): Thenable<sqlops.objectexplorer.ObjectExplorerNode> {
let parentPathEndIndex = this.nodePath.lastIndexOf('/');
if (parentPathEndIndex === -1) {
return Promise.resolve(undefined);
}
return this._proxy.$getNode(this.connectionId, this.nodePath.slice(0, parentPathEndIndex)).then(nodeInfo => nodeInfo ? new ExtHostObjectExplorerNode(nodeInfo, this.connectionId, this._proxy) : undefined);
}
}

View File

@@ -0,0 +1,72 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import { SqlExtHostContext, SqlMainContext, ExtHostObjectExplorerShape, MainThreadObjectExplorerShape } from 'sql/workbench/api/node/sqlExtHost.protocol';
import * as sqlops from 'sqlops';
import * as vscode from 'vscode';
import { IExtHostContext } from 'vs/workbench/api/node/extHost.protocol';
import { extHostNamedCustomer } from 'vs/workbench/api/electron-browser/extHostCustomers';
import { IConnectionManagementService } from 'sql/parts/connection/common/connectionManagement';
import { IObjectExplorerService, NodeInfoWithConnection } from 'sql/parts/registeredServer/common/objectExplorerService';
import { IWorkbenchEditorService } from 'vs/workbench/services/editor/common/editorService';
import * as TaskUtilities from 'sql/workbench/common/taskUtilities';
import { IConnectionProfile } from 'sql/parts/connection/common/interfaces';
import { dispose, IDisposable } from 'vs/base/common/lifecycle';
@extHostNamedCustomer(SqlMainContext.MainThreadObjectExplorer)
export class MainThreadObjectExplorer implements MainThreadObjectExplorerShape {
private _proxy: ExtHostObjectExplorerShape;
private _toDispose: IDisposable[];
constructor(
extHostContext: IExtHostContext,
@IConnectionManagementService private _connectionManagementService: IConnectionManagementService,
@IObjectExplorerService private _objectExplorerService: IObjectExplorerService,
@IWorkbenchEditorService private _workbenchEditorService: IWorkbenchEditorService
) {
if (extHostContext) {
this._proxy = extHostContext.get(SqlExtHostContext.ExtHostObjectExplorer);
}
this._toDispose = [];
}
public dispose(): void {
this._toDispose = dispose(this._toDispose);
}
public $getNode(connectionId: string, nodePath?: string): Thenable<sqlops.NodeInfo> {
return this._objectExplorerService.getTreeNode(connectionId, nodePath).then(treeNode => {
if (!treeNode) {
return undefined;
}
return treeNode.toNodeInfo();
});
}
public $getActiveConnectionNodes(): Thenable<NodeInfoWithConnection[]> {
let connectionNodes = this._objectExplorerService.getActiveConnectionNodes();
return Promise.resolve(connectionNodes.map(node => {
return {connectionId: node.connection.id, nodeInfo: node.toNodeInfo()};
}));
}
public $setExpandedState(connectionId: string, nodePath: string, expandedState: vscode.TreeItemCollapsibleState): Thenable<void> {
return this._objectExplorerService.getTreeNode(connectionId, nodePath).then(treeNode => treeNode.setExpandedState(expandedState));
}
public $setSelected(connectionId: string, nodePath: string, selected: boolean, clearOtherSelections: boolean = undefined): Thenable<void> {
return this._objectExplorerService.getTreeNode(connectionId, nodePath).then(treeNode => treeNode.setSelected(selected, clearOtherSelections));
}
public $getChildren(connectionId: string, nodePath: string): Thenable<sqlops.NodeInfo[]> {
return this._objectExplorerService.getTreeNode(connectionId, nodePath).then(treeNode => treeNode.getChildren().then(children => children.map(node => node.toNodeInfo())));
}
public $isExpanded(connectionId: string, nodePath: string): Thenable<boolean> {
return this._objectExplorerService.getTreeNode(connectionId, nodePath).then(treeNode => treeNode.isExpanded());
}
}

View File

@@ -32,6 +32,7 @@ import { IExtensionApiFactory } from 'vs/workbench/api/node/extHost.api.impl';
import { ExtHostDashboardWebviews } from 'sql/workbench/api/node/extHostDashboardWebview';
import { ExtHostConnectionManagement } from 'sql/workbench/api/node/extHostConnectionManagement';
import { ExtHostDashboard } from 'sql/workbench/api/node/extHostDashboard';
import { ExtHostObjectExplorer } from 'sql/workbench/api/node/extHostObjectExplorer';
export interface ISqlExtensionApiFactory {
vsCodeFactory(extension: IExtensionDescription): typeof vscode;
@@ -56,6 +57,7 @@ export function createApiFactory(
const extHostConnectionManagement = threadService.set(SqlExtHostContext.ExtHostConnectionManagement, new ExtHostConnectionManagement(threadService));
const extHostCredentialManagement = threadService.set(SqlExtHostContext.ExtHostCredentialManagement, new ExtHostCredentialManagement(threadService));
const extHostDataProvider = threadService.set(SqlExtHostContext.ExtHostDataProtocol, new ExtHostDataProtocol(threadService));
const extHostObjectExplorer = threadService.set(SqlExtHostContext.ExtHostObjectExplorer, new ExtHostObjectExplorer(threadService));
const extHostSerializationProvider = threadService.set(SqlExtHostContext.ExtHostSerializationProvider, new ExtHostSerializationProvider(threadService));
const extHostResourceProvider = threadService.set(SqlExtHostContext.ExtHostResourceProvider, new ExtHostResourceProvider(threadService));
const extHostModalDialogs = threadService.set(SqlExtHostContext.ExtHostModalDialogs, new ExtHostModalDialogs(threadService));
@@ -105,6 +107,16 @@ export function createApiFactory(
}
};
// namespace: objectexplorer
const objectExplorer: typeof sqlops.objectexplorer = {
getNode(connectionId: string, nodePath?: string): Thenable<sqlops.objectexplorer.ObjectExplorerNode> {
return extHostObjectExplorer.$getNode(connectionId, nodePath);
},
getActiveConnectionNodes(): Thenable<sqlops.objectexplorer.ObjectExplorerNode[]> {
return extHostObjectExplorer.$getActiveConnectionNodes();
}
};
// namespace: serialization
const serialization: typeof sqlops.serialization = {
registerProvider(provider: sqlops.SerializationProvider): vscode.Disposable {
@@ -286,6 +298,7 @@ export function createApiFactory(
accounts,
connection,
credentials,
objectexplorer: objectExplorer,
resources,
serialization,
dataprotocol,

View File

@@ -13,6 +13,7 @@ import { IInstantiationService } from 'vs/platform/instantiation/common/instanti
import 'sql/workbench/api/node/mainThreadConnectionManagement';
import 'sql/workbench/api/node/mainThreadCredentialManagement';
import 'sql/workbench/api/node/mainThreadDataProtocol';
import 'sql/workbench/api/node/mainThreadObjectExplorer';
import 'sql/workbench/api/node/mainThreadSerializationProvider';
import 'sql/workbench/api/node/mainThreadResourceProvider';
import 'sql/workbench/api/electron-browser/mainThreadTasks';

View File

@@ -13,6 +13,7 @@ import { TPromise } from 'vs/base/common/winjs.base';
import { IDisposable } from 'vs/base/common/lifecycle';
import * as sqlops from 'sqlops';
import * as vscode from 'vscode';
import { ITaskHandlerDescription } from 'sql/platform/tasks/common/tasks';
@@ -305,7 +306,6 @@ export abstract class ExtHostDataProtocolShape {
$stopSession(handle: number, sessionId: string): Thenable<boolean> { throw ni(); }
}
/**
* ResourceProvider extension host class.
*/
@@ -419,6 +419,7 @@ export const SqlMainContext = {
MainThreadConnectionManagement: createMainId<MainThreadConnectionManagementShape>('MainThreadConnectionManagement'),
MainThreadCredentialManagement: createMainId<MainThreadCredentialManagementShape>('MainThreadCredentialManagement'),
MainThreadDataProtocol: createMainId<MainThreadDataProtocolShape>('MainThreadDataProtocol'),
MainThreadObjectExplorer: createMainId<MainThreadObjectExplorerShape>('MainThreadObjectExplorer'),
MainThreadSerializationProvider: createMainId<MainThreadSerializationProviderShape>('MainThreadSerializationProvider'),
MainThreadResourceProvider: createMainId<MainThreadResourceProviderShape>('MainThreadResourceProvider'),
MainThreadModalDialog: createMainId<MainThreadModalDialogShape>('MainThreadModalDialog'),
@@ -432,6 +433,7 @@ export const SqlExtHostContext = {
ExtHostConnectionManagement: createExtId<ExtHostConnectionManagementShape>('ExtHostConnectionManagement'),
ExtHostCredentialManagement: createExtId<ExtHostCredentialManagementShape>('ExtHostCredentialManagement'),
ExtHostDataProtocol: createExtId<ExtHostDataProtocolShape>('ExtHostDataProtocol'),
ExtHostObjectExplorer: createExtId<ExtHostObjectExplorerShape>('ExtHostObjectExplorer'),
ExtHostSerializationProvider: createExtId<ExtHostSerializationProviderShape>('ExtHostSerializationProvider'),
ExtHostResourceProvider: createExtId<ExtHostResourceProviderShape>('ExtHostResourceProvider'),
ExtHostModalDialogs: createExtId<ExtHostModalDialogsShape>('ExtHostModalDialogs'),
@@ -485,3 +487,15 @@ export interface MainThreadDashboardWebviewShape extends IDisposable {
$registerProvider(widgetId: string);
$setHtml(handle: number, value: string);
}
export interface ExtHostObjectExplorerShape {
}
export interface MainThreadObjectExplorerShape extends IDisposable {
$getNode(connectionId: string, nodePath?: string): Thenable<sqlops.NodeInfo>;
$getActiveConnectionNodes(): Thenable<{ nodeInfo: sqlops.NodeInfo, connectionId: string}[]>;
$setExpandedState(connectionId: string, nodePath: string, expandedState: vscode.TreeItemCollapsibleState): Thenable<void>;
$setSelected(connectionId: string, nodePath: string, selected: boolean, clearOtherSelections?: boolean): Thenable<void>;
$getChildren(connectionId: string, nodePath: string): Thenable<sqlops.NodeInfo[]>;
$isExpanded(connectionId: string, nodePath: string): Thenable<boolean>;
}