@@ -179,26 +179,83 @@ export function parsePatch(patch: string): DiffHunk[] {
179179 let diffHunkIter = diffHunkReader . next ( ) ;
180180 const diffHunks : DiffHunk [ ] = [ ] ;
181181
182- const right : string [ ] = [ ] ;
183182 while ( ! diffHunkIter . done ) {
184183 const diffHunk = diffHunkIter . value ;
185184 diffHunks . push ( diffHunk ) ;
185+ diffHunkIter = diffHunkReader . next ( ) ;
186+ }
186187
187- for ( let j = 0 ; j < diffHunk . diffLines . length ; j ++ ) {
188- const diffLine = diffHunk . diffLines [ j ] ;
189- if ( diffLine . type === DiffChangeType . Delete || diffLine . type === DiffChangeType . Control ) {
190- } else if ( diffLine . type === DiffChangeType . Add ) {
191- right . push ( diffLine . text ) ;
192- } else {
193- const codeInFirstLine = diffLine . text ;
194- right . push ( codeInFirstLine ) ;
188+ return diffHunks ;
189+ }
190+
191+ /**
192+ * Split a hunk into smaller hunks based on the context lines. Position in hunk and control lines are not preserved.
193+ */
194+ export function splitIntoSmallerHunks ( hunk : DiffHunk ) : DiffHunk [ ] {
195+ const splitHunks : DiffHunk [ ] = [ ] ;
196+ const newHunk = ( fromLine : DiffLine ) => {
197+ return {
198+ diffLines : [ ] ,
199+ newLength : 0 ,
200+ oldLength : 0 ,
201+ oldLineNumber : fromLine . oldLineNumber ,
202+ newLineNumber : fromLine . newLineNumber ,
203+ positionInHunk : 0
204+ } ;
205+ } ;
206+
207+ // Split hunk into smaller hunks on context lines.
208+ // Context lines will be duplicated across the new smaller hunks
209+ let currentHunk : DiffHunk | undefined ;
210+ let nextHunk : DiffHunk | undefined ;
211+
212+ const addLineToHunk = ( hunk : DiffHunk , line : DiffLine ) => {
213+ hunk . diffLines . push ( line ) ;
214+ if ( line . type === DiffChangeType . Delete ) {
215+ hunk . oldLength ++ ;
216+ } else if ( line . type === DiffChangeType . Add ) {
217+ hunk . newLength ++ ;
218+ } else if ( line . type === DiffChangeType . Context ) {
219+ hunk . oldLength ++ ;
220+ hunk . newLength ++ ;
221+ }
222+ } ;
223+ const hunkHasChanges = ( hunk : DiffHunk ) => {
224+ return hunk . diffLines . some ( line => line . type !== DiffChangeType . Context ) ;
225+ } ;
226+ const hunkHasSandwichedChanges = ( hunk : DiffHunk ) => {
227+ return hunkHasChanges ( hunk ) && hunk . diffLines [ hunk . diffLines . length - 1 ] . type === DiffChangeType . Context ;
228+ } ;
229+
230+ for ( const line of hunk . diffLines ) {
231+ if ( line . type === DiffChangeType . Context ) {
232+ if ( ! currentHunk ) {
233+ currentHunk = newHunk ( line ) ;
234+ }
235+ addLineToHunk ( currentHunk , line ) ;
236+ if ( hunkHasSandwichedChanges ( currentHunk ) ) {
237+ if ( ! nextHunk ) {
238+ nextHunk = newHunk ( line ) ;
239+ }
240+ addLineToHunk ( nextHunk , line ) ;
241+ }
242+ } else if ( currentHunk ) {
243+ if ( hunkHasSandwichedChanges ( currentHunk ) ) {
244+ splitHunks . push ( currentHunk ) ;
245+ currentHunk = nextHunk ! ;
246+ nextHunk = undefined ;
247+ }
248+ if ( ( line . type === DiffChangeType . Delete ) || ( line . type === DiffChangeType . Add ) ) {
249+ addLineToHunk ( currentHunk , line ) ;
195250 }
196251 }
252+ }
197253
198- diffHunkIter = diffHunkReader . next ( ) ;
254+ if ( currentHunk ) {
255+ splitHunks . push ( currentHunk ) ;
199256 }
200257
201- return diffHunks ;
258+ return splitHunks ;
202259}
203260
204261export function getModifiedContentFromDiffHunk ( originalContent : string , patch : string ) {
0 commit comments