Repository navigation
Expand file tree
/
Copy pathpullRequestDiffComments.ts
More file actions
106 lines (105 loc) · 4.03 KB
/
Copy pathpullRequestDiffComments.ts
File metadata and controls
106 lines (105 loc) · 4.03 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
import type { PullRequestReviewPosition, PullRequestReviewThread } from "@t3tools/contracts";
import type { NativeReviewDiffRow } from "../diffs/nativeReviewDiffSurface";
import type { NativeReviewDiffData } from "../review/nativeReviewDiffAdapter";
import type { PendingReviewComment } from "./pullRequestReviewDrafts";
export function reviewPosition(row: NativeReviewDiffRow): PullRequestReviewPosition | null {
if (row.kind !== "line") return null;
if (row.change === "add" && row.newLineNumber)
return { kind: "added", newLine: row.newLineNumber };
if (row.change === "delete" && row.oldLineNumber)
return { kind: "deleted", oldLine: row.oldLineNumber };
if (row.oldLineNumber && row.newLineNumber)
return {
kind: "context",
oldLine: row.oldLineNumber,
newLine: row.newLineNumber,
side: "right",
};
return null;
}
export function discussionCommentCountLabel(count: number) {
return `${count} ${count === 1 ? "comment" : "comments"}`;
}
export function reviewPositionLabel(position: PullRequestReviewPosition) {
const oldSide =
position.kind === "deleted" || (position.kind === "context" && position.side === "left");
return `${oldSide ? "Old line" : "Line"} ${reviewLine(position)}`;
}
function reviewLine(position: PullRequestReviewPosition) {
if (position.kind === "deleted" || (position.kind === "context" && position.side === "left"))
return position.oldLine;
return position.newLine;
}
export function annotatePullRequestDiff(
data: NativeReviewDiffData,
threads: readonly PullRequestReviewThread[],
drafts: readonly PendingReviewComment[],
headSha: string | undefined,
): NativeReviewDiffData {
if (threads.length === 0 && drafts.length === 0) return data;
const anchors = new Map<string, NativeReviewDiffRow[]>();
const firstByPath = new Map<string, NativeReviewDiffRow>();
const lines = new Map<string, NativeReviewDiffRow>();
const paths = new Map(data.files.map((file) => [file.id, file.path]));
for (const original of data.rows) {
const row = {
...original,
filePath: original.filePath ?? (original.fileId ? paths.get(original.fileId) : undefined),
};
if (row.kind === "file" && row.filePath) firstByPath.set(row.filePath, row);
if (row.kind !== "line" || !row.filePath) continue;
if (row.oldLineNumber)
lines.set(JSON.stringify([row.filePath, "left", row.oldLineNumber]), row);
if (row.newLineNumber)
lines.set(JSON.stringify([row.filePath, "right", row.newLineNumber]), row);
}
const attach = (
anchor: NativeReviewDiffRow | undefined,
id: string,
body: string,
label: string,
) => {
if (!anchor) return;
const rows = anchors.get(anchor.id) ?? [];
rows.push({
kind: "comment",
id,
fileId: anchor.fileId,
filePath: anchor.filePath,
commentText: body,
commentRangeLabel: label,
});
anchors.set(anchor.id, rows);
};
for (const thread of threads) {
if (thread.isOutdated) continue;
const anchor =
thread.line === null
? firstByPath.get(thread.path)
: lines.get(JSON.stringify([thread.path, thread.side, thread.line]));
const first = thread.comments[0];
attach(
anchor,
`discussion:${thread.id}`,
`${first?.author?.login ?? "Discussion"}${thread.isResolved ? " · Resolved" : ""}\n${first?.body ?? ""}\n${discussionCommentCountLabel(thread.commentCount ?? thread.comments.length)} · Tap to open`,
thread.line === null ? "file" : String(thread.line),
);
}
for (const draft of drafts) {
if (draft.headSha !== headSha) continue;
const side =
draft.position.kind === "deleted"
? "left"
: draft.position.kind === "context"
? draft.position.side
: "right";
const line = reviewLine(draft.position);
attach(
lines.get(JSON.stringify([draft.path, side, line])),
`draft:${draft.id}`,
`Pending review · Tap to edit\n${draft.body}`,
String(line),
);
}
return { ...data, rows: data.rows.flatMap((row) => [row, ...(anchors.get(row.id) ?? [])]) };
}