提交 b457326a 编写于 作者: A Alex Dima

Remove no longer used code (due to vs/languages removal)

上级 8a6b8fd5
......@@ -30,7 +30,7 @@ var editorEntryPoints = [
prepend: [ 'vs/loader.js' ],
append: [ 'vs/base/worker/workerMain' ],
dest: 'vs/base/worker/workerMain.js'
},
}
];
var editorResources = [
......
......@@ -46,8 +46,6 @@ const builtInExtensions = [
const vscodeEntryPoints = _.flatten([
buildfile.entrypoint('vs/workbench/workbench.main'),
buildfile.base,
buildfile.editor,
buildfile.languages,
buildfile.workbench,
buildfile.code
]);
......@@ -60,8 +58,6 @@ const vscodeResources = [
'out-build/paths.js',
'out-build/vs/**/*.{svg,png,cur}',
'out-build/vs/base/node/{stdForkStart.js,terminateProcess.sh}',
'out-build/vs/base/worker/workerMainCompatibility.html',
'out-build/vs/base/worker/workerMain.{js,js.map}',
'out-build/vs/base/browser/ui/octiconLabel/octicons/**',
'out-build/vs/workbench/browser/media/*-theme.css',
'out-build/vs/workbench/electron-browser/bootstrap/**',
......
......@@ -3,9 +3,13 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
exports.base = require('./vs/base/buildfile').collectModules();
exports.editor = require('./vs/editor/buildfile').collectModules();
exports.languages = [];
exports.base = [{
name: 'vs/base/common/worker/simpleWorker',
include: [ 'vs/editor/common/services/editorSimpleWorker' ],
prepend: [ 'vs/loader.js' ],
append: [ 'vs/base/worker/workerMain' ],
dest: 'vs/base/worker/workerMain.js'
}];
exports.workbench = require('./vs/workbench/buildfile').collectModules(['vs/workbench/workbench.main']);
exports.code = require('./vs/code/buildfile').collectModules();
......
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
exports.collectModules = function() {
return [{
name: 'vs/base/common/worker/workerServer',
include: [ 'vs/editor/common/worker/editorWorkerServer' ],
exclude: [ 'vs/css', 'vs/nls' ]
}, {
name: 'vs/base/common/worker/simpleWorker',
include: [ 'vs/editor/common/services/editorSimpleWorker' ],
exclude: [ 'vs/css', 'vs/nls' ]
}];
};
......@@ -7,11 +7,38 @@
import {transformErrorForSerialization} from 'vs/base/common/errors';
import {Disposable} from 'vs/base/common/lifecycle';
import {ErrorCallback, TPromise, ValueCallback} from 'vs/base/common/winjs.base';
import {IWorker, IWorkerFactory} from './workerClient';
import {ShallowCancelThenPromise} from 'vs/base/common/async';
import {isWeb} from 'vs/base/common/platform';
const INITIALIZE = '$initialize';
export interface IWorker {
getId():number;
postMessage(message:string):void;
dispose():void;
}
export interface IWorkerCallback {
(message:string):void;
}
export interface IWorkerFactory {
create(moduleId:string, callback:IWorkerCallback, onErrorCallback:(err:any)=>void):IWorker;
}
let webWorkerWarningLogged = false;
export function logOnceWebWorkerWarning(err: any): void {
if (!isWeb) {
// running tests
return;
}
if (!webWorkerWarningLogged) {
webWorkerWarningLogged = true;
console.warn('Could not create web worker(s). Falling back to loading web worker code in main thread, which might cause UI freezes. Please see https://github.com/Microsoft/monaco-editor#faq');
}
console.warn(err.message);
}
interface IMessage {
vsWorker: number;
req?: string;
......@@ -308,7 +335,6 @@ export class SimpleWorkerServer {
private initialize(workerId: number, moduleId: string, loaderConfig:any): TPromise<any> {
this._protocol.setWorkerId(workerId);
// TODO@Alex: share this code with workerServer
if (loaderConfig) {
// Remove 'baseUrl', handling it is beyond scope for now
if (typeof loaderConfig.baseUrl !== 'undefined') {
......
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import {onUnexpectedError} from 'vs/base/common/errors';
import {parse, stringify} from 'vs/base/common/marshalling';
import {TPromise} from 'vs/base/common/winjs.base';
import * as workerProtocol from 'vs/base/common/worker/workerProtocol';
import {isWeb} from 'vs/base/common/platform';
export interface IWorker {
getId():number;
postMessage(message:string):void;
dispose():void;
}
let webWorkerWarningLogged = false;
export function logOnceWebWorkerWarning(err: any): void {
if (!isWeb) {
// running tests
return;
}
if (!webWorkerWarningLogged) {
webWorkerWarningLogged = true;
console.warn('Could not create web worker(s). Falling back to loading web worker code in main thread, which might cause UI freezes. Please see https://github.com/Microsoft/monaco-editor#faq');
}
console.warn(err.message);
}
export interface IWorkerCallback {
(message:string):void;
}
export interface IWorkerFactory {
create(moduleId:string, callback:IWorkerCallback, onErrorCallback:(err:any)=>void):IWorker;
}
interface IActiveRequest {
complete:(value:any)=>void;
error:(err:any)=>void;
progress:(progress:any)=>void;
type:string;
payload:any;
}
export class WorkerClient {
private _lastMessageId:number;
private _promises:{[id:string]:IActiveRequest;};
private _worker:IWorker;
private _messagesQueue:workerProtocol.IClientMessage[];
private _processQueueTimeout:number;
private _waitingForWorkerReply:boolean;
public onModuleLoaded:TPromise<void>;
constructor(workerFactory:IWorkerFactory, moduleId:string) {
this._lastMessageId = 0;
this._promises = {};
this._messagesQueue = [];
this._processQueueTimeout = -1;
this._waitingForWorkerReply = false;
this._worker = workerFactory.create(
'vs/base/common/worker/workerServer',
(msg) => this._onSerializedMessage(msg),
(err) => {
// reject the onModuleLoaded promise, this signals that things are bad
let promiseEntry:IActiveRequest = this._promises[1];
delete this._promises[1];
promiseEntry.error(err);
});
let loaderConfiguration:any = null;
let globalRequire = (<any>window).require;
if (typeof globalRequire.getConfig === 'function') {
// Get the configuration from the Monaco AMD Loader
loaderConfiguration = globalRequire.getConfig();
} else if (typeof (<any>window).requirejs !== 'undefined') {
// Get the configuration from requirejs
loaderConfiguration = (<any>window).requirejs.s.contexts._.config;
}
this.onModuleLoaded = this._sendMessage(workerProtocol.MessageType.INITIALIZE, {
id: this._worker.getId(),
moduleId: moduleId,
loaderConfiguration: loaderConfiguration
});
}
public request(requestName:string, payload:any): TPromise<any> {
if (requestName.charAt(0) === '$') {
throw new Error('Illegal requestName: ' + requestName);
}
let shouldCancelPromise = false,
messagePromise:TPromise<any>;
return new TPromise<any>((c, e, p) => {
// hide the initialize promise inside this
// promise so that it won't be canceled by accident
this.onModuleLoaded.then(() => {
if (!shouldCancelPromise) {
messagePromise = this._sendMessage(requestName, payload).then(c, e, p);
}
}, e, p);
}, () => {
// forward cancel to the proper promise
if(messagePromise) {
messagePromise.cancel();
} else {
shouldCancelPromise = true;
}
});
}
public dispose(): void {
let promises = Object.keys(this._promises);
if (promises.length > 0) {
console.warn('Terminating a worker with ' + promises.length + ' pending promises:');
console.warn(this._promises);
for (let id in this._promises) {
if (promises.hasOwnProperty(id)) {
this._promises[id].error('Worker forcefully terminated');
}
}
}
this._worker.dispose();
}
private _sendMessage(type:string, payload:any):TPromise<any> {
let msg = {
id: ++this._lastMessageId,
type: type,
timestamp: Date.now(),
payload: payload
};
let pc:(value:any)=>void, pe:(err:any)=>void, pp:(progress:any)=>void;
let promise = new TPromise<any>((c, e, p) => {
pc = c;
pe = e;
pp = p;
}, () => {
this._removeMessage(msg.id);
}
);
this._promises[msg.id] = {
complete: pc,
error: pe,
progress: pp,
type: type,
payload: payload
};
this._enqueueMessage(msg);
return promise;
}
private _enqueueMessage(msg:workerProtocol.IClientMessage): void {
let lastIndexSmallerOrEqual = -1,
i:number;
// Find the right index to insert at - keep the queue ordered by timestamp
for (i = this._messagesQueue.length - 1; i >= 0; i--) {
if (this._messagesQueue[i].timestamp <= msg.timestamp) {
lastIndexSmallerOrEqual = i;
break;
}
}
this._messagesQueue.splice(lastIndexSmallerOrEqual + 1, 0, msg);
this._processMessagesQueue();
}
private _removeMessage(msgId:number): void {
for (let i = 0, len = this._messagesQueue.length; i < len; i++) {
if (this._messagesQueue[i].id === msgId) {
if (this._promises.hasOwnProperty(String(msgId))) {
delete this._promises[String(msgId)];
}
this._messagesQueue.splice(i, 1);
this._processMessagesQueue();
return;
}
}
}
private _processMessagesQueue(): void {
if (this._processQueueTimeout !== -1) {
clearTimeout(this._processQueueTimeout);
this._processQueueTimeout = -1;
}
if (this._messagesQueue.length === 0) {
return;
}
if (this._waitingForWorkerReply) {
return;
}
let delayUntilNextMessage = this._messagesQueue[0].timestamp - (new Date()).getTime();
delayUntilNextMessage = Math.max(0, delayUntilNextMessage);
this._processQueueTimeout = setTimeout(() => {
this._processQueueTimeout = -1;
if (this._messagesQueue.length === 0) {
return;
}
this._waitingForWorkerReply = true;
let msg = this._messagesQueue.shift();
this._postMessage(msg);
}, delayUntilNextMessage);
}
private _postMessage(msg:any): void {
if (this._worker) {
this._worker.postMessage(stringify(msg));
}
}
private _onSerializedMessage(msg:string): void {
let message:workerProtocol.IServerMessage = null;
try {
message = parse(msg);
} catch (e) {
// nothing
}
if (message) {
this._onmessage(message);
}
}
private _onmessage(msg:workerProtocol.IServerMessage): void {
if (!msg.monacoWorker) {
return;
}
if (msg.from && msg.from !== this._worker.getId()) {
return;
}
switch (msg.type) {
case workerProtocol.MessageType.REPLY:
let serverReplyMessage = <workerProtocol.IServerReplyMessage>msg;
this._waitingForWorkerReply = false;
if (!this._promises.hasOwnProperty(String(serverReplyMessage.id))) {
this._onError('Received unexpected message from Worker:', msg);
return;
}
switch (serverReplyMessage.action) {
case workerProtocol.ReplyType.COMPLETE:
this._promises[serverReplyMessage.id].complete(serverReplyMessage.payload);
delete this._promises[serverReplyMessage.id];
break;
case workerProtocol.ReplyType.ERROR:
this._onError('Main Thread sent to worker the following message:', {
type: this._promises[serverReplyMessage.id].type,
payload: this._promises[serverReplyMessage.id].payload
});
this._onError('And the worker replied with an error:', serverReplyMessage.payload);
onUnexpectedError(serverReplyMessage.payload);
this._promises[serverReplyMessage.id].error(serverReplyMessage.payload);
delete this._promises[serverReplyMessage.id];
break;
case workerProtocol.ReplyType.PROGRESS:
this._promises[serverReplyMessage.id].progress(serverReplyMessage.payload);
break;
}
break;
case workerProtocol.MessageType.PRINT:
let serverPrintMessage = <workerProtocol.IServerPrintMessage>msg;
this._consoleLog(serverPrintMessage.level, serverPrintMessage.payload);
break;
default:
this._onError('Received unexpected message from worker:', msg);
}
this._processMessagesQueue();
}
_consoleLog(level:string, payload:any): void {
switch (level) {
case workerProtocol.PrintType.LOG:
console.log(payload);
break;
case workerProtocol.PrintType.DEBUG:
console.info(payload);
break;
case workerProtocol.PrintType.INFO:
console.info(payload);
break;
case workerProtocol.PrintType.WARN:
console.warn(payload);
break;
case workerProtocol.PrintType.ERROR:
console.error(payload);
break;
default:
this._onError('Received unexpected message from Worker:', payload);
}
}
_onError(message:string, error?:any): void {
console.error(message);
console.info(error);
}
}
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
/**
* A message sent from the UI thread to a worker
*/
export interface IClientMessage {
id:number;
type:string;
timestamp:number;
payload:any;
}
/**
* A message sent from a worker to the UI thread
*/
export interface IServerMessage {
monacoWorker:boolean;
from:number;
req:string;
type:string;
payload:any;
}
/**
* A message sent from a worker to the UI thread in reply to a UI thread request
*/
export interface IServerReplyMessage extends IServerMessage {
id:number;
action:string;
}
/**
* A message sent from a worker to the UI thread for debugging purposes (console.log, console.info, etc.)
*/
export interface IServerPrintMessage extends IServerMessage {
level:string;
}
export var MessageType = {
INITIALIZE: '$initialize',
REPLY: '$reply',
PRINT: '$print'
};
export var ReplyType = {
COMPLETE: 'complete',
ERROR: 'error',
PROGRESS: 'progress'
};
export var PrintType = {
LOG: 'log',
DEBUG: 'debug',
INFO: 'info',
WARN: 'warn',
ERROR: 'error'
};
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import {setUnexpectedErrorHandler, transformErrorForSerialization} from 'vs/base/common/errors';
import {parse, stringify} from 'vs/base/common/marshalling';
import * as workerProtocol from 'vs/base/common/worker/workerProtocol';
export class WorkerServer {
private _postSerializedMessage:(msg:string)=>void;
private _workerId:number;
private _requestHandler:any;
constructor(postSerializedMessage:(msg:string)=>void) {
this._postSerializedMessage = postSerializedMessage;
this._workerId = 0;
this._requestHandler = null;
this._bindConsole();
}
private _bindConsole(): void {
(<any> self).console = {
log: this._sendPrintMessage.bind(this, workerProtocol.PrintType.LOG),
debug: this._sendPrintMessage.bind(this, workerProtocol.PrintType.DEBUG),
info: this._sendPrintMessage.bind(this, workerProtocol.PrintType.INFO),
warn: this._sendPrintMessage.bind(this, workerProtocol.PrintType.WARN),
error: this._sendPrintMessage.bind(this, workerProtocol.PrintType.ERROR)
};
setUnexpectedErrorHandler((e) => {
self.console.error(e);
});
}
private _sendPrintMessage(level:string, ...objects:any[]): void {
let transformedObjects = objects.map((obj) => (obj instanceof Error) ? transformErrorForSerialization(obj) : obj);
let msg:workerProtocol.IServerPrintMessage = {
monacoWorker: true,
from: this._workerId,
req: '0',
type: workerProtocol.MessageType.PRINT,
level: level,
payload: (transformedObjects.length === 1 ? transformedObjects[0] : transformedObjects)
};
this._postMessage(msg);
}
private _sendReply(msgId:number, action:string, payload:any): void {
let msg:workerProtocol.IServerReplyMessage = {
monacoWorker: true,
from: this._workerId,
req: '0',
id: msgId,
type: workerProtocol.MessageType.REPLY,
action: action,
payload: (payload instanceof Error) ? transformErrorForSerialization(payload) : payload
};
this._postMessage(msg);
}
public loadModule(moduleId:string, callback:Function, errorback:(err:any)=>void): void {
// Use the global require to be sure to get the global config
(<any>self).require([moduleId], (...result:any[]) => {
callback(result[0]);
}, errorback);
}
public onmessage(msg:string): void {
this._onmessage(parse(msg));
}
private _postMessage(msg:workerProtocol.IServerMessage): void {
this._postSerializedMessage(stringify(msg));
}
private _onmessage(msg:workerProtocol.IClientMessage): void {
let c = this._sendReply.bind(this, msg.id, workerProtocol.ReplyType.COMPLETE);
let e = this._sendReply.bind(this, msg.id, workerProtocol.ReplyType.ERROR);
let p = this._sendReply.bind(this, msg.id, workerProtocol.ReplyType.PROGRESS);
switch(msg.type) {
case workerProtocol.MessageType.INITIALIZE:
this._workerId = msg.payload.id;
let loaderConfig = msg.payload.loaderConfiguration;
// TODO@Alex: share this code with simpleWorker
if (loaderConfig) {
// Remove 'baseUrl', handling it is beyond scope for now
if (typeof loaderConfig.baseUrl !== 'undefined') {
delete loaderConfig['baseUrl'];
}
if (typeof loaderConfig.paths !== 'undefined') {
if (typeof loaderConfig.paths.vs !== 'undefined') {
delete loaderConfig.paths['vs'];
}
}
let nlsConfig = loaderConfig['vs/nls'];
// We need to have pseudo translation
if (nlsConfig && nlsConfig.pseudo) {
require(['vs/nls'], function(nlsPlugin) {
nlsPlugin.setPseudoTranslation(nlsConfig.pseudo);
});
}
// Since this is in a web worker, enable catching errors
loaderConfig.catchError = true;
(<any>self).require.config(loaderConfig);
}
this.loadModule(msg.payload.moduleId, (handlerModule:any) => {
this._requestHandler = handlerModule.value;
c();
}, e);
break;
default:
this._handleMessage(msg, c, e, p);
break;
}
}
private _handleMessage(msg:workerProtocol.IClientMessage, c:(value:any)=>void, e:(err:any)=>void, p:(progress:any)=>void): void {
if (!this._requestHandler) {
e('Request handler not loaded');
return;
}
let handlerMethod = this._requestHandler[msg.type];
if (typeof handlerMethod !== 'function') {
e('Handler does not have method ' + msg.type);
return;
}
try {
handlerMethod.call(this._requestHandler, this, c, e, p, msg.payload);
} catch (handlerError) {
e(transformErrorForSerialization(handlerError));
}
}
}
export function create(postMessage:(msg:string)=>void): WorkerServer {
return new WorkerServer(postMessage);
}
......@@ -5,9 +5,7 @@
'use strict';
import * as flags from 'vs/base/common/flags';
import {IDisposable, dispose} from 'vs/base/common/lifecycle';
import {logOnceWebWorkerWarning, IWorker, IWorkerCallback, IWorkerFactory} from 'vs/base/common/worker/workerClient';
import * as dom from 'vs/base/browser/dom';
import {logOnceWebWorkerWarning, IWorker, IWorkerCallback, IWorkerFactory} from 'vs/base/common/worker/simpleWorker';
function defaultGetWorkerUrl(workerId:string, label:string): string {
return require.toUrl('./' + workerId) + '#' + label;
......@@ -52,117 +50,25 @@ class WebWorker implements IWorker {
}
}
/**
* A worker that runs in an iframe and therefore does have its
* own global scope, but no own thread.
*/
class FrameWorker implements IWorker {
private id: number;
private iframe: HTMLIFrameElement;
private onMessage: EventListener;
private loaded: boolean;
private beforeLoadMessages: any[];
private _listeners: IDisposable[];
constructor(moduleId:string, id: number, onMessageCallback:IWorkerCallback) {
this.id = id;
this._listeners = [];
// Collect all messages sent to the worker until the iframe is loaded
this.loaded = false;
this.beforeLoadMessages = [];
this.postMessage(moduleId);
this.iframe = <HTMLIFrameElement> document.createElement('iframe');
this.iframe.id = this.iframeId();
this.iframe.src = require.toUrl('./workerMainCompatibility.html');
(<any> this.iframe).frameborder = this.iframe.height = this.iframe.width = '0';
this.iframe.style.display = 'none';
this._listeners.push(dom.addDisposableListener(this.iframe, 'load', () => this.onLoaded()));
this.onMessage = function(ev:any) {
onMessageCallback(ev.data);
};
this._listeners.push(dom.addDisposableListener(window, 'message', this.onMessage));
document.body.appendChild(this.iframe);
}
public dispose(): void {
this._listeners = dispose(this._listeners);
window.removeEventListener('message', this.onMessage);
window.frames[this.iframeId()].close();
}
private iframeId(): string {
return 'worker_iframe_' + this.id;
}
private onLoaded(): void {
this.loaded = true;
while (this.beforeLoadMessages.length > 0) {
this.postMessage(this.beforeLoadMessages.shift());
}
}
public getId(): number {
return this.id;
}
public postMessage(msg:string): void {
if (this.loaded === true) {
var iframe = window.frames[this.iframeId()];
if (iframe.postMessage) {
iframe.postMessage(msg, '*');
} else {
iframe.contentWindow.postMessage(msg, '*');
}
} else {
this.beforeLoadMessages.push(msg);
}
}
}
export class DefaultWorkerFactory implements IWorkerFactory {
private static LAST_WORKER_ID = 0;
private _label: string;
private _fallbackToIframe:boolean;
private _webWorkerFailedBeforeError:any;
constructor(label:string, fallbackToIframe:boolean) {
constructor(label:string) {
this._label = label;
this._fallbackToIframe = fallbackToIframe;
this._webWorkerFailedBeforeError = false;
}
public create(moduleId:string, onMessageCallback:IWorkerCallback, onErrorCallback:(err:any)=>void):IWorker {
let workerId = (++DefaultWorkerFactory.LAST_WORKER_ID);
if (this._fallbackToIframe) {
if (this._webWorkerFailedBeforeError) {
// Avoid always trying to create web workers if they would just fail...
return new FrameWorker(moduleId, workerId, onMessageCallback);
}
try {
return new WebWorker(moduleId, workerId, this._label || 'anonymous' + workerId, onMessageCallback, (err) => {
logOnceWebWorkerWarning(err);
this._webWorkerFailedBeforeError = err;
onErrorCallback(err);
});
} catch(err) {
logOnceWebWorkerWarning(err);
return new FrameWorker(moduleId, workerId, onMessageCallback);
}
}
if (this._webWorkerFailedBeforeError) {
throw this._webWorkerFailedBeforeError;
}
return new WebWorker(moduleId, workerId, this._label || 'anonymous' + workerId, onMessageCallback, (err) => {
logOnceWebWorkerWarning(err);
this._webWorkerFailedBeforeError = err;
......
<!-- Copyright (c) Microsoft Corporation. All rights reserved. -->
<html>
<head>
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<script type="text/javascript" src="../../loader.js"></script>
<script>
require.config({
baseUrl: '../../../',
catchError: true
});
(function() {
var isFirstMessage = true;
var beforeReadyMessages = [];
var loadCode = function(moduleId) {
require([moduleId], function(ws) {
var workerServer = ws.create(function (msg) {
window.parent.postMessage(msg, '*');
});
var readyListener = function (ev) {
workerServer.onmessage(ev.data);
};
if (window.attachEvent) {
window.detachEvent('onmessage', beforeReadyListener);
window.attachEvent('onmessage', readyListener);
} else {
window.onmessage = readyListener;
}
while(beforeReadyMessages.length > 0) {
readyListener({ data: beforeReadyMessages.shift() });
}
});
};
var beforeReadyListener = function (message) {
if (!isFirstMessage) {
beforeReadyMessages.push(message.data);
return;
}
isFirstMessage = false;
loadCode(message.data);
};
if (window.attachEvent) {
window.attachEvent('onmessage', beforeReadyListener);
} else {
window.onmessage = beforeReadyListener;
}
})();
</script>
</head>
<body>
<div>compatibility worker iframe</div>
</body>
</html>
......@@ -43,5 +43,3 @@ import 'vs/editor/contrib/wordHighlighter/common/wordHighlighter';
import 'vs/editor/contrib/folding/browser/folding';
import 'vs/editor/contrib/indentation/common/indentation';
// include these in the editor bundle because they are widely used by many languages
import 'vs/editor/common/languages.common';
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
exports.collectModules = function() {
return [];
};
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
// base common
import 'vs/base/common/assert';
import 'vs/base/common/async';
import 'vs/base/common/callbackList';
import 'vs/base/common/cancellation';
import 'vs/base/common/collections';
import 'vs/base/common/event';
import 'vs/base/common/events';
import 'vs/base/common/lifecycle';
import 'vs/base/common/paths';
import 'vs/base/common/uri';
// platform common
import 'vs/platform/platform';
import 'vs/platform/jsonschemas/common/jsonContributionRegistry';
import 'vs/platform/workspace/common/workspace';
import 'vs/platform/telemetry/common/telemetry';
// editor common
import 'vs/editor/common/editorCommon';
import 'vs/editor/common/modes';
import 'vs/editor/common/modes/abstractMode';
import 'vs/editor/common/modes/abstractState';
import 'vs/editor/common/modes/monarch/monarchCommon';
import 'vs/editor/common/modes/monarch/monarchLexer';
import 'vs/editor/common/modes/monarch/monarchCompile';
import 'vs/editor/common/modes/languageConfigurationRegistry';
import 'vs/editor/common/modes/supports/suggestSupport';
import 'vs/editor/common/modes/supports/tokenizationSupport';
import 'vs/editor/common/services/modelService';
import 'vs/editor/common/services/modeService';
import 'vs/editor/common/services/compatWorkerService';
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import URI from 'vs/base/common/uri';
import * as editorCommon from 'vs/editor/common/editorCommon';
import {ModelLine} from 'vs/editor/common/model/modelLine';
import {TextModelWithTokens} from 'vs/editor/common/model/textModelWithTokens';
import {ICompatMirrorModel} from 'vs/editor/common/services/resourceService';
export interface ICompatMirrorModelEvents {
contentChanged: editorCommon.IModelContentChangedEvent[];
}
const NO_TAB_SIZE = 0;
export class CompatMirrorModel extends TextModelWithTokens implements ICompatMirrorModel {
protected _associatedResource:URI;
constructor(versionId:number, value:editorCommon.IRawText, languageId:string, associatedResource?:URI) {
super(['changed', editorCommon.EventType.ModelDispose], value, languageId);
this._setVersionId(versionId);
this._associatedResource = associatedResource;
}
public dispose(): void {
this.emit(editorCommon.EventType.ModelDispose);
super.dispose();
}
public get uri(): URI {
return this._associatedResource;
}
protected _constructLines(rawText:editorCommon.IRawText):void {
super._constructLines(rawText);
// Force EOL to be \n
this._EOL = '\n';
}
public onEvents(events:ICompatMirrorModelEvents) : void {
let changed = false;
for (let i = 0, len = events.contentChanged.length; i < len; i++) {
let contentChangedEvent = events.contentChanged[i];
this._setVersionId(contentChangedEvent.versionId);
switch (contentChangedEvent.changeType) {
case editorCommon.EventType.ModelRawContentChangedFlush:
this._onLinesFlushed(<editorCommon.IModelContentChangedFlushEvent>contentChangedEvent);
changed = true;
break;
case editorCommon.EventType.ModelRawContentChangedLinesDeleted:
this._onLinesDeleted(<editorCommon.IModelContentChangedLinesDeletedEvent>contentChangedEvent);
changed = true;
break;
case editorCommon.EventType.ModelRawContentChangedLinesInserted:
this._onLinesInserted(<editorCommon.IModelContentChangedLinesInsertedEvent>contentChangedEvent);
changed = true;
break;
case editorCommon.EventType.ModelRawContentChangedLineChanged:
this._onLineChanged(<editorCommon.IModelContentChangedLineChangedEvent>contentChangedEvent);
changed = true;
break;
}
}
if (changed) {
this.emit('changed', {});
}
}
private _onLinesFlushed(e:editorCommon.IModelContentChangedFlushEvent): void {
// Flush my lines
this._constructLines(e.detail);
this._resetTokenizationState();
}
private _onLineChanged(e:editorCommon.IModelContentChangedLineChangedEvent) : void {
this._lines[e.lineNumber - 1].applyEdits({}, [{
startColumn: 1,
endColumn: Number.MAX_VALUE,
text: e.detail,
forceMoveMarkers: false
}], NO_TAB_SIZE);
if (this._lineStarts) {
// update prefix sum
this._lineStarts.changeValue(e.lineNumber - 1, this._lines[e.lineNumber - 1].text.length + this._EOL.length);
}
this._invalidateLine(e.lineNumber - 1);
}
private _onLinesDeleted(e:editorCommon.IModelContentChangedLinesDeletedEvent) : void {
var fromLineIndex = e.fromLineNumber - 1,
toLineIndex = e.toLineNumber - 1;
// Save first line's state
var firstLineState = this._lines[fromLineIndex].getState();
this._lines.splice(fromLineIndex, toLineIndex - fromLineIndex + 1);
if (this._lineStarts) {
// update prefix sum
this._lineStarts.removeValues(fromLineIndex, toLineIndex - fromLineIndex + 1);
}
if (fromLineIndex < this._lines.length) {
// This check is always true in real world, but the tests forced this
// Restore first line's state
this._lines[fromLineIndex].setState(firstLineState);
// Invalidate line
this._invalidateLine(fromLineIndex);
}
}
private _onLinesInserted(e:editorCommon.IModelContentChangedLinesInsertedEvent) : void {
var lineIndex:number,
i:number,
splitLines = e.detail.split('\n');
let newLengths:number[] = [];
for (lineIndex = e.fromLineNumber - 1, i = 0; lineIndex < e.toLineNumber; lineIndex++, i++) {
this._lines.splice(lineIndex, 0, new ModelLine(0, splitLines[i], NO_TAB_SIZE));
newLengths.push(splitLines[i].length + this._EOL.length);
}
if (this._lineStarts) {
// update prefix sum
this._lineStarts.insertValues(e.fromLineNumber - 1, newLengths);
}
if (e.fromLineNumber >= 2) {
// This check is always true in real world, but the tests forced this
this._invalidateLine(e.fromLineNumber - 2);
}
}
}
......@@ -15,7 +15,7 @@ export const USUAL_WORD_SEPARATORS = '`~!@#$%^&*()-=+[{]}\\|;:\'",.<>/?';
* The default would look like this:
* /(-?\d*\.\d\w*)|([^\`\~\!\@\#\$\%\^\&\*\(\)\-\=\+\[\{\]\}\\\|\;\:\'\"\,\.\<\>\/\?\s]+)/g
*/
export function createWordRegExp(allowInWords:string = ''): RegExp {
function createWordRegExp(allowInWords:string = ''): RegExp {
var usualSeparators = USUAL_WORD_SEPARATORS;
var source = '(-?\\d*\\.\\d\\w*)|([^';
for (var i = 0; i < usualSeparators.length; i++) {
......
......@@ -4,77 +4,13 @@
*--------------------------------------------------------------------------------------------*/
'use strict';
import {TPromise} from 'vs/base/common/winjs.base';
import {AsyncDescriptor1, createAsyncDescriptor1} from 'vs/platform/instantiation/common/descriptors';
import {IInstantiationService, optional} from 'vs/platform/instantiation/common/instantiation';
import {optional} from 'vs/platform/instantiation/common/instantiation';
import {IConfigurationService} from 'vs/platform/configuration/common/configuration';
import * as modes from 'vs/editor/common/modes';
import {TextualSuggestSupport} from 'vs/editor/common/modes/supports/suggestSupport';
import {IEditorWorkerService} from 'vs/editor/common/services/editorWorkerService';
import * as wordHelper from 'vs/editor/common/model/wordHelper';
import {ICompatWorkerService, ICompatMode} from 'vs/editor/common/services/compatWorkerService';
import {CharCode} from 'vs/base/common/charCode';
export function createWordRegExp(allowInWords:string = ''): RegExp {
return wordHelper.createWordRegExp(allowInWords);
}
export class ModeWorkerManager<W> {
private _descriptor: modes.IModeDescriptor;
private _workerDescriptor: AsyncDescriptor1<string, W>;
private _superWorkerModuleId: string;
private _instantiationService: IInstantiationService;
private _workerPiecePromise:TPromise<W>;
constructor(
descriptor:modes.IModeDescriptor,
workerModuleId:string,
workerClassName:string,
superWorkerModuleId:string,
instantiationService: IInstantiationService
) {
this._descriptor = descriptor;
this._workerDescriptor = createAsyncDescriptor1(workerModuleId, workerClassName);
this._superWorkerModuleId = superWorkerModuleId;
this._instantiationService = instantiationService;
this._workerPiecePromise = null;
}
public worker<T>(runner:(worker:W)=>TPromise<T>): TPromise<T>
public worker<T>(runner:(worker:W)=>T): TPromise<T> {
return this._getOrCreateWorker().then(runner);
}
private _getOrCreateWorker(): TPromise<W> {
if (!this._workerPiecePromise) {
// TODO@Alex: workaround for missing `bundles` config
// First, load the code of the worker super class
let superWorkerCodePromise = (this._superWorkerModuleId ? ModeWorkerManager._loadModule(this._superWorkerModuleId) : TPromise.as(null));
this._workerPiecePromise = superWorkerCodePromise.then(() => {
// Second, load the code of the worker (without instantiating it)
return ModeWorkerManager._loadModule(this._workerDescriptor.moduleName);
}).then(() => {
// Finally, create the mode worker instance
return this._instantiationService.createInstance<string, W>(this._workerDescriptor, this._descriptor.id);
});
}
return this._workerPiecePromise;
}
private static _loadModule(moduleName:string): TPromise<any> {
return new TPromise((c, e, p) => {
// Use the global require to be sure to get the global config
(<any>self).require([moduleName], c, e);
}, () => {
// Cannot cancel loading code
});
}
}
// TODO@Alex: inline to FrankensteinMode, review optional IEditorWorkerService
export abstract class AbstractMode implements modes.IMode {
private _modeId: string;
......@@ -88,59 +24,6 @@ export abstract class AbstractMode implements modes.IMode {
}
}
export abstract class CompatMode extends AbstractMode implements ICompatMode {
public compatWorkerService:ICompatWorkerService;
constructor(modeId:string, compatWorkerService:ICompatWorkerService) {
super(modeId);
this.compatWorkerService = compatWorkerService;
if (this.compatWorkerService) {
this.compatWorkerService.registerCompatMode(this);
}
}
}
export function isDigit(character:string, base:number): boolean {
let c = character.charCodeAt(0);
switch (base) {
case 1:
return c === CharCode.Digit0;
case 2:
return c >= CharCode.Digit0 && c <= CharCode.Digit1;
case 3:
return c >= CharCode.Digit0 && c <= CharCode.Digit2;
case 4:
return c >= CharCode.Digit0 && c <= CharCode.Digit3;
case 5:
return c >= CharCode.Digit0 && c <= CharCode.Digit4;
case 6:
return c >= CharCode.Digit0 && c <= CharCode.Digit5;
case 7:
return c >= CharCode.Digit0 && c <= CharCode.Digit6;
case 8:
return c >= CharCode.Digit0 && c <= CharCode.Digit7;
case 9:
return c >= CharCode.Digit0 && c <= CharCode.Digit8;
case 10:
return c >= CharCode.Digit0 && c <= CharCode.Digit9;
case 11:
return (c >= CharCode.Digit0 && c <= CharCode.Digit9) || (c === CharCode.a) || (c === CharCode.A);
case 12:
return (c >= CharCode.Digit0 && c <= CharCode.Digit9) || (c >= CharCode.a && c <= CharCode.b) || (c >= CharCode.A && c <= CharCode.B);
case 13:
return (c >= CharCode.Digit0 && c <= CharCode.Digit9) || (c >= CharCode.a && c <= CharCode.c) || (c >= CharCode.A && c <= CharCode.C);
case 14:
return (c >= CharCode.Digit0 && c <= CharCode.Digit9) || (c >= CharCode.a && c <= CharCode.d) || (c >= CharCode.A && c <= CharCode.D);
case 15:
return (c >= CharCode.Digit0 && c <= CharCode.Digit9) || (c >= CharCode.a && c <= CharCode.e) || (c >= CharCode.A && c <= CharCode.E);
default:
return (c >= CharCode.Digit0 && c <= CharCode.Digit9) || (c >= CharCode.a && c <= CharCode.f) || (c >= CharCode.A && c <= CharCode.F);
}
}
export class FrankensteinMode extends AbstractMode {
constructor(
......
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import URI from 'vs/base/common/uri';
import {TPromise} from 'vs/base/common/winjs.base';
import {createDecorator} from 'vs/platform/instantiation/common/instantiation';
import {IRawText} from 'vs/editor/common/editorCommon';
export var ICompatWorkerService = createDecorator<ICompatWorkerService>('compatWorkerService');
export interface IRawModelData {
url: URI;
versionId: number;
value: IRawText;
modeId: string;
}
export interface ICompatMode {
getId(): string;
compatWorkerService: ICompatWorkerService;
}
export interface ICompatWorkerService {
_serviceBrand: any;
isInMainThread: boolean;
registerCompatMode(compatMode:ICompatMode): void;
CompatWorker(obj: ICompatMode, methodName: string, target: Function, param: any[]): TPromise<any>;
}
function findMember(proto: any, target: any): string {
for (let i in proto) {
if (proto[i] === target) {
return i;
}
}
throw new Error('Member not found in prototype');
}
export function CompatWorkerAttr(type: Function, target: Function): void {
let methodName = findMember(type.prototype, target);
type.prototype[methodName] = function(...param: any[]) {
let obj = <ICompatMode>this;
return obj.compatWorkerService.CompatWorker(obj, methodName, target, param);
};
}
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import {TPromise} from 'vs/base/common/winjs.base';
import {IDisposable} from 'vs/base/common/lifecycle';
import {IModel, EventType, IModelContentChangedEvent} from 'vs/editor/common/editorCommon';
import {ICompatWorkerService, ICompatMode} from 'vs/editor/common/services/compatWorkerService';
import {DefaultWorkerFactory} from 'vs/base/worker/defaultWorkerFactory';
import {WorkerClient} from 'vs/base/common/worker/workerClient';
import {IModelService} from 'vs/editor/common/services/modelService';
import {ModesRegistry} from 'vs/editor/common/modes/modesRegistry';
export class MainThreadCompatWorkerService implements ICompatWorkerService {
public _serviceBrand: any;
public isInMainThread = true;
private _workerFactory: DefaultWorkerFactory;
private _worker: WorkerClient;
private _workerCreatedPromise: TPromise<void>;
private _triggerWorkersCreatedPromise: (value: void) => void;
private _modelListeners: { [uri: string]: IDisposable };
constructor(
@IModelService modelService: IModelService
) {
this._workerFactory = new DefaultWorkerFactory('compatWorker', true);
this._worker = null;
this._workerCreatedPromise = new TPromise<void>((c, e, p) => {
this._triggerWorkersCreatedPromise = c;
}, () => {
// Not cancelable
});
this._modelListeners = Object.create(null);
const isInterestingModel = (model:IModel) => {
if (model.isTooLargeForHavingARichMode()) {
return false;
}
let modeId = model.getModeId();
let compatModes = ModesRegistry.getCompatModes();
for (let i = 0; i < compatModes.length; i++) {
if (compatModes[i].id === modeId) {
return true;
}
}
return false;
};
const onModelAdded = (model:IModel) => {
if (!isInterestingModel(model)) {
return;
}
this._modelListeners[model.uri.toString()] = model.addBulkListener((events) => {
let contentChangedEvents = (
events
.filter(e => e.getType() === EventType.ModelRawContentChanged)
.map(e => <IModelContentChangedEvent>e.getData())
);
if (contentChangedEvents.length === 0) {
return;
}
this._call('$', 'acceptModelEvents', [model.uri, { contentChanged: contentChangedEvents }]);
});
this._call('$', 'acceptNewModel', [{
url: model.uri,
versionId: model.getVersionId(),
value: model.toRawText(),
modeId: model.getMode().getId()
}]);
};
const onModelRemoved = (model:IModel) => {
if (this._modelListeners[model.uri.toString()]) {
this._modelListeners[model.uri.toString()].dispose();
delete this._modelListeners[model.uri.toString()];
this._call('$', 'acceptDidDisposeModel', [model.uri]);
}
};
modelService.onModelAdded(onModelAdded);
modelService.onModelRemoved(onModelRemoved);
modelService.onModelModeChanged(event => {
onModelRemoved(event.model);
onModelAdded(event.model);
});
}
public registerCompatMode(compatMode:ICompatMode): void {
this._call('$', 'instantiateCompatMode', [compatMode.getId()]);
}
public CompatWorker(obj: ICompatMode, methodName: string, target: Function, param: any[]): TPromise<any> {
return this._call(obj.getId(), methodName, param);
}
private _ensureWorkers(): void {
if (this._triggerWorkersCreatedPromise) {
// Workers not created yet
this._createWorker();
let complete = this._triggerWorkersCreatedPromise;
this._triggerWorkersCreatedPromise = null;
complete(null);
}
}
private _afterWorkers(): TPromise<void> {
this._ensureWorkers();
let shouldCancelPromise = false;
return new TPromise<void>((c, e, p) => {
// hide the initialize promise inside this
// promise so that it won't be canceled by accident
this._workerCreatedPromise.then(() => {
if (!shouldCancelPromise) {
c(null);
}
}, e, p);
}, () => {
// mark that this promise is canceled
shouldCancelPromise = true;
});
}
private _createWorker(isRetry:boolean = false): void {
this._worker = new WorkerClient(
this._workerFactory,
'vs/editor/common/worker/editorWorkerServer'
);
this._worker.onModuleLoaded = this._worker.request('initialize', {
modesRegistryData: {
compatModes: ModesRegistry.getCompatModes(),
languages: ModesRegistry.getLanguages()
}
}).then(() => {
ModesRegistry.onDidAddCompatModes((m) => this._call('$', 'acceptCompatModes', [m]));
ModesRegistry.onDidAddLanguages((m) => this._call('$', 'acceptLanguages', [m]));
}, (err) => {
this._worker.dispose();
this._worker = null;
if (isRetry) {
console.warn('Creating the web worker already failed twice. Giving up!');
} else {
this._createWorker(true);
}
});
}
private _call(rpcId: string, methodName: string, args:any[]): TPromise<any> {
return this._afterWorkers().then(_ => {
if (this._worker === null) {
throw new Error('Cannot fulfill request...');
}
return this._worker.request('request', {
target: rpcId,
methodName: methodName,
args: args
});
});
}
}
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import {TPromise} from 'vs/base/common/winjs.base';
import {ICompatWorkerService, ICompatMode, IRawModelData} from 'vs/editor/common/services/compatWorkerService';
import {IResourceService} from 'vs/editor/common/services/resourceService';
import {ILanguageExtensionPoint, IModeService} from 'vs/editor/common/services/modeService';
import {ICompatMirrorModelEvents, CompatMirrorModel} from 'vs/editor/common/model/compatMirrorModel';
import {onUnexpectedError} from 'vs/base/common/errors';
import URI from 'vs/base/common/uri';
import {ILegacyLanguageDefinition, ModesRegistry} from 'vs/editor/common/modes/modesRegistry';
export class CompatWorkerServiceWorker implements ICompatWorkerService {
public _serviceBrand: any;
public isInMainThread = false;
private _compatModes: {[modeId:string]:ICompatMode;};
constructor(
@IResourceService private resourceService: IResourceService,
@IModeService private modeService: IModeService,
modesRegistryData: {
compatModes: ILegacyLanguageDefinition[];
languages: ILanguageExtensionPoint[];
}
) {
ModesRegistry.registerCompatModes(modesRegistryData.compatModes);
ModesRegistry.registerLanguages(modesRegistryData.languages);
this._compatModes = Object.create(null);
}
registerCompatMode(compatMode:ICompatMode): void {
this._compatModes[compatMode.getId()] = compatMode;
}
public handleMainRequest(rpcId: string, methodName: string, args: any[]): any {
if (rpcId === '$') {
switch (methodName) {
case 'acceptNewModel':
return this._acceptNewModel(args[0]);
case 'acceptDidDisposeModel':
return this._acceptDidDisposeModel(args[0]);
case 'acceptModelEvents':
return this._acceptModelEvents(args[0], args[1]);
case 'acceptCompatModes':
return this._acceptCompatModes(args[0]);
case 'acceptLanguages':
return this._acceptLanguages(args[0]);
case 'instantiateCompatMode':
return this._instantiateCompatMode(args[0]);
}
}
let obj = this._compatModes[rpcId];
return TPromise.as(obj[methodName].apply(obj, args));
}
public CompatWorker(obj: ICompatMode, methodName: string, target: Function, param: any[]): TPromise<any> {
return target.apply(obj, param);
}
private _acceptNewModel(data: IRawModelData): TPromise<void> {
// Create & insert the mirror model eagerly in the resource service
let mirrorModel = new CompatMirrorModel(data.versionId, data.value, null, data.url);
this.resourceService.insert(mirrorModel.uri, mirrorModel);
// Block worker execution until the mode is instantiated
return this.modeService.getOrCreateMode(data.modeId).then((mode) => {
// Changing mode should trigger a remove & an add, therefore:
// (1) Remove from resource service
this.resourceService.remove(mirrorModel.uri);
// (2) Change mode
mirrorModel.setMode(mode.getId());
// (3) Insert again to resource service (it will have the new mode)
this.resourceService.insert(mirrorModel.uri, mirrorModel);
});
}
private _acceptDidDisposeModel(uri: URI): void {
let model = <CompatMirrorModel>this.resourceService.get(uri);
this.resourceService.remove(uri);
model.dispose();
}
private _acceptModelEvents(uri: URI, events: ICompatMirrorModelEvents): void {
let model = <CompatMirrorModel>this.resourceService.get(uri);
try {
model.onEvents(events);
} catch (err) {
onUnexpectedError(err);
}
}
private _acceptCompatModes(modes:ILegacyLanguageDefinition[]): void {
ModesRegistry.registerCompatModes(modes);
}
private _acceptLanguages(languages:ILanguageExtensionPoint[]): void {
ModesRegistry.registerLanguages(languages);
}
private _instantiateCompatMode(modeId:string): TPromise<void> {
return this.modeService.getOrCreateMode(modeId).then(_ => void 0);
}
}
......@@ -8,7 +8,7 @@ import {IntervalTimer, ShallowCancelThenPromise, wireCancellationToken} from 'vs
import {Disposable, IDisposable, dispose} from 'vs/base/common/lifecycle';
import URI from 'vs/base/common/uri';
import {TPromise} from 'vs/base/common/winjs.base';
import {SimpleWorkerClient} from 'vs/base/common/worker/simpleWorker';
import {SimpleWorkerClient, logOnceWebWorkerWarning} from 'vs/base/common/worker/simpleWorker';
import {DefaultWorkerFactory} from 'vs/base/worker/defaultWorkerFactory';
import * as editorCommon from 'vs/editor/common/editorCommon';
import {WordHelper} from 'vs/editor/common/model/textModelWithTokensHelpers';
......@@ -16,7 +16,6 @@ import {IInplaceReplaceSupportResult, ILink, ISuggestResult, LinkProviderRegistr
import {IEditorWorkerService} from 'vs/editor/common/services/editorWorkerService';
import {IModelService} from 'vs/editor/common/services/modelService';
import {EditorSimpleWorkerImpl} from 'vs/editor/common/services/editorSimpleWorker';
import {logOnceWebWorkerWarning} from 'vs/base/common/worker/workerClient';
/**
* Stop syncing a model to the worker if it was not needed for 1 min.
......@@ -256,7 +255,7 @@ export class EditorWorkerClient extends Disposable {
constructor(modelService: IModelService, label:string) {
super();
this._modelService = modelService;
this._workerFactory = new DefaultWorkerFactory(label, /*do not use iframe*/false);
this._workerFactory = new DefaultWorkerFactory(label);
this._worker = null;
this._modelManager = null;
}
......
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import URI from 'vs/base/common/uri';
import {createDecorator} from 'vs/platform/instantiation/common/instantiation';
import {ITokenizedModel} from 'vs/editor/common/editorCommon';
export interface ICompatMirrorModel extends ITokenizedModel {
}
// Resource Service
export let IResourceService = createDecorator<IResourceService>('resourceService');
export interface IResourceService {
_serviceBrand: any;
insert(url: URI, element: ICompatMirrorModel): void;
get(url: URI): ICompatMirrorModel;
remove(url: URI): void;
}
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import URI from 'vs/base/common/uri';
import {IResourceService, ICompatMirrorModel} from 'vs/editor/common/services/resourceService';
class CompatMirrorModelMap {
private _data: {[key:string]:ICompatMirrorModel};
constructor() {
this._data = {};
}
public set(key:string, data:ICompatMirrorModel): void {
this._data[key] = data;
}
public get(key:string): ICompatMirrorModel {
return this._data[key] || null;
}
public contains(key:string): boolean {
return !!this._data[key];
}
public remove(key:string): void {
delete this._data[key];
}
}
export class ResourceService implements IResourceService {
public _serviceBrand: any;
private _map:CompatMirrorModelMap;
constructor() {
this._map = new CompatMirrorModelMap();
}
private static _anonymousModelId(input:string): string {
let r = '';
for (let i = 0; i < input.length; i++) {
let ch = input[i];
if (ch >= '0' && ch <= '9') {
r += '0';
continue;
}
if (ch >= 'a' && ch <= 'z') {
r += 'a';
continue;
}
if (ch >= 'A' && ch <= 'Z') {
r += 'A';
continue;
}
r += ch;
}
return r;
}
public insert(uri:URI, element:ICompatMirrorModel): void {
let key = uri.toString();
if (this._map.contains(key)) {
// There already exists a model with this id => this is a programmer error
throw new Error('ResourceService: Cannot add model ' + ResourceService._anonymousModelId(key) + ' because it already exists!');
}
this._map.set(key, element);
}
public get(uri:URI):ICompatMirrorModel {
let key = uri.toString();
return this._map.get(key);
}
public remove(uri:URI):void {
let key = uri.toString();
this._map.remove(key);
}
}
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
// include these in the editor bundle because they are widely used by many languages
import 'vs/editor/common/languages.common';
import Severity from 'vs/base/common/severity';
import {TPromise} from 'vs/base/common/winjs.base';
import {WorkerServer} from 'vs/base/common/worker/workerServer';
import {EventService} from 'vs/platform/event/common/eventService';
import {IEventService} from 'vs/platform/event/common/event';
import {AbstractExtensionService, ActivatedExtension} from 'vs/platform/extensions/common/abstractExtensionService';
import {IExtensionDescription, IExtensionService} from 'vs/platform/extensions/common/extensions';
import {ServiceCollection} from 'vs/platform/instantiation/common/serviceCollection';
import {InstantiationService} from 'vs/platform/instantiation/common/instantiationService';
import {ModeServiceImpl} from 'vs/editor/common/services/modeServiceImpl';
import {IModeService, ILanguageExtensionPoint} from 'vs/editor/common/services/modeService';
import {ResourceService} from 'vs/editor/common/services/resourceServiceImpl';
import {IResourceService} from 'vs/editor/common/services/resourceService';
import {CompatWorkerServiceWorker} from 'vs/editor/common/services/compatWorkerServiceWorker';
import {ICompatWorkerService} from 'vs/editor/common/services/compatWorkerService';
import {ILegacyLanguageDefinition} from 'vs/editor/common/modes/modesRegistry';
export interface IInitData {
modesRegistryData?: {
compatModes: ILegacyLanguageDefinition[];
languages: ILanguageExtensionPoint[];
};
}
export interface ICallback {
(something:any):void;
}
class WorkerExtensionService extends AbstractExtensionService<ActivatedExtension> {
constructor() {
super(true);
}
protected _showMessage(severity:Severity, msg:string): void {
switch (severity) {
case Severity.Error:
console.error(msg);
break;
case Severity.Warning:
console.warn(msg);
break;
case Severity.Info:
console.info(msg);
break;
default:
console.log(msg);
}
}
protected _createFailedExtension(): ActivatedExtension {
throw new Error('unexpected');
}
protected _actualActivateExtension(extensionDescription: IExtensionDescription): TPromise<ActivatedExtension> {
throw new Error('unexpected');
}
}
export class EditorWorkerServer {
private compatWorkerService:CompatWorkerServiceWorker;
constructor() {
}
public initialize(mainThread:WorkerServer, complete:ICallback, error:ICallback, progress:ICallback, initData:IInitData):void {
const services = new ServiceCollection();
const instantiationService = new InstantiationService(services);
const extensionService = new WorkerExtensionService();
services.set(IExtensionService, extensionService);
const resourceService = new ResourceService();
services.set(IResourceService, resourceService);
services.set(IEventService, new EventService());
const modeService = new ModeServiceImpl(instantiationService, extensionService);
services.set(IModeService, modeService);
this.compatWorkerService = new CompatWorkerServiceWorker(resourceService, modeService, initData.modesRegistryData);
services.set(ICompatWorkerService, this.compatWorkerService);
complete(undefined);
}
public request(mainThread:WorkerServer, complete:ICallback, error:ICallback, progress:ICallback, data:any):void {
try {
TPromise.as(
this.compatWorkerService.handleMainRequest(data.target, data.methodName, data.args)
).then(complete, error);
} catch (err) {
error(err);
}
}
}
export var value = new EditorWorkerServer();
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as assert from 'assert';
import * as editorCommon from 'vs/editor/common/editorCommon';
import {ICompatMirrorModelEvents, CompatMirrorModel} from 'vs/editor/common/model/compatMirrorModel';
import {Position} from 'vs/editor/common/core/position';
import {MirrorModel as SimpleMirrorModel} from 'vs/editor/common/services/editorSimpleWorker';
import {DEFAULT_WORD_REGEXP} from 'vs/editor/common/model/wordHelper';
import {TextModel} from 'vs/editor/common/model/textModel';
function createTestMirrorModelFromString(value:string): CompatMirrorModel {
return new CompatMirrorModel(0, TextModel.toRawText(value, TextModel.DEFAULT_CREATION_OPTIONS), null);
}
function contentChangedFlushEvent(detail: editorCommon.IRawText): editorCommon.IModelContentChangedFlushEvent {
return {
changeType: editorCommon.EventType.ModelRawContentChangedFlush,
isRedoing: false,
isUndoing: false,
versionId: 0,
detail: detail
};
}
function contentChangedLinesDeletedEvent(fromLineNumber: number, toLineNumber: number): editorCommon.IModelContentChangedLinesDeletedEvent {
return {
changeType: editorCommon.EventType.ModelRawContentChangedLinesDeleted,
isRedoing: false,
isUndoing: false,
versionId: 0,
fromLineNumber: fromLineNumber,
toLineNumber: toLineNumber
};
}
function contentChangedLinesInsertedEvent(fromLineNumber: number, toLineNumber: number, detail: string): editorCommon.IModelContentChangedLinesInsertedEvent {
return {
changeType: editorCommon.EventType.ModelRawContentChangedLinesInserted,
isRedoing: false,
isUndoing: false,
versionId: 0,
fromLineNumber: fromLineNumber,
toLineNumber: toLineNumber,
detail: detail
};
}
function contentChangedLineChanged(lineNumber: number, detail: string): editorCommon.IModelContentChangedLineChangedEvent {
return {
changeType: editorCommon.EventType.ModelRawContentChangedLineChanged,
isRedoing: false,
isUndoing: false,
versionId: 0,
lineNumber: lineNumber,
detail: detail
};
}
function mirrorModelEvents(contentChanged:editorCommon.IModelContentChangedEvent[]): ICompatMirrorModelEvents {
return {
contentChanged: contentChanged
};
}
suite('Editor Model - MirrorModel', () => {
var mirrorModel:CompatMirrorModel;
setup(() => {
mirrorModel = createTestMirrorModelFromString('line1\nline2\nline3\nline4');
});
teardown(() => {
mirrorModel.dispose();
mirrorModel = null;
});
test('get line start ', () => {
assert.equal(mirrorModel.getOffsetAt(new Position(1, 1)), 0);
assert.equal(mirrorModel.getOffsetAt(new Position(2, 1)), 6);
assert.equal(mirrorModel.getOffsetAt(new Position(3, 1)), 12);
assert.equal(mirrorModel.getOffsetAt(new Position(4, 1)), 18);
assert.equal(mirrorModel.getOffsetAt(new Position(1000, 1)), mirrorModel.getOffsetAt(new Position(mirrorModel.getLineCount(), mirrorModel.getLineMaxColumn(mirrorModel.getLineCount()))));
});
test('get line start /flush event/', () => {
assert.equal(mirrorModel.getOffsetAt(new Position(2, 1)), 6);
assert.equal(mirrorModel.getOffsetAt(new Position(3, 1)), 12);
mirrorModel.onEvents(mirrorModelEvents([contentChangedFlushEvent({
length: -1,
lines: [
'foo',
'bar'
],
BOM: '',
EOL: '\n',
options: {
tabSize: 4,
insertSpaces: true,
trimAutoWhitespace: true,
defaultEOL: editorCommon.DefaultEndOfLine.LF
}
})]));
assert.equal(mirrorModel.getOffsetAt(new Position(1, 1)), 0);
assert.equal(mirrorModel.getOffsetAt(new Position(2, 1)), 4);
});
test('get offset', () => {
assert.equal(mirrorModel.getOffsetAt({lineNumber: 1, column: 1}), 0);
assert.equal(mirrorModel.getOffsetAt({lineNumber: 1, column: 3}), 2);
assert.equal(mirrorModel.getOffsetAt({lineNumber: 2, column: 1}), 6);
assert.equal(mirrorModel.getOffsetAt({lineNumber: 4, column: 6}), 23);
assert.equal(mirrorModel.getOffsetAt({lineNumber: 4, column: 7}), 23);
});
test('get position from offset', () => {
assert.deepEqual(mirrorModel.getPositionAt(0), {lineNumber: 1, column: 1});
assert.deepEqual(mirrorModel.getPositionAt(2), {lineNumber: 1, column: 3});
assert.deepEqual(mirrorModel.getPositionAt(6), {lineNumber: 2, column: 1});
assert.deepEqual(mirrorModel.getPositionAt(23), {lineNumber: 4, column: 6});
assert.deepEqual(mirrorModel.getPositionAt(24), {lineNumber: 4, column: 6});
});
test('get (all/unique) words', () => {
let model = new SimpleMirrorModel(null, [ 'foo bar foo bar' ], '\n', 1);
let uniqueWords = model.getAllUniqueWords(DEFAULT_WORD_REGEXP);
assert.equal(uniqueWords.length, 2);
assert.equal(uniqueWords[0], 'foo');
assert.equal(uniqueWords[1], 'bar');
model = new SimpleMirrorModel(null, [ 'foo bar', 'foo', 'bar' ], '\n', 1);
uniqueWords = model.getAllUniqueWords(DEFAULT_WORD_REGEXP);
assert.equal(uniqueWords.length, 2);
assert.equal(uniqueWords[0], 'foo');
assert.equal(uniqueWords[1], 'bar');
model = new SimpleMirrorModel(null, [ 'toString', 'hasOwnProperty', 'foo' ], '\n', 1);
uniqueWords = model.getAllUniqueWords(DEFAULT_WORD_REGEXP);
assert.equal(uniqueWords.length, 3);
assert.equal(uniqueWords[0], 'toString');
assert.equal(uniqueWords[1], 'hasOwnProperty');
assert.equal(uniqueWords[2], 'foo');
});
test('word at/until pos', () => {
var pos = { lineNumber: 1, column: 3 };
assert.equal(mirrorModel.getWordAtPosition(pos).word, 'line1');
var model = createTestMirrorModelFromString('foo bar 1234 :";\'');
assert.equal(model.getWordAtPosition({lineNumber: 1, column: 1}).word, 'foo');
assert.equal(model.getWordAtPosition({lineNumber: 1, column: 2}).word, 'foo');
assert.equal(model.getWordAtPosition({lineNumber: 1, column: 3}).word, 'foo');
assert.equal(model.getWordAtPosition({lineNumber: 1, column: 4}).word, 'foo');
assert.equal(model.getWordAtPosition({lineNumber: 1, column: 5}).word, 'bar');
assert.equal(model.getWordAtPosition({lineNumber: 1, column: 6}).word, 'bar');
assert.equal(model.getWordAtPosition({lineNumber: 1, column: 7}).word, 'bar');
assert.equal(model.getWordAtPosition({lineNumber: 1, column: 8}).word, 'bar');
assert.equal(model.getWordAtPosition({lineNumber: 1, column: 9}).word, '1234');
assert.equal(model.getWordAtPosition({lineNumber: 1, column: 10}).word, '1234');
assert.equal(model.getWordAtPosition({lineNumber: 1, column: 11}).word, '1234');
assert.equal(model.getWordAtPosition({lineNumber: 1, column: 12}).word, '1234');
assert.equal(model.getWordAtPosition({lineNumber: 1, column: 13}).word, '1234');
assert.equal(model.getWordAtPosition({lineNumber: 1, column: 14}), null);
assert.equal(model.getWordAtPosition({lineNumber: 1, column: 15}), null);
assert.equal(model.getWordAtPosition({lineNumber: 1, column: 16}), null);
assert.equal(mirrorModel.getWordUntilPosition(pos).word, 'li');
});
});
suite('Editor Model - MirrorModel Eventing', () => {
var mirrorModel:CompatMirrorModel;
setup(() => {
mirrorModel = createTestMirrorModelFromString('line one\nline two\nline three\nline four');
});
teardown(() => {
mirrorModel.dispose();
mirrorModel = null;
});
test('delete single line', () => {
assert.equal(mirrorModel.getLineContent(3), 'line three');
mirrorModel.onEvents(mirrorModelEvents([contentChangedLinesDeletedEvent(3, 3)]));
assert.equal(mirrorModel.getLineContent(3), 'line four');
});
test('delete multiple lines', () => {
mirrorModel.onEvents(mirrorModelEvents([contentChangedLinesDeletedEvent(1, 2)]));
assert.equal(mirrorModel.getLineContent(1), 'line three');
assert.equal(mirrorModel.getLineContent(2), 'line four');
});
test('delete all lines', () => {
mirrorModel.onEvents(mirrorModelEvents([contentChangedLinesDeletedEvent(1, 4)]));
});
test('add single lines', () => {
assert.equal(mirrorModel.getLineContent(1), 'line one');
mirrorModel.onEvents(mirrorModelEvents([contentChangedLinesInsertedEvent(1, 1, 'foo bar\nbar foo')]));
assert.equal(mirrorModel.getLineContent(1), 'foo bar');
assert.equal(mirrorModel.getLineContent(2), 'line one');
});
test('add multiple lines', () => {
assert.equal(mirrorModel.getLineContent(1), 'line one');
mirrorModel.onEvents(mirrorModelEvents([contentChangedLinesInsertedEvent(1, 2, 'foo bar\nbar foo')]));
assert.equal(mirrorModel.getLineContent(1), 'foo bar');
assert.equal(mirrorModel.getLineContent(2), 'bar foo');
assert.equal(mirrorModel.getLineContent(3), 'line one');
});
test('change line', () => {
assert.equal(mirrorModel.getLineContent(1), 'line one');
mirrorModel.onEvents(mirrorModelEvents([contentChangedLineChanged(1, 'foobar')]));
assert.equal(mirrorModel.getLineContent(1), 'foobar');
});
test('flush model', () => {
assert.equal(mirrorModel.getLineContent(1), 'line one');
assert.equal(mirrorModel.getLineContent(2), 'line two');
mirrorModel.onEvents(mirrorModelEvents([contentChangedFlushEvent({
length: -1,
lines: [
'foo',
'bar'
],
BOM: '',
EOL: '\n',
options: {
tabSize: 4,
insertSpaces: true,
trimAutoWhitespace: true,
defaultEOL: editorCommon.DefaultEndOfLine.LF
}
})]));
assert.equal(mirrorModel.getLineContent(1), 'foo');
assert.equal(mirrorModel.getLineContent(2), 'bar');
});
});
......@@ -7,7 +7,6 @@
import * as assert from 'assert';
import * as editorCommon from 'vs/editor/common/editorCommon';
import {EditableTextModel} from 'vs/editor/common/model/editableTextModel';
import {ICompatMirrorModelEvents, CompatMirrorModel} from 'vs/editor/common/model/compatMirrorModel';
import {MirrorModel2} from 'vs/editor/common/model/mirrorModel2';
import {TextModel} from 'vs/editor/common/model/textModel';
import {Position} from 'vs/editor/common/core/position';
......@@ -90,25 +89,9 @@ export function assertSyncedModels(text:string, callback:(model:EditableTextMode
assertLineMapping(model, 'model');
}
var mirrorModel1 = new CompatMirrorModel(model.getVersionId(), model.toRawText(), null);
assertLineMapping(mirrorModel1, 'mirrorModel1');
var mirrorModel1PrevVersionId = model.getVersionId();
var mirrorModel2 = new MirrorModel2(null, model.toRawText().lines, model.toRawText().EOL, model.getVersionId());
var mirrorModel2PrevVersionId = model.getVersionId();
model.onDidChangeRawContent((e:editorCommon.IModelContentChangedEvent) => {
let versionId = e.versionId;
if (versionId < mirrorModel1PrevVersionId) {
console.warn('Model version id did not advance between edits (1)');
}
mirrorModel1PrevVersionId = versionId;
let mirrorModelEvents:ICompatMirrorModelEvents = {
contentChanged: [e]
};
mirrorModel1.onEvents(mirrorModelEvents);
});
model.onDidChangeContent((e:editorCommon.IModelContentChangedEvent2) => {
let versionId = e.versionId;
if (versionId < mirrorModel2PrevVersionId) {
......@@ -120,17 +103,13 @@ export function assertSyncedModels(text:string, callback:(model:EditableTextMode
var assertMirrorModels = () => {
assertLineMapping(model, 'model');
assertLineMapping(mirrorModel1, 'mirrorModel1');
model._assertLineNumbersOK();
assert.equal(mirrorModel2.getText(), model.getValue(), 'mirror model 2 text OK');
assert.equal(mirrorModel2.version, model.getVersionId(), 'mirror model 2 version OK');
assert.equal(mirrorModel1.getValue(), model.getValue(), 'mirror model 1 text OK');
assert.equal(mirrorModel1.getVersionId(), model.getVersionId(), 'mirror model 1 version OK');
};
callback(model, assertMirrorModels);
model.dispose();
mirrorModel1.dispose();
mirrorModel2.dispose();
}
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import * as assert from 'assert';
import URI from 'vs/base/common/uri';
import {CompatMirrorModel} from 'vs/editor/common/model/compatMirrorModel';
import {ResourceService} from 'vs/editor/common/services/resourceServiceImpl';
import {TextModel} from 'vs/editor/common/model/textModel';
function createTestMirrorModelFromString(value:string): CompatMirrorModel {
return new CompatMirrorModel(0, TextModel.toRawText(value, TextModel.DEFAULT_CREATION_OPTIONS), null);
}
suite('Editor Services - ResourceService', () => {
test('insert, remove, all', () => {
let service = new ResourceService();
service.insert(URI.parse('test://1'), createTestMirrorModelFromString('hi'));
assert.equal(service.get(URI.parse('test://1')).getValue(), 'hi');
service.insert(URI.parse('test://2'), createTestMirrorModelFromString('hi'));
service.remove(URI.parse('test://1'));
service.remove(URI.parse('test://1'));
service.remove(URI.parse('test://2'));
assert.equal(service.get(URI.parse('test://1')), null);
});
test('inserting the same resource twice throws', () => {
let service = new ResourceService();
service.insert(URI.parse('test://path/some-N1ce-name'), createTestMirrorModelFromString('hello'));
assert.throws(() => {
service.insert(URI.parse('test://path/some-N1ce-name'), createTestMirrorModelFromString('hello again'));
});
});
});
......@@ -42,8 +42,6 @@ import {MainThreadService} from 'vs/workbench/services/thread/electron-browser/t
import {MarkerService} from 'vs/platform/markers/common/markerService';
import {IModelService} from 'vs/editor/common/services/modelService';
import {ModelServiceImpl} from 'vs/editor/common/services/modelServiceImpl';
import {ICompatWorkerService} from 'vs/editor/common/services/compatWorkerService';
import {MainThreadCompatWorkerService} from 'vs/editor/common/services/compatWorkerServiceMain';
import {CodeEditorServiceImpl} from 'vs/editor/browser/services/codeEditorServiceImpl';
import {ICodeEditorService} from 'vs/editor/common/services/codeEditorService';
import {IntegrityServiceImpl} from 'vs/platform/integrity/node/integrityServiceImpl';
......@@ -315,9 +313,6 @@ export class WorkbenchShell {
const modelService = instantiationService.createInstance(ModelServiceImpl);
serviceCollection.set(IModelService, modelService);
const compatWorkerService = instantiationService.createInstance(MainThreadCompatWorkerService);
serviceCollection.set(ICompatWorkerService, compatWorkerService);
const editorWorkerService = instantiationService.createInstance(EditorWorkerServiceImpl);
serviceCollection.set(IEditorWorkerService, editorWorkerService);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册