From b266ae40a5ccbbb1ec1cac523cd3eeb33bff3a4c Mon Sep 17 00:00:00 2001 From: luca cappa Date: Thu, 29 Feb 2024 10:28:15 -0800 Subject: [PATCH 01/10] #cpp chat variable --- Extension/package.json | 4 +- Extension/src/LanguageServer/client.ts | 16 +++++ Extension/src/LanguageServer/extension.ts | 78 ++++++++++++++++++++++- Extension/src/telemetry.ts | 14 ++++ 4 files changed, 110 insertions(+), 2 deletions(-) diff --git a/Extension/package.json b/Extension/package.json index d95c577d0c..8d0acf7e99 100644 --- a/Extension/package.json +++ b/Extension/package.json @@ -38,7 +38,9 @@ "Snippets" ], "enabledApiProposals": [ - "terminalDataWriteEvent" + "terminalDataWriteEvent", + "chatParticipant", + "chatVariableResolver" ], "capabilities": { "untrustedWorkspaces": { diff --git a/Extension/src/LanguageServer/client.ts b/Extension/src/LanguageServer/client.ts index 05a500ee50..6fc0519299 100644 --- a/Extension/src/LanguageServer/client.ts +++ b/Extension/src/LanguageServer/client.ts @@ -542,6 +542,14 @@ interface GetIncludesResult { includedFiles: string[]; } +export interface ChatContextResult { + language: string; + standardVersion: string; + compiler: string; + targetPlatform: string; + targetArchitecture: string; +} + // Requests const PreInitializationRequest: RequestType = new RequestType('cpptools/preinitialize'); const InitializationRequest: RequestType = new RequestType('cpptools/initialize'); @@ -562,6 +570,7 @@ const GoToDirectiveInGroupRequest: RequestType = new RequestType('cpptools/generateDoxygenComment'); const ChangeCppPropertiesRequest: RequestType = new RequestType('cpptools/didChangeCppProperties'); const IncludesRequest: RequestType = new RequestType('cpptools/getIncludes'); +const CppContextRequest: RequestType = new RequestType('cpptools/getChatContext'); // Notifications to the server const DidOpenNotification: NotificationType = new NotificationType('textDocument/didOpen'); @@ -792,6 +801,7 @@ export interface Client { setShowConfigureIntelliSenseButton(show: boolean): void; addTrustedCompiler(path: string): Promise; getIncludes(maxDepth: number): Promise; + getChatContext(): Promise; } export function createClient(workspaceFolder?: vscode.WorkspaceFolder): Client { @@ -2234,6 +2244,11 @@ export class DefaultClient implements Client { return this.languageClient.sendRequest(IncludesRequest, params); } + public async getChatContext(): Promise { + await this.ready; + return this.languageClient.sendRequest(CppContextRequest, null); + } + /** * a Promise that can be awaited to know when it's ok to proceed. * @@ -4114,4 +4129,5 @@ class NullClient implements Client { setShowConfigureIntelliSenseButton(show: boolean): void { } addTrustedCompiler(path: string): Promise { return Promise.resolve(); } getIncludes(): Promise { return Promise.resolve({} as GetIncludesResult); } + getChatContext(): Promise { return Promise.resolve({} as ChatContextResult); } } diff --git a/Extension/src/LanguageServer/extension.ts b/Extension/src/LanguageServer/extension.ts index 5c656ad6b7..cde6a8f6f5 100644 --- a/Extension/src/LanguageServer/extension.ts +++ b/Extension/src/LanguageServer/extension.ts @@ -20,7 +20,7 @@ import * as util from '../common'; import { getCrashCallStacksChannel } from '../logger'; 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'; @@ -248,6 +248,78 @@ export async function activate(): Promise { clients.timeTelemetryCollector.setFirstFile(activeEditor.document.uri); activeDocument = activeEditor.document; } + + await setupCppChatVariable(util.extensionContext); +} + +export async function setupCppChatVariable(context: vscode.ExtensionContext | undefined): Promise +{ + if (!context) { + return; + } + + vscode.chat.registerChatVariableResolver('cpp', + `Describes the the C++ language features that can be used according + 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", + 'c23': "C23" }; + 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 }); + + 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 { @@ -1372,3 +1444,7 @@ export async function getIncludes(maxDepth: number): Promise { const includes = await clients.ActiveClient.getIncludes(maxDepth); return includes; } + +export async function getChatContext(): Promise { + return clients?.ActiveClient?.getChatContext() ?? undefined; +} diff --git a/Extension/src/telemetry.ts b/Extension/src/telemetry.ts index dc6a1c199f..bc48253e67 100644 --- a/Extension/src/telemetry.ts +++ b/Extension/src/telemetry.ts @@ -123,6 +123,20 @@ export function logLanguageServerEvent(eventName: string, properties?: Record, metrics?: Record): 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, From f75d9a2073d24e46a0af14ba43ca607fd4b771f0 Mon Sep 17 00:00:00 2001 From: Ben McMorran Date: Thu, 15 Aug 2024 15:31:00 -0700 Subject: [PATCH 02/10] Adapt to lmTool API --- Extension/package.json | 15 +++- Extension/src/LanguageServer/extension.ts | 80 ++------------------ Extension/src/LanguageServer/lmTool.ts | 90 +++++++++++++++++++++++ Extension/src/telemetry.ts | 4 +- 4 files changed, 110 insertions(+), 79 deletions(-) create mode 100644 Extension/src/LanguageServer/lmTool.ts diff --git a/Extension/package.json b/Extension/package.json index 8d0acf7e99..a20e2aa38f 100644 --- a/Extension/package.json +++ b/Extension/package.json @@ -39,8 +39,7 @@ ], "enabledApiProposals": [ "terminalDataWriteEvent", - "chatParticipant", - "chatVariableResolver" + "lmTools" ], "capabilities": { "untrustedWorkspaces": { @@ -6442,6 +6441,18 @@ "description": "%c_cpp.codeActions.refactor.extract.function.description%" } } + ], + "languageModelTools": [ + { + "id": "cpptools-lmtool-configuration", + "name": "cpp", + "displayName": "C/C++ configuration", + "canBeInvokedManually": true, + "userDescription": "Configuration of the active C or C++ file, like language standard version and target platform.", + "modelDescription": "For the active C or C++ file, this tool provides: the language (C, C++, or CUDA), the language standard version (such as C++11, C++14, C++17, or C++20), the compiler (such as GCC, Clang, or MSVC), the target platform (such as x86, x64, or ARM), and the target architecture (such as 32-bit or 64-bit).", + "icon": "$(file-code)", + "parametersSchema": {} + } ] }, "scripts": { diff --git a/Extension/src/LanguageServer/extension.ts b/Extension/src/LanguageServer/extension.ts index cde6a8f6f5..d88665d6f3 100644 --- a/Extension/src/LanguageServer/extension.ts +++ b/Extension/src/LanguageServer/extension.ts @@ -20,12 +20,13 @@ import * as util from '../common'; import { getCrashCallStacksChannel } from '../logger'; import { PlatformInformation } from '../platform'; import * as telemetry from '../telemetry'; -import { ChatContextResult, Client, DefaultClient, DoxygenCodeActionCommandArguments, openFileVersions } from './client'; +import { Client, DefaultClient, DoxygenCodeActionCommandArguments, openFileVersions } from './client'; import { ClientCollection } from './clientCollection'; import { CodeActionDiagnosticInfo, CodeAnalysisDiagnosticIdentifiersAndUri, codeAnalysisAllFixes, codeAnalysisCodeToFixes, codeAnalysisFileToCodeActions } from './codeAnalysis'; import { CppBuildTaskProvider } from './cppBuildTaskProvider'; import { getCustomConfigProviders } from './customProviders'; import { getLanguageConfig } from './languageConfig'; +import { CppConfigurationLanguageModelTool } from './lmTool'; import { PersistentState } from './persistentState'; import { NodeType, TreeNode } from './referencesModel'; import { CppSettings } from './settings'; @@ -249,77 +250,10 @@ export async function activate(): Promise { activeDocument = activeEditor.document; } - await setupCppChatVariable(util.extensionContext); -} - -export async function setupCppChatVariable(context: vscode.ExtensionContext | undefined): Promise -{ - if (!context) { - return; + if (util.extensionContext) { + const tool = vscode.lm.registerTool('cpptools-lmtool-configuration', new CppConfigurationLanguageModelTool(clients)); + disposables.push(tool); } - - vscode.chat.registerChatVariableResolver('cpp', - `Describes the the C++ language features that can be used according - 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", - 'c23': "C23" }; - 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 }); - - 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 { @@ -1444,7 +1378,3 @@ export async function getIncludes(maxDepth: number): Promise { const includes = await clients.ActiveClient.getIncludes(maxDepth); return includes; } - -export async function getChatContext(): Promise { - return clients?.ActiveClient?.getChatContext() ?? undefined; -} diff --git a/Extension/src/LanguageServer/lmTool.ts b/Extension/src/LanguageServer/lmTool.ts new file mode 100644 index 0000000000..c5f9563ce4 --- /dev/null +++ b/Extension/src/LanguageServer/lmTool.ts @@ -0,0 +1,90 @@ +/* -------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All Rights Reserved. + * See 'LICENSE' in the project root for license information. + * ------------------------------------------------------------------------------------------ */ +'use strict'; + +import * as vscode from 'vscode'; +import * as util from '../common'; +import * as telemetry from '../telemetry'; +import { ChatContextResult } from './client'; +import { ClientCollection } from './clientCollection'; + +const knownValues: { [Property in keyof ChatContextResult]?: { [id: string]: string } } = { + language: { + 'c': 'C', + 'cpp': 'C++', + 'cuda-cpp': 'CUDA C++', + }, + compiler: { + 'msvc': 'MSVC', + 'clang': 'Clang', + 'gcc': 'GCC', + }, + standardVersion: { + '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", + 'c23': "C23", + }, + targetPlatform: { + 'windows': 'Windows', + 'Linux': 'Linux', + 'macos': 'macOS', + }, +}; + +class StringLanguageModelToolResult implements vscode.LanguageModelToolResult +{ + public constructor(public readonly value: string) {} + public toString(): string { return this.value; } +} + +export class CppConfigurationLanguageModelTool implements vscode.LanguageModelTool +{ + public constructor(private readonly clients: ClientCollection) {} + + public async invoke(parameters: any, token: vscode.CancellationToken): Promise { + return new StringLanguageModelToolResult(await this.getContext()); + } + + private async getContext(): Promise { + const currentDoc = vscode.window.activeTextEditor?.document; + if (!currentDoc || (!util.isCpp(currentDoc) && !util.isHeaderFile(currentDoc.uri))) { + return 'The active document is not a C, C++, or CUDA file.'; + } + + const chatContext: ChatContextResult | undefined = await (this.clients?.ActiveClient?.getChatContext() ?? undefined); + if (!chatContext) { + return 'No configuration information is available for the active document.'; + } + + telemetry.logLanguageModelToolEvent( + 'cpp', + { + "language": chatContext.language, + "compiler": chatContext.compiler, + "standardVersion": chatContext.standardVersion, + "targetPlatform": chatContext.targetPlatform, + "targetArchitecture": chatContext.targetArchitecture + }); + + for (const key in knownValues) { + const knownKey = key as keyof ChatContextResult; + if (knownValues[knownKey] && chatContext[knownKey]) + { + chatContext[knownKey] = knownValues[knownKey][chatContext[knownKey]] || chatContext[knownKey]; + } + } + + return `The user is working on a ${chatContext.language} project. The project uses language version ${chatContext.standardVersion}, compiles using the ${chatContext.compiler} compiler, targets the ${chatContext.targetPlatform} platform, and targets the ${chatContext.targetArchitecture} architecture.`; + } +} diff --git a/Extension/src/telemetry.ts b/Extension/src/telemetry.ts index bc48253e67..600ffa4c45 100644 --- a/Extension/src/telemetry.ts +++ b/Extension/src/telemetry.ts @@ -123,10 +123,10 @@ export function logLanguageServerEvent(eventName: string, properties?: Record, metrics?: Record): void { +export function logLanguageModelToolEvent(eventName: string, properties?: Record, metrics?: Record): void { const sendTelemetry = () => { if (experimentationTelemetry) { - const eventNamePrefix: string = "C_Cpp/Copilot/Chat/Variable/"; + const eventNamePrefix: string = "C_Cpp/Copilot/Chat/Tool/"; experimentationTelemetry.sendTelemetryEvent(eventNamePrefix + eventName, properties, metrics); } }; From 5a46e601cc85dc438b2dd07b7039dde578178a06 Mon Sep 17 00:00:00 2001 From: Ben McMorran Date: Thu, 15 Aug 2024 15:49:03 -0700 Subject: [PATCH 03/10] Fix lint errors --- Extension/src/LanguageServer/lmTool.ts | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Extension/src/LanguageServer/lmTool.ts b/Extension/src/LanguageServer/lmTool.ts index c5f9563ce4..9e7d18b239 100644 --- a/Extension/src/LanguageServer/lmTool.ts +++ b/Extension/src/LanguageServer/lmTool.ts @@ -14,12 +14,12 @@ const knownValues: { [Property in keyof ChatContextResult]?: { [id: string]: str language: { 'c': 'C', 'cpp': 'C++', - 'cuda-cpp': 'CUDA C++', + 'cuda-cpp': 'CUDA C++' }, compiler: { 'msvc': 'MSVC', 'clang': 'Clang', - 'gcc': 'GCC', + 'gcc': 'GCC' }, standardVersion: { 'c++98': 'C++98', @@ -33,13 +33,13 @@ const knownValues: { [Property in keyof ChatContextResult]?: { [id: string]: str 'c99': "C99", 'c11': "C11", 'c17': "C17", - 'c23': "C23", + 'c23': "C23" }, targetPlatform: { 'windows': 'Windows', 'Linux': 'Linux', - 'macos': 'macOS', - }, + 'macos': 'macOS' + } }; class StringLanguageModelToolResult implements vscode.LanguageModelToolResult @@ -52,7 +52,7 @@ export class CppConfigurationLanguageModelTool implements vscode.LanguageModelTo { public constructor(private readonly clients: ClientCollection) {} - public async invoke(parameters: any, token: vscode.CancellationToken): Promise { + public async invoke(_parameters: any, _token: vscode.CancellationToken): Promise { return new StringLanguageModelToolResult(await this.getContext()); } From ed2145638e20879cd8ecc5974691d073e6596c9c Mon Sep 17 00:00:00 2001 From: Ben McMorran Date: Thu, 15 Aug 2024 17:17:50 -0700 Subject: [PATCH 04/10] Address PR comments --- Extension/package.json | 4 +- Extension/package.nls.json | 4 +- Extension/src/LanguageServer/client.ts | 20 ++- Extension/src/LanguageServer/extension.ts | 2 +- Extension/src/LanguageServer/lmTool.ts | 12 +- Extension/src/LanguageServer/utils.ts | 209 +++++++++++----------- 6 files changed, 133 insertions(+), 118 deletions(-) diff --git a/Extension/package.json b/Extension/package.json index a20e2aa38f..cad51c4dd2 100644 --- a/Extension/package.json +++ b/Extension/package.json @@ -6446,9 +6446,9 @@ { "id": "cpptools-lmtool-configuration", "name": "cpp", - "displayName": "C/C++ configuration", + "displayName": "%c_cpp.languageModelTools.configuration.displayName%", "canBeInvokedManually": true, - "userDescription": "Configuration of the active C or C++ file, like language standard version and target platform.", + "userDescription": "%c_cpp.languageModelTools.configuration.userDescription%", "modelDescription": "For the active C or C++ file, this tool provides: the language (C, C++, or CUDA), the language standard version (such as C++11, C++14, C++17, or C++20), the compiler (such as GCC, Clang, or MSVC), the target platform (such as x86, x64, or ARM), and the target architecture (such as 32-bit or 64-bit).", "icon": "$(file-code)", "parametersSchema": {} diff --git a/Extension/package.nls.json b/Extension/package.nls.json index 2768013971..7f784f7c99 100644 --- a/Extension/package.nls.json +++ b/Extension/package.nls.json @@ -1006,5 +1006,7 @@ "c_cpp.configuration.refactoring.includeHeader.markdownDescription": "Controls whether to include the header file of a refactored function/symbol to its corresponding source file when doing a refactoring action, such as create declaration/definition.", "c_cpp.configuration.refactoring.includeHeader.always.description": "Always include the header file if it is not included explicitly in its source file.", "c_cpp.configuration.refactoring.includeHeader.ifNeeded.description": "Only include the header file if it is not included explicitly in its source file or through implicit inclusion.", - "c_cpp.configuration.refactoring.includeHeader.never.description": "Never include the header file." + "c_cpp.configuration.refactoring.includeHeader.never.description": "Never include the header file.", + "c_cpp.languageModelTools.configuration.displayName": "C/C++ configuration", + "c_cpp.languageModelTools.configuration.userDescription": "Configuration of the active C or C++ file, like language standard version and target platform." } diff --git a/Extension/src/LanguageServer/client.ts b/Extension/src/LanguageServer/client.ts index 6fc0519299..b72de58ad2 100644 --- a/Extension/src/LanguageServer/client.ts +++ b/Extension/src/LanguageServer/client.ts @@ -63,7 +63,7 @@ import * as refs from './references'; import { CppSettings, OtherSettings, SettingsParams, WorkspaceFolderSettingsParams } from './settings'; import { SettingsTracker } from './settingsTracker'; import { ConfigurationType, LanguageStatusUI, getUI } from './ui'; -import { handleChangedFromCppToC, makeLspRange, makeVscodeLocation, makeVscodeRange } from './utils'; +import { handleChangedFromCppToC, makeLspRange, makeVscodeLocation, makeVscodeRange, withCancellation } from './utils'; import minimatch = require("minimatch"); function deepCopy(obj: any) { @@ -801,7 +801,7 @@ export interface Client { setShowConfigureIntelliSenseButton(show: boolean): void; addTrustedCompiler(path: string): Promise; getIncludes(maxDepth: number): Promise; - getChatContext(): Promise; + getChatContext(token: vscode.CancellationToken): Promise; } export function createClient(workspaceFolder?: vscode.WorkspaceFolder): Client { @@ -2244,9 +2244,17 @@ export class DefaultClient implements Client { return this.languageClient.sendRequest(IncludesRequest, params); } - public async getChatContext(): Promise { - await this.ready; - return this.languageClient.sendRequest(CppContextRequest, null); + public async getChatContext(token: vscode.CancellationToken): Promise { + await withCancellation(this.ready, token); + const result = await this.languageClient.sendRequest(CppContextRequest, null, token); + + // sendRequest() won't throw on cancellation, but will return an + // unexpected object with an error code and message. + if (token.isCancellationRequested) { + throw new vscode.CancellationError(); + } + + return result; } /** @@ -4129,5 +4137,5 @@ class NullClient implements Client { setShowConfigureIntelliSenseButton(show: boolean): void { } addTrustedCompiler(path: string): Promise { return Promise.resolve(); } getIncludes(): Promise { return Promise.resolve({} as GetIncludesResult); } - getChatContext(): Promise { return Promise.resolve({} as ChatContextResult); } + getChatContext(token: vscode.CancellationToken): Promise { return Promise.resolve({} as ChatContextResult); } } diff --git a/Extension/src/LanguageServer/extension.ts b/Extension/src/LanguageServer/extension.ts index d88665d6f3..a4d7887093 100644 --- a/Extension/src/LanguageServer/extension.ts +++ b/Extension/src/LanguageServer/extension.ts @@ -251,7 +251,7 @@ export async function activate(): Promise { } if (util.extensionContext) { - const tool = vscode.lm.registerTool('cpptools-lmtool-configuration', new CppConfigurationLanguageModelTool(clients)); + const tool = vscode.lm.registerTool('cpptools-lmtool-configuration', new CppConfigurationLanguageModelTool()); disposables.push(tool); } } diff --git a/Extension/src/LanguageServer/lmTool.ts b/Extension/src/LanguageServer/lmTool.ts index 9e7d18b239..91d877f18c 100644 --- a/Extension/src/LanguageServer/lmTool.ts +++ b/Extension/src/LanguageServer/lmTool.ts @@ -8,7 +8,7 @@ import * as vscode from 'vscode'; import * as util from '../common'; import * as telemetry from '../telemetry'; import { ChatContextResult } from './client'; -import { ClientCollection } from './clientCollection'; +import { getClients } from './extension'; const knownValues: { [Property in keyof ChatContextResult]?: { [id: string]: string } } = { language: { @@ -50,19 +50,17 @@ class StringLanguageModelToolResult implements vscode.LanguageModelToolResult export class CppConfigurationLanguageModelTool implements vscode.LanguageModelTool { - public constructor(private readonly clients: ClientCollection) {} - - public async invoke(_parameters: any, _token: vscode.CancellationToken): Promise { - return new StringLanguageModelToolResult(await this.getContext()); + public async invoke(_parameters: any, token: vscode.CancellationToken): Promise { + return new StringLanguageModelToolResult(await this.getContext(token)); } - private async getContext(): Promise { + private async getContext(token: vscode.CancellationToken): Promise { const currentDoc = vscode.window.activeTextEditor?.document; if (!currentDoc || (!util.isCpp(currentDoc) && !util.isHeaderFile(currentDoc.uri))) { return 'The active document is not a C, C++, or CUDA file.'; } - const chatContext: ChatContextResult | undefined = await (this.clients?.ActiveClient?.getChatContext() ?? undefined); + const chatContext: ChatContextResult | undefined = await (getClients()?.ActiveClient?.getChatContext(token) ?? undefined); if (!chatContext) { return 'No configuration information is available for the active document.'; } diff --git a/Extension/src/LanguageServer/utils.ts b/Extension/src/LanguageServer/utils.ts index da3d29b693..4f4d1384b0 100644 --- a/Extension/src/LanguageServer/utils.ts +++ b/Extension/src/LanguageServer/utils.ts @@ -1,101 +1,108 @@ -/* -------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All Rights Reserved. - * See 'LICENSE' in the project root for license information. - * ------------------------------------------------------------------------------------------ */ -'use strict'; -import * as os from 'os'; -import * as vscode from 'vscode'; -import { Range } from 'vscode-languageclient'; -import { SessionState } from '../sessionState'; -import { Location, TextEdit } from './commonTypes'; -import { CppSettings } from './settings'; - -export function makeLspRange(vscRange: vscode.Range): Range { - return { - start: { line: vscRange.start.line, character: vscRange.start.character }, - end: { line: vscRange.end.line, character: vscRange.end.character } - }; -} - -export function makeVscodeRange(cpptoolsRange: Range): vscode.Range { - return new vscode.Range(cpptoolsRange.start.line, cpptoolsRange.start.character, cpptoolsRange.end.line, cpptoolsRange.end.character); -} - -export function makeVscodeLocation(cpptoolsLocation: Location): vscode.Location { - return new vscode.Location(vscode.Uri.parse(cpptoolsLocation.uri), makeVscodeRange(cpptoolsLocation.range)); -} - -export function makeVscodeTextEdits(cpptoolsTextEdits: TextEdit[]): vscode.TextEdit[] { - return cpptoolsTextEdits.map(textEdit => new vscode.TextEdit(makeVscodeRange(textEdit.range), textEdit.newText)); -} - -export function rangeEquals(range1: vscode.Range | Range, range2: vscode.Range | Range): boolean { - return range1.start.line === range2.start.line && range1.start.character === range2.start.character && - range1.end.line === range2.end.line && range1.end.character === range2.end.character; -} - -// Check this before attempting to switch a document from C to C++. -export function shouldChangeFromCToCpp(document: vscode.TextDocument): boolean { - if (document.fileName.endsWith(".C") || document.fileName.endsWith(".H")) { - const cppSettings: CppSettings = new CppSettings(); - if (cppSettings.autoAddFileAssociations) { - return !docsChangedFromCppToC.has(document.fileName); - } - // We could potentially add a new setting to enable switching to cpp even when files.associations isn't changed. - } - return false; -} - -// Call this before changing from C++ to C. -export function handleChangedFromCppToC(document: vscode.TextDocument): void { - if (shouldChangeFromCToCpp(document)) { - docsChangedFromCppToC.add(document.fileName); - } -} - -export function showInstallCompilerWalkthrough(): void { - // Because we need to conditionally enable/disable steps to alter their contents, - // we need to determine which step is actually visible. If the steps change, this - // logic will need to change to reflect them. - enum Step { - Activation = 'awaiting.activation', - NoCompilers = 'no.compilers.found', - Verify = 'verify.compiler' - } - - const step = (() => { - if (!SessionState.scanForCompilersDone.get()) { - return Step.Activation; - } else if (!SessionState.trustedCompilerFound.get()) { - return Step.NoCompilers; - } else { - return Step.Verify; - } - })(); - - const platform = (() => { - switch (os.platform()) { - case 'win32': return 'windows'; - case 'darwin': return 'mac'; - default: return 'linux'; - } - })(); - - const version = (platform === 'windows') ? SessionState.windowsVersion.get() : ''; - - const index = `ms-vscode.cpptools#${step}.${platform}${version}`; - - void vscode.commands.executeCommand( - 'workbench.action.openWalkthrough', - { category: 'ms-vscode.cpptools#cppWelcome', step: index }, - false) - // Run it twice for now because of VS Code bug #187958 - .then(() => vscode.commands.executeCommand( - "workbench.action.openWalkthrough", - { category: 'ms-vscode.cpptools#cppWelcome', step: index }, - false) - ); - return; -} - -const docsChangedFromCppToC: Set = new Set(); +/* -------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All Rights Reserved. + * See 'LICENSE' in the project root for license information. + * ------------------------------------------------------------------------------------------ */ +'use strict'; +import * as os from 'os'; +import * as vscode from 'vscode'; +import { Range } from 'vscode-languageclient'; +import { SessionState } from '../sessionState'; +import { Location, TextEdit } from './commonTypes'; +import { CppSettings } from './settings'; + +export function makeLspRange(vscRange: vscode.Range): Range { + return { + start: { line: vscRange.start.line, character: vscRange.start.character }, + end: { line: vscRange.end.line, character: vscRange.end.character } + }; +} + +export function makeVscodeRange(cpptoolsRange: Range): vscode.Range { + return new vscode.Range(cpptoolsRange.start.line, cpptoolsRange.start.character, cpptoolsRange.end.line, cpptoolsRange.end.character); +} + +export function makeVscodeLocation(cpptoolsLocation: Location): vscode.Location { + return new vscode.Location(vscode.Uri.parse(cpptoolsLocation.uri), makeVscodeRange(cpptoolsLocation.range)); +} + +export function makeVscodeTextEdits(cpptoolsTextEdits: TextEdit[]): vscode.TextEdit[] { + return cpptoolsTextEdits.map(textEdit => new vscode.TextEdit(makeVscodeRange(textEdit.range), textEdit.newText)); +} + +export function rangeEquals(range1: vscode.Range | Range, range2: vscode.Range | Range): boolean { + return range1.start.line === range2.start.line && range1.start.character === range2.start.character && + range1.end.line === range2.end.line && range1.end.character === range2.end.character; +} + +// Check this before attempting to switch a document from C to C++. +export function shouldChangeFromCToCpp(document: vscode.TextDocument): boolean { + if (document.fileName.endsWith(".C") || document.fileName.endsWith(".H")) { + const cppSettings: CppSettings = new CppSettings(); + if (cppSettings.autoAddFileAssociations) { + return !docsChangedFromCppToC.has(document.fileName); + } + // We could potentially add a new setting to enable switching to cpp even when files.associations isn't changed. + } + return false; +} + +// Call this before changing from C++ to C. +export function handleChangedFromCppToC(document: vscode.TextDocument): void { + if (shouldChangeFromCToCpp(document)) { + docsChangedFromCppToC.add(document.fileName); + } +} + +export function showInstallCompilerWalkthrough(): void { + // Because we need to conditionally enable/disable steps to alter their contents, + // we need to determine which step is actually visible. If the steps change, this + // logic will need to change to reflect them. + enum Step { + Activation = 'awaiting.activation', + NoCompilers = 'no.compilers.found', + Verify = 'verify.compiler' + } + + const step = (() => { + if (!SessionState.scanForCompilersDone.get()) { + return Step.Activation; + } else if (!SessionState.trustedCompilerFound.get()) { + return Step.NoCompilers; + } else { + return Step.Verify; + } + })(); + + const platform = (() => { + switch (os.platform()) { + case 'win32': return 'windows'; + case 'darwin': return 'mac'; + default: return 'linux'; + } + })(); + + const version = (platform === 'windows') ? SessionState.windowsVersion.get() : ''; + + const index = `ms-vscode.cpptools#${step}.${platform}${version}`; + + void vscode.commands.executeCommand( + 'workbench.action.openWalkthrough', + { category: 'ms-vscode.cpptools#cppWelcome', step: index }, + false) + // Run it twice for now because of VS Code bug #187958 + .then(() => vscode.commands.executeCommand( + "workbench.action.openWalkthrough", + { category: 'ms-vscode.cpptools#cppWelcome', step: index }, + false) + ); + return; +} + +const docsChangedFromCppToC: Set = new Set(); + +export async function withCancellation(promise: Promise, token: vscode.CancellationToken): Promise { + return new Promise((resolve, reject) => { + token.onCancellationRequested(() => reject(new vscode.CancellationError())); + promise.then((value) => resolve(value), (reason) => reject(reason)); + }); +} From e46974488dae241b804411b69bd15e0a24139212 Mon Sep 17 00:00:00 2001 From: luca cappa Date: Thu, 5 Sep 2024 09:09:58 -0700 Subject: [PATCH 05/10] drop undefined return type, and apply suggested cancellation logic, format lmTools.ts --- Extension/src/LanguageServer/client.ts | 20 ++++++++++++++------ Extension/src/LanguageServer/lmTool.ts | 3 +-- 2 files changed, 15 insertions(+), 8 deletions(-) diff --git a/Extension/src/LanguageServer/client.ts b/Extension/src/LanguageServer/client.ts index b72de58ad2..ab8efb0bfe 100644 --- a/Extension/src/LanguageServer/client.ts +++ b/Extension/src/LanguageServer/client.ts @@ -27,7 +27,7 @@ import * as fs from 'fs'; import * as os from 'os'; import { SourceFileConfiguration, SourceFileConfigurationItem, Version, WorkspaceBrowseConfiguration } from 'vscode-cpptools'; import { IntelliSenseStatus, Status } from 'vscode-cpptools/out/testApi'; -import { CloseAction, DidOpenTextDocumentParams, ErrorAction, LanguageClientOptions, NotificationType, Position, Range, RequestType, TextDocumentIdentifier, TextDocumentPositionParams } from 'vscode-languageclient'; +import { CloseAction, DidOpenTextDocumentParams, ErrorAction, LanguageClientOptions, NotificationType, Position, Range, RequestType, ResponseError, TextDocumentIdentifier, TextDocumentPositionParams } from 'vscode-languageclient'; import { LanguageClient, ServerOptions } from 'vscode-languageclient/node'; import * as nls from 'vscode-nls'; import { DebugConfigurationProvider } from '../Debugger/configurationProvider'; @@ -801,7 +801,7 @@ export interface Client { setShowConfigureIntelliSenseButton(show: boolean): void; addTrustedCompiler(path: string): Promise; getIncludes(maxDepth: number): Promise; - getChatContext(token: vscode.CancellationToken): Promise; + getChatContext(token: vscode.CancellationToken): Promise; } export function createClient(workspaceFolder?: vscode.WorkspaceFolder): Client { @@ -2244,12 +2244,20 @@ export class DefaultClient implements Client { return this.languageClient.sendRequest(IncludesRequest, params); } - public async getChatContext(token: vscode.CancellationToken): Promise { + public async getChatContext(token: vscode.CancellationToken): Promise { await withCancellation(this.ready, token); - const result = await this.languageClient.sendRequest(CppContextRequest, null, token); + let result: ChatContextResult; + try { + result = await this.languageClient.sendRequest(CppContextRequest, null, token); + } catch (e: any) { + // From + // RequestCancelled = -32800, ServerCancelled = -32802, + if (e instanceof ResponseError && (e.code === -32800 /*RequestCancelled*/ || e.code === -32802 /*ServerCancelled*/)) { + throw new vscode.CancellationError(); + } - // sendRequest() won't throw on cancellation, but will return an - // unexpected object with an error code and message. + throw e; + } if (token.isCancellationRequested) { throw new vscode.CancellationError(); } diff --git a/Extension/src/LanguageServer/lmTool.ts b/Extension/src/LanguageServer/lmTool.ts index 91d877f18c..65ac7d08cf 100644 --- a/Extension/src/LanguageServer/lmTool.ts +++ b/Extension/src/LanguageServer/lmTool.ts @@ -77,8 +77,7 @@ export class CppConfigurationLanguageModelTool implements vscode.LanguageModelTo for (const key in knownValues) { const knownKey = key as keyof ChatContextResult; - if (knownValues[knownKey] && chatContext[knownKey]) - { + if (knownValues[knownKey] && chatContext[knownKey]) { chatContext[knownKey] = knownValues[knownKey][chatContext[knownKey]] || chatContext[knownKey]; } } From 7105e65ab30f54e6d65b34b8faaec058288d0230 Mon Sep 17 00:00:00 2001 From: luca cappa Date: Thu, 5 Sep 2024 16:03:40 -0700 Subject: [PATCH 06/10] - register #cpp only upon expFeatures enabled. - dispose the token callback. - get rid of magic numbers with consts. --- Extension/src/LanguageServer/client.ts | 6 ++---- Extension/src/LanguageServer/extension.ts | 2 +- Extension/src/LanguageServer/utils.ts | 11 +++++++++-- 3 files changed, 12 insertions(+), 7 deletions(-) diff --git a/Extension/src/LanguageServer/client.ts b/Extension/src/LanguageServer/client.ts index ab8efb0bfe..736353a7fa 100644 --- a/Extension/src/LanguageServer/client.ts +++ b/Extension/src/LanguageServer/client.ts @@ -58,7 +58,7 @@ import { cachedEditorConfigSettings, getEditorConfigSettings } from './editorCon import { CppSourceStr, clients, configPrefix, updateLanguageConfigurations, usesCrashHandler, watchForCrashes } from './extension'; import { LocalizeStringParams, getLocaleId, getLocalizedString } from './localization'; import { PersistentFolderState, PersistentWorkspaceState } from './persistentState'; -import { createProtocolFilter } from './protocolFilter'; +import { RequestCancelled, ServerCancelled, createProtocolFilter } from './protocolFilter'; import * as refs from './references'; import { CppSettings, OtherSettings, SettingsParams, WorkspaceFolderSettingsParams } from './settings'; import { SettingsTracker } from './settingsTracker'; @@ -2250,9 +2250,7 @@ export class DefaultClient implements Client { try { result = await this.languageClient.sendRequest(CppContextRequest, null, token); } catch (e: any) { - // From - // RequestCancelled = -32800, ServerCancelled = -32802, - if (e instanceof ResponseError && (e.code === -32800 /*RequestCancelled*/ || e.code === -32802 /*ServerCancelled*/)) { + if (e instanceof ResponseError && (e.code === RequestCancelled || e.code === ServerCancelled)) { throw new vscode.CancellationError(); } diff --git a/Extension/src/LanguageServer/extension.ts b/Extension/src/LanguageServer/extension.ts index a4d7887093..470ca51fe5 100644 --- a/Extension/src/LanguageServer/extension.ts +++ b/Extension/src/LanguageServer/extension.ts @@ -250,7 +250,7 @@ export async function activate(): Promise { activeDocument = activeEditor.document; } - if (util.extensionContext) { + if (util.extensionContext && new CppSettings().experimentalFeatures) { const tool = vscode.lm.registerTool('cpptools-lmtool-configuration', new CppConfigurationLanguageModelTool()); disposables.push(tool); } diff --git a/Extension/src/LanguageServer/utils.ts b/Extension/src/LanguageServer/utils.ts index 4f4d1384b0..3e769ba065 100644 --- a/Extension/src/LanguageServer/utils.ts +++ b/Extension/src/LanguageServer/utils.ts @@ -102,7 +102,14 @@ const docsChangedFromCppToC: Set = new Set(); export async function withCancellation(promise: Promise, token: vscode.CancellationToken): Promise { return new Promise((resolve, reject) => { - token.onCancellationRequested(() => reject(new vscode.CancellationError())); - promise.then((value) => resolve(value), (reason) => reject(reason)); + const disposable = token.onCancellationRequested(() => reject(new vscode.CancellationError())); + promise.then((value) => { + disposable.dispose(); + resolve(value); + }, (reason) => + { + disposable.dispose(); + reject(reason); + }); }); } From 7c3ff32142c1f530609f56309a8b40d5944119d2 Mon Sep 17 00:00:00 2001 From: luca cappa Date: Fri, 6 Sep 2024 13:11:16 -0700 Subject: [PATCH 07/10] add a when: clause and report a error log entry on failures --- Extension/package.json | 3 +- Extension/src/LanguageServer/lmTool.ts | 66 +++++++++++++++++--------- 2 files changed, 46 insertions(+), 23 deletions(-) diff --git a/Extension/package.json b/Extension/package.json index cad51c4dd2..47dacea175 100644 --- a/Extension/package.json +++ b/Extension/package.json @@ -6451,7 +6451,8 @@ "userDescription": "%c_cpp.languageModelTools.configuration.userDescription%", "modelDescription": "For the active C or C++ file, this tool provides: the language (C, C++, or CUDA), the language standard version (such as C++11, C++14, C++17, or C++20), the compiler (such as GCC, Clang, or MSVC), the target platform (such as x86, x64, or ARM), and the target architecture (such as 32-bit or 64-bit).", "icon": "$(file-code)", - "parametersSchema": {} + "parametersSchema": {}, + "when": "(config.C_Cpp.experimentalFeatures =~ /^[eE]nabled$/)" } ] }, diff --git a/Extension/src/LanguageServer/lmTool.ts b/Extension/src/LanguageServer/lmTool.ts index 65ac7d08cf..b9d92d2b77 100644 --- a/Extension/src/LanguageServer/lmTool.ts +++ b/Extension/src/LanguageServer/lmTool.ts @@ -5,7 +5,9 @@ 'use strict'; import * as vscode from 'vscode'; +import { localize } from 'vscode-nls'; import * as util from '../common'; +import * as logger from '../logger'; import * as telemetry from '../telemetry'; import { ChatContextResult } from './client'; import { getClients } from './extension'; @@ -55,33 +57,53 @@ export class CppConfigurationLanguageModelTool implements vscode.LanguageModelTo } private async getContext(token: vscode.CancellationToken): Promise { - const currentDoc = vscode.window.activeTextEditor?.document; - if (!currentDoc || (!util.isCpp(currentDoc) && !util.isHeaderFile(currentDoc.uri))) { - return 'The active document is not a C, C++, or CUDA file.'; - } + try + { + const currentDoc = vscode.window.activeTextEditor?.document; + if (!currentDoc || (!util.isCpp(currentDoc) && !util.isHeaderFile(currentDoc.uri))) { + return 'The active document is not a C, C++, or CUDA file.'; + } - const chatContext: ChatContextResult | undefined = await (getClients()?.ActiveClient?.getChatContext(token) ?? undefined); - if (!chatContext) { - return 'No configuration information is available for the active document.'; - } + const chatContext: ChatContextResult | undefined = await (getClients()?.ActiveClient?.getChatContext(token) ?? undefined); + if (!chatContext) { + return 'No configuration information is available for the active document.'; + } - telemetry.logLanguageModelToolEvent( - 'cpp', - { - "language": chatContext.language, - "compiler": chatContext.compiler, - "standardVersion": chatContext.standardVersion, - "targetPlatform": chatContext.targetPlatform, - "targetArchitecture": chatContext.targetArchitecture - }); + telemetry.logLanguageModelToolEvent( + 'cpp', + { + "language": chatContext.language, + "compiler": chatContext.compiler, + "standardVersion": chatContext.standardVersion, + "targetPlatform": chatContext.targetPlatform, + "targetArchitecture": chatContext.targetArchitecture + }); - for (const key in knownValues) { - const knownKey = key as keyof ChatContextResult; - if (knownValues[knownKey] && chatContext[knownKey]) { - chatContext[knownKey] = knownValues[knownKey][chatContext[knownKey]] || chatContext[knownKey]; + for (const key in knownValues) { + const knownKey = key as keyof ChatContextResult; + if (knownValues[knownKey] && chatContext[knownKey]) { + chatContext[knownKey] = knownValues[knownKey][chatContext[knownKey]] || chatContext[knownKey]; + } } + + return `The user is working on a ${chatContext.language} project. The project uses language version ${chatContext.standardVersion}, compiles using the ${chatContext.compiler} compiler, targets the ${chatContext.targetPlatform} platform, and targets the ${chatContext.targetArchitecture} architecture.`; } + catch (e: any) + { + await this.reportError(); + return ""; + } + } - return `The user is working on a ${chatContext.language} project. The project uses language version ${chatContext.standardVersion}, compiles using the ${chatContext.compiler} compiler, targets the ${chatContext.targetPlatform} platform, and targets the ${chatContext.targetArchitecture} architecture.`; + private async reportError(): Promise + { + try + { + logger.getOutputChannelLogger().appendLine(localize("copilot.cppcontext.error", "Error while retrieving the #cpp context.")); + } + catch + { + // Intentionally swallow any exception. + } } } From 80b901361979fd5e111a492dbd752fd9829d0640 Mon Sep 17 00:00:00 2001 From: luca cappa Date: Fri, 6 Sep 2024 14:19:05 -0700 Subject: [PATCH 08/10] lint --- Extension/src/LanguageServer/utils.ts | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/Extension/src/LanguageServer/utils.ts b/Extension/src/LanguageServer/utils.ts index 3e769ba065..e8c8073ee1 100644 --- a/Extension/src/LanguageServer/utils.ts +++ b/Extension/src/LanguageServer/utils.ts @@ -31,7 +31,7 @@ export function makeVscodeTextEdits(cpptoolsTextEdits: TextEdit[]): vscode.TextE export function rangeEquals(range1: vscode.Range | Range, range2: vscode.Range | Range): boolean { return range1.start.line === range2.start.line && range1.start.character === range2.start.character && - range1.end.line === range2.end.line && range1.end.character === range2.end.character; + range1.end.line === range2.end.line && range1.end.character === range2.end.character; } // Check this before attempting to switch a document from C to C++. @@ -106,8 +106,7 @@ export async function withCancellation(promise: Promise, token: vscode.Can promise.then((value) => { disposable.dispose(); resolve(value); - }, (reason) => - { + }, (reason) => { disposable.dispose(); reject(reason); }); From 6afe49a1e1e620e6dbdb69b0cbcb87ef9213815d Mon Sep 17 00:00:00 2001 From: luca cappa Date: Fri, 6 Sep 2024 14:19:51 -0700 Subject: [PATCH 09/10] fix the settings.json lint to use the standard one --- Extension/.vscode/settings.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Extension/.vscode/settings.json b/Extension/.vscode/settings.json index 969f4c40dc..7c60adca74 100644 --- a/Extension/.vscode/settings.json +++ b/Extension/.vscode/settings.json @@ -37,7 +37,7 @@ }, "[typescript]": { "editor.tabSize": 4, - "editor.defaultFormatter": "dbaeumer.vscode-eslint", + "editor.defaultFormatter": "vscode.typescript-language-features", "editor.formatOnSave": true, "files.insertFinalNewline": true, "editor.codeActionsOnSave": { From f9be6619f7c2a32326335847e71063022e19a0ff Mon Sep 17 00:00:00 2001 From: luca cappa Date: Fri, 6 Sep 2024 14:21:51 -0700 Subject: [PATCH 10/10] more linting --- Extension/src/LanguageServer/lmTool.ts | 23 ++++++++--------------- 1 file changed, 8 insertions(+), 15 deletions(-) diff --git a/Extension/src/LanguageServer/lmTool.ts b/Extension/src/LanguageServer/lmTool.ts index b9d92d2b77..f643c63714 100644 --- a/Extension/src/LanguageServer/lmTool.ts +++ b/Extension/src/LanguageServer/lmTool.ts @@ -44,21 +44,18 @@ const knownValues: { [Property in keyof ChatContextResult]?: { [id: string]: str } }; -class StringLanguageModelToolResult implements vscode.LanguageModelToolResult -{ - public constructor(public readonly value: string) {} +class StringLanguageModelToolResult implements vscode.LanguageModelToolResult { + public constructor(public readonly value: string) { } public toString(): string { return this.value; } } -export class CppConfigurationLanguageModelTool implements vscode.LanguageModelTool -{ +export class CppConfigurationLanguageModelTool implements vscode.LanguageModelTool { public async invoke(_parameters: any, token: vscode.CancellationToken): Promise { return new StringLanguageModelToolResult(await this.getContext(token)); } private async getContext(token: vscode.CancellationToken): Promise { - try - { + try { const currentDoc = vscode.window.activeTextEditor?.document; if (!currentDoc || (!util.isCpp(currentDoc) && !util.isHeaderFile(currentDoc.uri))) { return 'The active document is not a C, C++, or CUDA file.'; @@ -88,21 +85,17 @@ export class CppConfigurationLanguageModelTool implements vscode.LanguageModelTo return `The user is working on a ${chatContext.language} project. The project uses language version ${chatContext.standardVersion}, compiles using the ${chatContext.compiler} compiler, targets the ${chatContext.targetPlatform} platform, and targets the ${chatContext.targetArchitecture} architecture.`; } - catch (e: any) - { + catch { await this.reportError(); return ""; } } - private async reportError(): Promise - { - try - { + private async reportError(): Promise { + try { logger.getOutputChannelLogger().appendLine(localize("copilot.cppcontext.error", "Error while retrieving the #cpp context.")); } - catch - { + catch { // Intentionally swallow any exception. } }