Skip to content

Commit f662f12

Browse files
committed
Review individual file changes
1 parent c5fbb36 commit f662f12

File tree

5 files changed

+69
-6
lines changed

5 files changed

+69
-6
lines changed

package.json

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1898,6 +1898,20 @@
18981898
"enablement": "github.copilot.chat.reviewDiff.enabled && !github.copilot.interactiveSession.disabled",
18991899
"category": "GitHub Copilot"
19001900
},
1901+
{
1902+
"command": "github.copilot.chat.review.stagedFileChange",
1903+
"title": "%github.copilot.command.reviewFileChange%",
1904+
"icon": "$(code-review)",
1905+
"enablement": "github.copilot.chat.reviewDiff.enabled && !github.copilot.interactiveSession.disabled",
1906+
"category": "GitHub Copilot"
1907+
},
1908+
{
1909+
"command": "github.copilot.chat.review.unstagedFileChange",
1910+
"title": "%github.copilot.command.reviewFileChange%",
1911+
"icon": "$(code-review)",
1912+
"enablement": "github.copilot.chat.reviewDiff.enabled && !github.copilot.interactiveSession.disabled",
1913+
"category": "GitHub Copilot"
1914+
},
19011915
{
19021916
"command": "github.copilot.chat.review.changes.cancel",
19031917
"title": "%github.copilot.command.reviewChanges.cancel%",
@@ -3067,6 +3081,14 @@
30673081
"command": "github.copilot.chat.review.changes",
30683082
"when": "false"
30693083
},
3084+
{
3085+
"command": "github.copilot.chat.review.stagedFileChange",
3086+
"when": "false"
3087+
},
3088+
{
3089+
"command": "github.copilot.chat.review.unstagedFileChange",
3090+
"when": "false"
3091+
},
30703092
{
30713093
"command": "github.copilot.chat.review.changes.cancel",
30723094
"when": "false"
@@ -3334,6 +3356,18 @@
33343356
"group": "inline@-3"
33353357
}
33363358
],
3359+
"scm/resourceState/context": [
3360+
{
3361+
"command": "github.copilot.chat.review.stagedFileChange",
3362+
"group": "3_copilot",
3363+
"when": "github.copilot.chat.reviewDiff.enabled && scmProvider == git && scmResourceGroup == index"
3364+
},
3365+
{
3366+
"command": "github.copilot.chat.review.unstagedFileChange",
3367+
"group": "3_copilot",
3368+
"when": "github.copilot.chat.reviewDiff.enabled && scmProvider == git && scmResourceGroup == workingTree"
3369+
}
3370+
],
33373371
"scm/inputBox": [
33383372
{
33393373
"command": "github.copilot.git.generateCommitMessage",

package.nls.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
"github.copilot.command.reviewUnstagedChanges": "Code Review - Unstaged Changes",
1616
"github.copilot.command.reviewChanges": "Code Review - Uncommitted Changes",
1717
"github.copilot.command.reviewChanges.cancel": "Code Review - Cancel",
18+
"github.copilot.command.reviewFileChange": "Review Changes",
1819
"github.copilot.command.gotoPreviousReviewSuggestion": "Previous Suggestion",
1920
"github.copilot.command.gotoNextReviewSuggestion": "Next Suggestion",
2021
"github.copilot.command.continueReviewInInlineChat": "Discard and Copy to Inline Chat",

src/extension/inlineChat/vscode-node/inlineChatCommands.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -314,6 +314,14 @@ ${message}`,
314314
disposables.add(vscode.commands.registerCommand('github.copilot.chat.review.stagedChanges', () => doReview(...instaService.invokeFunction(getServicesForReview), 'index', vscode.ProgressLocation.SourceControl)));
315315
disposables.add(vscode.commands.registerCommand('github.copilot.chat.review.unstagedChanges', () => doReview(...instaService.invokeFunction(getServicesForReview), 'workingTree', vscode.ProgressLocation.SourceControl)));
316316
disposables.add(vscode.commands.registerCommand('github.copilot.chat.review.changes', () => doReview(...instaService.invokeFunction(getServicesForReview), 'all', vscode.ProgressLocation.SourceControl)));
317+
disposables.add(vscode.commands.registerCommand('github.copilot.chat.review.stagedFileChange', (resource: vscode.SourceControlResourceState) => {
318+
vscode.window.showTextDocument(resource.resourceUri, { preview: false });
319+
return doReview(...instaService.invokeFunction(getServicesForReview), { group: 'index', file: resource.resourceUri }, vscode.ProgressLocation.SourceControl);
320+
}));
321+
disposables.add(vscode.commands.registerCommand('github.copilot.chat.review.unstagedFileChange', (resource: vscode.SourceControlResourceState) => {
322+
vscode.window.showTextDocument(resource.resourceUri, { preview: false });
323+
return doReview(...instaService.invokeFunction(getServicesForReview), { group: 'workingTree', file: resource.resourceUri }, vscode.ProgressLocation.SourceControl);
324+
}));
317325
disposables.add(vscode.commands.registerCommand('github.copilot.chat.review.changes.cancel', () => cancelReview(vscode.ProgressLocation.SourceControl, instaService.invokeFunction(accessor => accessor.get(IRunCommandExecutionService)))));
318326
disposables.add(vscode.commands.registerCommand('github.copilot.chat.review.apply', doApplyReview));
319327
disposables.add(vscode.commands.registerCommand('github.copilot.chat.review.applyAndNext', (commentThread: vscode.CommentThread) => doApplyReview(commentThread, true)));

src/extension/review/node/doReview.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
* Licensed under the MIT License. See License.txt in the project root for license information.
44
*--------------------------------------------------------------------------------------------*/
55

6-
import type { TextEditor } from 'vscode';
6+
import type { TextEditor, Uri } from 'vscode';
77
import { IAuthenticationService } from '../../../platform/authentication/common/authentication';
88
import { IRunCommandExecutionService } from '../../../platform/commands/common/runCommandExecutionService';
99
import { TextDocumentSnapshot } from '../../../platform/editing/common/textDocumentSnapshot';
@@ -69,7 +69,7 @@ export async function doReview(
6969
workspaceService: IWorkspaceService,
7070
commandService: IRunCommandExecutionService,
7171
notificationService: INotificationService,
72-
group: 'selection' | 'index' | 'workingTree' | 'all' | { repositoryRoot: string; commitMessages: string[]; patches: { patch: string; fileUri: string; previousFileUri?: string }[] },
72+
group: 'selection' | 'index' | 'workingTree' | 'all' | { group: 'index' | 'workingTree'; file: Uri } | { repositoryRoot: string; commitMessages: string[]; patches: { patch: string; fileUri: string; previousFileUri?: string }[] },
7373
progressLocation: ProgressLocation,
7474
cancellationToken?: CancellationToken
7575
): Promise<FeedbackResult | undefined> {
@@ -121,7 +121,7 @@ export async function doReview(
121121
try {
122122
const copilotToken = await authService.getCopilotToken();
123123
const canUseGitHubAgent = (group === 'index' || group === 'workingTree' || group === 'all' || typeof group === 'object') && copilotToken.isCopilotCodeReviewEnabled;
124-
result = canUseGitHubAgent ? await githubReview(logService, gitExtensionService, authService, capiClientService, domainService, fetcherService, envService, ignoreService, workspaceService, group, progress, tokenSource.token) : await review(instantiationService, gitExtensionService, workspaceService, group, editor, progress, tokenSource.token);
124+
result = canUseGitHubAgent ? await githubReview(logService, gitExtensionService, authService, capiClientService, domainService, fetcherService, envService, ignoreService, workspaceService, group, progress, tokenSource.token) : await review(instantiationService, gitExtensionService, workspaceService, typeof group === 'object' && 'group' in group ? group.group : group, editor, progress, tokenSource.token);
125125
} catch (err) {
126126
result = { type: 'error', reason: err.message, severity: err.severity };
127127
} finally {

src/extension/review/node/githubReviewAgent.ts

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ export async function githubReview(
3939
envService: IEnvService,
4040
ignoreService: IIgnoreService,
4141
workspaceService: IWorkspaceService,
42-
group: 'index' | 'workingTree' | 'all' | { repositoryRoot: string; commitMessages: string[]; patches: { patch: string; fileUri: string; previousFileUri?: string }[] },
42+
group: 'index' | 'workingTree' | 'all' | { group: 'index' | 'workingTree'; file: Uri } | { repositoryRoot: string; commitMessages: string[]; patches: { patch: string; fileUri: string; previousFileUri?: string }[] },
4343
progress: Progress<ReviewComment[]>,
4444
cancellationToken: CancellationToken
4545
): Promise<FeedbackResult> {
@@ -76,7 +76,7 @@ export async function githubReview(
7676
}));
7777
return changes;
7878
}))).flat()
79-
: await Promise.all(group.patches.map(async patch => {
79+
: 'repositoryRoot' in group ? await Promise.all(group.patches.map(async patch => {
8080
const uri = Uri.parse(patch.fileUri);
8181
const document = await workspaceService.openTextDocument(uri).then(undefined, () => undefined);
8282
if (!document) {
@@ -92,7 +92,27 @@ export async function githubReview(
9292
after,
9393
document,
9494
};
95-
}))).filter((change): change is NonNullable<typeof change> => !!change);
95+
}))
96+
: await (async () => {
97+
const { group: g, file } = group;
98+
const repository = git.getRepository(file);
99+
const document = await workspaceService.openTextDocument(file).then(undefined, () => undefined);
100+
if (!repository || !document) {
101+
return [];
102+
}
103+
const before = await (g === 'index' ? repository.show('HEAD', file.fsPath).catch(() => '') : repository.show('', file.fsPath).catch(() => ''));
104+
const after = g === 'index' ? await (repository.show('', file.fsPath).catch(() => '')) : document.getText();
105+
const relativePath = path.relative(repository.rootUri.fsPath, file.fsPath);
106+
return [
107+
{
108+
repository,
109+
relativePath: process.platform === 'win32' ? relativePath.replace(/\\/g, '/') : relativePath,
110+
before,
111+
after,
112+
document,
113+
}
114+
];
115+
})()).filter((change): change is NonNullable<typeof change> => !!change);
96116

97117
if (!changes.length) {
98118
return { type: 'success', comments: [] };

0 commit comments

Comments
 (0)