mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-01-26 09:35:38 -05:00
SQL Operations Studio Public Preview 1 (0.23) release source code
This commit is contained in:
39
src/vs/workbench/services/extensions/node/barrier.ts
Normal file
39
src/vs/workbench/services/extensions/node/barrier.ts
Normal file
@@ -0,0 +1,39 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* 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 { TPromise } from 'vs/base/common/winjs.base';
|
||||
|
||||
/**
|
||||
* A barrier that is initially closed and then becomes opened permanently.
|
||||
*/
|
||||
export class Barrier {
|
||||
|
||||
private _isOpen: boolean;
|
||||
private _promise: TPromise<boolean>;
|
||||
private _completePromise: (v: boolean) => void;
|
||||
|
||||
constructor() {
|
||||
this._isOpen = false;
|
||||
this._promise = new TPromise<boolean>((c, e, p) => {
|
||||
this._completePromise = c;
|
||||
}, () => {
|
||||
console.warn('You should really not try to cancel this ready promise!');
|
||||
});
|
||||
}
|
||||
|
||||
public isOpen(): boolean {
|
||||
return this._isOpen;
|
||||
}
|
||||
|
||||
public open(): void {
|
||||
this._isOpen = true;
|
||||
this._completePromise(true);
|
||||
}
|
||||
|
||||
public wait(): TPromise<boolean> {
|
||||
return this._promise;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* 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 { IExtensionDescription } from 'vs/platform/extensions/common/extensions';
|
||||
|
||||
const hasOwnProperty = Object.hasOwnProperty;
|
||||
|
||||
export class ExtensionDescriptionRegistry {
|
||||
private _extensionsMap: { [extensionId: string]: IExtensionDescription; };
|
||||
private _extensionsArr: IExtensionDescription[];
|
||||
private _activationMap: { [activationEvent: string]: IExtensionDescription[]; };
|
||||
|
||||
constructor(extensionDescriptions: IExtensionDescription[]) {
|
||||
this._extensionsMap = {};
|
||||
this._extensionsArr = [];
|
||||
this._activationMap = {};
|
||||
|
||||
for (let i = 0, len = extensionDescriptions.length; i < len; i++) {
|
||||
let extensionDescription = extensionDescriptions[i];
|
||||
|
||||
if (hasOwnProperty.call(this._extensionsMap, extensionDescription.id)) {
|
||||
// No overwriting allowed!
|
||||
console.error('Extension `' + extensionDescription.id + '` is already registered');
|
||||
continue;
|
||||
}
|
||||
|
||||
this._extensionsMap[extensionDescription.id] = extensionDescription;
|
||||
this._extensionsArr.push(extensionDescription);
|
||||
|
||||
if (Array.isArray(extensionDescription.activationEvents)) {
|
||||
for (let j = 0, lenJ = extensionDescription.activationEvents.length; j < lenJ; j++) {
|
||||
let activationEvent = extensionDescription.activationEvents[j];
|
||||
this._activationMap[activationEvent] = this._activationMap[activationEvent] || [];
|
||||
this._activationMap[activationEvent].push(extensionDescription);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public containsActivationEvent(activationEvent: string): boolean {
|
||||
return hasOwnProperty.call(this._activationMap, activationEvent);
|
||||
}
|
||||
|
||||
public getExtensionDescriptionsForActivationEvent(activationEvent: string): IExtensionDescription[] {
|
||||
if (!hasOwnProperty.call(this._activationMap, activationEvent)) {
|
||||
return [];
|
||||
}
|
||||
return this._activationMap[activationEvent].slice(0);
|
||||
}
|
||||
|
||||
public getAllExtensionDescriptions(): IExtensionDescription[] {
|
||||
return this._extensionsArr.slice(0);
|
||||
}
|
||||
|
||||
public getExtensionDescription(extensionId: string): IExtensionDescription {
|
||||
if (!hasOwnProperty.call(this._extensionsMap, extensionId)) {
|
||||
return null;
|
||||
}
|
||||
return this._extensionsMap[extensionId];
|
||||
}
|
||||
}
|
||||
110
src/vs/workbench/services/extensions/node/lazyPromise.ts
Normal file
110
src/vs/workbench/services/extensions/node/lazyPromise.ts
Normal file
@@ -0,0 +1,110 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* 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 { TPromise, ValueCallback, ErrorCallback } from 'vs/base/common/winjs.base';
|
||||
|
||||
export class LazyPromise {
|
||||
|
||||
private _onCancel: () => void;
|
||||
|
||||
private _actual: TPromise<any>;
|
||||
private _actualOk: ValueCallback;
|
||||
private _actualErr: ErrorCallback;
|
||||
|
||||
private _hasValue: boolean;
|
||||
private _value: any;
|
||||
|
||||
private _hasErr: boolean;
|
||||
private _err: any;
|
||||
|
||||
private _isCanceled: boolean;
|
||||
|
||||
constructor(onCancel: () => void) {
|
||||
this._onCancel = onCancel;
|
||||
this._actual = null;
|
||||
this._actualOk = null;
|
||||
this._actualErr = null;
|
||||
this._hasValue = false;
|
||||
this._value = null;
|
||||
this._hasErr = false;
|
||||
this._err = null;
|
||||
this._isCanceled = false;
|
||||
}
|
||||
|
||||
private _ensureActual(): TPromise<any> {
|
||||
if (!this._actual) {
|
||||
this._actual = new TPromise<any>((c, e) => {
|
||||
this._actualOk = c;
|
||||
this._actualErr = e;
|
||||
}, this._onCancel);
|
||||
|
||||
if (this._hasValue) {
|
||||
this._actualOk(this._value);
|
||||
}
|
||||
|
||||
if (this._hasErr) {
|
||||
this._actualErr(this._err);
|
||||
}
|
||||
}
|
||||
return this._actual;
|
||||
}
|
||||
|
||||
public resolveOk(value: any): void {
|
||||
if (this._isCanceled || this._hasErr) {
|
||||
return;
|
||||
}
|
||||
|
||||
this._hasValue = true;
|
||||
this._value = value;
|
||||
|
||||
if (this._actual) {
|
||||
this._actualOk(value);
|
||||
}
|
||||
}
|
||||
|
||||
public resolveErr(err: any): void {
|
||||
if (this._isCanceled || this._hasValue) {
|
||||
return;
|
||||
}
|
||||
|
||||
this._hasErr = true;
|
||||
this._err = err;
|
||||
|
||||
if (this._actual) {
|
||||
this._actualErr(err);
|
||||
}
|
||||
}
|
||||
|
||||
public then(success: any, error: any): any {
|
||||
if (this._isCanceled) {
|
||||
return;
|
||||
}
|
||||
|
||||
return this._ensureActual().then(success, error);
|
||||
}
|
||||
|
||||
public done(success: any, error: any): void {
|
||||
if (this._isCanceled) {
|
||||
return;
|
||||
}
|
||||
|
||||
this._ensureActual().done(success, error);
|
||||
}
|
||||
|
||||
public cancel(): void {
|
||||
if (this._hasValue || this._hasErr) {
|
||||
return;
|
||||
}
|
||||
|
||||
this._isCanceled = true;
|
||||
|
||||
if (this._actual) {
|
||||
this._actual.cancel();
|
||||
} else {
|
||||
this._onCancel();
|
||||
}
|
||||
}
|
||||
}
|
||||
198
src/vs/workbench/services/extensions/node/rpcProtocol.ts
Normal file
198
src/vs/workbench/services/extensions/node/rpcProtocol.ts
Normal file
@@ -0,0 +1,198 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* 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 { TPromise } from 'vs/base/common/winjs.base';
|
||||
import * as marshalling from 'vs/base/common/marshalling';
|
||||
import * as errors from 'vs/base/common/errors';
|
||||
import { IMessagePassingProtocol } from 'vs/base/parts/ipc/common/ipc';
|
||||
import { LazyPromise } from 'vs/workbench/services/extensions/node/lazyPromise';
|
||||
|
||||
export interface IDispatcher {
|
||||
invoke(proxyId: string, methodName: string, args: any[]): any;
|
||||
}
|
||||
|
||||
export class RPCProtocol {
|
||||
|
||||
private _isDisposed: boolean;
|
||||
private _bigHandler: IDispatcher;
|
||||
private _lastMessageId: number;
|
||||
private readonly _invokedHandlers: { [req: string]: TPromise<any>; };
|
||||
private readonly _pendingRPCReplies: { [msgId: string]: LazyPromise; };
|
||||
private readonly _multiplexor: RPCMultiplexer;
|
||||
|
||||
constructor(protocol: IMessagePassingProtocol) {
|
||||
this._isDisposed = false;
|
||||
this._bigHandler = null;
|
||||
this._lastMessageId = 0;
|
||||
this._invokedHandlers = Object.create(null);
|
||||
this._pendingRPCReplies = {};
|
||||
this._multiplexor = new RPCMultiplexer(protocol, (msg) => this._receiveOneMessage(msg));
|
||||
}
|
||||
|
||||
public dispose(): void {
|
||||
this._isDisposed = true;
|
||||
|
||||
// Release all outstanding promises with a canceled error
|
||||
Object.keys(this._pendingRPCReplies).forEach((msgId) => {
|
||||
const pending = this._pendingRPCReplies[msgId];
|
||||
pending.resolveErr(errors.canceled());
|
||||
});
|
||||
}
|
||||
|
||||
private _receiveOneMessage(rawmsg: string): void {
|
||||
if (this._isDisposed) {
|
||||
console.warn('Received message after being shutdown: ', rawmsg);
|
||||
return;
|
||||
}
|
||||
let msg = marshalling.parse(rawmsg);
|
||||
|
||||
if (msg.seq) {
|
||||
if (!this._pendingRPCReplies.hasOwnProperty(msg.seq)) {
|
||||
console.warn('Got reply to unknown seq');
|
||||
return;
|
||||
}
|
||||
let reply = this._pendingRPCReplies[msg.seq];
|
||||
delete this._pendingRPCReplies[msg.seq];
|
||||
|
||||
if (msg.err) {
|
||||
let err = msg.err;
|
||||
if (msg.err.$isError) {
|
||||
err = new Error();
|
||||
err.name = msg.err.name;
|
||||
err.message = msg.err.message;
|
||||
err.stack = msg.err.stack;
|
||||
}
|
||||
reply.resolveErr(err);
|
||||
return;
|
||||
}
|
||||
|
||||
reply.resolveOk(msg.res);
|
||||
return;
|
||||
}
|
||||
|
||||
if (msg.cancel) {
|
||||
if (this._invokedHandlers[msg.cancel]) {
|
||||
this._invokedHandlers[msg.cancel].cancel();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (msg.err) {
|
||||
console.error(msg.err);
|
||||
return;
|
||||
}
|
||||
|
||||
let rpcId = msg.rpcId;
|
||||
|
||||
if (!this._bigHandler) {
|
||||
throw new Error('got message before big handler attached!');
|
||||
}
|
||||
|
||||
let req = msg.req;
|
||||
|
||||
this._invokedHandlers[req] = this._invokeHandler(rpcId, msg.method, msg.args);
|
||||
|
||||
this._invokedHandlers[req].then((r) => {
|
||||
delete this._invokedHandlers[req];
|
||||
this._multiplexor.send(MessageFactory.replyOK(req, r));
|
||||
}, (err) => {
|
||||
delete this._invokedHandlers[req];
|
||||
this._multiplexor.send(MessageFactory.replyErr(req, err));
|
||||
});
|
||||
}
|
||||
|
||||
private _invokeHandler(proxyId: string, methodName: string, args: any[]): TPromise<any> {
|
||||
try {
|
||||
return TPromise.as(this._bigHandler.invoke(proxyId, methodName, args));
|
||||
} catch (err) {
|
||||
return TPromise.wrapError(err);
|
||||
}
|
||||
}
|
||||
|
||||
public callOnRemote(proxyId: string, methodName: string, args: any[]): TPromise<any> {
|
||||
if (this._isDisposed) {
|
||||
return TPromise.wrapError<any>(errors.canceled());
|
||||
}
|
||||
|
||||
let req = String(++this._lastMessageId);
|
||||
let result = new LazyPromise(() => {
|
||||
this._multiplexor.send(MessageFactory.cancel(req));
|
||||
});
|
||||
|
||||
this._pendingRPCReplies[req] = result;
|
||||
|
||||
this._multiplexor.send(MessageFactory.request(req, proxyId, methodName, args));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public setDispatcher(handler: IDispatcher): void {
|
||||
this._bigHandler = handler;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends/Receives multiple messages in one go:
|
||||
* - multiple messages to be sent from one stack get sent in bulk at `process.nextTick`.
|
||||
* - each incoming message is handled in a separate `process.nextTick`.
|
||||
*/
|
||||
class RPCMultiplexer {
|
||||
|
||||
private readonly _protocol: IMessagePassingProtocol;
|
||||
private readonly _sendAccumulatedBound: () => void;
|
||||
|
||||
private _messagesToSend: string[];
|
||||
|
||||
constructor(protocol: IMessagePassingProtocol, onMessage: (msg: string) => void) {
|
||||
this._protocol = protocol;
|
||||
this._sendAccumulatedBound = this._sendAccumulated.bind(this);
|
||||
|
||||
this._messagesToSend = [];
|
||||
|
||||
this._protocol.onMessage(data => {
|
||||
for (let i = 0, len = data.length; i < len; i++) {
|
||||
onMessage(data[i]);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private _sendAccumulated(): void {
|
||||
const tmp = this._messagesToSend;
|
||||
this._messagesToSend = [];
|
||||
this._protocol.send(tmp);
|
||||
}
|
||||
|
||||
public send(msg: string): void {
|
||||
if (this._messagesToSend.length === 0) {
|
||||
process.nextTick(this._sendAccumulatedBound);
|
||||
}
|
||||
this._messagesToSend.push(msg);
|
||||
}
|
||||
}
|
||||
|
||||
class MessageFactory {
|
||||
public static cancel(req: string): string {
|
||||
return `{"cancel":"${req}"}`;
|
||||
}
|
||||
|
||||
public static request(req: string, rpcId: string, method: string, args: any[]): string {
|
||||
return `{"req":"${req}","rpcId":"${rpcId}","method":"${method}","args":${marshalling.stringify(args)}}`;
|
||||
}
|
||||
|
||||
public static replyOK(req: string, res: any): string {
|
||||
if (typeof res === 'undefined') {
|
||||
return `{"seq":"${req}"}`;
|
||||
}
|
||||
return `{"seq":"${req}","res":${marshalling.stringify(res)}}`;
|
||||
}
|
||||
|
||||
public static replyErr(req: string, err: any): string {
|
||||
if (typeof err === 'undefined') {
|
||||
return `{"seq":"${req}","err":null}`;
|
||||
}
|
||||
return `{"seq":"${req}","err":${marshalling.stringify(errors.transformErrorForSerialization(err))}}`;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user