Path: blob/main/extensions/copilot/src/platform/diff/node/diffServiceImpl.ts
13401 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 { WorkerWithRpcProxy } from '../../../util/node/worker';6import { Lazy } from '../../../util/vs/base/common/lazy';7import * as path from '../../../util/vs/base/common/path';8import { Range } from '../../../util/vs/editor/common/core/range';9import { LineRange } from '../../../util/vs/editor/common/core/ranges/lineRange';1011import { existsSync } from 'fs';12import { ILinesDiffComputerOptions, MovedText } from '../../../util/vs/editor/common/diff/linesDiffComputer';13import { DetailedLineRangeMapping, LineRangeMapping, RangeMapping } from '../../../util/vs/editor/common/diff/rangeMapping';14import { IDiffService, IDocumentDiff } from '../common/diffService';15import * as diffWorker from '../common/diffWorker';1617export class DiffServiceImpl implements IDiffService {1819declare readonly _serviceBrand: undefined;2021private _worker: Lazy<WorkerWithRpcProxy<typeof diffWorker>>;2223constructor(private _useWorker = true) {24this._worker = new Lazy(() => {25const workerPath = firstExistingPath([26path.join(__dirname, 'diffWorker.js'), // after bundling by esbuild27path.join(__dirname, '../../../../dist/diffWorker.js'), // relative to the typescript source file (for tsx)28]);2930if (workerPath === undefined) {31throw new Error('DiffServiceImpl: worker file not found');32}3334return new WorkerWithRpcProxy<typeof diffWorker>(workerPath, {35name: 'Diff worker',36});37});38}3940dispose(): void {41this._worker.rawValue?.terminate();42}4344async computeDiff(original: string, modified: string, options: ILinesDiffComputerOptions): Promise<IDocumentDiff> {45const result = this._useWorker ?46await this._worker.value.proxy.computeDiff(original, modified, options) :47await diffWorker.computeDiff(original, modified, options);4849// Convert from space efficient JSON data to rich objects.50const diff: IDocumentDiff = {51identical: result.identical,52quitEarly: result.quitEarly,53changes: toLineRangeMappings(result.changes),54moves: result.moves.map(m => new MovedText(55new LineRangeMapping(new LineRange(m[0], m[1]), new LineRange(m[2], m[3])),56toLineRangeMappings(m[4])57))58};59return diff;60}61}6263export function toLineRangeMappings(changes: readonly diffWorker.ILineChange[]): readonly DetailedLineRangeMapping[] {64return changes.map(65(c) => new DetailedLineRangeMapping(66new LineRange(c[0], c[1]),67new LineRange(c[2], c[3]),68c[4]?.map(69(c) => new RangeMapping(70new Range(c[0], c[1], c[2], c[3]),71new Range(c[4], c[5], c[6], c[7])72)73)74)75);76}7778function firstExistingPath(paths: string[]): string | undefined {79for (const p of paths) {80if (existsSync(p)) {81return p;82}83}84}858687