|
3 | 3 | * Licensed under the MIT License. See License.txt in the project root for license information.
|
4 | 4 | *--------------------------------------------------------------------------------------------*/
|
5 | 5 |
|
6 |
| -import { compareBy, CompareResult, equals, numberComparator, tieBreakComparators } from 'vs/base/common/arrays'; |
| 6 | +import { CompareResult, equals } from 'vs/base/common/arrays'; |
7 | 7 | import { BugIndicatingError } from 'vs/base/common/errors';
|
8 |
| -import { splitLines } from 'vs/base/common/strings'; |
9 |
| -import { Constants } from 'vs/base/common/uint'; |
10 |
| -import { Position } from 'vs/editor/common/core/position'; |
11 |
| -import { Range } from 'vs/editor/common/core/range'; |
12 | 8 | import { ILanguageService } from 'vs/editor/common/languages/language';
|
13 | 9 | import { ITextModel } from 'vs/editor/common/model';
|
14 | 10 | import { IModelService } from 'vs/editor/common/services/model';
|
15 | 11 | import { EditorModel } from 'vs/workbench/common/editor/editorModel';
|
16 | 12 | import { autorunHandleChanges, derivedObservable, IObservable, IReader, ITransaction, keepAlive, ObservableValue, transaction, waitForState } from 'vs/workbench/contrib/audioCues/browser/observable';
|
17 | 13 | import { IDiffComputer } from 'vs/workbench/contrib/mergeEditor/browser/model/diffComputer';
|
18 |
| -import { LineRangeEdit, RangeEdit } from 'vs/workbench/contrib/mergeEditor/browser/model/editing'; |
19 | 14 | import { LineRange } from 'vs/workbench/contrib/mergeEditor/browser/model/lineRange';
|
20 | 15 | import { DetailedLineRangeMapping, DocumentMapping, LineRangeMapping } from 'vs/workbench/contrib/mergeEditor/browser/model/mapping';
|
21 | 16 | import { TextModelDiffChangeReason, TextModelDiffs, TextModelDiffState } from 'vs/workbench/contrib/mergeEditor/browser/model/textModelDiffs';
|
22 |
| -import { concatArrays, elementAtOrUndefined, leftJoin } from 'vs/workbench/contrib/mergeEditor/browser/utils'; |
| 17 | +import { leftJoin } from 'vs/workbench/contrib/mergeEditor/browser/utils'; |
23 | 18 | import { ModifiedBaseRange, ModifiedBaseRangeState } from './modifiedBaseRange';
|
24 | 19 |
|
25 | 20 | export const enum MergeEditorModelState {
|
@@ -269,7 +264,7 @@ export class MergeEditorModel extends EditorModel {
|
269 | 264 | this.resultTextModelDiffs.removeDiffs(conflictingDiffs, transaction);
|
270 | 265 | }
|
271 | 266 |
|
272 |
| - const { edit, effectiveState } = getEditForBase(baseRange, state); |
| 267 | + const { edit, effectiveState } = baseRange.getEditForBase(state); |
273 | 268 |
|
274 | 269 | existingState.set(effectiveState, transaction);
|
275 | 270 |
|
@@ -312,7 +307,7 @@ export class MergeEditorModel extends EditorModel {
|
312 | 307 | ];
|
313 | 308 |
|
314 | 309 | for (const s of states) {
|
315 |
| - const { edit } = getEditForBase(baseRange, s); |
| 310 | + const { edit } = baseRange.getEditForBase(s); |
316 | 311 | if (edit) {
|
317 | 312 | const resultRange = this.resultTextModelDiffs.getResultRange(baseRange.baseRange);
|
318 | 313 | const existingLines = resultRange.getLines(this.result);
|
@@ -342,108 +337,3 @@ export class MergeEditorModel extends EditorModel {
|
342 | 337 | this.modelService.setMode(this.result, language);
|
343 | 338 | }
|
344 | 339 | }
|
345 |
| - |
346 |
| -function getEditForBase(baseRange: ModifiedBaseRange, state: ModifiedBaseRangeState): { edit: LineRangeEdit | undefined; effectiveState: ModifiedBaseRangeState } { |
347 |
| - const diffs = concatArrays( |
348 |
| - state.input1 && baseRange.input1CombinedDiff ? [{ diff: baseRange.input1CombinedDiff, inputNumber: 1 as const }] : [], |
349 |
| - state.input2 && baseRange.input2CombinedDiff ? [{ diff: baseRange.input2CombinedDiff, inputNumber: 2 as const }] : [], |
350 |
| - ); |
351 |
| - |
352 |
| - if (state.input2First) { |
353 |
| - diffs.reverse(); |
354 |
| - } |
355 |
| - |
356 |
| - const firstDiff = elementAtOrUndefined(diffs, 0); |
357 |
| - const secondDiff = elementAtOrUndefined(diffs, 1); |
358 |
| - |
359 |
| - if (!firstDiff) { |
360 |
| - return { edit: undefined, effectiveState: ModifiedBaseRangeState.default }; |
361 |
| - } |
362 |
| - if (!secondDiff) { |
363 |
| - return { edit: firstDiff.diff.getLineEdit(), effectiveState: ModifiedBaseRangeState.default.withInputValue(firstDiff.inputNumber, true) }; |
364 |
| - } |
365 |
| - |
366 |
| - const result = combineInputs(baseRange, state.input2First ? 2 : 1); |
367 |
| - if (result) { |
368 |
| - return { edit: result, effectiveState: state }; |
369 |
| - } |
370 |
| - |
371 |
| - return { |
372 |
| - edit: secondDiff.diff.getLineEdit(), |
373 |
| - effectiveState: ModifiedBaseRangeState.default.withInputValue( |
374 |
| - secondDiff.inputNumber, |
375 |
| - true |
376 |
| - ), |
377 |
| - }; |
378 |
| -} |
379 |
| - |
380 |
| -function combineInputs(baseRange: ModifiedBaseRange, firstInput: 1 | 2): LineRangeEdit | undefined { |
381 |
| - const combinedDiffs = concatArrays( |
382 |
| - baseRange.input1Diffs.flatMap((diffs) => |
383 |
| - diffs.rangeMappings.map((diff) => ({ diff, input: 1 as const })) |
384 |
| - ), |
385 |
| - baseRange.input2Diffs.flatMap((diffs) => |
386 |
| - diffs.rangeMappings.map((diff) => ({ diff, input: 2 as const })) |
387 |
| - ) |
388 |
| - ).sort( |
389 |
| - tieBreakComparators( |
390 |
| - compareBy((d) => d.diff.inputRange, Range.compareRangesUsingStarts), |
391 |
| - compareBy((d) => (d.input === firstInput ? 1 : 2), numberComparator) |
392 |
| - ) |
393 |
| - ); |
394 |
| - |
395 |
| - const sortedEdits = combinedDiffs.map(d => { |
396 |
| - const sourceTextModel = d.input === 1 ? baseRange.input1TextModel : baseRange.input2TextModel; |
397 |
| - return new RangeEdit(d.diff.inputRange, sourceTextModel.getValueInRange(d.diff.outputRange)); |
398 |
| - }); |
399 |
| - |
400 |
| - return editsToLineRangeEdit(baseRange.baseRange, sortedEdits, baseRange.baseTextModel); |
401 |
| -} |
402 |
| - |
403 |
| -function editsToLineRangeEdit(range: LineRange, sortedEdits: RangeEdit[], textModel: ITextModel): LineRangeEdit | undefined { |
404 |
| - let text = ''; |
405 |
| - const startsLineBefore = range.startLineNumber > 1; |
406 |
| - let currentPosition = startsLineBefore |
407 |
| - ? new Position( |
408 |
| - range.startLineNumber - 1, |
409 |
| - Constants.MAX_SAFE_SMALL_INTEGER |
410 |
| - ) |
411 |
| - : new Position(range.startLineNumber, 1); |
412 |
| - |
413 |
| - for (const edit of sortedEdits) { |
414 |
| - const diffStart = edit.range.getStartPosition(); |
415 |
| - if (!currentPosition.isBeforeOrEqual(diffStart)) { |
416 |
| - return undefined; |
417 |
| - } |
418 |
| - let originalText = textModel.getValueInRange(Range.fromPositions(currentPosition, diffStart)); |
419 |
| - if (diffStart.lineNumber > textModel.getLineCount()) { |
420 |
| - // assert diffStart.lineNumber === textModel.getLineCount() + 1 |
421 |
| - // getValueInRange doesn't include this virtual line break, as the document ends the line before. |
422 |
| - // endsLineAfter will be false. |
423 |
| - originalText += '\n'; |
424 |
| - } |
425 |
| - text += originalText; |
426 |
| - text += edit.newText; |
427 |
| - currentPosition = edit.range.getEndPosition(); |
428 |
| - } |
429 |
| - |
430 |
| - const endsLineAfter = range.endLineNumberExclusive <= textModel.getLineCount(); |
431 |
| - const end = endsLineAfter ? new Position( |
432 |
| - range.endLineNumberExclusive, |
433 |
| - 1 |
434 |
| - ) : new Position(range.endLineNumberExclusive - 1, Constants.MAX_SAFE_SMALL_INTEGER); |
435 |
| - |
436 |
| - const originalText = textModel.getValueInRange( |
437 |
| - Range.fromPositions(currentPosition, end) |
438 |
| - ); |
439 |
| - text += originalText; |
440 |
| - |
441 |
| - const lines = splitLines(text); |
442 |
| - if (startsLineBefore) { |
443 |
| - lines.shift(); |
444 |
| - } |
445 |
| - if (endsLineAfter) { |
446 |
| - lines.pop(); |
447 |
| - } |
448 |
| - return new LineRangeEdit(range, lines); |
449 |
| -} |
0 commit comments