Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
microsoft
GitHub Repository: microsoft/vscode
Path: blob/main/src/vs/editor/contrib/inlineCompletions/browser/utils.ts
3296 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 { Permutation, compareBy } from '../../../../base/common/arrays.js';
7
import { CancellationToken } from '../../../../base/common/cancellation.js';
8
import { DisposableStore, IDisposable } from '../../../../base/common/lifecycle.js';
9
import { IObservable, observableValue, ISettableObservable, autorun, transaction, IReader } from '../../../../base/common/observable.js';
10
import { ContextKeyValue, IContextKeyService, RawContextKey } from '../../../../platform/contextkey/common/contextkey.js';
11
import { bindContextKey } from '../../../../platform/observable/common/platformObservableUtils.js';
12
import { Position } from '../../../common/core/position.js';
13
import { PositionOffsetTransformer } from '../../../common/core/text/positionToOffset.js';
14
import { Range } from '../../../common/core/range.js';
15
import { TextReplacement, TextEdit } from '../../../common/core/edits/textEdit.js';
16
import { getPositionOffsetTransformerFromTextModel } from '../../../common/core/text/getPositionOffsetTransformerFromTextModel.js';
17
import { ITextModel } from '../../../common/model.js';
18
19
const array: ReadonlyArray<any> = [];
20
export function getReadonlyEmptyArray<T>(): readonly T[] {
21
return array;
22
}
23
24
export function addPositions(pos1: Position, pos2: Position): Position {
25
return new Position(pos1.lineNumber + pos2.lineNumber - 1, pos2.lineNumber === 1 ? pos1.column + pos2.column - 1 : pos2.column);
26
}
27
28
export function subtractPositions(pos1: Position, pos2: Position): Position {
29
return new Position(pos1.lineNumber - pos2.lineNumber + 1, pos1.lineNumber - pos2.lineNumber === 0 ? pos1.column - pos2.column + 1 : pos1.column);
30
}
31
32
export function substringPos(text: string, pos: Position): string {
33
const transformer = new PositionOffsetTransformer(text);
34
const offset = transformer.getOffset(pos);
35
return text.substring(offset);
36
}
37
38
export function getEndPositionsAfterApplying(edits: readonly TextReplacement[]): Position[] {
39
const newRanges = getModifiedRangesAfterApplying(edits);
40
return newRanges.map(range => range.getEndPosition());
41
}
42
43
export function getModifiedRangesAfterApplying(edits: readonly TextReplacement[]): Range[] {
44
const sortPerm = Permutation.createSortPermutation(edits, compareBy(e => e.range, Range.compareRangesUsingStarts));
45
const edit = new TextEdit(sortPerm.apply(edits));
46
const sortedNewRanges = edit.getNewRanges();
47
return sortPerm.inverse().apply(sortedNewRanges);
48
}
49
50
export function removeTextReplacementCommonSuffixPrefix(edits: readonly TextReplacement[], textModel: ITextModel): TextReplacement[] {
51
const transformer = getPositionOffsetTransformerFromTextModel(textModel);
52
const text = textModel.getValue();
53
const stringReplacements = edits.map(edit => transformer.getStringReplacement(edit));
54
const minimalStringReplacements = stringReplacements.map(replacement => replacement.removeCommonSuffixPrefix(text));
55
return minimalStringReplacements.map(replacement => transformer.getTextReplacement(replacement));
56
}
57
58
export function convertItemsToStableObservables<T>(items: IObservable<readonly T[]>, store: DisposableStore): IObservable<IObservable<T>[]> {
59
const result = observableValue<IObservable<T>[]>('result', []);
60
const innerObservables: ISettableObservable<T>[] = [];
61
62
store.add(autorun(reader => {
63
const itemsValue = items.read(reader);
64
65
transaction(tx => {
66
if (itemsValue.length !== innerObservables.length) {
67
innerObservables.length = itemsValue.length;
68
for (let i = 0; i < innerObservables.length; i++) {
69
if (!innerObservables[i]) {
70
innerObservables[i] = observableValue<T>('item', itemsValue[i]);
71
}
72
}
73
result.set([...innerObservables], tx);
74
}
75
innerObservables.forEach((o, i) => o.set(itemsValue[i], tx));
76
});
77
}));
78
79
return result;
80
}
81
82
export class ObservableContextKeyService {
83
constructor(
84
private readonly _contextKeyService: IContextKeyService,
85
) {
86
}
87
88
bind<T extends ContextKeyValue>(key: RawContextKey<T>, obs: IObservable<T>): IDisposable;
89
bind<T extends ContextKeyValue>(key: RawContextKey<T>, fn: (reader: IReader) => T): IDisposable;
90
bind<T extends ContextKeyValue>(key: RawContextKey<T>, obs: IObservable<T> | ((reader: IReader) => T)): IDisposable {
91
return bindContextKey(key, this._contextKeyService, obs instanceof Function ? obs : reader => obs.read(reader));
92
}
93
}
94
95
export function wait(ms: number, cancellationToken?: CancellationToken): Promise<void> {
96
return new Promise(resolve => {
97
let d: IDisposable | undefined = undefined;
98
const handle = setTimeout(() => {
99
if (d) { d.dispose(); }
100
resolve();
101
}, ms);
102
if (cancellationToken) {
103
d = cancellationToken.onCancellationRequested(() => {
104
clearTimeout(handle);
105
if (d) { d.dispose(); }
106
resolve();
107
});
108
}
109
});
110
}
111
112