Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
microsoft
GitHub Repository: microsoft/vscode
Path: blob/main/extensions/copilot/src/platform/inlineEdits/common/utils/observable.ts
13405 views
1
/*---------------------------------------------------------------------------------------------
2
* Copyright (c) Microsoft Corporation. All rights reserved.
3
* Licensed under the MIT License. See License.txt in the project root for license information.
4
*--------------------------------------------------------------------------------------------*/
5
6
import { IDisposable } from '../../../../util/vs/base/common/lifecycle';
7
import { autorunHandleChanges, IObservableWithChange } from '../../../../util/vs/base/common/observable';
8
9
type ObservableResult<T> = T extends IObservableWithChange<infer U, any> ? U : never;
10
11
type ObservableArrayToChangesData<T extends Record<string, IObservableWithChange<any, any>>> = {
12
[Key in keyof T]: {
13
value: ObservableResult<T[Key]>;
14
changes: T[Key]['TChange'][];
15
/**
16
* The value of the observable before the changes. `undefined` if
17
*/
18
previous: ObservableResult<T[Key]> | undefined;
19
}
20
};
21
22
export function autorunWithChanges<T extends Record<string, IObservableWithChange<any, any>>>(owner: object, observables: T, handler: (data: ObservableArrayToChangesData<T>) => void): IDisposable {
23
const observableToKey = new Map(Object.entries(observables).map(([key, value]) => [value, key] as const));
24
25
const previousValues = new Map(Object.keys(observables).map(key => [key, undefined]));
26
27
return autorunHandleChanges({
28
owner,
29
changeTracker: {
30
createChangeSummary: () => ({}) as ObservableArrayToChangesData<T>,
31
handleChange: (ctx, changeSummary) => {
32
const key = observableToKey.get(ctx.changedObservable)!;
33
34
if (changeSummary[key] === undefined) {
35
(changeSummary as any)[key] = { value: undefined!, changes: [] };
36
}
37
changeSummary[key].changes.push(ctx.change);
38
return true;
39
}
40
}
41
}, (reader, data) => {
42
for (const [key, value] of Object.entries(observables)) {
43
const v = value.read(reader);
44
45
if (data[key] === undefined) {
46
(data as any)[key] = { value: v, changes: [], previous: previousValues.get(key) };
47
}
48
data[key].value = v;
49
data[key].previous = previousValues.get(key) === undefined ? undefined : previousValues.get(key);
50
previousValues.set(key, v);
51
}
52
handler(data);
53
});
54
}
55
56