@@ -294,8 +294,19 @@ async function getPullRequestEditedDiffRanges(
294
294
headLabel : string ,
295
295
logger : Logger ,
296
296
) : Promise < DiffThunkRange [ ] | undefined > {
297
- await getFileDiffsWithBasehead ( baseRef , headLabel , logger ) ;
298
- return undefined ;
297
+ const fileDiffs = await getFileDiffsWithBasehead ( baseRef , headLabel , logger ) ;
298
+ if ( fileDiffs === undefined ) {
299
+ return undefined ;
300
+ }
301
+ const results : DiffThunkRange [ ] = [ ] ;
302
+ for ( const filediff of fileDiffs ) {
303
+ const diffRanges = getDiffRanges ( filediff , logger ) ;
304
+ if ( diffRanges === undefined ) {
305
+ return undefined ;
306
+ }
307
+ results . push ( ...diffRanges ) ;
308
+ }
309
+ return results ;
299
310
}
300
311
301
312
/**
@@ -348,6 +359,76 @@ async function getFileDiffsWithBasehead(
348
359
}
349
360
}
350
361
362
+ function getDiffRanges (
363
+ fileDiff : FileDiff ,
364
+ logger : Logger ,
365
+ ) : DiffThunkRange [ ] | undefined {
366
+ if ( fileDiff . patch === undefined ) {
367
+ return undefined ;
368
+ }
369
+
370
+ // Diff-informed queries expect the file path to be absolute. CodeQL always
371
+ // uses forward slashes as the path separator, so on Windows we need to
372
+ // replace any backslashes with forward slashes.
373
+ const filename = path
374
+ . join ( actionsUtil . getRequiredInput ( "checkout_path" ) , fileDiff . filename )
375
+ . replaceAll ( path . sep , "/" ) ;
376
+
377
+ // The 1-based file line number of the current line
378
+ let currentLine = 0 ;
379
+ // The 1-based file line number that starts the current range of added lines
380
+ let additionRangeStartLine : number | undefined = undefined ;
381
+ const diffRanges : DiffThunkRange [ ] = [ ] ;
382
+
383
+ const diffLines = fileDiff . patch . split ( "\n" ) ;
384
+ // Adding a fake context line at the end ensures that the following loop will
385
+ // always terminate the last range of added lines.
386
+ diffLines . push ( " " ) ;
387
+
388
+ for ( const diffLine of diffLines ) {
389
+ if ( diffLine . startsWith ( "-" ) ) {
390
+ // Ignore deletions completely -- we do not even want to consider them when
391
+ // calculating consecutive ranges of added lines.
392
+ continue ;
393
+ }
394
+ if ( diffLine . startsWith ( "+" ) ) {
395
+ if ( additionRangeStartLine === undefined ) {
396
+ additionRangeStartLine = currentLine ;
397
+ }
398
+ currentLine ++ ;
399
+ continue ;
400
+ }
401
+ if ( additionRangeStartLine !== undefined ) {
402
+ // Any line that does not start with a "+" or "-" terminates the current
403
+ // range of added lines.
404
+ diffRanges . push ( {
405
+ path : filename ,
406
+ startLine : additionRangeStartLine ,
407
+ endLine : currentLine - 1 ,
408
+ } ) ;
409
+ additionRangeStartLine = undefined ;
410
+ }
411
+ if ( diffLine . startsWith ( "@@ " ) ) {
412
+ // A new hunk header line resets the current line number.
413
+ const match = diffLine . match ( / ^ @ @ - \d + (?: , \d + ) ? \+ ( \d + ) (?: , \d + ) ? @ @ / ) ;
414
+ if ( match === null ) {
415
+ logger . warning (
416
+ `Cannot parse diff hunk header for ${ fileDiff . filename } : ${ diffLine } ` ,
417
+ ) ;
418
+ return undefined ;
419
+ }
420
+ currentLine = parseInt ( match [ 1 ] , 10 ) ;
421
+ continue ;
422
+ }
423
+ if ( diffLine . startsWith ( " " ) ) {
424
+ // An unchanged context line advances the current line number.
425
+ currentLine ++ ;
426
+ continue ;
427
+ }
428
+ }
429
+ return diffRanges ;
430
+ }
431
+
351
432
/**
352
433
* Create an extension pack in the temporary directory that contains the file
353
434
* line ranges that were added or modified in the pull request.
0 commit comments