Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
microsoft
GitHub Repository: microsoft/vscode
Path: blob/main/extensions/copilot/src/platform/diff/node/diffServiceImpl.ts
13401 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 { WorkerWithRpcProxy } from '../../../util/node/worker';
7
import { Lazy } from '../../../util/vs/base/common/lazy';
8
import * as path from '../../../util/vs/base/common/path';
9
import { Range } from '../../../util/vs/editor/common/core/range';
10
import { LineRange } from '../../../util/vs/editor/common/core/ranges/lineRange';
11
12
import { existsSync } from 'fs';
13
import { ILinesDiffComputerOptions, MovedText } from '../../../util/vs/editor/common/diff/linesDiffComputer';
14
import { DetailedLineRangeMapping, LineRangeMapping, RangeMapping } from '../../../util/vs/editor/common/diff/rangeMapping';
15
import { IDiffService, IDocumentDiff } from '../common/diffService';
16
import * as diffWorker from '../common/diffWorker';
17
18
export class DiffServiceImpl implements IDiffService {
19
20
declare readonly _serviceBrand: undefined;
21
22
private _worker: Lazy<WorkerWithRpcProxy<typeof diffWorker>>;
23
24
constructor(private _useWorker = true) {
25
this._worker = new Lazy(() => {
26
const workerPath = firstExistingPath([
27
path.join(__dirname, 'diffWorker.js'), // after bundling by esbuild
28
path.join(__dirname, '../../../../dist/diffWorker.js'), // relative to the typescript source file (for tsx)
29
]);
30
31
if (workerPath === undefined) {
32
throw new Error('DiffServiceImpl: worker file not found');
33
}
34
35
return new WorkerWithRpcProxy<typeof diffWorker>(workerPath, {
36
name: 'Diff worker',
37
});
38
});
39
}
40
41
dispose(): void {
42
this._worker.rawValue?.terminate();
43
}
44
45
async computeDiff(original: string, modified: string, options: ILinesDiffComputerOptions): Promise<IDocumentDiff> {
46
const result = this._useWorker ?
47
await this._worker.value.proxy.computeDiff(original, modified, options) :
48
await diffWorker.computeDiff(original, modified, options);
49
50
// Convert from space efficient JSON data to rich objects.
51
const diff: IDocumentDiff = {
52
identical: result.identical,
53
quitEarly: result.quitEarly,
54
changes: toLineRangeMappings(result.changes),
55
moves: result.moves.map(m => new MovedText(
56
new LineRangeMapping(new LineRange(m[0], m[1]), new LineRange(m[2], m[3])),
57
toLineRangeMappings(m[4])
58
))
59
};
60
return diff;
61
}
62
}
63
64
export function toLineRangeMappings(changes: readonly diffWorker.ILineChange[]): readonly DetailedLineRangeMapping[] {
65
return changes.map(
66
(c) => new DetailedLineRangeMapping(
67
new LineRange(c[0], c[1]),
68
new LineRange(c[2], c[3]),
69
c[4]?.map(
70
(c) => new RangeMapping(
71
new Range(c[0], c[1], c[2], c[3]),
72
new Range(c[4], c[5], c[6], c[7])
73
)
74
)
75
)
76
);
77
}
78
79
function firstExistingPath(paths: string[]): string | undefined {
80
for (const p of paths) {
81
if (existsSync(p)) {
82
return p;
83
}
84
}
85
}
86
87