legacyLinesDiffComputer.ts ×28

Frontier kind: Code frontier

unlabeled · c_c67a47fbd6f3

182 tests · 7508 LOC · 43 files · introduces 0 tests · 209 LOC · 2 files

Introduces — evidence that enters the hierarchy at this concept

Code
32 ranges209 lines · 2 files
Tests
0 tests

Contains — complete concept membership

All code (extent)
1166 ranges7508 lines · 43 files · Browse complete extent
All tests (intent)
182 testsBrowse complete intent

Neighbourhood graph

The orange circle is the focus. Violet and green circles are every ancestor and descendant, broader and narrower, at any distance; blue squares and pink diamonds are the introduced files and exact introduced tests of every visible concept, not only the focus's. Arrows point from broader to narrower concepts and bridge only concepts omitted from this view. Undirected links show source or test introduction. Concept and file size follows LOC; exact test nodes use test-count units.

Introduced files, introduced tests, and structurally relevant concept specialization

In the embedded map, ordinary wheel input scrolls the page; use the visible controls to zoom and drag to pan. Open the full-screen map for canvas navigation: wheel pans, Ctrl/Command plus wheel zooms, and arrow keys pan when this region is focused. On touch screens, open the full-screen map to pan or pinch. If JavaScript or WebGL is unavailable, use the native relationship evidence on this page.

Graph controls are ready.

Interactive rendering requires JavaScript and WebGL. Use the native relationship evidence on this page while the interactive map is unavailable.

Native relationship evidence

Every exact file and test below is linked only from the concept that introduces it.

Introduced tests

Every collected test enters the hierarchy at exactly one concept.

No tests are introduced at this concept. Its intent tests are introduced by other concepts.

Introduced code

Every collected source range enters the hierarchy at exactly one concept.

2 files ranked by introduced lines: 209 introduced LOC across 32 ranges. Expand a file to inspect source; the > gutter marks introduced lines.

src/vs/editor/common/diff/legacyLinesDiffComputer.ts 173 introduced LOC · 28 ranges

Open complete file

