@@ -50,34 +50,78 @@ export function joinSequenceDiffs(sequence1: ISequence, sequence2: ISequence, se
5050 result . push ( sequenceDiffs [ 0 ] ) ;
5151 }
5252
53+ // First move them all to the left as much as possible and join them if possible
5354 for ( let i = 1 ; i < sequenceDiffs . length ; i ++ ) {
54- const lastResult = result [ result . length - 1 ] ;
55- const cur = sequenceDiffs [ i ] ;
56-
57- if ( cur . seq1Range . isEmpty ) {
58- let all = true ;
59- const length = cur . seq1Range . start - lastResult . seq1Range . endExclusive ;
60- for ( let i = 1 ; i <= length ; i ++ ) {
61- if ( sequence2 . getElement ( cur . seq2Range . start - i ) !== sequence2 . getElement ( cur . seq2Range . endExclusive - i ) ) {
62- all = false ;
55+ const prevResult = sequenceDiffs [ i - 1 ] ;
56+ let cur = sequenceDiffs [ i ] ;
57+
58+ if ( cur . seq1Range . isEmpty || cur . seq2Range . isEmpty ) {
59+ const length = cur . seq1Range . start - prevResult . seq1Range . endExclusive ;
60+ let d ;
61+ for ( d = 1 ; d <= length ; d ++ ) {
62+ if (
63+ sequence1 . getElement ( cur . seq1Range . start - d ) !== sequence1 . getElement ( cur . seq1Range . endExclusive - d ) ||
64+ sequence2 . getElement ( cur . seq2Range . start - d ) !== sequence2 . getElement ( cur . seq2Range . endExclusive - d ) ) {
6365 break ;
6466 }
6567 }
68+ d -- ;
6669
67- if ( all ) {
70+ if ( d === length ) {
6871 // Merge previous and current diff
69- result [ result . length - 1 ] = new SequenceDiff ( lastResult . seq1Range , new OffsetRange (
70- lastResult . seq2Range . start ,
71- cur . seq2Range . endExclusive - length
72- ) ) ;
72+ result [ result . length - 1 ] = new SequenceDiff (
73+ new OffsetRange ( prevResult . seq1Range . start , cur . seq1Range . endExclusive - length ) ,
74+ new OffsetRange ( prevResult . seq2Range . start , cur . seq2Range . endExclusive - length ) ,
75+ ) ;
7376 continue ;
7477 }
78+
79+ cur = cur . delta ( - d ) ;
7580 }
7681
7782 result . push ( cur ) ;
7883 }
7984
80- return result ;
85+ const result2 : SequenceDiff [ ] = [ ] ;
86+ // Then move them all to the right and join them again if possible
87+ for ( let i = 0 ; i < result . length - 1 ; i ++ ) {
88+ const nextResult = result [ i + 1 ] ;
89+ let cur = result [ i ] ;
90+
91+ if ( cur . seq1Range . isEmpty || cur . seq2Range . isEmpty ) {
92+ const length = nextResult . seq1Range . start - cur . seq1Range . endExclusive ;
93+ let d ;
94+ for ( d = 0 ; d < length ; d ++ ) {
95+ if (
96+ sequence1 . getElement ( cur . seq1Range . start + d ) !== sequence1 . getElement ( cur . seq1Range . endExclusive + d ) ||
97+ sequence2 . getElement ( cur . seq2Range . start + d ) !== sequence2 . getElement ( cur . seq2Range . endExclusive + d )
98+ ) {
99+ break ;
100+ }
101+ }
102+
103+ if ( d === length ) {
104+ // Merge previous and current diff, write to result!
105+ result [ i + 1 ] = new SequenceDiff (
106+ new OffsetRange ( cur . seq1Range . start + length , nextResult . seq1Range . endExclusive ) ,
107+ new OffsetRange ( cur . seq2Range . start + length , nextResult . seq2Range . endExclusive ) ,
108+ ) ;
109+ continue ;
110+ }
111+
112+ if ( d > 0 ) {
113+ cur = cur . delta ( d ) ;
114+ }
115+ }
116+
117+ result2 . push ( cur ) ;
118+ }
119+
120+ if ( result . length > 0 ) {
121+ result2 . push ( result [ result . length - 1 ] ) ;
122+ }
123+
124+ return result2 ;
81125}
82126
83127// align character level diffs at whitespace characters
@@ -102,37 +146,45 @@ export function shiftSequenceDiffs(sequence1: ISequence, sequence2: ISequence, s
102146 }
103147
104148 for ( let i = 0 ; i < sequenceDiffs . length ; i ++ ) {
149+ const prevDiff = ( i > 0 ? sequenceDiffs [ i - 1 ] : undefined ) ;
105150 const diff = sequenceDiffs [ i ] ;
151+ const nextDiff = ( i + 1 < sequenceDiffs . length ? sequenceDiffs [ i + 1 ] : undefined ) ;
152+
153+ const seq1ValidRange = new OffsetRange ( prevDiff ? prevDiff . seq1Range . start + 1 : 0 , nextDiff ? nextDiff . seq1Range . endExclusive - 1 : sequence1 . length ) ;
154+ const seq2ValidRange = new OffsetRange ( prevDiff ? prevDiff . seq2Range . start + 1 : 0 , nextDiff ? nextDiff . seq2Range . endExclusive - 1 : sequence2 . length ) ;
155+
106156 if ( diff . seq1Range . isEmpty ) {
107- const seq2PrevEndExclusive = ( i > 0 ? sequenceDiffs [ i - 1 ] . seq2Range . endExclusive : - 1 ) ;
108- const seq2NextStart = ( i + 1 < sequenceDiffs . length ? sequenceDiffs [ i + 1 ] . seq2Range . start : sequence2 . length ) ;
109- sequenceDiffs [ i ] = shiftDiffToBetterPosition ( diff , sequence1 , sequence2 , seq2NextStart , seq2PrevEndExclusive ) ;
157+ sequenceDiffs [ i ] = shiftDiffToBetterPosition ( diff , sequence1 , sequence2 , seq1ValidRange , seq2ValidRange ) ;
110158 } else if ( diff . seq2Range . isEmpty ) {
111- const seq1PrevEndExclusive = ( i > 0 ? sequenceDiffs [ i - 1 ] . seq1Range . endExclusive : - 1 ) ;
112- const seq1NextStart = ( i + 1 < sequenceDiffs . length ? sequenceDiffs [ i + 1 ] . seq1Range . start : sequence1 . length ) ;
113- sequenceDiffs [ i ] = shiftDiffToBetterPosition ( diff . reverse ( ) , sequence2 , sequence1 , seq1NextStart , seq1PrevEndExclusive ) . reverse ( ) ;
159+ sequenceDiffs [ i ] = shiftDiffToBetterPosition ( diff . reverse ( ) , sequence2 , sequence1 , seq2ValidRange , seq1ValidRange ) . reverse ( ) ;
114160 }
115161 }
116162
117163 return sequenceDiffs ;
118164}
119165
120- function shiftDiffToBetterPosition ( diff : SequenceDiff , sequence1 : ISequence , sequence2 : ISequence , seq2NextStart : number , seq2PrevEndExclusive : number ) {
121- const maxShiftLimit = 20 ; // To prevent performance issues
166+ function shiftDiffToBetterPosition ( diff : SequenceDiff , sequence1 : ISequence , sequence2 : ISequence , seq1ValidRange : OffsetRange , seq2ValidRange : OffsetRange , ) {
167+ const maxShiftLimit = 100 ; // To prevent performance issues
122168
123169 // don't touch previous or next!
124170 let deltaBefore = 1 ;
125- while ( diff . seq2Range . start - deltaBefore > seq2PrevEndExclusive &&
171+ while (
172+ diff . seq1Range . start - deltaBefore >= seq1ValidRange . start &&
173+ diff . seq2Range . start - deltaBefore >= seq2ValidRange . start &&
126174 sequence2 . getElement ( diff . seq2Range . start - deltaBefore ) ===
127- sequence2 . getElement ( diff . seq2Range . endExclusive - deltaBefore ) && deltaBefore < maxShiftLimit ) {
175+ sequence2 . getElement ( diff . seq2Range . endExclusive - deltaBefore ) && deltaBefore < maxShiftLimit
176+ ) {
128177 deltaBefore ++ ;
129178 }
130179 deltaBefore -- ;
131180
132181 let deltaAfter = 0 ;
133- while ( diff . seq2Range . start + deltaAfter < seq2NextStart &&
182+ while (
183+ diff . seq1Range . start + deltaAfter < seq1ValidRange . endExclusive &&
184+ diff . seq2Range . endExclusive + deltaAfter < seq2ValidRange . endExclusive &&
134185 sequence2 . getElement ( diff . seq2Range . start + deltaAfter ) ===
135- sequence2 . getElement ( diff . seq2Range . endExclusive + deltaAfter ) && deltaAfter < maxShiftLimit ) {
186+ sequence2 . getElement ( diff . seq2Range . endExclusive + deltaAfter ) && deltaAfter < maxShiftLimit
187+ ) {
136188 deltaAfter ++ ;
137189 }
138190
@@ -158,8 +210,5 @@ function shiftDiffToBetterPosition(diff: SequenceDiff, sequence1: ISequence, seq
158210 }
159211 }
160212
161- if ( bestDelta !== 0 ) {
162- return new SequenceDiff ( diff . seq1Range . delta ( bestDelta ) , diff . seq2Range . delta ( bestDelta ) ) ;
163- }
164- return diff ;
213+ return diff . delta ( bestDelta ) ;
165214}
0 commit comments