Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
microsoft
GitHub Repository: microsoft/vscode
Path: blob/main/extensions/copilot/src/extension/prompts/node/inline/diffEditGeneration.tsx
13405 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 { PromptElement } from '@vscode/prompt-tsx';
7
import { extractCodeBlocks } from '../../../../util/common/markdown';
8
import { splitLines } from '../../../../util/vs/base/common/strings';
9
import { TextEdit } from '../../../../vscodeTypes';
10
import { OutcomeAnnotation } from '../../../inlineChat/node/promptCraftingTypes';
11
import { createEditsFromPseudoDiff } from '../../../prompt/node/editFromDiffGeneration';
12
import { LineRange, Lines, LinesEdit } from '../../../prompt/node/editGeneration';
13
14
export class EditGenerationRules extends PromptElement {
15
render() {
16
return (
17
<>
18
For the response always follow these instructions:<br />
19
Describe in a single sentence how you would solve the problem. After that sentence, add an empty line. Then add a code block with the fix.<br />
20
When proposing a change in the code, use a single code block that starts with ```diff and that describes the changes in the diff format. In the diff, always use tab to indent, never spaces. Make sure that the diff format is valid and contains all changes: Removed and unchanged lines must match exactly the original code line. Keep the changes minimal and the diff short.<br />
21
When proposing to fix the problem by running a terminal command, provide the terminal script in a code block that starts with ```bash.<br />
22
</>
23
);
24
}
25
}
26
27
export class EditGenerationExampleSetup extends PromptElement {
28
render() {
29
return (
30
<>
31
```csharp<br />
32
// This is my class<br />
33
class C &#123; &#125;<br />
34
<br />
35
new C().Field = 9;<br />
36
```
37
</>
38
);
39
}
40
}
41
42
export class EditGenerationExampleSolution extends PromptElement {
43
render() {
44
return (
45
<>
46
The problem is that the class 'C' does not have a field or property named 'Field'. To fix this, you need to add a 'Field' property to the 'C' class.<br />
47
<br />
48
```diff<br />
49
// This is my class<br />
50
-class C &#123; &#125;<br />
51
+class C &#123;<br />
52
+ public int Field &#123; get; set; &#125;<br />
53
+&#125;<br />
54
<br />
55
new C().Field = 9;<br />
56
```<br />
57
</>
58
);
59
}
60
}
61
62
export interface ReplyProcessor {
63
getFirstSentence(text: string): string;
64
process(replyText: string, documentText: string, lineRange: LineRange): ReplyProcessorResult;
65
}
66
67
export type ReplyProcessorResult = { edits?: TextEdit[]; content?: string; annotations: OutcomeAnnotation[] };
68
69
export function getReplyProcessor(): ReplyProcessor {
70
return {
71
getFirstSentence(text: string): string {
72
return text.split('```', 1)[0].match(/^.+/)?.[0] ?? '';
73
},
74
process(replyText: string, documentText: string, lineRange: LineRange): ReplyProcessorResult {
75
const annotations: OutcomeAnnotation[] = [];
76
const extractResult = extractAndParseFirstCodeBlock(replyText);
77
if (!extractResult || extractResult.language === 'bash' || extractResult.language === 'ps1') {
78
return { content: replyText, annotations };
79
}
80
let lineEdits: LinesEdit[] = [];
81
if (extractResult.language === 'diff') {
82
const diff = Lines.fromString(extractResult.code);
83
const code = Lines.fromString(documentText);
84
const reporter = {
85
recovery: () => { },
86
warning(message: string) {
87
if (annotations.length === 0) {
88
annotations.push({ message: message, label: 'invalid diff', severity: 'error' });
89
}
90
}
91
};
92
lineEdits = createEditsFromPseudoDiff(code, diff, reporter);
93
} else {
94
lineEdits = [new LinesEdit(lineRange.firstLineIndex, lineRange.endLineIndex, Lines.fromString(extractResult.code))];
95
}
96
const edits = lineEdits.map(e => e.toTextEdit());
97
return { edits, annotations };
98
}
99
100
};
101
}
102
103
function extractAndParseFirstCodeBlock(text: string): { code: string; contentBeforeCode: string; language: string } | undefined {
104
const blocks = extractCodeBlocks(text);
105
const firstBlock = blocks.at(0);
106
if (firstBlock) {
107
const lines = splitLines(text);
108
return { code: firstBlock.code, contentBeforeCode: lines.slice(0, firstBlock.startLine).join('\n').trimEnd(), language: firstBlock.language };
109
}
110
return undefined;
111
}
112
113