UNPKG

monaco-editor

Version:
380 lines (379 loc) • 18.3 kB
/*--------------------------------------------------------------------------------------------- * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ var __extends = (this && this.__extends) || (function () { var extendStatics = function (d, b) { extendStatics = Object.setPrototypeOf || ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; return extendStatics(d, b); } return function (d, b) { extendStatics(d, b); function __() { this.constructor = d; } d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); }; })(); var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; return c > 3 && r && Object.defineProperty(target, key, r), r; }; var __param = (this && this.__param) || function (paramIndex, decorator) { return function (target, key) { decorator(target, key, paramIndex); } }; import { IntervalTimer } from '../../../base/common/async.js'; import { Disposable, dispose, toDisposable } from '../../../base/common/lifecycle.js'; import { SimpleWorkerClient, logOnceWebWorkerWarning } from '../../../base/common/worker/simpleWorker.js'; import { DefaultWorkerFactory } from '../../../base/worker/defaultWorkerFactory.js'; import * as modes from '../modes.js'; import { LanguageConfigurationRegistry } from '../modes/languageConfigurationRegistry.js'; import { EditorSimpleWorkerImpl } from './editorSimpleWorker.js'; import { IModelService } from './modelService.js'; import { ITextResourceConfigurationService } from './resourceConfiguration.js'; /** * Stop syncing a model to the worker if it was not needed for 1 min. */ var STOP_SYNC_MODEL_DELTA_TIME_MS = 60 * 1000; /** * Stop the worker if it was not needed for 5 min. */ var STOP_WORKER_DELTA_TIME_MS = 5 * 60 * 1000; function canSyncModel(modelService, resource) { var model = modelService.getModel(resource); if (!model) { return false; } if (model.isTooLargeForSyncing()) { return false; } return true; } var EditorWorkerServiceImpl = /** @class */ (function (_super) { __extends(EditorWorkerServiceImpl, _super); function EditorWorkerServiceImpl(modelService, configurationService) { var _this = _super.call(this) || this; _this._modelService = modelService; _this._workerManager = _this._register(new WorkerManager(_this._modelService)); // todo@joh make sure this happens only once _this._register(modes.LinkProviderRegistry.register('*', { provideLinks: function (model, token) { if (!canSyncModel(_this._modelService, model.uri)) { return Promise.resolve([]); // File too large } return _this._workerManager.withWorker().then(function (client) { return client.computeLinks(model.uri); }); } })); _this._register(modes.CompletionProviderRegistry.register('*', new WordBasedCompletionItemProvider(_this._workerManager, configurationService, _this._modelService))); return _this; } EditorWorkerServiceImpl.prototype.dispose = function () { _super.prototype.dispose.call(this); }; EditorWorkerServiceImpl.prototype.canComputeDiff = function (original, modified) { return (canSyncModel(this._modelService, original) && canSyncModel(this._modelService, modified)); }; EditorWorkerServiceImpl.prototype.computeDiff = function (original, modified, ignoreTrimWhitespace) { return this._workerManager.withWorker().then(function (client) { return client.computeDiff(original, modified, ignoreTrimWhitespace); }); }; EditorWorkerServiceImpl.prototype.computeMoreMinimalEdits = function (resource, edits) { if (!Array.isArray(edits) || edits.length === 0) { return Promise.resolve(edits); } else { if (!canSyncModel(this._modelService, resource)) { return Promise.resolve(edits); // File too large } return this._workerManager.withWorker().then(function (client) { return client.computeMoreMinimalEdits(resource, edits); }); } }; EditorWorkerServiceImpl.prototype.canNavigateValueSet = function (resource) { return (canSyncModel(this._modelService, resource)); }; EditorWorkerServiceImpl.prototype.navigateValueSet = function (resource, range, up) { return this._workerManager.withWorker().then(function (client) { return client.navigateValueSet(resource, range, up); }); }; EditorWorkerServiceImpl.prototype.canComputeWordRanges = function (resource) { return canSyncModel(this._modelService, resource); }; EditorWorkerServiceImpl.prototype.computeWordRanges = function (resource, range) { return this._workerManager.withWorker().then(function (client) { return client.computeWordRanges(resource, range); }); }; EditorWorkerServiceImpl = __decorate([ __param(0, IModelService), __param(1, ITextResourceConfigurationService) ], EditorWorkerServiceImpl); return EditorWorkerServiceImpl; }(Disposable)); export { EditorWorkerServiceImpl }; var WordBasedCompletionItemProvider = /** @class */ (function () { function WordBasedCompletionItemProvider(workerManager, configurationService, modelService) { this._workerManager = workerManager; this._configurationService = configurationService; this._modelService = modelService; } WordBasedCompletionItemProvider.prototype.provideCompletionItems = function (model, position) { var wordBasedSuggestions = this._configurationService.getValue(model.uri, position, 'editor').wordBasedSuggestions; if (!wordBasedSuggestions) { return undefined; } if (!canSyncModel(this._modelService, model.uri)) { return undefined; // File too large } return this._workerManager.withWorker().then(function (client) { return client.textualSuggest(model.uri, position); }); }; return WordBasedCompletionItemProvider; }()); var WorkerManager = /** @class */ (function (_super) { __extends(WorkerManager, _super); function WorkerManager(modelService) { var _this = _super.call(this) || this; _this._modelService = modelService; _this._editorWorkerClient = null; var stopWorkerInterval = _this._register(new IntervalTimer()); stopWorkerInterval.cancelAndSet(function () { return _this._checkStopIdleWorker(); }, Math.round(STOP_WORKER_DELTA_TIME_MS / 2)); _this._register(_this._modelService.onModelRemoved(function (_) { return _this._checkStopEmptyWorker(); })); return _this; } WorkerManager.prototype.dispose = function () { if (this._editorWorkerClient) { this._editorWorkerClient.dispose(); this._editorWorkerClient = null; } _super.prototype.dispose.call(this); }; /** * Check if the model service has no more models and stop the worker if that is the case. */ WorkerManager.prototype._checkStopEmptyWorker = function () { if (!this._editorWorkerClient) { return; } var models = this._modelService.getModels(); if (models.length === 0) { // There are no more models => nothing possible for me to do this._editorWorkerClient.dispose(); this._editorWorkerClient = null; } }; /** * Check if the worker has been idle for a while and then stop it. */ WorkerManager.prototype._checkStopIdleWorker = function () { if (!this._editorWorkerClient) { return; } var timeSinceLastWorkerUsedTime = (new Date()).getTime() - this._lastWorkerUsedTime; if (timeSinceLastWorkerUsedTime > STOP_WORKER_DELTA_TIME_MS) { this._editorWorkerClient.dispose(); this._editorWorkerClient = null; } }; WorkerManager.prototype.withWorker = function () { this._lastWorkerUsedTime = (new Date()).getTime(); if (!this._editorWorkerClient) { this._editorWorkerClient = new EditorWorkerClient(this._modelService, 'editorWorkerService'); } return Promise.resolve(this._editorWorkerClient); }; return WorkerManager; }(Disposable)); var EditorModelManager = /** @class */ (function (_super) { __extends(EditorModelManager, _super); function EditorModelManager(proxy, modelService, keepIdleModels) { var _this = _super.call(this) || this; _this._syncedModels = Object.create(null); _this._syncedModelsLastUsedTime = Object.create(null); _this._proxy = proxy; _this._modelService = modelService; if (!keepIdleModels) { var timer = new IntervalTimer(); timer.cancelAndSet(function () { return _this._checkStopModelSync(); }, Math.round(STOP_SYNC_MODEL_DELTA_TIME_MS / 2)); _this._register(timer); } return _this; } EditorModelManager.prototype.dispose = function () { for (var modelUrl in this._syncedModels) { dispose(this._syncedModels[modelUrl]); } this._syncedModels = Object.create(null); this._syncedModelsLastUsedTime = Object.create(null); _super.prototype.dispose.call(this); }; EditorModelManager.prototype.esureSyncedResources = function (resources) { for (var i = 0; i < resources.length; i++) { var resource = resources[i]; var resourceStr = resource.toString(); if (!this._syncedModels[resourceStr]) { this._beginModelSync(resource); } if (this._syncedModels[resourceStr]) { this._syncedModelsLastUsedTime[resourceStr] = (new Date()).getTime(); } } }; EditorModelManager.prototype._checkStopModelSync = function () { var currentTime = (new Date()).getTime(); var toRemove = []; for (var modelUrl in this._syncedModelsLastUsedTime) { var elapsedTime = currentTime - this._syncedModelsLastUsedTime[modelUrl]; if (elapsedTime > STOP_SYNC_MODEL_DELTA_TIME_MS) { toRemove.push(modelUrl); } } for (var i = 0; i < toRemove.length; i++) { this._stopModelSync(toRemove[i]); } }; EditorModelManager.prototype._beginModelSync = function (resource) { var _this = this; var model = this._modelService.getModel(resource); if (!model) { return; } if (model.isTooLargeForSyncing()) { return; } var modelUrl = resource.toString(); this._proxy.acceptNewModel({ url: model.uri.toString(), lines: model.getLinesContent(), EOL: model.getEOL(), versionId: model.getVersionId() }); var toDispose = []; toDispose.push(model.onDidChangeContent(function (e) { _this._proxy.acceptModelChanged(modelUrl.toString(), e); })); toDispose.push(model.onWillDispose(function () { _this._stopModelSync(modelUrl); })); toDispose.push(toDisposable(function () { _this._proxy.acceptRemovedModel(modelUrl); })); this._syncedModels[modelUrl] = toDispose; }; EditorModelManager.prototype._stopModelSync = function (modelUrl) { var toDispose = this._syncedModels[modelUrl]; delete this._syncedModels[modelUrl]; delete this._syncedModelsLastUsedTime[modelUrl]; dispose(toDispose); }; return EditorModelManager; }(Disposable)); var SynchronousWorkerClient = /** @class */ (function () { function SynchronousWorkerClient(instance) { this._instance = instance; this._proxyObj = Promise.resolve(this._instance); } SynchronousWorkerClient.prototype.dispose = function () { this._instance.dispose(); }; SynchronousWorkerClient.prototype.getProxyObject = function () { return this._proxyObj; }; return SynchronousWorkerClient; }()); var EditorWorkerClient = /** @class */ (function (_super) { __extends(EditorWorkerClient, _super); function EditorWorkerClient(modelService, label) { var _this = _super.call(this) || this; _this._modelService = modelService; _this._workerFactory = new DefaultWorkerFactory(label); _this._worker = null; _this._modelManager = null; return _this; } EditorWorkerClient.prototype._getOrCreateWorker = function () { if (!this._worker) { try { this._worker = this._register(new SimpleWorkerClient(this._workerFactory, 'vs/editor/common/services/editorSimpleWorker')); } catch (err) { logOnceWebWorkerWarning(err); this._worker = new SynchronousWorkerClient(new EditorSimpleWorkerImpl(null)); } } return this._worker; }; EditorWorkerClient.prototype._getProxy = function () { var _this = this; return this._getOrCreateWorker().getProxyObject().then(null, function (err) { logOnceWebWorkerWarning(err); _this._worker = new SynchronousWorkerClient(new EditorSimpleWorkerImpl(null)); return _this._getOrCreateWorker().getProxyObject(); }); }; EditorWorkerClient.prototype._getOrCreateModelManager = function (proxy) { if (!this._modelManager) { this._modelManager = this._register(new EditorModelManager(proxy, this._modelService, false)); } return this._modelManager; }; EditorWorkerClient.prototype._withSyncedResources = function (resources) { var _this = this; return this._getProxy().then(function (proxy) { _this._getOrCreateModelManager(proxy).esureSyncedResources(resources); return proxy; }); }; EditorWorkerClient.prototype.computeDiff = function (original, modified, ignoreTrimWhitespace) { return this._withSyncedResources([original, modified]).then(function (proxy) { return proxy.computeDiff(original.toString(), modified.toString(), ignoreTrimWhitespace); }); }; EditorWorkerClient.prototype.computeMoreMinimalEdits = function (resource, edits) { return this._withSyncedResources([resource]).then(function (proxy) { return proxy.computeMoreMinimalEdits(resource.toString(), edits); }); }; EditorWorkerClient.prototype.computeLinks = function (resource) { return this._withSyncedResources([resource]).then(function (proxy) { return proxy.computeLinks(resource.toString()); }); }; EditorWorkerClient.prototype.textualSuggest = function (resource, position) { var _this = this; return this._withSyncedResources([resource]).then(function (proxy) { var model = _this._modelService.getModel(resource); if (!model) { return null; } var wordDefRegExp = LanguageConfigurationRegistry.getWordDefinition(model.getLanguageIdentifier().id); var wordDef = wordDefRegExp.source; var wordDefFlags = (wordDefRegExp.global ? 'g' : '') + (wordDefRegExp.ignoreCase ? 'i' : '') + (wordDefRegExp.multiline ? 'm' : ''); return proxy.textualSuggest(resource.toString(), position, wordDef, wordDefFlags); }); }; EditorWorkerClient.prototype.computeWordRanges = function (resource, range) { var _this = this; return this._withSyncedResources([resource]).then(function (proxy) { var model = _this._modelService.getModel(resource); if (!model) { return Promise.resolve(null); } var wordDefRegExp = LanguageConfigurationRegistry.getWordDefinition(model.getLanguageIdentifier().id); var wordDef = wordDefRegExp.source; var wordDefFlags = (wordDefRegExp.global ? 'g' : '') + (wordDefRegExp.ignoreCase ? 'i' : '') + (wordDefRegExp.multiline ? 'm' : ''); return proxy.computeWordRanges(resource.toString(), range, wordDef, wordDefFlags); }); }; EditorWorkerClient.prototype.navigateValueSet = function (resource, range, up) { var _this = this; return this._withSyncedResources([resource]).then(function (proxy) { var model = _this._modelService.getModel(resource); if (!model) { return null; } var wordDefRegExp = LanguageConfigurationRegistry.getWordDefinition(model.getLanguageIdentifier().id); var wordDef = wordDefRegExp.source; var wordDefFlags = (wordDefRegExp.global ? 'g' : '') + (wordDefRegExp.ignoreCase ? 'i' : '') + (wordDefRegExp.multiline ? 'm' : ''); return proxy.navigateValueSet(resource.toString(), range, up, wordDef, wordDefFlags); }); }; return EditorWorkerClient; }(Disposable)); export { EditorWorkerClient };