UNPKG

@codingame/monaco-vscode-extensions-service-override

Version:

VSCode public API plugged on the monaco editor - extensions service-override

255 lines (252 loc) 11.3 kB
import { __decorate, __param } from 'vscode/external/tslib/tslib.es6.js'; import { toErrorMessage } from 'vscode/vscode/vs/base/common/errorMessage'; import { dispose, Disposable } from 'vscode/vscode/vs/base/common/lifecycle'; import { Schemas } from 'vscode/vscode/vs/base/common/network'; import { URI } from 'vscode/vscode/vs/base/common/uri'; import { shouldSynchronizeModel } from 'vscode/vscode/vs/editor/common/model'; import { IModelService } from 'vscode/vscode/vs/editor/common/services/model'; import { ITextModelService } from 'vscode/vscode/vs/editor/common/services/resolverService'; import { FileOperation } from 'vscode/vscode/vs/platform/files/common/files'; import { IFileService } from 'vscode/vscode/vs/platform/files/common/files.service'; import { ExtHostContext } from 'vscode/vscode/vs/workbench/api/common/extHost.protocol'; import { ITextFileService } from 'vscode/vscode/vs/workbench/services/textfile/common/textfiles.service'; import { IWorkbenchEnvironmentService } from 'vscode/vscode/vs/workbench/services/environment/common/environmentService.service'; import { extUri, toLocalResource } from 'vscode/vscode/vs/base/common/resources'; import { IWorkingCopyFileService } from 'vscode/vscode/vs/workbench/services/workingCopy/common/workingCopyFileService.service'; import { IUriIdentityService } from 'vscode/vscode/vs/platform/uriIdentity/common/uriIdentity.service'; import { Emitter, Event } from 'vscode/vscode/vs/base/common/event'; import { IPathService } from 'vscode/vscode/vs/workbench/services/path/common/pathService.service'; import { ResourceMap } from 'vscode/vscode/vs/base/common/map'; import { ErrorNoTelemetry } from 'vscode/vscode/vs/base/common/errors'; class BoundModelReferenceCollection { constructor(_extUri, _maxAge = 1000 * 60 * 3, _maxLength = 1024 * 1024 * 80, _maxSize = 50 ) { this._extUri = _extUri; this._maxAge = _maxAge; this._maxLength = _maxLength; this._maxSize = _maxSize; this._data = ( new Array()); this._length = 0; } dispose() { this._data = dispose(this._data); } remove(uri) { for (const entry of [...this._data] ) { if (this._extUri.isEqualOrParent(entry.uri, uri)) { entry.dispose(); } } } add(uri, ref, length = 0) { const dispose = () => { const idx = this._data.indexOf(entry); if (idx >= 0) { this._length -= length; ref.dispose(); clearTimeout(handle); this._data.splice(idx, 1); } }; const handle = setTimeout(dispose, this._maxAge); const entry = { uri, length, dispose }; this._data.push(entry); this._length += length; this._cleanup(); } _cleanup() { while (this._length > this._maxLength) { this._data[0].dispose(); } const extraSize = Math.ceil(this._maxSize * 1.2); if (this._data.length >= extraSize) { dispose(this._data.slice(0, extraSize - this._maxSize)); } } } class ModelTracker extends Disposable { constructor(_model, _onIsCaughtUpWithContentChanges, _proxy, _textFileService) { super(); this._model = _model; this._onIsCaughtUpWithContentChanges = _onIsCaughtUpWithContentChanges; this._proxy = _proxy; this._textFileService = _textFileService; this._knownVersionId = this._model.getVersionId(); this._store.add(this._model.onDidChangeContent((e) => { this._knownVersionId = e.versionId; this._proxy.$acceptModelChanged(this._model.uri, e, this._textFileService.isDirty(this._model.uri)); if (this.isCaughtUpWithContentChanges()) { this._onIsCaughtUpWithContentChanges.fire(this._model.uri); } })); } isCaughtUpWithContentChanges() { return (this._model.getVersionId() === this._knownVersionId); } } let MainThreadDocuments = class MainThreadDocuments extends Disposable { constructor(extHostContext, _modelService, _textFileService, _fileService, _textModelResolverService, _environmentService, _uriIdentityService, workingCopyFileService, _pathService) { super(); this._modelService = _modelService; this._textFileService = _textFileService; this._fileService = _fileService; this._textModelResolverService = _textModelResolverService; this._environmentService = _environmentService; this._uriIdentityService = _uriIdentityService; this._pathService = _pathService; this._onIsCaughtUpWithContentChanges = this._store.add(( new Emitter())); this.onIsCaughtUpWithContentChanges = this._onIsCaughtUpWithContentChanges.event; this._modelTrackers = ( new ResourceMap()); this._modelReferenceCollection = this._store.add(( new BoundModelReferenceCollection(_uriIdentityService.extUri))); this._proxy = ( extHostContext.getProxy(ExtHostContext.ExtHostDocuments)); this._store.add(_modelService.onModelLanguageChanged(this._onModelModeChanged, this)); this._store.add(_textFileService.files.onDidSave(e => { if (this._shouldHandleFileEvent(e.model.resource)) { this._proxy.$acceptModelSaved(e.model.resource); } })); this._store.add(_textFileService.files.onDidChangeDirty(m => { if (this._shouldHandleFileEvent(m.resource)) { this._proxy.$acceptDirtyStateChanged(m.resource, m.isDirty()); } })); this._store.add(workingCopyFileService.onDidRunWorkingCopyFileOperation(e => { const isMove = e.operation === FileOperation.MOVE; if (isMove || e.operation === FileOperation.DELETE) { for (const pair of e.files) { const removed = isMove ? pair.source : pair.target; if (removed) { this._modelReferenceCollection.remove(removed); } } } })); } dispose() { dispose(( this._modelTrackers.values())); this._modelTrackers.clear(); super.dispose(); } isCaughtUpWithContentChanges(resource) { const tracker = this._modelTrackers.get(resource); if (tracker) { return tracker.isCaughtUpWithContentChanges(); } return true; } _shouldHandleFileEvent(resource) { const model = this._modelService.getModel(resource); return !!model && shouldSynchronizeModel(model); } handleModelAdded(model) { if (!shouldSynchronizeModel(model)) { return; } this._modelTrackers.set(model.uri, ( new ModelTracker( model, this._onIsCaughtUpWithContentChanges, this._proxy, this._textFileService ))); } _onModelModeChanged(event) { const { model } = event; if (!( this._modelTrackers.has(model.uri))) { return; } this._proxy.$acceptModelLanguageChanged(model.uri, model.getLanguageId()); } handleModelRemoved(modelUrl) { if (!( this._modelTrackers.has(modelUrl))) { return; } this._modelTrackers.get(modelUrl).dispose(); this._modelTrackers.delete(modelUrl); } async $trySaveDocument(uri) { const target = await this._textFileService.save(URI.revive(uri)); return Boolean(target); } async $tryOpenDocument(uriData) { const inputUri = URI.revive(uriData); if (!inputUri.scheme || !(inputUri.fsPath || inputUri.authority)) { throw ( new ErrorNoTelemetry(`Invalid uri. Scheme and authority or path must be set.`)); } const canonicalUri = this._uriIdentityService.asCanonicalUri(inputUri); let promise; switch (canonicalUri.scheme) { case Schemas.untitled: promise = this._handleUntitledScheme(canonicalUri); break; case Schemas.file: default: promise = this._handleAsResourceInput(canonicalUri); break; } let documentUri; try { documentUri = await promise; } catch (err) { throw ( new ErrorNoTelemetry(`cannot open ${( canonicalUri.toString())}. Detail: ${toErrorMessage(err)}`)); } if (!documentUri) { throw ( new ErrorNoTelemetry(`cannot open ${( canonicalUri.toString())}`)); } else if (!extUri.isEqual(documentUri, canonicalUri)) { throw ( new ErrorNoTelemetry(`cannot open ${( canonicalUri.toString())}. Detail: Actual document opened as ${( documentUri.toString())}`)); } else if (!( this._modelTrackers.has(canonicalUri))) { throw ( new ErrorNoTelemetry(`cannot open ${( canonicalUri.toString())}. Detail: Files above 50MB cannot be synchronized with extensions.`)); } else { return canonicalUri; } } $tryCreateDocument(options) { return this._doCreateUntitled(undefined, options ? options.language : undefined, options ? options.content : undefined); } async _handleAsResourceInput(uri) { const ref = await this._textModelResolverService.createModelReference(uri); this._modelReferenceCollection.add(uri, ref, ref.object.textEditorModel.getValueLength()); return ref.object.textEditorModel.uri; } async _handleUntitledScheme(uri) { const asLocalUri = toLocalResource(uri, this._environmentService.remoteAuthority, this._pathService.defaultUriScheme); const exists = await this._fileService.exists(asLocalUri); if (exists) { return Promise.reject(( new Error('file already exists'))); } return await this._doCreateUntitled(Boolean(uri.path) ? uri : undefined); } async _doCreateUntitled(associatedResource, languageId, initialValue) { const model = this._textFileService.untitled.create({ associatedResource, languageId, initialValue }); const resource = model.resource; const ref = await this._textModelResolverService.createModelReference(resource); if (!( this._modelTrackers.has(resource))) { ref.dispose(); throw ( new Error(`expected URI ${( resource.toString())} to have come to LIFE`)); } this._modelReferenceCollection.add(resource, ref, ref.object.textEditorModel.getValueLength()); Event.once(model.onDidRevert)(() => this._modelReferenceCollection.remove(resource)); this._proxy.$acceptDirtyStateChanged(resource, true); return resource; } }; MainThreadDocuments = ( __decorate([ ( __param(1, IModelService)), ( __param(2, ITextFileService)), ( __param(3, IFileService)), ( __param(4, ITextModelService)), ( __param(5, IWorkbenchEnvironmentService)), ( __param(6, IUriIdentityService)), ( __param(7, IWorkingCopyFileService)), ( __param(8, IPathService)) ], MainThreadDocuments)); export { BoundModelReferenceCollection, MainThreadDocuments };