Compare commits

..
Author SHA1 Message Date
Sean McManus db29f1bb68 Merge remote-tracking branch 'origin/main' into seanmcm/integration 2026-08-11 19:29:09 +00:00
Sean McManus 53e9bdb245 Merge remote-tracking branch 'origin/main' into seanmcm/integration 2026-08-11 17:06:07 +00:00
Sean McManus 74af7ade30 Merge commit '79e58c61515b92ea5288e85500cc48bdfbb50df8' into seanmcm/integration 2026-08-11 02:08:34 +00:00
Sean McManus 79e58c6151 Lock localization literals 2026-08-11 01:34:01 +00:00
Sean McManus 52be722a32 Merge commit '639a0c7b08b1b2dfc521327072fb1ab492fe5ed7' into seanmcm/integration 2026-08-11 01:33:46 +00:00
Sean McManus 639a0c7b08 Validate Yarn lockfile selectors 2026-08-11 01:21:19 +00:00
Sean McManus eae53ddf84 Merge remote-tracking branch 'origin/main' into seanmcm/integration 2026-08-11 01:11:46 +00:00
Sean McManus a8d2b261ba Merge commit '12d2528b29f63b4674d90d6fb02771b0561bb0e1' into seanmcm/integration 2026-08-11 01:03:16 +00:00
Sean McManus 12d2528b29 Preserve Portuguese include literals 2026-08-11 01:01:54 +00:00
Sean McManus 61f51d1690 Merge commit 'a78136f85b76b8239a2ad846ebd04c64fb4cce1a' into seanmcm/integration 2026-08-11 00:49:13 +00:00
Sean McManus a78136f85b Merge remote-tracking branch 'origin/seanmcm/devbox2-wsl/agent4/fix-localization-translation-errors' into seanmcm/devbox2-wsl/agent4/fix-localization-translation-errors 2026-08-11 00:35:50 +00:00
Sean McManus b2ddb96611 Preserve Turkish check option literal 2026-08-11 00:35:02 +00:00
Sean McManus b7fcd42e88 Merge branch 'main' into seanmcm/devbox2-wsl/agent4/fix-localization-translation-errors 2026-08-10 17:30:53 -07:00
Sean McManus 1385e1e19f Fix localization translation errors 2026-08-11 00:20:31 +00:00
Sean McManus 282c176eb3 Merge remote-tracking branch 'origin/main' into seanmcm/integration 2026-08-10 23:53:36 +00:00
Sean McManus ac37abac12 Merge remote-tracking branch 'origin/main' into seanmcm/integration 2026-08-10 23:05:58 +00:00
Sean McManus 314495ef37 Merge commit '6112068ac68245da8bc0b015b9eb6ba4a55ed6d1' into seanmcm/integration 2026-08-10 23:01:17 +00:00
Sean McManus 6112068ac6 Use frozen lockfile for webpack install 2026-08-10 22:27:56 +00:00
Sean McManus 9564835dd8 Merge remote-tracking branch 'origin/main' into seanmcm/integration 2026-08-10 21:47:56 +00:00
Sean McManus b4afbe2672 Merge commit 'd6c9fd5559bba437babd466ed3dc5686a1d6b46f' into seanmcm/integration 2026-08-10 21:42:47 +00:00
Sean McManus d6c9fd5559 Update nanoid to 3.3.17 2026-08-10 19:59:13 +00:00
Sean McManus 75d458accb Merge remote-tracking branch 'origin/main' into seanmcm/integration 2026-08-10 18:24:12 +00:00
Sean McManus 8e81300a7c Merge commit '24831bc81adff860e046d8cc83d270307a8f3dc8' into seanmcm/integration 2026-08-10 17:46:38 +00:00
Sean McManus 24831bc81a Update js-yaml in remaining lockfiles 2026-08-10 15:28:58 +00:00
Sean McManus 6cb184c483 Merge remote-tracking branch 'origin/main' into seanmcm/integration 2026-08-10 14:37:43 +00:00
Sean McManus 53a3811743 Merge remote-tracking branch 'origin/main' into seanmcm/integration 2026-08-09 16:43:54 +00:00
Sean McManus f630fc4da9 Merge remote-tracking branch 'origin/main' into seanmcm/integration 2026-08-08 00:08:32 +00:00
Sean McManus a1a4bb0f5d Merge remote-tracking branch 'origin/main' into seanmcm/integration 2026-08-07 03:28:32 +00:00
Sean McManus 660abd601c Merge remote-tracking branch 'origin/main' into seanmcm/integration 2026-08-05 01:10:26 +00:00
Sean McManus c0ad99a76f Merge remote-tracking branch 'origin/main' into seanmcm/integration 2026-08-04 20:13:21 +00:00
Sean McManus bb288f7e1a Merge remote-tracking branch 'origin/main' into seanmcm/integration 2026-08-04 18:30:53 +00:00
Sean McManus 5ce4eaaf6a Merge remote-tracking branch 'origin/main' into seanmcm/integration 2026-08-04 17:01:25 +00:00
csigs c1a9d604ac Localization - Translated Strings 2026-08-04 07:16:05 +00:00
Sean McManus 038c742125 Merge remote-tracking branch 'origin/main' into seanmcm/integration 2026-08-03 17:08:43 -07:00
Sean McManus f9f1e55832 Merge remote-tracking branch 'origin/main' into seanmcm/integration 2026-08-03 14:19:31 -07:00
Sean McManus 32cb58fe87 Merge remote-tracking branch 'origin/main' into seanmcm/integration 2026-08-03 11:30:08 -07:00
Sean McManus b3e83d8b48 Merge remote-tracking branch 'origin/main' into seanmcm/integration 2026-08-03 09:26:38 -07:00
Sean McManus 9a1b479ced Merge branch 'seanmcm/updateIntelliSenseLocStringsPR757614' into seanmcm/integration 2026-08-03 08:25:29 -07:00
Sean McManus 8878f05a18 Merge branch 'main' into seanmcm/updateIntelliSenseLocStringsPR757614 2026-08-03 08:24:38 -07:00
Sean McManus 0b10e39fef Merge branch 'seanmcm/devbox2-wsl/agent9/fix-copy-binaries-tracked-files' into seanmcm/integration 2026-08-01 21:29:18 +00:00
Sean McManus 9b2644d614 Restore repo-tracked files after copying test binaries
The install/copy-binaries script rm -rf's and re-copies the installed extension's bin, debugAdapters, and LLVM folders. A few files under bin are checked into the repo (bin/cpp.hint and bin/messages/**/messages.json); the copy overwrote them with the installed extension's versions (differing line endings and/or content), leaving spurious local modifications that had to be reverted by hand. Restore any tracked files the copy changed so only the untracked binaries remain, and gitignore the generated bin/binaryVersion.json marker.
2026-08-01 21:03:34 +00:00
Sean McManus cdd5240e39 Merge remote-tracking branch 'origin/main' into seanmcm/integration 2026-07-31 03:33:53 +00:00
Sean McManus dd5f8f997c Merge branch 'main' into seanmcm/integration 2026-07-30 23:17:41 +00:00
Sean McManus dac32bc0c3 Merge branch 'main' into seanmcm/integration 2026-07-30 00:45:22 +00:00
Sean McManus 778ddbd6a3 Merge branch 'seanmcm/devbox2-wsl/agent6/bump-test-electron' into seanmcm/integration 2026-07-29 19:40:40 +00:00
Sean McManus 0bbd36695f Move test VS Code pin to 1.131.0
With @vscode/test-electron 3.1.0 the macOS 1.131.0 bundle launches correctly, so advance the pinned test VS Code from 1.130.0 to the current stable 1.131.0.
2026-07-29 17:15:16 +00:00
Sean McManus e962adaccc Bump @vscode/test-electron to 3.1.0 so tests launch VS Code >=1.110 on macOS
VS Code 1.110 renamed the macOS main binary from Contents/MacOS/Electron to the product name and later removed the compatibility symlink (microsoft/vscode#326502, 2026-07-20), so @vscode/test-electron <=3.0.0 — which hardcodes the Electron name — fails to launch downloaded stable builds on macOS with 'spawn .../Contents/MacOS/Electron ENOENT'. 3.1.0 resolves the executable from the bundle's Info.plist CFBundleExecutable (microsoft/vscode-test#348, #349), letting the tests track latest stable VS Code again without pinning.
2026-07-29 17:15:16 +00:00
Sean McManus f01ab4da97 Merge branch 'main' into seanmcm/integration 2026-07-28 21:55:42 +00:00
Sean McManus 9053d9fb0d Merge branch 'main' into seanmcm/integration 2026-07-28 11:13:29 +00:00
Sean McManus 56be5729fb Merge branch 'main' into seanmcm/integration 2026-07-27 23:12:25 +00:00
Sean McManus d8f8783035 Merge branch 'seanmcm/updateThirdPartyNotices' into seanmcm/integration 2026-07-27 22:26:57 +00:00
Sean McManus 6ab8203ce0 Update from review. 2026-07-27 22:25:12 +00:00
Sean McManus 6d33605e84 Merge branch 'seanmcm/updateThirdPartyNotices' into seanmcm/integration 2026-07-27 22:00:26 +00:00
Sean McManus 51b25d1e9e Merge branch 'main' into seanmcm/integration 2026-07-27 22:00:18 +00:00
Sean McManus 3ee7d16c6d Update ThirdPartyNotices.txt 2026-07-27 21:36:51 +00:00
Sean McManus 9bb8ee4409 Merge branch 'seanmcm/updateBraceExpansion' into seanmcm/integration 2026-07-27 18:40:43 +00:00
Sean McManus d57678108d Update brace-expansion. 2026-07-27 18:36:38 +00:00
Sean McManus 0a82449d66 Merge branch 'seanmcm/skipTerminateHandlerFrames' into seanmcm/integration 2026-07-26 21:46:31 +00:00
Sean McManus c412f7da71 Skip terminate_handler( frames. 2026-07-26 21:29:34 +00:00
Sean McManus 4113e00318 Merge branch 'seanmcm/fixEmptyUndefinedSignalInfo' into seanmcm/integration 2026-07-26 20:43:38 +00:00
Sean McManus 248c44bdbc Code review feedback. 2026-07-26 20:33:30 +00:00
Sean McManus 9db0aff845 Fix si_code=, si_addr=undefined. 2026-07-26 20:15:47 +00:00
Sean McManus 627a4622b0 Merge branch 'seanmcm/updateGitIgnore' into seanmcm/integration 2026-07-26 17:48:15 +00:00
Sean McManus c2b605399a Merge branch 'seanmcm/updateIntelliSenseStringAddJsonNewlines' into seanmcm/integration 2026-07-26 17:47:45 +00:00
Sean McManus 714b35123d Update IntelliSense loc strings for PR 757614. 2026-07-26 17:41:35 +00:00
Sean McManus ab6e93fa31 Undo the IntelliSense string change. 2026-07-26 17:34:34 +00:00
Sean McManus 8ccffc9e5b Merge branch 'main' into seanmcm/updateIntelliSenseStringAddJsonNewlines 2026-07-26 17:31:00 +00:00
Sean McManus 9a12ee6149 Update .gitignore for installed bin files. 2026-07-26 17:25:17 +00:00
Sean McManus bdd6a39e9d Merge branch 'main' into seanmcm/updateIntelliSenseStringAddJsonNewlines 2026-07-14 14:52:55 -07:00
Sean McManus b477243fef Add a new IntelliSense translation string and unify json newlines. 2026-07-13 04:40:53 -07:00
39 changed files with 374 additions and 294 deletions
+2 -2
View File
@@ -63,7 +63,7 @@ jobs:
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@5595ccaf912efad79be6eef63a5619ff05969be3 # v4.37.6
uses: github/codeql-action/init@f205ea1c3313d32999d8d6a48b4f6530d4437b38 # v4.37.4
with:
languages: ${{ matrix.language }}
build-mode: ${{ matrix.build-mode }}
@@ -91,7 +91,7 @@ jobs:
exit 1
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@5595ccaf912efad79be6eef63a5619ff05969be3 # v4.37.6
uses: github/codeql-action/analyze@f205ea1c3313d32999d8d6a48b4f6530d4437b38 # v4.37.4
with:
category: "/language:${{matrix.language}}"
+2 -7
View File
@@ -5,7 +5,7 @@
import * as fs from "fs";
import * as path from 'path';
import { parseString } from 'xml2js';
import { glob, mkdir, write } from './common';
import { mkdir, write } from './common';
export async function main() {
@@ -45,16 +45,11 @@ export async function main() {
const locFolderNames = fs.readdirSync(localizeRepoPath).filter(f => fs.lstatSync(path.join(localizeRepoPath, f)).isDirectory());
for (const locFolderName of locFolderNames) {
const lclPath = path.join(localizeRepoPath, locFolderName, "vc/vc/cpfeui.dll.lcl");
const languageInfo = languages.find(l => l.folderName === locFolderName);
if (!languageInfo) {
return;
}
const localePath = path.join(localizeRepoPath, locFolderName);
const lclPaths = await glob("vc/vc/cpfeui.dll.lcl", { cwd: localePath, nocase: true, nodir: true });
if (lclPaths.length !== 1) {
throw new Error(`Expected one cpfeui.dll.lcl under '${localePath}', found ${lclPaths.length}.`);
}
const lclPath = path.join(localePath, lclPaths[0]);
const languageId = languageInfo.id;
const outputLanguageFolder = path.join(cpptoolsRepoPath, "Extension/bin/messages", languageId);
const outputPath = path.join(outputLanguageFolder, "messages.json");
+71 -33
View File
@@ -1,55 +1,93 @@
# C/C++ for Visual Studio Code Changelog
## Version 1.33.8: August 17, 2026
## Version 1.33.7: August 11, 2026
### Bug Fixes
* Fix another crash when reading files saved in certain multibyte encodings such as GB18030 or EUC-JP.
* Fix newly created files not being associated with the correct configuration in the browse database.
* Fix the language server becoming unresponsive during browse database initialization.
* Fix stale diagnostics and missing code actions after editing visible headers.
* Fix `/ZW:nostdlib` not being processed correctly by IntelliSense.
* Update dependencies.
## Version 1.33.6: August 4, 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 a tag parser crash when a UTF-8 string literal is concatenated with a narrow string literal containing an invalid multibyte sequence.
* 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.
* Update dependencies.
## 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)
* Thanks for the contribution. [@HuzaifaAbdulRehman](https://github.com/HuzaifaAbdulRehman) [PR #14592](https://github.com/microsoft/vscode-cpptools/pull/14592)
* Fix a spurious IntelliSense error with class template argument deduction (CTAD). [#14453](https://github.com/microsoft/vscode-cpptools/issues/14453), [#14459](https://github.com/microsoft/vscode-cpptools/issues/14459), [#14504](https://github.com/microsoft/vscode-cpptools/issues/14504)
* Fix 'Run C/C++ File' not running the program in PowerShell when terminal shell integration is unavailable. [#14583](https://github.com/microsoft/vscode-cpptools/issues/14583)
* Thanks for the contribution. [@owevertonguedes (Weverton Guedes)](https://github.com/owevertonguedes) [PR #14585](https://github.com/microsoft/vscode-cpptools/pull/14585)
* Fix the build tools walkthrough for Visual Studio 2026. [PR #14589](https://github.com/microsoft/vscode-cpptools/pull/14589)
* Fix empty database folders being created in every folder of a multi-root workspace.
* Fix 'Rescan Workspace' triggering a full database reset instead of only a rescan.
* Fix several potential deadlocks and data races in the language server.
* Reduce memory usage to help avoid out-of-memory crashes.
* Fix an incorrect `#include` casing error on Linux.
* Fix an IntelliSense crash.
* Various localization updates.
* Update dependencies.
## Version 1.33.4: July 8, 2026
### Bug Fixes
* Fix the wording for the `#include` errors detected message. [#8227](https://github.com/microsoft/vscode-cpptools/issues/8227)
* Fix another "directory_cache" crash.
* Update some localization.
## Version 1.33.3: July 6, 2026
### Enhancement
* Allow platform overrides in `cppbuild` tasks. [#11601](https://github.com/microsoft/vscode-cpptools/issues/11601)
### Bug Fixes
* Fix `[[no_unique_address]]` empty-base layout `sizeof` being computed too large. [#14524](https://github.com/microsoft/vscode-cpptools/issues/14524)
* Fix C/C++ debug data-tips on members of a dereferenced expression. [PR #14540](https://github.com/microsoft/vscode-cpptools/pull/14540)
* Thanks for the contribution. [@tieo](https://github.com/tieo)
* Fix `clang-format`/`clang-tidy` version check failing on Windows. [PR #14552](https://github.com/microsoft/vscode-cpptools/pull/14552)
* Fix Windows backslash paths being mangled when adding an SSH target. [PR #14554](https://github.com/microsoft/vscode-cpptools/pull/14554)
* Fix "directory_cache" crashes.
* Fix spurious IntelliSense error on `std::variant` brace-initialization.
## Version 1.33.2: June 26, 2026
### Bug Fixes
* Fix a regression with 'Find All References' with functions that exist in both C and C++ files. [#14546](https://github.com/microsoft/vscode-cpptools/issues/14546)
## Version 1.33.1: June 23, 2026
### Bug Fixes
* Fix 'Find All References' dropping valid references when a template parameter type has a typedef alias in only one translation unit. [#14344](https://github.com/microsoft/vscode-cpptools/issues/14344)
* Fix a crash regression on file open.
* Fix IntelliSense incorrectly resolving `#include` files through a symbolic link after the target directory was deleted from disk.
* Fix "tag parsing finished" status randomly getting reported too soon after a 'Reset IntelliSense Database' command.
## Version 1.33.0: June 22, 2026
### New Feature
* Unification of tag parsing with the VS implementation. In particular, it's now done using multiple parallel `cpptools-srv2` processes. [PR #14426](https://github.com/microsoft/vscode-cpptools/pull/14426)
### Enhancements
* Allow platform overrides in `cppbuild` tasks. [#11601](https://github.com/microsoft/vscode-cpptools/issues/11601)
* Add the `debuginfod` launch option to the `cppdbg` debugger schema. [#14458](https://github.com/microsoft/vscode-cpptools/issues/14458), [#14460](https://github.com/microsoft/vscode-cpptools/issues/14460), [PR #14471](https://github.com/microsoft/vscode-cpptools/pull/14471), [PR #14506](https://github.com/microsoft/vscode-cpptools/pull/14506), [MIEngine#1562](https://github.com/microsoft/MIEngine/issues/1562)
* Add the `ignoreRunWithoutDebuggingWarnings` property to allow 'Run without debugging' warnings to be suppressed. [#14515](https://github.com/microsoft/vscode-cpptools/issues/14515)
* Various localization updates.
### Bug Fixes
* Fix the wording for the `#include` errors detected message. [#8227](https://github.com/microsoft/vscode-cpptools/issues/8227)
* Fix an incorrect `invalid type conversion` IntelliSense error. [#11294](https://github.com/microsoft/vscode-cpptools/issues/11294)
* Fix include completion (with recursive includes) still suggesting headers from a deleted folder. [#12636](https://github.com/microsoft/vscode-cpptools/issues/12636)
* 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 'Find All References' dropping valid references when a template parameter type has a typedef alias in only one translation unit. [#14344](https://github.com/microsoft/vscode-cpptools/issues/14344)
* Fix the remote process picker `ps` command not working with some shells. [#14442](https://github.com/microsoft/vscode-cpptools/issues/14442)
* Thanks for the contribution. [@HuzaifaAbdulRehman](https://github.com/HuzaifaAbdulRehman) [PR #14592](https://github.com/microsoft/vscode-cpptools/pull/14592)
* Fix a spurious IntelliSense error with class template argument deduction (CTAD). [#14453](https://github.com/microsoft/vscode-cpptools/issues/14453), [#14459](https://github.com/microsoft/vscode-cpptools/issues/14459), [#14504](https://github.com/microsoft/vscode-cpptools/issues/14504)
* Add `important` to `C_Cpp.doxygen.sectionTags`. [PR #14473](https://github.com/microsoft/vscode-cpptools/pull/14473)
* Update the minimum supported VS Code version to 1.77. [PR #14502](https://github.com/microsoft/vscode-cpptools/pull/14502)
* Fix issues with the debugger `launch.json` schema. [PR #14523](https://github.com/microsoft/vscode-cpptools/pull/14523)
* Fix `[[no_unique_address]]` empty-base layout `sizeof` being computed too large. [#14524](https://github.com/microsoft/vscode-cpptools/issues/14524)
* Fix `${env:VAR}` and `${env.VAR}` not expanding to an empty string when the environment variable is unset, to match VS Code's behavior. [PR #14535](https://github.com/microsoft/vscode-cpptools/pull/14535)
* Thanks for the contribution. [@notable-equivalent](https://github.com/notable-equivalent)
* Fix C/C++ debug data-tips on members of a dereferenced expression. [PR #14540](https://github.com/microsoft/vscode-cpptools/pull/14540)
* Thanks for the contribution. [@tieo](https://github.com/tieo)
* Fix Windows backslash paths being mangled when adding an SSH target. [PR #14554](https://github.com/microsoft/vscode-cpptools/pull/14554)
* Fix 'Run C/C++ File' not running the program in PowerShell when terminal shell integration is unavailable. [#14583](https://github.com/microsoft/vscode-cpptools/issues/14583)
* Thanks for the contribution. [@owevertonguedes (Weverton Guedes)](https://github.com/owevertonguedes) [PR #14585](https://github.com/microsoft/vscode-cpptools/pull/14585)
* Fix the build tools walkthrough for Visual Studio 2026. [PR #14589](https://github.com/microsoft/vscode-cpptools/pull/14589)
* 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 a tag parser crash when a UTF-8 string literal is concatenated with a narrow string literal containing an invalid multibyte sequence.
* Fix IntelliSense incorrectly resolving `#include` files through a symbolic link after the target directory was deleted from disk.
* Fix potential browse database corruption when the same workspace is opened by multiple processes on Linux and macOS.
* Fix crashes when reading files saved in certain multibyte encodings such as GB18030 or EUC-JP.
* Fix empty database folders being created in every folder of a multi-root workspace.
* Fix the `C_Cpp.refactoring.includeHeader` setting not honoring `always`.
* Fix spurious IntelliSense error on `std::variant` brace-initialization.
* Fix several potential deadlocks and data races in the language server.
* Fix an incorrect file path in an error message on Windows.
* Reduce memory usage to help avoid out-of-memory crashes.
* Fix stale diagnostics after editing visible headers.
* Fix several crashes in the recursive include cache.
* Fix an incorrect `#include` casing error on Linux.
* Various other fixes found internally.
* Various localization updates.
* Fix an IntelliSense crash.
* Update dependencies.
## Version 1.32.2: April 28, 2026
### New Feature
+3 -2
View File
@@ -2999,7 +2999,7 @@
"Přiřazení k anachronizmu this není kompatibilní s režimem C++11.",
"Došlo k neznámé chybě. Soubor PCH IntelliSense se nevygeneroval.",
"Nejméně jednu ze vzdálených cest nejde namapovat na stávající místní cesty. Funkce IntelliSense možná nebude fungovat zcela podle očekávání.",
"too many nested user-defined conversions (possible cycle of converting routines)",
null,
null,
null,
null,
@@ -3747,5 +3747,6 @@
"„static“ je zde nestandardní",
"%nd byl dříve deklarován bez explicitního základu výčtu",
"Chybějící typename je tady nestandardní.",
"Zkrácená syntaxe šablony funkce není standardní pro vodítka dedukce"
"Zkrácená syntaxe šablony funkce není standardní pro vodítka dedukce",
"too many nested user-defined conversions (possible cycle of converting routines)"
]
+3 -2
View File
@@ -2999,7 +2999,7 @@
"Die Zuweisung zum this-Anachronismus ist mit dem C++11-Modus nicht kompatibel.",
"Unbekannter Fehler. Es wurde keine IntelliSense PCH-Datei generiert.",
"Mindestens ein Remotepfad kann vorhandenen lokalen Pfaden nicht zugeordnet werden. Die IntelliSense-Funktionen werden ggf. beeinträchtigt.",
"too many nested user-defined conversions (possible cycle of converting routines)",
null,
null,
null,
null,
@@ -3747,5 +3747,6 @@
"„static“ entspricht hier nicht dem Standard",
"%nd wurde zuvor ohne explizite Enumerationsbasis deklariert",
"Fehlender „typename“ entspricht hier nicht dem Standard.",
"Die abgekürzte Funktionsvorlagensyntax entspricht nicht dem Standard für Deduktionsleitfäden."
"Die abgekürzte Funktionsvorlagensyntax entspricht nicht dem Standard für Deduktionsleitfäden.",
"too many nested user-defined conversions (possible cycle of converting routines)"
]
+3 -2
View File
@@ -2999,7 +2999,7 @@
"la asignación al anacronismo \"this\" no es compatible con el modo C++11",
"error desconocido. No se generó un archivo IntelliSense PCH.",
"No se pueden asignar una o varias rutas remotas a las rutas locales actuales. La experiencia con IntelliSense puede degradarse.",
"too many nested user-defined conversions (possible cycle of converting routines)",
null,
null,
null,
null,
@@ -3747,5 +3747,6 @@
"\"static\" no es estándar aquí",
"%nd se declaró previamente sin una base explícita de enumeración",
"falta 'typename' no estándar aquí",
"La sintaxis abreviada de las plantillas de funciones no es estándar para las guías de deducción"
"La sintaxis abreviada de las plantillas de funciones no es estándar para las guías de deducción",
"too many nested user-defined conversions (possible cycle of converting routines)"
]
+3 -2
View File
@@ -2999,7 +2999,7 @@
"l'assignation à l'anachronisme 'this' n'est pas compatible avec le mode C++11",
"une erreur inconnue s'est produite. Aucun fichier PCH IntelliSense n'a été généré.",
"Impossible de mapper un ou plusieurs chemins distants à des chemins locaux existants. L'expérience IntelliSense risque d'être dégradée.",
"too many nested user-defined conversions (possible cycle of converting routines)",
null,
null,
null,
null,
@@ -3747,5 +3747,6 @@
"« static » nest pas standard ici",
"%nd a été déclaré précédemment sans base d’énumération explicite",
"le mot-clé « typename » manquant nest pas standard ici",
"la syntaxe abrégée du modèle de fonction nest pas standard pour les guides de déduction"
"la syntaxe abrégée du modèle de fonction nest pas standard pour les guides de déduction",
"too many nested user-defined conversions (possible cycle of converting routines)"
]
+3 -2
View File
@@ -2999,7 +2999,7 @@
"l'assegnazione all'anacronismo 'this' non è compatibile con la modalità C++11",
"si è verificato un errore sconosciuto. Non è stato generato alcun file PCH IntelliSense.",
"Non è possibile eseguire il mapping di uno o più percorsi remoti a percorsi locali esistenti. L'operazione potrebbe influire negativamente sull'esperienza IntelliSense.",
"too many nested user-defined conversions (possible cycle of converting routines)",
null,
null,
null,
null,
@@ -3747,5 +3747,6 @@
"'static' non è standard qui",
"%nd era stato dichiarato in precedenza senza una base di enumerazione esplicita",
"manca 'typename' che qui non è standard",
"la sintassi abbreviata del modello di funzione non è standard per le guide alla deduzione"
"la sintassi abbreviata del modello di funzione non è standard per le guide alla deduzione",
"too many nested user-defined conversions (possible cycle of converting routines)"
]
+3 -2
View File
@@ -2999,7 +2999,7 @@
"'this' への代入 (旧形式) は C++11 モードと互換性がありません",
"不明なエラーが発生しました。IntelliSense PCH ファイルは生成されませんでした。",
"1 つ以上のリモート パスを既存のローカル パスにマップできません。IntelliSense の機能が低下する可能性があります。",
"too many nested user-defined conversions (possible cycle of converting routines)",
null,
null,
null,
null,
@@ -3747,5 +3747,6 @@
"'static' はここでは非標準です",
"%nd は、明示的な列挙型ベースなしで以前に宣言されました",
"見つからない 'typename' はここでは非標準です",
"省略形の関数テンプレート構文は、推論ガイドでは非標準です"
"省略形の関数テンプレート構文は、推論ガイドでは非標準です",
"too many nested user-defined conversions (possible cycle of converting routines)"
]
+3 -2
View File
@@ -2999,7 +2999,7 @@
"'this'에 대한 할당(오래된 구문)은 C++11 모드와 호환되지 않습니다.",
"알 수 없는 오류가 발생했습니다. IntelliSense PCH 파일이 생성되지 않았습니다.",
"하나 이상의 원격 경로를 기존 로컬 경로에 매핑할 수 없습니다. IntelliSense 성능이 저하될 수 있습니다.",
"too many nested user-defined conversions (possible cycle of converting routines)",
null,
null,
null,
null,
@@ -3747,5 +3747,6 @@
"여기서 'static'은 표준이 아닙니다.",
"%nd은(는) 이전에 명시적 열거형 기반 없이 선언되었습니다.",
"여기서 누락된 'typename'이 표준이 아닙니다.",
"약식 함수 템플릿 구문은 추론 가이드에 대한 표준이 아닙니다."
"약식 함수 템플릿 구문은 추론 가이드에 대한 표준이 아닙니다.",
"too many nested user-defined conversions (possible cycle of converting routines)"
]
+3 -2
View File
@@ -2999,7 +2999,7 @@
"przypisanie do przestarzałej konstrukcji „this” nie jest zgodne z trybem C++11",
"wystąpił nieznany błąd. Nie wygenerowano pliku PCH funkcji IntelliSense.",
"Nie można zamapować co najmniej jednej ścieżki zdalnej na istniejące ścieżki lokalne. Może to mieć negatywny wpływ na działanie funkcji IntelliSense.",
"too many nested user-defined conversions (possible cycle of converting routines)",
null,
null,
null,
null,
@@ -3747,5 +3747,6 @@
"„static” jest tutaj niestandardowy",
"funkcja %nd została poprzednio zadeklarowana bez jawnej bazy wyliczenia",
"brak elementu „typename” jest tutaj niestandardowe",
"skrócona składnia szablonu funkcji jest niestandardowa dla przewodników dedukcji"
"skrócona składnia szablonu funkcji jest niestandardowa dla przewodników dedukcji",
"too many nested user-defined conversions (possible cycle of converting routines)"
]
+3 -2
View File
@@ -2999,7 +2999,7 @@
"a atribuição ao anacronismo 'this' não é compatível com o modo C++11",
"erro desconhecido. Não foi gerado um arquivo PCH do IntelliSense.",
"Um ou mais caminhos remotos não podem ser mapeados para os caminhos locais existentes. A experiência do IntelliSense pode ser degradada.",
"too many nested user-defined conversions (possible cycle of converting routines)",
null,
null,
null,
null,
@@ -3747,5 +3747,6 @@
"\"static\" não é padrão aqui",
"%nd foi declarado anteriormente sem uma base de enumeração explícita",
"\"typename\" ausente não é padrão aqui",
"a sintaxe abreviada de template de função é não padrão para guias de dedução"
"a sintaxe abreviada de template de função é não padrão para guias de dedução",
"too many nested user-defined conversions (possible cycle of converting routines)"
]
+3 -2
View File
@@ -2999,7 +2999,7 @@
"назначение устаревшему элементу this несовместимо с режимом C++11",
"произошла неизвестная ошибка. PCH-файл IntelliSense не был создан.",
"Один или несколько удаленных путей не могут быть сопоставлены с существующими локальными путями. Использование IntelliSense может быть ограничено.",
"too many nested user-defined conversions (possible cycle of converting routines)",
null,
null,
null,
null,
@@ -3747,5 +3747,6 @@
"\"static\" является здесь нестандартным",
"%nd ранее был объявлен без явной базы перечисления",
"отсутствие typename здесь является нестандартным",
"сокращенный синтаксис шаблона функции не является стандартным для правил дедукции"
"сокращенный синтаксис шаблона функции не является стандартным для правил дедукции",
"too many nested user-defined conversions (possible cycle of converting routines)"
]
+3 -2
View File
@@ -2999,7 +2999,7 @@
"'this' anakronizmine yönelik atama C++11 modu ile uyumlu değil",
"bilinmeyen bir hata oluştu. IntelliSense PCH dosyası oluşturulmadı.",
"Bir veya daha fazla uzak yol, mevcut yerel yollarla eşlenemiyor. IntelliSense deneyimi bozulabilir.",
"too many nested user-defined conversions (possible cycle of converting routines)",
null,
null,
null,
null,
@@ -3747,5 +3747,6 @@
"'static' burada standart dışıdır",
"%nd daha önce açık bir sabit liste tabanı olmadan tanımlanmıştı",
"eksik 'typename' burada standart dışı",
"kısaltılmış işlev şablonu sözdizimi çıkarsama kılavuzları için standart değil"
"kısaltılmış işlev şablonu sözdizimi çıkarsama kılavuzları için standart değil",
"too many nested user-defined conversions (possible cycle of converting routines)"
]
+3 -2
View File
@@ -2999,7 +2999,7 @@
"对 \"this\" 计时错误的赋值与 C++11 模式不兼容",
"出现了未知错误。未生成 IntelliSense PCH 文件。",
"一个或多个远程路径无法映射到现有本地路径。IntelliSense 体验可能会降级。",
"too many nested user-defined conversions (possible cycle of converting routines)",
null,
null,
null,
null,
@@ -3747,5 +3747,6 @@
"此处使用 \"static\" 不符合标准",
"之前声明 %nd 时未指定显式枚举基类型",
"此处缺少 'typename' 属于非标准用法",
"缩写函数模板语法对于推导指南是不标准的"
"缩写函数模板语法对于推导指南是不标准的",
"too many nested user-defined conversions (possible cycle of converting routines)"
]
+3 -2
View File
@@ -2999,7 +2999,7 @@
"'this' 用法已過時,且這種指派與 C++11 模式不相容",
"發生未知的錯誤。未產生 IntelliSense PCH 檔案。",
"有一或多個遠端路徑無法對應到現有的本機路徑。IntelliSense 的效能可能會變差。",
"too many nested user-defined conversions (possible cycle of converting routines)",
null,
null,
null,
null,
@@ -3747,5 +3747,6 @@
"此處使用的 'static' 非標準",
"%nd 先前宣告時未明確指定的列舉基底",
"此處缺少 'typename' 非標準用法",
"簡化函式範本語法在推導指南中並非標準用法"
"簡化函式範本語法在推導指南中並非標準用法",
"too many nested user-defined conversions (possible cycle of converting routines)"
]
+1 -1
View File
@@ -2,7 +2,7 @@
"name": "cpptools",
"displayName": "C/C++",
"description": "C/C++ IntelliSense, debugging, and code browsing.",
"version": "1.33.8-main",
"version": "1.33.7-main",
"publisher": "ms-vscode",
"icon": "LanguageCCPP_color_128x.png",
"readme": "README.md",
@@ -16,6 +16,7 @@ nls.config({ messageFormat: nls.MessageFormat.bundle, bundleFormat: nls.BundleFo
const localize: nls.LocalizeFunc = nls.loadMessageBundle();
export class CopilotHoverProvider implements vscode.HoverProvider {
private client: DefaultClient;
private currentDocument: vscode.TextDocument | undefined;
private currentPosition: vscode.Position | undefined;
private currentCancellationToken: vscode.CancellationToken | undefined;
@@ -29,8 +30,8 @@ export class CopilotHoverProvider implements vscode.HoverProvider {
private chatModelId: string | undefined; // Save the selected model ID to avoid trying the same unavailable model repeatedly.
// Flag to avoid querying the LanguageModelChat repeatedly if no model is found
private checkedChatModel: boolean = false;
constructor(private client: DefaultClient) {
constructor(client: DefaultClient) {
this.client = client;
}
public async getCachedChatModel(): Promise<vscode.LanguageModelChat | undefined> {
@@ -170,6 +171,7 @@ export class CopilotHoverProvider implements vscode.HoverProvider {
position: Position.create(position.line, position.character)
};
await this.client.ready;
if (this.currentCancellationToken?.isCancellationRequested) {
throw new vscode.CancellationError();
}
@@ -10,10 +10,11 @@ import { RequestCancelled, ServerCancelled } from '../protocolFilter';
import { CppSettings } from '../settings';
export class HoverProvider implements vscode.HoverProvider {
private client: DefaultClient;
private lastContent: vscode.MarkdownString[] | undefined;
private readonly hasContent = new ManualSignal<boolean>(true);
constructor(private client: DefaultClient) {
constructor(client: DefaultClient) {
this.client = client;
}
public async provideHover(document: vscode.TextDocument, position: vscode.Position, token: vscode.CancellationToken): Promise<vscode.Hover | undefined> {
@@ -35,6 +36,7 @@ export class HoverProvider implements vscode.HoverProvider {
textDocument: { uri: document.uri.toString() },
position: Position.create(position.line, position.character)
};
await this.client.ready;
let hoverResult: vscode.Hover;
try {
hoverResult = await this.client.languageClient.sendRequest(HoverRequest, params, token);
@@ -214,11 +214,15 @@ export async function sendCallHierarchyCallsFromRequest(client: DefaultClient, i
export class CallHierarchyProvider implements vscode.CallHierarchyProvider {
// Indicates whether a request is from an entry root node (e.g. top function in the call tree).
private isEntryRootNodeTelemetry: boolean = false;
private client: DefaultClient;
constructor(private client: DefaultClient) {
constructor(client: DefaultClient) {
this.client = client;
}
public async prepareCallHierarchy(document: vscode.TextDocument, position: vscode.Position, token: vscode.CancellationToken): Promise<vscode.CallHierarchyItem | undefined> {
await this.client.ready;
workspaceReferences.cancelCurrentReferenceRequest(CancellationSender.NewRequest);
workspaceReferences.clearViews();
@@ -257,6 +261,7 @@ export class CallHierarchyProvider implements vscode.CallHierarchyProvider {
}
public async provideCallHierarchyIncomingCalls(item: vscode.CallHierarchyItem, token: vscode.CancellationToken): Promise<vscode.CallHierarchyIncomingCall[] | undefined> {
await this.client.ready;
workspaceReferences.cancelCurrentReferenceRequest(CancellationSender.NewRequest);
const CallHierarchyCallsToEvent: string = "CallHierarchyCallsTo";
@@ -311,6 +316,8 @@ export class CallHierarchyProvider implements vscode.CallHierarchyProvider {
return undefined;
}
await this.client.ready;
const result: vscode.CallHierarchyOutgoingCall[] | undefined =
await sendCallHierarchyCallsFromRequest(this.client, item, token);
if (token.isCancellationRequested || result === undefined) {
@@ -40,7 +40,9 @@ export const GetCodeActionsRequest: RequestType<GetCodeActionsRequestParams, Get
new RequestType<GetCodeActionsRequestParams, GetCodeActionsResult, void>('cpptools/getCodeActions');
export class CodeActionProvider implements vscode.CodeActionProvider {
constructor(private client: DefaultClient) {
private client: DefaultClient;
constructor(client: DefaultClient) {
this.client = client;
}
private static inlineMacroKind: vscode.CodeActionKind = vscode.CodeActionKind.RefactorInline.append("macro");
@@ -49,6 +51,7 @@ export class CodeActionProvider implements vscode.CodeActionProvider {
public async provideCodeActions(document: vscode.TextDocument, range: vscode.Range | vscode.Selection,
context: vscode.CodeActionContext, token: vscode.CancellationToken): Promise<(vscode.Command | vscode.CodeAction)[]> {
await this.client.ready;
let r: Range;
if (range instanceof vscode.Selection) {
if (range.active.isBefore(range.anchor)) {
@@ -11,7 +11,9 @@ import { CppSettings, OtherSettings } from '../settings';
import { makeVscodeTextEdits } from '../utils';
export class DocumentFormattingEditProvider implements vscode.DocumentFormattingEditProvider {
constructor(private client: DefaultClient) {
private client: DefaultClient;
constructor(client: DefaultClient) {
this.client = client;
}
public async provideDocumentFormattingEdits(document: vscode.TextDocument, options: vscode.FormattingOptions, token: vscode.CancellationToken): Promise<vscode.TextEdit[]> {
@@ -19,6 +21,7 @@ export class DocumentFormattingEditProvider implements vscode.DocumentFormatting
if (settings.formattingEngine === "disabled") {
return [];
}
await this.client.ready;
const filePath: string = document.uri.fsPath;
if (options.onChanges) {
let insertSpacesSet: boolean = false;
@@ -11,7 +11,9 @@ import { CppSettings } from '../settings';
import { makeVscodeTextEdits } from '../utils';
export class DocumentRangeFormattingEditProvider implements vscode.DocumentRangeFormattingEditProvider {
constructor(private client: DefaultClient) {
private client: DefaultClient;
constructor(client: DefaultClient) {
this.client = client;
}
public async provideDocumentRangeFormattingEdits(document: vscode.TextDocument, range: vscode.Range,
@@ -20,6 +22,7 @@ export class DocumentRangeFormattingEditProvider implements vscode.DocumentRange
if (settings.formattingEngine === "disabled") {
return [];
}
await this.client.ready;
const filePath: string = document.uri.fsPath;
const useVcFormat: boolean = settings.useVcFormat(document);
const configCallBack = async (editorConfigSettings: any | undefined) => {
@@ -58,12 +58,14 @@ export class DocumentSymbolProvider implements vscode.DocumentSymbolProvider {
public async provideDocumentSymbols(document: vscode.TextDocument, token: vscode.CancellationToken): Promise<vscode.SymbolInformation[] | vscode.DocumentSymbol[]> {
const client: Client = clients.getClientFor(document.uri);
if (client instanceof DefaultClient) {
const defaultClient: DefaultClient = <DefaultClient>client;
await client.ready;
const params: GetDocumentSymbolRequestParams = {
uri: document.uri.toString()
};
let response: GetDocumentSymbolResult;
try {
response = await client.languageClient.sendRequest(GetDocumentSymbolRequest, params, token);
response = await defaultClient.languageClient.sendRequest(GetDocumentSymbolRequest, params, token);
} catch (e: any) {
if (e instanceof ResponseError && (e.code === RequestCancelled || e.code === ServerCancelled)) {
throw new vscode.CancellationError();
@@ -56,10 +56,14 @@ export async function sendFindAllReferencesRequest(client: DefaultClient, uri: v
}
export class FindAllReferencesProvider implements vscode.ReferenceProvider {
constructor(private client: DefaultClient) {
private client: DefaultClient;
constructor(client: DefaultClient) {
this.client = client;
}
public async provideReferences(document: vscode.TextDocument, position: vscode.Position, context: vscode.ReferenceContext, token: vscode.CancellationToken): Promise<vscode.Location[] | undefined> {
await this.client.ready;
workspaceReferences.cancelCurrentReferenceRequest(CancellationSender.NewRequest);
// Listen to a cancellation for this request. When this request is cancelled,
@@ -14,6 +14,7 @@ interface FoldingRangeRequestInfo {
}
export class FoldingRangeProvider implements vscode.FoldingRangeProvider {
private client: DefaultClient;
public onDidChangeFoldingRangesEvent = new vscode.EventEmitter<void>();
public onDidChangeFoldingRanges?: vscode.Event<void>;
@@ -21,11 +22,12 @@ export class FoldingRangeProvider implements vscode.FoldingRangeProvider {
// for the same file without waiting for the prior request to complete or cancelling them.
private pendingRequests: Map<string, FoldingRangeRequestInfo> = new Map<string, FoldingRangeRequestInfo>();
constructor(private client: DefaultClient) {
constructor(client: DefaultClient) {
this.client = client;
this.onDidChangeFoldingRanges = this.onDidChangeFoldingRangesEvent.event;
}
async provideFoldingRanges(document: vscode.TextDocument, context: vscode.FoldingContext, token: vscode.CancellationToken): Promise<vscode.FoldingRange[] | undefined> {
await this.client.ready;
const settings: CppSettings = new CppSettings();
if (!settings.codeFolding) {
return [];
@@ -11,7 +11,9 @@ import { CppSettings } from '../settings';
import { makeVscodeTextEdits } from '../utils';
export class OnTypeFormattingEditProvider implements vscode.OnTypeFormattingEditProvider {
constructor(private client: DefaultClient) {
private client: DefaultClient;
constructor(client: DefaultClient) {
this.client = client;
}
public async provideOnTypeFormattingEdits(document: vscode.TextDocument, position: vscode.Position, ch: string, options: vscode.FormattingOptions, token: vscode.CancellationToken): Promise<vscode.TextEdit[]> {
@@ -19,6 +21,7 @@ export class OnTypeFormattingEditProvider implements vscode.OnTypeFormattingEdit
if (settings.formattingEngine === "disabled") {
return [];
}
await this.client.ready;
const filePath: string = document.uri.fsPath;
const useVcFormat: boolean = settings.useVcFormat(document);
const configCallBack = async (editorConfigSettings: any | undefined) => {
@@ -18,10 +18,14 @@ const RenameRequest: RequestType<ReferencesParams, ReferencesResult, void> =
new RequestType<ReferencesParams, ReferencesResult, void>('cpptools/rename');
export class RenameProvider implements vscode.RenameProvider {
constructor(private client: DefaultClient) {
private client: DefaultClient;
constructor(client: DefaultClient) {
this.client = client;
}
public async provideRenameEdits(document: vscode.TextDocument, position: vscode.Position, newName: string, _token: vscode.CancellationToken): Promise<vscode.WorkspaceEdit | undefined> {
await this.client.ready;
workspaceReferences.cancelCurrentReferenceRequest(CancellationSender.NewRequest);
const settings: CppSettings = new CppSettings();
@@ -5,7 +5,8 @@
import * as vscode from 'vscode';
import { ManualPromise } from '../../Utility/Async/manualPromise';
interface FileData {
interface FileData
{
version: number;
promise: ManualPromise<vscode.SemanticTokens>;
tokenBuilder: vscode.SemanticTokensBuilder;
@@ -10,7 +10,9 @@ import { RequestCancelled, ServerCancelled } from '../protocolFilter';
import { makeVscodeLocation } from '../utils';
export class WorkspaceSymbolProvider implements vscode.WorkspaceSymbolProvider {
constructor(private client: DefaultClient) {
private client: DefaultClient;
constructor(client: DefaultClient) {
this.client = client;
}
public async provideWorkspaceSymbols(query: string, token: vscode.CancellationToken): Promise<vscode.SymbolInformation[]> {
+182 -66
View File
@@ -23,16 +23,19 @@ import { WorkspaceSymbolProvider } from './Providers/workspaceSymbolProvider';
// End provider imports
import { CodeSnippet, Trait } from '@github/copilot-language-server';
import { ok } from 'assert';
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, NotificationType, Position, Range, RequestType, ResponseError, TextDocumentIdentifier, TextDocumentPositionParams } from 'vscode-languageclient';
import * as rpc from 'vscode-languageclient/node';
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';
import { ManualPromise } from '../Utility/Async/manualPromise';
import { ManualSignal } from '../Utility/Async/manualSignal';
import { logAndReturn } from '../Utility/Async/returns';
import { is } from '../Utility/System/guards';
import * as util from '../common';
import { isWindows } from '../constants';
import { instrument, isInstrumentationEnabled } from '../instrumentation';
@@ -57,7 +60,6 @@ import { CustomConfigurationProvider1, getCustomConfigProviders, isSameProviderE
import { DataBinding } from './dataBinding';
import { cachedEditorConfigSettings, getEditorConfigSettings } from './editorConfig';
import { CppSourceStr, clients, configPrefix, initializeIntervalTimer, isWritingCrashCallStack, updateLanguageConfigurations, usesCrashHandler, watchForCrashes } from './extension';
import { LanguageClient } from './languageClient';
import { LocalizeStringParams, getLocaleId, getLocalizedString } from './localization';
import { PersistentFolderState, PersistentState, PersistentWorkspaceState } from './persistentState';
import { RequestCancelled, ServerCancelled, createProtocolFilter } from './protocolFilter';
@@ -86,7 +88,7 @@ export function hasTrustedCompilerPaths(): boolean {
}
// Data shared by all clients.
const languageClient: LanguageClient = new LanguageClient();
let languageClient: LanguageClient;
let firstClientStarted: Promise<{ wasShutdown: boolean }>;
let languageClientHasCrashed: boolean = false;
let languageClientCrashedNeedsRestart: boolean = false;
@@ -219,16 +221,9 @@ interface FileChangedParams extends WorkspaceFolderParams {
uri: string;
}
interface InputLineRange {
startLine: number;
endLine: number;
}
interface InputRegion {
startLine: number;
startColumn: number;
endLine: number;
endColumn: number;
}
interface DecorationRangesPair {
@@ -379,7 +374,7 @@ export enum FoldingRangeKind {
export interface CppFoldingRange {
kind: FoldingRangeKind;
range: InputLineRange;
range: InputRegion;
}
export interface GetFoldingRangesResult {
@@ -786,6 +781,7 @@ class ClientModel {
export interface Client {
readonly ready: Promise<void>;
enqueue<T>(task: () => Promise<T>): Promise<T>;
InitializingWorkspaceChanged: vscode.Event<boolean>;
IndexingWorkspaceChanged: vscode.Event<boolean>;
ParsingWorkspaceChanged: vscode.Event<boolean>;
@@ -897,6 +893,7 @@ export function createNullClient(): Client {
}
export class DefaultClient implements Client {
private innerLanguageClient?: LanguageClient; // The "client" that launches and communicates with our language "server" process.
private disposables: vscode.Disposable[] = [];
private documentFormattingProviderDisposable: vscode.Disposable | undefined;
private formattingRangeProviderDisposable: vscode.Disposable | undefined;
@@ -912,6 +909,7 @@ export class DefaultClient implements Client {
private rootRealPath: string;
private workspaceStoragePath: string;
private trackedDocuments = new Map<string, vscode.TextDocument>();
private isSupported: boolean = true;
private inactiveRegionsDecorations = new Map<string, DecorationRangesPair>();
private settingsTracker: SettingsTracker;
private loggingLevel: number = 1;
@@ -936,6 +934,20 @@ export class DefaultClient implements Client {
private showConfigureIntelliSenseButton: boolean = false;
private pendingTagParsingCalls: PendingTagParsingCall[] = [];
/** A queue of asynchronous tasks that need to be processed befofe ready is considered active. */
private static queue = new Array<[ManualPromise<unknown>, () => Promise<unknown>] | [ManualPromise<unknown>]>();
/** returns a promise that waits initialization and/or a change to configuration to complete (i.e. language client is ready-to-use) */
private static readonly isStarted = new ManualSignal<void>(true);
/**
* Indicates if the blocking task dispatcher is currently running
*
* This will be in the Set state when the dispatcher is not running (i.e. if you await this it will be resolved immediately)
* If the dispatcher is running, this will be in the Reset state (i.e. if you await this it will be resolved when the dispatcher is done)
*/
private static readonly dispatching = new ManualSignal<void>();
// The "model" that is displayed via the UI (status bar).
private model: ClientModel = new ClientModel();
@@ -952,7 +964,7 @@ export class DefaultClient implements Client {
public get ReferencesCommandModeChanged(): vscode.Event<refs.ReferencesCommandMode> { return this.model.referencesCommandMode.ValueChanged; }
public get TagParserStatusChanged(): vscode.Event<string> { return this.model.parsingWorkspaceStatus.ValueChanged; }
public get ActiveConfigChanged(): vscode.Event<string> { return this.model.activeConfigName.ValueChanged; }
public isInitialized(): boolean { return this.languageClient.isInitialized; }
public isInitialized(): boolean { return this.innerLanguageClient !== undefined; }
public getShowConfigureIntelliSenseButton(): boolean { return this.showConfigureIntelliSenseButton; }
public setShowConfigureIntelliSenseButton(show: boolean): void { this.showConfigureIntelliSenseButton = show; }
@@ -987,7 +999,10 @@ export class DefaultClient implements Client {
}
public get languageClient(): LanguageClient {
return languageClient;
if (!this.innerLanguageClient) {
throw new Error("Attempting to use languageClient before initialized");
}
return this.innerLanguageClient;
}
public get configuration(): configs.CppProperties {
@@ -1361,18 +1376,19 @@ export class DefaultClient implements Client {
if (firstClientStarted === undefined || languageClientCrashedNeedsRestart) {
if (languageClientCrashedNeedsRestart) {
languageClientCrashedNeedsRestart = false;
// if we're recovering, the isStarted needs to be reset
// if we're recovering, the isStarted needs to be reset.
// because we're starting the first client again.
this.languageClient.isStarted = false;
this.languageClient.setLanguageClient(undefined);
DefaultClient.isStarted.reset();
}
firstClientStarted = this.createLanguageClient();
util.setProgress(util.getProgressExecutableStarted());
isFirstClient = true;
}
void this.init(rootUri, isFirstClient).catch(logAndReturn.undefined);
} catch (errJS) {
const err: NodeJS.ErrnoException = errJS as NodeJS.ErrnoException;
this.isSupported = false; // Running on an OS we don't support yet.
if (!failureMessageShown) {
failureMessageShown = true;
let additionalInfo: string;
@@ -1392,7 +1408,8 @@ export class DefaultClient implements Client {
ui = getUI();
ui.bind(this);
if ((await firstClientStarted).wasShutdown) {
this.languageClient.isStarted = true;
this.isSupported = false;
DefaultClient.isStarted.resolve();
return;
}
@@ -1404,10 +1421,7 @@ export class DefaultClient implements Client {
this.innerConfiguration.CompileCommandsChanged((e) => this.onCompileCommandsChanged(e));
this.disposables.push(this.innerConfiguration);
// Ideally this would be set earlier, but the task provider expects it to also mean that `this.innerConfiguration` is set.
this.languageClient.isStarted = true;
compilerDefaults = await this.requestCompiler();
this.innerLanguageClient = languageClient;
telemetry.logLanguageServerEvent("NonDefaultInitialCppSettings", this.settingsTracker.getUserModifiedSettings());
failureMessageShown = false;
@@ -1474,6 +1488,7 @@ export class DefaultClient implements Client {
});
// The configurations will not be sent to the language server until the default include paths and frameworks have been set.
// The event handlers must be set before this happens.
compilerDefaults = await this.requestCompiler();
DefaultClient.updateClientConfigurations();
clients.forEach(client => {
if (client instanceof DefaultClient) {
@@ -1483,11 +1498,14 @@ export class DefaultClient implements Client {
});
}
} catch (err) {
this.isSupported = false; // Running on an OS we don't support yet.
if (!failureMessageShown) {
failureMessageShown = true;
void vscode.window.showErrorMessage(localize("unable.to.start", "Unable to start the C/C++ language server. IntelliSense features will be disabled. Error: {0}", String(err)));
}
}
DefaultClient.isStarted.resolve();
}
private getWorkspaceFolderSettings(workspaceFolderUri: vscode.Uri | undefined, workspaceFolder: vscode.WorkspaceFolder | undefined, settings: CppSettings, otherSettings: OtherSettings): WorkspaceFolderSettingsParams {
@@ -1675,7 +1693,7 @@ export class DefaultClient implements Client {
// from a sanitizer build to files in that directory (see getSanitizerServerEnv). This is
// undefined -- i.e. the environment is inherited unchanged -- for normal builds.
const sanitizerServerEnv: NodeJS.ProcessEnv | undefined = getSanitizerServerEnv();
const serverOptions: rpc.ServerOptions = {
const serverOptions: ServerOptions = {
run: { command: serverModule, options: { detached: false, cwd: util.getExtensionFilePath("bin"), env: sanitizerServerEnv } },
debug: { command: serverModule, args: [serverName], options: { detached: true, cwd: util.getExtensionFilePath("bin"), env: sanitizerServerEnv } }
};
@@ -1738,7 +1756,7 @@ export class DefaultClient implements Client {
loggingLevel: this.loggingLevel
};
const clientOptions: rpc.LanguageClientOptions = {
const clientOptions: LanguageClientOptions = {
documentSelector: [
{ scheme: 'file', language: 'c' },
{ scheme: 'file', language: 'cpp' },
@@ -1818,40 +1836,34 @@ export class DefaultClient implements Client {
// Refresh initializing state in UI.
this.model.isInitializingWorkspace.Value = true;
// Create the language client that spawns cpptools and configures RPC over stdin/stdout.
// This is the ONLY place outside of the LanguageClient wrapper where the VS Code LanguageClient class should be used directly.
// All other code should use the LanguageClient wrapper class.
const client = new rpc.LanguageClient(`cpptools`, serverOptions, clientOptions);
client.onNotification(DebugProtocolNotification, logDebugProtocol);
client.onNotification(DebugLogNotification, logLocalized);
client.onNotification(LogTelemetryNotification, (e) => void this.logTelemetry(e));
client.onNotification(ShowMessageWindowNotification, showMessageWindow);
client.registerProposedFeatures();
await client.start();
// Create the language client
languageClient = new LanguageClient(`cpptools`, serverOptions, clientOptions);
languageClient.onNotification(DebugProtocolNotification, logDebugProtocol);
languageClient.onNotification(DebugLogNotification, logLocalized);
languageClient.onNotification(LogTelemetryNotification, (e) => void this.logTelemetry(e));
languageClient.onNotification(ShowMessageWindowNotification, showMessageWindow);
languageClient.registerProposedFeatures();
await languageClient.start();
if (usesCrashHandler()) {
watchForCrashes(await client.sendRequest(PreInitializationRequest, null));
watchForCrashes(await languageClient.sendRequest(PreInitializationRequest, null));
} else if (os.platform() === "win32") {
const settings: CppSettings = new CppSettings();
if ((settings.windowsErrorReportingMode === "default" && !languageClientHasCrashed) ||
settings.windowsErrorReportingMode === "enabled") {
await client.sendRequest(PreInitializationRequest, null);
await languageClient.sendRequest(PreInitializationRequest, null);
}
}
// Move initialization to a separate message, so we can see log output from it.
// A request is used in order to wait for completion and ensure that no subsequent
// higher priority message may be processed before the Initialization request.
const initializeResult = await client.sendRequest(InitializationRequest, cppInitializationParams);
const initializeResult = await languageClient.sendRequest(InitializationRequest, cppInitializationParams);
// If the server requested shutdown, then reload with the failsafe (null) client.
if (initializeResult.shouldShutdown) {
await client.stop();
await languageClient.stop();
await clients.recreateClients(true);
} else {
// Don't set the inner language client on the wrapper until after initialization is complete.
// This ensures the order of the initialization messages.
languageClient.setLanguageClient(client);
}
return { wasShutdown: initializeResult.shouldShutdown };
@@ -1859,6 +1871,7 @@ export class DefaultClient implements Client {
public async sendDidChangeSettings(): Promise<void> {
// Send settings json to native side.
await this.ready;
await this.languageClient.sendNotification(DidChangeSettingsNotification, this.getAllSettings());
}
@@ -2198,6 +2211,7 @@ export class DefaultClient implements Client {
}
public async logDiagnostics(): Promise<void> {
await this.ready;
const response: GetDiagnosticsResult = await this.languageClient.sendRequest(GetDiagnosticsRequest, null);
const diagnosticsChannel: vscode.OutputChannel = getDiagnosticsChannel();
diagnosticsChannel.clear();
@@ -2265,12 +2279,16 @@ export class DefaultClient implements Client {
diagnosticsChannel.show(false);
}
public rescanFolder(): Promise<void> {
public async rescanFolder(): Promise<void> {
await this.ready;
return this.languageClient.sendNotification(RescanFolderNotification);
}
public async provideCustomConfigurations(docUris: vscode.Uri[], batchId: number): Promise<void> {
let isProviderRegistered: boolean = false;
const onFinished: () => void = () => {
void this.languageClient.sendNotification(FinishedRequestCustomConfig, { batchId, isProviderRegistered });
};
try {
const providerId: string | undefined = this.configurationProvider;
if (!providerId) {
@@ -2284,7 +2302,7 @@ export class DefaultClient implements Client {
const resultCode = await this.provideCustomConfigurationAsync(docUris, provider);
telemetry.logLanguageServerEvent('provideCustomConfigurations', { providerId, resultCode });
} finally {
void this.languageClient.sendNotification(FinishedRequestCustomConfig, { batchId, isProviderRegistered });
onFinished();
}
}
@@ -2504,8 +2522,9 @@ export class DefaultClient implements Client {
* the UI results and always re-requests (no caching).
*/
public getIncludes(uri: vscode.Uri, maxDepth: number): Promise<GetIncludesResult> {
public async getIncludes(uri: vscode.Uri, maxDepth: number): Promise<GetIncludesResult> {
const params: GetIncludesParams = { fileUri: uri.toString(), maxDepth };
await this.ready;
return this.languageClient.sendRequest(IncludesRequest, params);
}
@@ -2526,11 +2545,82 @@ export class DefaultClient implements Client {
}
/**
* A Promise that can be awaited to know when the language client (cpptools) is up and running.
* It also implies that `this.innerConfiguration` is set.
* a Promise that can be awaited to know when it's ok to proceed.
*
* This is a lighter-weight complement to `enqueue()`
*
* Use `await <client>.ready` when you need to ensure that the client is initialized, and to run in order
* Use `enqueue()` when you want to ensure that subsequent calls are blocked until a critical bit of code is run.
*
* This is lightweight, because if the queue is empty, then the only thing to wait for is the client itself to be initialized
*/
get ready(): Promise<void> {
return this.languageClient.ready;
if (!DefaultClient.dispatching.isCompleted || DefaultClient.queue.length) {
// if the dispatcher has stuff going on, then we need to stick in a promise into the queue so we can
// be notified when it's our turn
const p = new ManualPromise<void>();
DefaultClient.queue.push([p as ManualPromise<unknown>]);
return p;
}
// otherwise, we're only waiting for the client to be in an initialized state, in which case just wait for that.
return DefaultClient.isStarted;
}
/**
* Enqueue a task to ensure that the order is maintained. The tasks are executed sequentially after the client is ready.
*
* this is a bit more expensive than `.ready` - this ensures the task is absolutely finished executing before allowing
* the dispatcher to move forward.
*
* Use `enqueue()` when you want to ensure that subsequent calls are blocked until a critical bit of code is run.
* Use `await <client>.ready` when you need to ensure that the client is initialized, and still run in order.
*/
enqueue<T>(task: () => Promise<T>) {
ok(this.isSupported, localize("unsupported.client", "Unsupported client"));
// create a placeholder promise that is resolved when the task is complete.
const result = new ManualPromise<unknown>();
// add the task to the queue
DefaultClient.queue.push([result, task]);
// if we're not already dispatching, start
if (DefaultClient.dispatching.isSet) {
// start dispatching
void DefaultClient.dispatch();
}
// return the placeholder promise to the caller.
return result as Promise<T>;
}
/**
* The dispatch loop asynchronously processes items in the async queue in order, and ensures that tasks are dispatched in the
* order they were inserted.
*/
private static async dispatch() {
// reset the promise for the dispatcher
DefaultClient.dispatching.reset();
do {
// ensure that this is OK to start working
await this.isStarted;
// pick items up off the queue and run then one at a time until the queue is empty
const [promise, task] = DefaultClient.queue.shift() ?? [];
if (is.promise(promise)) {
try {
promise.resolve(task ? await task() : undefined);
} catch (e) {
console.log(e);
promise.reject(e);
}
}
} while (DefaultClient.queue.length);
// unblock anything that is waiting for the dispatcher to empty
this.dispatching.resolve();
}
private static async withLspCancellationHandling<T>(task: () => Promise<T>, token: vscode.CancellationToken): Promise<T> {
@@ -2582,7 +2672,7 @@ export class DefaultClient implements Client {
* listen for notifications from the language server.
*/
private registerNotifications(): void {
console.assert(this.languageClient.isInitialized, "This method must not be called until the language client is initialized.");
console.assert(this.languageClient !== undefined, "This method must not be called until this.languageClient is set in \"onReady\"");
this.languageClient.onNotification(ReloadWindowNotification, () => void util.promptForReloadWindowDueToSettingsChange());
this.languageClient.onNotification(UpdateTrustedCompilersNotification, (e) => void this.addTrustedCompiler(e.compilerPath));
@@ -2691,7 +2781,7 @@ export class DefaultClient implements Client {
* listen for file created/deleted events under the ${workspaceFolder} folder
*/
private registerFileWatcher(): void {
console.assert(this.languageClient.isInitialized, "This method must not be called until the language client is initialized.");
console.assert(this.languageClient !== undefined, "This method must not be called until this.languageClient is set in \"onReady\"");
if (this.rootFolder) {
// WARNING: The default limit on Linux is 8k, so for big directories, this can cause file watching to fail.
@@ -2964,8 +3054,7 @@ export class DefaultClient implements Client {
this.inactiveRegionsDecorations.set(uriString, currentSet);
}
Array.prototype.push.apply(currentSet.ranges, inactiveRegions.map(element =>
new vscode.Range(element.startLine, element.startColumn, element.endLine, element.endColumn)));
Array.prototype.push.apply(currentSet.ranges, inactiveRegions.map(element => new vscode.Range(element.startLine, 0, element.endLine, 0)));
// Apply the decorations to all *visible* text editors
const editors: vscode.TextEditor[] = vscode.window.visibleTextEditors.filter(e => e.document.uri.toString() === uriString);
@@ -3053,16 +3142,18 @@ export class DefaultClient implements Client {
switchHeaderSourceFileName: fileName,
workspaceFolderUri: rootUri.toString()
};
// Don't use withLspCancellationHandling() or withCancellation() here. If the switch target is already known,
// the caller should still be able to use it even if the progress notification was just cancelled.
try {
return await this.languageClient.sendRequest(SwitchHeaderSourceRequest, params, token);
} catch (e: any) {
if (e instanceof ResponseError && (e.code === RequestCancelled || e.code === ServerCancelled)) {
throw new vscode.CancellationError();
return this.enqueue(async () => {
// Don't use withLspCancellationHandling() or withCancellation() here. If the switch target is already known,
// the caller should still be able to use it even if the progress notification was just cancelled.
try {
return await this.languageClient.sendRequest(SwitchHeaderSourceRequest, params, token);
} catch (e: any) {
if (e instanceof ResponseError && (e.code === RequestCancelled || e.code === ServerCancelled)) {
throw new vscode.CancellationError();
}
throw e;
}
throw e;
}
});
}
public async requestCompiler(newCompilerPath?: string): Promise<configs.CompilerDefaults> {
@@ -3142,6 +3233,7 @@ export class DefaultClient implements Client {
* send notifications to the language server to restart IntelliSense for the selected file.
*/
public async restartIntelliSenseForFile(document: vscode.TextDocument): Promise<void> {
await this.ready;
return this.languageClient.sendNotification(RestartIntelliSenseForFileNotification, this.languageClient.code2ProtocolConverter.asTextDocumentIdentifier(document)).catch(logAndReturn.undefined);
}
@@ -3158,6 +3250,7 @@ export class DefaultClient implements Client {
}
public async resetDatabase(): Promise<void> {
await this.ready;
return this.languageClient.sendNotification(ResetDatabaseNotification);
}
@@ -3169,24 +3262,29 @@ export class DefaultClient implements Client {
}
public async pauseParsing(): Promise<void> {
await this.ready;
return this.languageClient.sendNotification(PauseParsingNotification);
}
public async resumeParsing(): Promise<void> {
await this.ready;
return this.languageClient.sendNotification(ResumeParsingNotification);
}
public async PauseCodeAnalysis(): Promise<void> {
await this.ready;
this.model.isCodeAnalysisPaused.Value = true;
return this.languageClient.sendNotification(PauseCodeAnalysisNotification);
}
public async ResumeCodeAnalysis(): Promise<void> {
await this.ready;
this.model.isCodeAnalysisPaused.Value = false;
return this.languageClient.sendNotification(ResumeCodeAnalysisNotification);
}
public async CancelCodeAnalysis(): Promise<void> {
await this.ready;
return this.languageClient.sendNotification(CancelCodeAnalysisNotification);
}
@@ -3321,6 +3419,7 @@ export class DefaultClient implements Client {
currentConfiguration: index,
workspaceFolderUri: this.RootUri?.toString()
};
await this.ready;
await this.languageClient.sendNotification(ChangeSelectedSettingNotification, params);
let configName: string = "";
@@ -3336,6 +3435,7 @@ export class DefaultClient implements Client {
uri: vscode.Uri.file(path).toString(),
workspaceFolderUri: this.RootUri?.toString()
};
await this.ready;
return this.languageClient.sendNotification(ChangeCompileCommandsNotification, params);
}
@@ -3521,6 +3621,7 @@ export class DefaultClient implements Client {
const params: WorkspaceFolderParams = {
workspaceFolderUri: this.RootUri?.toString()
};
await this.ready;
return this.languageClient.sendNotification(ClearCustomConfigurationsNotification, params);
}
@@ -3529,6 +3630,7 @@ export class DefaultClient implements Client {
const params: WorkspaceFolderParams = {
workspaceFolderUri: this.RootUri?.toString()
};
await this.ready;
return this.languageClient.sendNotification(ClearCustomBrowseConfigurationNotification, params);
}
@@ -3615,6 +3717,7 @@ export class DefaultClient implements Client {
position: editor.selection.active,
next: next
};
await this.ready;
const response: Position | undefined = await this.languageClient.sendRequest(GoToDirectiveInGroupRequest, params);
if (response) {
const p: vscode.Position = new vscode.Position(response.line, response.character);
@@ -3647,6 +3750,7 @@ export class DefaultClient implements Client {
isCodeAction: codeActionArguments !== undefined,
isCursorAboveSignatureLine: codeActionArguments?.isCursorAboveSignatureLine
};
await this.ready;
const currentFileVersion: number | undefined = openFileVersions.get(params.uri);
if (currentFileVersion === undefined) {
return;
@@ -3692,19 +3796,23 @@ export class DefaultClient implements Client {
}
}
public handleRunCodeAnalysisOnActiveFile(): Promise<void> {
public async handleRunCodeAnalysisOnActiveFile(): Promise<void> {
await this.ready;
return this.languageClient.sendNotification(CodeAnalysisNotification, { scope: CodeAnalysisScope.ActiveFile });
}
public handleRunCodeAnalysisOnOpenFiles(): Promise<void> {
public async handleRunCodeAnalysisOnOpenFiles(): Promise<void> {
await this.ready;
return this.languageClient.sendNotification(CodeAnalysisNotification, { scope: CodeAnalysisScope.OpenFiles });
}
public handleRunCodeAnalysisOnAllFiles(): Promise<void> {
public async handleRunCodeAnalysisOnAllFiles(): Promise<void> {
await this.ready;
return this.languageClient.sendNotification(CodeAnalysisNotification, { scope: CodeAnalysisScope.AllFiles });
}
public async handleRemoveAllCodeAnalysisProblems(): Promise<void> {
await this.ready;
if (removeAllCodeAnalysisProblems()) {
return this.languageClient.sendNotification(CodeAnalysisNotification, { scope: CodeAnalysisScope.ClearSquiggles });
}
@@ -3735,6 +3843,8 @@ export class DefaultClient implements Client {
}
public async handleRemoveCodeAnalysisProblems(refreshSquigglesOnSave: boolean, identifiersAndUris: CodeAnalysisDiagnosticIdentifiersAndUri[]): Promise<void> {
await this.ready;
// A deep copy is needed because the call to identifiers.splice below can
// remove elements in identifiersAndUris[...].identifiers.
const identifiersAndUrisCopy: CodeAnalysisDiagnosticIdentifiersAndUri[] = [];
@@ -4214,8 +4324,9 @@ export class DefaultClient implements Client {
}
public onInterval(): void {
// These events can be discarded until the language client is ready. Don't queue them up.
if (this.languageClient.isInitialized && this.configuration !== undefined) {
// These events can be discarded until the language client is ready.
// Don't queue them up with this.notifyWhenLanguageClientReady calls.
if (this.innerLanguageClient !== undefined && this.configuration !== undefined) {
void this.languageClient.sendNotification(IntervalTimerNotification).catch(logAndReturn.undefined);
this.configuration.checkCppProperties();
this.configuration.checkCompileCommands();
@@ -4261,6 +4372,8 @@ export class DefaultClient implements Client {
}
public async handleReferencesIcon(): Promise<void> {
await this.ready;
workspaceReferences.UpdateProgressUICounter(this.model.referencesCommandMode.Value);
// If the search is find all references, preview partial results.
@@ -4394,6 +4507,9 @@ class NullClient implements Client {
readonly ready: Promise<void> = Promise.resolve();
async enqueue<T>(task: () => Promise<T>) {
return task();
}
public get InitializingWorkspaceChanged(): vscode.Event<boolean> { return this.booleanEvent.event; }
public get IndexingWorkspaceChanged(): vscode.Event<boolean> { return this.booleanEvent.event; }
public get ParsingWorkspaceChanged(): vscode.Event<boolean> { return this.booleanEvent.event; }
@@ -121,6 +121,7 @@ export class ClientCollection {
const client: cpptools.Client = pair[1];
const newClient: cpptools.Client = this.createClient(client.RootFolder, true);
await newClient.ready;
for (const document of client.TrackedDocuments.values()) {
this.transferOwnership(document, client);
await newClient.sendDidOpen(document);
+1 -2
View File
@@ -4,11 +4,10 @@
* ------------------------------------------------------------------------------------------ */
'use strict';
import * as vscode from 'vscode';
import { NotificationType, Range } from 'vscode-languageclient';
import { LanguageClient, NotificationType, Range } from 'vscode-languageclient/node';
import * as nls from 'vscode-nls';
import { Location, WorkspaceEdit } from './commonTypes';
import { CppSourceStr } from './extension';
import { LanguageClient } from './languageClient';
import { LocalizeStringParams, getLocalizedString } from './localization';
import { CppSettings } from './settings';
import { makeVscodeLocation, makeVscodeRange, makeVscodeTextEdits, rangeEquals } from './utils';
@@ -14,7 +14,6 @@ import * as vscode from 'vscode';
import * as nls from 'vscode-nls';
import * as which from 'which';
import { logAndReturn, returns } from '../Utility/Async/returns';
import { escapePathForSquiggles } from '../Utility/Text/escape';
import * as util from '../common';
import { isWindows } from '../constants';
import { getOutputChannelLogger } from '../logger';
@@ -136,7 +135,7 @@ export interface CompilerDefaults {
trustedCompilerFound: boolean;
}
export class CppProperties implements vscode.Disposable {
export class CppProperties {
private client: DefaultClient;
private rootUri: vscode.Uri | undefined;
private propertiesFile: vscode.Uri | undefined | null = undefined; // undefined and null values are handled differently
@@ -2120,8 +2119,10 @@ export class CppProperties implements vscode.Disposable {
continue;
}
// Escape the parsed path for a literal regex match against its JSON spelling.
const escapedPath: string = escapePathForSquiggles(curPath);
// Escape the path string for literal use in a regular expression
// Need to escape any quotes to match the original text
let escapedPath: string = curPath.replace(/"/g, '\\"');
escapedPath = escapedPath.replace(/[-\"\/\\^$*+?.()|[\]{}]/g, '\\$&');
// Create a pattern to search for the path with either a quote or semicolon immediately before and after,
// and extend that pattern to the next quote before and next quote after it.
+12 -4
View File
@@ -185,11 +185,11 @@ export async function activate(): Promise<void> {
disposables.push(vscode.workspace.onDidOpenTextDocument(onDidOpenTextDocument));
disposables.push(vscode.workspace.onDidChangeConfiguration(onDidChangeSettings));
disposables.push(vscode.window.onDidChangeTextEditorVisibleRanges(e => onDidChangeTextEditorVisibleRanges(e)));
disposables.push(vscode.window.onDidChangeActiveTextEditor(e => onDidChangeActiveTextEditor(e)));
disposables.push(vscode.window.onDidChangeTextEditorVisibleRanges((e) => clients.ActiveClient.enqueue(async () => onDidChangeTextEditorVisibleRanges(e))));
disposables.push(vscode.window.onDidChangeActiveTextEditor((e) => clients.ActiveClient.enqueue(async () => onDidChangeActiveTextEditor(e))));
ui.didChangeActiveEditor(); // Handle already active documents (for non-cpp files that we don't register didOpen).
disposables.push(vscode.window.onDidChangeTextEditorSelection(e => onDidChangeTextEditorSelection(e)));
disposables.push(vscode.window.onDidChangeVisibleTextEditors(e => onDidChangeVisibleTextEditors(e)));
disposables.push(vscode.window.onDidChangeTextEditorSelection((e) => clients.ActiveClient.enqueue(async () => onDidChangeTextEditorSelection(e))));
disposables.push(vscode.window.onDidChangeVisibleTextEditors((e) => clients.ActiveClient.enqueue(async () => onDidChangeVisibleTextEditors(e))));
updateLanguageConfigurations();
reportMacCrashes();
@@ -565,10 +565,12 @@ async function selectClient(): Promise<Client> {
}
async function onResetDatabase(): Promise<void> {
await clients.ActiveClient.ready;
return clients.ActiveClient.resetDatabase();
}
async function onRescanCompilers(sender?: any): Promise<void> {
await clients.ActiveClient.ready;
return clients.ActiveClient.rescanCompilers(sender);
}
@@ -577,6 +579,7 @@ async function onAddMissingInclude(): Promise<void> {
}
async function selectIntelliSenseConfiguration(sender?: any): Promise<void> {
await clients.ActiveClient.ready;
return clients.ActiveClient.promptSelectIntelliSenseConfiguration(sender);
}
@@ -874,6 +877,7 @@ async function onFindAllReferences(uri: vscode.Uri, position: vscode.Position, t
return undefined;
}
await client.ready;
const result = await sendFindAllReferencesRequest(client, uri, position, token ?? CancellationToken.None);
return result?.locations;
}
@@ -888,6 +892,7 @@ async function onGoToDefinition(uri: vscode.Uri, position: vscode.Position, toke
return undefined;
}
await client.ready;
return sendGoToDefinitionRequest(client, uri, position, token ?? CancellationToken.None);
}
@@ -901,6 +906,7 @@ async function onPrepareCallHierarchy(uri: vscode.Uri, position: vscode.Position
return undefined;
}
await client.ready;
return sendPrepareCallHierarchyRequest(client, uri, position, token ?? CancellationToken.None);
}
@@ -914,6 +920,7 @@ async function onCallHierarchyCallsTo(item: vscode.CallHierarchyItem, token?: vs
return undefined;
}
await client.ready;
return sendCallHierarchyCallsToRequest(client, item, token ?? CancellationToken.None);
}
@@ -927,6 +934,7 @@ async function onCallHierarchyCallsFrom(item: vscode.CallHierarchyItem, token?:
return undefined;
}
await client.ready;
return sendCallHierarchyCallsFromRequest(client, item, token ?? CancellationToken.None);
}
@@ -1,90 +0,0 @@
/* --------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All Rights Reserved.
* See 'LICENSE' in the project root for license information.
* ------------------------------------------------------------------------------------------ */
'use strict';
import { Disposable } from 'vscode';
import { CancellationToken, NotificationHandler, NotificationType, RequestType } from 'vscode-languageclient';
import * as rpc from 'vscode-languageclient/node';
import { ManualSignal } from '../Utility/Async/manualSignal';
export class LanguageClient {
private _rpcClient?: rpc.LanguageClient;
private readonly _started = new ManualSignal<void>(true);
/**
* Returns a promise that waits for the RPC connection to be ready.
*/
public get ready(): Promise<void> {
return this._started;
}
/**
* Set the initialization state of the underlying RPC client.
* This is used to indicate that the underlying RPC client has been initialized and is ready to send requests.
* If resetting the RPC client, set this to false.
*/
public set isStarted(value: boolean) {
if (value) {
this._started.resolve();
} else {
this._started.reset();
}
}
/**
* Returns true if the underlying RPC client has been initialized.
* Used in cases where a quick check of the initialization state is desired instead of waiting on the `ready` promise.
*/
public get isInitialized(): boolean {
return !!this._rpcClient;
}
/**
* Set the underlying RPC client.
* This should only be called once during initialization.
*/
public setLanguageClient(languageClient?: rpc.LanguageClient): void {
this._rpcClient = languageClient;
}
/**
* Validate and return the underlying RPC client.
* Strips away the `undefined` type from `this._rpcClient`.
*/
private get rpcClient(): rpc.LanguageClient {
if (!this._rpcClient) {
throw new Error("Attempting to use languageClient before initialized");
}
return this._rpcClient;
}
public get protocol2CodeConverter(): rpc.LanguageClient["protocol2CodeConverter"] {
return this.rpcClient.protocol2CodeConverter;
}
public get code2ProtocolConverter(): rpc.LanguageClient["code2ProtocolConverter"] {
return this.rpcClient.code2ProtocolConverter;
}
public async sendRequest<P, R, E>(type: RequestType<P, R, E>, params: P, token?: CancellationToken): Promise<R> {
await this.ready;
return this.rpcClient.sendRequest(type, params, token);
}
public async sendNotification<P>(type: NotificationType<P>, params?: P): Promise<void> {
await this.ready;
return this.rpcClient.sendNotification(type, params);
}
public onNotification<P>(type: NotificationType<P>, handler: NotificationHandler<P>): Disposable {
// These messages are received from cpptools, and therefore it is not needed to await the ready signal.
return this.rpcClient.onNotification(type, handler);
}
public stop(): Promise<void> {
return this._rpcClient?.stop() ?? Promise.resolve();
}
}
@@ -45,8 +45,10 @@ export function createProtocolFilter(): Middleware {
// client.takeOwnership() will call client.TrackedDocuments.add() again, but that's ok. It's a Set.
client.takeOwnership(document);
void sendMessage(document);
const cppEditors: vscode.TextEditor[] = vscode.window.visibleTextEditors.filter(e => util.isCpp(e.document));
void client.onDidChangeVisibleTextEditors(cppEditors).catch(logAndReturn.undefined);
client.ready.then(() => {
const cppEditors: vscode.TextEditor[] = vscode.window.visibleTextEditors.filter(e => util.isCpp(e.document));
client.onDidChangeVisibleTextEditors(cppEditors).catch(logAndReturn.undefined);
}).catch(logAndReturn.undefined);
}
}
},
-9
View File
@@ -1,9 +0,0 @@
/* --------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All Rights Reserved.
* See 'LICENSE' in the project root for license information.
* ------------------------------------------------------------------------------------------ */
export function escapePathForSquiggles(s: string): string {
return s.replace(/[-"\/\\^$*+?.()|[\]{}]/g, (character: string): string =>
character === '"' ? '\\\\"' : `\\${character}`);
}
-32
View File
@@ -1,32 +0,0 @@
/* --------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All Rights Reserved.
* See 'LICENSE' in the project root for license information.
* ------------------------------------------------------------------------------------------ */
import { describe, it } from 'mocha';
import { doesNotMatch, match, strictEqual } from 'node:assert';
import { escapePathForSquiggles } from '../../src/Utility/Text/escape';
describe('Text escaping', () => {
it('escapes paths for matching their JSON spelling', () => {
strictEqual(escapePathForSquiggles('"'), '\\\\"');
strictEqual(escapePathForSquiggles('\\'), '\\\\');
strictEqual(escapePathForSquiggles('.*'), '\\.\\*');
const parsedPath: string = String.raw`C:\src"quoted"`;
const sourcePath: string = String.raw`C:\src\"quoted\"`;
const pattern: RegExp = new RegExp(`^${escapePathForSquiggles(parsedPath)}$`);
match(sourcePath, pattern);
doesNotMatch(parsedPath, pattern);
});
it('handles repeated backslashes and regex metacharacters', () => {
const parsedPath: string = String.raw`C:\\sdk\\[headers]+(x)?.h\\say"hello"and"goodbye`;
const sourcePath: string = String.raw`C:\\sdk\\[headers]+(x)?.h\\say\"hello\"and\"goodbye`;
const pattern: RegExp = new RegExp(`^${escapePathForSquiggles(parsedPath)}$`);
match(sourcePath, pattern);
doesNotMatch(String.raw`C:\sdk\[headers]+(x)?.h\say\"hello\"and\"goodbye`, pattern);
doesNotMatch(String.raw`C:\\sdk\\headers+(x)?.h\\say\"hello\"and\"goodbye`, pattern);
});
});