|
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