@theia/filesystem 1.75.0 → 1.76.0-next.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/browser/file-tree/file-tree-decorator-adapter.d.ts +6 -0
- package/lib/browser/file-tree/file-tree-decorator-adapter.d.ts.map +1 -1
- package/lib/browser/file-tree/file-tree-decorator-adapter.js +24 -0
- package/lib/browser/file-tree/file-tree-decorator-adapter.js.map +1 -1
- package/lib/browser/file-tree/file-tree-decorator-adapter.spec.d.ts +2 -0
- package/lib/browser/file-tree/file-tree-decorator-adapter.spec.d.ts.map +1 -0
- package/lib/browser/file-tree/file-tree-decorator-adapter.spec.js +152 -0
- package/lib/browser/file-tree/file-tree-decorator-adapter.spec.js.map +1 -0
- package/package.json +3 -3
- package/src/browser/file-tree/file-tree-decorator-adapter.spec.ts +181 -0
- package/src/browser/file-tree/file-tree-decorator-adapter.ts +24 -0
|
@@ -12,6 +12,12 @@ export declare class FileTreeDecoratorAdapter implements TreeDecorator {
|
|
|
12
12
|
protected readonly onDidChangeDecorationsEmitter: Emitter<(tree: Tree) => Map<string, TreeDecoration.Data>>;
|
|
13
13
|
protected decorationsByUri: Map<string, TreeDecoration.Data>;
|
|
14
14
|
protected parentDecorations: Map<string, TreeDecoration.Data>;
|
|
15
|
+
/**
|
|
16
|
+
* Resources already queried from the service since the last decoration change event.
|
|
17
|
+
* Undecorated resources never enter {@link decorationsByUri}, so without this set
|
|
18
|
+
* every render pass would re-query (and re-parse the URI of) every undecorated node.
|
|
19
|
+
*/
|
|
20
|
+
protected readonly queriedUris: Set<string>;
|
|
15
21
|
get onDidChangeDecorations(): Event<(tree: Tree) => Map<string, TreeDecoration.Data>>;
|
|
16
22
|
protected init(): void;
|
|
17
23
|
decorations(tree: Tree): MaybePromise<Map<string, TreeDecoration.Data>>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"file-tree-decorator-adapter.d.ts","sourceRoot":"","sources":["../../../src/browser/file-tree/file-tree-decorator-adapter.ts"],"names":[],"mappings":"AAiBA,OAAO,GAAG,MAAM,4BAA4B,CAAC;AAC7C,OAAO,EAAE,KAAK,EAAE,OAAO,EAAO,MAAM,wBAAwB,CAAC;AAC7D,OAAO,EAAE,UAAU,EAAE,kBAAkB,EAAE,MAAM,6CAA6C,CAAC;AAC7F,OAAO,EAAE,QAAQ,EAAE,cAAc,EAAE,aAAa,EAAE,IAAI,EAAuB,MAAM,yBAAyB,CAAC;AAC7G,OAAO,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAC;AAC5D,OAAO,EAAE,aAAa,EAAE,MAAM,wCAAwC,CAAC;AAGvE,qBACa,wBAAyB,YAAW,aAAa;IAC1D,QAAQ,CAAC,EAAE,gDAAgD;IAC3D,SAAS,CAAC,QAAQ,CAAC,aAAa,SAAsD;IAC1D,SAAS,CAAC,QAAQ,CAAC,kBAAkB,EAAE,kBAAkB,CAAC;IAC/D,SAAS,CAAC,QAAQ,CAAC,aAAa,EAAE,aAAa,CAAC;IAEvE,SAAS,CAAC,QAAQ,CAAC,6BAA6B,iBAAsB,IAAI,KAAK,GAAG,CAAC,MAAM,EAAE,cAAc,CAAC,IAAI,CAAC,EAAI;IACnH,SAAS,CAAC,gBAAgB,mCAA0C;IACpE,SAAS,CAAC,iBAAiB,mCAA0C;
|
|
1
|
+
{"version":3,"file":"file-tree-decorator-adapter.d.ts","sourceRoot":"","sources":["../../../src/browser/file-tree/file-tree-decorator-adapter.ts"],"names":[],"mappings":"AAiBA,OAAO,GAAG,MAAM,4BAA4B,CAAC;AAC7C,OAAO,EAAE,KAAK,EAAE,OAAO,EAAO,MAAM,wBAAwB,CAAC;AAC7D,OAAO,EAAE,UAAU,EAAE,kBAAkB,EAAE,MAAM,6CAA6C,CAAC;AAC7F,OAAO,EAAE,QAAQ,EAAE,cAAc,EAAE,aAAa,EAAE,IAAI,EAAuB,MAAM,yBAAyB,CAAC;AAC7G,OAAO,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAC;AAC5D,OAAO,EAAE,aAAa,EAAE,MAAM,wCAAwC,CAAC;AAGvE,qBACa,wBAAyB,YAAW,aAAa;IAC1D,QAAQ,CAAC,EAAE,gDAAgD;IAC3D,SAAS,CAAC,QAAQ,CAAC,aAAa,SAAsD;IAC1D,SAAS,CAAC,QAAQ,CAAC,kBAAkB,EAAE,kBAAkB,CAAC;IAC/D,SAAS,CAAC,QAAQ,CAAC,aAAa,EAAE,aAAa,CAAC;IAEvE,SAAS,CAAC,QAAQ,CAAC,6BAA6B,iBAAsB,IAAI,KAAK,GAAG,CAAC,MAAM,EAAE,cAAc,CAAC,IAAI,CAAC,EAAI;IACnH,SAAS,CAAC,gBAAgB,mCAA0C;IACpE,SAAS,CAAC,iBAAiB,mCAA0C;IACrE;;;;OAIG;IACH,SAAS,CAAC,QAAQ,CAAC,WAAW,cAAqB;IAEnD,IAAI,sBAAsB,IAAI,KAAK,CAAC,CAAC,IAAI,EAAE,IAAI,KAAK,GAAG,CAAC,MAAM,EAAE,cAAc,CAAC,IAAI,CAAC,CAAC,CAEpF;IAGD,SAAS,CAAC,IAAI,IAAI,IAAI;IAQtB,WAAW,CAAC,IAAI,EAAE,IAAI,GAAG,YAAY,CAAC,GAAG,CAAC,MAAM,EAAE,cAAc,CAAC,IAAI,CAAC,CAAC;IAIvE,SAAS,CAAC,kBAAkB,CAAC,IAAI,EAAE,IAAI,GAAG,GAAG,CAAC,MAAM,EAAE,cAAc,CAAC,IAAI,CAAC;IAmC1E,SAAS,CAAC,gBAAgB,CAAC,aAAa,CAAC,EAAE,cAAc,CAAC,IAAI,EAAE,iBAAiB,CAAC,EAAE,cAAc,CAAC,IAAI,GAAG,cAAc,CAAC,IAAI,GAAG,SAAS;IAczI,SAAS,CAAC,iBAAiB,CAAC,OAAO,EAAE,gBAAgB,CAAC,MAAM,CAAC,EAAE,OAAO,EAAE,gBAAgB,CAAC,MAAM,CAAC,GAAG,IAAI;IAuBvG,SAAS,CAAC,iBAAiB,CAAC,WAAW,EAAE,UAAU,EAAE,EAAE,MAAM,CAAC,EAAE,OAAO,GAAG,cAAc,CAAC,IAAI;IAU7F,SAAS,CAAC,gBAAgB,CAAC,UAAU,EAAE,UAAU,EAAE,QAAQ,CAAC,EAAE,cAAc,CAAC,QAAQ,EAAE,MAAM,CAAC,EAAE,OAAO,GAAG,cAAc,CAAC,cAAc,CAAC,WAAW;IAOnJ,SAAS,CAAC,yBAAyB,CAAC,KAAK,EAAE,GAAG,EAAE,WAAW,EAAE,UAAU,EAAE,GAAG,IAAI;IAoBhF;;OAEG;IACH,SAAS,CAAC,aAAa,CAAC,IAAI,EAAE,UAAU,EAAE,KAAK,EAAE,UAAU,GAAG,MAAM;IAIpE,SAAS,CAAC,aAAa,CAAC,IAAI,EAAE,QAAQ,GAAG,MAAM,GAAG,SAAS;IAI3D,wBAAwB,IAAI,IAAI;CAGnC"}
|
|
@@ -31,12 +31,19 @@ let FileTreeDecoratorAdapter = class FileTreeDecoratorAdapter {
|
|
|
31
31
|
this.onDidChangeDecorationsEmitter = new common_1.Emitter();
|
|
32
32
|
this.decorationsByUri = new Map();
|
|
33
33
|
this.parentDecorations = new Map();
|
|
34
|
+
/**
|
|
35
|
+
* Resources already queried from the service since the last decoration change event.
|
|
36
|
+
* Undecorated resources never enter {@link decorationsByUri}, so without this set
|
|
37
|
+
* every render pass would re-query (and re-parse the URI of) every undecorated node.
|
|
38
|
+
*/
|
|
39
|
+
this.queriedUris = new Set();
|
|
34
40
|
}
|
|
35
41
|
get onDidChangeDecorations() {
|
|
36
42
|
return this.onDidChangeDecorationsEmitter.event;
|
|
37
43
|
}
|
|
38
44
|
init() {
|
|
39
45
|
this.decorationsService.onDidChangeDecorations(newDecorations => {
|
|
46
|
+
this.queriedUris.clear();
|
|
40
47
|
this.updateDecorations(this.decorationsByUri.keys(), newDecorations.keys());
|
|
41
48
|
this.fireDidChangeDecorations();
|
|
42
49
|
});
|
|
@@ -51,6 +58,22 @@ let FileTreeDecoratorAdapter = class FileTreeDecoratorAdapter {
|
|
|
51
58
|
const uri = this.getUriForNode(node);
|
|
52
59
|
if (uri) {
|
|
53
60
|
const stringified = uri.toString();
|
|
61
|
+
if (!this.decorationsByUri.has(stringified) && !this.queriedUris.has(stringified)) {
|
|
62
|
+
// Query the service once per change event for resources this decorator
|
|
63
|
+
// has not seen, so that decorations dropped from change events (e.g. by
|
|
64
|
+
// the plugin-ext event cap, see #17507) are fetched on demand. The
|
|
65
|
+
// service caches results, including "no decoration": known resources
|
|
66
|
+
// resolve synchronously and undecorated ones are not fetched again.
|
|
67
|
+
// Resolved fetches arrive as a single batched change event handled in
|
|
68
|
+
// updateDecorations.
|
|
69
|
+
this.queriedUris.add(stringified);
|
|
70
|
+
const nodeUri = new uri_1.default(stringified);
|
|
71
|
+
const fetched = this.decorationsService.getDecoration(nodeUri, false);
|
|
72
|
+
if (fetched.length) {
|
|
73
|
+
this.decorationsByUri.set(stringified, this.toTheiaDecoration(fetched, false));
|
|
74
|
+
this.propagateDecorationsByUri(nodeUri, fetched);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
54
77
|
const ownDecoration = this.decorationsByUri.get(stringified);
|
|
55
78
|
const bubbledDecoration = this.parentDecorations.get(stringified);
|
|
56
79
|
const combined = this.mergeDecorations(ownDecoration, bubbledDecoration);
|
|
@@ -82,6 +105,7 @@ let FileTreeDecoratorAdapter = class FileTreeDecoratorAdapter {
|
|
|
82
105
|
const newDecorations = new Map();
|
|
83
106
|
const handleUri = (rawUri) => {
|
|
84
107
|
if (!newDecorations.has(rawUri)) {
|
|
108
|
+
this.queriedUris.add(rawUri);
|
|
85
109
|
const uri = new uri_1.default(rawUri);
|
|
86
110
|
const decorations = this.decorationsService.getDecoration(uri, false);
|
|
87
111
|
if (decorations.length) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"file-tree-decorator-adapter.js","sourceRoot":"","sources":["../../../src/browser/file-tree/file-tree-decorator-adapter.ts"],"names":[],"mappings":";AAAA,gFAAgF;AAChF,0CAA0C;AAC1C,EAAE;AACF,2EAA2E;AAC3E,mEAAmE;AACnE,wCAAwC;AACxC,EAAE;AACF,4EAA4E;AAC5E,8EAA8E;AAC9E,6EAA6E;AAC7E,yDAAyD;AACzD,uDAAuD;AACvD,EAAE;AACF,gFAAgF;AAChF,gFAAgF;;;;AAEhF,4DAAiF;AACjF,oDAA6C;AAC7C,mDAA6D;AAC7D,qFAA6F;AAC7F,qDAA6G;AAE7G,2EAAuE;AACvE,2CAA2C;AAGpC,IAAM,wBAAwB,GAA9B,MAAM,wBAAwB;IAA9B;QACM,OAAE,GAAG,4CAA4C,CAAC;QACxC,kBAAa,GAAG,YAAG,CAAC,iBAAiB,CAAC,2BAA2B,CAAC,CAAC;QAInE,kCAA6B,GAAG,IAAI,gBAAO,EAAoD,CAAC;QACzG,qBAAgB,GAAG,IAAI,GAAG,EAA+B,CAAC;QAC1D,sBAAiB,GAAG,IAAI,GAAG,EAA+B,CAAC;
|
|
1
|
+
{"version":3,"file":"file-tree-decorator-adapter.js","sourceRoot":"","sources":["../../../src/browser/file-tree/file-tree-decorator-adapter.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"file-tree-decorator-adapter.spec.d.ts","sourceRoot":"","sources":["../../../src/browser/file-tree/file-tree-decorator-adapter.spec.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// *****************************************************************************
|
|
3
|
+
// Copyright (C) 2026 Safi Seid-Ahmad, K2view 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
|
+
// *****************************************************************************
|
|
17
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
18
|
+
const jsdom_1 = require("@theia/core/lib/browser/test/jsdom");
|
|
19
|
+
let disableJSDOM = (0, jsdom_1.enableJSDOM)();
|
|
20
|
+
const color_registry_1 = require("@theia/core/lib/browser/color-registry");
|
|
21
|
+
const decorations_service_1 = require("@theia/core/lib/browser/decorations-service");
|
|
22
|
+
const common_1 = require("@theia/core/lib/common");
|
|
23
|
+
const uri_1 = require("@theia/core/lib/common/uri");
|
|
24
|
+
const inversify_1 = require("@theia/core/shared/inversify");
|
|
25
|
+
const chai_1 = require("chai");
|
|
26
|
+
const file_tree_decorator_adapter_1 = require("./file-tree-decorator-adapter");
|
|
27
|
+
disableJSDOM();
|
|
28
|
+
class TestDecorationsProvider {
|
|
29
|
+
constructor() {
|
|
30
|
+
this.onDidChangeEmitter = new common_1.Emitter();
|
|
31
|
+
this.decorations = new Map();
|
|
32
|
+
this.queried = [];
|
|
33
|
+
}
|
|
34
|
+
get onDidChange() {
|
|
35
|
+
return this.onDidChangeEmitter.event;
|
|
36
|
+
}
|
|
37
|
+
fireDidChange(uris) {
|
|
38
|
+
this.onDidChangeEmitter.fire(uris);
|
|
39
|
+
}
|
|
40
|
+
provideDecorations(uri, token) {
|
|
41
|
+
this.queried.push(uri.toString());
|
|
42
|
+
return Promise.resolve(this.decorations.get(uri.toString()));
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
function createTree(uris) {
|
|
46
|
+
const root = {
|
|
47
|
+
id: 'root',
|
|
48
|
+
name: 'root',
|
|
49
|
+
parent: undefined,
|
|
50
|
+
children: []
|
|
51
|
+
};
|
|
52
|
+
const children = uris.map(uri => ({
|
|
53
|
+
id: uri,
|
|
54
|
+
name: new uri_1.default(uri).path.base,
|
|
55
|
+
parent: root,
|
|
56
|
+
fileStat: { resource: new uri_1.default(uri) }
|
|
57
|
+
}));
|
|
58
|
+
children.forEach((child, index) => Object.assign(child, { nextSibling: children[index + 1] }));
|
|
59
|
+
Object.assign(root, { children });
|
|
60
|
+
return { root };
|
|
61
|
+
}
|
|
62
|
+
const sleep = (ms) => new Promise(resolve => setTimeout(resolve, ms));
|
|
63
|
+
describe('FileTreeDecoratorAdapter', () => {
|
|
64
|
+
before(() => {
|
|
65
|
+
disableJSDOM = (0, jsdom_1.enableJSDOM)();
|
|
66
|
+
});
|
|
67
|
+
after(() => {
|
|
68
|
+
disableJSDOM();
|
|
69
|
+
});
|
|
70
|
+
const fileUris = ['file:///project/f1.ts', 'file:///project/f2.ts', 'file:///project/f3.ts'];
|
|
71
|
+
let service;
|
|
72
|
+
let provider;
|
|
73
|
+
let adapter;
|
|
74
|
+
let tree;
|
|
75
|
+
beforeEach(() => {
|
|
76
|
+
service = new decorations_service_1.DecorationsServiceImpl();
|
|
77
|
+
provider = new TestDecorationsProvider();
|
|
78
|
+
service.registerDecorationsProvider(provider);
|
|
79
|
+
const container = new inversify_1.Container();
|
|
80
|
+
container.bind(decorations_service_1.DecorationsService).toConstantValue(service);
|
|
81
|
+
container.bind(color_registry_1.ColorRegistry).toSelf().inSingletonScope();
|
|
82
|
+
container.bind(file_tree_decorator_adapter_1.FileTreeDecoratorAdapter).toSelf().inSingletonScope();
|
|
83
|
+
adapter = container.get(file_tree_decorator_adapter_1.FileTreeDecoratorAdapter);
|
|
84
|
+
tree = createTree(fileUris);
|
|
85
|
+
});
|
|
86
|
+
afterEach(() => {
|
|
87
|
+
service.dispose();
|
|
88
|
+
});
|
|
89
|
+
it('fetches decorations on demand for resources never mentioned in a change event', async () => {
|
|
90
|
+
for (const uri of fileUris) {
|
|
91
|
+
provider.decorations.set(uri, { letter: 'U', bubble: true });
|
|
92
|
+
}
|
|
93
|
+
// simulates a render: nothing decorated yet, but fetches are triggered
|
|
94
|
+
(0, chai_1.expect)(await adapter.decorations(tree)).to.have.lengthOf(0);
|
|
95
|
+
await sleep(20);
|
|
96
|
+
const decorations = await adapter.decorations(tree);
|
|
97
|
+
for (const uri of fileUris) {
|
|
98
|
+
(0, chai_1.expect)(decorations.has(uri), uri).to.equal(true);
|
|
99
|
+
}
|
|
100
|
+
});
|
|
101
|
+
it('does not re-query the provider for undecorated resources on repeated renders', async () => {
|
|
102
|
+
await adapter.decorations(tree);
|
|
103
|
+
await sleep(20);
|
|
104
|
+
const queriesAfterFirstRender = provider.queried.length;
|
|
105
|
+
await adapter.decorations(tree);
|
|
106
|
+
await adapter.decorations(tree);
|
|
107
|
+
await sleep(20);
|
|
108
|
+
(0, chai_1.expect)(provider.queried.length).to.equal(queriesAfterFirstRender);
|
|
109
|
+
});
|
|
110
|
+
it('does not query the decorations service for undecorated resources on repeated renders', async () => {
|
|
111
|
+
const originalGetDecoration = service.getDecoration.bind(service);
|
|
112
|
+
let queries = 0;
|
|
113
|
+
service.getDecoration = (uri, includeChildren) => {
|
|
114
|
+
queries++;
|
|
115
|
+
return originalGetDecoration(uri, includeChildren);
|
|
116
|
+
};
|
|
117
|
+
await adapter.decorations(tree);
|
|
118
|
+
await sleep(20);
|
|
119
|
+
const queriesAfterFirstRender = queries;
|
|
120
|
+
await adapter.decorations(tree);
|
|
121
|
+
await adapter.decorations(tree);
|
|
122
|
+
(0, chai_1.expect)(queries).to.equal(queriesAfterFirstRender);
|
|
123
|
+
});
|
|
124
|
+
it('recovers decorations of resources cached as undecorated after a flush event', async () => {
|
|
125
|
+
// resources are queried before the provider has any data, e.g. before
|
|
126
|
+
// the initial git status is computed
|
|
127
|
+
await adapter.decorations(tree);
|
|
128
|
+
await sleep(20);
|
|
129
|
+
(0, chai_1.expect)(await adapter.decorations(tree)).to.have.lengthOf(0);
|
|
130
|
+
// data becomes available, but the change event exceeds the plugin-ext
|
|
131
|
+
// event cap and arrives as a flush (see #17507)
|
|
132
|
+
for (const uri of fileUris) {
|
|
133
|
+
provider.decorations.set(uri, { letter: 'M' });
|
|
134
|
+
}
|
|
135
|
+
let treeInvalidated = false;
|
|
136
|
+
adapter.onDidChangeDecorations(() => {
|
|
137
|
+
treeInvalidated = true;
|
|
138
|
+
});
|
|
139
|
+
provider.fireDidChange(undefined);
|
|
140
|
+
await sleep(20);
|
|
141
|
+
(0, chai_1.expect)(treeInvalidated, 'flush must invalidate the tree decorations').to.equal(true);
|
|
142
|
+
// the invalidation makes the tree render, which re-fetches on demand ...
|
|
143
|
+
await adapter.decorations(tree);
|
|
144
|
+
await sleep(20);
|
|
145
|
+
// ... and the next render shows every decoration
|
|
146
|
+
const decorations = await adapter.decorations(tree);
|
|
147
|
+
for (const uri of fileUris) {
|
|
148
|
+
(0, chai_1.expect)(decorations.get(uri)?.tailDecorations?.some(tail => 'data' in tail && tail.data === 'M'), uri).to.equal(true);
|
|
149
|
+
}
|
|
150
|
+
});
|
|
151
|
+
});
|
|
152
|
+
//# sourceMappingURL=file-tree-decorator-adapter.spec.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"file-tree-decorator-adapter.spec.js","sourceRoot":"","sources":["../../../src/browser/file-tree/file-tree-decorator-adapter.spec.ts"],"names":[],"mappings":";AAAA,gFAAgF;AAChF,yDAAyD;AACzD,EAAE;AACF,2EAA2E;AAC3E,mEAAmE;AACnE,wCAAwC;AACxC,EAAE;AACF,4EAA4E;AAC5E,8EAA8E;AAC9E,6EAA6E;AAC7E,yDAAyD;AACzD,uDAAuD;AACvD,EAAE;AACF,gFAAgF;AAChF,gFAAgF;;AAEhF,8DAAiE;AACjE,IAAI,YAAY,GAAG,IAAA,mBAAW,GAAE,CAAC;AAEjC,2EAAuE;AACvE,qFAA0I;AAE1I,mDAA2E;AAC3E,oDAA6C;AAC7C,4DAAyD;AACzD,+BAA8B;AAC9B,+EAAyE;AAEzE,YAAY,EAAE,CAAC;AAEf,MAAM,uBAAuB;IAA7B;QAEuB,uBAAkB,GAAG,IAAI,gBAAO,EAAqB,CAAC;QAChE,gBAAW,GAAG,IAAI,GAAG,EAAsB,CAAC;QAC5C,YAAO,GAAa,EAAE,CAAC;IAcpC,CAAC;IAZG,IAAI,WAAW;QACX,OAAO,IAAI,CAAC,kBAAkB,CAAC,KAAK,CAAC;IACzC,CAAC;IAED,aAAa,CAAC,IAAY;QACtB,IAAI,CAAC,kBAAkB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACvC,CAAC;IAED,kBAAkB,CAAC,GAAQ,EAAE,KAAwB;QACjD,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,QAAQ,EAAE,CAAC,CAAC;QAClC,OAAO,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,GAAG,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC;IACjE,CAAC;CACJ;AAED,SAAS,UAAU,CAAC,IAAc;IAC9B,MAAM,IAAI,GAAG;QACT,EAAE,EAAE,MAAM;QACV,IAAI,EAAE,MAAM;QACZ,MAAM,EAAE,SAAS;QACjB,QAAQ,EAAE,EAAE;KACiB,CAAC;IAClC,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAC9B,EAAE,EAAE,GAAG;QACP,IAAI,EAAE,IAAI,aAAG,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,IAAI;QAC5B,MAAM,EAAE,IAAI;QACZ,QAAQ,EAAE,EAAE,QAAQ,EAAE,IAAI,aAAG,CAAC,GAAG,CAAC,EAAE;KACvC,CAAC,CAAC,CAAC;IACJ,QAAQ,CAAC,OAAO,CAAC,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,KAAK,EAAE,EAAE,WAAW,EAAE,QAAQ,CAAC,KAAK,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IAC/F,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,EAAE,QAAQ,EAAE,CAAC,CAAC;IAClC,OAAO,EAAE,IAAI,EAAqB,CAAC;AACvC,CAAC;AAED,MAAM,KAAK,GAAG,CAAC,EAAU,EAAiB,EAAE,CAAC,IAAI,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,CAAC;AAE7F,QAAQ,CAAC,0BAA0B,EAAE,GAAG,EAAE;IAEtC,MAAM,CAAC,GAAG,EAAE;QACR,YAAY,GAAG,IAAA,mBAAW,GAAE,CAAC;IACjC,CAAC,CAAC,CAAC;IAEH,KAAK,CAAC,GAAG,EAAE;QACP,YAAY,EAAE,CAAC;IACnB,CAAC,CAAC,CAAC;IAEH,MAAM,QAAQ,GAAG,CAAC,uBAAuB,EAAE,uBAAuB,EAAE,uBAAuB,CAAC,CAAC;IAE7F,IAAI,OAA+B,CAAC;IACpC,IAAI,QAAiC,CAAC;IACtC,IAAI,OAAiC,CAAC;IACtC,IAAI,IAAU,CAAC;IAEf,UAAU,CAAC,GAAG,EAAE;QACZ,OAAO,GAAG,IAAI,4CAAsB,EAAE,CAAC;QACvC,QAAQ,GAAG,IAAI,uBAAuB,EAAE,CAAC;QACzC,OAAO,CAAC,2BAA2B,CAAC,QAAQ,CAAC,CAAC;QAE9C,MAAM,SAAS,GAAG,IAAI,qBAAS,EAAE,CAAC;QAClC,SAAS,CAAC,IAAI,CAAC,wCAAkB,CAAC,CAAC,eAAe,CAAC,OAAO,CAAC,CAAC;QAC5D,SAAS,CAAC,IAAI,CAAC,8BAAa,CAAC,CAAC,MAAM,EAAE,CAAC,gBAAgB,EAAE,CAAC;QAC1D,SAAS,CAAC,IAAI,CAAC,sDAAwB,CAAC,CAAC,MAAM,EAAE,CAAC,gBAAgB,EAAE,CAAC;QACrE,OAAO,GAAG,SAAS,CAAC,GAAG,CAAC,sDAAwB,CAAC,CAAC;QAElD,IAAI,GAAG,UAAU,CAAC,QAAQ,CAAC,CAAC;IAChC,CAAC,CAAC,CAAC;IAEH,SAAS,CAAC,GAAG,EAAE;QACX,OAAO,CAAC,OAAO,EAAE,CAAC;IACtB,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,+EAA+E,EAAE,KAAK,IAAI,EAAE;QAC3F,KAAK,MAAM,GAAG,IAAI,QAAQ,EAAE,CAAC;YACzB,QAAQ,CAAC,WAAW,CAAC,GAAG,CAAC,GAAG,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC;QACjE,CAAC;QAED,uEAAuE;QACvE,IAAA,aAAM,EAAC,MAAM,OAAO,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;QAC5D,MAAM,KAAK,CAAC,EAAE,CAAC,CAAC;QAEhB,MAAM,WAAW,GAAG,MAAM,OAAO,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC;QACpD,KAAK,MAAM,GAAG,IAAI,QAAQ,EAAE,CAAC;YACzB,IAAA,aAAM,EAAC,WAAW,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,GAAG,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QACrD,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,8EAA8E,EAAE,KAAK,IAAI,EAAE;QAC1F,MAAM,OAAO,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC;QAChC,MAAM,KAAK,CAAC,EAAE,CAAC,CAAC;QAChB,MAAM,uBAAuB,GAAG,QAAQ,CAAC,OAAO,CAAC,MAAM,CAAC;QAExD,MAAM,OAAO,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC;QAChC,MAAM,OAAO,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC;QAChC,MAAM,KAAK,CAAC,EAAE,CAAC,CAAC;QAEhB,IAAA,aAAM,EAAC,QAAQ,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,uBAAuB,CAAC,CAAC;IACtE,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,sFAAsF,EAAE,KAAK,IAAI,EAAE;QAClG,MAAM,qBAAqB,GAAG,OAAO,CAAC,aAAa,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QAClE,IAAI,OAAO,GAAG,CAAC,CAAC;QAChB,OAAO,CAAC,aAAa,GAAG,CAAC,GAAG,EAAE,eAAe,EAAE,EAAE;YAC7C,OAAO,EAAE,CAAC;YACV,OAAO,qBAAqB,CAAC,GAAG,EAAE,eAAe,CAAC,CAAC;QACvD,CAAC,CAAC;QACF,MAAM,OAAO,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC;QAChC,MAAM,KAAK,CAAC,EAAE,CAAC,CAAC;QAChB,MAAM,uBAAuB,GAAG,OAAO,CAAC;QAExC,MAAM,OAAO,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC;QAChC,MAAM,OAAO,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC;QAEhC,IAAA,aAAM,EAAC,OAAO,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,uBAAuB,CAAC,CAAC;IACtD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,6EAA6E,EAAE,KAAK,IAAI,EAAE;QACzF,sEAAsE;QACtE,qCAAqC;QACrC,MAAM,OAAO,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC;QAChC,MAAM,KAAK,CAAC,EAAE,CAAC,CAAC;QAChB,IAAA,aAAM,EAAC,MAAM,OAAO,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;QAE5D,sEAAsE;QACtE,gDAAgD;QAChD,KAAK,MAAM,GAAG,IAAI,QAAQ,EAAE,CAAC;YACzB,QAAQ,CAAC,WAAW,CAAC,GAAG,CAAC,GAAG,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,CAAC;QACnD,CAAC;QACD,IAAI,eAAe,GAAG,KAAK,CAAC;QAC5B,OAAO,CAAC,sBAAsB,CAAC,GAAG,EAAE;YAChC,eAAe,GAAG,IAAI,CAAC;QAC3B,CAAC,CAAC,CAAC;QACH,QAAQ,CAAC,aAAa,CAAC,SAAS,CAAC,CAAC;QAClC,MAAM,KAAK,CAAC,EAAE,CAAC,CAAC;QAChB,IAAA,aAAM,EAAC,eAAe,EAAE,4CAA4C,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAErF,yEAAyE;QACzE,MAAM,OAAO,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC;QAChC,MAAM,KAAK,CAAC,EAAE,CAAC,CAAC;QAEhB,iDAAiD;QACjD,MAAM,WAAW,GAAG,MAAM,OAAO,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC;QACpD,KAAK,MAAM,GAAG,IAAI,QAAQ,EAAE,CAAC;YACzB,IAAA,aAAM,EAAC,WAAW,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,eAAe,EAAE,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,MAAM,IAAI,IAAI,IAAI,IAAI,CAAC,IAAI,KAAK,GAAG,CAAC,EAAE,GAAG,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QACzH,CAAC;IACL,CAAC,CAAC,CAAC;AAEP,CAAC,CAAC,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@theia/filesystem",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.76.0-next.4+21b9b5342",
|
|
4
4
|
"description": "Theia - FileSystem Extension",
|
|
5
5
|
"dependencies": {
|
|
6
|
-
"@theia/core": "1.
|
|
6
|
+
"@theia/core": "1.76.0-next.4+21b9b5342",
|
|
7
7
|
"@types/body-parser": "^1.19.6",
|
|
8
8
|
"@types/multer": "^1.4.13",
|
|
9
9
|
"@types/tar-fs": "^1.16.3",
|
|
@@ -82,5 +82,5 @@
|
|
|
82
82
|
"nyc": {
|
|
83
83
|
"extends": "../../configs/nyc.json"
|
|
84
84
|
},
|
|
85
|
-
"gitHead": "
|
|
85
|
+
"gitHead": "21b9b534224c55152fca0b67af7f8a8283dad2bd"
|
|
86
86
|
}
|
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
// *****************************************************************************
|
|
2
|
+
// Copyright (C) 2026 Safi Seid-Ahmad, K2view and others.
|
|
3
|
+
//
|
|
4
|
+
// This program and the accompanying materials are made available under the
|
|
5
|
+
// terms of the Eclipse Public License v. 2.0 which is available at
|
|
6
|
+
// http://www.eclipse.org/legal/epl-2.0.
|
|
7
|
+
//
|
|
8
|
+
// This Source Code may also be made available under the following Secondary
|
|
9
|
+
// Licenses when the conditions for such availability set forth in the Eclipse
|
|
10
|
+
// Public License v. 2.0 are satisfied: GNU General Public License, version 2
|
|
11
|
+
// with the GNU Classpath Exception which is available at
|
|
12
|
+
// https://www.gnu.org/software/classpath/license.html.
|
|
13
|
+
//
|
|
14
|
+
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
|
|
15
|
+
// *****************************************************************************
|
|
16
|
+
|
|
17
|
+
import { enableJSDOM } from '@theia/core/lib/browser/test/jsdom';
|
|
18
|
+
let disableJSDOM = enableJSDOM();
|
|
19
|
+
|
|
20
|
+
import { ColorRegistry } from '@theia/core/lib/browser/color-registry';
|
|
21
|
+
import { Decoration, DecorationsProvider, DecorationsService, DecorationsServiceImpl } from '@theia/core/lib/browser/decorations-service';
|
|
22
|
+
import { CompositeTreeNode, Tree } from '@theia/core/lib/browser/tree';
|
|
23
|
+
import { CancellationToken, Emitter, Event } from '@theia/core/lib/common';
|
|
24
|
+
import URI from '@theia/core/lib/common/uri';
|
|
25
|
+
import { Container } from '@theia/core/shared/inversify';
|
|
26
|
+
import { expect } from 'chai';
|
|
27
|
+
import { FileTreeDecoratorAdapter } from './file-tree-decorator-adapter';
|
|
28
|
+
|
|
29
|
+
disableJSDOM();
|
|
30
|
+
|
|
31
|
+
class TestDecorationsProvider implements DecorationsProvider {
|
|
32
|
+
|
|
33
|
+
protected readonly onDidChangeEmitter = new Emitter<URI[] | undefined>();
|
|
34
|
+
readonly decorations = new Map<string, Decoration>();
|
|
35
|
+
readonly queried: string[] = [];
|
|
36
|
+
|
|
37
|
+
get onDidChange(): Event<URI[] | undefined> {
|
|
38
|
+
return this.onDidChangeEmitter.event;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
fireDidChange(uris?: URI[]): void {
|
|
42
|
+
this.onDidChangeEmitter.fire(uris);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
provideDecorations(uri: URI, token: CancellationToken): Promise<Decoration | undefined> {
|
|
46
|
+
this.queried.push(uri.toString());
|
|
47
|
+
return Promise.resolve(this.decorations.get(uri.toString()));
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function createTree(uris: string[]): Tree {
|
|
52
|
+
const root = {
|
|
53
|
+
id: 'root',
|
|
54
|
+
name: 'root',
|
|
55
|
+
parent: undefined,
|
|
56
|
+
children: []
|
|
57
|
+
} as unknown as CompositeTreeNode;
|
|
58
|
+
const children = uris.map(uri => ({
|
|
59
|
+
id: uri,
|
|
60
|
+
name: new URI(uri).path.base,
|
|
61
|
+
parent: root,
|
|
62
|
+
fileStat: { resource: new URI(uri) }
|
|
63
|
+
}));
|
|
64
|
+
children.forEach((child, index) => Object.assign(child, { nextSibling: children[index + 1] }));
|
|
65
|
+
Object.assign(root, { children });
|
|
66
|
+
return { root } as unknown as Tree;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
const sleep = (ms: number): Promise<void> => new Promise(resolve => setTimeout(resolve, ms));
|
|
70
|
+
|
|
71
|
+
describe('FileTreeDecoratorAdapter', () => {
|
|
72
|
+
|
|
73
|
+
before(() => {
|
|
74
|
+
disableJSDOM = enableJSDOM();
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
after(() => {
|
|
78
|
+
disableJSDOM();
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
const fileUris = ['file:///project/f1.ts', 'file:///project/f2.ts', 'file:///project/f3.ts'];
|
|
82
|
+
|
|
83
|
+
let service: DecorationsServiceImpl;
|
|
84
|
+
let provider: TestDecorationsProvider;
|
|
85
|
+
let adapter: FileTreeDecoratorAdapter;
|
|
86
|
+
let tree: Tree;
|
|
87
|
+
|
|
88
|
+
beforeEach(() => {
|
|
89
|
+
service = new DecorationsServiceImpl();
|
|
90
|
+
provider = new TestDecorationsProvider();
|
|
91
|
+
service.registerDecorationsProvider(provider);
|
|
92
|
+
|
|
93
|
+
const container = new Container();
|
|
94
|
+
container.bind(DecorationsService).toConstantValue(service);
|
|
95
|
+
container.bind(ColorRegistry).toSelf().inSingletonScope();
|
|
96
|
+
container.bind(FileTreeDecoratorAdapter).toSelf().inSingletonScope();
|
|
97
|
+
adapter = container.get(FileTreeDecoratorAdapter);
|
|
98
|
+
|
|
99
|
+
tree = createTree(fileUris);
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
afterEach(() => {
|
|
103
|
+
service.dispose();
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
it('fetches decorations on demand for resources never mentioned in a change event', async () => {
|
|
107
|
+
for (const uri of fileUris) {
|
|
108
|
+
provider.decorations.set(uri, { letter: 'U', bubble: true });
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
// simulates a render: nothing decorated yet, but fetches are triggered
|
|
112
|
+
expect(await adapter.decorations(tree)).to.have.lengthOf(0);
|
|
113
|
+
await sleep(20);
|
|
114
|
+
|
|
115
|
+
const decorations = await adapter.decorations(tree);
|
|
116
|
+
for (const uri of fileUris) {
|
|
117
|
+
expect(decorations.has(uri), uri).to.equal(true);
|
|
118
|
+
}
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
it('does not re-query the provider for undecorated resources on repeated renders', async () => {
|
|
122
|
+
await adapter.decorations(tree);
|
|
123
|
+
await sleep(20);
|
|
124
|
+
const queriesAfterFirstRender = provider.queried.length;
|
|
125
|
+
|
|
126
|
+
await adapter.decorations(tree);
|
|
127
|
+
await adapter.decorations(tree);
|
|
128
|
+
await sleep(20);
|
|
129
|
+
|
|
130
|
+
expect(provider.queried.length).to.equal(queriesAfterFirstRender);
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
it('does not query the decorations service for undecorated resources on repeated renders', async () => {
|
|
134
|
+
const originalGetDecoration = service.getDecoration.bind(service);
|
|
135
|
+
let queries = 0;
|
|
136
|
+
service.getDecoration = (uri, includeChildren) => {
|
|
137
|
+
queries++;
|
|
138
|
+
return originalGetDecoration(uri, includeChildren);
|
|
139
|
+
};
|
|
140
|
+
await adapter.decorations(tree);
|
|
141
|
+
await sleep(20);
|
|
142
|
+
const queriesAfterFirstRender = queries;
|
|
143
|
+
|
|
144
|
+
await adapter.decorations(tree);
|
|
145
|
+
await adapter.decorations(tree);
|
|
146
|
+
|
|
147
|
+
expect(queries).to.equal(queriesAfterFirstRender);
|
|
148
|
+
});
|
|
149
|
+
|
|
150
|
+
it('recovers decorations of resources cached as undecorated after a flush event', async () => {
|
|
151
|
+
// resources are queried before the provider has any data, e.g. before
|
|
152
|
+
// the initial git status is computed
|
|
153
|
+
await adapter.decorations(tree);
|
|
154
|
+
await sleep(20);
|
|
155
|
+
expect(await adapter.decorations(tree)).to.have.lengthOf(0);
|
|
156
|
+
|
|
157
|
+
// data becomes available, but the change event exceeds the plugin-ext
|
|
158
|
+
// event cap and arrives as a flush (see #17507)
|
|
159
|
+
for (const uri of fileUris) {
|
|
160
|
+
provider.decorations.set(uri, { letter: 'M' });
|
|
161
|
+
}
|
|
162
|
+
let treeInvalidated = false;
|
|
163
|
+
adapter.onDidChangeDecorations(() => {
|
|
164
|
+
treeInvalidated = true;
|
|
165
|
+
});
|
|
166
|
+
provider.fireDidChange(undefined);
|
|
167
|
+
await sleep(20);
|
|
168
|
+
expect(treeInvalidated, 'flush must invalidate the tree decorations').to.equal(true);
|
|
169
|
+
|
|
170
|
+
// the invalidation makes the tree render, which re-fetches on demand ...
|
|
171
|
+
await adapter.decorations(tree);
|
|
172
|
+
await sleep(20);
|
|
173
|
+
|
|
174
|
+
// ... and the next render shows every decoration
|
|
175
|
+
const decorations = await adapter.decorations(tree);
|
|
176
|
+
for (const uri of fileUris) {
|
|
177
|
+
expect(decorations.get(uri)?.tailDecorations?.some(tail => 'data' in tail && tail.data === 'M'), uri).to.equal(true);
|
|
178
|
+
}
|
|
179
|
+
});
|
|
180
|
+
|
|
181
|
+
});
|
|
@@ -33,6 +33,12 @@ export class FileTreeDecoratorAdapter implements TreeDecorator {
|
|
|
33
33
|
protected readonly onDidChangeDecorationsEmitter = new Emitter<(tree: Tree) => Map<string, TreeDecoration.Data>>();
|
|
34
34
|
protected decorationsByUri = new Map<string, TreeDecoration.Data>();
|
|
35
35
|
protected parentDecorations = new Map<string, TreeDecoration.Data>();
|
|
36
|
+
/**
|
|
37
|
+
* Resources already queried from the service since the last decoration change event.
|
|
38
|
+
* Undecorated resources never enter {@link decorationsByUri}, so without this set
|
|
39
|
+
* every render pass would re-query (and re-parse the URI of) every undecorated node.
|
|
40
|
+
*/
|
|
41
|
+
protected readonly queriedUris = new Set<string>();
|
|
36
42
|
|
|
37
43
|
get onDidChangeDecorations(): Event<(tree: Tree) => Map<string, TreeDecoration.Data>> {
|
|
38
44
|
return this.onDidChangeDecorationsEmitter.event;
|
|
@@ -41,6 +47,7 @@ export class FileTreeDecoratorAdapter implements TreeDecorator {
|
|
|
41
47
|
@postConstruct()
|
|
42
48
|
protected init(): void {
|
|
43
49
|
this.decorationsService.onDidChangeDecorations(newDecorations => {
|
|
50
|
+
this.queriedUris.clear();
|
|
44
51
|
this.updateDecorations(this.decorationsByUri.keys(), newDecorations.keys());
|
|
45
52
|
this.fireDidChangeDecorations();
|
|
46
53
|
});
|
|
@@ -57,6 +64,22 @@ export class FileTreeDecoratorAdapter implements TreeDecorator {
|
|
|
57
64
|
const uri = this.getUriForNode(node);
|
|
58
65
|
if (uri) {
|
|
59
66
|
const stringified = uri.toString();
|
|
67
|
+
if (!this.decorationsByUri.has(stringified) && !this.queriedUris.has(stringified)) {
|
|
68
|
+
// Query the service once per change event for resources this decorator
|
|
69
|
+
// has not seen, so that decorations dropped from change events (e.g. by
|
|
70
|
+
// the plugin-ext event cap, see #17507) are fetched on demand. The
|
|
71
|
+
// service caches results, including "no decoration": known resources
|
|
72
|
+
// resolve synchronously and undecorated ones are not fetched again.
|
|
73
|
+
// Resolved fetches arrive as a single batched change event handled in
|
|
74
|
+
// updateDecorations.
|
|
75
|
+
this.queriedUris.add(stringified);
|
|
76
|
+
const nodeUri = new URI(stringified);
|
|
77
|
+
const fetched = this.decorationsService.getDecoration(nodeUri, false);
|
|
78
|
+
if (fetched.length) {
|
|
79
|
+
this.decorationsByUri.set(stringified, this.toTheiaDecoration(fetched, false));
|
|
80
|
+
this.propagateDecorationsByUri(nodeUri, fetched);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
60
83
|
const ownDecoration = this.decorationsByUri.get(stringified);
|
|
61
84
|
const bubbledDecoration = this.parentDecorations.get(stringified);
|
|
62
85
|
const combined = this.mergeDecorations(ownDecoration, bubbledDecoration);
|
|
@@ -88,6 +111,7 @@ export class FileTreeDecoratorAdapter implements TreeDecorator {
|
|
|
88
111
|
const newDecorations = new Map<string, TreeDecoration.Data>();
|
|
89
112
|
const handleUri = (rawUri: string) => {
|
|
90
113
|
if (!newDecorations.has(rawUri)) {
|
|
114
|
+
this.queriedUris.add(rawUri);
|
|
91
115
|
const uri = new URI(rawUri);
|
|
92
116
|
const decorations = this.decorationsService.getDecoration(uri, false);
|
|
93
117
|
if (decorations.length) {
|