Skip to content

Commit 8b94dc2

Browse files
authored
Support multiline comments (#3454)
* Support multiline comments Part of microsoft/vscode#146510 * Fix test
1 parent 1f2bb6e commit 8b94dc2

File tree

10 files changed

+70
-40
lines changed

10 files changed

+70
-40
lines changed

src/common/comment.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,10 @@ export interface IReviewThread {
3232
viewerCanUnresolve: boolean;
3333
path: string;
3434
diffSide: DiffSide;
35-
line: number;
36-
originalLine: number;
35+
startLine: number;
36+
endLine: number;
37+
originalStartLine: number;
38+
originalEndLine: number;
3739
isOutdated: boolean;
3840
comments: IComment[];
3941
}

src/github/graphql.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,9 @@ export interface ReviewThread {
168168
viewerCanUnresolve: boolean;
169169
path: string;
170170
diffSide: DiffSide;
171+
startLine: number | null;
171172
line: number;
173+
originalStartLine: number | null;
172174
originalLine: number;
173175
isOutdated: boolean;
174176
comments: {

src/github/pullRequestModel.ts

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -467,7 +467,8 @@ export class PullRequestModel extends IssueModel<PullRequest> implements IPullRe
467467
* a new review.
468468
* @param body The body of the thread's first comment.
469469
* @param commentPath The path to the file being commented on.
470-
* @param line The line on which to add the comment.
470+
* @param startLine The start line on which to add the comment.
471+
* @param endLine The end line on which to add the comment.
471472
* @param side The side the comment should be deleted on, i.e. the original or modified file.
472473
* @param suppressDraftModeUpdate If a draft mode change should event should be suppressed. In the
473474
* case of a single comment add, the review is created and then immediately submitted, so this prevents
@@ -477,7 +478,8 @@ export class PullRequestModel extends IssueModel<PullRequest> implements IPullRe
477478
async createReviewThread(
478479
body: string,
479480
commentPath: string,
480-
line: number,
481+
startLine: number,
482+
endLine: number,
481483
side: DiffSide,
482484
suppressDraftModeUpdate?: boolean,
483485
): Promise<IReviewThread | undefined> {
@@ -495,7 +497,8 @@ export class PullRequestModel extends IssueModel<PullRequest> implements IPullRe
495497
body,
496498
pullRequestId: this.graphNodeId,
497499
pullRequestReviewId: pendingReviewId,
498-
line,
500+
startLine: startLine === endLine ? undefined : startLine,
501+
line: endLine,
499502
side,
500503
},
501504
},

src/github/queries.gql

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,8 @@ fragment ReviewThread on PullRequestReviewThread {
147147
path
148148
diffSide
149149
line
150+
startLine
151+
originalStartLine
150152
originalLine
151153
isOutdated
152154
comments(first: 100) {
@@ -269,7 +271,9 @@ query PullRequestComments($owner: String!, $name: String!, $number: Int!, $first
269271
viewerCanUnresolve
270272
path
271273
diffSide
274+
startLine
272275
line
276+
originalStartLine
273277
originalLine
274278
isOutdated
275279
comments(first: 100) {

src/github/utils.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -354,8 +354,10 @@ export function parseGraphQLReviewThread(thread: GraphQL.ReviewThread): IReviewT
354354
viewerCanResolve: thread.viewerCanResolve,
355355
viewerCanUnresolve: thread.viewerCanUnresolve,
356356
path: thread.path,
357-
line: thread.line,
358-
originalLine: thread.originalLine,
357+
startLine: thread.startLine ?? thread.line,
358+
endLine: thread.line,
359+
originalStartLine: thread.originalStartLine ?? thread.originalLine,
360+
originalEndLine: thread.originalLine,
359361
diffSide: thread.diffSide,
360362
isOutdated: thread.isOutdated,
361363
comments: thread.comments.nodes.map(comment => parseGraphQLComment(comment, thread.isResolved)),

src/test/github/pullRequestModel.test.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,9 @@ const reviewThreadResponse = {
2525
viewerCanResolve: true,
2626
path: 'README.md',
2727
diffSide: 'RIGHT',
28+
startLine: null,
2829
line: 4,
30+
originalStartLine: null,
2931
originalLine: 4,
3032
isOutdated: false,
3133
comments: {

src/test/view/reviewCommentController.test.ts

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -164,8 +164,10 @@ describe('ReviewCommentController', function () {
164164
viewerCanUnresolve: false,
165165
path: fileName,
166166
diffSide: DiffSide.RIGHT,
167-
line: 372,
168-
originalLine: 372,
167+
startLine: 372,
168+
endLine: 372,
169+
originalStartLine: 372,
170+
originalEndLine: 372,
169171
isOutdated: false,
170172
comments: [
171173
{
@@ -252,6 +254,7 @@ describe('ReviewCommentController', function () {
252254
body: 'hello world',
253255
pullRequestId: activePullRequest.graphNodeId,
254256
pullRequestReviewId: undefined,
257+
startLine: undefined,
255258
line: 22,
256259
side: 'RIGHT'
257260
}
@@ -266,6 +269,8 @@ describe('ReviewCommentController', function () {
266269
viewCanResolve: true,
267270
path: fileName,
268271
line: 22,
272+
startLine: null,
273+
originalStartLine: null,
269274
originalLine: 22,
270275
diffSide: 'RIGHT',
271276
isOutdated: false,

src/view/pullRequestCommentController.ts

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -165,13 +165,13 @@ export class PullRequestCommentController implements CommentHandler, CommentReac
165165
.filter(
166166
thread =>
167167
((thread.diffSide === DiffSide.LEFT && isBase) ||
168-
(thread.diffSide === DiffSide.RIGHT && !isBase))
169-
&& (thread.line !== null),
168+
(thread.diffSide === DiffSide.RIGHT && !isBase))
169+
&& (thread.endLine !== null),
170170
)
171171
.map(thread => {
172172
const range = new vscode.Range(
173-
new vscode.Position(thread.line - 1, 0),
174-
new vscode.Position(thread.line - 1, 0),
173+
new vscode.Position(thread.startLine - 1, 0),
174+
new vscode.Position(thread.endLine - 1, 0),
175175
);
176176

177177
return createVSCodeCommentThreadForReviewThread(
@@ -239,7 +239,7 @@ export class PullRequestCommentController implements CommentHandler, CommentReac
239239
const fileName = thread.path;
240240
const index = this._pendingCommentThreadAdds.findIndex(t => {
241241
const samePath = this.gitRelativeRootPath(t.uri.path) === thread.path;
242-
const sameLine = t.range.start.line + 1 === thread.line;
242+
const sameLine = t.range.end.line + 1 === thread.endLine;
243243
return samePath && sameLine;
244244
});
245245

@@ -261,8 +261,8 @@ export class PullRequestCommentController implements CommentHandler, CommentReac
261261

262262
if (matchingEditor) {
263263
const range = new vscode.Range(
264-
new vscode.Position(thread.line - 1, 0),
265-
new vscode.Position(thread.line - 1, 0),
264+
new vscode.Position(thread.startLine - 1, 0),
265+
new vscode.Position(thread.endLine - 1, 0),
266266
);
267267

268268
newThread = createVSCodeCommentThreadForReviewThread(
@@ -334,8 +334,8 @@ export class PullRequestCommentController implements CommentHandler, CommentReac
334334
const isDraft = isSingleComment
335335
? false
336336
: inDraft !== undefined
337-
? inDraft
338-
: this.pullRequestModel.hasPendingReview;
337+
? inDraft
338+
: this.pullRequestModel.hasPendingReview;
339339
const temporaryCommentId = this.optimisticallyAddComment(thread, input, isDraft);
340340

341341
try {
@@ -349,6 +349,7 @@ export class PullRequestCommentController implements CommentHandler, CommentReac
349349
input,
350350
fileName,
351351
thread.range.start.line + 1,
352+
thread.range.end.line + 1,
352353
side,
353354
isSingleComment,
354355
);
@@ -461,7 +462,7 @@ export class PullRequestCommentController implements CommentHandler, CommentReac
461462
const fileName = this.gitRelativeRootPath(thread.uri.path);
462463
const side = this.getCommentSide(thread);
463464
this._pendingCommentThreadAdds.push(thread);
464-
await this.pullRequestModel.createReviewThread(input, fileName, thread.range.start.line + 1, side);
465+
await this.pullRequestModel.createReviewThread(input, fileName, thread.range.start.line + 1, thread.range.end.line + 1, side);
465466
} else {
466467
await this.reply(thread, input, false);
467468
}

src/view/reviewCommentController.ts

Lines changed: 26 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -100,8 +100,8 @@ export class ReviewCommentController
100100
);
101101

102102
const range = new vscode.Range(
103-
new vscode.Position(thread.originalLine - 1, 0),
104-
new vscode.Position(thread.originalLine - 1, 0),
103+
new vscode.Position(thread.originalStartLine - 1, 0),
104+
new vscode.Position(thread.originalEndLine - 1, 0),
105105
);
106106

107107
return createVSCodeCommentThreadForReviewThread(reviewUri, range, thread, this._commentController);
@@ -120,13 +120,15 @@ export class ReviewCommentController
120120
path: string,
121121
thread: IReviewThread,
122122
): Promise<GHPRCommentThread> {
123-
let line = thread.line;
123+
let startLine = thread.startLine;
124+
let endLine = thread.endLine;
124125
const localDiff = await this._repository.diffWithHEAD(path);
125126
if (localDiff) {
126-
line = mapOldPositionToNew(localDiff, thread.line);
127+
startLine = mapOldPositionToNew(localDiff, startLine);
128+
endLine = mapOldPositionToNew(localDiff, endLine);
127129
}
128130

129-
const range = new vscode.Range(new vscode.Position(line - 1, 0), new vscode.Position(line - 1, 0));
131+
const range = new vscode.Range(new vscode.Position(startLine - 1, 0), new vscode.Position(endLine - 1, 0));
130132

131133
return createVSCodeCommentThreadForReviewThread(uri, range, thread, this._commentController);
132134
}
@@ -154,8 +156,8 @@ export class ReviewCommentController
154156
);
155157

156158
const range = new vscode.Range(
157-
new vscode.Position(thread.line - 1, 0),
158-
new vscode.Position(thread.line - 1, 0),
159+
new vscode.Position(thread.startLine - 1, 0),
160+
new vscode.Position(thread.endLine - 1, 0),
159161
);
160162

161163
return createVSCodeCommentThreadForReviewThread(reviewUri, range, thread, this._commentController);
@@ -234,8 +236,8 @@ export class ReviewCommentController
234236
}
235237

236238
const diff = await this.getContentDiff(t.uri, fileName);
237-
const line = mapNewPositionToOld(diff, t.range.start.line);
238-
const sameLine = line + 1 === thread.line;
239+
const line = mapNewPositionToOld(diff, t.range.end.line);
240+
const sameLine = line + 1 === thread.endLine;
239241
return sameLine;
240242
});
241243

@@ -550,15 +552,18 @@ export class ReviewCommentController
550552

551553
// If the thread is on the workspace file, make sure the position
552554
// is properly adjusted to account for any local changes.
553-
let line: number;
555+
let startLine: number;
556+
let endLine: number;
554557
if (side === DiffSide.RIGHT) {
555558
const diff = await this.getContentDiff(thread.uri, fileName);
556-
line = mapNewPositionToOld(diff, thread.range.start.line);
559+
startLine = mapNewPositionToOld(diff, thread.range.start.line);
560+
endLine = mapNewPositionToOld(diff, thread.range.end.line);
557561
} else {
558-
line = thread.range.start.line;
562+
startLine = thread.range.start.line;
563+
endLine = thread.range.end.line;
559564
}
560565

561-
await this._reposManager.activePullRequest!.createReviewThread(input, fileName, line + 1, side);
566+
await this._reposManager.activePullRequest!.createReviewThread(input, fileName, startLine + 1, endLine + 1, side);
562567
} else {
563568
const comment = thread.comments[0];
564569
if (comment instanceof GHPRComment) {
@@ -649,17 +654,21 @@ export class ReviewCommentController
649654

650655
// If the thread is on the workspace file, make sure the position
651656
// is properly adjusted to account for any local changes.
652-
let line: number;
657+
let startLine: number;
658+
let endLine: number;
653659
if (side === DiffSide.RIGHT) {
654660
const diff = await this.getContentDiff(thread.uri, fileName);
655-
line = mapNewPositionToOld(diff, thread.range.start.line);
661+
startLine = mapNewPositionToOld(diff, thread.range.start.line);
662+
endLine = mapNewPositionToOld(diff, thread.range.end.line);
656663
} else {
657-
line = thread.range.start.line;
664+
startLine = thread.range.start.line;
665+
endLine = thread.range.end.line;
658666
}
659667
await this._reposManager.activePullRequest.createReviewThread(
660668
input,
661669
fileName,
662-
line + 1,
670+
startLine + 1,
671+
endLine + 1,
663672
side,
664673
isSingleComment,
665674
);

src/view/treeNodes/fileChangeNode.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -269,8 +269,8 @@ export class FileChangeNode extends TreeNode implements vscode.TreeItem {
269269
);
270270

271271
if (reviewThreadsForNode.length) {
272-
reviewThreadsForNode.sort((a, b) => a.line - b.line);
273-
this.opts.selection = new vscode.Range(reviewThreadsForNode[0].line, 0, reviewThreadsForNode[0].line, 0);
272+
reviewThreadsForNode.sort((a, b) => a.endLine - b.endLine);
273+
this.opts.selection = new vscode.Range(reviewThreadsForNode[0].startLine, 0, reviewThreadsForNode[0].endLine, 0);
274274
} else {
275275
delete this.opts.selection;
276276
}
@@ -421,10 +421,10 @@ export class GitFileChangeNode extends FileChangeNode implements vscode.TreeItem
421421
const reviewThreadsByFile = groupBy(reviewThreads, t => t.path);
422422
const reviewThreadsForNode = (reviewThreadsByFile[this.fileName] || [])
423423
.filter(thread => thread.isOutdated)
424-
.sort((a, b) => a.line - b.line);
424+
.sort((a, b) => a.endLine - b.endLine);
425425

426426
if (reviewThreadsForNode.length) {
427-
options.selection = new vscode.Range(reviewThreadsForNode[0].originalLine, 0, reviewThreadsForNode[0].originalLine, 0);
427+
options.selection = new vscode.Range(reviewThreadsForNode[0].originalStartLine, 0, reviewThreadsForNode[0].originalEndLine, 0);
428428
}
429429

430430
return {

0 commit comments

Comments
 (0)