1 > /*--------------------------------------------------------------------------------------------- legacyLinesDiffComputer.ts
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 { CharCode } from '../../../base/common/charCode.js';
7 > import { IDiffChange, ISequence, LcsDiff, IDiffResult } from '../../../base/common/diff/diff.js';
8 > import { ILinesDiffComputer, ILinesDiffComputerOptions, LinesDiff } from './linesDiffComputer.js';
9 > import { RangeMapping, DetailedLineRangeMapping } from './rangeMapping.js';
10 > import * as strings from '../../../base/common/strings.js';
11 > import { Range } from '../core/range.js';
12 > import { assertFn, checkAdjacentItems } from '../../../base/common/assert.js';
13 > import { LineRange } from '../core/ranges/lineRange.js';
14 >
15 > const MINIMUM_MATCHING_CHARACTER_LENGTH = 3;
16 >
17 > export class LegacyLinesDiffComputer implements ILinesDiffComputer {
18 > computeDiff(originalLines: string[], modifiedLines: string[], options: ILinesDiffComputerOptions): LinesDiff {
19 const diffComputer = new DiffComputer(originalLines, modifiedLines, {
20 maxComputationTime: options.maxComputationTimeMs,
79 return new LinesDiff(changes, [], result.quitEarly);
80 }
82 >
83 > export interface IDiffComputationResult {
84 > quitEarly: boolean;
85 > identical: boolean;
86 >
87 > /**
88 > * The changes as (legacy) line change array.
89 > * @deprecated Use `changes2` instead.
90 > */
91 > changes: ILineChange[];
92 >
93 > /**
94 > * The changes as (modern) line range mapping array.
95 > */
96 > changes2: readonly DetailedLineRangeMapping[];
97 > }
98 >
99 > /**
100 > * A change
101 > */
102 > export interface IChange {
103 > readonly originalStartLineNumber: number;
104 > readonly originalEndLineNumber: number;
105 > readonly modifiedStartLineNumber: number;
106 > readonly modifiedEndLineNumber: number;
107 > }
108 >
109 > /**
110 > * A character level change.
111 > */
112 > export interface ICharChange extends IChange {
113 > readonly originalStartColumn: number;
114 > readonly originalEndColumn: number;
115 > readonly modifiedStartColumn: number;
116 > readonly modifiedEndColumn: number;
117 > }
118 >
119 > /**
120 > * A line change
121 > */
122 > export interface ILineChange extends IChange {
123 > readonly charChanges: ICharChange[] | undefined;
124 > }
125 >
126 > export interface IDiffComputerResult {
127 > quitEarly: boolean;
128 > changes: ILineChange[];
129 > }
130 >
131 function computeDiff(originalSequence: ISequence, modifiedSequence: ISequence, continueProcessingPredicate: () => boolean, pretty: boolean): IDiffResult {
132 const diffAlgo = new LcsDiff(originalSequence, modifiedSequence, continueProcessingPredicate);
133 return diffAlgo.ComputeDiff(pretty);
134 }
136 > class LineSequence implements ISequence {
137 >
138 > public readonly lines: string[];
139 > private readonly _startColumns: number[];
140 > private readonly _endColumns: number[];
141 >
142 > constructor(lines: string[]) {
143 const startColumns: number[] = [];
144 const endColumns: number[] = [];
151 this._endColumns = endColumns;
152 }
154 > public getElements(): Int32Array | number[] | string[] {
155 const elements: string[] = [];
156 for (let i = 0, len = this.lines.length; i < len; i++) {
159 return elements;
160 }
162 > public getStrictElement(index: number): string {
163 return this.lines[index];
164 }
166 > public getStartLineNumber(i: number): number {
167 return i + 1;
168 }
170 > public getEndLineNumber(i: number): number {
171 return i + 1;
172 }
174 > public createCharSequence(shouldIgnoreTrimWhitespace: boolean, startIndex: number, endIndex: number): CharSequence {
175 const charCodes: number[] = [];
176 const lineNumbers: number[] = [];
197 return new CharSequence(charCodes, lineNumbers, columns);
198 }
200 >
201 > class CharSequence implements ISequence {
202 >
203 > private readonly _charCodes: number[];
204 > private readonly _lineNumbers: number[];
205 > private readonly _columns: number[];
206 >
207 > constructor(charCodes: number[], lineNumbers: number[], columns: number[]) {
208 this._charCodes = charCodes;
209 this._lineNumbers = lineNumbers;
210 this._columns = columns;
211 }
213 > public toString() {
214 return (
215 '[' + this._charCodes.map((s, idx) => (s === CharCode.LineFeed ? '\\n' : String.fromCharCode(s)) + `-(${this._lineNumbers[idx]},${this._columns[idx]})`).join(', ') + ']'
216 );
217 }
219 > private _assertIndex(index: number, arr: number[]): void {
220 if (index < 0 || index >= arr.length) {
221 throw new Error(`Illegal index`);
222 }
223 }
225 > public getElements(): Int32Array | number[] | string[] {
226 return this._charCodes;
227 }
229 > public getStartLineNumber(i: number): number {
230 if (i > 0 && i === this._lineNumbers.length) {
231 // the start line number of the element after the last element
237 return this._lineNumbers[i];
238 }
240 > public getEndLineNumber(i: number): number {
241 if (i === -1) {
242 // the end line number of the element before the first element
251 return this._lineNumbers[i];
252 }
254 > public getStartColumn(i: number): number {
255 if (i > 0 && i === this._columns.length) {
256 // the start column of the element after the last element
261 return this._columns[i];
262 }
264 > public getEndColumn(i: number): number {
265 if (i === -1) {
266 // the end column of the element before the first element
275 return this._columns[i] + 1;
276 }
278 >
279 > class CharChange implements ICharChange {
280 >
281 > public originalStartLineNumber: number;
282 > public originalStartColumn: number;
283 > public originalEndLineNumber: number;
284 > public originalEndColumn: number;
285 >
286 > public modifiedStartLineNumber: number;
287 > public modifiedStartColumn: number;
288 > public modifiedEndLineNumber: number;
289 > public modifiedEndColumn: number;
290 >
291 > constructor(
292 originalStartLineNumber: number,
293 originalStartColumn: number,
308 this.modifiedEndColumn = modifiedEndColumn;
309 }
311 > public static createFromDiffChange(diffChange: IDiffChange, originalCharSequence: CharSequence, modifiedCharSequence: CharSequence): CharChange {
312 const originalStartLineNumber = originalCharSequence.getStartLineNumber(diffChange.originalStart);
313 const originalStartColumn = originalCharSequence.getStartColumn(diffChange.originalStart);
325 );
326 }
328 >
329 function postProcessCharChanges(rawChanges: IDiffChange[]): IDiffChange[] {
330 if (rawChanges.length <= 1) {
356 return result;
357 }
359 > class LineChange implements ILineChange {
360 > public originalStartLineNumber: number;
361 > public originalEndLineNumber: number;
362 > public modifiedStartLineNumber: number;
363 > public modifiedEndLineNumber: number;
364 > public charChanges: CharChange[] | undefined;
365 >
366 > constructor(
367 originalStartLineNumber: number,
368 originalEndLineNumber: number,
377 this.charChanges = charChanges;
378 }
380 > public static createFromDiffResult(shouldIgnoreTrimWhitespace: boolean, diffChange: IDiffChange, originalLineSequence: LineSequence, modifiedLineSequence: LineSequence, continueCharDiff: () => boolean, shouldComputeCharChanges: boolean, shouldPostProcessCharChanges: boolean): LineChange {
381 let originalStartLineNumber: number;
382 let originalEndLineNumber: number;
422 return new LineChange(originalStartLineNumber, originalEndLineNumber, modifiedStartLineNumber, modifiedEndLineNumber, charChanges);
423 }
425 >
426 > export interface IDiffComputerOpts {
427 > shouldComputeCharChanges: boolean;
428 > shouldPostProcessCharChanges: boolean;
429 > shouldIgnoreTrimWhitespace: boolean;
430 > shouldMakePrettyDiff: boolean;
431 > maxComputationTime: number;
432 > }
433 >
434 > export class DiffComputer {
435 >
436 > private readonly shouldComputeCharChanges: boolean;
437 > private readonly shouldPostProcessCharChanges: boolean;
438 > private readonly shouldIgnoreTrimWhitespace: boolean;
439 > private readonly shouldMakePrettyDiff: boolean;
440 > private readonly originalLines: string[];
441 > private readonly modifiedLines: string[];
442 > private readonly original: LineSequence;
443 > private readonly modified: LineSequence;
444 > private readonly continueLineDiff: () => boolean;
445 > private readonly continueCharDiff: () => boolean;
446 >
447 > constructor(originalLines: string[], modifiedLines: string[], opts: IDiffComputerOpts) {
448 this.shouldComputeCharChanges = opts.shouldComputeCharChanges;
449 this.shouldPostProcessCharChanges = opts.shouldPostProcessCharChanges;
458 this.continueCharDiff = createContinueProcessingPredicate(opts.maxComputationTime === 0 ? 0 : Math.min(opts.maxComputationTime, 5000)); // never run after 5s for character changes...
459 }
461 > public computeDiff(): IDiffComputerResult {
462
463 if (this.original.lines.length === 1 && this.original.lines[0].length === 0) {
596 };
597 }
599 > private _pushTrimWhitespaceCharChange(
600 result: LineChange[],
601 originalLineNumber: number, originalStartColumn: number, originalEndColumn: number,
620 ));
621 }
623 > private _mergeTrimWhitespaceCharChange(
624 result: LineChange[],
625 originalLineNumber: number, originalStartColumn: number, originalEndColumn: number,
662 return false;
663 }
665 >
666 function getFirstNonBlankColumn(txt: string, defaultValue: number): number {
667 const r = strings.firstNonWhitespaceIndex(txt);
671 return r + 1;
672 }
674 function getLastNonBlankColumn(txt: string, defaultValue: number): number {
675 const r = strings.lastNonWhitespaceIndex(txt);
679 return r + 2;
680 }
682 function createContinueProcessingPredicate(maximumRuntime: number): () => boolean {
683 if (maximumRuntime === 0) {
src/vs/editor/common/diff/linesDiffComputer.ts 36 introduced LOC · 4 ranges

Open complete file

1 > /*--------------------------------------------------------------------------------------------- linesDiffComputer.ts
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 { DetailedLineRangeMapping, LineRangeMapping } from './rangeMapping.js';
7 >
8 > export interface ILinesDiffComputer {
9 > computeDiff(originalLines: string[], modifiedLines: string[], options: ILinesDiffComputerOptions): LinesDiff;
10 > }
11 >
12 > export interface ILinesDiffComputerOptions {
13 > readonly ignoreTrimWhitespace: boolean;
14 > readonly maxComputationTimeMs: number;
15 > readonly computeMoves: boolean;
16 > readonly extendToSubwords?: boolean;
17 > }
18 >
19 > export class LinesDiff {
20 > constructor(
21 readonly changes: readonly DetailedLineRangeMapping[],
22
34 ) {
35 }
37 >
38 > export class MovedText {
39 > public readonly lineRangeMapping: LineRangeMapping;
40 >
41 > /**
42 > * The diff from the original text to the moved text.
43 > * Must be contained in the original/modified line range.
44 > * Can be empty if the text didn't change (only moved).
45 > */
46 > public readonly changes: readonly DetailedLineRangeMapping[];
47 >
48 > constructor(
49 lineRangeMapping: LineRangeMapping,
50 changes: readonly DetailedLineRangeMapping[],
53 this.changes = changes;
54 }
56 > public flip(): MovedText {
57 return new MovedText(this.lineRangeMapping.flip(), this.changes.map(c => c.flip()));
58 }