Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
microsoft
GitHub Repository: microsoft/vscode
Path: blob/main/src/vs/workbench/contrib/editTelemetry/browser/telemetry/editTracker.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
7
import { Disposable } from '../../../../../base/common/lifecycle.js';
8
import { observableSignal, runOnChange, IReader } from '../../../../../base/common/observable.js';
9
import { AnnotatedStringEdit } from '../../../../../editor/common/core/edits/stringEdit.js';
10
import { OffsetRange } from '../../../../../editor/common/core/ranges/offsetRange.js';
11
import { TextModelEditSource } from '../../../../../editor/common/textModelEditSource.js';
12
import { IDocumentWithAnnotatedEdits, EditKeySourceData, EditSource } from '../helpers/documentWithAnnotatedEdits.js';
13
14
/**
15
* Tracks a single document.
16
*/
17
export class DocumentEditSourceTracker<T = void> extends Disposable {
18
private _edits: AnnotatedStringEdit<EditKeySourceData> = AnnotatedStringEdit.empty;
19
private _pendingExternalEdits: AnnotatedStringEdit<EditKeySourceData> = AnnotatedStringEdit.empty;
20
21
private readonly _update = observableSignal(this);
22
private readonly _sumAddedCharactersPerKey: Map<string, number> = new Map();
23
24
constructor(
25
private readonly _doc: IDocumentWithAnnotatedEdits,
26
public readonly data: T,
27
) {
28
super();
29
30
this._register(runOnChange(this._doc.value, (_val, _prevVal, edits) => {
31
const eComposed = AnnotatedStringEdit.compose(edits.map(e => e.edit));
32
if (eComposed.replacements.every(e => e.data.source.category === 'external')) {
33
if (this._edits.isEmpty()) {
34
// Ignore initial external edits
35
} else {
36
// queue pending external edits
37
this._pendingExternalEdits = this._pendingExternalEdits.compose(eComposed);
38
}
39
} else {
40
if (!this._pendingExternalEdits.isEmpty()) {
41
this._applyEdit(this._pendingExternalEdits);
42
this._pendingExternalEdits = AnnotatedStringEdit.empty;
43
}
44
this._applyEdit(eComposed);
45
}
46
47
this._update.trigger(undefined);
48
}));
49
}
50
51
private _applyEdit(e: AnnotatedStringEdit<EditKeySourceData>): void {
52
for (const r of e.replacements) {
53
const existing = this._sumAddedCharactersPerKey.get(r.data.key) ?? 0;
54
const newCount = existing + r.getNewLength();
55
this._sumAddedCharactersPerKey.set(r.data.key, newCount);
56
}
57
58
this._edits = this._edits.compose(e);
59
}
60
61
async waitForQueue(): Promise<void> {
62
await this._doc.waitForQueue();
63
}
64
65
public getChangedCharactersCount(key: string): number {
66
const val = this._sumAddedCharactersPerKey.get(key);
67
return val ?? 0;
68
}
69
70
getTrackedRanges(reader?: IReader): TrackedEdit[] {
71
this._update.read(reader);
72
const ranges = this._edits.getNewRanges();
73
return ranges.map((r, idx) => {
74
const e = this._edits.replacements[idx];
75
const te = new TrackedEdit(e.replaceRange, r, e.data.key, e.data.source, e.data.representative);
76
return te;
77
});
78
}
79
80
isEmpty(): boolean {
81
return this._edits.isEmpty();
82
}
83
84
public reset(): void {
85
this._edits = AnnotatedStringEdit.empty;
86
}
87
88
public _getDebugVisualization() {
89
const ranges = this.getTrackedRanges();
90
const txt = this._doc.value.get().value;
91
92
return {
93
...{ $fileExtension: 'text.w' },
94
'value': txt,
95
'decorations': ranges.map(r => {
96
return {
97
range: [r.range.start, r.range.endExclusive],
98
color: r.source.getColor(),
99
};
100
})
101
};
102
}
103
}
104
105
export class TrackedEdit {
106
constructor(
107
public readonly originalRange: OffsetRange,
108
public readonly range: OffsetRange,
109
public readonly sourceKey: string,
110
public readonly source: EditSource,
111
public readonly sourceRepresentative: TextModelEditSource,
112
) { }
113
}
114
115