UNPKG

@theia/core

Version:

Theia is a cloud & desktop IDE framework implemented in TypeScript.

164 lines 7.03 kB
"use strict"; // ***************************************************************************** // Copyright (C) 2020 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 WITH Classpath-exception-2.0 // ***************************************************************************** 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; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.DecorationsServiceImpl = exports.DecorationsService = void 0; const inversify_1 = require("inversify"); const promise_util_1 = require("../common/promise-util"); const common_1 = require("../common"); const ternary_search_tree_1 = require("../common/ternary-search-tree"); const uri_1 = require("../common/uri"); exports.DecorationsService = Symbol('DecorationsService'); class DecorationDataRequest { constructor(source, thenable) { this.source = source; this.thenable = thenable; } } class DecorationProviderWrapper { constructor(provider, onDidChangeDecorationsEmitter) { this.provider = provider; this.onDidChangeDecorationsEmitter = onDidChangeDecorationsEmitter; this.decorations = new Map(); this.data = ternary_search_tree_1.TernarySearchTree.forUris(true); this.disposable = this.provider.onDidChange(async (uris) => { this.decorations.clear(); if (!uris) { this.data.clear(); } else { for (const uri of uris) { this.fetchData(new uri_1.default(uri.toString())); const decoration = await provider.provideDecorations(uri, common_1.CancellationToken.None); if (decoration) { this.decorations.set(uri.toString(), decoration); } } } this.onDidChangeDecorationsEmitter.fire(this.decorations); }); } dispose() { this.disposable.dispose(); this.data.clear(); } knowsAbout(uri) { return !!this.data.get(uri) || Boolean(this.data.findSuperstr(uri)); } getOrRetrieve(uri, includeChildren, callback) { let item = this.data.get(uri); if (item === undefined) { // unknown -> trigger request item = this.fetchData(uri); } if (item && !(item instanceof DecorationDataRequest)) { // found something (which isn't pending anymore) callback(item, false); } if (includeChildren) { // (resolved) children const iter = this.data.findSuperstr(uri); if (iter) { let next = iter.next(); while (!next.done) { const value = next.value; if (value && !(value instanceof DecorationDataRequest)) { callback(value, true); } next = iter.next(); } } } } fetchData(uri) { // check for pending request and cancel it const pendingRequest = this.data.get(new uri_1.default(uri.toString())); if (pendingRequest instanceof DecorationDataRequest) { pendingRequest.source.cancel(); this.data.delete(uri); } const source = new common_1.CancellationTokenSource(); const dataOrThenable = this.provider.provideDecorations(new uri_1.default(uri.toString()), source.token); if (!(0, promise_util_1.isThenable)(dataOrThenable)) { // sync -> we have a result now return this.keepItem(uri, dataOrThenable); } else { // async -> we have a result soon const request = new DecorationDataRequest(source, Promise.resolve(dataOrThenable).then(data => { if (this.data.get(uri) === request) { this.keepItem(uri, data); } }).catch(err => { if (!(err instanceof Error && err.name === 'Canceled' && err.message === 'Canceled') && this.data.get(uri) === request) { this.data.delete(uri); } })); this.data.set(uri, request); return undefined; } } keepItem(uri, data) { const deco = data ? data : undefined; this.data.set(uri, deco); return deco; } } let DecorationsServiceImpl = class DecorationsServiceImpl { constructor() { this.data = []; this.onDidChangeDecorationsEmitter = new common_1.Emitter(); this.onDidChangeDecorations = this.onDidChangeDecorationsEmitter.event; } dispose() { this.onDidChangeDecorationsEmitter.dispose(); } registerDecorationsProvider(provider) { const wrapper = new DecorationProviderWrapper(provider, this.onDidChangeDecorationsEmitter); this.data.push(wrapper); return common_1.Disposable.create(() => { // fire event that says 'yes' for any resource // known to this provider. then dispose and remove it. this.data.splice(this.data.indexOf(wrapper), 1); this.onDidChangeDecorationsEmitter.fire(new Map()); wrapper.dispose(); }); } getDecoration(uri, includeChildren) { const data = []; let containsChildren = false; for (const wrapper of this.data) { wrapper.getOrRetrieve(new uri_1.default(uri.toString()), includeChildren, (deco, isChild) => { if (!isChild || deco.bubble) { data.push(deco); containsChildren = isChild || containsChildren; } }); } return data; } }; DecorationsServiceImpl = __decorate([ (0, inversify_1.injectable)() ], DecorationsServiceImpl); exports.DecorationsServiceImpl = DecorationsServiceImpl; //# sourceMappingURL=decorations-service.js.map