Path: blob/main/src/vs/editor/contrib/inlineCompletions/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 { Permutation, compareBy } from '../../../../base/common/arrays.js';6import { CancellationToken } from '../../../../base/common/cancellation.js';7import { DisposableStore, IDisposable } from '../../../../base/common/lifecycle.js';8import { IObservable, observableValue, ISettableObservable, autorun, transaction, IReader } from '../../../../base/common/observable.js';9import { ContextKeyValue, IContextKeyService, RawContextKey } from '../../../../platform/contextkey/common/contextkey.js';10import { bindContextKey } from '../../../../platform/observable/common/platformObservableUtils.js';11import { Position } from '../../../common/core/position.js';12import { PositionOffsetTransformer } from '../../../common/core/text/positionToOffset.js';13import { Range } from '../../../common/core/range.js';14import { TextReplacement, TextEdit } from '../../../common/core/edits/textEdit.js';15import { getPositionOffsetTransformerFromTextModel } from '../../../common/core/text/getPositionOffsetTransformerFromTextModel.js';16import { ITextModel } from '../../../common/model.js';1718const array: ReadonlyArray<any> = [];19export function getReadonlyEmptyArray<T>(): readonly T[] {20return array;21}2223export function addPositions(pos1: Position, pos2: Position): Position {24return new Position(pos1.lineNumber + pos2.lineNumber - 1, pos2.lineNumber === 1 ? pos1.column + pos2.column - 1 : pos2.column);25}2627export function subtractPositions(pos1: Position, pos2: Position): Position {28return new Position(pos1.lineNumber - pos2.lineNumber + 1, pos1.lineNumber - pos2.lineNumber === 0 ? pos1.column - pos2.column + 1 : pos1.column);29}3031export function substringPos(text: string, pos: Position): string {32const transformer = new PositionOffsetTransformer(text);33const offset = transformer.getOffset(pos);34return text.substring(offset);35}3637export function getEndPositionsAfterApplying(edits: readonly TextReplacement[]): Position[] {38const newRanges = getModifiedRangesAfterApplying(edits);39return newRanges.map(range => range.getEndPosition());40}4142export function getModifiedRangesAfterApplying(edits: readonly TextReplacement[]): Range[] {43const sortPerm = Permutation.createSortPermutation(edits, compareBy(e => e.range, Range.compareRangesUsingStarts));44const edit = new TextEdit(sortPerm.apply(edits));45const sortedNewRanges = edit.getNewRanges();46return sortPerm.inverse().apply(sortedNewRanges);47}4849export function removeTextReplacementCommonSuffixPrefix(edits: readonly TextReplacement[], textModel: ITextModel): TextReplacement[] {50const transformer = getPositionOffsetTransformerFromTextModel(textModel);51const text = textModel.getValue();52const stringReplacements = edits.map(edit => transformer.getStringReplacement(edit));53const minimalStringReplacements = stringReplacements.map(replacement => replacement.removeCommonSuffixPrefix(text));54return minimalStringReplacements.map(replacement => transformer.getTextReplacement(replacement));55}5657export function convertItemsToStableObservables<T>(items: IObservable<readonly T[]>, store: DisposableStore): IObservable<IObservable<T>[]> {58const result = observableValue<IObservable<T>[]>('result', []);59const innerObservables: ISettableObservable<T>[] = [];6061store.add(autorun(reader => {62const itemsValue = items.read(reader);6364transaction(tx => {65if (itemsValue.length !== innerObservables.length) {66innerObservables.length = itemsValue.length;67for (let i = 0; i < innerObservables.length; i++) {68if (!innerObservables[i]) {69innerObservables[i] = observableValue<T>('item', itemsValue[i]);70}71}72result.set([...innerObservables], tx);73}74innerObservables.forEach((o, i) => o.set(itemsValue[i], tx));75});76}));7778return result;79}8081export class ObservableContextKeyService {82constructor(83private readonly _contextKeyService: IContextKeyService,84) {85}8687bind<T extends ContextKeyValue>(key: RawContextKey<T>, obs: IObservable<T>): IDisposable;88bind<T extends ContextKeyValue>(key: RawContextKey<T>, fn: (reader: IReader) => T): IDisposable;89bind<T extends ContextKeyValue>(key: RawContextKey<T>, obs: IObservable<T> | ((reader: IReader) => T)): IDisposable {90return bindContextKey(key, this._contextKeyService, obs instanceof Function ? obs : reader => obs.read(reader));91}92}9394export function wait(ms: number, cancellationToken?: CancellationToken): Promise<void> {95return new Promise(resolve => {96let d: IDisposable | undefined = undefined;97const handle = setTimeout(() => {98if (d) { d.dispose(); }99resolve();100}, ms);101if (cancellationToken) {102d = cancellationToken.onCancellationRequested(() => {103clearTimeout(handle);104if (d) { d.dispose(); }105resolve();106});107}108});109}110111112