Skip to content

Commit 791e8c8

Browse files
Copilotalexr00
andauthored
Fix file-scoped comment failing with "Error: File has been deleted"
When creating a file-scoped comment (range is undefined), the createReviewThread method was passing `line: 0` to the GitHub GraphQL API. The API does not accept line 0 and returns a null thread, which caused the misleading "File has been deleted" error. Fix: pass endLine directly (undefined for file-scoped comments) instead of converting undefined to 0. The line parameter is not required when subjectType is FILE. Agent-Logs-Url: https://github.com/microsoft/vscode-pull-request-github/sessions/2e5f5355-cccd-4ac6-b866-9d00dcd8b8b4 Co-authored-by: alexr00 <38270282+alexr00@users.noreply.github.com>
1 parent d226d16 commit 791e8c8

File tree

2 files changed

+102
-1
lines changed

2 files changed

+102
-1
lines changed

src/github/pullRequestModel.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -751,7 +751,7 @@ export class PullRequestModel extends IssueModel<PullRequest> implements IPullRe
751751
pullRequestId: this.graphNodeId,
752752
pullRequestReviewId: pendingReviewId,
753753
startLine: startLine === endLine ? undefined : startLine,
754-
line: (endLine === undefined) ? 0 : endLine,
754+
line: endLine,
755755
side,
756756
subjectType: (startLine === undefined || endLine === undefined) ? SubjectType.FILE : SubjectType.LINE
757757
}

src/test/view/reviewCommentController.test.ts

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -339,5 +339,106 @@ describe('ReviewCommentController', function () {
339339
assert.strictEqual(Object.keys(workspaceFileChangeCommentThreads)[0], fileName);
340340
assert.strictEqual(workspaceFileChangeCommentThreads[fileName].length, 1);
341341
});
342+
343+
it('creates a file-scoped comment on an empty thread', async function () {
344+
const fileName = 'data/products.json';
345+
const uri = vscode.Uri.parse(`${repository.rootUri.toString()}/${fileName}`);
346+
await activePullRequest.initializeReviewThreadCache();
347+
const localFileChanges = [createLocalFileChange(uri, fileName, repository.rootUri)];
348+
const reviewModel = new ReviewModel();
349+
reviewModel.localFileChanges = localFileChanges;
350+
const reviewCommentController = new TestReviewCommentController(
351+
reviewManager,
352+
manager,
353+
repository,
354+
reviewModel,
355+
gitApiImpl,
356+
telemetry
357+
);
358+
const thread = createGHPRCommentThread('review-1.2', uri);
359+
thread.range = undefined as any;
360+
361+
sinon.stub(activePullRequest, 'validateDraftMode').returns(Promise.resolve(false));
362+
sinon.stub(activePullRequest, 'getReviewThreads').returns(Promise.resolve([]));
363+
sinon.stub(activePullRequest, 'getPendingReviewId').returns(Promise.resolve(undefined));
364+
365+
sinon.stub(manager, 'getCurrentUser').returns(Promise.resolve({
366+
login: 'rmacfarlane',
367+
url: 'https://github.com/rmacfarlane',
368+
id: '123',
369+
accountType: AccountType.User
370+
}));
371+
372+
sinon.stub(vscode.workspace, 'getWorkspaceFolder').returns({
373+
uri: repository.rootUri,
374+
name: '',
375+
index: 0,
376+
});
377+
378+
sinon.stub(vscode.workspace, 'asRelativePath').callsFake((pathOrUri: string | vscode.Uri): string => {
379+
const path = pathOrUri.toString();
380+
return path.substring('/root/'.length);
381+
});
382+
383+
sinon.stub(repository, 'diffWith').returns(Promise.resolve(''));
384+
385+
await reviewCommentController.initialize();
386+
387+
githubRepo.queryProvider.expectGraphQLMutation(
388+
{
389+
mutation: schema.AddReviewThread,
390+
variables: {
391+
input: {
392+
path: fileName,
393+
body: 'file comment',
394+
pullRequestId: activePullRequest.graphNodeId,
395+
pullRequestReviewId: undefined,
396+
startLine: undefined,
397+
line: undefined,
398+
side: 'RIGHT',
399+
subjectType: 'FILE'
400+
}
401+
}
402+
},
403+
{
404+
data: {
405+
addPullRequestReviewThread: {
406+
thread: {
407+
id: 2,
408+
isResolved: false,
409+
viewCanResolve: true,
410+
path: fileName,
411+
line: null,
412+
startLine: null,
413+
originalStartLine: null,
414+
originalLine: null,
415+
diffSide: 'RIGHT',
416+
isOutdated: false,
417+
subjectType: 'FILE',
418+
comments: {
419+
nodes: [
420+
{
421+
databaseId: 2,
422+
id: 2,
423+
body: 'file comment',
424+
commit: {},
425+
diffHunk: '',
426+
reactionGroups: [],
427+
author: {}
428+
}
429+
]
430+
}
431+
}
432+
}
433+
}
434+
}
435+
)
436+
437+
const newReviewThreadPromise = asPromise(activePullRequest.onDidChangeReviewThreads);
438+
await reviewCommentController.createOrReplyComment(thread, 'file comment', false);
439+
await newReviewThreadPromise;
440+
assert.strictEqual(thread.comments.length, 1);
441+
assert.strictEqual(thread.comments[0].parent, thread);
442+
});
342443
});
343444
});

0 commit comments

Comments
 (0)