Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
microsoft
GitHub Repository: microsoft/vscode
Path: blob/main/extensions/copilot/src/extension/renameSuggestions/node/renameSuggestionsPrompt.tsx
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 { PromptElement, PromptElementProps, PromptPiece, PromptSizing, SystemMessage, UserMessage } from '@vscode/prompt-tsx';
7
import type * as vscode from 'vscode';
8
import { TextDocumentSnapshot } from '../../../platform/editing/common/textDocumentSnapshot';
9
import { IEndpointProvider } from '../../../platform/endpoint/common/endpointProvider';
10
import { getLanguage } from '../../../util/common/languages';
11
import { SyncDescriptor } from '../../../util/vs/platform/instantiation/common/descriptors';
12
import { IInstantiationService } from '../../../util/vs/platform/instantiation/common/instantiation';
13
import { Selection } from '../../../vscodeTypes';
14
import { DefinitionAroundCursor, State as DefinitionAroundCursorState } from '../../prompt/node/definitionAroundCursor';
15
import { IDocumentContext } from '../../prompt/node/documentContext';
16
import { LegacySafetyRules } from '../../prompts/node/base/safetyRules';
17
import { DefinitionAtPosition, State as DefinitionAtPositionState } from '../../prompts/node/panel/definitionAtPosition';
18
19
type Props = PromptElementProps<{
20
21
/** Document rename happening in */
22
document: TextDocumentSnapshot;
23
24
/** Range corresponding to the symbol that's being renamed */
25
range: vscode.Range;
26
}>;
27
28
type State = {
29
defAtPositionState: DefinitionAtPositionState;
30
defAroundCursorState: DefinitionAroundCursorState | undefined;
31
};
32
33
export class RenameSuggestionsPrompt extends PromptElement<Props, State> {
34
35
private readonly _defAtPos: DefinitionAtPosition;
36
private _defAroundCursor: DefinitionAroundCursor | undefined;
37
38
constructor(
39
props: Props,
40
@IInstantiationService private readonly instaService: IInstantiationService,
41
@IEndpointProvider private readonly endpointProvider: IEndpointProvider,
42
) {
43
super(props);
44
45
const { document, range } = this.props;
46
47
this._defAtPos = instaService.createInstance(new SyncDescriptor(DefinitionAtPosition, [{ document, position: range.start }]));
48
}
49
50
override async prepare(sizing: PromptSizing, progress?: vscode.Progress<vscode.ChatResponseProgressPart | vscode.ChatResponseReferencePart> | undefined, token?: vscode.CancellationToken | undefined): Promise<State> {
51
52
const { document, range } = this.props;
53
54
const defState = await this._defAtPos.prepare();
55
56
const isDefinitionBeingRenamed = defState.k === 'found' && defState.definitions.some(def => def.excerptRange.contains(this.props.range));
57
58
if (!isDefinitionBeingRenamed) {
59
const endpointInfo = await this.endpointProvider.getChatEndpoint('copilot-fast');
60
const documentContext: IDocumentContext = {
61
document,
62
fileIndentInfo: undefined,
63
language: getLanguage(document.languageId),
64
wholeRange: range,
65
selection: new Selection(range.start, range.end),
66
};
67
this._defAroundCursor = this.instaService.createInstance(DefinitionAroundCursor, { documentContext, endpointInfo });
68
}
69
70
const state: State = {
71
defAtPositionState: defState,
72
defAroundCursorState: this._defAroundCursor ? await this._defAroundCursor.prepare(sizing) : undefined,
73
};
74
75
return state;
76
}
77
78
override render(state: State, sizing: PromptSizing): PromptPiece<any, any> | undefined {
79
80
const { document, range } = this.props;
81
82
const symbolName = document.getText(range);
83
84
const prefix = extractIdentifierPrefix(symbolName);
85
const instructionToKeepPrefix = prefix ? ` keeping prefix '${prefix}'` : '';
86
87
const renderedDef = this._defAtPos.render(state.defAtPositionState, sizing);
88
89
const renderedDefAroundCursor = state.defAroundCursorState !== undefined && this._defAroundCursor?.render(state.defAroundCursorState, sizing);
90
91
return (
92
<>
93
<SystemMessage>
94
You are a distinguished software engineer.<br />
95
<LegacySafetyRules />
96
You must reply with a JSON array of strings of at least four new names, e.g., `["first", "second", "third", "fourth"]`.<br />
97
You must respect existing naming conventions{instructionToKeepPrefix}.
98
</SystemMessage>
99
{renderedDefAroundCursor}
100
<UserMessage>
101
{renderedDef !== undefined && <>
102
{renderedDef}<br />
103
</>}
104
Think of the purpose of `{symbolName}` in the given code. Think of several names that reflect what `{symbolName}` is and what it does{instructionToKeepPrefix}. Follow existing naming conventions. Reply with a JSON array of strings of at least four new names for `{symbolName}`.
105
</UserMessage>
106
</>
107
);
108
}
109
}
110
111
/**
112
* Extracts the prefix of an identifier. The prefix is defined as the leading sequence of dots, dollar signs, and underscores.
113
*
114
* @param identifier - The identifier to extract the prefix from.
115
* @returns The prefix of the identifier, or undefined if no prefix is found.
116
*/
117
function extractIdentifierPrefix(identifier: string): string | undefined {
118
const prefix = identifier.match(/^([\\.\\$\\_]+)/)?.[0];
119
return prefix;
120
}
121
122