UNPKG

7.03 kBJavaScriptView Raw
1"use strict";
2// *****************************************************************************
3// Copyright (C) 2020 Red Hat, Inc. and others.
4//
5// This program and the accompanying materials are made available under the
6// terms of the Eclipse Public License v. 2.0 which is available at
7// http://www.eclipse.org/legal/epl-2.0.
8//
9// This Source Code may also be made available under the following Secondary
10// Licenses when the conditions for such availability set forth in the Eclipse
11// Public License v. 2.0 are satisfied: GNU General Public License, version 2
12// with the GNU Classpath Exception which is available at
13// https://www.gnu.org/software/classpath/license.html.
14//
15// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
16// *****************************************************************************
17var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
18 var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
19 if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
20 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;
21 return c > 3 && r && Object.defineProperty(target, key, r), r;
22};
23Object.defineProperty(exports, "__esModule", { value: true });
24exports.DecorationsServiceImpl = exports.DecorationsService = void 0;
25const inversify_1 = require("inversify");
26const promise_util_1 = require("../common/promise-util");
27const common_1 = require("../common");
28const ternary_search_tree_1 = require("../common/ternary-search-tree");
29const uri_1 = require("../common/uri");
30exports.DecorationsService = Symbol('DecorationsService');
31class DecorationDataRequest {
32 constructor(source, thenable) {
33 this.source = source;
34 this.thenable = thenable;
35 }
36}
37class DecorationProviderWrapper {
38 constructor(provider, onDidChangeDecorationsEmitter) {
39 this.provider = provider;
40 this.onDidChangeDecorationsEmitter = onDidChangeDecorationsEmitter;
41 this.decorations = new Map();
42 this.data = ternary_search_tree_1.TernarySearchTree.forUris(true);
43 this.disposable = this.provider.onDidChange(async (uris) => {
44 this.decorations.clear();
45 if (!uris) {
46 this.data.clear();
47 }
48 else {
49 for (const uri of uris) {
50 this.fetchData(new uri_1.default(uri.toString()));
51 const decoration = await provider.provideDecorations(uri, common_1.CancellationToken.None);
52 if (decoration) {
53 this.decorations.set(uri.toString(), decoration);
54 }
55 }
56 }
57 this.onDidChangeDecorationsEmitter.fire(this.decorations);
58 });
59 }
60 dispose() {
61 this.disposable.dispose();
62 this.data.clear();
63 }
64 knowsAbout(uri) {
65 return !!this.data.get(uri) || Boolean(this.data.findSuperstr(uri));
66 }
67 getOrRetrieve(uri, includeChildren, callback) {
68 let item = this.data.get(uri);
69 if (item === undefined) {
70 // unknown -> trigger request
71 item = this.fetchData(uri);
72 }
73 if (item && !(item instanceof DecorationDataRequest)) {
74 // found something (which isn't pending anymore)
75 callback(item, false);
76 }
77 if (includeChildren) {
78 // (resolved) children
79 const iter = this.data.findSuperstr(uri);
80 if (iter) {
81 let next = iter.next();
82 while (!next.done) {
83 const value = next.value;
84 if (value && !(value instanceof DecorationDataRequest)) {
85 callback(value, true);
86 }
87 next = iter.next();
88 }
89 }
90 }
91 }
92 fetchData(uri) {
93 // check for pending request and cancel it
94 const pendingRequest = this.data.get(new uri_1.default(uri.toString()));
95 if (pendingRequest instanceof DecorationDataRequest) {
96 pendingRequest.source.cancel();
97 this.data.delete(uri);
98 }
99 const source = new common_1.CancellationTokenSource();
100 const dataOrThenable = this.provider.provideDecorations(new uri_1.default(uri.toString()), source.token);
101 if (!(0, promise_util_1.isThenable)(dataOrThenable)) {
102 // sync -> we have a result now
103 return this.keepItem(uri, dataOrThenable);
104 }
105 else {
106 // async -> we have a result soon
107 const request = new DecorationDataRequest(source, Promise.resolve(dataOrThenable).then(data => {
108 if (this.data.get(uri) === request) {
109 this.keepItem(uri, data);
110 }
111 }).catch(err => {
112 if (!(err instanceof Error && err.name === 'Canceled' && err.message === 'Canceled') && this.data.get(uri) === request) {
113 this.data.delete(uri);
114 }
115 }));
116 this.data.set(uri, request);
117 return undefined;
118 }
119 }
120 keepItem(uri, data) {
121 const deco = data ? data : undefined;
122 this.data.set(uri, deco);
123 return deco;
124 }
125}
126let DecorationsServiceImpl = class DecorationsServiceImpl {
127 constructor() {
128 this.data = [];
129 this.onDidChangeDecorationsEmitter = new common_1.Emitter();
130 this.onDidChangeDecorations = this.onDidChangeDecorationsEmitter.event;
131 }
132 dispose() {
133 this.onDidChangeDecorationsEmitter.dispose();
134 }
135 registerDecorationsProvider(provider) {
136 const wrapper = new DecorationProviderWrapper(provider, this.onDidChangeDecorationsEmitter);
137 this.data.push(wrapper);
138 return common_1.Disposable.create(() => {
139 // fire event that says 'yes' for any resource
140 // known to this provider. then dispose and remove it.
141 this.data.splice(this.data.indexOf(wrapper), 1);
142 this.onDidChangeDecorationsEmitter.fire(new Map());
143 wrapper.dispose();
144 });
145 }
146 getDecoration(uri, includeChildren) {
147 const data = [];
148 let containsChildren = false;
149 for (const wrapper of this.data) {
150 wrapper.getOrRetrieve(new uri_1.default(uri.toString()), includeChildren, (deco, isChild) => {
151 if (!isChild || deco.bubble) {
152 data.push(deco);
153 containsChildren = isChild || containsChildren;
154 }
155 });
156 }
157 return data;
158 }
159};
160DecorationsServiceImpl = __decorate([
161 (0, inversify_1.injectable)()
162], DecorationsServiceImpl);
163exports.DecorationsServiceImpl = DecorationsServiceImpl;
164//# sourceMappingURL=decorations-service.js.map
\No newline at end of file