Skip to content

Commit 68b1b4e

Browse files
committed
getPullRequestEditedDiffRanges: compute diff ranges
1 parent 68378a3 commit 68b1b4e

File tree

1 file changed

+83
-2
lines changed

1 file changed

+83
-2
lines changed

src/analyze.ts

+83-2
Original file line numberDiff line numberDiff line change
@@ -294,8 +294,19 @@ async function getPullRequestEditedDiffRanges(
294294
headLabel: string,
295295
logger: Logger,
296296
): 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;
299310
}
300311

301312
/**
@@ -348,6 +359,76 @@ async function getFileDiffsWithBasehead(
348359
}
349360
}
350361

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+
351432
/**
352433
* Create an extension pack in the temporary directory that contains the file
353434
* line ranges that were added or modified in the pull request.

0 commit comments

Comments
 (0)