Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add context to the Copilot Chat #12044

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion Extension/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,9 @@
"Snippets"
],
"enabledApiProposals": [
"terminalDataWriteEvent"
"terminalDataWriteEvent",
"chatParticipant",
"chatVariableResolver"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We will need approval to use these APIs before this PR can be approved.

],
"capabilities": {
"untrustedWorkspaces": {
Expand Down
16 changes: 16 additions & 0 deletions Extension/src/LanguageServer/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -536,6 +536,14 @@ interface DidChangeActiveEditorParams {
selection?: Range;
}

export interface ChatContextResult {
language: string;
standardVersion: string;
compiler: string;
targetPlatform: string;
targetArchitecture: string;
}

// Requests
const InitializationRequest: RequestType<CppInitializationParams, string, void> = new RequestType<CppInitializationParams, string, void>('cpptools/initialize');
const QueryCompilerDefaultsRequest: RequestType<QueryDefaultCompilerParams, configs.CompilerDefaults, void> = new RequestType<QueryDefaultCompilerParams, configs.CompilerDefaults, void>('cpptools/queryCompilerDefaults');
Expand All @@ -553,6 +561,7 @@ const ExtractToFunctionRequest: RequestType<ExtractToFunctionParams, WorkspaceEd
const GoToDirectiveInGroupRequest: RequestType<GoToDirectiveInGroupParams, Position | undefined, void> = new RequestType<GoToDirectiveInGroupParams, Position | undefined, void>('cpptools/goToDirectiveInGroup');
const GenerateDoxygenCommentRequest: RequestType<GenerateDoxygenCommentParams, GenerateDoxygenCommentResult | undefined, void> = new RequestType<GenerateDoxygenCommentParams, GenerateDoxygenCommentResult, void>('cpptools/generateDoxygenComment');
const ChangeCppPropertiesRequest: RequestType<CppPropertiesParams, void, void> = new RequestType<CppPropertiesParams, void, void>('cpptools/didChangeCppProperties');
const CppContextRequest: RequestType<void, ChatContextResult, void> = new RequestType<void, ChatContextResult, void>('cpptools/getChatContext');

// Notifications to the server
const DidOpenNotification: NotificationType<DidOpenTextDocumentParams> = new NotificationType<DidOpenTextDocumentParams>('textDocument/didOpen');
Expand Down Expand Up @@ -778,6 +787,7 @@ export interface Client {
getShowConfigureIntelliSenseButton(): boolean;
setShowConfigureIntelliSenseButton(show: boolean): void;
addTrustedCompiler(path: string): Promise<void>;
getChatContext(): Promise<ChatContextResult | undefined>;
}

export function createClient(workspaceFolder?: vscode.WorkspaceFolder): Client {
Expand Down Expand Up @@ -2187,6 +2197,11 @@ export class DefaultClient implements Client {
await this.languageClient.sendNotification(DidOpenNotification, params);
}

public async getChatContext(): Promise<ChatContextResult | undefined> {
await this.ready;
return this.languageClient.sendRequest(CppContextRequest, null);
}

/**
* a Promise that can be awaited to know when it's ok to proceed.
*
Expand Down Expand Up @@ -4007,4 +4022,5 @@ class NullClient implements Client {
getShowConfigureIntelliSenseButton(): boolean { return false; }
setShowConfigureIntelliSenseButton(show: boolean): void { }
addTrustedCompiler(path: string): Promise<void> { return Promise.resolve(); }
getChatContext(): Promise<ChatContextResult> { return Promise.resolve({} as ChatContextResult); }
}
78 changes: 77 additions & 1 deletion Extension/src/LanguageServer/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
import * as util from '../common';
import { PlatformInformation } from '../platform';
import * as telemetry from '../telemetry';
import { Client, DefaultClient, DoxygenCodeActionCommandArguments, openFileVersions } from './client';
import { ChatContextResult, Client, DefaultClient, DoxygenCodeActionCommandArguments, openFileVersions } from './client';
import { ClientCollection } from './clientCollection';
import { CodeActionDiagnosticInfo, CodeAnalysisDiagnosticIdentifiersAndUri, codeAnalysisAllFixes, codeAnalysisCodeToFixes, codeAnalysisFileToCodeActions } from './codeAnalysis';
import { CppBuildTaskProvider } from './cppBuildTaskProvider';
Expand Down Expand Up @@ -246,6 +246,78 @@
clients.timeTelemetryCollector.setFirstFile(activeEditor.document.uri);
activeDocument = activeEditor.document;
}

await setupCppChatVariable(util.extensionContext);
}

export async function setupCppChatVariable(context: vscode.ExtensionContext | undefined): Promise<void>
{
if (!context) {
return;
}

vscode.chat.registerChatVariableResolver('cpp',
lukka marked this conversation as resolved.
Show resolved Hide resolved
`Describes the the C++ language features that can be used according
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

duplicated word "the the"

to the following information: the C++ language standard version, the target architecture and target operating system.`, {
resolve: async (name, _context, _token) => {
function fixUpLanguage(languageId: string) {
const languageIdToLanguage: { [id: string]: string } =
{ 'c': 'C', 'cpp': 'C++', 'cuda-cpp': 'CUDA C++' };
return languageIdToLanguage[languageId] || languageId;
}

function fixUpCompiler(compilerId: string) {
const compilerIdToCompiler: { [id: string]: string } =
{ 'msvc': 'MSVC', 'clang': 'Clang', 'gcc': 'GCC' };
return compilerIdToCompiler[compilerId] || compilerId;
}

function fixUpStandardVersion(stdVerId: string) {
const stdVerIdToStdVer: { [id: string]: string } =
{ 'c++98': 'C++98', 'c++03': 'C++03', 'c++11': 'C++11', 'c++14': 'C++14', 'c++17': 'C++17',
'c++20': 'C++20', 'c++23': 'C++23', 'c90' : "C90", 'c99': "C99", 'c11': "C11", 'c17': "C17",

Check warning on line 278 in Extension/src/LanguageServer/extension.ts

View workflow job for this annotation

GitHub Actions / job / build

Expected indentation of 22 spaces but found 24

Check warning on line 278 in Extension/src/LanguageServer/extension.ts

View workflow job for this annotation

GitHub Actions / job / build

Expected indentation of 22 spaces but found 24

Check warning on line 278 in Extension/src/LanguageServer/extension.ts

View workflow job for this annotation

GitHub Actions / job / build

Expected indentation of 22 spaces but found 24
'c23': "C23" };

Check warning on line 279 in Extension/src/LanguageServer/extension.ts

View workflow job for this annotation

GitHub Actions / job / build

Expected indentation of 22 spaces but found 24

Check warning on line 279 in Extension/src/LanguageServer/extension.ts

View workflow job for this annotation

GitHub Actions / job / build

Expected indentation of 22 spaces but found 24

Check warning on line 279 in Extension/src/LanguageServer/extension.ts

View workflow job for this annotation

GitHub Actions / job / build

Expected indentation of 22 spaces but found 24
return stdVerIdToStdVer[stdVerId] || stdVerId;
}

function fixTargetPlatform(targetPlatformId: string) {
const platformIdToPlatform: { [id: string]: string } = { 'windows': 'Windows', 'Linux': 'Linux', 'macos': 'macOS' };
return platformIdToPlatform[targetPlatformId] || targetPlatformId;
}

if (name !== 'cpp') {
return undefined;
}

// Return undefined if the active document is not a C++/C/CUDA/Header file.
const currentDoc = vscode.window.activeTextEditor?.document;
if (!currentDoc || (!util.isCpp(currentDoc) && !util.isHeaderFile(currentDoc.uri))) {
return undefined;
}

const chatContext: ChatContextResult | undefined = await getChatContext();
if (!chatContext) {
return undefined;
}

telemetry.logCppChatVariableEvent('cpp',
{ "language": chatContext.language, "compiler": chatContext.compiler, "standardVersion": chatContext.standardVersion,
"targetPlatform": chatContext.targetPlatform, "targetArchitecture": chatContext.targetArchitecture });

Check warning on line 305 in Extension/src/LanguageServer/extension.ts

View workflow job for this annotation

GitHub Actions / job / build

Expected indentation of 22 spaces but found 24

Check warning on line 305 in Extension/src/LanguageServer/extension.ts

View workflow job for this annotation

GitHub Actions / job / build

Expected indentation of 22 spaces but found 24

Check warning on line 305 in Extension/src/LanguageServer/extension.ts

View workflow job for this annotation

GitHub Actions / job / build

Expected indentation of 22 spaces but found 24

const language = fixUpLanguage(chatContext.language);
const compiler = fixUpCompiler(chatContext.compiler);
const standardVersion = fixUpStandardVersion(chatContext.standardVersion);
const targetPlatform = fixTargetPlatform(chatContext.targetPlatform);
const value = `I am working on a project of the following nature:
- Using ${language}. Prefer a solution written in ${language} to any other language. Call out which language you are using in the answer.
- Using the ${language} standard language version ${standardVersion}. Prefer solutions using the new and more recent features introduced in ${standardVersion}. Call out which standard version you are using in the answer.
- Using the ${compiler} compiler. Prefer solutions supported by the ${compiler} compiler.
- Targeting the ${targetPlatform} platform. Prefer solutions and API that are supported on ${targetPlatform}.
- Targeting the ${chatContext.targetArchitecture} architecture. Prefer solutions and techniques that are supported on the ${chatContext.targetArchitecture} architecture.
`;
return [ { level: vscode.ChatVariableLevel.Full, value: value } ];
}
});
}

export function updateLanguageConfigurations(): void {
Expand Down Expand Up @@ -1305,3 +1377,7 @@
}
}
}

export async function getChatContext(): Promise<ChatContextResult | undefined> {
return clients?.ActiveClient?.getChatContext() ?? undefined;
}
14 changes: 14 additions & 0 deletions Extension/src/telemetry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,20 @@ export function logLanguageServerEvent(eventName: string, properties?: Record<st
sendTelemetry();
}

export function logCppChatVariableEvent(eventName: string, properties?: Record<string, string>, metrics?: Record<string, number>): void {
const sendTelemetry = () => {
if (experimentationTelemetry) {
const eventNamePrefix: string = "C_Cpp/Copilot/Chat/Variable/";
experimentationTelemetry.sendTelemetryEvent(eventNamePrefix + eventName, properties, metrics);
}
};

if (is.promise(initializationPromise)) {
return void initializationPromise.catch(logAndReturn.undefined).then(sendTelemetry).catch(logAndReturn.undefined);
}
sendTelemetry();
}

function getPackageInfo(): IPackageInfo {
return {
name: util.packageJson.publisher + "." + util.packageJson.name,
Expand Down
Loading