Path: blob/main/extensions/copilot/src/extension/prompt/node/testExample.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, PromptReference, PromptSizing } from '@vscode/prompt-tsx';6import type { Progress } from 'vscode';7import { TextDocumentSnapshot } from '../../../platform/editing/common/textDocumentSnapshot';8import { IParserService } from '../../../platform/parser/node/parserService';9import { IWorkspaceService } from '../../../platform/workspace/common/workspaceService';10import { CancellationToken } from '../../../util/vs/base/common/cancellation';11import * as path from '../../../util/vs/base/common/path';12import { URI } from '../../../util/vs/base/common/uri';13import { ChatResponseProgressPart, Range } from '../../../vscodeTypes';14import { Tag } from '../../prompts/node/base/tag';15import { summarizeDocument } from '../../prompts/node/inline/summarizedDocument/summarizeDocumentHelpers';16import { CodeBlock } from '../../prompts/node/panel/safeElements';1718// Finds the file that is testing a given file. Uses the findFiles API and file name19// heuristics for this.2021export type TestExampleFile = {22kind: 'candidateTestFile' | 'anyTestFile';23testExampleFile: URI;24};2526type Props = PromptElementProps<TestExampleFile>;2728/**29* @remark Does NOT respected copilot-ignore. Parent element must make sure the URI is not copilot-ignored.30*/31export class TestExample extends PromptElement<Props> {3233constructor(34props: Props,35@IParserService private readonly parserService: IParserService,36@IWorkspaceService private readonly workspaceService: IWorkspaceService37) {38super(props);39}4041override async render(state: void, sizing: PromptSizing, progress?: Progress<ChatResponseProgressPart> | undefined, token?: CancellationToken | undefined) {4243const { kind, testExampleFile } = this.props;4445let testDocument: TextDocumentSnapshot;46try {47testDocument = await this.workspaceService.openTextDocumentAndSnapshot(testExampleFile);48} catch (e) {49return undefined;50}5152const codeExcerpt = await summarizeDocument(53this.parserService,54testDocument,55undefined,56new Range(0, 0, 0, 0),57sizing.tokenBudget58);5960const references = [new PromptReference(testExampleFile)];6162const workspaceOfTestFile = this.workspaceService.getWorkspaceFolders().find(folder => testExampleFile.path.startsWith(folder.path));63let pathToTestFile: string = testExampleFile.path;64if (workspaceOfTestFile !== undefined) {65pathToTestFile = path.relative(workspaceOfTestFile.path, testExampleFile.path);66// Convert the path separator to be platform-independent67pathToTestFile = pathToTestFile.split(path.sep).join('/');68}6970switch (kind) {71case 'candidateTestFile': {72return (73<Tag name='testExample' priority={this.props.priority}>74<references value={references} />75Excerpt of the existing test file at `{pathToTestFile}`:<br />76<CodeBlock uri={testExampleFile} code={codeExcerpt.text} languageId={codeExcerpt.languageId} /><br />77Because a test file exists: <br />78- Do not generate preambles, like imports, copyright headers etc.<br />79- Do generate code that can be appended to the existing test file.80</Tag>81);82}83case 'anyTestFile': {84return (85<Tag name='testExample' priority={this.props.priority}>86This is a sample test file:<br />87<CodeBlock uri={testExampleFile} code={codeExcerpt.text} languageId={codeExcerpt.languageId} />88</Tag>89);90}91}92}93}949596