@@ -50,34 +50,78 @@ export function joinSequenceDiffs(sequence1: ISequence, sequence2: ISequence, se
50
50
result . push ( sequenceDiffs [ 0 ] ) ;
51
51
}
52
52
53
+ // First move them all to the left as much as possible and join them if possible
53
54
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 ) ) {
63
65
break ;
64
66
}
65
67
}
68
+ d -- ;
66
69
67
- if ( all ) {
70
+ if ( d === length ) {
68
71
// 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
+ ) ;
73
76
continue ;
74
77
}
78
+
79
+ cur = cur . delta ( - d ) ;
75
80
}
76
81
77
82
result . push ( cur ) ;
78
83
}
79
84
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 ;
81
125
}
82
126
83
127
// align character level diffs at whitespace characters
@@ -102,37 +146,45 @@ export function shiftSequenceDiffs(sequence1: ISequence, sequence2: ISequence, s
102
146
}
103
147
104
148
for ( let i = 0 ; i < sequenceDiffs . length ; i ++ ) {
149
+ const prevDiff = ( i > 0 ? sequenceDiffs [ i - 1 ] : undefined ) ;
105
150
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
+
106
156
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 ) ;
110
158
} 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 ( ) ;
114
160
}
115
161
}
116
162
117
163
return sequenceDiffs ;
118
164
}
119
165
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
122
168
123
169
// don't touch previous or next!
124
170
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 &&
126
174
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
+ ) {
128
177
deltaBefore ++ ;
129
178
}
130
179
deltaBefore -- ;
131
180
132
181
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 &&
134
185
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
+ ) {
136
188
deltaAfter ++ ;
137
189
}
138
190
@@ -158,8 +210,5 @@ function shiftDiffToBetterPosition(diff: SequenceDiff, sequence1: ISequence, seq
158
210
}
159
211
}
160
212
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 ) ;
165
214
}
0 commit comments