Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
microsoft
GitHub Repository: microsoft/vscode
Path: blob/main/src/vs/sessions/contrib/agentFeedback/browser/sessionEditorComments.ts
13401 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 { IRange, Range } from '../../../../editor/common/core/range.js';
7
import { URI } from '../../../../base/common/uri.js';
8
import { IAgentFeedback } from './agentFeedbackService.js';
9
import { CodeReviewStateKind, ICodeReviewComment, ICodeReviewState, ICodeReviewSuggestion, IPRReviewComment, IPRReviewState, PRReviewStateKind } from '../../codeReview/browser/codeReviewService.js';
10
11
export const enum SessionEditorCommentSource {
12
AgentFeedback = 'agentFeedback',
13
CodeReview = 'codeReview',
14
PRReview = 'prReview',
15
}
16
17
export interface ISessionEditorComment {
18
readonly id: string;
19
readonly sourceId: string;
20
readonly source: SessionEditorCommentSource;
21
readonly sessionResource: URI;
22
readonly resourceUri: URI;
23
readonly range: IRange;
24
readonly text: string;
25
readonly suggestion?: ICodeReviewSuggestion;
26
readonly severity?: string;
27
readonly canConvertToAgentFeedback: boolean;
28
}
29
30
export function getCodeReviewComments(reviewState: ICodeReviewState): readonly ICodeReviewComment[] {
31
return reviewState.kind === CodeReviewStateKind.Result ? reviewState.comments : [];
32
}
33
34
export function getPRReviewComments(prReviewState: IPRReviewState | undefined): readonly IPRReviewComment[] {
35
return prReviewState?.kind === PRReviewStateKind.Loaded ? prReviewState.comments : [];
36
}
37
38
export function getSessionEditorComments(
39
sessionResource: URI,
40
agentFeedbackItems: readonly IAgentFeedback[],
41
reviewState: ICodeReviewState,
42
prReviewState?: IPRReviewState,
43
): readonly ISessionEditorComment[] {
44
const comments: ISessionEditorComment[] = [];
45
46
for (const item of agentFeedbackItems) {
47
comments.push({
48
id: toSessionEditorCommentId(SessionEditorCommentSource.AgentFeedback, item.id),
49
sourceId: item.id,
50
source: SessionEditorCommentSource.AgentFeedback,
51
sessionResource,
52
resourceUri: item.resourceUri,
53
range: item.range,
54
text: item.text,
55
suggestion: item.suggestion,
56
canConvertToAgentFeedback: false,
57
});
58
}
59
60
for (const item of getCodeReviewComments(reviewState)) {
61
comments.push({
62
id: toSessionEditorCommentId(SessionEditorCommentSource.CodeReview, item.id),
63
sourceId: item.id,
64
source: SessionEditorCommentSource.CodeReview,
65
sessionResource,
66
resourceUri: item.uri,
67
range: item.range,
68
text: item.body,
69
suggestion: item.suggestion,
70
severity: item.severity,
71
canConvertToAgentFeedback: true,
72
});
73
}
74
75
for (const item of getPRReviewComments(prReviewState)) {
76
comments.push({
77
id: toSessionEditorCommentId(SessionEditorCommentSource.PRReview, item.id),
78
sourceId: item.id,
79
source: SessionEditorCommentSource.PRReview,
80
sessionResource,
81
resourceUri: item.uri,
82
range: item.range,
83
text: item.body,
84
canConvertToAgentFeedback: true,
85
});
86
}
87
88
comments.sort(compareSessionEditorComments);
89
return comments;
90
}
91
92
export function compareSessionEditorComments(a: ISessionEditorComment, b: ISessionEditorComment): number {
93
return a.resourceUri.toString().localeCompare(b.resourceUri.toString())
94
|| Range.compareRangesUsingStarts(Range.lift(a.range), Range.lift(b.range))
95
|| a.source.localeCompare(b.source)
96
|| a.sourceId.localeCompare(b.sourceId);
97
}
98
99
export function groupNearbySessionEditorComments(items: readonly ISessionEditorComment[], lineThreshold: number = 5): ISessionEditorComment[][] {
100
if (items.length === 0) {
101
return [];
102
}
103
104
const sorted = [...items].sort(compareSessionEditorComments);
105
const groups: ISessionEditorComment[][] = [];
106
let currentGroup: ISessionEditorComment[] = [sorted[0]];
107
108
for (let i = 1; i < sorted.length; i++) {
109
const firstItem = currentGroup[0];
110
const currentItem = sorted[i];
111
112
const sameResource = currentItem.resourceUri.toString() === firstItem.resourceUri.toString();
113
const verticalSpan = currentItem.range.startLineNumber - firstItem.range.startLineNumber;
114
115
if (sameResource && verticalSpan <= lineThreshold) {
116
currentGroup.push(currentItem);
117
} else {
118
groups.push(currentGroup);
119
currentGroup = [currentItem];
120
}
121
}
122
123
groups.push(currentGroup);
124
return groups;
125
}
126
127
export function getResourceEditorComments(resourceUri: URI, comments: readonly ISessionEditorComment[]): readonly ISessionEditorComment[] {
128
const resource = resourceUri.toString();
129
return comments.filter(comment => comment.resourceUri.toString() === resource);
130
}
131
132
export function toSessionEditorCommentId(source: SessionEditorCommentSource, sourceId: string): string {
133
return `${source}:${sourceId}`;
134
}
135
136
export function hasAgentFeedbackComments(comments: readonly ISessionEditorComment[]): boolean {
137
return comments.some(comment => comment.source === SessionEditorCommentSource.AgentFeedback);
138
}
139
140