rangeMapping.ts ×28

Frontier kind: Code frontier

unlabeled · c_6bdebf24e804

187 tests · 6081 LOC · 35 files · introduces 0 tests · 126 LOC · 1 file

Introduces — evidence that enters the hierarchy at this concept

Code
28 ranges126 lines · 1 files
Tests
0 tests

Contains — complete concept membership

All code (extent)
984 ranges6081 lines · 35 files · Browse complete extent
All tests (intent)
187 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.

1 file ranked by introduced lines: 126 introduced LOC across 28 ranges. Expand a file to inspect source; the > gutter marks introduced lines.

src/vs/editor/common/diff/rangeMapping.ts 126 introduced LOC · 28 ranges

Open complete file

1 > /*--------------------------------------------------------------------------------------------- rangeMapping.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 { groupAdjacentBy } from '../../../base/common/arrays.js';
7 > import { assertFn, checkAdjacentItems } from '../../../base/common/assert.js';
8 > import { BugIndicatingError } from '../../../base/common/errors.js';
9 > import { LineRange } from '../core/ranges/lineRange.js';
10 > import { Position } from '../core/position.js';
11 > import { Range } from '../core/range.js';
12 > import { TextReplacement, TextEdit } from '../core/edits/textEdit.js';
13 > import { AbstractText } from '../core/text/abstractText.js';
14 > import { IChange } from './legacyLinesDiffComputer.js';
15 >
16 > /**
17 > * Maps a line range in the original text model to a line range in the modified text model.
18 > */
19 > export class LineRangeMapping {
20 > public static inverse(mapping: readonly LineRangeMapping[], originalLineCount: number, modifiedLineCount: number): LineRangeMapping[] {
21 const result: LineRangeMapping[] = [];
22 let lastOriginalEndLineNumber = 1;
43 return result;
44 }
46 > public static clip(mapping: readonly LineRangeMapping[], originalRange: LineRange, modifiedRange: LineRange): LineRangeMapping[] {
47 const result: LineRangeMapping[] = [];
48 for (const m of mapping) {
55 return result;
56 }
58 > /**
59 > * The line range in the original text model.
60 > */
61 > public readonly original: LineRange;
62 >
63 > /**
64 > * The line range in the modified text model.
65 > */
66 > public readonly modified: LineRange;
67 >
68 > constructor(
69 originalRange: LineRange,
70 modifiedRange: LineRange
73 this.modified = modifiedRange;
74 }
76 >
77 > public toString(): string {
78 return `{${this.original.toString()}->${this.modified.toString()}}`;
79 }
81 > public flip(): LineRangeMapping {
82 return new LineRangeMapping(this.modified, this.original);
83 }
85 > public join(other: LineRangeMapping): LineRangeMapping {
86 return new LineRangeMapping(
87 this.original.join(other.original),
89 );
90 }
92 > public get changedLineCount() {
93 return Math.max(this.original.length, this.modified.length);
94 }
96 > /**
97 > * This method assumes that the LineRangeMapping describes a valid diff!
98 > * I.e. if one range is empty, the other range cannot be the entire document.
99 > * It avoids various problems when the line range points to non-existing line-numbers.
100 > */
101 > public toRangeMapping(): RangeMapping {
102 const origInclusiveRange = this.original.toInclusiveRange();
103 const modInclusiveRange = this.modified.toInclusiveRange();
124 }
125 }
127 > /**
128 > * This method assumes that the LineRangeMapping describes a valid diff!
129 > * I.e. if one range is empty, the other range cannot be the entire document.
130 > * It avoids various problems when the line range points to non-existing line-numbers.
131 > */
132 > public toRangeMapping2(original: string[], modified: string[]): RangeMapping {
133 if (isValidLineNumber(this.original.endLineNumberExclusive, original)
134 && isValidLineNumber(this.modified.endLineNumberExclusive, modified)) {
170 throw new BugIndicatingError();
171 }
172 > } rangeMapping.ts
173 >
174 function normalizePosition(position: Position, content: string[]): Position {
175 if (position.lineNumber < 1) {
185 return position;
186 }
188 function isValidLineNumber(lineNumber: number, lines: string[]): boolean {
189 return lineNumber >= 1 && lineNumber <= lines.length;
190 }
192 > /**
193 > * Maps a line range in the original text model to a line range in the modified text model.
194 > * Also contains inner range mappings.
195 > */
196 > export class DetailedLineRangeMapping extends LineRangeMapping {
197 > public static toTextEdit(mapping: readonly DetailedLineRangeMapping[], modified: AbstractText): TextEdit {
198 const replacements: TextReplacement[] = [];
199 for (const m of mapping) {
205 return new TextEdit(replacements);
206 }
208 > public static fromRangeMappings(rangeMappings: RangeMapping[]): DetailedLineRangeMapping {
209 const originalRange = LineRange.join(rangeMappings.map(r => LineRange.fromRangeInclusive(r.originalRange)));
210 const modifiedRange = LineRange.join(rangeMappings.map(r => LineRange.fromRangeInclusive(r.modifiedRange)));
211 return new DetailedLineRangeMapping(originalRange, modifiedRange, rangeMappings);
212 }
214 > /**
215 > * If inner changes have not been computed, this is set to undefined.
216 > * Otherwise, it represents the character-level diff in this line range.
217 > * The original range of each range mapping should be contained in the original line range (same for modified), exceptions are new-lines.
218 > * Must not be an empty array.
219 > */
220 > public readonly innerChanges: RangeMapping[] | undefined;
221 >
222 > constructor(
223 originalRange: LineRange,
224 modifiedRange: LineRange,
228 this.innerChanges = innerChanges;
229 }
231 > public override flip(): DetailedLineRangeMapping {
232 return new DetailedLineRangeMapping(this.modified, this.original, this.innerChanges?.map(c => c.flip()));
233 }
235 > public withInnerChangesFromLineRanges(): DetailedLineRangeMapping {
236 return new DetailedLineRangeMapping(this.original, this.modified, [this.toRangeMapping()]);
237 }
238 > } rangeMapping.ts
239 >
240 > /**
241 > * Maps a range in the original text model to a range in the modified text model.
242 > */
243 > export class RangeMapping {
244 > public static fromEdit(edit: TextEdit): RangeMapping[] {
245 const newRanges = edit.getNewRanges();
246 const result = edit.replacements.map((e, idx) => new RangeMapping(e.range, newRanges[idx]));
247 return result;
248 }
250 > public static fromEditJoin(edit: TextEdit): RangeMapping {
251 const newRanges = edit.getNewRanges();
252 const result = edit.replacements.map((e, idx) => new RangeMapping(e.range, newRanges[idx]));
253 return RangeMapping.join(result);
254 }
256 > public static join(rangeMappings: RangeMapping[]): RangeMapping {
257 if (rangeMappings.length === 0) {
258 throw new BugIndicatingError('Cannot join an empty list of range mappings');
264 return result;
265 }
267 > public static assertSorted(rangeMappings: RangeMapping[]): void {
268 for (let i = 1; i < rangeMappings.length; i++) {
269 const previous = rangeMappings[i - 1];
277 }
278 }
280 > /**
281 > * The original range.
282 > */
283 > readonly originalRange: Range;
284 >
285 > /**
286 > * The modified range.
287 > */
288 > readonly modifiedRange: Range;
289 >
290 > constructor(
291 originalRange: Range,
292 modifiedRange: Range
295 this.modifiedRange = modifiedRange;
296 }
298 > public toString(): string {
299 return `{${this.originalRange.toString()}->${this.modifiedRange.toString()}}`;
300 }
302 > public flip(): RangeMapping {
303 return new RangeMapping(this.modifiedRange, this.originalRange);
304 }
306 > /**
307 > * Creates a single text edit that describes the change from the original to the modified text.
308 > */
309 > public toTextEdit(modified: AbstractText): TextReplacement {
310 const newText = modified.getValueOfRange(this.modifiedRange);
311 return new TextReplacement(this.originalRange, newText);
312 }
314 > public join(other: RangeMapping): RangeMapping {
315 return new RangeMapping(
316 this.originalRange.plusRange(other.originalRange),
318 );
319 }
320 > } rangeMapping.ts
321 >
322 > export function lineRangeMappingFromRangeMappings(alignments: readonly RangeMapping[], originalLines: AbstractText, modifiedLines: AbstractText, dontAssertStartLine: boolean = false): DetailedLineRangeMapping[] {
323 const changes: DetailedLineRangeMapping[] = [];
324 for (const g of groupAdjacentBy(
358 return changes;
359 }
361 > export function getLineRangeMapping(rangeMapping: RangeMapping, originalLines: AbstractText, modifiedLines: AbstractText): DetailedLineRangeMapping {
362 let lineStartDelta = 0;
363 let lineEndDelta = 0;
395 return new DetailedLineRangeMapping(originalLineRange, modifiedLineRange, [rangeMapping]);
396 }
398 > export function lineRangeMappingFromChange(change: IChange): LineRangeMapping {
399 let originalRange: LineRange;
400 if (change.originalEndLineNumber === 0) {