Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
microsoft
GitHub Repository: microsoft/vscode
Path: blob/main/src/vs/workbench/contrib/editTelemetry/common/arcTracker.ts
5251 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 { sumBy } from '../../../../base/common/arrays.js';
7
import { LineEdit } from '../../../../editor/common/core/edits/lineEdit.js';
8
import { AnnotatedStringEdit, BaseStringEdit, IEditData } from '../../../../editor/common/core/edits/stringEdit.js';
9
import { AbstractText } from '../../../../editor/common/core/text/abstractText.js';
10
11
/**
12
* The ARC (accepted and retained characters) counts how many characters inserted by the initial suggestion (trackedEdit)
13
* stay unmodified after a certain amount of time after acceptance.
14
*/
15
export class ArcTracker {
16
private _updatedTrackedEdit: AnnotatedStringEdit<IsTrackedEditData>;
17
private _trackedEdit: BaseStringEdit;
18
19
constructor(
20
private readonly _valueBeforeTrackedEdit: AbstractText,
21
trackedEdit: BaseStringEdit,
22
) {
23
this._trackedEdit = trackedEdit.removeCommonSuffixPrefix(_valueBeforeTrackedEdit.getValue());
24
this._updatedTrackedEdit = this._trackedEdit.mapData(() => new IsTrackedEditData(true));
25
}
26
27
getOriginalCharacterCount(): number {
28
return sumBy(this._trackedEdit.replacements, e => e.getNewLength());
29
}
30
31
/**
32
* edit must apply to _updatedTrackedEdit.apply(_valueBeforeTrackedEdit)
33
*/
34
handleEdits(edit: BaseStringEdit): void {
35
const e = edit.mapData(_d => new IsTrackedEditData(false));
36
const composedEdit = this._updatedTrackedEdit.compose(e); // (still) applies to _valueBeforeTrackedEdit
37
38
// TODO@hediet improve memory by using:
39
// composedEdit = const onlyTrackedEdit = composedEdit.decomposeSplit(e => !e.data.isTrackedEdit).e2;
40
41
this._updatedTrackedEdit = composedEdit;
42
}
43
44
getAcceptedRestrainedCharactersCount(): number {
45
const s = sumBy(this._updatedTrackedEdit.replacements, e => e.data.isTrackedEdit ? e.getNewLength() : 0);
46
return s;
47
}
48
49
getDebugState(): unknown {
50
return {
51
edits: this._updatedTrackedEdit.replacements.map(e => ({
52
range: e.replaceRange.toString(),
53
newText: e.newText,
54
isTrackedEdit: e.data.isTrackedEdit,
55
}))
56
};
57
}
58
59
public getLineCountInfo(): { deletedLineCounts: number; insertedLineCounts: number } {
60
const e = this._updatedTrackedEdit.toStringEdit(r => r.data.isTrackedEdit);
61
const le = LineEdit.fromStringEdit(e, this._valueBeforeTrackedEdit);
62
const deletedLineCount = sumBy(le.replacements, r => r.lineRange.length);
63
const insertedLineCount = sumBy(le.getNewLineRanges(), r => r.length);
64
return {
65
deletedLineCounts: deletedLineCount,
66
insertedLineCounts: insertedLineCount,
67
};
68
}
69
70
public getValues(): unknown {
71
return {
72
arc: this.getAcceptedRestrainedCharactersCount(),
73
...this.getLineCountInfo(),
74
};
75
}
76
}
77
78
export class IsTrackedEditData implements IEditData<IsTrackedEditData> {
79
constructor(
80
public readonly isTrackedEdit: boolean
81
) { }
82
83
join(data: IsTrackedEditData): IsTrackedEditData | undefined {
84
if (this.isTrackedEdit !== data.isTrackedEdit) {
85
return undefined;
86
}
87
return this;
88
}
89
}
90
91