Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
microsoft
GitHub Repository: microsoft/vscode
Path: blob/main/extensions/copilot/src/extension/conversation/node/githubPullRequestProviders.ts
13399 views
1
/*---------------------------------------------------------------------------------------------
2
* Copyright (c) Microsoft Corporation. All rights reserved.
3
* Licensed under the MIT License. See License.txt in the project root for license information.
4
*--------------------------------------------------------------------------------------------*/
5
6
import type { Disposable } from 'vscode';
7
import * as l10n from '@vscode/l10n';
8
import { IExtensionsService } from '../../../platform/extensions/common/extensionsService';
9
import { ILogService } from '../../../platform/log/common/logService';
10
import { IReviewService } from '../../../platform/review/common/reviewService';
11
import { DisposableStore } from '../../../util/vs/base/common/lifecycle';
12
import { IInstantiationService } from '../../../util/vs/platform/instantiation/common/instantiation';
13
import { Extension, Uri } from '../../../vscodeTypes';
14
import { API, RepositoryDescription } from '../../githubPullRequest';
15
import { GitHubPullRequestTitleAndDescriptionGenerator } from '../../prompt/node/githubPullRequestTitleAndDescriptionGenerator';
16
import { GitHubPullRequestReviewerCommentsProvider } from '../../review/node/githubPullRequestReviewerCommentsProvider';
17
import { ConfigKey, IConfigurationService } from '../../../platform/configuration/common/configurationService';
18
19
export class GitHubPullRequestProviders implements Disposable {
20
private gitHubExtensionApi: API | undefined;
21
protected readonly disposables: DisposableStore = new DisposableStore();
22
23
constructor(
24
@ILogService protected readonly logService: ILogService,
25
@IInstantiationService private readonly instantiationService: IInstantiationService,
26
@IReviewService private readonly reviewService: IReviewService,
27
@IExtensionsService private readonly extensionService: IExtensionsService,
28
@IConfigurationService private _configurationService: IConfigurationService,
29
) {
30
this.initializeGitHubPRExtensionApi();
31
}
32
dispose() {
33
this.disposables.dispose();
34
}
35
36
private getExtension(): Extension<API> | undefined {
37
return this.extensionService.getExtension('github.vscode-pull-request-github');
38
}
39
40
private initializeGitHubPRExtensionApi() {
41
let githubPRExtension = this.getExtension();
42
43
const initialize = async () => {
44
if (githubPRExtension) {
45
const extension = await githubPRExtension!.activate();
46
this.logService.info('Successfully activated the GitHub.vscode-pull-request-github extension.');
47
48
this.gitHubExtensionApi = extension;
49
this.registerTitleAndDescriptionProvider();
50
this.registerReviewerCommentsProvider();
51
}
52
};
53
54
if (githubPRExtension) {
55
initialize();
56
} else {
57
this.logService.info('GitHub.vscode-pull-request-github extension is not yet activated.');
58
59
const listener = this.extensionService.onDidChange(() => {
60
githubPRExtension = this.getExtension();
61
if (githubPRExtension) {
62
initialize();
63
listener.dispose();
64
}
65
});
66
this.disposables.add(listener);
67
}
68
69
this.disposables.add(this._configurationService.onDidChangeConfiguration(e => {
70
if (e.affectsConfiguration(ConfigKey.ReviewAgent.fullyQualifiedId)) {
71
this.registerReviewerCommentsProvider();
72
}
73
}));
74
}
75
76
private titleAndDescriptionProvider: GitHubPullRequestTitleAndDescriptionGenerator | undefined;
77
private async registerTitleAndDescriptionProvider() {
78
if (!this.gitHubExtensionApi) {
79
return;
80
}
81
try {
82
if (!this.titleAndDescriptionProvider) {
83
this.titleAndDescriptionProvider = this.disposables.add(this.instantiationService.createInstance(GitHubPullRequestTitleAndDescriptionGenerator));
84
}
85
// This string "Copilot" needs to be in here. It's how we an tell which provider to use in the PR extension.
86
this.disposables.add(this.gitHubExtensionApi.registerTitleAndDescriptionProvider(l10n.t('Generate with Copilot'), this.titleAndDescriptionProvider));
87
this.logService.info('Successfully registered GitHub PR title and description provider.');
88
} catch (e) {
89
// Catch errors in case there's a breaking API change.
90
}
91
}
92
93
private reviewerCommentsProvider: GitHubPullRequestReviewerCommentsProvider | undefined;
94
private reviewerCommentsRegistration: Disposable | undefined;
95
private async registerReviewerCommentsProvider() {
96
if (!this.gitHubExtensionApi) {
97
return;
98
}
99
100
if (!this.reviewService.isReviewDiffEnabled()) {
101
if (this.reviewerCommentsRegistration) {
102
this.disposables.delete(this.reviewerCommentsRegistration);
103
this.reviewerCommentsRegistration = undefined;
104
}
105
return;
106
}
107
108
if (this.reviewerCommentsRegistration) {
109
return;
110
}
111
112
try {
113
if (!this.reviewerCommentsProvider) {
114
this.reviewerCommentsProvider = this.instantiationService.createInstance(GitHubPullRequestReviewerCommentsProvider);
115
}
116
this.reviewerCommentsRegistration = this.gitHubExtensionApi.registerReviewerCommentsProvider(l10n.t('Copilot'), this.reviewerCommentsProvider);
117
this.disposables.add(this.reviewerCommentsRegistration);
118
this.logService.info('Successfully registered GitHub PR reviewer comments provider.');
119
} catch (e) {
120
// Catch errors in case there's a breaking API change.
121
}
122
}
123
124
public async getRepositoryDescription(uri: Uri): Promise<RepositoryDescription | undefined> {
125
try {
126
// Wait for gitHubExtensionApi to be initialized if not already
127
if (!this.gitHubExtensionApi) {
128
// Try to get and activate the extension if possible
129
const githubPRExtension = this.getExtension();
130
if (githubPRExtension) {
131
const extension = await githubPRExtension.activate();
132
this.gitHubExtensionApi = extension;
133
} else {
134
this.logService.warn('GitHub.vscode-pull-request-github extension API is not available.');
135
return undefined;
136
}
137
}
138
139
if (!this.gitHubExtensionApi.getRepositoryDescription) {
140
return undefined;
141
}
142
143
return await this.gitHubExtensionApi.getRepositoryDescription(uri);
144
} catch (error) {
145
this.logService.error('Failed to get repository description from GitHub.vscode-pull-request-github extension.', error);
146
return undefined;
147
}
148
}
149
}
150
151