@theia/core 1.46.1 → 1.47.0-next.0

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.
Files changed (36) hide show
  1. package/README.md +6 -6
  2. package/lib/browser/tree/test/mock-selectable-tree-model.d.ts +15 -0
  3. package/lib/browser/tree/test/mock-selectable-tree-model.d.ts.map +1 -0
  4. package/lib/browser/tree/test/mock-selectable-tree-model.js +103 -0
  5. package/lib/browser/tree/test/mock-selectable-tree-model.js.map +1 -0
  6. package/lib/browser/tree/tree-model.d.ts +24 -0
  7. package/lib/browser/tree/tree-model.d.ts.map +1 -1
  8. package/lib/browser/tree/tree-model.js +46 -0
  9. package/lib/browser/tree/tree-model.js.map +1 -1
  10. package/lib/browser/tree/tree-selectable.spec.d.ts +2 -0
  11. package/lib/browser/tree/tree-selectable.spec.d.ts.map +1 -0
  12. package/lib/browser/tree/tree-selectable.spec.js +147 -0
  13. package/lib/browser/tree/tree-selectable.spec.js.map +1 -0
  14. package/lib/common/disposable.d.ts +28 -0
  15. package/lib/common/disposable.d.ts.map +1 -1
  16. package/lib/common/disposable.js +28 -0
  17. package/lib/common/disposable.js.map +1 -1
  18. package/lib/common/disposable.spec.js +51 -0
  19. package/lib/common/disposable.spec.js.map +1 -1
  20. package/lib/common/quick-pick-service.d.ts +1 -1
  21. package/lib/common/quick-pick-service.d.ts.map +1 -1
  22. package/lib/common/reference.d.ts +55 -0
  23. package/lib/common/reference.d.ts.map +1 -1
  24. package/lib/common/reference.js +55 -0
  25. package/lib/common/reference.js.map +1 -1
  26. package/lib/electron-browser/messaging/electron-messaging-frontend-module.js +3 -3
  27. package/lib/electron-browser/messaging/electron-messaging-frontend-module.js.map +1 -1
  28. package/package.json +6 -6
  29. package/src/browser/tree/test/mock-selectable-tree-model.ts +109 -0
  30. package/src/browser/tree/tree-model.ts +74 -0
  31. package/src/browser/tree/tree-selectable.spec.ts +152 -0
  32. package/src/common/disposable.spec.ts +66 -1
  33. package/src/common/disposable.ts +28 -0
  34. package/src/common/quick-pick-service.ts +1 -1
  35. package/src/common/reference.ts +55 -0
  36. package/src/electron-browser/messaging/electron-messaging-frontend-module.ts +1 -1
@@ -99,21 +99,41 @@ export interface TreeModel extends Tree, TreeSelectionService, TreeExpansionServ
99
99
  */
100
100
  navigateBackward(): Promise<void>;
101
101
 
102
+ /**
103
+ * Selects the previous tree node, regardless of its selection or visibility state.
104
+ */
105
+ selectPrev(): void;
106
+
102
107
  /**
103
108
  * Selects the previous node relatively to the currently selected one. This method takes the expansion state of the tree into consideration.
104
109
  */
105
110
  selectPrevNode(type?: TreeSelection.SelectionType): void;
106
111
 
112
+ /**
113
+ * Returns the previous tree node, regardless of its selection or visibility state.
114
+ */
115
+ getPrevNode(node?: TreeNode): TreeNode | undefined;
116
+
107
117
  /**
108
118
  * Returns the previous selectable tree node.
109
119
  */
110
120
  getPrevSelectableNode(node?: TreeNode): SelectableTreeNode | undefined;
111
121
 
122
+ /**
123
+ * Selects the next tree node, regardless of its selection or visibility state.
124
+ */
125
+ selectNext(): void;
126
+
112
127
  /**
113
128
  * Selects the next node relatively to the currently selected one. This method takes the expansion state of the tree into consideration.
114
129
  */
