Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
microsoft
GitHub Repository: microsoft/vscode
Path: blob/main/extensions/copilot/src/util/vs/base/common/cache.ts
13405 views
1
//!!! DO NOT modify, this file was COPIED from 'microsoft/vscode'
2
3
/*---------------------------------------------------------------------------------------------
4
* Copyright (c) Microsoft Corporation. All rights reserved.
5
* Licensed under the MIT License. See License.txt in the project root for license information.
6
*--------------------------------------------------------------------------------------------*/
7
8
import { CancellationToken, CancellationTokenSource } from './cancellation';
9
import { IDisposable } from './lifecycle';
10
11
export interface CacheResult<T> extends IDisposable {
12
promise: Promise<T>;
13
}
14
15
export class Cache<T> {
16
17
private result: CacheResult<T> | null = null;
18
constructor(private task: (ct: CancellationToken) => Promise<T>) { }
19
20
get(): CacheResult<T> {
21
if (this.result) {
22
return this.result;
23
}
24
25
const cts = new CancellationTokenSource();
26
const promise = this.task(cts.token);
27
28
this.result = {
29
promise,
30
dispose: () => {
31
this.result = null;
32
cts.cancel();
33
cts.dispose();
34
}
35
};
36
37
return this.result;
38
}
39
}
40
41
export function identity<T>(t: T): T {
42
return t;
43
}
44
45
interface ICacheOptions<TArg> {
46
/**
47
* The cache key is used to identify the cache entry.
48
* Strict equality is used to compare cache keys.
49
*/
50
getCacheKey: (arg: TArg) => unknown;
51
}
52
53
/**
54
* Uses a LRU cache to make a given parametrized function cached.
55
* Caches just the last key/value.
56
*/
57
export class LRUCachedFunction<TArg, TComputed> {
58
private lastCache: TComputed | undefined = undefined;
59
private lastArgKey: unknown | undefined = undefined;
60
61
private readonly _fn: (arg: TArg) => TComputed;
62
private readonly _computeKey: (arg: TArg) => unknown;
63
64
constructor(fn: (arg: TArg) => TComputed);
65
constructor(options: ICacheOptions<TArg>, fn: (arg: TArg) => TComputed);
66
constructor(arg1: ICacheOptions<TArg> | ((arg: TArg) => TComputed), arg2?: (arg: TArg) => TComputed) {
67
if (typeof arg1 === 'function') {
68
this._fn = arg1;
69
this._computeKey = identity;
70
} else {
71
this._fn = arg2!;
72
this._computeKey = arg1.getCacheKey;
73
}
74
}
75
76
public get(arg: TArg): TComputed {
77
const key = this._computeKey(arg);
78
if (this.lastArgKey !== key) {
79
this.lastArgKey = key;
80
this.lastCache = this._fn(arg);
81
}
82
return this.lastCache!;
83
}
84
}
85
86
/**
87
* Uses an unbounded cache to memoize the results of the given function.
88
*/
89
export class CachedFunction<TArg, TComputed> {
90
private readonly _map = new Map<TArg, TComputed>();
91
private readonly _map2 = new Map<unknown, TComputed>();
92
public get cachedValues(): ReadonlyMap<TArg, TComputed> {
93
return this._map;
94
}
95
96
private readonly _fn: (arg: TArg) => TComputed;
97
private readonly _computeKey: (arg: TArg) => unknown;
98
99
constructor(fn: (arg: TArg) => TComputed);
100
constructor(options: ICacheOptions<TArg>, fn: (arg: TArg) => TComputed);
101
constructor(arg1: ICacheOptions<TArg> | ((arg: TArg) => TComputed), arg2?: (arg: TArg) => TComputed) {
102
if (typeof arg1 === 'function') {
103
this._fn = arg1;
104
this._computeKey = identity;
105
} else {
106
this._fn = arg2!;
107
this._computeKey = arg1.getCacheKey;
108
}
109
}
110
111
public get(arg: TArg): TComputed {
112
const key = this._computeKey(arg);
113
if (this._map2.has(key)) {
114
return this._map2.get(key)!;
115
}
116
117
const value = this._fn(arg);
118
this._map.set(arg, value);
119
this._map2.set(key, value);
120
return value;
121
}
122
}
123
124
/**
125
* Uses an unbounded cache to memoize the results of the given function.
126
*/
127
export class WeakCachedFunction<TArg, TComputed> {
128
private readonly _map = new WeakMap<WeakKey, TComputed>();
129
130
private readonly _fn: (arg: TArg) => TComputed;
131
private readonly _computeKey: (arg: TArg) => unknown;
132
133
constructor(fn: (arg: TArg) => TComputed);
134
constructor(options: ICacheOptions<TArg>, fn: (arg: TArg) => TComputed);
135
constructor(arg1: ICacheOptions<TArg> | ((arg: TArg) => TComputed), arg2?: (arg: TArg) => TComputed) {
136
if (typeof arg1 === 'function') {
137
this._fn = arg1;
138
this._computeKey = identity;
139
} else {
140
this._fn = arg2!;
141
this._computeKey = arg1.getCacheKey;
142
}
143
}
144
145
public get(arg: TArg): TComputed {
146
const key = this._computeKey(arg) as WeakKey;
147
if (this._map.has(key)) {
148
return this._map.get(key)!;
149
}
150
151
const value = this._fn(arg);
152
this._map.set(key, value);
153
return value;
154
}
155
}
156
157