Path: blob/main/src/vs/workbench/contrib/mergeEditor/browser/utils.ts
3296 views
/*---------------------------------------------------------------------------------------------1* Copyright (c) Microsoft Corporation. All rights reserved.2* Licensed under the MIT License. See License.txt in the project root for license information.3*--------------------------------------------------------------------------------------------*/45import { ArrayQueue, CompareResult } from '../../../../base/common/arrays.js';6import { onUnexpectedError } from '../../../../base/common/errors.js';7import { DisposableStore, IDisposable } from '../../../../base/common/lifecycle.js';8import { IObservable, autorunOpts } from '../../../../base/common/observable.js';9import { CodeEditorWidget } from '../../../../editor/browser/widget/codeEditor/codeEditorWidget.js';10import { IModelDeltaDecoration } from '../../../../editor/common/model.js';11import { IStorageService, StorageScope, StorageTarget } from '../../../../platform/storage/common/storage.js';1213export function setStyle(14element: HTMLElement,15style: {16width?: number | string;17height?: number | string;18left?: number | string;19top?: number | string;20}21): void {22Object.entries(style).forEach(([key, value]) => {23element.style.setProperty(key, toSize(value));24});25}2627function toSize(value: number | string): string {28return typeof value === 'number' ? `${value}px` : value;29}3031export function applyObservableDecorations(editor: CodeEditorWidget, decorations: IObservable<IModelDeltaDecoration[]>): IDisposable {32const d = new DisposableStore();33let decorationIds: string[] = [];34d.add(autorunOpts({ debugName: () => `Apply decorations from ${decorations.debugName}` }, reader => {35const d = decorations.read(reader);36editor.changeDecorations(a => {37decorationIds = a.deltaDecorations(decorationIds, d);38});39}));40d.add({41dispose: () => {42editor.changeDecorations(a => {43decorationIds = a.deltaDecorations(decorationIds, []);44});45}46});47return d;48}4950export function* leftJoin<TLeft, TRight>(51left: Iterable<TLeft>,52right: readonly TRight[],53compare: (left: TLeft, right: TRight) => CompareResult,54): IterableIterator<{ left: TLeft; rights: TRight[] }> {55const rightQueue = new ArrayQueue(right);56for (const leftElement of left) {57rightQueue.takeWhile(rightElement => CompareResult.isGreaterThan(compare(leftElement, rightElement)));58const equals = rightQueue.takeWhile(rightElement => CompareResult.isNeitherLessOrGreaterThan(compare(leftElement, rightElement)));59yield { left: leftElement, rights: equals || [] };60}61}6263export function* join<TLeft, TRight>(64left: Iterable<TLeft>,65right: readonly TRight[],66compare: (left: TLeft, right: TRight) => CompareResult,67): IterableIterator<{ left?: TLeft; rights: TRight[] }> {68const rightQueue = new ArrayQueue(right);69for (const leftElement of left) {70const skipped = rightQueue.takeWhile(rightElement => CompareResult.isGreaterThan(compare(leftElement, rightElement)));71if (skipped) {72yield { rights: skipped };73}74const equals = rightQueue.takeWhile(rightElement => CompareResult.isNeitherLessOrGreaterThan(compare(leftElement, rightElement)));75yield { left: leftElement, rights: equals || [] };76}77}7879export function elementAtOrUndefined<T>(arr: T[], index: number): T | undefined {80return arr[index];81}8283export function setFields<T extends {}>(obj: T, fields: Partial<T>): T {84return Object.assign(obj, fields);85}8687export function deepMerge<T extends {}>(source1: T, source2: Partial<T>): T {88const result = {} as any as T;89for (const key in source1) {90result[key] = source1[key];91}92for (const key in source2) {93const source2Value = source2[key];94if (typeof result[key] === 'object' && source2Value && typeof source2Value === 'object') {95result[key] = deepMerge<any>(result[key], source2Value);96} else {97result[key] = source2Value as any;98}99}100return result;101}102103export class PersistentStore<T> {104private hasValue = false;105private value: Readonly<T> | undefined = undefined;106107constructor(108private readonly key: string,109@IStorageService private readonly storageService: IStorageService110) { }111112public get(): Readonly<T> | undefined {113if (!this.hasValue) {114const value = this.storageService.get(this.key, StorageScope.PROFILE);115if (value !== undefined) {116try {117this.value = JSON.parse(value) as any;118} catch (e) {119onUnexpectedError(e);120}121}122this.hasValue = true;123}124125return this.value;126}127128public set(newValue: T | undefined): void {129this.value = newValue;130131this.storageService.store(132this.key,133JSON.stringify(this.value),134StorageScope.PROFILE,135StorageTarget.USER136);137}138}139140141