@@ -9,7 +9,7 @@ import { IconLabel } from 'vs/base/browser/ui/iconLabel/iconLabel';
9
9
import { Orientation , Sizing } from 'vs/base/browser/ui/splitview/splitview' ;
10
10
import { Toggle } from 'vs/base/browser/ui/toggle/toggle' ;
11
11
import { IAction } from 'vs/base/common/actions' ;
12
- import { CompareResult , findLast } from 'vs/base/common/arrays' ;
12
+ import { CompareResult } from 'vs/base/common/arrays' ;
13
13
import { CancellationToken } from 'vs/base/common/cancellation' ;
14
14
import { Codicon } from 'vs/base/common/codicons' ;
15
15
import { Color } from 'vs/base/common/color' ;
@@ -47,7 +47,7 @@ import { applyTextEditorOptions } from 'vs/workbench/common/editor/editorOptions
47
47
import { autorun , autorunWithStore , derivedObservable , IObservable , ITransaction , keepAlive , ObservableValue , transaction } from 'vs/workbench/contrib/audioCues/browser/observable' ;
48
48
import { MergeEditorInput } from 'vs/workbench/contrib/mergeEditor/browser/mergeEditorInput' ;
49
49
import { MergeEditorModel } from 'vs/workbench/contrib/mergeEditor/browser/mergeEditorModel' ;
50
- import { LineRange , ModifiedBaseRange } from 'vs/workbench/contrib/mergeEditor/browser/model' ;
50
+ import { DocumentMapping , LineRange , SimpleLineRangeMapping , ToggleState } from 'vs/workbench/contrib/mergeEditor/browser/model' ;
51
51
import { applyObservableDecorations , join , n , ReentrancyBarrier , setStyle } from 'vs/workbench/contrib/mergeEditor/browser/utils' ;
52
52
import { settingsSashBorder } from 'vs/workbench/contrib/preferences/common/settingsEditorColorRegistry' ;
53
53
import { IEditorGroup , IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService' ;
@@ -109,17 +109,39 @@ export class MergeEditor extends AbstractTextEditor<any> {
109
109
return undefined ;
110
110
}
111
111
const resultDiffs = model . resultDiffs . read ( reader ) ;
112
- const modifiedBaseRanges = ModifiedBaseRange . fromDiffs ( model . base , model . input1 , model . input1LinesDiffs . read ( reader ) , model . result , resultDiffs ) ;
113
- return modifiedBaseRanges ;
112
+ const modifiedBaseRanges = DocumentMapping . fromDiffs ( model . input1LinesDiffs . read ( reader ) , resultDiffs , model . input1 . getLineCount ( ) ) ;
113
+
114
+ return new DocumentMapping (
115
+ modifiedBaseRanges . lineRangeMappings . map ( ( m ) =>
116
+ m . inputRange . isEmpty || m . outputRange . isEmpty
117
+ ? new SimpleLineRangeMapping (
118
+ m . inputRange . deltaStart ( - 1 ) ,
119
+ m . outputRange . deltaStart ( - 1 )
120
+ )
121
+ : m
122
+ ) ,
123
+ modifiedBaseRanges . inputLineCount
124
+ ) ;
114
125
} ) ;
115
126
const input2ResultMapping = derivedObservable ( 'input2ResultMapping' , reader => {
116
127
const model = this . input2View . model . read ( reader ) ;
117
128
if ( ! model ) {
118
129
return undefined ;
119
130
}
120
131
const resultDiffs = model . resultDiffs . read ( reader ) ;
121
- const modifiedBaseRanges = ModifiedBaseRange . fromDiffs ( model . base , model . input2 , model . input2LinesDiffs . read ( reader ) , model . result , resultDiffs ) ;
122
- return modifiedBaseRanges ;
132
+ const modifiedBaseRanges = DocumentMapping . fromDiffs ( model . input2LinesDiffs . read ( reader ) , resultDiffs , model . input2 . getLineCount ( ) ) ;
133
+
134
+ return new DocumentMapping (
135
+ modifiedBaseRanges . lineRangeMappings . map ( ( m ) =>
136
+ m . inputRange . isEmpty || m . outputRange . isEmpty
137
+ ? new SimpleLineRangeMapping (
138
+ m . inputRange . deltaStart ( - 1 ) ,
139
+ m . outputRange . deltaStart ( - 1 )
140
+ )
141
+ : m
142
+ ) ,
143
+ modifiedBaseRanges . inputLineCount
144
+ ) ;
123
145
} ) ;
124
146
125
147
this . _register ( keepAlive ( input1ResultMapping ) ) ;
@@ -390,7 +412,7 @@ export class MergeEditor extends AbstractTextEditor<any> {
390
412
}
391
413
}
392
414
393
- function synchronizeScrolling ( scrollingEditor : CodeEditorWidget , targetEditor : CodeEditorWidget , mapping : ModifiedBaseRange [ ] | undefined , sourceNumber : 1 | 2 ) {
415
+ function synchronizeScrolling ( scrollingEditor : CodeEditorWidget , targetEditor : CodeEditorWidget , mapping : DocumentMapping | undefined , sourceNumber : 1 | 2 ) {
394
416
if ( ! mapping ) {
395
417
return ;
396
418
}
@@ -401,25 +423,27 @@ function synchronizeScrolling(scrollingEditor: CodeEditorWidget, targetEditor: C
401
423
}
402
424
const topLineNumber = visibleRanges [ 0 ] . startLineNumber - 1 ;
403
425
404
- const firstBefore = findLast ( mapping , r => r . getInputRange ( sourceNumber ) . startLineNumber <= topLineNumber ) ;
405
426
let sourceRange : LineRange ;
406
427
let targetRange : LineRange ;
407
428
408
- const targetNumber = sourceNumber === 1 ? 2 : 1 ;
409
-
410
- const firstBeforeSourceRange = firstBefore ?. getInputRange ( sourceNumber ) ;
411
- const firstBeforeTargetRange = firstBefore ?. getInputRange ( targetNumber ) ;
412
-
413
- if ( firstBeforeSourceRange && firstBeforeSourceRange . contains ( topLineNumber ) ) {
414
- sourceRange = firstBeforeSourceRange ;
415
- targetRange = firstBeforeTargetRange ! ;
416
- } else if ( firstBeforeSourceRange && firstBeforeSourceRange . isEmpty && firstBeforeSourceRange . startLineNumber === topLineNumber ) {
417
- sourceRange = firstBeforeSourceRange . deltaEnd ( 1 ) ;
418
- targetRange = firstBeforeTargetRange ! . deltaEnd ( 1 ) ;
429
+ if ( sourceNumber === 1 ) {
430
+ const number = mapping . getOutputLine ( topLineNumber ) ;
431
+ if ( typeof number === 'number' ) {
432
+ sourceRange = new LineRange ( topLineNumber , 1 ) ;
433
+ targetRange = new LineRange ( number , 1 ) ;
434
+ } else {
435
+ sourceRange = number . inputRange ;
436
+ targetRange = number . outputRange ;
437
+ }
419
438
} else {
420
- const delta = firstBeforeSourceRange ? firstBeforeTargetRange ! . endLineNumberExclusive - firstBeforeSourceRange . endLineNumberExclusive : 0 ;
421
- sourceRange = new LineRange ( topLineNumber , 1 ) ;
422
- targetRange = new LineRange ( topLineNumber + delta , 1 ) ;
439
+ const number = mapping . getInputLine ( topLineNumber ) ;
440
+ if ( typeof number === 'number' ) {
441
+ sourceRange = new LineRange ( topLineNumber , 1 ) ;
442
+ targetRange = new LineRange ( number , 1 ) ;
443
+ } else {
444
+ sourceRange = number . outputRange ;
445
+ targetRange = number . inputRange ;
446
+ }
423
447
}
424
448
425
449
// sourceRange contains topLineNumber!
@@ -532,6 +556,21 @@ class InputCodeEditorView extends CodeEditorView {
532
556
description : 'Base Range Projection'
533
557
}
534
558
} ) ;
559
+
560
+ const inputDiffs = m . getInputDiffs ( this . inputNumber ) ;
561
+ for ( const diff of inputDiffs ) {
562
+ if ( diff . innerRangeMappings ) {
563
+ for ( const d of diff . innerRangeMappings ) {
564
+ result . push ( {
565
+ range : d . outputRange ,
566
+ options : {
567
+ className : `merge-editor-diff-input${ this . inputNumber } ` ,
568
+ description : 'Base Range Projection'
569
+ }
570
+ } ) ;
571
+ }
572
+ }
573
+ }
535
574
}
536
575
}
537
576
return result ;
@@ -585,7 +624,7 @@ class InputCodeEditorView extends CodeEditorView {
585
624
586
625
interface ModifiedBaseRangeGutterItemInfo extends IGutterItemInfo {
587
626
enabled : IObservable < boolean > ;
588
- toggleState : IObservable < boolean | undefined > ;
627
+ toggleState : IObservable < ToggleState > ;
589
628
setState ( value : boolean , tx : ITransaction ) : void ;
590
629
}
591
630
@@ -606,14 +645,14 @@ class MergeConflictGutterItemView extends Disposable implements IGutterItemView<
606
645
autorun ( ( reader ) => {
607
646
const item = this . item . read ( reader ) ! ;
608
647
const value = item . toggleState . read ( reader ) ;
609
- checkBox . setIcon (
610
- value === true
611
- ? Codicon . check
612
- : value === false
613
- ? undefined
614
- : Codicon . circleFilled
615
- ) ;
616
- checkBox . checked = value === true ;
648
+ const iconMap : Record < ToggleState , { icon : Codicon | undefined ; checked : boolean } > = {
649
+ [ ToggleState . unset ] : { icon : undefined , checked : false } ,
650
+ [ ToggleState . conflicting ] : { icon : Codicon . circleFilled , checked : false } ,
651
+ [ ToggleState . first ] : { icon : Codicon . check , checked : true } ,
652
+ [ ToggleState . second ] : { icon : Codicon . checkAll , checked : true } ,
653
+ } ;
654
+ checkBox . setIcon ( iconMap [ value ] . icon ) ;
655
+ checkBox . checked = iconMap [ value ] . checked ;
617
656
618
657
if ( ! item . enabled . read ( reader ) ) {
619
658
checkBox . disable ( ) ;
@@ -658,17 +697,17 @@ class ResultCodeEditorView extends CodeEditorView {
658
697
model . modifiedBaseRanges . read ( reader ) ,
659
698
model . resultDiffs . read ( reader ) ,
660
699
( baseRange , diff ) =>
661
- baseRange . baseRange . touches ( diff . originalRange )
700
+ baseRange . baseRange . touches ( diff . inputRange )
662
701
? CompareResult . neitherLessOrGreaterThan
663
702
: LineRange . compareByStart (
664
703
baseRange . baseRange ,
665
- diff . originalRange
704
+ diff . inputRange
666
705
)
667
706
) ;
668
707
669
708
for ( const m of baseRangeWithStoreAndTouchingDiffs ) {
670
709
for ( const r of m . rights ) {
671
- const range = r . modifiedRange ;
710
+ const range = r . outputRange ;
672
711
673
712
const state = m . left ? model . getState ( m . left ) . read ( reader ) : undefined ;
674
713
@@ -687,8 +726,11 @@ class ResultCodeEditorView extends CodeEditorView {
687
726
if ( state . input2 && ! state . input1 ) {
688
727
return 'merge-editor-modified-base-range-input2' ;
689
728
}
729
+ if ( state . input1 && state . input2 ) {
730
+ return 'merge-editor-modified-base-range-combination' ;
731
+ }
690
732
}
691
- return 'merge-editor-modified-base-range-combination ' ;
733
+ return 'merge-editor-modified-base-range' ;
692
734
} ) ( ) ,
693
735
description : 'Result Diff'
694
736
}
0 commit comments