diff --git a/Extension/.scripts/installAndCopyBinaries.ts b/Extension/.scripts/installAndCopyBinaries.ts index 69f7f3b37..4eb6a4054 100644 --- a/Extension/.scripts/installAndCopyBinaries.ts +++ b/Extension/.scripts/installAndCopyBinaries.ts @@ -6,7 +6,7 @@ import { runVSCodeCommand } from '@vscode/test-electron'; import { writeFile } from 'node:fs/promises'; import { join } from 'node:path'; -import { $root, error, heading, note } from './common'; +import { $root, error, heading, note, warn } from './common'; import * as copy from './copyExtensionBinaries'; import { install, isolated, options } from "./vscode"; @@ -24,7 +24,9 @@ export async function main() { console.log(result.stdout.toString()); } if (result.stderr) { - error(result.stderr.toString()); + // runVSCodeCommand resolves only when the command succeeds (it throws on a non-zero exit), so stderr here is + // non-fatal output such as Node deprecation warnings and must not be reported as an error. + warn(result.stderr.toString()); } const binaryVersion = await copy.main(isolated); diff --git a/Extension/.scripts/test.ts b/Extension/.scripts/test.ts index 033d7010c..300963684 100644 --- a/Extension/.scripts/test.ts +++ b/Extension/.scripts/test.ts @@ -27,6 +27,7 @@ const filters = [ /^Unexpected token A/, /Cannot register 'cmake.cmakePath'/, /\[DEP0005\] DeprecationWarning/, + /\[DEP0169\] DeprecationWarning/, /--trace-deprecation/, /Iconv-lite warning/, /^Extension '/, diff --git a/Extension/.scripts/vscode.ts b/Extension/.scripts/vscode.ts index 9be75a371..de22ac20b 100644 --- a/Extension/.scripts/vscode.ts +++ b/Extension/.scripts/vscode.ts @@ -15,7 +15,12 @@ export const extensionsDir = resolve(isolated, 'extensions'); export const userDir = resolve(isolated, 'user-data'); export const settings = resolve(userDir, "User", 'settings.json'); +// Pin the test VS Code build to a known-good stable release for deterministic CI instead of +// always pulling latest. Launching macOS 1.110+ builds requires @vscode/test-electron >= 3.1.0. +export const testVSCodeVersion = '1.131.0'; + export const options = { + version: testVSCodeVersion, cachePath: `${isolated}/cache`, launchArgs: ['--no-sandbox', '--disable-updates', '--skip-welcome', '--skip-release-notes', '--disable-extensions', `--extensions-dir=${extensionsDir}`, `--user-data-dir=${userDir}`, '--disable-workspace-trust'] }; diff --git a/Extension/CHANGELOG.md b/Extension/CHANGELOG.md index 6fc5b98be..c0e8bbe12 100644 --- a/Extension/CHANGELOG.md +++ b/Extension/CHANGELOG.md @@ -1,5 +1,16 @@ # C/C++ for Visual Studio Code Changelog +## Version 1.33.6: July 31, 2026 +### Bug Fixes +* Fix a spurious recursive includes (`**`) debug console log warning for paths merged from `c_cpp_properties.json` when `C_Cpp.mergeConfigurations` is enabled. [#14125](https://github.com/microsoft/vscode-cpptools/issues/14125) + * Thanks for the contribution. [@owevertonguedes (Weverton Guedes)](https://github.com/owevertonguedes) [PR #14620](https://github.com/microsoft/vscode-cpptools/pull/14620) +* Fix custom configurations being discarded when `C_Cpp.mergeConfigurations` is enabled and a provider supplies the file `uri` as a `vscode.Uri`. [#14621](https://github.com/microsoft/vscode-cpptools/issues/14621) + * Thanks for the contribution. [@owevertonguedes (Weverton Guedes)](https://github.com/owevertonguedes) [PR #14624](https://github.com/microsoft/vscode-cpptools/pull/14624) +* Fix potential browse database corruption when the same workspace is opened by multiple processes on Linux and macOS. +* Fix a crash when reading files saved in certain multibyte encodings such as GB18030 or EUC-JP. +* Fix an incorrect file path in an error message on Windows. +* Other potential crash fixes. + ## Version 1.33.5: July 28, 2026 ### Bug Fixes * Fix the remote process picker `ps` command not working with some shells. [#14442](https://github.com/microsoft/vscode-cpptools/issues/14442) diff --git a/Extension/package.json b/Extension/package.json index 1321404ff..dc6d5a98a 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.33.5-main", + "version": "1.33.6-main", "publisher": "ms-vscode", "icon": "LanguageCCPP_color_128x.png", "readme": "README.md", @@ -7203,7 +7203,7 @@ "@vscode/debugadapter": "^1.65.0", "@vscode/debugprotocol": "^1.65.0", "@vscode/dts": "^0.4.0", - "@vscode/test-electron": "^2.3.10", + "@vscode/test-electron": "^3.1.0", "@vscode/vsce": "^3.9.2", "async-child-process": "^1.1.1", "await-notify": "^1.0.1", diff --git a/Extension/src/LanguageServer/client.ts b/Extension/src/LanguageServer/client.ts index 133890cfa..8adbea339 100644 --- a/Extension/src/LanguageServer/client.ts +++ b/Extension/src/LanguageServer/client.ts @@ -1767,8 +1767,8 @@ export class DefaultClient implements Client { errorHandler: { error: (error, message, count) => { telemetry.logLanguageServerEvent("languageClientError", { - error: error.toString(), - message: message?.toString() ?? '', + clientError: error.toString(), + clientMessage: message?.toString() ?? '', count: count?.toString() ?? '' }); return { action: ErrorAction.Continue }; @@ -2328,7 +2328,35 @@ export class DefaultClient implements Client { if (configs && configs.length > 0 && configs[0]) { const fileConfiguration: configs.Configuration | undefined = this.configuration.CurrentConfiguration; if (fileConfiguration?.mergeConfigurations) { + // deepCopy is a JSON round trip, which a vscode.Uri does not survive. The copy is + // a plain object that is neither a string nor a Uri, so sendCustomConfigurations + // discards the item. The uri field also accepts a string, so normalize it into a + // new item before copying, without assigning into what the provider returned or + // calling a method on its array. + if (configs instanceof Array) { + const normalized: util.Mutable[] = []; + const count: number = configs.length; + for (let i: number = 0; i < count; ++i) { + const config: util.Mutable = configs[i]; + const uri = config?.uri; + normalized.push(util.isUri(uri) ? { uri: uri.toString(), configuration: config.configuration } : config); + } + configs = normalized; + } configs = deepCopy(configs); + } + // Only the include paths from the provider are checked for recursive includes, so + // this has to happen before the include paths from c_cpp_properties.json are + // appended below, where a trailing '**' is a supported way to recurse. + if (configs instanceof Array) { + configs.forEach(config => { + if (util.isArrayOfString(config?.configuration?.includePath) && + config.configuration.includePath.some(path => path.endsWith('**'))) { + console.warn("custom include paths should not use recursive includes ('**')"); + } + }); + } + if (fileConfiguration?.mergeConfigurations) { configs.forEach(config => { if (fileConfiguration.includePath) { fileConfiguration.includePath.forEach(p => { @@ -3457,9 +3485,6 @@ export class DefaultClient implements Client { this.configurationLogging.set(uri, JSON.stringify(item.configuration, null, 4)); out.appendLineAtLevel(6, ` uri: ${uri}`); out.appendLineAtLevel(6, ` config: ${JSON.stringify(item.configuration, null, 2)}`); - if (item.configuration.includePath.some(path => path.endsWith('**'))) { - console.warn("custom include paths should not use recursive includes ('**')"); - } // Separate compiler path and args before sending to language client const itemConfig: util.Mutable = deepCopy(item.configuration); if (util.isString(itemConfig.compilerPath)) { diff --git a/Extension/src/LanguageServer/extension.ts b/Extension/src/LanguageServer/extension.ts index 1f1d58477..e1857ba9e 100644 --- a/Extension/src/LanguageServer/extension.ts +++ b/Extension/src/LanguageServer/extension.ts @@ -38,7 +38,7 @@ import { CppConfigurationLanguageModelTool } from './lmTool'; import { getLocaleId } from './localization'; import { PersistentState } from './persistentState'; import { NodeType, TreeNode } from './referencesModel'; -import { CppSettings } from './settings'; +import { CppSettings, trackedSections } from './settings'; import { LanguageStatusUI, getUI } from './ui'; import { makeLspRange, rangeEquals, showInstallCompilerWalkthrough } from './utils'; @@ -293,7 +293,9 @@ export function updateLanguageConfigurations(): void { async function onDidChangeSettings(event: vscode.ConfigurationChangeEvent): Promise { clients.forEach(client => { if (client instanceof DefaultClient) { - void client.onDidChangeSettings(event).catch(logAndReturn.undefined); + if (trackedSections.some(section => event.affectsConfiguration(section, client.RootUri))) { + void client.onDidChangeSettings(event).catch(logAndReturn.undefined); + } } }); } diff --git a/Extension/src/LanguageServer/settings.ts b/Extension/src/LanguageServer/settings.ts index 71f6730bd..502144300 100644 --- a/Extension/src/LanguageServer/settings.ts +++ b/Extension/src/LanguageServer/settings.ts @@ -32,6 +32,10 @@ export interface Associations { [key: string]: string; } +// The settings sections that we provide accessors for. +// This is used to filter out settings changed events that do not impact the extension. +export const trackedSections: string[] = ['C_Cpp', 'editor', 'files', 'search', 'workbench']; + // Settings that can be undefined have default values assigned in the native code or are meant to return undefined. export interface WorkspaceFolderSettingsParams { uri: string | undefined; diff --git a/Extension/src/nativeStrings.json b/Extension/src/nativeStrings.json index d7cd154dd..66170d813 100644 --- a/Extension/src/nativeStrings.json +++ b/Extension/src/nativeStrings.json @@ -747,5 +747,13 @@ "check_timed_out": { "text": "timed out waiting for analysis of {0} to finish", "hint": "{0} is the source file path. {Locked=\"{0}\"}" + }, + "failed_to_open_browse_db_lock_file": { + "text": "Failed to open browse database lock file: {0} (errno={1})", + "hint": "{0} is the lock file path. {1} is the errno value. {Locked=\"{0}\"} {Locked=\"errno\"} {Locked=\"{1}\"}" + }, + "failed_to_lock_browse_db_lock_file": { + "text": "Failed to lock browse database lock file: {0} (errno={1})", + "hint": "{0} is the lock file path. {1} is the errno value. {Locked=\"{0}\"} {Locked=\"errno\"} {Locked=\"{1}\"}" } } diff --git a/Extension/yarn.lock b/Extension/yarn.lock index ed4fa4354..9fa5674fe 100644 --- a/Extension/yarn.lock +++ b/Extension/yarn.lock @@ -1055,10 +1055,10 @@ "@microsoft/1ds-post-js" "^4.3.4" "@microsoft/applicationinsights-web-basic" "^3.3.4" -"@vscode/test-electron@^2.3.10": - version "2.5.2" - resolved "https://pkgs.dev.azure.com/azure-public/VisualCpp/_packaging/cpp_PublicPackages/npm/registry/@vscode/test-electron/-/test-electron-2.5.2.tgz#f7d4078e8230ce9c94322f2a29cc16c17954085d" - integrity sha1-99QHjoIwzpyUMi8qKcwWwXlUCF0= +"@vscode/test-electron@^3.1.0": + version "3.1.0" + resolved "https://pkgs.dev.azure.com/azure-public/VisualCpp/_packaging/cpp_PublicPackages/npm/registry/@vscode/test-electron/-/test-electron-3.1.0.tgz#46b93d118dcd3b3c89caae296a13f9a7f5eb63c5" + integrity sha1-Rrk9EY3NOzyJyq4pahP5p/XrY8U= dependencies: http-proxy-agent "^7.0.2" https-proxy-agent "^7.0.5" @@ -1744,13 +1744,6 @@ brace-expansion@^1.1.7: balanced-match "^1.0.0" concat-map "0.0.1" -brace-expansion@^5.0.2: - version "5.0.8" - resolved "https://pkgs.dev.azure.com/azure-public/VisualCpp/_packaging/cpp_PublicPackages/npm/registry/brace-expansion/-/brace-expansion-5.0.8.tgz#135ad0d8d808eb18eb5e0ec9a21f3a0b92ef18cf" - integrity sha1-E1rQ2NgI6xjrXg7Joh86C5LvGM8= - dependencies: - balanced-match "^4.0.2" - brace-expansion@^2.0.1: version "2.1.2" resolved "https://pkgs.dev.azure.com/azure-public/VisualCpp/_packaging/cpp_PublicPackages/npm/registry/brace-expansion/-/brace-expansion-2.1.2.tgz#0bba2271feb7d458b0d31ad13625aaa4754431e2" @@ -1758,6 +1751,13 @@ brace-expansion@^2.0.1: dependencies: balanced-match "^1.0.0" +brace-expansion@^5.0.2: + version "5.0.8" + resolved "https://pkgs.dev.azure.com/azure-public/VisualCpp/_packaging/cpp_PublicPackages/npm/registry/brace-expansion/-/brace-expansion-5.0.8.tgz#135ad0d8d808eb18eb5e0ec9a21f3a0b92ef18cf" + integrity sha1-E1rQ2NgI6xjrXg7Joh86C5LvGM8= + dependencies: + balanced-match "^4.0.2" + braces@^3.0.3, braces@~3.0.2: version "3.0.3" resolved "https://pkgs.dev.azure.com/azure-public/VisualCpp/_packaging/cpp_PublicPackages/npm/registry/braces/-/braces-3.0.3.tgz#490332f40919452272d55a8480adc0c441358789"