Compare commits

...
Author SHA1 Message Date
Bob Brown bdbac5714b Update some comments 2026-08-14 10:46:07 -07:00
Bob Brown 4d01799159 Merge branch 'main' into bobbrow/languageClientRefactor 2026-08-14 09:02:24 -07:00
dependabot[bot] d41ba04e26 Bump the github-actions group with 2 updates (#14678)
Bumps the github-actions group with 2 updates: [github/codeql-action/init](https://github.com/github/codeql-action) and [github/codeql-action/analyze](https://github.com/github/codeql-action).


Updates `github/codeql-action/init` from 4.37.4 to 4.37.6
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](https://github.com/github/codeql-action/compare/f205ea1c3313d32999d8d6a48b4f6530d4437b38...5595ccaf912efad79be6eef63a5619ff05969be3)

Updates `github/codeql-action/analyze` from 4.37.4 to 4.37.6
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](https://github.com/github/codeql-action/compare/f205ea1c3313d32999d8d6a48b4f6530d4437b38...5595ccaf912efad79be6eef63a5619ff05969be3)

---
updated-dependencies:
- dependency-name: github/codeql-action/init
  dependency-version: 4.37.6
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: github-actions
- dependency-name: github/codeql-action/analyze
  dependency-version: 4.37.6
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: github-actions
...

Signed-off-by: dependabot[bot] <[email protected]>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-08-13 18:04:49 -07:00
Colen Garoutte-Carsonand@8prashant (Prashant Kumar Rai) 592661994a Update inactive regions to support column granularity (#14667)
Co-authored-by: @8prashant (Prashant Kumar Rai)
2026-08-13 13:41:59 -07:00
Sean McManus 98055e0aa8 Fix configuration path regex escaping (#14674) 2026-08-13 12:11:18 -07:00
Sean McManus 7a7c1f421b Update changelog and version for 1.33.8 (#14671) 2026-08-12 15:10:35 -07:00
Sean McManus 82c66b05d3 Handle localization path casing generically (#14669) 2026-08-12 13:20:37 -07:00
Sean McManus 08baa1d0d2 Fix IntelliSense translation strings. (#14668)
* Fix IntelliSense translation strings.
2026-08-12 10:52:21 -07:00
Sean McManus 9d19aa858f Validate Yarn lockfile selectors (#14663) 2026-08-11 12:14:31 -07:00
Bob Brown dde8653da5 address PR feedback 2026-07-29 10:16:44 -07:00
Bob Brown 154f56e4c7 fix a bug found while testing 2026-07-29 09:50:11 -07:00
Bob Brown 95717b4eb4 self review 2026-07-29 08:59:36 -07:00
Bob Brown 2587d00a47 remove some more ready awaits 2026-07-28 17:27:45 -07:00
Bob Brown 77c1a14635 More cleanup 2026-07-28 17:05:14 -07:00
Bob Brown 07a4927c41 cleaning up and removing enqueue 2026-07-28 15:07:02 -07:00
Bob Brown 5351c00667 ensure that the language client is ready before all messages are sent 2026-07-27 17:15:42 -07:00
42 changed files with 439 additions and 375 deletions
+2 -2
View File
@@ -63,7 +63,7 @@ jobs:
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@f205ea1c3313d32999d8d6a48b4f6530d4437b38 # v4.37.4
uses: github/codeql-action/init@5595ccaf912efad79be6eef63a5619ff05969be3 # v4.37.6
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@f205ea1c3313d32999d8d6a48b4f6530d4437b38 # v4.37.4
uses: github/codeql-action/analyze@5595ccaf912efad79be6eef63a5619ff05969be3 # v4.37.6
with:
category: "/language:${{matrix.language}}"
@@ -34,6 +34,10 @@ jobs:
with:
node-version: 24
- name: Validate Yarn lockfile
run: yarn test-yarn-lock && yarn verify-yarn-lock
working-directory: Extension
- name: Install Dependencies
run: yarn install ${{ inputs.yarn-args }}
working-directory: Extension
+7 -2
View File
@@ -5,7 +5,7 @@
import * as fs from "fs";
import * as path from 'path';
import { parseString } from 'xml2js';
import { mkdir, write } from './common';
import { glob, mkdir, write } from './common';
export async function main() {
@@ -45,11 +45,16 @@ 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");
+97
View File
@@ -0,0 +1,97 @@
import fs from 'node:fs';
import path from 'node:path';
import process from 'node:process';
import { fileURLToPath, pathToFileURL } from 'node:url';
const dependencySections = ['dependencies', 'devDependencies', 'optionalDependencies'];
function parseLockfileKey(key) {
const selectors = [];
let selectorStart = 0;
let quoted = false;
let escaped = false;
for (let index = 0; index < key.length; index++) {
const character = key[index];
if (escaped) {
escaped = false;
} else if (character === '\\' && quoted) {
escaped = true;
} else if (character === '"') {
quoted = !quoted;
} else if (character === ',' && !quoted) {
selectors.push(key.slice(selectorStart, index));
selectorStart = index + 1;
}
}
selectors.push(key.slice(selectorStart));
return selectors.map(selector => {
const trimmedSelector = selector.trim();
return trimmedSelector.startsWith('"') ? JSON.parse(trimmedSelector) : trimmedSelector;
});
}
function parseLockfileSelectors(lockfile) {
const selectors = new Set();
for (const line of lockfile.split(/\r?\n/)) {
if (/^[^\s#].*:\s*$/.test(line)) {
for (const selector of parseLockfileKey(line.replace(/:\s*$/, ''))) {
selectors.add(selector);
}
}
}
return selectors;
}
function getResolutionPackageName(pattern) {
const segments = pattern.split('/');
const packageName = segments.at(-1);
const scope = segments.at(-2);
return scope?.startsWith('@') ? `${scope}/${packageName}` : packageName;
}
function getExpectedSelectors(manifest) {
const selectors = [];
for (const section of dependencySections) {
for (const [packageName, range] of Object.entries(manifest[section] ?? {})) {
selectors.push(`${packageName}@${range}`);
}
}
for (const [pattern, range] of Object.entries(manifest.resolutions ?? {})) {
selectors.push(`${getResolutionPackageName(pattern)}@${range}`);
}
return selectors;
}
function findMissingSelectors(manifest, lockfile) {
const lockfileSelectors = parseLockfileSelectors(lockfile);
return getExpectedSelectors(manifest)
.filter(selector => !lockfileSelectors.has(selector))
.sort();
}
function validateYarnLock(packageJsonPath, yarnLockPath) {
const manifest = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'));
const lockfile = fs.readFileSync(yarnLockPath, 'utf8');
const missingSelectors = findMissingSelectors(manifest, lockfile);
if (missingSelectors.length > 0) {
throw new Error(`yarn.lock is missing selectors required by package.json:\n${missingSelectors.map(selector => ` ${selector}`).join('\n')}\nRun yarn install to update yarn.lock.`);
}
}
const invokedUrl = process.argv[1] ? pathToFileURL(path.resolve(process.argv[1])).href : undefined;
if (invokedUrl === import.meta.url) {
const extensionRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..');
const packageJsonPath = process.argv[2] ?? path.join(extensionRoot, 'package.json');
const yarnLockPath = process.argv[3] ?? path.join(extensionRoot, 'yarn.lock');
try {
validateYarnLock(packageJsonPath, yarnLockPath);
} catch (error) {
process.stderr.write(`${error instanceof Error ? error.message : String(error)}\n`);
process.exitCode = 1;
}
}
export { findMissingSelectors, getExpectedSelectors, parseLockfileSelectors, validateYarnLock };
@@ -0,0 +1,41 @@
import assert from 'node:assert/strict';
import test from 'node:test';
import { findMissingSelectors } from './verifyYarnLock.mjs';
test('reports a stale resolution selector', () => {
const manifest = { resolutions: { 'fast-uri': '^3.1.5' } };
const lockfile = `fast-uri@^3.0.1, fast-uri@^3.1.4:
version "3.1.5"
`;
assert.deepEqual(findMissingSelectors(manifest, lockfile), ['fast-uri@^3.1.5']);
});
test('accepts direct, scoped, and nested resolution selectors', () => {
const manifest = {
dependencies: { '@scope/direct': '^1.0.0' },
devDependencies: { 'gulp-typescript': '^5.0.1' },
resolutions: {
'@scope/resolved': '^2.0.0',
'gulp-typescript/**/glob-parent': '^5.1.2',
'parent/**/@nested/package': '~3.0.0'
}
};
const lockfile = `"@nested/package@~3.0.0":
version "3.0.1"
"@scope/direct@^1.0.0":
version "1.0.0"
"@scope/resolved@^2.0.0":
version "2.0.0"
glob-parent@^3.1.0, glob-parent@^5.1.2:
version "5.1.2"
gulp-typescript@^5.0.1:
version "5.0.1"
`;
assert.deepEqual(findMissingSelectors(manifest, lockfile), []);
});
+33 -71
View File
@@ -1,93 +1,55 @@
# C/C++ for Visual Studio Code Changelog
## 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
## Version 1.33.8: August 17, 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
+2 -3
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í.",
null,
"too many nested user-defined conversions (possible cycle of converting routines)",
null,
null,
null,
@@ -3747,6 +3747,5 @@
"„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",
"too many nested user-defined conversions (possible cycle of converting routines)"
"Zkrácená syntaxe šablony funkce není standardní pro vodítka dedukce"
]
+2 -3
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.",
null,
"too many nested user-defined conversions (possible cycle of converting routines)",
null,
null,
null,
@@ -3747,6 +3747,5 @@
"„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.",
"too many nested user-defined conversions (possible cycle of converting routines)"
"Die abgekürzte Funktionsvorlagensyntax entspricht nicht dem Standard für Deduktionsleitfäden."
]
+2 -3
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.",
null,
"too many nested user-defined conversions (possible cycle of converting routines)",
null,
null,
null,
@@ -3747,6 +3747,5 @@
"\"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",
"too many nested user-defined conversions (possible cycle of converting routines)"
"La sintaxis abreviada de las plantillas de funciones no es estándar para las guías de deducción"
]
+2 -3
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.",
null,
"too many nested user-defined conversions (possible cycle of converting routines)",
null,
null,
null,
@@ -3747,6 +3747,5 @@
"« 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",
"too many nested user-defined conversions (possible cycle of converting routines)"
"la syntaxe abrégée du modèle de fonction nest pas standard pour les guides de déduction"
]
+2 -3
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.",
null,
"too many nested user-defined conversions (possible cycle of converting routines)",
null,
null,
null,
@@ -3747,6 +3747,5 @@
"'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",
"too many nested user-defined conversions (possible cycle of converting routines)"
"la sintassi abbreviata del modello di funzione non è standard per le guide alla deduzione"
]
+2 -3
View File
@@ -2999,7 +2999,7 @@
"'this' への代入 (旧形式) は C++11 モードと互換性がありません",
"不明なエラーが発生しました。IntelliSense PCH ファイルは生成されませんでした。",
"1 つ以上のリモート パスを既存のローカル パスにマップできません。IntelliSense の機能が低下する可能性があります。",
null,
"too many nested user-defined conversions (possible cycle of converting routines)",
null,
null,
null,
@@ -3747,6 +3747,5 @@
"'static' はここでは非標準です",
"%nd は、明示的な列挙型ベースなしで以前に宣言されました",
"見つからない 'typename' はここでは非標準です",
"省略形の関数テンプレート構文は、推論ガイドでは非標準です",
"too many nested user-defined conversions (possible cycle of converting routines)"
"省略形の関数テンプレート構文は、推論ガイドでは非標準です"
]
+2 -3
View File
@@ -2999,7 +2999,7 @@
"'this'에 대한 할당(오래된 구문)은 C++11 모드와 호환되지 않습니다.",
"알 수 없는 오류가 발생했습니다. IntelliSense PCH 파일이 생성되지 않았습니다.",
"하나 이상의 원격 경로를 기존 로컬 경로에 매핑할 수 없습니다. IntelliSense 성능이 저하될 수 있습니다.",
null,
"too many nested user-defined conversions (possible cycle of converting routines)",
null,
null,
null,
@@ -3747,6 +3747,5 @@
"여기서 'static'은 표준이 아닙니다.",
"%nd은(는) 이전에 명시적 열거형 기반 없이 선언되었습니다.",
"여기서 누락된 'typename'이 표준이 아닙니다.",
"약식 함수 템플릿 구문은 추론 가이드에 대한 표준이 아닙니다.",
"too many nested user-defined conversions (possible cycle of converting routines)"
"약식 함수 템플릿 구문은 추론 가이드에 대한 표준이 아닙니다."
]
+2 -3
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.",
null,
"too many nested user-defined conversions (possible cycle of converting routines)",
null,
null,
null,
@@ -3747,6 +3747,5 @@
"„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",
"too many nested user-defined conversions (possible cycle of converting routines)"
"skrócona składnia szablonu funkcji jest niestandardowa dla przewodników dedukcji"
]
+2 -3
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.",
null,
"too many nested user-defined conversions (possible cycle of converting routines)",
null,
null,
null,
@@ -3747,6 +3747,5 @@
"\"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",
"too many nested user-defined conversions (possible cycle of converting routines)"
"a sintaxe abreviada de template de função é não padrão para guias de dedução"
]
+2 -3
View File
@@ -2999,7 +2999,7 @@
"назначение устаревшему элементу this несовместимо с режимом C++11",
"произошла неизвестная ошибка. PCH-файл IntelliSense не был создан.",
"Один или несколько удаленных путей не могут быть сопоставлены с существующими локальными путями. Использование IntelliSense может быть ограничено.",
null,
"too many nested user-defined conversions (possible cycle of converting routines)",
null,
null,
null,
@@ -3747,6 +3747,5 @@
"\"static\" является здесь нестандартным",
"%nd ранее был объявлен без явной базы перечисления",
"отсутствие typename здесь является нестандартным",
"сокращенный синтаксис шаблона функции не является стандартным для правил дедукции",
"too many nested user-defined conversions (possible cycle of converting routines)"
"сокращенный синтаксис шаблона функции не является стандартным для правил дедукции"
]
+2 -3
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.",
null,
"too many nested user-defined conversions (possible cycle of converting routines)",
null,
null,
null,
@@ -3747,6 +3747,5 @@
"'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",
"too many nested user-defined conversions (possible cycle of converting routines)"
"kısaltılmış işlev şablonu sözdizimi çıkarsama kılavuzları için standart değil"
]
+2 -3
View File
@@ -2999,7 +2999,7 @@
"对 \"this\" 计时错误的赋值与 C++11 模式不兼容",
"出现了未知错误。未生成 IntelliSense PCH 文件。",
"一个或多个远程路径无法映射到现有本地路径。IntelliSense 体验可能会降级。",
null,
"too many nested user-defined conversions (possible cycle of converting routines)",
null,
null,
null,
@@ -3747,6 +3747,5 @@
"此处使用 \"static\" 不符合标准",
"之前声明 %nd 时未指定显式枚举基类型",
"此处缺少 'typename' 属于非标准用法",
"缩写函数模板语法对于推导指南是不标准的",
"too many nested user-defined conversions (possible cycle of converting routines)"
"缩写函数模板语法对于推导指南是不标准的"
]
+2 -3
View File
@@ -2999,7 +2999,7 @@
"'this' 用法已過時,且這種指派與 C++11 模式不相容",
"發生未知的錯誤。未產生 IntelliSense PCH 檔案。",
"有一或多個遠端路徑無法對應到現有的本機路徑。IntelliSense 的效能可能會變差。",
null,
"too many nested user-defined conversions (possible cycle of converting routines)",
null,
null,
null,
@@ -3747,6 +3747,5 @@
"此處使用的 'static' 非標準",
"%nd 先前宣告時未明確指定的列舉基底",
"此處缺少 'typename' 非標準用法",
"簡化函式範本語法在推導指南中並非標準用法",
"too many nested user-defined conversions (possible cycle of converting routines)"
"簡化函式範本語法在推導指南中並非標準用法"
]
+3 -1
View File
@@ -2,7 +2,7 @@
"name": "cpptools",
"displayName": "C/C++",
"description": "C/C++ IntelliSense, debugging, and code browsing.",
"version": "1.33.7-main",
"version": "1.33.8-main",
"publisher": "ms-vscode",
"icon": "LanguageCCPP_color_128x.png",
"readme": "README.md",
@@ -7163,6 +7163,8 @@
"scripts": "ts-node -T .scripts/scripts.ts",
"show": "ts-node -T .scripts/clean.ts show",
"clean": "ts-node -T .scripts/clean.ts",
"test-yarn-lock": "node --test .scripts/verifyYarnLock.test.mjs",
"verify-yarn-lock": "node .scripts/verifyYarnLock.mjs",
"test": "yarn install && (yarn verify prep --quiet || yarn prep) && (yarn verify compiled --quiet || yarn build) && ts-node -T .scripts/test.ts",
"code": "yarn install && (yarn verify compiled --quiet || yarn build) && yarn verify binaries && ts-node -T .scripts/code.ts",
"verify": "ts-node -T .scripts/verify.ts",
@@ -16,7 +16,6 @@ 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;
@@ -30,8 +29,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(client: DefaultClient) {
this.client = client;
constructor(private client: DefaultClient) {
}
public async getCachedChatModel(): Promise<vscode.LanguageModelChat | undefined> {
@@ -171,7 +170,6 @@ 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,11 +10,10 @@ 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(client: DefaultClient) {
this.client = client;
constructor(private client: DefaultClient) {
}
public async provideHover(document: vscode.TextDocument, position: vscode.Position, token: vscode.CancellationToken): Promise<vscode.Hover | undefined> {
@@ -36,7 +35,6 @@ 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,15 +214,11 @@ 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(client: DefaultClient) {
this.client = client;
constructor(private client: DefaultClient) {
}
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();
@@ -261,7 +257,6 @@ 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";
@@ -316,8 +311,6 @@ 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,9 +40,7 @@ export const GetCodeActionsRequest: RequestType<GetCodeActionsRequestParams, Get
new RequestType<GetCodeActionsRequestParams, GetCodeActionsResult, void>('cpptools/getCodeActions');
export class CodeActionProvider implements vscode.CodeActionProvider {
private client: DefaultClient;
constructor(client: DefaultClient) {
this.client = client;
constructor(private client: DefaultClient) {
}
private static inlineMacroKind: vscode.CodeActionKind = vscode.CodeActionKind.RefactorInline.append("macro");
@@ -51,7 +49,6 @@ 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,9 +11,7 @@ import { CppSettings, OtherSettings } from '../settings';
import { makeVscodeTextEdits } from '../utils';
export class DocumentFormattingEditProvider implements vscode.DocumentFormattingEditProvider {
private client: DefaultClient;
constructor(client: DefaultClient) {
this.client = client;
constructor(private client: DefaultClient) {
}
public async provideDocumentFormattingEdits(document: vscode.TextDocument, options: vscode.FormattingOptions, token: vscode.CancellationToken): Promise<vscode.TextEdit[]> {
@@ -21,7 +19,6 @@ 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,9 +11,7 @@ import { CppSettings } from '../settings';
import { makeVscodeTextEdits } from '../utils';
export class DocumentRangeFormattingEditProvider implements vscode.DocumentRangeFormattingEditProvider {
private client: DefaultClient;
constructor(client: DefaultClient) {
this.client = client;
constructor(private client: DefaultClient) {
}
public async provideDocumentRangeFormattingEdits(document: vscode.TextDocument, range: vscode.Range,
@@ -22,7 +20,6 @@ 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,14 +58,12 @@ 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 defaultClient.languageClient.sendRequest(GetDocumentSymbolRequest, params, token);
response = await client.languageClient.sendRequest(GetDocumentSymbolRequest, params, token);
} catch (e: any) {
if (e instanceof ResponseError && (e.code === RequestCancelled || e.code === ServerCancelled)) {
throw new vscode.CancellationError();
@@ -56,14 +56,10 @@ export async function sendFindAllReferencesRequest(client: DefaultClient, uri: v
}
export class FindAllReferencesProvider implements vscode.ReferenceProvider {
private client: DefaultClient;
constructor(client: DefaultClient) {
this.client = client;
constructor(private client: DefaultClient) {
}
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,7 +14,6 @@ interface FoldingRangeRequestInfo {
}
export class FoldingRangeProvider implements vscode.FoldingRangeProvider {
private client: DefaultClient;
public onDidChangeFoldingRangesEvent = new vscode.EventEmitter<void>();
public onDidChangeFoldingRanges?: vscode.Event<void>;
@@ -22,12 +21,11 @@ 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(client: DefaultClient) {
this.client = client;
constructor(private client: DefaultClient) {
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,9 +11,7 @@ import { CppSettings } from '../settings';
import { makeVscodeTextEdits } from '../utils';
export class OnTypeFormattingEditProvider implements vscode.OnTypeFormattingEditProvider {
private client: DefaultClient;
constructor(client: DefaultClient) {
this.client = client;
constructor(private client: DefaultClient) {
}
public async provideOnTypeFormattingEdits(document: vscode.TextDocument, position: vscode.Position, ch: string, options: vscode.FormattingOptions, token: vscode.CancellationToken): Promise<vscode.TextEdit[]> {
@@ -21,7 +19,6 @@ 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,14 +18,10 @@ const RenameRequest: RequestType<ReferencesParams, ReferencesResult, void> =
new RequestType<ReferencesParams, ReferencesResult, void>('cpptools/rename');
export class RenameProvider implements vscode.RenameProvider {
private client: DefaultClient;
constructor(client: DefaultClient) {
this.client = client;
constructor(private client: DefaultClient) {
}
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,8 +5,7 @@
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,9 +10,7 @@ import { RequestCancelled, ServerCancelled } from '../protocolFilter';
import { makeVscodeLocation } from '../utils';
export class WorkspaceSymbolProvider implements vscode.WorkspaceSymbolProvider {
private client: DefaultClient;
constructor(client: DefaultClient) {
this.client = client;
constructor(private client: DefaultClient) {
}
public async provideWorkspaceSymbols(query: string, token: vscode.CancellationToken): Promise<vscode.SymbolInformation[]> {
+67 -183
View File
@@ -23,19 +23,16 @@ 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, LanguageClientOptions, NotificationType, Position, Range, RequestType, ResponseError, TextDocumentIdentifier, TextDocumentPositionParams } from 'vscode-languageclient';
import { LanguageClient, ServerOptions } from 'vscode-languageclient/node';
import { CloseAction, DidOpenTextDocumentParams, ErrorAction, NotificationType, Position, Range, RequestType, ResponseError, TextDocumentIdentifier, TextDocumentPositionParams } from 'vscode-languageclient';
import * as rpc 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';
@@ -60,6 +57,7 @@ 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';
@@ -88,7 +86,7 @@ export function hasTrustedCompilerPaths(): boolean {
}
// Data shared by all clients.
let languageClient: LanguageClient;
const languageClient: LanguageClient = new LanguageClient();
let firstClientStarted: Promise<{ wasShutdown: boolean }>;
let languageClientHasCrashed: boolean = false;
let languageClientCrashedNeedsRestart: boolean = false;
@@ -221,11 +219,18 @@ interface FileChangedParams extends WorkspaceFolderParams {
uri: string;
}
interface InputRegion {
interface InputLineRange {
startLine: number;
endLine: number;
}
interface InputRegion {
startLine: number;
startColumn: number;
endLine: number;
endColumn: number;
}
interface DecorationRangesPair {
decoration: vscode.TextEditorDecorationType;
ranges: vscode.Range[];
@@ -374,7 +379,7 @@ export enum FoldingRangeKind {
export interface CppFoldingRange {
kind: FoldingRangeKind;
range: InputRegion;
range: InputLineRange;
}
export interface GetFoldingRangesResult {
@@ -781,7 +786,6 @@ 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>;
@@ -893,7 +897,6 @@ 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;
@@ -909,7 +912,6 @@ 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;
@@ -934,20 +936,6 @@ 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();
@@ -964,7 +952,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.innerLanguageClient !== undefined; }
public isInitialized(): boolean { return this.languageClient.isInitialized; }
public getShowConfigureIntelliSenseButton(): boolean { return this.showConfigureIntelliSenseButton; }
public setShowConfigureIntelliSenseButton(show: boolean): void { this.showConfigureIntelliSenseButton = show; }
@@ -999,10 +987,7 @@ export class DefaultClient implements Client {
}
public get languageClient(): LanguageClient {
if (!this.innerLanguageClient) {
throw new Error("Attempting to use languageClient before initialized");
}
return this.innerLanguageClient;
return languageClient;
}
public get configuration(): configs.CppProperties {
@@ -1376,19 +1361,18 @@ 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.
DefaultClient.isStarted.reset();
this.languageClient.isStarted = false;
this.languageClient.setLanguageClient(undefined);
}
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;
@@ -1408,8 +1392,7 @@ export class DefaultClient implements Client {
ui = getUI();
ui.bind(this);
if ((await firstClientStarted).wasShutdown) {
this.isSupported = false;
DefaultClient.isStarted.resolve();
this.languageClient.isStarted = true;
return;
}
@@ -1421,7 +1404,10 @@ export class DefaultClient implements Client {
this.innerConfiguration.CompileCommandsChanged((e) => this.onCompileCommandsChanged(e));
this.disposables.push(this.innerConfiguration);
this.innerLanguageClient = languageClient;
// 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();
telemetry.logLanguageServerEvent("NonDefaultInitialCppSettings", this.settingsTracker.getUserModifiedSettings());
failureMessageShown = false;
@@ -1488,7 +1474,6 @@ 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) {
@@ -1498,14 +1483,11 @@ 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 {
@@ -1693,7 +1675,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: ServerOptions = {
const serverOptions: rpc.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 } }
};
@@ -1756,7 +1738,7 @@ export class DefaultClient implements Client {
loggingLevel: this.loggingLevel
};
const clientOptions: LanguageClientOptions = {
const clientOptions: rpc.LanguageClientOptions = {
documentSelector: [
{ scheme: 'file', language: 'c' },
{ scheme: 'file', language: 'cpp' },
@@ -1836,34 +1818,40 @@ export class DefaultClient implements Client {
// Refresh initializing state in UI.
this.model.isInitializingWorkspace.Value = true;
// 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();
// 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();
if (usesCrashHandler()) {
watchForCrashes(await languageClient.sendRequest(PreInitializationRequest, null));
watchForCrashes(await client.sendRequest(PreInitializationRequest, null));
} else if (os.platform() === "win32") {
const settings: CppSettings = new CppSettings();
if ((settings.windowsErrorReportingMode === "default" && !languageClientHasCrashed) ||
settings.windowsErrorReportingMode === "enabled") {
await languageClient.sendRequest(PreInitializationRequest, null);
await client.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 languageClient.sendRequest(InitializationRequest, cppInitializationParams);
const initializeResult = await client.sendRequest(InitializationRequest, cppInitializationParams);
// If the server requested shutdown, then reload with the failsafe (null) client.
if (initializeResult.shouldShutdown) {
await languageClient.stop();
await client.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 };
@@ -1871,7 +1859,6 @@ 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());
}
@@ -2211,7 +2198,6 @@ 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();
@@ -2279,16 +2265,12 @@ export class DefaultClient implements Client {
diagnosticsChannel.show(false);
}
public async rescanFolder(): Promise<void> {
await this.ready;
public rescanFolder(): Promise<void> {
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) {
@@ -2302,7 +2284,7 @@ export class DefaultClient implements Client {
const resultCode = await this.provideCustomConfigurationAsync(docUris, provider);
telemetry.logLanguageServerEvent('provideCustomConfigurations', { providerId, resultCode });
} finally {
onFinished();
void this.languageClient.sendNotification(FinishedRequestCustomConfig, { batchId, isProviderRegistered });
}
}
@@ -2522,9 +2504,8 @@ export class DefaultClient implements Client {
* the UI results and always re-requests (no caching).
*/
public async getIncludes(uri: vscode.Uri, maxDepth: number): Promise<GetIncludesResult> {
public getIncludes(uri: vscode.Uri, maxDepth: number): Promise<GetIncludesResult> {
const params: GetIncludesParams = { fileUri: uri.toString(), maxDepth };
await this.ready;
return this.languageClient.sendRequest(IncludesRequest, params);
}
@@ -2545,82 +2526,11 @@ export class DefaultClient implements Client {
}
/**
* 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
* 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.
*/
get ready(): Promise<void> {
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();
return this.languageClient.ready;
}
private static async withLspCancellationHandling<T>(task: () => Promise<T>, token: vscode.CancellationToken): Promise<T> {
@@ -2672,7 +2582,7 @@ export class DefaultClient implements Client {
* listen for notifications from the language server.
*/
private registerNotifications(): void {
console.assert(this.languageClient !== undefined, "This method must not be called until this.languageClient is set in \"onReady\"");
console.assert(this.languageClient.isInitialized, "This method must not be called until the language client is initialized.");
this.languageClient.onNotification(ReloadWindowNotification, () => void util.promptForReloadWindowDueToSettingsChange());
this.languageClient.onNotification(UpdateTrustedCompilersNotification, (e) => void this.addTrustedCompiler(e.compilerPath));
@@ -2781,7 +2691,7 @@ export class DefaultClient implements Client {
* listen for file created/deleted events under the ${workspaceFolder} folder
*/
private registerFileWatcher(): void {
console.assert(this.languageClient !== undefined, "This method must not be called until this.languageClient is set in \"onReady\"");
console.assert(this.languageClient.isInitialized, "This method must not be called until the language client is initialized.");
if (this.rootFolder) {
// WARNING: The default limit on Linux is 8k, so for big directories, this can cause file watching to fail.
@@ -3054,7 +2964,8 @@ export class DefaultClient implements Client {
this.inactiveRegionsDecorations.set(uriString, currentSet);
}
Array.prototype.push.apply(currentSet.ranges, inactiveRegions.map(element => new vscode.Range(element.startLine, 0, element.endLine, 0)));
Array.prototype.push.apply(currentSet.ranges, inactiveRegions.map(element =>
new vscode.Range(element.startLine, element.startColumn, element.endLine, element.endColumn)));
// Apply the decorations to all *visible* text editors
const editors: vscode.TextEditor[] = vscode.window.visibleTextEditors.filter(e => e.document.uri.toString() === uriString);
@@ -3142,18 +3053,16 @@ export class DefaultClient implements Client {
switchHeaderSourceFileName: fileName,
workspaceFolderUri: rootUri.toString()
};
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;
// 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;
}
}
public async requestCompiler(newCompilerPath?: string): Promise<configs.CompilerDefaults> {
@@ -3233,7 +3142,6 @@ 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);
}
@@ -3250,7 +3158,6 @@ export class DefaultClient implements Client {
}
public async resetDatabase(): Promise<void> {
await this.ready;
return this.languageClient.sendNotification(ResetDatabaseNotification);
}
@@ -3262,29 +3169,24 @@ 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);
}
@@ -3419,7 +3321,6 @@ export class DefaultClient implements Client {
currentConfiguration: index,
workspaceFolderUri: this.RootUri?.toString()
};
await this.ready;
await this.languageClient.sendNotification(ChangeSelectedSettingNotification, params);
let configName: string = "";
@@ -3435,7 +3336,6 @@ export class DefaultClient implements Client {
uri: vscode.Uri.file(path).toString(),
workspaceFolderUri: this.RootUri?.toString()
};
await this.ready;
return this.languageClient.sendNotification(ChangeCompileCommandsNotification, params);
}
@@ -3621,7 +3521,6 @@ export class DefaultClient implements Client {
const params: WorkspaceFolderParams = {
workspaceFolderUri: this.RootUri?.toString()
};
await this.ready;
return this.languageClient.sendNotification(ClearCustomConfigurationsNotification, params);
}
@@ -3630,7 +3529,6 @@ export class DefaultClient implements Client {
const params: WorkspaceFolderParams = {
workspaceFolderUri: this.RootUri?.toString()
};
await this.ready;
return this.languageClient.sendNotification(ClearCustomBrowseConfigurationNotification, params);
}
@@ -3717,7 +3615,6 @@ 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);
@@ -3750,7 +3647,6 @@ 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;
@@ -3796,23 +3692,19 @@ export class DefaultClient implements Client {
}
}
public async handleRunCodeAnalysisOnActiveFile(): Promise<void> {
await this.ready;
public handleRunCodeAnalysisOnActiveFile(): Promise<void> {
return this.languageClient.sendNotification(CodeAnalysisNotification, { scope: CodeAnalysisScope.ActiveFile });
}
public async handleRunCodeAnalysisOnOpenFiles(): Promise<void> {
await this.ready;
public handleRunCodeAnalysisOnOpenFiles(): Promise<void> {
return this.languageClient.sendNotification(CodeAnalysisNotification, { scope: CodeAnalysisScope.OpenFiles });
}
public async handleRunCodeAnalysisOnAllFiles(): Promise<void> {
await this.ready;
public handleRunCodeAnalysisOnAllFiles(): Promise<void> {
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 });
}
@@ -3843,8 +3735,6 @@ 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[] = [];
@@ -4324,9 +4214,8 @@ export class DefaultClient implements Client {
}
public onInterval(): void {
// 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) {
// These events can be discarded until the language client is ready. Don't queue them up.
if (this.languageClient.isInitialized && this.configuration !== undefined) {
void this.languageClient.sendNotification(IntervalTimerNotification).catch(logAndReturn.undefined);
this.configuration.checkCppProperties();
this.configuration.checkCompileCommands();
@@ -4372,8 +4261,6 @@ 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.
@@ -4507,9 +4394,6 @@ 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,7 +121,6 @@ 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);
+2 -1
View File
@@ -4,10 +4,11 @@
* ------------------------------------------------------------------------------------------ */
'use strict';
import * as vscode from 'vscode';
import { LanguageClient, NotificationType, Range } from 'vscode-languageclient/node';
import { NotificationType, Range } from 'vscode-languageclient';
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,6 +14,7 @@ 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';
@@ -135,7 +136,7 @@ export interface CompilerDefaults {
trustedCompilerFound: boolean;
}
export class CppProperties {
export class CppProperties implements vscode.Disposable {
private client: DefaultClient;
private rootUri: vscode.Uri | undefined;
private propertiesFile: vscode.Uri | undefined | null = undefined; // undefined and null values are handled differently
@@ -2119,10 +2120,8 @@ export class CppProperties {
continue;
}
// 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, '\\$&');
// Escape the parsed path for a literal regex match against its JSON spelling.
const escapedPath: string = escapePathForSquiggles(curPath);
// 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.
+4 -12
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) => clients.ActiveClient.enqueue(async () => onDidChangeTextEditorVisibleRanges(e))));
disposables.push(vscode.window.onDidChangeActiveTextEditor((e) => clients.ActiveClient.enqueue(async () => onDidChangeActiveTextEditor(e))));
disposables.push(vscode.window.onDidChangeTextEditorVisibleRanges(e => onDidChangeTextEditorVisibleRanges(e)));
disposables.push(vscode.window.onDidChangeActiveTextEditor(e => onDidChangeActiveTextEditor(e)));
ui.didChangeActiveEditor(); // Handle already active documents (for non-cpp files that we don't register didOpen).
disposables.push(vscode.window.onDidChangeTextEditorSelection((e) => clients.ActiveClient.enqueue(async () => onDidChangeTextEditorSelection(e))));
disposables.push(vscode.window.onDidChangeVisibleTextEditors((e) => clients.ActiveClient.enqueue(async () => onDidChangeVisibleTextEditors(e))));
disposables.push(vscode.window.onDidChangeTextEditorSelection(e => onDidChangeTextEditorSelection(e)));
disposables.push(vscode.window.onDidChangeVisibleTextEditors(e => onDidChangeVisibleTextEditors(e)));
updateLanguageConfigurations();
reportMacCrashes();
@@ -565,12 +565,10 @@ 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);
}
@@ -579,7 +577,6 @@ async function onAddMissingInclude(): Promise<void> {
}
async function selectIntelliSenseConfiguration(sender?: any): Promise<void> {
await clients.ActiveClient.ready;
return clients.ActiveClient.promptSelectIntelliSenseConfiguration(sender);
}
@@ -877,7 +874,6 @@ 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;
}
@@ -892,7 +888,6 @@ async function onGoToDefinition(uri: vscode.Uri, position: vscode.Position, toke
return undefined;
}
await client.ready;
return sendGoToDefinitionRequest(client, uri, position, token ?? CancellationToken.None);
}
@@ -906,7 +901,6 @@ async function onPrepareCallHierarchy(uri: vscode.Uri, position: vscode.Position
return undefined;
}
await client.ready;
return sendPrepareCallHierarchyRequest(client, uri, position, token ?? CancellationToken.None);
}
@@ -920,7 +914,6 @@ async function onCallHierarchyCallsTo(item: vscode.CallHierarchyItem, token?: vs
return undefined;
}
await client.ready;
return sendCallHierarchyCallsToRequest(client, item, token ?? CancellationToken.None);
}
@@ -934,7 +927,6 @@ async function onCallHierarchyCallsFrom(item: vscode.CallHierarchyItem, token?:
return undefined;
}
await client.ready;
return sendCallHierarchyCallsFromRequest(client, item, token ?? CancellationToken.None);
}
@@ -0,0 +1,90 @@
/* --------------------------------------------------------------------------------------------
* 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,10 +45,8 @@ 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);
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);
const cppEditors: vscode.TextEditor[] = vscode.window.visibleTextEditors.filter(e => util.isCpp(e.document));
void client.onDidChangeVisibleTextEditors(cppEditors).catch(logAndReturn.undefined);
}
}
},
+9
View File
@@ -0,0 +1,9 @@
/* --------------------------------------------------------------------------------------------
* 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
@@ -0,0 +1,32 @@
/* --------------------------------------------------------------------------------------------
* 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);
});
});