// ***************************************************************************** // Copyright (C) 2018 Red Hat, Inc. and others. // // This program and the accompanying materials are made available under the // terms of the Eclipse Public License v. 2.0 which is available at // http://www.eclipse.org/legal/epl-2.0. // // This Source Code may also be made available under the following Secondary // Licenses when the conditions for such availability set forth in the Eclipse // Public License v. 2.0 are satisfied: GNU General Public License, version 2 // with the GNU Classpath Exception which is available at // https://www.gnu.org/software/classpath/license.html. // // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0 // ***************************************************************************** import { Event, Emitter, ListenerList, Listener } from '@theia/core'; import { MonacoEditorModel, WillSaveMonacoModelEvent } from '@theia/monaco/lib/browser/monaco-editor-model'; import { injectable, inject } from '@theia/core/shared/inversify'; import { MonacoTextModelService } from '@theia/monaco/lib/browser/monaco-text-model-service'; import { MonacoWorkspace } from '@theia/monaco/lib/browser/monaco-workspace'; import { Schemes } from '../../common/uri-components'; import URI from '@theia/core/lib/common/uri'; import { Reference } from '@theia/core/lib/common/reference'; @injectable() export class EditorModelService { private monacoModelService: MonacoTextModelService; private modelModeChangedEmitter = new Emitter<{ model: MonacoEditorModel, oldModeId: string }>(); private onModelRemovedEmitter = new Emitter(); private modelDirtyEmitter = new Emitter(); private modelEncodingEmitter = new Emitter<{ model: MonacoEditorModel, encoding: string }>(); private modelSavedEmitter = new Emitter(); private onModelWillSaveListeners: ListenerList> = new ListenerList(); readonly onModelDirtyChanged = this.modelDirtyEmitter.event; readonly onModelEncodingChanged = this.modelEncodingEmitter.event; readonly onModelWillSave = this.onModelWillSaveListeners.registration; readonly onModelSaved = this.modelSavedEmitter.event; readonly onModelModeChanged = this.modelModeChangedEmitter.event; readonly onModelRemoved = this.onModelRemovedEmitter.event; constructor(@inject(MonacoTextModelService) monacoModelService: MonacoTextModelService, @inject(MonacoWorkspace) monacoWorkspace: MonacoWorkspace) { this.monacoModelService = monacoModelService; monacoModelService.models.forEach(model => this.modelCreated(model)); monacoModelService.onDidCreate(this.modelCreated, this); monacoWorkspace.onDidCloseTextDocument(model => { setTimeout(() => { this.onModelRemovedEmitter.fire(model); }, 1); }); } private modelCreated(model: MonacoEditorModel): void { model.textEditorModel.onDidChangeLanguage(e => { this.modelModeChangedEmitter.fire({ model, oldModeId: e.oldLanguage }); }); model.onDidSaveModel(_ => { this.modelSavedEmitter.fire(model); }); model.onModelWillSaveModel(async (e: WillSaveMonacoModelEvent) => { await Listener.awaitAll(e, this.onModelWillSaveListeners); }); model.onDirtyChanged(_ => { this.modelDirtyEmitter.fire(model); }); model.onDidChangeEncoding(encoding => { this.modelEncodingEmitter.fire({ model, encoding }); }); } get onModelAdded(): Event { return this.monacoModelService.onDidCreate; } getModels(): MonacoEditorModel[] { return this.monacoModelService.models; } async save(uri: URI): Promise { const model = this.monacoModelService.get(uri.toString()); if (model) { await model.save(); return true; } return false; } async saveAll(includeUntitled?: boolean): Promise { const saves = []; for (const model of this.monacoModelService.models) { const { uri } = model.textEditorModel; if (model.dirty && (includeUntitled || uri.scheme !== Schemes.untitled)) { saves.push((async () => { try { await model.save(); return true; } catch (e) { console.error('Failed to save ', uri.toString(), e); return false; } })()); } } const results = await Promise.all(saves); return results.reduce((a, b) => a && b, true); } async createModelReference(uri: URI): Promise> { return this.monacoModelService.createModelReference(uri); } }