This commit is contained in:
Ben McMorran 2024-08-15 17:17:50 -07:00
Родитель 366e3f5af5
Коммит 76ec4f7ea6
6 изменённых файлов: 133 добавлений и 118 удалений

Просмотреть файл

@ -6464,9 +6464,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": {}

Просмотреть файл

@ -1013,5 +1013,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."
}

Просмотреть файл

@ -61,7 +61,7 @@ import * as refs from './references';
import { CppSettings, OtherSettings, SettingsParams, WorkspaceFolderSettingsParams, getEditorConfigSettings } 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) {
@ -799,7 +799,7 @@ export interface Client {
setShowConfigureIntelliSenseButton(show: boolean): void;
addTrustedCompiler(path: string): Promise<void>;
getIncludes(maxDepth: number): Promise<GetIncludesResult>;
getChatContext(): Promise<ChatContextResult | undefined>;
getChatContext(token: vscode.CancellationToken): Promise<ChatContextResult | undefined>;
}
export function createClient(workspaceFolder?: vscode.WorkspaceFolder): Client {
@ -2214,9 +2214,17 @@ export class DefaultClient implements Client {
return this.languageClient.sendRequest(IncludesRequest, params);
}
public async getChatContext(): Promise<ChatContextResult | undefined> {
await this.ready;
return this.languageClient.sendRequest(CppContextRequest, null);
public async getChatContext(token: vscode.CancellationToken): Promise<ChatContextResult | undefined> {
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;
}
/**
@ -4099,5 +4107,5 @@ class NullClient implements Client {
setShowConfigureIntelliSenseButton(show: boolean): void { }
addTrustedCompiler(path: string): Promise<void> { return Promise.resolve(); }
getIncludes(): Promise<GetIncludesResult> { return Promise.resolve({} as GetIncludesResult); }
getChatContext(): Promise<ChatContextResult> { return Promise.resolve({} as ChatContextResult); }
getChatContext(token: vscode.CancellationToken): Promise<ChatContextResult> { return Promise.resolve({} as ChatContextResult); }
}

Просмотреть файл

@ -251,7 +251,7 @@ export async function activate(): Promise<void> {
}
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);
}
}

Просмотреть файл

@ -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<vscode.LanguageModelToolResult> {
return new StringLanguageModelToolResult(await this.getContext());
public async invoke(_parameters: any, token: vscode.CancellationToken): Promise<vscode.LanguageModelToolResult> {
return new StringLanguageModelToolResult(await this.getContext(token));
}
private async getContext(): Promise<string> {
private async getContext(token: vscode.CancellationToken): Promise<string> {
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.';
}

Просмотреть файл

@ -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<string> = new Set<string>();
/* --------------------------------------------------------------------------------------------
* 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<string> = new Set<string>();
export async function withCancellation<T>(promise: Promise<T>, token: vscode.CancellationToken): Promise<T> {
return new Promise<T>((resolve, reject) => {
token.onCancellationRequested(() => reject(new vscode.CancellationError()));
promise.then((value) => resolve(value), (reason) => reject(reason));
});
}