diff --git a/Extension/CHANGELOG.md b/Extension/CHANGELOG.md index 8307759533..7bba868497 100644 --- a/Extension/CHANGELOG.md +++ b/Extension/CHANGELOG.md @@ -1,5 +1,13 @@ # C/C++ for Visual Studio Code Changelog +## Version 1.22.8: October 8, 2024 +### Bug Fixes +* Fix an issue with the 'Add #include' code action incorrectly using a relative path for a system include. [#12010](https://github.com/microsoft/vscode-cpptools/issues/12010) +* Fix an issue with lingering incorrect squiggles after an edit. [#12175](https://github.com/microsoft/vscode-cpptools/issues/12175) +* Fix an issue with clang-format/tidy version checks for some builds. [#12806](https://github.com/microsoft/vscode-cpptools/issues/12806) +* Revert/postpone changes related to recursive includes handling due to issues with some projects. +* Fix a memory leak. + ## Version 1.22.7: September 30, 2024 ### Enhancement * The .vsix and .js files are now signed. [#12725](https://github.com/microsoft/vscode-cpptools/issues/12725), [#12744](https://github.com/microsoft/vscode-cpptools/issues/12744) @@ -1377,7 +1385,7 @@ ## Version 0.29.0: July 15, 2020 ### New Features * Add Doxygen comment support (to tooltip display of hover, completion, and signature help). [#658](https://github.com/microsoft/vscode-cpptools/issues/658) - * The way comments are formatted is controlled by the `C_Cpp.simplifyStructuredComments` setting. + * The way comments are formatted is controlled by the `C_Cpp.simplifyStructuredComments` setting. * Auto-convert `.` to `->` when the type is a pointer. [#862](https://github.com/microsoft/vscode-cpptools/issues/862) * Switch to using the VS Code Semantic Tokens API for semantic colorization (works with remoting). [PR #5401](https://github.com/microsoft/vscode-cpptools/pull/5401), [#3932](https://github.com/microsoft/vscode-cpptools/issues/3932), [#3933](https://github.com/microsoft/vscode-cpptools/issues/3933), [#3942](https://github.com/microsoft/vscode-cpptools/issues/3942) * Add support for LogMessage Breakpoints for debug type `cppdbg`. [PR MIEngine#1013](https://github.com/microsoft/MIEngine/pull/1013) @@ -2082,7 +2090,7 @@ ## Version 0.16.1: March 30, 2018 * Fix random deadlock caused by logging code on Linux/Mac. [#1759](https://github.com/Microsoft/vscode-cpptools/issues/1759) * Fix compiler from `compileCommands` not being queried for includes/defines if `compilerPath` isn't set on Windows. [#1754](https://github.com/Microsoft/vscode-cpptools/issues/1754) -* Fix OSX `UseShellExecute` I/O bug. [#1756](https://github.com/Microsoft/vscode-cpptools/issues/1756) +* Fix OSX `UseShellExecute` I/O bug. [#1756](https://github.com/Microsoft/vscode-cpptools/issues/1756) * Invalidate partially unzipped files from package manager. [#1757](https://github.com/Microsoft/vscode-cpptools/issues/1757) ## Version 0.16.0: March 28, 2018 @@ -2426,4 +2434,4 @@ ## Version 0.5.0: April 14, 2016 * Usability and correctness bug fixes. -* Simplify installation experience. +* Simplify installation experience. \ No newline at end of file diff --git a/Extension/package.json b/Extension/package.json index ae53da9e9c..7ec7975b7a 100644 --- a/Extension/package.json +++ b/Extension/package.json @@ -2,7 +2,7 @@ "name": "cpptools", "displayName": "C/C++", "description": "C/C++ IntelliSense, debugging, and code browsing.", - "version": "1.22.7-main", + "version": "1.22.8-main", "publisher": "ms-vscode", "icon": "LanguageCCPP_color_128x.png", "readme": "README.md", diff --git a/Extension/src/LanguageServer/Providers/callHierarchyProvider.ts b/Extension/src/LanguageServer/Providers/callHierarchyProvider.ts index 0abb04a5d3..82bcf39efd 100644 --- a/Extension/src/LanguageServer/Providers/callHierarchyProvider.ts +++ b/Extension/src/LanguageServer/Providers/callHierarchyProvider.ts @@ -51,12 +51,6 @@ export interface CallHierarchyParams { interface CallHierarchyItemResult { item?: CallHierarchyItem; - - /** - * If a request is cancelled, `succeeded` will be undefined to indicate no result was returned. - * Therefore, object is not defined as optional on the language server. - */ - succeeded: boolean; } interface CallHierarchyCallsItem { @@ -137,16 +131,15 @@ export class CallHierarchyProvider implements vscode.CallHierarchyProvider { } throw e; } - cancellationTokenListener.dispose(); - requestCanceledListener.dispose(); + finally { + cancellationTokenListener.dispose(); + requestCanceledListener.dispose(); + } - if (cancelSource.token.isCancellationRequested || response.succeeded === undefined) { - // Return undefined instead of vscode.CancellationError to avoid the following error message from VS Code: - // "MISSING provider." - // TODO: per issue https://github.com/microsoft/vscode/issues/169698 vscode.CancellationError is expected, - // so when VS Code fixes the error use vscode.CancellationError again. - return undefined; - } else if (response.item === undefined) { + if (cancelSource.token.isCancellationRequested) { + throw new vscode.CancellationError(); + } + if (response.item === undefined) { return undefined; } @@ -154,8 +147,7 @@ export class CallHierarchyProvider implements vscode.CallHierarchyProvider { return this.makeVscodeCallHierarchyItem(response.item); } - public async provideCallHierarchyIncomingCalls(item: vscode.CallHierarchyItem, token: vscode.CancellationToken): - Promise { + public async provideCallHierarchyIncomingCalls(item: vscode.CallHierarchyItem, token: vscode.CancellationToken): Promise { await this.client.ready; workspaceReferences.cancelCurrentReferenceRequest(CancellationSender.NewRequest); @@ -215,8 +207,7 @@ export class CallHierarchyProvider implements vscode.CallHierarchyProvider { return result; } - public async provideCallHierarchyOutgoingCalls(item: vscode.CallHierarchyItem, token: vscode.CancellationToken): - Promise { + public async provideCallHierarchyOutgoingCalls(item: vscode.CallHierarchyItem, token: vscode.CancellationToken): Promise { const CallHierarchyCallsFromEvent: string = "CallHierarchyCallsFrom"; if (item === undefined) { this.logTelemetry(CallHierarchyCallsFromEvent, CallHierarchyRequestStatus.Failed); diff --git a/Extension/src/LanguageServer/Providers/findAllReferencesProvider.ts b/Extension/src/LanguageServer/Providers/findAllReferencesProvider.ts index 01b2dc18e2..ffdb1cf9e2 100644 --- a/Extension/src/LanguageServer/Providers/findAllReferencesProvider.ts +++ b/Extension/src/LanguageServer/Providers/findAllReferencesProvider.ts @@ -45,11 +45,12 @@ export class FindAllReferencesProvider implements vscode.ReferenceProvider { throw e; } } - - // Reset anything that can be cleared before processing the result. - workspaceReferences.resetProgressBar(); - cancellationTokenListener.dispose(); - requestCanceledListener.dispose(); + finally { + // Reset anything that can be cleared before processing the result. + workspaceReferences.resetProgressBar(); + cancellationTokenListener.dispose(); + requestCanceledListener.dispose(); + } // Process the result. if (cancelSource.token.isCancellationRequested || cancelled || (response && response.isCanceled)) { diff --git a/Extension/src/LanguageServer/Providers/renameProvider.ts b/Extension/src/LanguageServer/Providers/renameProvider.ts index 8a46d81c8c..ea93ba1c2b 100644 --- a/Extension/src/LanguageServer/Providers/renameProvider.ts +++ b/Extension/src/LanguageServer/Providers/renameProvider.ts @@ -57,11 +57,12 @@ export class RenameProvider implements vscode.RenameProvider { } throw e; } - - // Reset anything that can be cleared before processing the result. - workspaceReferences.resetProgressBar(); - workspaceReferences.resetReferences(); - requestCanceledListener.dispose(); + finally { + // Reset anything that can be cleared before processing the result. + workspaceReferences.resetProgressBar(); + workspaceReferences.resetReferences(); + requestCanceledListener.dispose(); + } // Process the result. if (cancelSource.token.isCancellationRequested || response.isCanceled) { diff --git a/Extension/src/LanguageServer/client.ts b/Extension/src/LanguageServer/client.ts index 2b1b8125b1..04dcaba701 100644 --- a/Extension/src/LanguageServer/client.ts +++ b/Extension/src/LanguageServer/client.ts @@ -529,7 +529,7 @@ interface GetIncludesParams { maxDepth: number; } -interface GetIncludesResult { +export interface GetIncludesResult { includedFiles: string[]; } diff --git a/Extension/src/LanguageServer/extension.ts b/Extension/src/LanguageServer/extension.ts index 5ed2159c79..47a7cd0342 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 { Client, DefaultClient, DoxygenCodeActionCommandArguments, GetIncludesResult, openFileVersions } from './client'; import { ClientCollection } from './clientCollection'; import { CodeActionDiagnosticInfo, CodeAnalysisDiagnosticIdentifiersAndUri, codeAnalysisAllFixes, codeAnalysisCodeToFixes, codeAnalysisFileToCodeActions } from './codeAnalysis'; import { CppBuildTaskProvider } from './cppBuildTaskProvider'; @@ -33,11 +33,22 @@ import { CppSettings } from './settings'; import { LanguageStatusUI, getUI } from './ui'; import { makeLspRange, rangeEquals, showInstallCompilerWalkthrough } from './utils'; +interface CopilotTrait { + name: string; + value: string; + includeInPrompt?: boolean; + promptTextOverride?: string; +} + interface CopilotApi { registerRelatedFilesProvider( providerId: { extensionId: string; languageId: string }, - callback: (uri: vscode.Uri, token: vscode.CancellationToken) => Promise<{ entries: vscode.Uri[]; traits?: { name: string; value: string }[] }> - ): vscode.Disposable; + callback: ( + uri: vscode.Uri, + context: { flags: Record }, + cancellationToken: vscode.CancellationToken + ) => Promise<{ entries: vscode.Uri[]; traits?: CopilotTrait[] }> + ): Disposable; } nls.config({ messageFormat: nls.MessageFormat.bundle, bundleFormat: nls.BundleFormat.standalone })(); @@ -270,8 +281,8 @@ export async function activate(): Promise { for (const languageId of ['c', 'cpp', 'cuda-cpp']) { api.registerRelatedFilesProvider( { extensionId: util.extensionContext.extension.id, languageId }, - async (_uri: vscode.Uri, token: vscode.CancellationToken) => - ({ entries: (await clients.ActiveClient.getIncludes(1, token))?.includedFiles.map(file => vscode.Uri.file(file)) ?? [] }) + async (_uri: vscode.Uri, _context: { flags: Record }, token: vscode.CancellationToken) => + ({ entries: (await getIncludesWithCancellation(1, token))?.includedFiles.map(file => vscode.Uri.file(file)) ?? [] }) ); } } catch { @@ -1402,13 +1413,28 @@ export async function preReleaseCheck(): Promise { } } -export async function getIncludes(maxDepth: number): Promise { - const tokenSource = new vscode.CancellationTokenSource(); - const includes = await clients.ActiveClient.getIncludes(maxDepth, tokenSource.token); - tokenSource.dispose(); +export async function getIncludesWithCancellation(maxDepth: number, token: vscode.CancellationToken): Promise { + const includes = await clients.ActiveClient.getIncludes(maxDepth, token); + const wksFolder = clients.ActiveClient.RootUri?.toString(); + + if (!wksFolder) { + return includes; + } + + includes.includedFiles = includes.includedFiles.filter(header => vscode.Uri.file(header).toString().startsWith(wksFolder)); return includes; } +async function getIncludes(maxDepth: number): Promise { + const tokenSource = new vscode.CancellationTokenSource(); + try { + const includes = await getIncludesWithCancellation(maxDepth, tokenSource.token); + return includes; + } finally { + tokenSource.dispose(); + } +} + async function getCopilotApi(): Promise { const copilotExtension = vscode.extensions.getExtension('github.copilot'); if (!copilotExtension) { diff --git a/Extension/src/LanguageServer/lmTool.ts b/Extension/src/LanguageServer/lmTool.ts index 6b986463e1..5951377b4e 100644 --- a/Extension/src/LanguageServer/lmTool.ts +++ b/Extension/src/LanguageServer/lmTool.ts @@ -46,8 +46,8 @@ const knownValues: { [Property in keyof ChatContextResult]?: { [id: string]: str const plainTextContentType = 'text/plain'; -export class CppConfigurationLanguageModelTool implements vscode.LanguageModelTool { - public async invoke(options: vscode.LanguageModelToolInvocationOptions, token: vscode.CancellationToken): Promise { +export class CppConfigurationLanguageModelTool implements vscode.LanguageModelTool { + public async invoke(options: vscode.LanguageModelToolInvocationOptions, token: vscode.CancellationToken): Promise { const result: vscode.LanguageModelToolResult = {}; if (options.requestedContentTypes.includes(plainTextContentType)) { result[plainTextContentType] = await this.getContext(token); diff --git a/Extension/src/LanguageServer/settings.ts b/Extension/src/LanguageServer/settings.ts index 5171f27793..8e8d6c0654 100644 --- a/Extension/src/LanguageServer/settings.ts +++ b/Extension/src/LanguageServer/settings.ts @@ -277,7 +277,6 @@ export class CppSettings extends Settings { if (cachedClangPath !== undefined) { return cachedClangPath; } - const clangStr: string = isFormat ? this.clangFormatStr : this.clangTidyStr; const clangName: string = isFormat ? this.clangFormatName : this.clangTidyName; const setCachedClangPath: (path: string) => void = isFormat ? setCachedClangFormatPath : setCachedClangTidyPath; const whichPath: string | null = which.sync(clangName, { nothrow: true }); @@ -290,20 +289,14 @@ export class CppSettings extends Settings { return undefined; } else { // Attempt to invoke both our own version of clang-* to see if we can successfully execute it, and to get its version. - let clangVersion: string; + let bundledVersion: string; try { - const exePath: string = getExtensionFilePath(`./LLVM/bin/${clangName}`); - const output: string[] = execSync(quote([exePath, '--version'])).toString().split(" "); - if (output.length < 3 || output[0] !== clangStr || output[1] !== "version" || !semver.valid(output[2])) { - if (output.length === 3) { - return path; - } - const versionIndex: number = output.findIndex((value: string) => value === "version"); - if (versionIndex < 0 || versionIndex + 1 >= output.length || !semver.valid(output[versionIndex + 1].trim())) { - return path; - } + const bundledPath: string = getExtensionFilePath(`./LLVM/bin/${clangName}`); + const output: string = execSync(quote([bundledPath, '--version'])).toString(); + bundledVersion = output.match(/(\d+\.\d+\.\d+)/)?.[1] ?? ""; + if (!semver.valid(bundledVersion)) { + return path; } - clangVersion = output[2]; } catch (e) { // Unable to invoke our own clang-*. Use the system installed clang-*. return path; @@ -311,8 +304,9 @@ export class CppSettings extends Settings { // Invoke the version on the system to compare versions. Use ours if it's more recent. try { - const output: string[] = execSync(`"${path}" --version`).toString().split(" "); - if (output.length < 3 || output[0] !== clangStr || output[1] !== "version" || semver.ltr(output[2], clangVersion)) { + const output: string = execSync(`"${path}" --version`).toString(); + const userVersion = output.match(/(\d+\.\d+\.\d+)/)?.[1] ?? ""; + if (semver.ltr(userVersion, bundledVersion)) { path = ""; setCachedClangPath(path); }