@theia/core
Version:
Theia is a cloud & desktop IDE framework implemented in TypeScript.
164 lines • 7.03 kB
JavaScript
"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-only 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