Skip to content

Commit de8e8b3

Browse files
committed
File watcher support for vfs
1 parent aa0cddd commit de8e8b3

File tree

3 files changed

+1043
-5
lines changed

3 files changed

+1043
-5
lines changed

src/harness/collections.ts

Lines changed: 194 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,200 @@ namespace collections {
210210
}
211211
}
212212

213+
export class SortedSet<T> {
214+
private _comparer: (a: T, b: T) => number;
215+
private _values: T[] = [];
216+
private _order: number[] | undefined;
217+
private _version = 0;
218+
private _copyOnWrite = false;
219+
220+
constructor(comparer: ((a: T, b: T) => number) | SortOptions<T>, iterable?: Iterable<T>) {
221+
this._comparer = typeof comparer === "object" ? comparer.comparer : comparer;
222+
this._order = typeof comparer === "object" && comparer.sort === "insertion" ? [] : undefined;
223+
if (iterable) {
224+
const iterator = getIterator(iterable);
225+
try {
226+
for (let i = nextResult(iterator); i; i = nextResult(iterator)) {
227+
const value = i.value;
228+
this.add(value);
229+
}
230+
}
231+
finally {
232+
closeIterator(iterator);
233+
}
234+
}
235+
}
236+
237+
public get size() {
238+
return this._values.length;
239+
}
240+
241+
public get comparer() {
242+
return this._comparer;
243+
}
244+
245+
public get [Symbol.toStringTag]() {
246+
return "SortedSet";
247+
}
248+
249+
public has(key: T) {
250+
return ts.binarySearch(this._values, key, ts.identity, this._comparer) >= 0;
251+
}
252+
253+
public add(value: T) {
254+
const index = ts.binarySearch(this._values, value, ts.identity, this._comparer);
255+
if (index >= 0) {
256+
this._values[index] = value;
257+
}
258+
else {
259+
this.writePreamble();
260+
insertAt(this._values, ~index, value);
261+
if (this._order) insertAt(this._order, ~index, this._version);
262+
this.writePostScript();
263+
}
264+
return this;
265+
}
266+
267+
public delete(value: T) {
268+
const index = ts.binarySearch(this._values, value, ts.identity, this._comparer);
269+
if (index >= 0) {
270+
this.writePreamble();
271+
ts.orderedRemoveItemAt(this._values, index);
272+
if (this._order) ts.orderedRemoveItemAt(this._order, index);
273+
this.writePostScript();
274+
return true;
275+
}
276+
return false;
277+
}
278+
279+
public clear() {
280+
if (this.size > 0) {
281+
this.writePreamble();
282+
this._values.length = 0;
283+
if (this._order) this._order.length = 0;
284+
this.writePostScript();
285+
}
286+
}
287+
288+
public forEach(callback: (value: T, key: T, collection: this) => void, thisArg?: any) {
289+
const values = this._values;
290+
const indices = this.getIterationOrder();
291+
const version = this._version;
292+
this._copyOnWrite = true;
293+
try {
294+
if (indices) {
295+
for (const i of indices) {
296+
callback.call(thisArg, values[i], values[i], this);
297+
}
298+
}
299+
else {
300+
for (const value of values) {
301+
callback.call(thisArg, value, value, this);
302+
}
303+
}
304+
}
305+
finally {
306+
if (version === this._version) {
307+
this._copyOnWrite = false;
308+
}
309+
}
310+
}
311+
312+
public * keys() {
313+
const values = this._values;
314+
const indices = this.getIterationOrder();
315+
const version = this._version;
316+
this._copyOnWrite = true;
317+
try {
318+
if (indices) {
319+
for (const i of indices) {
320+
yield values[i];
321+
}
322+
}
323+
else {
324+
yield* values;
325+
}
326+
}
327+
finally {
328+
if (version === this._version) {
329+
this._copyOnWrite = false;
330+
}
331+
}
332+
}
333+
334+
public * values() {
335+
const values = this._values;
336+
const indices = this.getIterationOrder();
337+
const version = this._version;
338+
this._copyOnWrite = true;
339+
try {
340+
if (indices) {
341+
for (const i of indices) {
342+
yield values[i];
343+
}
344+
}
345+
else {
346+
yield* values;
347+
}
348+
}
349+
finally {
350+
if (version === this._version) {
351+
this._copyOnWrite = false;
352+
}
353+
}
354+
}
355+
356+
public * entries() {
357+
const values = this._values;
358+
const indices = this.getIterationOrder();
359+
const version = this._version;
360+
this._copyOnWrite = true;
361+
try {
362+
if (indices) {
363+
for (const i of indices) {
364+
yield [values[i], values[i]] as [T, T];
365+
}
366+
}
367+
else {
368+
for (const value of values) {
369+
yield [value, value] as [T, T];
370+
}
371+
}
372+
}
373+
finally {
374+
if (version === this._version) {
375+
this._copyOnWrite = false;
376+
}
377+
}
378+
}
379+
380+
public [Symbol.iterator]() {
381+
return this.values();
382+
}
383+
384+
private writePreamble() {
385+
if (this._copyOnWrite) {
386+
this._values = this._values.slice();
387+
if (this._order) this._order = this._order.slice();
388+
this._copyOnWrite = false;
389+
}
390+
}
391+
392+
private writePostScript() {
393+
this._version++;
394+
}
395+
396+
private getIterationOrder() {
397+
if (this._order) {
398+
const order = this._order;
399+
return this._order
400+
.map((_, i) => i)
401+
.sort((x, y) => order[x] - order[y]);
402+
}
403+
return undefined;
404+
}
405+
}
406+
213407
export function insertAt<T>(array: T[], index: number, value: T): void {
214408
if (index === 0) {
215409
array.unshift(value);

0 commit comments

Comments
 (0)