115
130
  selectNextNode(type?: TreeSelection.SelectionType): void;
116
131
 
132
+ /**
133
+ * Returns the next tree node, regardless of its selection or visibility state.
134
+ */
135
+ getNextNode(node?: TreeNode): TreeNode | undefined;
136
+
117
137
  /**
118
138
  * Returns the next selectable tree node.
119
139
  */
@@ -294,6 +314,11 @@ export class TreeModelImpl implements TreeModel, SelectionProvider<ReadonlyArray
294
314
  }
295
315
  }
296
316
 
317
+ selectPrev(): void {
318
+ const node = this.getPrevNode();
319
+ this.selectNodeIfSelectable(node);
320
+ }
321
+
297
322
  selectPrevNode(type: TreeSelection.SelectionType = TreeSelection.SelectionType.DEFAULT): void {
298
323
  const node = this.getPrevSelectableNode();
299
324
  if (node) {
@@ -301,6 +326,11 @@ export class TreeModelImpl implements TreeModel, SelectionProvider<ReadonlyArray
301
326
  }
302
327
  }
303
328
 
329
+ getPrevNode(node: TreeNode | undefined = this.getFocusedNode()): TreeNode | undefined {
330
+ const iterator = this.createBackwardTreeIterator(node);
331
+ return iterator && this.doGetNode(iterator);
332
+ }
333
+
304
334
  getPrevSelectableNode(node: TreeNode | undefined = this.getFocusedNode()): SelectableTreeNode | undefined {
305
335
  if (!node) {
306
336
  return this.getNextSelectableNode(this.root);
@@ -309,6 +339,11 @@ export class TreeModelImpl implements TreeModel, SelectionProvider<ReadonlyArray
309
339
  return iterator && this.doGetNextNode(iterator, this.isVisibleSelectableNode.bind(this));
310
340
  }
311
341
 
342
+ selectNext(): void {
343
+ const node = this.getNextNode();
344
+ this.selectNodeIfSelectable(node);
345
+ }
346
+
312
347
  selectNextNode(type: TreeSelection.SelectionType = TreeSelection.SelectionType.DEFAULT): void {
313
348
  const node = this.getNextSelectableNode();
314
349
  if (node) {
@@ -316,11 +351,28 @@ export class TreeModelImpl implements TreeModel, SelectionProvider<ReadonlyArray
316
351
  }
317
352
  }
318
353
 
354
+ getNextNode(node: TreeNode | undefined = this.getFocusedNode()): TreeNode | undefined {
355
+ const iterator = this.createTreeIterator(node);
356
+ return iterator && this.doGetNode(iterator);
357
+ }
358
+
319
359
  getNextSelectableNode(node: TreeNode | undefined = this.getFocusedNode() ?? this.root): SelectableTreeNode | undefined {
320
360
  const iterator = this.createIterator(node);
321
361
  return iterator && this.doGetNextNode(iterator, this.isVisibleSelectableNode.bind(this));
322
362
  }
323
363
 
364
+ protected selectNodeIfSelectable(node: TreeNode | undefined): void {
365
+ if (SelectableTreeNode.is(node)) {
366
+ this.addSelection(node);
367
+ }
368
+ }
369
+
370
+ protected doGetNode(iterator: TreeIterator): TreeNode | undefined {
371
+ iterator.next();
372
+ const result = iterator.next();
373
+ return result.done ? undefined : result.value;
374
+ }
375
+
324
376
  protected doGetNextNode<T extends TreeNode>(iterator: TreeIterator, criterion: (node: TreeNode) => node is T): T | undefined {
325
377
  // Skip the first item. // TODO: clean this up, and skip the first item in a different way without loading everything.
326
378
  iterator.next();
@@ -338,6 +390,17 @@ export class TreeModelImpl implements TreeModel, SelectionProvider<ReadonlyArray
338
390
  return SelectableTreeNode.isVisible(node);
339
391
  }
340
392
 
393
+ protected createBackwardTreeIterator(node: TreeNode | undefined): TreeIterator | undefined {
394
+ const { filteredNodes } = this.treeSearch;
395
+ if (filteredNodes.length === 0) {
396
+ return node ? new BottomUpTreeIterator(node!, { pruneCollapsed: false }) : undefined;
397
+ }
398
+ if (node && filteredNodes.indexOf(node) === -1) {
399
+ return undefined;
400
+ }
401
+ return Iterators.cycle(filteredNodes.slice().reverse(), node);
402
+ }
403
+
341
404
  protected createBackwardIterator(node: TreeNode | undefined): TreeIterator | undefined {
342
405
  const { filteredNodes } = this.treeSearch;
343
406
  if (filteredNodes.length === 0) {
@@ -349,6 +412,17 @@ export class TreeModelImpl implements TreeModel, SelectionProvider<ReadonlyArray
349
412
  return Iterators.cycle(filteredNodes.slice().reverse(), node);
350
413
  }
351
414
 
415
+ protected createTreeIterator(node: TreeNode | undefined): TreeIterator | undefined {
416
+ const { filteredNodes } = this.treeSearch;
417
+ if (filteredNodes.length === 0) {
418
+ return node && new TopDownTreeIterator(node, { pruneCollapsed: false });
419
+ }
420
+ if (node && filteredNodes.indexOf(node) === -1) {
421
+ return undefined;
422
+ }
423
+ return Iterators.cycle(filteredNodes, node);
424
+ }
425
+
352
426
  protected createIterator(node: TreeNode | undefined): TreeIterator | undefined {
353
427
  const { filteredNodes } = this.treeSearch;
354
428
  if (filteredNodes.length === 0) {
@@ -0,0 +1,152 @@
1
+ // *****************************************************************************
2
+ // Copyright (C) 2018 TypeFox 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 { TreeNode } from './tree';
18
+ import { TreeModel } from './tree-model';
19
+ import { notEmpty } from '../../common/objects';
20
+ import { expect } from 'chai';
21
+ import { createTreeTestContainer } from './test/tree-test-container';
22
+ import { SelectableTreeNode } from './tree-selection';
23
+ import { MockSelectableTreeModel } from './test/mock-selectable-tree-model';
24
+ import { ExpandableTreeNode } from './tree-expansion';
25
+
26
+ describe('Selectable Tree', () => {
27
+ let model: TreeModel;
28
+ function assertNodeRetrieval(method: () => TreeNode | undefined, sequence: string[]): void {
29
+ for (const expectedNodeId of sequence) {
30
+ const actualNode = method();
31
+ const expectedNode = retrieveNode<SelectableTreeNode>(expectedNodeId);
32
+ expect(actualNode?.id).to.be.equal(expectedNode.id);
33
+ model.addSelection(expectedNode);
34
+ }
35
+ }
36
+ function assertNodeSelection(method: () => void, sequence: string[]): void {
37
+ for (const expectedNodeId of sequence) {
38
+ method();
39
+ const node = retrieveNode<SelectableTreeNode>(expectedNodeId);
40
+ expect(node.selected).to.be.true;
41
+ }
42
+ }
43
+ describe('Get and Set Next Nodes Methods', () => {
44
+ const uncollapsedSelectionOrder = ['1.1', '1.1.1', '1.1.2', '1.2', '1.2.1', '1.2.1.1', '1.2.1.2', '1.2.2', '1.2.3', '1.3'];
45
+ const collapsedSelectionOrder = ['1.1', '1.2', '1.2.1', '1.2.2', '1.2.3', '1.3'];
46
+ beforeEach(() => {
47
+ model = createTreeModel();
48
+ model.root = MockSelectableTreeModel.HIERARCHICAL_MOCK_ROOT();
49
+ model.addSelection(retrieveNode<SelectableTreeNode>('1'));
50
+
51
+ });
52
+ it('`getNextNode()` should select each node in sequence (uncollapsed)', done => {
53
+ assertNodeRetrieval(model.getNextNode.bind(model), uncollapsedSelectionOrder);
54
+ done();
55
+ });
56
+ it('`getNextNode()` should select each node in sequence (collapsed)', done => {
57
+ collapseNode('1.1', '1.2.1');
58
+ assertNodeRetrieval(model.getNextNode.bind(model), uncollapsedSelectionOrder);
59
+ done();
60
+ });
61
+ it('`getNextSelectableNode()` should select each node in sequence (uncollapsed)', done => {
62
+ assertNodeRetrieval(model.getNextSelectableNode.bind(model), uncollapsedSelectionOrder);
63
+ done();
64
+ });
65
+ it('`getNextSelectableNode()` should select each node in sequence (collapsed)', done => {
66
+ collapseNode('1.1', '1.2.1');
67
+ assertNodeRetrieval(model.getNextSelectableNode.bind(model), collapsedSelectionOrder);
68
+ done();
69
+ });
70
+ it('`selectNext()` should select each node in sequence (uncollapsed)', done => {
71
+ assertNodeSelection(model.selectNext.bind(model), uncollapsedSelectionOrder);
72
+ done();
73
+ });
74
+ it('`selectNext()` should select each node in sequence (collapsed)', done => {
75
+ collapseNode('1.1', '1.2.1');
76
+ assertNodeSelection(model.selectNext.bind(model), uncollapsedSelectionOrder);
77
+ done();
78
+ });
79
+ it('`selectNextNode()` should select each node in sequence (uncollapsed)', done => {
80
+ assertNodeSelection(model.selectNextNode.bind(model), uncollapsedSelectionOrder);
81
+ done();
82
+ });
83
+ it('`selectNextNode()` should select each node in sequence (collapsed)', done => {
84
+ collapseNode('1.1', '1.2.1');
85
+ assertNodeSelection(model.selectNextNode.bind(model), collapsedSelectionOrder);
86
+ done();
87
+ });
88
+ });
89
+
90
+ describe('Get and Set Previous Nodes Methods', () => {
91
+ const uncollapsedSelectionOrder = ['1.2.3', '1.2.2', '1.2.1.2', '1.2.1.1', '1.2.1', '1.2', '1.1.2', '1.1.1', '1.1'];
92
+ const collapsedSelectionOrder = ['1.2.3', '1.2.2', '1.2.1', '1.2', '1.1'];
93
+ beforeEach(() => {
94
+ model = createTreeModel();
95
+ model.root = MockSelectableTreeModel.HIERARCHICAL_MOCK_ROOT();
96
+ model.addSelection(retrieveNode<SelectableTreeNode>('1.3'));
97
+ });
98
+ it('`getPrevNode()` should select each node in reverse sequence (uncollapsed)', done => {
99
+ assertNodeRetrieval(model.getPrevNode.bind(model), uncollapsedSelectionOrder);
100
+ done();
101
+ });
102
+ it('`getPrevNode()` should select each node in reverse sequence (collapsed)', done => {
103
+ collapseNode('1.1', '1.2.1');
104
+ assertNodeRetrieval(model.getPrevNode.bind(model), uncollapsedSelectionOrder);
105
+ done();
106
+ });
107
+ it('`getPrevSelectableNode()` should select each node in reverse sequence (uncollapsed)', done => {
108
+ assertNodeRetrieval(model.getPrevSelectableNode.bind(model), uncollapsedSelectionOrder);
109
+ done();
110
+ });
111
+ it('`getPrevSelectableNode()` should select each node in reverse sequence (collapsed)', done => {
112
+ collapseNode('1.1', '1.2.1');
113
+ assertNodeRetrieval(model.getPrevSelectableNode.bind(model), collapsedSelectionOrder);
114
+ done();
115
+ });
116
+ it('`selectPrev()` should select each node in reverse sequence (uncollapsed)', done => {
117
+ assertNodeSelection(model.selectPrev.bind(model), uncollapsedSelectionOrder);
118
+ done();
119
+ });
120
+ it('`selectPrev()` should select each node in reverse sequence (collapsed)', done => {
121
+ collapseNode('1.1', '1.2.1');
122
+ assertNodeSelection(model.selectPrev.bind(model), uncollapsedSelectionOrder);
123
+ done();
124
+ });
125
+ it('`selectPrevNode()` should select each node in reverse sequence (uncollapsed)', done => {
126
+ assertNodeSelection(model.selectPrevNode.bind(model), uncollapsedSelectionOrder);
127
+ done();
128
+ });
129
+ it('`selectPrevNode()` should select each node in reverse sequence (collapsed)', done => {
130
+ collapseNode('1.1', '1.2.1');
131
+ assertNodeSelection(model.selectPrevNode.bind(model), collapsedSelectionOrder);
132
+ done();
133
+ });
134
+ });
135
+
136
+ const findNode = (id: string) => model.getNode(id);
137
+ function createTreeModel(): TreeModel {
138
+ const container = createTreeTestContainer();
139
+ return container.get(TreeModel);
140
+ }
141
+ function retrieveNode<T extends TreeNode>(id: string): Readonly<T> {
142
+ const readonlyNode: Readonly<T> = model.getNode(id) as T;
143
+ return readonlyNode;
144
+ }
145
+ function collapseNode(...ids: string[]): void {
146
+ ids.map(findNode).filter(notEmpty).filter(ExpandableTreeNode.is).forEach(node => {
147
+ model.collapseNode(node);
148
+ expect(node).to.have.property('expanded', false);
149
+ });
150
+ }
151
+
152
+ });
@@ -14,8 +14,11 @@
14
14
  // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
15
15
  // *****************************************************************************
16
16
 
17
- import { expect } from 'chai';
17
+ import { expect, spy, use } from 'chai';
18
18
  import { DisposableCollection, Disposable } from './disposable';
19
+ import * as spies from 'chai-spies';
20
+
21
+ use(spies);
19
22
 
20
23
  describe('Disposables', () => {
21
24
  it('Is safe to use Disposable.NULL', () => {
@@ -26,4 +29,66 @@ describe('Disposables', () => {
26
29
  expect(collectionA.disposed, 'A should be disposed after being disposed.').to.be.true;
27
30
  expect(collectionB.disposed, 'B should not be disposed because A was disposed.').to.be.false;
28
31
  });
32
+
33
+ it('Collection is auto-pruned when an element is disposed', () => {
34
+ const onDispose = spy(() => { });
35
+ const elementDispose = () => { };
36
+
37
+ const collection = new DisposableCollection();
38
+ collection.onDispose(onDispose);
39
+
40
+ const disposable1 = Disposable.create(elementDispose);
41
+ collection.push(disposable1);
42
+ expect(collection['disposables']).to.have.lengthOf(1);
43
+
44
+ const disposable2 = Disposable.create(elementDispose);
45
+ collection.push(disposable2);
46
+ expect(collection['disposables']).to.have.lengthOf(2);
47
+
48
+ disposable1.dispose();
49
+ expect(collection['disposables']).to.have.lengthOf(1);
50
+ expect(onDispose).to.have.not.been.called();
51
+ expect(collection.disposed).is.false;
52
+
53
+ // Test that calling dispose on an already disposed element doesn't
54
+ // alter the collection state
55
+ disposable1.dispose();
56
+ expect(collection['disposables']).to.have.lengthOf(1);
57
+ expect(onDispose).to.have.not.been.called();
58
+ expect(collection.disposed).is.false;
59
+
60
+ disposable2.dispose();
61
+ expect(collection['disposables']).to.be.empty;
62
+ expect(collection.disposed).is.true;
63
+ expect(onDispose).to.have.been.called.once;
64
+ });
65
+
66
+ it('onDispose is only called once on actual disposal of elements', () => {
67
+ const onDispose = spy(() => { });
68
+ const elementDispose = spy(() => { });
69
+
70
+ const collection = new DisposableCollection();
71
+ collection.onDispose(onDispose);
72
+
73
+ // if the collection is empty 'onDispose' is not called
74
+ collection.dispose();
75
+ expect(onDispose).to.not.have.been.called();
76
+
77
+ // 'onDispose' is called because we actually dispose an element
78
+ collection.push(Disposable.create(elementDispose));
79
+ collection.dispose();
80
+ expect(elementDispose).to.have.been.called.once;
81
+ expect(onDispose).to.have.been.called.once;
82
+
83
+ // if the collection is empty 'onDispose' is not called and no further element is disposed
84
+ collection.dispose();
85
+ expect(elementDispose).to.have.been.called.once;
86
+ expect(onDispose).to.have.been.called.once;
87
+
88
+ // 'onDispose' is not called again even if we actually dispose an element
89
+ collection.push(Disposable.create(elementDispose));
90
+ collection.dispose();
91
+ expect(elementDispose).to.have.been.called.twice;
92
+ expect(onDispose).to.have.been.called.once;
93
+ });
29
94
  });
@@ -47,6 +47,34 @@ Object.defineProperty(Disposable, 'NULL', {
47
47
  }
48
48
  });
49
49
 
50
+ /**
51
+ * Utility for tracking a collection of Disposable objects.
52
+ *
53
+ * This utility provides a number of benefits over just using an array of
54
+ * Disposables:
55
+ *
56
+ * - the collection is auto-pruned when an element it contains is disposed by
57
+ * any code that has a reference to it
58
+ * - you can register to be notified when all elements in the collection have
59
+ * been disposed [1]
60
+ * - you can conveniently dispose all elements by calling dispose()
61
+ * on the collection
62
+ *
63
+ * Unlike an array, however, this utility does not give you direct access to
64
+ * its elements.
65
+ *
66
+ * Being notified when all elements are disposed is simple:
67
+ * ```
68
+ * const dc = new DisposableCollection(myDisposables);
69
+ * dc.onDispose(() => {
70
+ * console.log('All elements in the collection have been disposed');
71
+ * });
72
+ * ```
73
+ *
74
+ * [1] The collection will notify only once. It will continue to function in so
75
+ * far as accepting new Disposables and pruning them when they are disposed, but
76
+ * such activity will never result in another notification.
77
+ */
50
78
  export class DisposableCollection implements Disposable {
51
79
 
52
80
  protected readonly disposables: Disposable[] = [];
@@ -191,7 +191,7 @@ export interface QuickPick<T extends QuickPickItemOrSeparator> extends QuickInpu
191
191
  readonly onDidAccept: Event<{ inBackground: boolean } | undefined>;
192
192
  readonly onDidChangeValue: Event<string>;
193
193
  readonly onDidTriggerButton: Event<QuickInputButton>;
194
- readonly onDidTriggerItemButton: Event<QuickPickItemButtonEvent<T>>;
194
+ readonly onDidTriggerItemButton: Event<QuickPickItemButtonEvent<QuickPickItem>>;
195
195
  readonly onDidChangeActive: Event<T[]>;
196
196
  readonly onDidChangeSelection: Event<T[]>;
197
197
  }
@@ -22,6 +22,50 @@ export interface Reference<T> extends Disposable {
22
22
  readonly object: T
23
23
  }
24
24
 
25
+ /**
26
+ * Abstract class for a map of reference-counted disposable objects, with the
27
+ * following features:
28
+ *
29
+ * - values are not inserted explicitly; instead, acquire() is used to
30
+ * create the value for a given key, or return the previously created
31
+ * value for it. How the value is created for a given key is
32
+ * implementation specific.
33
+ *
34
+ * - any subsquent acquire() with the same key will bump the reference
35
+ * count on that value. acquire() returns not the value directly but
36
+ * a reference object that holds the value. Calling dispose() on the
37
+ * reference decreases the value's effective reference count.
38
+ *
39
+ * - a contained value will have its dispose() function called when its
40
+ * reference count reaches zero. The key/value pair will be purged
41
+ * from the collection.
42
+ *
43
+ * - calling dispose() on the value directly, instead of calling it on
44
+ * the reference returned by acquire(), will automatically dispose
45
+ * all outstanding references to that value and the key/value pair
46
+ * will be purged from the collection.
47
+ *
48
+ * - supports synchronous and asynchronous implementations. acquire() will
49
+ * return a Promise if the value cannot be created immediately
50
+ *
51
+ * - functions has|keys|values|get are always synchronous and the result
52
+ * excludes asynchronous additions in flight.
53
+ *
54
+ * - functions values|get return the value directly and not a reference
55
+ * to the value. Use these functions to obtain a value without bumping
56
+ * its reference count.
57
+ *
58
+ * - clients can register to be notified when values are added and removed;
59
+ * notification for asynchronous additions happen when the creation
60
+ * completes, not when it's requested.
61
+ *
62
+ * - keys can be any value/object that can be successfully stringified using
63
+ * JSON.stringify(), sans arguments
64
+ *
65
+ * - calling dispose() on the collection will dispose all outstanding
66
+ * references to all contained values, which results in the disposal of
67
+ * the values themselves.
68
+ */
25
69
  export abstract class AbstractReferenceCollection<K, V extends Disposable> implements Disposable {
26
70
 
27
71
  protected readonly _keys = new Map<string, K>();
@@ -108,6 +152,12 @@ export abstract class AbstractReferenceCollection<K, V extends Disposable> imple
108
152
 
109
153
  }
110
154
 
155
+ /**
156
+ * Asynchronous implementation of AbstractReferenceCollection that requires
157
+ * the client to provide a value factory, used to service the acquire()
158
+ * function. That factory may return a Promise if the value cannot be
159
+ * created immediately.
160
+ */
111
161
  export class ReferenceCollection<K, V extends Disposable> extends AbstractReferenceCollection<K, V> {
112
162
 
113
163
  constructor(protected readonly factory: (key: K) => MaybePromise<V>) {
@@ -148,6 +198,11 @@ export class ReferenceCollection<K, V extends Disposable> extends AbstractRefere
148
198
 
149
199
  }
150
200
 
201
+ /**
202
+ * Synchronous implementation of AbstractReferenceCollection that requires
203
+ * the client to provide a value factory, used to service the acquire()
204
+ * function.
205
+ */
151
206
  export class SyncReferenceCollection<K, V extends Disposable> extends AbstractReferenceCollection<K, V> {
152
207
 
153
208
  constructor(protected readonly factory: (key: K) => V) {
@@ -23,7 +23,7 @@ import { ElectronFrontendIdProvider } from './electron-frontend-id-provider';
23
23
  import { FrontendIdProvider } from '../../browser/messaging/frontend-id-provider';
24
24
  import { ConnectionSource } from '../../browser/messaging/connection-source';
25
25
  import { LocalConnectionProvider, RemoteConnectionProvider, ServiceConnectionProvider } from '../../browser/messaging/service-connection-provider';
26
- import { WebSocketConnectionProvider } from '../../browser';
26
+ import { WebSocketConnectionProvider } from '../../browser/messaging/ws-connection-provider';
27
27
  import { ConnectionCloseService, connectionCloseServicePath } from '../../common/messaging/connection-management';
28
28
  import { WebSocketConnectionSource } from '../../browser/messaging/ws-connection-source';
29
29