Path: blob/main/extensions/copilot/src/util/vs/base/common/observableInternal/changeTracker.ts
13406 views
//!!! DO NOT modify, this file was COPIED from 'microsoft/vscode'12/*---------------------------------------------------------------------------------------------3* Copyright (c) Microsoft Corporation. All rights reserved.4* Licensed under the MIT License. See License.txt in the project root for license information.5*--------------------------------------------------------------------------------------------*/67import { BugIndicatingError } from './commonFacade/deps';8import { IObservableWithChange, IReader } from './base';910export interface IChangeTracker<TChangeSummary> {11createChangeSummary(previousChangeSummary: TChangeSummary | undefined): TChangeSummary;12handleChange(ctx: IChangeContext, change: TChangeSummary): boolean;13beforeUpdate?(reader: IReader, change: TChangeSummary): void;14}1516export interface IChangeContext {17readonly changedObservable: IObservableWithChange<any, any>;18readonly change: unknown;1920/**21* Returns if the given observable caused the change.22*/23didChange<T, TChange>(observable: IObservableWithChange<T, TChange>): this is { change: TChange };24}2526/**27* Subscribes to and records changes and the last value of the given observables.28* Don't use the key "changes", as it is reserved for the changes array!29*/30export function recordChanges<TObs extends Record<any, IObservableWithChange<any, any>>>(obs: TObs):31IChangeTracker<{ [TKey in keyof TObs]: ReturnType<TObs[TKey]['get']> }32& { changes: readonly ({ [TKey in keyof TObs]: { key: TKey; change: TObs[TKey]['TChange'] } }[keyof TObs])[] }> {33return {34createChangeSummary: (_previousChangeSummary) => {35// eslint-disable-next-line local/code-no-any-casts36return {37changes: [],38} as any;39},40handleChange(ctx, changeSummary) {41for (const key in obs) {42if (ctx.didChange(obs[key])) {43// eslint-disable-next-line local/code-no-any-casts44(changeSummary.changes as any).push({ key, change: ctx.change });45}46}47return true;48},49beforeUpdate(reader, changeSummary) {50for (const key in obs) {51if (key === 'changes') {52throw new BugIndicatingError('property name "changes" is reserved for change tracking');53}54changeSummary[key] = obs[key].read(reader);55}56}57};58}5960/**61* Subscribes to and records changes and the last value of the given observables.62* Don't use the key "changes", as it is reserved for the changes array!63*/64export function recordChangesLazy<TObs extends Record<any, IObservableWithChange<any, any>>>(getObs: () => TObs):65IChangeTracker<{ [TKey in keyof TObs]: ReturnType<TObs[TKey]['get']> }66& { changes: readonly ({ [TKey in keyof TObs]: { key: TKey; change: TObs[TKey]['TChange'] } }[keyof TObs])[] }> {67let obs: TObs | undefined = undefined;68return {69createChangeSummary: (_previousChangeSummary) => {70// eslint-disable-next-line local/code-no-any-casts71return {72changes: [],73} as any;74},75handleChange(ctx, changeSummary) {76if (!obs) {77obs = getObs();78}79for (const key in obs) {80if (ctx.didChange(obs[key])) {81// eslint-disable-next-line local/code-no-any-casts82(changeSummary.changes as any).push({ key, change: ctx.change });83}84}85return true;86},87beforeUpdate(reader, changeSummary) {88if (!obs) {89obs = getObs();90}91for (const key in obs) {92if (key === 'changes') {93throw new BugIndicatingError('property name "changes" is reserved for change tracking');94}95changeSummary[key] = obs[key].read(reader);96}97}98};99}100101102