Path: blob/main/extensions/copilot/src/extension/renameSuggestions/node/renameSuggestionsPrompt.tsx
13399 views
/*---------------------------------------------------------------------------------------------1* Copyright (c) Microsoft Corporation. All rights reserved.2* Licensed under the MIT License. See License.txt in the project root for license information.3*--------------------------------------------------------------------------------------------*/45import { PromptElement, PromptElementProps, PromptPiece, PromptSizing, SystemMessage, UserMessage } from '@vscode/prompt-tsx';6import type * as vscode from 'vscode';7import { TextDocumentSnapshot } from '../../../platform/editing/common/textDocumentSnapshot';8import { IEndpointProvider } from '../../../platform/endpoint/common/endpointProvider';9import { getLanguage } from '../../../util/common/languages';10import { SyncDescriptor } from '../../../util/vs/platform/instantiation/common/descriptors';11import { IInstantiationService } from '../../../util/vs/platform/instantiation/common/instantiation';12import { Selection } from '../../../vscodeTypes';13import { DefinitionAroundCursor, State as DefinitionAroundCursorState } from '../../prompt/node/definitionAroundCursor';14import { IDocumentContext } from '../../prompt/node/documentContext';15import { LegacySafetyRules } from '../../prompts/node/base/safetyRules';16import { DefinitionAtPosition, State as DefinitionAtPositionState } from '../../prompts/node/panel/definitionAtPosition';1718type Props = PromptElementProps<{1920/** Document rename happening in */21document: TextDocumentSnapshot;2223/** Range corresponding to the symbol that's being renamed */24range: vscode.Range;25}>;2627type State = {28defAtPositionState: DefinitionAtPositionState;29defAroundCursorState: DefinitionAroundCursorState | undefined;30};3132export class RenameSuggestionsPrompt extends PromptElement<Props, State> {3334private readonly _defAtPos: DefinitionAtPosition;35private _defAroundCursor: DefinitionAroundCursor | undefined;3637constructor(38props: Props,39@IInstantiationService private readonly instaService: IInstantiationService,40@IEndpointProvider private readonly endpointProvider: IEndpointProvider,41) {42super(props);4344const { document, range } = this.props;4546this._defAtPos = instaService.createInstance(new SyncDescriptor(DefinitionAtPosition, [{ document, position: range.start }]));47}4849override async prepare(sizing: PromptSizing, progress?: vscode.Progress<vscode.ChatResponseProgressPart | vscode.ChatResponseReferencePart> | undefined, token?: vscode.CancellationToken | undefined): Promise<State> {5051const { document, range } = this.props;5253const defState = await this._defAtPos.prepare();5455const isDefinitionBeingRenamed = defState.k === 'found' && defState.definitions.some(def => def.excerptRange.contains(this.props.range));5657if (!isDefinitionBeingRenamed) {58const endpointInfo = await this.endpointProvider.getChatEndpoint('copilot-fast');59const documentContext: IDocumentContext = {60document,61fileIndentInfo: undefined,62language: getLanguage(document.languageId),63wholeRange: range,64selection: new Selection(range.start, range.end),65};66this._defAroundCursor = this.instaService.createInstance(DefinitionAroundCursor, { documentContext, endpointInfo });67}6869const state: State = {70defAtPositionState: defState,71defAroundCursorState: this._defAroundCursor ? await this._defAroundCursor.prepare(sizing) : undefined,72};7374return state;75}7677override render(state: State, sizing: PromptSizing): PromptPiece<any, any> | undefined {7879const { document, range } = this.props;8081const symbolName = document.getText(range);8283const prefix = extractIdentifierPrefix(symbolName);84const instructionToKeepPrefix = prefix ? ` keeping prefix '${prefix}'` : '';8586const renderedDef = this._defAtPos.render(state.defAtPositionState, sizing);8788const renderedDefAroundCursor = state.defAroundCursorState !== undefined && this._defAroundCursor?.render(state.defAroundCursorState, sizing);8990return (91<>92<SystemMessage>93You are a distinguished software engineer.<br />94<LegacySafetyRules />95You must reply with a JSON array of strings of at least four new names, e.g., `["first", "second", "third", "fourth"]`.<br />96You must respect existing naming conventions{instructionToKeepPrefix}.97</SystemMessage>98{renderedDefAroundCursor}99<UserMessage>100{renderedDef !== undefined && <>101{renderedDef}<br />102</>}103Think 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}`.104</UserMessage>105</>106);107}108}109110/**111* Extracts the prefix of an identifier. The prefix is defined as the leading sequence of dots, dollar signs, and underscores.112*113* @param identifier - The identifier to extract the prefix from.114* @returns The prefix of the identifier, or undefined if no prefix is found.115*/116function extractIdentifierPrefix(identifier: string): string | undefined {117const prefix = identifier.match(/^([\\.\\$\\_]+)/)?.[0];118return prefix;119}120121122