Compare commits

...
Author SHA1 Message Date
Sean McManus e53b190380 Merge pull request #11253 from microsoft/main
Merge (again) for 1.17.0
2023-07-26 16:56:43 -07:00
Sean McManus 4f805c4263 Update changelog (again) for 1.17.0 (#11251)
* Update changelog.
2023-07-26 16:26:40 -07:00
Michał Mąka a7870fc1b2 Added support for Toybox to remote process picker (#11175)
* Added separate remote process command for ToyBox
2023-07-26 16:08:07 -07:00
Michelle Matias 1846fd4001 Merge pull request #11250 from microsoft/main 2023-07-26 14:15:17 -07:00
Michelle Matias d48fd4343b fix merge (#11249) 2023-07-26 14:11:18 -07:00
Colen Garoutte-Carson 62e09945e3 Merge pull request #11241 from microsoft/main 2023-07-24 17:32:28 -07:00
Michelle Matias 9ce7b5a87c update change log (#11240) 2023-07-24 16:35:29 -07:00
Michelle Matias 460aee5971 'Create Declaration / Definition' command via 'Quick Fix...' hover (#11239) 2023-07-24 15:49:19 -07:00
Sean McManus 0e309a7e7f Fix config provider ordering. (#11237) 2023-07-24 11:48:18 -07:00
Sean McManus 27f9fafc73 Fix console logging. (#11233) 2023-07-24 10:38:26 -07:00
Michelle Matias c9b0db02fd Merge pull request #11230 from microsoft/main
Merge 1.17.0
2023-07-21 14:08:21 -07:00
Sean McManus 72ea4d5eb9 Update ThirdPartyNotices.txt. (#11232) 2023-07-21 13:52:52 -07:00
Michelle Matias 3c63457e38 changelog 17 (#11227) 2023-07-21 13:19:32 -07:00
Garrett Serack 477eb06f2b Fix out-of-order message handling (#11212) 2023-07-21 12:44:14 -07:00
Michelle Matias 51da619eec Merge pull request #11099 from microsoft/main
1.16.1 pre-release
2023-06-15 21:19:13 -07:00
Michelle Matias 3eb50568e9 Merge pull request #10986 from microsoft/main
[Auto] Localization - Translated Strings (#10889)
2023-05-22 13:53:52 -07:00
Michelle Matias 866b145645 Merge pull request #10975 from microsoft/main
1.16.0 pre-release
2023-05-19 15:52:02 -07:00
Sean McManus 9762fe5397 Merge pull request #10862 from microsoft/main
Merge for 1.15.3 (2nd time)
2023-04-21 19:00:16 -07:00
Sean McManus 377896c30a Merge pull request #10846 from microsoft/main
Merge for 1.15.3
2023-04-20 18:55:05 -07:00
Michelle Matias 98f13a6f11 Merge pull request #10815 from microsoft/main
Don't put the compiler selection in the global settings if using the …
2023-04-12 17:57:26 -07:00
Michelle Matias 0d85aea687 Merge pull request #10813 from microsoft/main
Revert walkthrough doc links until walkthrough is published (#10812)
2023-04-12 15:51:05 -07:00
Sean McManus 25d2b76514 Merge pull request #10811 from microsoft/main
Merge for 1.15.2
2023-04-12 11:03:43 -07:00
Sean McManus 42dfef3f6b Merge pull request #10728 from microsoft/main
Merge for 1.15.1
2023-03-22 11:43:15 -07:00
Sean McManus 1ce1e9cd71 Merge pull request #10716 from microsoft/main
Update changelog for 1.15.1. (#10708)
2023-03-21 09:53:45 -07:00
Sean McManus 65163966d5 Merge pull request #10679 from microsoft/main
Merge for 1.15.0
2023-03-15 17:17:35 -07:00
Sean McManus edf8e0a155 Merge pull request #10504 from microsoft/main
Merge for 1.14.2 (2nd time)
2023-02-09 16:30:37 -08:00
Sean McManus 4083075476 Merge pull request #10501 from microsoft/main
Merge for 1.14.2
2023-02-09 14:26:59 -08:00
Michelle Matias b745ebc218 Merge pull request #10453 from microsoft/main
1.14.1 pre-release merge
2023-02-01 14:29:00 -08:00
Michelle Matias b69d17a0f5 Merge pull request #10378 from microsoft/seanmcm/1_14_0_insiders
Merge for 1.14.0
2023-01-11 20:00:38 -08:00
Sean McManus be8b6fb693 Merge branch 'main' into seanmcm/1_14_0_insiders 2023-01-11 19:07:54 -08:00
39 changed files with 7117 additions and 6859 deletions
+4
View File
@@ -62,6 +62,8 @@ module.exports = {
"no-case-declarations": "off",
"no-useless-escape": "off",
"no-floating-decimal": "error",
"keyword-spacing": ["error", { "before": true, "overrides": { "this": { "before": false } } }],
"arrow-spacing": ["error", { "before": true, "after": true }],
"@typescript-eslint/no-for-in-array": "error",
"@typescript-eslint/no-misused-new": "error",
"@typescript-eslint/no-misused-promises": "error",
@@ -85,6 +87,8 @@ module.exports = {
"@typescript-eslint/no-unnecessary-boolean-literal-compare": "error",
"arrow-body-style": "error",
"comma-dangle": "error",
"comma-spacing": "off",
"@typescript-eslint/comma-spacing": "error",
"constructor-super": "error",
"curly": "error",
"eol-last": "error",
+141 -141
View File
@@ -1,143 +1,143 @@
// A launch configuration that compiles the extension and then opens it inside a new window
{
"version": "0.1.0",
"configurations": [
{
"name": "Launch Extension (development)",
"type": "extensionHost",
"request": "launch",
"runtimeExecutable": "${execPath}",
"args": [
"--extensionDevelopmentPath=${workspaceFolder}"
],
"sourceMaps": true,
"outFiles": [
"${workspaceFolder}/dist/**/*.js"
],
"preLaunchTask": "Compile Dev",
},
{
"name": "Launch Extension (production)",
"type": "extensionHost",
"request": "launch",
"runtimeExecutable": "${execPath}",
"args": [
"--extensionDevelopmentPath=${workspaceFolder}"
],
"sourceMaps": true,
"outFiles": [
"${workspaceFolder}/dist/**/*.js"
],
"preLaunchTask": "TypeScript Compile",
},
{
"name": "Launch Extension (do not build)",
"type": "extensionHost",
"request": "launch",
"runtimeExecutable": "${execPath}",
"args": [
"--extensionDevelopmentPath=${workspaceFolder}"
],
"sourceMaps": true,
"outFiles": [
"${workspaceFolder}/dist/**/*.js"
]
},
{
"name": "Launch Extension (watch, development)",
"type": "extensionHost",
"request": "launch",
"runtimeExecutable": "${execPath}",
"args": [
"--extensionDevelopmentPath=${workspaceFolder}"
],
"sourceMaps": true,
"outFiles": [
"${workspaceFolder}/dist/**/*.js"
],
"preLaunchTask": "Compile Dev Watch",
},
{
"name": "Launch Extension (watch, production)",
"type": "extensionHost",
"request": "launch",
"runtimeExecutable": "${execPath}",
"args": [
"--extensionDevelopmentPath=${workspaceFolder}"
],
"sourceMaps": true,
"outFiles": [
"${workspaceFolder}/dist/**/*.js"
],
"preLaunchTask": "TypeScript Compile Watch",
},
{
"name": "Launch Unit Tests",
"type": "extensionHost",
"request": "launch",
"runtimeExecutable": "${execPath}",
"args": [
"--extensionDevelopmentPath=${workspaceFolder}",
"--extensionTestsPath=${workspaceFolder}/out/test/unitTests/index"
],
"sourceMaps": true,
"outFiles": [
"${workspaceFolder}/out/test/**/*.js"
],
"preLaunchTask": "Pretest"
},
{
"name": "Launch Integration Tests",
"type": "extensionHost",
"request": "launch",
"runtimeExecutable": "${execPath}",
"args": [
"${workspaceFolder}/test/integrationTests/testAssets/SimpleCppProject/simpleCppProject.code-workspace",
"--extensionDevelopmentPath=${workspaceFolder}",
"--extensionTestsPath=${workspaceFolder}/out/test/integrationTests/languageServer/index"
],
"sourceMaps": true,
"outFiles": [
"${workspaceFolder}/out/test/**/*.js"
],
"preLaunchTask": "Pretest",
},
{
"name": "Launch E2E IntelliSense features tests",
"type": "extensionHost",
"request": "launch",
"runtimeExecutable": "${execPath}",
"args": [
"C:/git/Vcls-vscode-test/MultirootDeadlockTest/test.code-workspace",
"--extensionDevelopmentPath=${workspaceFolder}",
"--extensionTestsPath=${workspaceFolder}/out/test/integrationTests/IntelliSenseFeatures/index"
],
"sourceMaps": true,
"outFiles": [
"${workspaceFolder}/out/test/**/*.js"
],
"preLaunchTask": "Pretest"
},
{
"name": "Node Attach",
"type": "node",
"request": "attach",
"port": 5858
},
{
"name": "MochaTest",
"type": "node",
"request": "attach",
"port": 9229,
"continueOnAttach": true,
"autoAttachChildProcesses": false,
"skipFiles": [
"<node_internals>/**"
],
"outFiles": [
"${workspaceFolder}/**/out/**/*.js",
"!**/node_modules/**"
]
}
]
}
"version": "0.1.0",
"configurations": [
{
"name": "Launch Extension (development)",
"type": "extensionHost",
"request": "launch",
"runtimeExecutable": "${execPath}",
"args": [
"--extensionDevelopmentPath=${workspaceFolder}"
],
"sourceMaps": true,
"outFiles": [
"${workspaceFolder}/dist/**/*.js"
],
"preLaunchTask": "Compile Dev",
},
{
"name": "Launch Extension (production)",
"type": "extensionHost",
"request": "launch",
"runtimeExecutable": "${execPath}",
"args": [
"--extensionDevelopmentPath=${workspaceFolder}"
],
"sourceMaps": true,
"outFiles": [
"${workspaceFolder}/dist/**/*.js"
],
"preLaunchTask": "TypeScript Compile",
},
{
"name": "Launch Extension (do not build)",
"type": "extensionHost",
"request": "launch",
"runtimeExecutable": "${execPath}",
"args": [
"--extensionDevelopmentPath=${workspaceFolder}"
],
"sourceMaps": true,
"outFiles": [
"${workspaceFolder}/dist/**/*.js"
]
},
{
"name": "Launch Extension (watch, development)",
"type": "extensionHost",
"request": "launch",
"runtimeExecutable": "${execPath}",
"args": [
"--extensionDevelopmentPath=${workspaceFolder}"
],
"sourceMaps": true,
"outFiles": [
"${workspaceFolder}/dist/**/*.js"
],
"preLaunchTask": "Compile Dev Watch",
},
{
"name": "Launch Extension (watch, production)",
"type": "extensionHost",
"request": "launch",
"runtimeExecutable": "${execPath}",
"args": [
"--extensionDevelopmentPath=${workspaceFolder}"
],
"sourceMaps": true,
"outFiles": [
"${workspaceFolder}/dist/**/*.js"
],
"preLaunchTask": "TypeScript Compile Watch",
},
{
"name": "Launch Unit Tests",
"type": "extensionHost",
"request": "launch",
"runtimeExecutable": "${execPath}",
"args": [
"--extensionDevelopmentPath=${workspaceFolder}",
"--extensionTestsPath=${workspaceFolder}/out/test/unitTests/index"
],
"sourceMaps": true,
"outFiles": [
"${workspaceFolder}/out/test/**/*.js"
],
"preLaunchTask": "Pretest"
},
{
"name": "Launch Integration Tests",
"type": "extensionHost",
"request": "launch",
"runtimeExecutable": "${execPath}",
"args": [
"${workspaceFolder}/test/integrationTests/testAssets/SimpleCppProject/simpleCppProject.code-workspace",
"--extensionDevelopmentPath=${workspaceFolder}",
"--extensionTestsPath=${workspaceFolder}/out/test/integrationTests/languageServer/index"
],
"sourceMaps": true,
"outFiles": [
"${workspaceFolder}/out/test/**/*.js"
],
"preLaunchTask": "Pretest",
},
{
"name": "Launch E2E IntelliSense features tests",
"type": "extensionHost",
"request": "launch",
"runtimeExecutable": "${execPath}",
"args": [
"${workspaceFolder}/../../Vcls-vscode-test/MultirootDeadlockTest/test.code-workspace",
"--extensionDevelopmentPath=${workspaceFolder}",
"--extensionTestsPath=${workspaceFolder}/out/test/integrationTests/IntelliSenseFeatures/index"
],
"sourceMaps": true,
"outFiles": [
"${workspaceFolder}/out/test/**/*.js"
],
"preLaunchTask": "Pretest"
},
{
"name": "Node Attach",
"type": "node",
"request": "attach",
"port": 5858
},
{
"name": "MochaTest",
"type": "node",
"request": "attach",
"port": 9229,
"continueOnAttach": true,
"autoAttachChildProcesses": false,
"skipFiles": [
"<node_internals>/**"
],
"outFiles": [
"${workspaceFolder}/**/out/**/*.js",
"!**/node_modules/**"
]
}
]
}
+4 -2
View File
@@ -9,8 +9,8 @@
"typescript.tsdk": "./node_modules/typescript/lib", // we want to use the TS server from our node_modules folder to control its version
// if you install the mocha test explorer extension, you can run the unit tests from the test explorer UI
"testExplorer.useNativeTesting": true,
"mochaExplorer.files": "./**/internalUnitTests/**/test-*.js",
"mochaExplorer.watch": "./**/internalUnitTests/**/test-*.js",
"mochaExplorer.files": "./**/internalUnitTests/**/*.test.js",
"mochaExplorer.watch": "./**/internalUnitTests/**/*.test.js",
"mochaExplorer.ignore": [
"**/*skip*",
"**/dist/test/**/*.d.ts",
@@ -24,11 +24,13 @@
],
"mochaExplorer.monkeyPatch": true,
"[json]": {
"editor.formatOnSave": true,
"editor.defaultFormatter": "vscode.json-language-features",
"editor.tabSize": 4,
"files.insertFinalNewline": true
},
"[jsonc]": {
"editor.formatOnSave": true,
"editor.defaultFormatter": "vscode.json-language-features",
"editor.tabSize": 4,
"files.insertFinalNewline": true
+30
View File
@@ -1,5 +1,35 @@
# C/C++ for Visual Studio Code Changelog
## Version 1.17.0: July 26, 2023
### Enhancements
* Enable a subset of markdown to render in hover by default and a `C_Cpp.markdownInComments` setting. [#6020](https://github.com/microsoft/vscode-cpptools/issues/6020), [#10461](https://github.com/microsoft/vscode-cpptools/issues/10461)
* Add default compiler detection of additional compilers in MSYS environments. [#11211](https://github.com/microsoft/vscode-cpptools/issues/11211)
* Add support for additional compiler wrappers: gomacc, distcc, buildcache, and icecc.
### Bug Fixes
* Fix a couple bugs with documentation comments. [#5241](https://github.com/microsoft/vscode-cpptools/issues/5241)
* Added `__float128` support in gcc IntelliSense mode. [#9558](https://github.com/microsoft/vscode-cpptools/issues/9558)
* Address various issues with support for gcc 13. [#11038](https://github.com/microsoft/vscode-cpptools/issues/11038)
* Fix `#include` completion leaving an extra `>`. [#11042](https://github.com/microsoft/vscode-cpptools/issues/11042)
* Fix an issue with matching of glob patterns containing path delimiters. [#11132](https://github.com/microsoft/vscode-cpptools/issues/11132)
* Fix Create Declaration/Definition via `Quick Fix…` from hover tooltip. [#11157](https://github.com/microsoft/vscode-cpptools/issues/11157)
* Fix issues with compiler querying of clang-cl. [#11207](https://github.com/microsoft/vscode-cpptools/issues/11207)
* Fix `files.encoding` setting on startup. [#11210](https://github.com/microsoft/vscode-cpptools/issues/11210)
* Fix a crash related to directories with a very large number of files. [#11226](https://github.com/microsoft/vscode-cpptools/issues/11226)
* Fix Rank > 1 Display Strings for Natvis. [PR MIEngine#1406](https://github.com/microsoft/MIEngine/pull/1406)
* Fix some crashes identified by crash telemetry.
* Fix an issue that could cause zombie processes on Linux/Mac.
* Address some issues with glibc version compatibility. Native binaries for cpptools and the bundled clang-tidy/clang-format are now built with musl and fully statically linked.
* Fix the wrong compiler being set as default when configured to use `compile_commands.json` and overriding the compiler used there with an explicit `compilerPath`.
### Thank You to the Contributors
* [@gareth-rees (Gareth Rees)](https://github.com/gareth-rees): Always use `--simple-values` in newer versions of GDB. [PR MIEngine#1400](https://github.com/microsoft/MIEngine/pull/1400)
* [@iAbadia (Iñaki)](https://github.com/iAbadia): Align use of 'sendInvalidate' request arguments. [PR MIEngine#1402](https://github.com/microsoft/MIEngine/pull/1402)
* [@intel-rganesh (Rakesh Ganesh)](https://github.com/intel-rganesh): Introduce `--thread` and `--frame options`. [PR MIEngine#1401](https://github.com/microsoft/MIEngine/pull/1401)
* [@michalmaka (Michał Mąka)](https://github.com/michalmaka): Add support for Toybox to the remote process picker. [PR #11175](https://github.com/microsoft/vscode-cpptools/pull/11175)
* [@sbobko (Sergey Bobko)](https://github.com/sbobko): Add 'sendInvalidate' request. [PR MIEngine#1367](https://github.com/microsoft/MIEngine/pull/1367)
* [@yne (Rémy F.)](https://github.com/yne): Add wildcard support for `includePath`. [PR #10388](https://github.com/microsoft/vscode-cpptools/pull/10388)
## Version 1.16.3: June 23, 2023
### Bug Fix
* Fix "cout is ambiguous" error. [#11122](https://github.com/microsoft/vscode-cpptools/issues/11122)
+32
View File
@@ -2366,6 +2366,38 @@ ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
---------------------------------------------------------
---------------------------------------------------------
ssh-config 4.2.1 - MIT
https://github.com/cyjake/ssh-config#readme
Copyright (c) 2017 Chen Yangjian
MIT License
Copyright (c) 2017 Chen Yangjian
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
---------------------------------------------------------
---------------------------------------------------------
+6091 -6091
View File
File diff suppressed because it is too large Load Diff
+3 -2
View File
@@ -132,8 +132,9 @@ export class RemoteAttachPicker {
shPrefix = `/bin/`;
}
return `${outerQuote}${shPrefix}sh -c ${innerQuote}uname && if [ ${parameterBegin}uname${parameterEnd} = ${escapedQuote}Linux${escapedQuote} ] ; ` +
`then ${PsProcessParser.psLinuxCommand} ; elif [ ${parameterBegin}uname${parameterEnd} = ${escapedQuote}Darwin${escapedQuote} ] ; ` +
return `${outerQuote}${shPrefix}sh -c ${innerQuote}uname && if [ ${parameterBegin}uname -o${parameterEnd} = ${escapedQuote}Toybox${escapedQuote} ] ; ` +
`then ${PsProcessParser.psToyboxCommand} ; elif [ ${parameterBegin}uname${parameterEnd} = ${escapedQuote}Darwin${escapedQuote} ] ; ` +
`then ${PsProcessParser.psLinuxCommand} ; elif [ ${parameterBegin}uname${parameterEnd} = ${escapedQuote}Linux${escapedQuote} ] ; ` +
`then ${PsProcessParser.psDarwinCommand}; fi${innerQuote}${outerQuote}`;
}
+1
View File
@@ -119,6 +119,7 @@ export class PsProcessParser {
// Since 'args' contains the full path to the executable, even if truncated, searching will work as desired.
public static get psLinuxCommand(): string { return `ps axww -o pid=,comm=${PsProcessParser.commColumnTitle},args=`; }
public static get psDarwinCommand(): string { return `ps axww -o pid=,comm=${PsProcessParser.commColumnTitle},args= -c`; }
public static get psToyboxCommand(): string { return `ps -A -o pid=,comm=${PsProcessParser.commColumnTitle},args=`; }
// Only public for tests.
public static ParseProcessFromPs(processes: string): Process[] {
@@ -104,8 +104,7 @@ export class CallHierarchyProvider implements vscode.CallHierarchyProvider {
}
public async prepareCallHierarchy(document: vscode.TextDocument, position: vscode.Position, token: vscode.CancellationToken): Promise<vscode.CallHierarchyItem | undefined> {
await this.client.ready;
await processDelayedDidOpen(document);
await this.client.enqueue(() => processDelayedDidOpen(document));
workspaceReferences.cancelCurrentReferenceRequest(CancellationSender.NewRequest);
workspaceReferences.clearViews();
@@ -8,7 +8,7 @@ import { DefaultClient } from '../client';
import {
CodeActionCodeInfo, CodeActionDiagnosticInfo, codeAnalysisAllFixes, codeAnalysisCodeToFixes, codeAnalysisFileToCodeActions
} from '../codeAnalysis';
import { getLocalizedString, LocalizeStringParams } from '../localization';
import { LocalizeStringParams, getLocalizedString } from '../localization';
import { CppSettings } from '../settings';
import { makeVscodeRange } from '../utils';
@@ -23,12 +23,18 @@ interface CodeActionCommand {
arguments?: any[];
edit?: TextEdit;
uri?: string;
range?: Range;
}
interface GetCodeActionsResult {
commands: CodeActionCommand[];
}
export interface CreateDeclDefnCommandArguments {
sender: string;
range: Range;
}
export const GetCodeActionsRequest: RequestType<GetCodeActionsRequestParams, GetCodeActionsResult, void> =
new RequestType<GetCodeActionsRequestParams, GetCodeActionsResult, void>('cpptools/getCodeActions');
@@ -180,8 +186,14 @@ export class CodeActionProvider implements vscode.CodeActionProvider {
resultCodeActions.push(...disableCodeActions);
resultCodeActions.push(...docCodeActions);
return;
} else if (command.command === 'C_Cpp.CreateDeclarationOrDefinition' && (command.arguments ?? []).length === 0) {
command.arguments = ['codeAction']; // We report the sender of the command
} else if ((command.command === 'C_Cpp.CreateDeclarationOrDefinition' || command.command === 'C_Cpp.CopyDeclarationOrDefinition')
&& (command.arguments ?? []).length === 0 && command.range !== undefined) {
const args: CreateDeclDefnCommandArguments = {
sender: 'codeAction',
range: command.range
};
command.arguments = [];
command.arguments.push(args);
} else if (command.command === "C_Cpp.SelectIntelliSenseConfiguration") {
command.arguments = ['codeAction'];
hasSelectIntelliSenseConfiguration = true;
@@ -57,8 +57,7 @@ export class DocumentSymbolProvider implements vscode.DocumentSymbolProvider {
const client: Client = clients.getClientFor(document.uri);
if (client instanceof DefaultClient) {
const defaultClient: DefaultClient = <DefaultClient>client;
await client.ready;
await processDelayedDidOpen(document);
await client.enqueue(() => processDelayedDidOpen(document));
const params: GetDocumentSymbolRequestParams = {
uri: document.uri.toString()
};
@@ -23,8 +23,8 @@ export class FoldingRangeProvider implements vscode.FoldingRangeProvider {
const params: GetFoldingRangesParams = {
uri: document.uri.toString()
};
await this.client.ready;
await processDelayedDidOpen(document);
await this.client.enqueue(() => processDelayedDidOpen(document));
const response: GetFoldingRangesResult = await this.client.languageClient.sendRequest(GetFoldingRangesRequest, params, token);
if (token.isCancellationRequested || response.ranges === undefined) {
@@ -55,9 +55,7 @@ export class InlayHintsProvider implements vscode.InlayHintsProvider {
public async provideInlayHints(document: vscode.TextDocument, range: vscode.Range,
token: vscode.CancellationToken): Promise<vscode.InlayHint[] | undefined> {
await this.client.ready;
await processDelayedDidOpen(document);
await this.client.enqueue(() => processDelayedDidOpen(document));
const uriString: string = document.uri.toString();
// Get results from cache if available.
@@ -26,8 +26,7 @@ export class SemanticTokensProvider implements vscode.DocumentSemanticTokensProv
const tokens: vscode.SemanticTokens = builder.build();
return tokens;
}
await this.client.ready;
await processDelayedDidOpen(document);
await this.client.enqueue(() => processDelayedDidOpen(document));
const uriString: string = document.uri.toString();
// First check the semantic token cache to see if we already have results for that file and version
+317 -225
View File
@@ -22,7 +22,7 @@ import { SemanticTokensProvider } from './Providers/semanticTokensProvider';
import { WorkspaceSymbolProvider } from './Providers/workspaceSymbolProvider';
// End provider imports
import { fail } from 'assert';
import { ok } from 'assert';
import * as fs from 'fs';
import * as os from 'os';
import { SourceFileConfiguration, SourceFileConfigurationItem, Version, WorkspaceBrowseConfiguration } from 'vscode-cpptools';
@@ -32,6 +32,8 @@ import { LanguageClient, ServerOptions } from 'vscode-languageclient/node';
import * as nls from 'vscode-nls';
import { DebugConfigurationProvider } from '../Debugger/configurationProvider';
import { CustomConfigurationProvider1, getCustomConfigProviders, isSameProviderExtensionId } from '../LanguageServer/customProviders';
import { ManualPromise } from '../Utility/Async/manualPromise';
import { ManualSignal } from '../Utility/Async/manualSignal';
import { logAndReturn, returns } from '../Utility/Async/returns';
import * as util from '../common';
import { DebugProtocolParams, Logger, ShowWarningParams, getDiagnosticsChannel, getOutputChannelLogger, logDebugProtocol, logLocalized, showWarning } from '../logger';
@@ -80,7 +82,6 @@ let languageClient: LanguageClient;
let firstClientStarted: Promise<void>;
let languageClientCrashedNeedsRestart: boolean = false;
const languageClientCrashTimes: number[] = [];
let pendingTask: util.BlockingTask<any> | undefined;
let compilerDefaults: configs.CompilerDefaults | undefined;
let diagnosticsCollectionIntelliSense: vscode.DiagnosticCollection;
let diagnosticsCollectionRefactor: vscode.DiagnosticCollection;
@@ -718,6 +719,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>;
@@ -793,7 +795,7 @@ export interface Client {
handleRemoveCodeAnalysisProblems(refreshSquigglesOnSave: boolean, identifiersAndUris: CodeAnalysisDiagnosticIdentifiersAndUri[]): Promise<void>;
handleFixCodeAnalysisProblems(workspaceEdit: vscode.WorkspaceEdit, refreshSquigglesOnSave: boolean, identifiersAndUris: CodeAnalysisDiagnosticIdentifiersAndUri[]): Promise<void>;
handleDisableAllTypeCodeAnalysisProblems(code: string, identifiersAndUris: CodeAnalysisDiagnosticIdentifiersAndUri[]): Promise<void>;
handleCreateDeclarationOrDefinition(copy?: boolean): Promise<void>;
handleCreateDeclarationOrDefinition(isCopyToClipboard: boolean, codeActionRange?: Range): Promise<void>;
onInterval(): void;
dispose(): void;
addFileAssociations(fileAssociations: string, languageId: string): void;
@@ -843,6 +845,20 @@ export class DefaultClient implements Client {
private configStateReceived: ConfigStateReceived = { compilers: false, compileCommands: false, configProviders: undefined, timeout: false };
private showConfigureIntelliSenseButton: boolean = false;
/** 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 (ie, if you await this it will be resolved immediately)
* If the dispatcher is running, this will be in the Reset state (ie, 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();
@@ -1256,7 +1272,7 @@ export class DefaultClient implements Client {
// Semantic token types are identified by indexes in this list of types, in the legend.
const tokenTypesLegend: string[] = [];
for (const e in SemanticTokenTypes) {
// An enum is actually a set of mappings from key <=> value. Enumerate over only the names.
// An enum is actually a set of mappings from key <=> value. Enumerate over only the names.
// This allow us to represent the constants using an enum, which we can match in native code.
if (isNaN(Number(e))) {
tokenTypesLegend.push(e);
@@ -1303,91 +1319,8 @@ export class DefaultClient implements Client {
util.setProgress(util.getProgressExecutableStarted());
isFirstClient = true;
}
void this.init(rootUri, isFirstClient).catch(logAndReturn.undefined);
// requests/notifications are deferred until this.languageClient is set.
void this.queueBlockingTask(async () => {
ui = getUI();
ui.bind(this);
await firstClientStarted;
try {
const workspaceFolder: vscode.WorkspaceFolder | undefined = this.rootFolder;
this.innerConfiguration = new configs.CppProperties(this, rootUri, workspaceFolder);
this.innerConfiguration.ConfigurationsChanged((e) => this.onConfigurationsChanged(e));
this.innerConfiguration.SelectionChanged((e) => this.onSelectedConfigurationChanged(e));
this.innerConfiguration.CompileCommandsChanged((e) => this.onCompileCommandsChanged(e));
this.disposables.push(this.innerConfiguration);
this.innerLanguageClient = languageClient;
telemetry.logLanguageServerEvent("NonDefaultInitialCppSettings", this.settingsTracker.getUserModifiedSettings());
failureMessageShown = false;
if (isFirstClient) {
workspaceReferences = new refs.ReferencesManager(this);
// Only register file watchers and providers after the extension has finished initializing,
// e.g. prevents empty c_cpp_properties.json from generation.
this.registerFileWatcher();
initializedClientCount = 0;
this.inlayHintsProvider = new InlayHintsProvider(this);
this.disposables.push(vscode.languages.registerInlayHintsProvider(util.documentSelector, this.inlayHintsProvider));
this.disposables.push(vscode.languages.registerRenameProvider(util.documentSelector, new RenameProvider(this)));
this.disposables.push(vscode.languages.registerReferenceProvider(util.documentSelector, new FindAllReferencesProvider(this)));
this.disposables.push(vscode.languages.registerWorkspaceSymbolProvider(new WorkspaceSymbolProvider(this)));
this.disposables.push(vscode.languages.registerDocumentSymbolProvider(util.documentSelector, new DocumentSymbolProvider(), undefined));
this.disposables.push(vscode.languages.registerCodeActionsProvider(util.documentSelector, new CodeActionProvider(this), undefined));
this.disposables.push(vscode.languages.registerCallHierarchyProvider(util.documentSelector, new CallHierarchyProvider(this)));
// Because formatting and codeFolding can vary per folder, we need to register these providers once
// and leave them registered. The decision of whether to provide results needs to be made on a per folder basis,
// within the providers themselves.
this.documentFormattingProviderDisposable = vscode.languages.registerDocumentFormattingEditProvider(util.documentSelector, new DocumentFormattingEditProvider(this));
this.formattingRangeProviderDisposable = vscode.languages.registerDocumentRangeFormattingEditProvider(util.documentSelector, new DocumentRangeFormattingEditProvider(this));
this.onTypeFormattingProviderDisposable = vscode.languages.registerOnTypeFormattingEditProvider(util.documentSelector, new OnTypeFormattingEditProvider(this), ";", "}", "\n");
this.codeFoldingProvider = new FoldingRangeProvider(this);
this.codeFoldingProviderDisposable = vscode.languages.registerFoldingRangeProvider(util.documentSelector, this.codeFoldingProvider);
const settings: CppSettings = new CppSettings();
if (settings.enhancedColorization && semanticTokensLegend) {
this.semanticTokensProvider = new SemanticTokensProvider(this);
this.semanticTokensProviderDisposable = vscode.languages.registerDocumentSemanticTokensProvider(util.documentSelector, this.semanticTokensProvider, semanticTokensLegend);
}
// Listen for messages from the language server.
this.registerNotifications();
}
// update all client configurations
this.configuration.setupConfigurations();
initializedClientCount++;
// count number of clients, once all clients are configured, check for trusted compiler to display notification to user and add a short delay to account for config provider logic to finish
if ((vscode.workspace.workspaceFolders === undefined) || (initializedClientCount >= vscode.workspace.workspaceFolders.length)) {
// Timeout waiting for compile_commands.json and config providers.
// The quick pick options will update if they're added later on.
clients.forEach(client => {
if (client instanceof DefaultClient) {
global.setTimeout(() => {
client.configStateReceived.timeout = true;
void client.handleConfigStatusOrPrompt();
}, 15000);
}
});
// 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) {
client.configStateReceived.compilers = true;
void client.handleConfigStatusOrPrompt();
}
});
}
} 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)));
}
}
});
} catch (errJS) {
const err: NodeJS.ErrnoException = errJS as NodeJS.ErrnoException;
this.isSupported = false; // Running on an OS we don't support yet.
@@ -1404,6 +1337,92 @@ export class DefaultClient implements Client {
}
}
private async init(rootUri: vscode.Uri | undefined, isFirstClient: boolean) {
ui = getUI();
ui.bind(this);
await firstClientStarted;
try {
const workspaceFolder: vscode.WorkspaceFolder | undefined = this.rootFolder;
this.innerConfiguration = new configs.CppProperties(this, rootUri, workspaceFolder);
this.innerConfiguration.ConfigurationsChanged((e) => this.onConfigurationsChanged(e));
this.innerConfiguration.SelectionChanged((e) => this.onSelectedConfigurationChanged(e));
this.innerConfiguration.CompileCommandsChanged((e) => this.onCompileCommandsChanged(e));
this.disposables.push(this.innerConfiguration);
this.innerLanguageClient = languageClient;
telemetry.logLanguageServerEvent("NonDefaultInitialCppSettings", this.settingsTracker.getUserModifiedSettings());
failureMessageShown = false;
if (isFirstClient) {
workspaceReferences = new refs.ReferencesManager(this);
// Only register file watchers and providers after the extension has finished initializing,
// e.g. prevents empty c_cpp_properties.json from generation.
this.registerFileWatcher();
initializedClientCount = 0;
this.inlayHintsProvider = new InlayHintsProvider(this);
this.disposables.push(vscode.languages.registerInlayHintsProvider(util.documentSelector, this.inlayHintsProvider));
this.disposables.push(vscode.languages.registerRenameProvider(util.documentSelector, new RenameProvider(this)));
this.disposables.push(vscode.languages.registerReferenceProvider(util.documentSelector, new FindAllReferencesProvider(this)));
this.disposables.push(vscode.languages.registerWorkspaceSymbolProvider(new WorkspaceSymbolProvider(this)));
this.disposables.push(vscode.languages.registerDocumentSymbolProvider(util.documentSelector, new DocumentSymbolProvider(), undefined));
this.disposables.push(vscode.languages.registerCodeActionsProvider(util.documentSelector, new CodeActionProvider(this), undefined));
this.disposables.push(vscode.languages.registerCallHierarchyProvider(util.documentSelector, new CallHierarchyProvider(this)));
// Because formatting and codeFolding can vary per folder, we need to register these providers once
// and leave them registered. The decision of whether to provide results needs to be made on a per folder basis,
// within the providers themselves.
this.documentFormattingProviderDisposable = vscode.languages.registerDocumentFormattingEditProvider(util.documentSelector, new DocumentFormattingEditProvider(this));
this.formattingRangeProviderDisposable = vscode.languages.registerDocumentRangeFormattingEditProvider(util.documentSelector, new DocumentRangeFormattingEditProvider(this));
this.onTypeFormattingProviderDisposable = vscode.languages.registerOnTypeFormattingEditProvider(util.documentSelector, new OnTypeFormattingEditProvider(this), ";", "}", "\n");
this.codeFoldingProvider = new FoldingRangeProvider(this);
this.codeFoldingProviderDisposable = vscode.languages.registerFoldingRangeProvider(util.documentSelector, this.codeFoldingProvider);
const settings: CppSettings = new CppSettings();
if (settings.enhancedColorization && semanticTokensLegend) {
this.semanticTokensProvider = new SemanticTokensProvider(this);
this.semanticTokensProviderDisposable = vscode.languages.registerDocumentSemanticTokensProvider(util.documentSelector, this.semanticTokensProvider, semanticTokensLegend);
}
// Listen for messages from the language server.
this.registerNotifications();
}
// update all client configurations
this.configuration.setupConfigurations();
initializedClientCount++;
// count number of clients, once all clients are configured, check for trusted compiler to display notification to user and add a short delay to account for config provider logic to finish
if ((vscode.workspace.workspaceFolders === undefined) || (initializedClientCount >= vscode.workspace.workspaceFolders.length)) {
// Timeout waiting for compile_commands.json and config providers.
// The quick pick options will update if they're added later on.
clients.forEach(client => {
if (client instanceof DefaultClient) {
global.setTimeout(() => {
client.configStateReceived.timeout = true;
void client.handleConfigStatusOrPrompt();
}, 15000);
}
});
// 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) {
client.configStateReceived.compilers = true;
void client.handleConfigStatusOrPrompt();
}
});
}
} 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, settings: CppSettings, otherSettings: OtherSettings): WorkspaceFolderSettingsParams {
const result: WorkspaceFolderSettingsParams = {
uri: workspaceFolderUri?.toString(),
@@ -1640,7 +1659,7 @@ export class DefaultClient implements Client {
}
}
// TODO: should I set the output channel? Does this sort output between servers?
// TODO: should I set the output channel? Does this sort output between servers?
};
// Create the language client
@@ -1837,9 +1856,11 @@ export class DefaultClient implements Client {
if (!currentProvider.isReady) {
return;
}
await Promise.all([
this.clearCustomConfigurations(),
this.handleRemoveAllCodeAnalysisProblems(),
this.handleRemoveAllCodeAnalysisProblems()]);
await Promise.all([
...[...this.trackedDocuments].map(document => this.provideCustomConfiguration(document.uri, undefined, true))
]);
}
@@ -1905,7 +1926,7 @@ export class DefaultClient implements Client {
hasCompleted = true;
this.sendCustomBrowseConfiguration(null, undefined, Version.v0, true);
if (currentProvider.version >= Version.v2) {
console.warn("Configuration Provider timed out in {0}ms.", configProviderTimeout);
console.warn(`Configuration Provider timed out in ${configProviderTimeout}ms.`);
void this.resumeParsing().catch(logAndReturn.undefined);
}
}
@@ -1980,123 +2001,129 @@ export class DefaultClient implements Client {
return;
}
telemetry.logLanguageServerEvent('provideCustomConfiguration', { providerId });
void this.provideCustomConfigurationAsync(docUri, requestFile, replaceExisting, onFinished, provider);
}
return this.queueBlockingTask(async () => {
const tokenSource: vscode.CancellationTokenSource = new vscode.CancellationTokenSource();
console.log("provideCustomConfiguration");
private async provideCustomConfigurationAsync(docUri: vscode.Uri, requestFile: string | undefined, replaceExisting: boolean | undefined, onFinished: () => void, provider: CustomConfigurationProvider1) {
DefaultClient.isStarted.reset();
const providerName: string = provider.name;
const tokenSource: vscode.CancellationTokenSource = new vscode.CancellationTokenSource();
console.log("provideCustomConfiguration");
const params: QueryTranslationUnitSourceParams = {
uri: docUri.toString(),
ignoreExisting: !!replaceExisting,
workspaceFolderUri: this.RootUri?.toString()
};
const response: QueryTranslationUnitSourceResult = await this.languageClient.sendRequest(QueryTranslationUnitSourceRequest, params);
if (!response.candidates || response.candidates.length === 0) {
// If we didn't receive any candidates, no configuration is needed.
const params: QueryTranslationUnitSourceParams = {
uri: docUri.toString(),
ignoreExisting: !!replaceExisting,
workspaceFolderUri: this.RootUri?.toString()
};
const response: QueryTranslationUnitSourceResult = await this.languageClient.sendRequest(QueryTranslationUnitSourceRequest, params);
if (!response.candidates || response.candidates.length === 0) {
// If we didn't receive any candidates, no configuration is needed.
onFinished();
DefaultClient.isStarted.resolve();
return;
}
// Need to loop through candidates, to see if we can get a custom configuration from any of them.
// Wrap all lookups in a single task, so we can apply a timeout to the entire duration.
const provideConfigurationAsync: () => Thenable<SourceFileConfigurationItem[] | null | undefined> = async () => {
const uris: vscode.Uri[] = [];
for (let i: number = 0; i < response.candidates.length; ++i) {
const candidate: string = response.candidates[i];
const tuUri: vscode.Uri = vscode.Uri.parse(candidate);
try {
if (await provider.canProvideConfiguration(tuUri, tokenSource.token)) {
uris.push(tuUri);
}
} catch (err) {
console.warn("Caught exception from canProvideConfiguration");
}
}
if (!uris.length) {
return [];
}
let configs: util.Mutable<SourceFileConfigurationItem>[] = [];
try {
configs = await provider.provideConfigurations(uris, tokenSource.token);
} catch (err) {
console.warn("Caught exception from provideConfigurations");
}
if (configs && configs.length > 0 && configs[0]) {
const fileConfiguration: configs.Configuration | undefined = this.configuration.CurrentConfiguration;
if (fileConfiguration?.mergeConfigurations) {
configs.forEach(config => {
if (fileConfiguration.includePath) {
fileConfiguration.includePath.forEach(p => {
if (!config.configuration.includePath.includes(p)) {
config.configuration.includePath.push(p);
}
});
}
if (fileConfiguration.defines) {
fileConfiguration.defines.forEach(d => {
if (!config.configuration.defines.includes(d)) {
config.configuration.defines.push(d);
}
});
}
if (!config.configuration.forcedInclude) {
config.configuration.forcedInclude = [];
}
if (fileConfiguration.forcedInclude) {
fileConfiguration.forcedInclude.forEach(i => {
if (config.configuration.forcedInclude) {
if (!config.configuration.forcedInclude.includes(i)) {
config.configuration.forcedInclude.push(i);
}
}
});
}
});
}
return configs as SourceFileConfigurationItem[];
}
if (tokenSource.token.isCancellationRequested) {
return null;
}
};
try {
const configs: SourceFileConfigurationItem[] | null | undefined = await this.callTaskWithTimeout(provideConfigurationAsync, configProviderTimeout, tokenSource);
if (configs && configs.length > 0) {
this.sendCustomConfigurations(configs, provider.version);
}
onFinished();
} catch (err) {
if (requestFile) {
onFinished();
return;
}
// Need to loop through candidates, to see if we can get a custom configuration from any of them.
// Wrap all lookups in a single task, so we can apply a timeout to the entire duration.
const provideConfigurationAsync: () => Thenable<SourceFileConfigurationItem[] | null | undefined> = async () => {
const uris: vscode.Uri[] = [];
for (let i: number = 0; i < response.candidates.length; ++i) {
const candidate: string = response.candidates[i];
const tuUri: vscode.Uri = vscode.Uri.parse(candidate);
try {
if (await provider.canProvideConfiguration(tuUri, tokenSource.token)) {
uris.push(tuUri);
}
} catch (err) {
console.warn("Caught exception from canProvideConfiguration");
}
}
if (!uris.length) {
return [];
}
let configs: util.Mutable<SourceFileConfigurationItem>[] = [];
try {
configs = await provider.provideConfigurations(uris, tokenSource.token);
} catch (err) {
console.warn("Caught exception from provideConfigurations");
}
if (configs && configs.length > 0 && configs[0]) {
const fileConfiguration: configs.Configuration | undefined = this.configuration.CurrentConfiguration;
if (fileConfiguration?.mergeConfigurations) {
configs.forEach(config => {
if (fileConfiguration.includePath) {
fileConfiguration.includePath.forEach(p => {
if (!config.configuration.includePath.includes(p)) {
config.configuration.includePath.push(p);
}
});
}
if (fileConfiguration.defines) {
fileConfiguration.defines.forEach(d => {
if (!config.configuration.defines.includes(d)) {
config.configuration.defines.push(d);
}
});
}
if (!config.configuration.forcedInclude) {
config.configuration.forcedInclude = [];
}
if (fileConfiguration.forcedInclude) {
fileConfiguration.forcedInclude.forEach(i => {
if (config.configuration.forcedInclude) {
if (!config.configuration.forcedInclude.includes(i)) {
config.configuration.forcedInclude.push(i);
}
}
});
}
});
}
return configs as SourceFileConfigurationItem[];
}
if (tokenSource.token.isCancellationRequested) {
return null;
}
};
try {
const configs: SourceFileConfigurationItem[] | null | undefined = await this.callTaskWithTimeout(provideConfigurationAsync, configProviderTimeout, tokenSource);
if (configs && configs.length > 0) {
this.sendCustomConfigurations(configs, provider.version);
}
onFinished();
} catch (err) {
if (requestFile) {
onFinished();
const settings: CppSettings = new CppSettings(this.RootUri);
if (settings.configurationWarnings === true && !this.isExternalHeader(docUri) && !vscode.debug.activeDebugSession) {
const dismiss: string = localize("dismiss.button", "Dismiss");
const disable: string = localize("diable.warnings.button", "Disable Warnings");
const configName: string | undefined = this.configuration.CurrentConfiguration?.name;
if (!configName) {
return;
}
const settings: CppSettings = new CppSettings(this.RootUri);
if (settings.configurationWarnings === true && !this.isExternalHeader(docUri) && !vscode.debug.activeDebugSession) {
const dismiss: string = localize("dismiss.button", "Dismiss");
const disable: string = localize("diable.warnings.button", "Disable Warnings");
const configName: string | undefined = this.configuration.CurrentConfiguration?.name;
if (!configName) {
return;
}
let message: string = localize("unable.to.provide.configuration",
"{0} is unable to provide IntelliSense configuration information for '{1}'. Settings from the '{2}' configuration will be used instead.",
providerName, docUri.fsPath, configName);
if (err) {
message += ` (${err})`;
}
let message: string = localize("unable.to.provide.configuration",
"{0} is unable to provide IntelliSense configuration information for '{1}'. Settings from the '{2}' configuration will be used instead.",
provider.name, docUri.fsPath, configName);
if (err) {
message += ` (${err})`;
}
if (await vscode.window.showInformationMessage(message, dismiss, disable) === disable) {
settings.toggleSetting("configurationWarnings", "enabled", "disabled");
}
if (await vscode.window.showInformationMessage(message, dismiss, disable) === disable) {
settings.toggleSetting("configurationWarnings", "enabled", "disabled");
}
}
});
} finally {
DefaultClient.isStarted.resolve();
}
}
private async handleRequestCustomConfig(requestFile: string): Promise<void> {
@@ -2115,13 +2142,13 @@ export class DefaultClient implements Client {
public async getCurrentConfigCustomVariable(variableName: string): Promise<string> {
await this.ready;
return this.configuration.CurrentConfiguration?.customConfigurationVariables?.[variableName] || '';
return this.configuration.CurrentConfiguration?.customConfigurationVariables?.[variableName] ?? '';
}
public async setCurrentConfigName(configurationName: string): Promise<void> {
await this.ready;
const configurations: configs.Configuration[] = this.configuration.Configurations || [];
const configurations: configs.Configuration[] = this.configuration.Configurations ?? [];
const configurationIndex: number = configurations.findIndex((config) => config.name === configurationName);
if (configurationIndex === -1) {
@@ -2163,8 +2190,7 @@ export class DefaultClient implements Client {
public async takeOwnership(document: vscode.TextDocument): Promise<void> {
this.trackedDocuments.add(document);
this.updateActiveDocumentTextOptions();
await this.ready;
return this.sendDidOpen(document);
await this.sendDidOpen(document);
}
public async sendDidOpen(document: vscode.TextDocument): Promise<void> {
@@ -2180,24 +2206,82 @@ export class DefaultClient implements Client {
}
/**
* returns a promise that waits for the all pendingTasks are complete (e.g. language client is ready for use)
* 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.isSupported ? Promise.resolve(pendingTask?.getPromise() || undefined) : fail(localize("unsupported.client", "Unsupported client"));
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;
}
/**
* Queue a task that blocks all future tasks until it completes. This is currently only intended to be used
* during language client startup and for custom configuration providers.
* @param task The task that blocks all future tasks
* 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.
*/
private async queueBlockingTask<T>(task: () => Thenable<T>): Promise<T> {
if (this.isSupported) {
pendingTask = new util.BlockingTask<T>(task, pendingTask);
return pendingTask.getPromise();
} else {
throw new Error(localize("unsupported.client", "Unsupported client"));
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() {
// ensure that this is OK to start working
await this.isStarted;
// reset the promise for the dispatcher
DefaultClient.dispatching.reset();
do {
// 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 (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 callTaskWithTimeout<T>(task: () => Thenable<T>, ms: number, cancelToken?: vscode.CancellationTokenSource): Promise<T> {
@@ -2732,8 +2816,7 @@ export class DefaultClient implements Client {
switchHeaderSourceFileName: fileName,
workspaceFolderUri: rootUri.toString()
};
await this.ready;
return this.languageClient.sendRequest(SwitchHeaderSourceRequest, params);
return this.enqueue(async () => this.languageClient.sendRequest(SwitchHeaderSourceRequest, params));
}
public async requestCompiler(newCompilerPath?: string): Promise<configs.CompilerDefaults> {
@@ -3419,20 +3502,25 @@ export class DefaultClient implements Client {
return this.handleRemoveCodeAnalysisProblems(false, identifiersAndUris);
}
public async handleCreateDeclarationOrDefinition(copy?: boolean): Promise<void> {
public async handleCreateDeclarationOrDefinition(isCopyToClipboard: boolean, codeActionRange?: Range): Promise<void> {
let range: vscode.Range | undefined;
let uri: vscode.Uri | undefined;
// range is based on the cursor position.
const editor: vscode.TextEditor | undefined = vscode.window.activeTextEditor;
if (editor) {
uri = editor.document.uri;
if (editor.selection.isEmpty) {
range = new vscode.Range(editor.selection.active, editor.selection.active);
} else if (editor.selection.isReversed) {
range = new vscode.Range(editor.selection.active, editor.selection.anchor);
if (codeActionRange !== undefined) {
// Request is from a code action command which provides range from code actions args.
range = makeVscodeRange(codeActionRange);
} else {
range = new vscode.Range(editor.selection.anchor, editor.selection.active);
// Request is from context menu or command palette. Use range from cursor position.
if (editor.selection.isEmpty) {
range = new vscode.Range(editor.selection.active, editor.selection.active);
} else if (editor.selection.isReversed) {
range = new vscode.Range(editor.selection.active, editor.selection.anchor);
} else {
range = new vscode.Range(editor.selection.anchor, editor.selection.active);
}
}
}
@@ -3452,7 +3540,7 @@ export class DefaultClient implements Client {
line: range.end.line
}
},
copyToClipboard: copy ?? false
copyToClipboard: isCopyToClipboard
};
const result: CreateDeclarationOrDefinitionResult = await this.languageClient.sendRequest(CreateDeclarationOrDefinitionRequest, params);
@@ -3495,7 +3583,7 @@ export class DefaultClient implements Client {
if (lastEdit && lastEdit.newText.includes("#include") && lastEdit.range.isEqual(range)) {
// Destination file is empty.
// The edit positions for #include header file and definition or declaration are the same.
selectionPositionAdjustment = (lastEdit.newText.match(/\n/g) || []).length;
selectionPositionAdjustment = (lastEdit.newText.match(/\n/g) ?? []).length;
}
lastEdit = new vscode.TextEdit(range, edit.newText);
const position: vscode.Position = new vscode.Position(edit.range.start.line, edit.range.start.character);
@@ -3513,7 +3601,7 @@ export class DefaultClient implements Client {
// Move the cursor to the new declaration/definition edit, accounting for \n or \n\n at the start.
let startLine: number = lastEdit.range.start.line;
let numNewlines: number = (lastEdit.newText.match(/\n/g) || []).length;
let numNewlines: number = (lastEdit.newText.match(/\n/g) ?? []).length;
if (lastEdit.newText.startsWith("\r\n\r\n") || lastEdit.newText.startsWith("\n\n")) {
startLine += 2;
numNewlines -= 2;
@@ -3664,6 +3752,10 @@ class NullClient implements Client {
private referencesCommandModeEvent = new vscode.EventEmitter<refs.ReferencesCommandMode>();
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; }
@@ -3738,7 +3830,7 @@ class NullClient implements Client {
handleRemoveCodeAnalysisProblems(refreshSquigglesOnSave: boolean, identifiersAndUris: CodeAnalysisDiagnosticIdentifiersAndUri[]): Promise<void> { return Promise.resolve(); }
handleFixCodeAnalysisProblems(workspaceEdit: vscode.WorkspaceEdit, refreshSquigglesOnSave: boolean, identifiersAndUris: CodeAnalysisDiagnosticIdentifiersAndUri[]): Promise<void> { return Promise.resolve(); }
handleDisableAllTypeCodeAnalysisProblems(code: string, identifiersAndUris: CodeAnalysisDiagnosticIdentifiersAndUri[]): Promise<void> { return Promise.resolve(); }
handleCreateDeclarationOrDefinition(copy?: boolean): Promise<void> { return Promise.resolve(); }
handleCreateDeclarationOrDefinition(isCopyToClipboard: boolean, codeActionRange?: Range): Promise<void> { return Promise.resolve(); }
onInterval(): void { }
dispose(): void {
this.booleanEvent.dispose();
+8 -10
View File
@@ -1814,8 +1814,8 @@ export class CppProperties {
// Check for path-related squiggles.
let paths: string[] = [];
let compilerPath: string | undefined;
for (const pathArray of [(currentConfiguration.browse ? currentConfiguration.browse.path : undefined),
currentConfiguration.includePath, currentConfiguration.macFrameworkPath]) {
for (const pathArray of [ (currentConfiguration.browse ? currentConfiguration.browse.path : undefined),
currentConfiguration.includePath, currentConfiguration.macFrameworkPath ]) {
if (pathArray) {
for (const curPath of pathArray) {
paths.push(`${curPath}`);
@@ -1825,7 +1825,7 @@ export class CppProperties {
// Skip the relative forcedInclude files.
if (currentConfiguration.forcedInclude) {
for (const file of currentConfiguration.forcedInclude) {
const resolvedFilePath: string = this.resolvePath(file, isWindows);
const resolvedFilePath: string = this.resolvePath(file);
if (path.isAbsolute(resolvedFilePath)) {
paths.push(`${file}`);
}
@@ -1843,7 +1843,7 @@ export class CppProperties {
// Resolve and split any environment variables
paths = this.resolveAndSplit(paths, undefined, this.ExtendedEnvironment);
compilerPath = util.resolveVariables(compilerPath, this.ExtendedEnvironment).trim();
compilerPath = this.resolvePath(compilerPath, isWindows);
compilerPath = this.resolvePath(compilerPath);
// Get the start/end for properties that are file-only.
const forcedIncludeStart: number = curText.search(/\s*\"forcedInclude\"\s*:\s*\[/);
@@ -1907,7 +1907,7 @@ export class CppProperties {
dotConfigPath = currentConfiguration.dotConfig;
dotConfigPath = util.resolveVariables(dotConfigPath, this.ExtendedEnvironment).trim();
dotConfigPath = this.resolvePath(dotConfigPath, isWindows);
dotConfigPath = this.resolvePath(dotConfigPath);
// does not try resolve if the dotConfig property is empty
dotConfigPath = dotConfigPath !== '' ? dotConfigPath : undefined;
@@ -1946,7 +1946,7 @@ export class CppProperties {
continue;
}
let resolvedPath: string = this.resolvePath(curPath, isWindows);
let resolvedPath: string = this.resolvePath(curPath);
if (!resolvedPath) {
continue;
}
@@ -1986,7 +1986,7 @@ export class CppProperties {
let message: string;
if (!pathExists) {
if (curOffset >= forcedIncludeStart && curOffset <= forcedeIncludeEnd
&& !path.isAbsolute(resolvedPath)) {
&& !path.isAbsolute(resolvedPath)) {
continue; // Skip the error, because it could be resolved recursively.
}
message = localize('cannot.find2', "Cannot find \"{0}\".", resolvedPath);
@@ -1994,7 +1994,7 @@ export class CppProperties {
} else {
// Check for file versus path mismatches.
if ((curOffset >= forcedIncludeStart && curOffset <= forcedeIncludeEnd) ||
(curOffset >= compileCommandsStart && curOffset <= compileCommandsEnd)) {
(curOffset >= compileCommandsStart && curOffset <= compileCommandsEnd)) {
if (util.checkFileExistsSync(resolvedPath)) {
continue;
}
@@ -2018,7 +2018,6 @@ export class CppProperties {
// TODO: This never matches. https://github.com/microsoft/vscode-cpptools/issues/9140
const envMatches: string[] | null = envText.match(pattern);
if (envMatches) {
let curOffset: number = 0;
let endOffset: number = 0;
for (const curMatch of envMatches) {
@@ -2066,7 +2065,6 @@ export class CppProperties {
telemetry.logLanguageServerEvent("ConfigSquiggles", undefined, changedSquiggleMetrics);
}
this.prevSquiggleMetrics.set(currentConfiguration.name, newSquiggleMetrics);
}
private updateToVersion2(): void {
+8 -7
View File
@@ -368,6 +368,7 @@ export async function processDelayedDidOpen(document: vscode.TextDocument): Prom
}
await client.provideCustomConfiguration(document.uri, undefined);
// client.takeOwnership() will call client.TrackedDocuments.add() again, but that's ok. It's a Set.
client.onDidOpenTextDocument(document);
await client.takeOwnership(document);
return true;
}
@@ -382,8 +383,7 @@ function onDidChangeVisibleTextEditors(editors: readonly vscode.TextEditor[]): v
editors.forEach(async (editor) => {
if (util.isCpp(editor.document)) {
const client: Client = clients.getClientFor(editor.document.uri);
await client.ready;
await processDelayedDidOpen(editor.document);
await client.enqueue(() => processDelayedDidOpen(editor.document));
client.onDidChangeVisibleTextEditor(editor);
}
});
@@ -689,20 +689,22 @@ async function onDisableAllTypeCodeAnalysisProblems(code: string, identifiersAnd
return getActiveClient().handleDisableAllTypeCodeAnalysisProblems(code, identifiersAndUris);
}
async function onCopyDeclarationOrDefinition(sender?: any): Promise<void> {
async function onCopyDeclarationOrDefinition(args?: any): Promise<void> {
const sender: any | undefined = util.isString(args?.sender) ? args.sender : args;
const properties: { [key: string]: string } = {
sender: util.getSenderType(sender)
};
telemetry.logLanguageServerEvent('CopyDeclDefn', properties);
return getActiveClient().handleCreateDeclarationOrDefinition(true);
return getActiveClient().handleCreateDeclarationOrDefinition(true, args?.range);
}
async function onCreateDeclarationOrDefinition(sender?: any): Promise<void> {
async function onCreateDeclarationOrDefinition(args?: any): Promise<void> {
const sender: any | undefined = util.isString(args?.sender) ? args.sender : args;
const properties: { [key: string]: string } = {
sender: util.getSenderType(sender)
};
telemetry.logLanguageServerEvent('CreateDeclDefn', properties);
return getActiveClient().handleCreateDeclarationOrDefinition();
return getActiveClient().handleCreateDeclarationOrDefinition(false, args?.range);
}
function onAddToIncludePath(path: string): void {
@@ -711,7 +713,6 @@ function onAddToIncludePath(path: string): void {
// suggestion to a different workspace.
return clients.ActiveClient.handleAddToIncludePathCommand(path);
}
}
function onEnableSquiggles(): void {
+11 -16
View File
@@ -12,10 +12,10 @@ import { clients, onDidChangeActiveTextEditor, processDelayedDidOpen } from './e
export function createProtocolFilter(): Middleware {
// Disabling lint for invoke handlers
const invoke1 = (a: any, next: (a: any) => any): any => clients.ActiveClient.ready.then(() => next(a));
const invoke2 = (a: any, b: any, next: (a: any, b: any) => any): any => clients.ActiveClient.ready.then(() => next(a, b));
const invoke3 = (a: any, b: any, c: any, next: (a: any, b: any, c: any) => any): any => clients.ActiveClient.ready.then(() => next(a, b, c));
const invoke4 = (a: any, b: any, c: any, d: any, next: (a: any, b: any, c: any, d: any) => any): any => clients.ActiveClient.ready.then(() => next(a, b, c, d));
const invoke1 = (a: any, next: (a: any) => any): any => clients.ActiveClient.enqueue(() => next(a));
const invoke2 = (a: any, b: any, next: (a: any, b: any) => any): any => clients.ActiveClient.enqueue(() => next(a, b));
const invoke3 = (a: any, b: any, c: any, next: (a: any, b: any, c: any) => any): any => clients.ActiveClient.enqueue(() => next(a, b, c));
const invoke4 = (a: any, b: any, c: any, d: any, next: (a: any, b: any, c: any, d: any) => any): any => clients.ActiveClient.enqueue(() => next(a, b, c, d));
return {
didOpen: async (document, _sendMessage) => {
@@ -27,8 +27,7 @@ export function createProtocolFilter(): Middleware {
// If the file was visible editor when we were activated, we will not get a call to
// onDidChangeVisibleTextEditors, so immediately open any file that is visible when we receive didOpen.
// Otherwise, we defer opening the file until it's actually visible.
await clients.ActiveClient.ready;
await processDelayedDidOpen(document);
await clients.ActiveClient.enqueue(() => processDelayedDidOpen(document));
if (editor && editor === vscode.window.activeTextEditor) {
onDidChangeActiveTextEditor(editor);
}
@@ -42,12 +41,11 @@ export function createProtocolFilter(): Middleware {
// didOpen), and first becomes visible.
}
},
didChange: async (textDocumentChangeEvent, sendMessage) => {
await clients.ActiveClient.ready;
didChange: async (textDocumentChangeEvent, sendMessage) => clients.ActiveClient.enqueue(async () => {
const me: Client = clients.getClientFor(textDocumentChangeEvent.document.uri);
me.onDidChangeTextDocument(textDocumentChangeEvent);
await sendMessage(textDocumentChangeEvent);
},
}),
willSave: invoke1,
willSaveWaitUntil: async (event, sendMessage) => {
// await clients.ActiveClient.ready;
@@ -60,26 +58,23 @@ export function createProtocolFilter(): Middleware {
return [];
},
didSave: invoke1,
didClose: async (document, sendMessage) => {
await clients.ActiveClient.ready;
didClose: async (document, sendMessage) => clients.ActiveClient.enqueue(async () => {
const me: Client = clients.getClientFor(document.uri);
if (me.TrackedDocuments.has(document)) {
me.onDidCloseTextDocument(document);
me.TrackedDocuments.delete(document);
await sendMessage(document);
}
},
}),
provideCompletionItem: invoke4,
resolveCompletionItem: invoke2,
provideHover: async (document, position, token, next: (document: any, position: any, token: any) => any) => {
await clients.ActiveClient.ready;
provideHover: async (document, position, token, next: (document: any, position: any, token: any) => any) => clients.ActiveClient.enqueue(async () => {
const me: Client = clients.getClientFor(document.uri);
if (me.TrackedDocuments.has(document)) {
return next(document, position, token);
}
return null;
},
}),
provideSignatureHelp: invoke4,
provideDefinition: invoke3,
provideReferences: invoke4,
+1 -1
View File
@@ -8,7 +8,7 @@ import * as path from 'path';
import * as vscode from 'vscode';
import * as nls from 'vscode-nls';
import { CppSettings } from '../LanguageServer/settings';
import { ManualPromise } from '../Utility/Async/manual-promise';
import { ManualPromise } from '../Utility/Async/manualPromise';
import { ISshHostInfo, ProcessReturnType, splitLines, stripEscapeSequences } from '../common';
import { isWindows } from '../constants';
import { getSshChannel } from '../logger';
@@ -47,7 +47,7 @@ export class ManualPromise<T = void> implements Promise<T> {
};
/**
* A method to manually reject the Promise
* A method to manually reject the Promise
*/
public reject: (e: any) => void = (e) => {
void e; /* */
@@ -3,7 +3,7 @@
* See 'LICENSE' in the project root for license information.
* ------------------------------------------------------------------------------------------ */
import { ManualPromise } from './manual-promise';
import { ManualPromise } from './manualPromise';
import { Resetable } from './resolvable';
/**
@@ -18,9 +18,11 @@ export class ManualSignal<T> implements Promise<T>, Resetable<T> {
[Symbol.toStringTag] = 'Promise';
private promise = new ManualPromise<T>();
constructor() {
// initially not reset.
this.promise.resolve();
constructor(initiallyReset = false) {
if (!initiallyReset) {
// initially not reset.
this.promise.resolve();
}
}
get isPending(): boolean {
return this.promise.isPending;
@@ -34,6 +36,12 @@ export class ManualSignal<T> implements Promise<T>, Resetable<T> {
get isRejected(): boolean {
return this.promise.isRejected;
}
get isSet(): boolean {
return this.promise.isCompleted;
}
get isReset(): boolean {
return !this.promise.isCompleted;
}
/**
* Attaches callbacks for the resolution and/or rejection of the Promise.
* @param onfulfilled The callback to execute when the Promise is resolved.
@@ -70,22 +78,26 @@ export class ManualSignal<T> implements Promise<T>, Resetable<T> {
* @param value
*/
resolve(value: T): Resetable<T> {
this.promise.resolve(value);
if (!this.promise.isCompleted) {
this.promise.resolve(value);
}
return this as unknown as Resetable<T>;
}
/**
* A method to manually reject the Promise.
*
* This doesn't reset this instance to a new promise interally, call 'reset' to do that.
* This doesn't reset this instance to a new promise interally, call 'reset' to do that.
* @param value
*/
reject(reason: any): Resetable<T> {
this.promise.reject(reason);
if (!this.promise.isCompleted) {
this.promise.reject(reason);
}
return this as unknown as Resetable<T>;
}
/** Manually reset the promise to an uncompleted state. */
/** Manually reset the promise to an uncompleted state. */
reset(): Resetable<T> {
if (this.promise.isCompleted) {
this.promise = new ManualPromise<T>();
+1 -1
View File
@@ -3,7 +3,7 @@
* See 'LICENSE' in the project root for license information.
* ------------------------------------------------------------------------------------------ */
import { ManualPromise } from './manual-promise';
import { ManualPromise } from './manualPromise';
import { Resolveable } from './resolvable';
/**
+11 -3
View File
@@ -3,10 +3,18 @@
* See 'LICENSE' in the project root for license information.
* ------------------------------------------------------------------------------------------ */
import { fail } from 'node:assert';
import { returns } from './returns';
import { sleep } from './sleep';
/** wait on any of the promises to resolve, or the timeout to expire */
/** wait on any of the promises to resolve, or if the timeout is reached, throw */
export async function timeout(msecs: number, ...promises: Promise<any>[]): Promise<any> {
// get a promise for the timeout
const t = sleep(msecs).then(() => fail(`Timeout expired after ${msecs}ms`));
export function timeout(msecs: number, ...promises: Promise<any>[]): Promise<any> {
return Promise.any([sleep(msecs), ...promises]);
// wait until either the timout expires or one of the promises resolves
await Promise.race([t, ...promises]);
// tag the timeout with a catch to prevent unhandled rejection
t.catch(returns.undefined);
}
+1 -32
View File
@@ -15,7 +15,7 @@ import { DocumentFilter } from 'vscode-languageclient';
import * as nls from 'vscode-nls';
import { TargetPopulation } from 'vscode-tas-client';
import * as which from "which";
import { ManualPromise } from './Utility/Async/manual-promise';
import { ManualPromise } from './Utility/Async/manualPromise';
import { isWindows } from './constants';
import { getOutputChannelLogger, showOutputChannel } from './logger';
import { PlatformInformation } from './platform';
@@ -1172,37 +1172,6 @@ export function escapeForSquiggles(s: string): string {
return newResults;
}
export class BlockingTask<T> {
private done: boolean = false;
private promise: Thenable<T>;
constructor(task: () => Thenable<T>, dependency?: BlockingTask<any>) {
if (!dependency) {
this.promise = task();
} else {
this.promise = new Promise<T>((resolve, reject) => {
const f1: () => void = () => {
task().then(resolve, reject);
};
const f2: (err: any) => void = (err) => {
console.log(err);
task().then(resolve, reject);
};
dependency.promise.then(f1, f2);
});
}
this.promise.then(() => this.done = true, () => this.done = true);
}
public get Done(): boolean {
return this.done;
}
public getPromise(): Thenable<T> {
return this.promise;
}
}
export function getSenderType(sender?: any): string {
if (isString(sender)) {
return sender;
+8 -1
View File
@@ -4,32 +4,39 @@
* ------------------------------------------------------------------------------------------ */
'use strict';
import { ok } from 'assert';
import * as vscode from 'vscode';
import { CppToolsTestHook, IntelliSenseStatus, Status } from 'vscode-cpptools/out/testApi';
export class TestHook implements CppToolsTestHook {
private disposed = false;
private intelliSenseStatusChangedEvent: vscode.EventEmitter<IntelliSenseStatus> = new vscode.EventEmitter<IntelliSenseStatus>();
private statusChangedEvent: vscode.EventEmitter<Status> = new vscode.EventEmitter<Status>();
// The StatusChanged event is deprecated in CppToolsTestHook API.
public get StatusChanged(): vscode.Event<Status> {
ok(!this.disposed, "TestHook is disposed.");
return this.statusChangedEvent.event;
}
public get IntelliSenseStatusChanged(): vscode.Event<IntelliSenseStatus> {
ok(!this.disposed, "TestHook is disposed.");
return this.intelliSenseStatusChangedEvent.event;
}
public get valid(): boolean {
return !!this.intelliSenseStatusChangedEvent && !!this.statusChangedEvent;
return !this.disposed && !!this.intelliSenseStatusChangedEvent && !!this.statusChangedEvent;
}
public updateStatus(status: IntelliSenseStatus): void {
ok(!this.disposed, "TestHook is disposed.");
this.intelliSenseStatusChangedEvent.fire(status);
this.statusChangedEvent.fire(status.status);
}
public dispose(): void {
ok(!this.disposed, "TestHook is disposed.");
this.disposed = true;
this.intelliSenseStatusChangedEvent.dispose();
this.statusChangedEvent.dispose();
}
@@ -2,6 +2,12 @@
* Copyright (c) Microsoft Corporation. All Rights Reserved.
* See 'LICENSE' in the project root for license information.
* ------------------------------------------------------------------------------------------ */
/* eslint-disable @typescript-eslint/triple-slash-reference */
/* eslint-disable @typescript-eslint/no-non-null-assertion */
/// <reference path="../../../vscode.d.ts" />
import * as assert from 'assert';
import * as vscode from 'vscode';
import * as api from 'vscode-cpptools';
@@ -28,37 +34,25 @@ suite("[Inlay hints test]", function(): void {
let referenceOperatorEnabledValue: any;
let referenceOperatorShowSpaceValue: any;
// Test setup
const rootUri: vscode.Uri = vscode.workspace.workspaceFolders[1].uri;
const wf = vscode.workspace.workspaceFolders?.[1] ?? assert.fail("Test failed because workspace folder is undefined.");
const rootUri: vscode.Uri = wf.uri;
const filePath: string | undefined = rootUri.fsPath + "/inlay_hints.cpp";
const fileUri: vscode.Uri = vscode.Uri.file(filePath);
const disposables: vscode.Disposable[] = [];
let getIntelliSenseStatus: any;
suiteSetup(async function(): Promise<void> {
await testHelpers.activateCppExtension();
const cpptools = await apit.getCppToolsTestApi(api.Version.latest);
if (!cpptools) {
return;
}
const cpptools = await apit.getCppToolsTestApi(api.Version.latest) ?? assert.fail("Could not get cpptools test api");
const testHook: apit.CppToolsTestHook = cpptools.getTestHook();
disposables.push(testHook);
getIntelliSenseStatus = new Promise<void>((resolve, reject) => {
disposables.push(testHook.IntelliSenseStatusChanged(result => {
result = result as apit.IntelliSenseStatus;
if (result.filename === "inlay_hints.cpp" && result.status === apit.Status.IntelliSenseReady) {
resolve();
}
}));
setTimeout(() => { reject(new Error("Timeout: IntelliSenseStatusChanged event")); }, testHelpers.defaultTimeout);
});
// Start language server
console.log("Open file: " + fileUri.toString());
const document: vscode.TextDocument = await vscode.workspace.openTextDocument(fileUri);
await vscode.window.showTextDocument(document);
await getIntelliSenseStatus;
saveOriginalSettings();
await useDefaultSettings();
});
@@ -69,13 +63,13 @@ suite("[Inlay hints test]", function(): void {
});
function saveOriginalSettings(): void {
autoDeclarationTypesEnabledValue = inlayHintSettings.inspect(autoDeclarationTypesEnabled).globalValue;
autoDeclarationTypesShowOnLeftValue = inlayHintSettings.inspect(autoDeclarationTypesShowOnLeft).globalValue;
parameterNamesEnabledValue = inlayHintSettings.inspect(parameterNamesEnabled).globalValue;
parameterNamesSuppressValue = inlayHintSettings.inspect(parameterNamesSuppress).globalValue;
parameterNamesHideUnderScoreValue = inlayHintSettings.inspect(parameterNamesHideUnderScore).globalValue;
referenceOperatorEnabledValue = inlayHintSettings.inspect(referenceOperatorEnabled).globalValue;
referenceOperatorShowSpaceValue = inlayHintSettings.inspect(referenceOperatorShowSpace).globalValue;
autoDeclarationTypesEnabledValue = inlayHintSettings.inspect(autoDeclarationTypesEnabled)!.globalValue;
autoDeclarationTypesShowOnLeftValue = inlayHintSettings.inspect(autoDeclarationTypesShowOnLeft)!.globalValue;
parameterNamesEnabledValue = inlayHintSettings.inspect(parameterNamesEnabled)!.globalValue;
parameterNamesSuppressValue = inlayHintSettings.inspect(parameterNamesSuppress)!.globalValue;
parameterNamesHideUnderScoreValue = inlayHintSettings.inspect(parameterNamesHideUnderScore)!.globalValue;
referenceOperatorEnabledValue = inlayHintSettings.inspect(referenceOperatorEnabled)!.globalValue;
referenceOperatorShowSpaceValue = inlayHintSettings.inspect(referenceOperatorShowSpace)!.globalValue;
}
async function restoreOriginalSettings(): Promise<void> {
@@ -103,12 +97,12 @@ suite("[Inlay hints test]", function(): void {
await changeInlayHintSetting(autoDeclarationTypesEnabled, disabled);
await changeInlayHintSetting(autoDeclarationTypesShowOnLeft, disabled);
await getIntelliSenseStatus;
const result1 = await vscode.commands.executeCommand<vscode.InlayHint[]>('vscode.executeInlayHintProvider', fileUri, range);
assert.strictEqual(result1.length, 0, "Incorrect number of results.");
await changeInlayHintSetting(autoDeclarationTypesEnabled, enabled);
await getIntelliSenseStatus;
const result2 = await vscode.commands.executeCommand<vscode.InlayHint[]>('vscode.executeInlayHintProvider', fileUri, range);
assert.strictEqual(result2.length, 12, "Incorrect number of results.");
const expectedKind = vscode.InlayHintKind.Type;
@@ -125,19 +119,17 @@ suite("[Inlay hints test]", function(): void {
assertHintValues(result2, 10, 28, 14, ": int", expectedKind);
assertHintValues(result2, 11, 29, 15, ": int", expectedKind);
});
test("[Inlay Hints - auto type, show on left]", async () => {
const range: vscode.Range = new vscode.Range(new vscode.Position(15, 0), new vscode.Position(31, 0));
await changeInlayHintSetting(autoDeclarationTypesEnabled, disabled);
await changeInlayHintSetting(autoDeclarationTypesShowOnLeft, disabled);
await getIntelliSenseStatus;
const result1 = await vscode.commands.executeCommand<vscode.InlayHint[]>('vscode.executeInlayHintProvider', fileUri, range);
assert.strictEqual(result1.length, 0, "Incorrect number of results.");
await changeInlayHintSetting(autoDeclarationTypesEnabled, enabled);
await changeInlayHintSetting(autoDeclarationTypesShowOnLeft, enabled);
await getIntelliSenseStatus;
const result2 = await vscode.commands.executeCommand<vscode.InlayHint[]>('vscode.executeInlayHintProvider', fileUri, range);
assert.strictEqual(result2.length, 12, "Incorrect number of results.");
const expectedKind = vscode.InlayHintKind.Type;
@@ -160,13 +152,11 @@ suite("[Inlay hints test]", function(): void {
await changeInlayHintSetting(parameterNamesEnabled, disabled);
await changeInlayHintSetting(referenceOperatorEnabled, disabled);
await getIntelliSenseStatus;
const result1 = await vscode.commands.executeCommand<vscode.InlayHint[]>('vscode.executeInlayHintProvider', fileUri, range);
assert.strictEqual(result1.length, 0, "Incorrect number of results.");
await changeInlayHintSetting(parameterNamesEnabled, enabled);
await changeInlayHintSetting(parameterNamesSuppress, enabled);
await getIntelliSenseStatus;
const result2 = await vscode.commands.executeCommand<vscode.InlayHint[]>('vscode.executeInlayHintProvider', fileUri, range);
assert.strictEqual(result2.length, 16, "Incorrect number of results.");
const expectedKind = vscode.InlayHintKind.Parameter;
@@ -193,7 +183,6 @@ suite("[Inlay hints test]", function(): void {
await changeInlayHintSetting(parameterNamesEnabled, enabled);
await changeInlayHintSetting(parameterNamesHideUnderScore, disabled);
await getIntelliSenseStatus;
const result1 = await vscode.commands.executeCommand<vscode.InlayHint[]>('vscode.executeInlayHintProvider', fileUri, range);
assert.strictEqual(result1.length, 4, "Incorrect number of results.");
const expectedKind = vscode.InlayHintKind.Parameter;
@@ -203,7 +192,6 @@ suite("[Inlay hints test]", function(): void {
assertHintValues(result1, 3, 35, 25, "a:", expectedKind);
await changeInlayHintSetting(parameterNamesHideUnderScore, enabled);
await getIntelliSenseStatus;
const result2 = await vscode.commands.executeCommand<vscode.InlayHint[]>('vscode.executeInlayHintProvider', fileUri, range);
assert.strictEqual(result2.length, 4, "Incorrect number of results.");
assertHintValues(result2, 0, 35, 16, "x:", expectedKind);
@@ -218,12 +206,10 @@ suite("[Inlay hints test]", function(): void {
await changeInlayHintSetting(parameterNamesEnabled, disabled);
await changeInlayHintSetting(referenceOperatorEnabled, disabled);
await changeInlayHintSetting(referenceOperatorShowSpace, disabled);
await getIntelliSenseStatus;
const result1 = await vscode.commands.executeCommand<vscode.InlayHint[]>('vscode.executeInlayHintProvider', fileUri, range);
assert.strictEqual(result1.length, 0, "Incorrect number of results.");
await changeInlayHintSetting(referenceOperatorEnabled, enabled);
await getIntelliSenseStatus;
const result2 = await vscode.commands.executeCommand<vscode.InlayHint[]>('vscode.executeInlayHintProvider', fileUri, range);
assert.strictEqual(result2.length, 16, "Incorrect number of results.");
const expectedKind = vscode.InlayHintKind.Parameter;
@@ -254,7 +240,6 @@ suite("[Inlay hints test]", function(): void {
await changeInlayHintSetting(parameterNamesSuppress, disabled);
await changeInlayHintSetting(referenceOperatorEnabled, enabled);
await changeInlayHintSetting(referenceOperatorShowSpace, disabled);
await getIntelliSenseStatus;
const result1 = await vscode.commands.executeCommand<vscode.InlayHint[]>('vscode.executeInlayHintProvider', fileUri, range);
assert.strictEqual(result1.length, 12, "Incorrect number of results.");
const expectedKind = vscode.InlayHintKind.Parameter;
@@ -272,7 +257,6 @@ suite("[Inlay hints test]", function(): void {
assertHintValues(result1, 11, 95, 9, "flag:", expectedKind);
await changeInlayHintSetting(referenceOperatorShowSpace, enabled);
await getIntelliSenseStatus;
const result2 = await vscode.commands.executeCommand<vscode.InlayHint[]>('vscode.executeInlayHintProvider', fileUri, range);
assert.strictEqual(result2.length, 12, "Incorrect number of results.");
assertHintValues(result2, 0, 87, 9, "& first:", expectedKind);
@@ -290,10 +274,10 @@ suite("[Inlay hints test]", function(): void {
});
async function changeInlayHintSetting(inlayHintSetting: string, valueNew: any): Promise<void> {
const valueBeforeChange: any = inlayHintSettings.inspect(inlayHintSetting).globalValue;
const valueBeforeChange: any = inlayHintSettings.inspect(inlayHintSetting)!.globalValue;
if (valueBeforeChange !== valueNew) {
await inlayHintSettings.update(inlayHintSetting, valueNew, vscode.ConfigurationTarget.Global);
const valueAfterChange: any = inlayHintSettings.inspect(inlayHintSetting).globalValue;
const valueAfterChange: any = inlayHintSettings.inspect(inlayHintSetting)!.globalValue;
assert.strictEqual(valueAfterChange, valueNew, `Unable to change setting: ${inlayHintSetting}`);
}
}
@@ -7,6 +7,8 @@ import * as os from 'os';
import * as vscode from 'vscode';
import * as api from 'vscode-cpptools';
import * as apit from 'vscode-cpptools/out/testApi';
import { ManualSignal } from '../../../src/Utility/Async/manualSignal';
import { timeout } from '../../../src/Utility/Async/timeout';
import * as testHelpers from '../testHelpers';
suite("[Quick info test]", function(): void {
@@ -15,29 +17,26 @@ suite("[Quick info test]", function(): void {
const filePath: string = `${vscode.workspace.workspaceFolders?.[1]?.uri.fsPath}/quickInfo.cpp`;
const fileUri: vscode.Uri = vscode.Uri.file(filePath);
let platform: string = "";
const getIntelliSenseStatus = new ManualSignal<void>();
suiteSetup(async function(): Promise<void> {
await testHelpers.activateCppExtension();
cpptools = await apit.getCppToolsTestApi(api.Version.latest);
cpptools = await apit.getCppToolsTestApi(api.Version.latest) ?? assert.fail("Could not get CppToolsTestApi");
platform = os.platform();
const testHook: apit.CppToolsTestHook = cpptools.getTestHook();
disposables.push(testHook);
const getIntelliSenseStatus: any = new Promise<void>((resolve, reject) => {
disposables.push(testHook.IntelliSenseStatusChanged(result => {
result = result as apit.IntelliSenseStatus;
if (result.filename === "quickInfo.cpp" && result.status === apit.Status.IntelliSenseReady) {
resolve();
}
}));
setTimeout(() => { reject(new Error("Timeout: IntelliSenseStatusChanged event")); }, testHelpers.defaultTimeout);
testHook.IntelliSenseStatusChanged((result: apit.IntelliSenseStatus) => {
if (result.filename === "quickInfo.cpp" && result.status === apit.Status.IntelliSenseReady) {
getIntelliSenseStatus.resolve();
}
});
// Start language server
console.log("Open file: " + fileUri.toString());
await vscode.commands.executeCommand("vscode.open", fileUri);
await getIntelliSenseStatus;
await timeout(5000, getIntelliSenseStatus.then(() => getIntelliSenseStatus.reset()));
});
suiteTeardown(function(): void {
@@ -53,11 +52,12 @@ suite("[Quick info test]", function(): void {
expectedMap.set("darwin", expected_full_comment);
const actual: string = (<vscode.MarkdownString>result[0].contents[0]).value;
const expected: string = expectedMap.get(platform);
const expected: string = expectedMap.get(platform) ?? assert.fail("Platform not found");
assert.strictEqual(actual, expected);
});
test("[Hover over function call - Doxygen comment]", async () => {
// [TODO] - temporarily skip this test at the moment - it doesn't currently work (locally anyway) --
test.skip("[Hover over function call - Doxygen comment]", async () => {
const result: vscode.Hover[] = <vscode.Hover[]>(await vscode.commands.executeCommand('vscode.executeHoverProvider', fileUri, new vscode.Position(36, 9)));
const expected_full_comment: string = `\`\`\`cpp\nint testDoxygen<int>(int base, int height)\n\`\`\` \nCalculates area of rectangle \n \n**Template Parameters:** \n\`T\` is template param \n \n**Parameters:** \n\`base\` is horizontal length \n\`height\` is vertical length \n \n**Returns:** \nArea of rectangle \n \n**Exceptions:** \nThis is an exception comment`;
@@ -67,7 +67,7 @@ suite("[Quick info test]", function(): void {
expectedMap.set("darwin", expected_full_comment);
const actual: string = (<vscode.MarkdownString>result[0].contents[0]).value;
const expected: string = expectedMap.get(platform);
const expected: string = expectedMap.get(platform) ?? assert.fail("Platform not found");
assert.strictEqual(actual, expected);
});
@@ -79,7 +79,7 @@ suite("[Quick info test]", function(): void {
expectedMap.set("linux", `\`\`\`cpp\nstd::string stringVar\n\`\`\``);
expectedMap.set("darwin", `\`\`\`cpp\nstd::__cxx11::string stringVar\n\`\`\``);
const expected: string = expectedMap.get(platform);
const expected: string = expectedMap.get(platform) ?? assert.fail("Platform not found");
const actual: string = (<vscode.MarkdownString>result[0].contents[0]).value;
assert.strictEqual(actual, expected);
});
@@ -6,38 +6,39 @@ import * as assert from 'assert';
import * as vscode from 'vscode';
import * as api from 'vscode-cpptools';
import * as apit from 'vscode-cpptools/out/testApi';
import { ManualSignal } from '../../../src/Utility/Async/manualSignal';
import { timeout } from '../../../src/Utility/Async/timeout';
import * as testHelpers from '../testHelpers';
suite(`[Reference test]`, function(): void {
let cpptools: apit.CppToolsTestApi;
const disposables: vscode.Disposable[] = [];
const path: string = vscode.workspace.workspaceFolders[1].uri.fsPath + "/references.cpp";
const wf = vscode.workspace.workspaceFolders?.[1] ?? assert.fail("Could not get workspace folder");
const path: string = wf.uri.fsPath + "/references.cpp";
const fileUri: vscode.Uri = vscode.Uri.file(path);
let testHook: apit.CppToolsTestHook;
let getIntelliSenseStatus: any;
const getIntelliSenseStatus = new ManualSignal<void>();
let document: vscode.TextDocument;
suiteSetup(async function(): Promise<void> {
await testHelpers.activateCppExtension();
cpptools = await apit.getCppToolsTestApi(api.Version.latest);
cpptools = await apit.getCppToolsTestApi(api.Version.latest) ?? assert.fail("Could not get CppToolsTestApi");
testHook = cpptools.getTestHook();
getIntelliSenseStatus = new Promise<void>((resolve, reject) => {
disposables.push(testHook.IntelliSenseStatusChanged(result => {
result = result as apit.IntelliSenseStatus;
if (result.filename === "references.cpp" && result.status === apit.Status.IntelliSenseReady) {
resolve();
}
}));
setTimeout(() => { reject(new Error("Timeout: IntelliSenseStatusChanged event")); }, testHelpers.defaultTimeout);
testHook.IntelliSenseStatusChanged((result: apit.IntelliSenseStatus) => {
if (result.filename === "references.cpp" && result.status === apit.Status.IntelliSenseReady) {
getIntelliSenseStatus.resolve();
}
});
disposables.push(testHook);
// Start language server
console.log("Open file: " + fileUri.toString());
document = await vscode.workspace.openTextDocument(fileUri);
await vscode.window.showTextDocument(document);
await getIntelliSenseStatus;
await timeout(5000, getIntelliSenseStatus.then(() => getIntelliSenseStatus.reset()));
});
test("[Find confirmed references of a symbol]", async () => {
@@ -1,35 +1,75 @@
import * as path from 'path';
import { runTests } from '@vscode/test-electron';
async function main() {
try {
// The folder containing the Extension Manifest package.json
// Passed to `--extensionDevelopmentPath`
const extensionDevelopmentPath = path.resolve(__dirname, '../../../../');
// The path to the extension test script
// Passed to --extensionTestsPath
const extensionTestsPath = path.resolve(__dirname, './index');
// Note, when running tests locally, replace TESTS_WORKSPACE with local path to "~/Vcls-vscode-test/MultirootDeadlockTest/test.code-workspace"
// in the Launch.json file.
let testWorkspace: string | undefined = process.env.TESTS_WORKSPACE;
if (!testWorkspace) {
console.error("Unable to read process.env.TESTS_WORKSPACE");
} else {
console.log("TESTS_WORKSPACE: " + testWorkspace);
}
const launchArgs = [ "--disable-extensions", testWorkspace ];
// Download VS Code, unzip it and run the integration test
await runTests({ launchArgs, extensionDevelopmentPath, extensionTestsPath });
} catch (err) {
console.log(err);
console.log('Failed to run tests.');
process.exit(1);
}
}
main();
import { downloadAndUnzipVSCode, resolveCliArgsFromVSCodeExecutablePath, runTests } from '@vscode/test-electron';
import { ok } from 'assert';
import { createHash } from 'crypto';
import { existsSync } from 'fs';
import { mkdir as md, stat } from 'fs/promises';
import { tmpdir } from 'os';
import { resolve } from 'path';
// The folder containing the Extension Manifest package.json
// Passed to `--extensionDevelopmentPath`
const extensionDevelopmentPath = resolve(__dirname, '../../../../');
const isolated = resolve(tmpdir(), '.vscode-test', createHash('sha256').update(extensionDevelopmentPath).digest('hex').substring(0,6) );
const options = {
cachePath: `${isolated}/cache`,
launchArgs: ['--no-sandbox', '--disable-updates', '--skip-welcome', '--skip-release-notes', `--extensions-dir=${isolated}/extensions`, `--user-data-dir=${isolated}/user-data`]
};
async function mkdir(filePath:string) {
filePath = resolve(filePath);
try {
const s = await stat(filePath);
if( s.isDirectory() ) {
return filePath;
}
throw new Error(`Cannot create directory '${filePath}' because thre is a file there.`);
} catch {
// no worries
}
await md(filePath, { recursive: true })
return filePath;
}
async function main() {
try {
// create a folder for the isolated test environment
await mkdir(isolated);
// download VSCode to that location
const vscodeExecutablePath = await downloadAndUnzipVSCode(options);
const [cli, ...launchArgs] = resolveCliArgsFromVSCodeExecutablePath(vscodeExecutablePath).filter(each => !each.startsWith('--extensions-dir=') && !each.startsWith('--user-data-dir='));
// clean up args so that it works with the isolate extensions and data directories
launchArgs.push(`--extensions-dir=${isolated}/extensions`, `--user-data-dir=${isolated}/user-data`);
// The path to the extension test script
// Passed to --extensionTestsPath
const extensionTestsPath = resolve(__dirname, './index');
// Note, when running tests locally, replace TESTS_WORKSPACE with local path to "~/Vcls-vscode-test/MultirootDeadlockTest/test.code-workspace"
// in the Launch.json file.
let testWorkspace: string | undefined = process.env.TESTS_WORKSPACE || resolve(extensionDevelopmentPath, '../../Vcls-vscode-test/MultirootDeadlockTest/test.code-workspace');
ok(existsSync(testWorkspace), `TESTS_WORKSPACE '${testWorkspace}' does not exist.`);
console.log("TESTS_WORKSPACE: " + testWorkspace);
launchArgs.push("--disable-extensions", testWorkspace );
// Download VS Code, unzip it and run the integration test
await runTests({
...options,
launchArgs,
extensionDevelopmentPath,
extensionTestsPath
});
} catch (err) {
console.log(err);
console.log('Failed to run tests.');
process.exit(1);
}
}
main();
@@ -1,26 +1,65 @@
import * as path from 'path';
import { runTests } from '@vscode/test-electron';
async function main() {
try {
// The folder containing the Extension Manifest package.json
// Passed to `--extensionDevelopmentPath`
const extensionDevelopmentPath = path.resolve(__dirname, '../../../../');
// The path to the extension test script
// Passed to --extensionTestsPath
const extensionTestsPath = path.resolve(__dirname, './index');
const launchArgs = [ "--disable-extensions" ];
// Download VS Code, unzip it and run the integration test
await runTests({ launchArgs, extensionDevelopmentPath, extensionTestsPath });
} catch(err) {
console.log(err);
console.log('Failed to run tests.');
process.exit(1);
}
}
main();
import { downloadAndUnzipVSCode, resolveCliArgsFromVSCodeExecutablePath, runTests } from '@vscode/test-electron';
import { createHash } from 'crypto';
import { mkdir as md, stat } from 'fs/promises';
import { tmpdir } from 'os';
import { resolve } from 'path';
// The folder containing the Extension Manifest package.json
// Passed to `--extensionDevelopmentPath`
const extensionDevelopmentPath = resolve(__dirname, '../../../../');
const isolated = resolve(tmpdir(), '.vscode-test', createHash('sha256').update(extensionDevelopmentPath).digest('hex').substring(0,6) );
const options = {
cachePath: `${isolated}/cache`,
launchArgs: ['--no-sandbox', '--disable-updates', '--skip-welcome', '--skip-release-notes', `--extensions-dir=${isolated}/extensions`, `--user-data-dir=${isolated}/user-data`]
};
async function mkdir(filePath:string) {
filePath = resolve(filePath);
try {
const s = await stat(filePath);
if( s.isDirectory() ) {
return filePath;
}
throw new Error(`Cannot create directory '${filePath}' because thre is a file there.`);
} catch {
// no worries
}
await md(filePath, { recursive: true })
return filePath;
}
async function main() {
try {
// create a folder for the isolated test environment
await mkdir(isolated);
// download VSCode to that location
const vscodeExecutablePath = await downloadAndUnzipVSCode(options);
const [cli, ...launchArgs] = resolveCliArgsFromVSCodeExecutablePath(vscodeExecutablePath).filter(each => !each.startsWith('--extensions-dir=') && !each.startsWith('--user-data-dir='));
// clean up args so that it works with the isolate extensions and data directories
launchArgs.push(`--extensions-dir=${isolated}/extensions`, `--user-data-dir=${isolated}/user-data`);
// The path to the extension test script
// Passed to --extensionTestsPath
const extensionTestsPath = resolve(__dirname, './index');
launchArgs.push("--disable-extensions");
// Download VS Code, unzip it and run the integration test
await runTests({
...options,
launchArgs,
extensionDevelopmentPath,
extensionTestsPath
});
} catch (err) {
console.log(err);
console.log('Failed to run tests.');
process.exit(1);
}
}
main();
@@ -2,13 +2,17 @@
* Copyright (c) Microsoft Corporation. All Rights Reserved.
* See 'LICENSE' in the project root for license information.
* ------------------------------------------------------------------------------------------ */
/* eslint-disable @typescript-eslint/triple-slash-reference */
/// <reference path="../../../vscode.d.ts" />
import * as assert from 'assert';
import * as vscode from 'vscode';
import * as api from 'vscode-cpptools';
import * as apit from 'vscode-cpptools/out/testApi';
import * as util from '../../../src/common';
import * as config from '../../../src/LanguageServer/configurations';
import { getLanguageConfigFromPatterns } from '../../../src/LanguageServer/languageConfig';
import * as util from '../../../src/common';
import * as testHelpers from '../testHelpers';
suite("multiline comment setting tests", function(): void {
@@ -52,27 +56,27 @@ suite("multiline comment setting tests", function(): void {
];
test("Check the default OnEnterRules for C", () => {
const rules: vscode.OnEnterRule[] = getLanguageConfigFromPatterns('c', [ "/**" ]).onEnterRules;
const rules: vscode.OnEnterRule[] = getLanguageConfigFromPatterns('c', [ "/**" ]).onEnterRules ?? assert.fail('onEnterRules is undefined');
assert.deepStrictEqual(rules, defaultMLRules);
});
test("Check for removal of single line comment continuations for C", () => {
const rules: vscode.OnEnterRule[] = getLanguageConfigFromPatterns('c', [ "/**", "///" ]).onEnterRules;
const rules: vscode.OnEnterRule[] = getLanguageConfigFromPatterns('c', [ "/**", "///" ]).onEnterRules ?? assert.fail('onEnterRules is undefined');
assert.deepStrictEqual(rules, defaultMLRules);
});
test("Check the default OnEnterRules for C++", () => {
const rules: vscode.OnEnterRule[] = getLanguageConfigFromPatterns('cpp', [ "/**" ]).onEnterRules;
const rules: vscode.OnEnterRule[] = getLanguageConfigFromPatterns('cpp', [ "/**" ]).onEnterRules ?? assert.fail('onEnterRules is undefined');
assert.deepStrictEqual(rules, defaultMLRules);
});
test("Make sure duplicate rules are removed", () => {
const rules: vscode.OnEnterRule[] = getLanguageConfigFromPatterns('cpp', [ "/**", { begin: "/**", continue: " * " }, "/**" ]).onEnterRules;
const rules: vscode.OnEnterRule[] = getLanguageConfigFromPatterns('cpp', [ "/**", { begin: "/**", continue: " * " }, "/**" ]).onEnterRules ?? assert.fail('onEnterRules is undefined');
assert.deepStrictEqual(rules, defaultMLRules);
});
test("Check single line rules for C++", () => {
const rules: vscode.OnEnterRule[] = getLanguageConfigFromPatterns('cpp', [ "///" ]).onEnterRules;
const rules: vscode.OnEnterRule[] = getLanguageConfigFromPatterns('cpp', [ "///" ]).onEnterRules ?? assert.fail('onEnterRules is undefined');
assert.deepStrictEqual(rules, defaultSLRules);
});
@@ -81,10 +85,11 @@ suite("multiline comment setting tests", function(): void {
/* **************************************************************************** */
function cppPropertiesPath(): string {
return vscode.workspace.workspaceFolders[0].uri.fsPath + "/.vscode/c_cpp_properties.json";
const wf = vscode.workspace.workspaceFolders?.[0] ?? assert.fail("No workspace folder open");
return `${wf.uri.fsPath}/.vscode/c_cpp_properties.json`;
}
async function changeCppProperties(cppProperties: config.ConfigurationJson, disposables: vscode.Disposable[]): Promise<void> {
async function changeCppProperties(cppProperties: config.ConfigurationJson, _disposables: vscode.Disposable[]): Promise<void> {
await util.writeFileText(cppPropertiesPath(), JSON.stringify(cppProperties));
const contents: string = await util.readFileText(cppPropertiesPath());
console.log(" wrote c_cpp_properties.json: " + contents);
@@ -121,7 +126,7 @@ suite("extensibility tests v3", function(): void {
const provider: api.CustomConfigurationProvider = {
name: "cpptoolsTest-v3",
extensionId: "ms-vscode.cpptools-test3",
canProvideConfiguration(document: vscode.Uri): Thenable<boolean> {
canProvideConfiguration(_document: vscode.Uri): Thenable<boolean> {
return Promise.resolve(true);
},
provideConfigurations(uris: vscode.Uri[]): Thenable<api.SourceFileConfigurationItem[]> {
@@ -145,7 +150,7 @@ suite("extensibility tests v3", function(): void {
canProvideBrowseConfigurationsPerFolder(): Thenable<boolean> {
return Promise.resolve(true);
},
provideFolderBrowseConfiguration(uri: vscode.Uri): Thenable<api.WorkspaceBrowseConfiguration> {
provideFolderBrowseConfiguration(_uri: vscode.Uri): Thenable<api.WorkspaceBrowseConfiguration> {
lastBrowseResult = defaultFolderBrowseConfig;
return Promise.resolve(defaultFolderBrowseConfig);
},
@@ -156,7 +161,7 @@ suite("extensibility tests v3", function(): void {
const disposables: vscode.Disposable[] = [];
suiteSetup(async function(): Promise<void> {
cpptools = await apit.getCppToolsTestApi(api.Version.v3);
cpptools = await apit.getCppToolsTestApi(api.Version.v3) ?? assert.fail('Unable to get the CppToolsTestApi');
cpptools.registerCustomConfigurationProvider(provider);
cpptools.notifyReady(provider);
disposables.push(cpptools);
@@ -174,7 +179,8 @@ suite("extensibility tests v3", function(): void {
test("Check provider - main3.cpp", async () => {
// Open a c++ file to start the language server.
const path: string = vscode.workspace.workspaceFolders[0].uri.fsPath + "/main3.cpp";
const wf = vscode.workspace.workspaceFolders?.[0] ?? assert.fail("No workspace folder open");
const path: string = `${wf.uri.fsPath}/main3.cpp`;
const uri: vscode.Uri = vscode.Uri.file(path);
const testHook: apit.CppToolsTestHook = cpptools.getTestHook();
@@ -221,7 +227,7 @@ suite("extensibility tests v2", function(): void {
const provider: any = {
name: "cpptoolsTest-v2",
extensionId: "ms-vscode.cpptools-test2",
canProvideConfiguration(document: vscode.Uri): Thenable<boolean> {
canProvideConfiguration(_document: vscode.Uri): Thenable<boolean> {
return Promise.resolve(true);
},
provideConfigurations(uris: vscode.Uri[]): Thenable<api.SourceFileConfigurationItem[]> {
@@ -249,7 +255,7 @@ suite("extensibility tests v2", function(): void {
const disposables: vscode.Disposable[] = [];
suiteSetup(async function(): Promise<void> {
cpptools = await apit.getCppToolsTestApi(api.Version.v2);
cpptools = await apit.getCppToolsTestApi(api.Version.v2) ?? assert.fail('Unable to get the CppToolsTestApi');
cpptools.registerCustomConfigurationProvider(provider);
cpptools.notifyReady(provider);
disposables.push(cpptools);
@@ -267,7 +273,8 @@ suite("extensibility tests v2", function(): void {
test("Check provider - main2.cpp", async () => {
// Open a c++ file to start the language server.
const path: string = vscode.workspace.workspaceFolders[0].uri.fsPath + "/main2.cpp";
const wf = vscode.workspace.workspaceFolders?.[0] ?? assert.fail("No workspace folder open");
const path: string = `${wf.uri.fsPath}/main2.cpp`;
const uri: vscode.Uri = vscode.Uri.file(path);
const testHook: apit.CppToolsTestHook = cpptools.getTestHook();
@@ -308,7 +315,7 @@ suite("extensibility tests v1", function(): void {
const provider: any = {
name: "cpptoolsTest-v1",
extensionId: "ms-vscode.cpptools-test",
canProvideConfiguration(document: vscode.Uri): Thenable<boolean> {
canProvideConfiguration(_document: vscode.Uri): Thenable<boolean> {
return Promise.resolve(true);
},
provideConfigurations(uris: vscode.Uri[]): Thenable<api.SourceFileConfigurationItem[]> {
@@ -329,7 +336,7 @@ suite("extensibility tests v1", function(): void {
const disposables: vscode.Disposable[] = [];
suiteSetup(async function(): Promise<void> {
cpptools = await apit.getCppToolsTestApi(api.Version.v1);
cpptools = await apit.getCppToolsTestApi(api.Version.v1) ?? assert.fail('Unable to get the CppToolsTestApi');
cpptools.registerCustomConfigurationProvider(provider);
disposables.push(cpptools);
@@ -346,7 +353,8 @@ suite("extensibility tests v1", function(): void {
test("Check provider - main1.cpp", async () => {
// Open a c++ file to start the language server.
const path: string = vscode.workspace.workspaceFolders[0].uri.fsPath + "/main1.cpp";
const wf = vscode.workspace.workspaceFolders?.[0] ?? assert.fail("No workspace folder open");
const path: string = `${wf.uri.fsPath}/main1.cpp`;
const uri: vscode.Uri = vscode.Uri.file(path);
const testHook: apit.CppToolsTestHook = cpptools.getTestHook();
@@ -384,7 +392,7 @@ suite("extensibility tests v0", function(): void {
// Has to be 'any' instead of api.CustomConfigurationProvider because of missing interface members.
const provider: any = {
name: "cpptoolsTest-v0",
canProvideConfiguration(document: vscode.Uri): Thenable<boolean> {
canProvideConfiguration(_document: vscode.Uri): Thenable<boolean> {
return Promise.resolve(true);
},
provideConfigurations(uris: vscode.Uri[]): Thenable<api.SourceFileConfigurationItem[]> {
@@ -402,7 +410,7 @@ suite("extensibility tests v0", function(): void {
const disposables: vscode.Disposable[] = [];
suiteSetup(async function(): Promise<void> {
cpptools = await apit.getCppToolsTestApi(api.Version.v0);
cpptools = await apit.getCppToolsTestApi(api.Version.v0) ?? assert.fail('Unable to get the CppToolsTestApi');
cpptools.registerCustomConfigurationProvider(provider);
disposables.push(cpptools); // This is a no-op for v0, but do it anyway to make sure nothing breaks.
@@ -420,7 +428,8 @@ suite("extensibility tests v0", function(): void {
test("Check provider - main.cpp", async () => {
// Open a C++ file to start the language server.
const path: string = vscode.workspace.workspaceFolders[0].uri.fsPath + "/main.cpp";
const wf = vscode.workspace.workspaceFolders?.[0] ?? assert.fail("No workspace folder open");
const path: string = `${wf.uri.fsPath}/main.cpp`;
const uri: vscode.Uri = vscode.Uri.file(path);
const testHook: apit.CppToolsTestHook = cpptools.getTestHook();
@@ -1,28 +1,67 @@
import * as path from 'path';
import { runTests } from '@vscode/test-electron';
async function main() {
try {
// The folder containing the Extension Manifest package.json
// Passed to `--extensionDevelopmentPath`
const extensionDevelopmentPath = path.resolve(__dirname, '../../../../');
// The path to the extension test script
// Passed to --extensionTestsPath
const extensionTestsPath = path.resolve(__dirname, './index');
const testWorkspace = path.resolve(extensionDevelopmentPath, 'test/integrationTests/testAssets/SimpleCppProject/simpleCppProject.code-workspace');
const launchArgs = [ "--disable-extensions", testWorkspace ];
// Download VS Code, unzip it and run the integration test
await runTests({ launchArgs, extensionDevelopmentPath, extensionTestsPath });
} catch (err) {
console.log(err);
console.log('Failed to run tests.');
process.exit(1);
}
}
main();
import { downloadAndUnzipVSCode, resolveCliArgsFromVSCodeExecutablePath, runTests } from '@vscode/test-electron';
import { createHash } from 'crypto';
import { mkdir as md, stat } from 'fs/promises';
import { tmpdir } from 'os';
import { resolve } from 'path';
// The folder containing the Extension Manifest package.json
// Passed to `--extensionDevelopmentPath`
const extensionDevelopmentPath = resolve(__dirname, '../../../../');
const isolated = resolve(tmpdir(), '.vscode-test', createHash('sha256').update(extensionDevelopmentPath).digest('hex').substring(0,6) );
const options = {
cachePath: `${isolated}/cache`,
launchArgs: ['--no-sandbox', '--disable-updates', '--skip-welcome', '--skip-release-notes', `--extensions-dir=${isolated}/extensions`, `--user-data-dir=${isolated}/user-data`]
};
async function mkdir(filePath:string) {
filePath = resolve(filePath);
try {
const s = await stat(filePath);
if( s.isDirectory() ) {
return filePath;
}
throw new Error(`Cannot create directory '${filePath}' because thre is a file there.`);
} catch {
// no worries
}
await md(filePath, { recursive: true })
return filePath;
}
async function main() {
try {
// create a folder for the isolated test environment
await mkdir(isolated);
// download VSCode to that location
const vscodeExecutablePath = await downloadAndUnzipVSCode(options);
const [cli, ...launchArgs] = resolveCliArgsFromVSCodeExecutablePath(vscodeExecutablePath).filter(each => !each.startsWith('--extensions-dir=') && !each.startsWith('--user-data-dir='));
// clean up args so that it works with the isolate extensions and data directories
launchArgs.push(`--extensions-dir=${isolated}/extensions`, `--user-data-dir=${isolated}/user-data`);
// The path to the extension test script
// Passed to --extensionTestsPath
const extensionTestsPath = resolve(__dirname, './index');
const testWorkspace = resolve(extensionDevelopmentPath, 'test/integrationTests/testAssets/SimpleCppProject/simpleCppProject.code-workspace');
launchArgs.push("--disable-extensions", testWorkspace );
// Download VS Code, unzip it and run the integration test
await runTests({
...options,
launchArgs,
extensionDevelopmentPath,
extensionTestsPath
});
} catch (err) {
console.log(err);
console.log('Failed to run tests.');
process.exit(1);
}
}
main();
@@ -2,12 +2,16 @@
* Copyright (c) Microsoft Corporation. All Rights Reserved.
* See 'LICENSE' in the project root for license information.
* ------------------------------------------------------------------------------------------ */
/* eslint-disable @typescript-eslint/triple-slash-reference */
/// <reference path="../../vscode.d.ts" />
import { fail } from 'assert';
import * as vscode from 'vscode';
export const defaultTimeout: number = 100000;
export async function activateCppExtension(): Promise<void> {
const extension: vscode.Extension<any> = vscode.extensions.getExtension("ms-vscode.cpptools");
const extension = vscode.extensions.getExtension("ms-vscode.cpptools") ?? fail("Could not get CppTools extension");
if (!extension.isActive) {
await extension.activate();
}
@@ -6,7 +6,7 @@
import { ok, strictEqual, throws } from 'assert';
import { describe } from 'mocha';
import { setTimeout } from 'timers/promises';
import { ManualPromise } from '../../src/Utility/Async/manual-promise';
import { ManualPromise } from '../../src/Utility/Async/manualPromise';
// force dev mode (which throws on duplicate resolve calls)
(global as any).DEVMODE = true;
@@ -6,7 +6,7 @@
import { ok, strictEqual } from 'assert';
import { describe } from 'mocha';
import { setTimeout } from 'timers/promises';
import { ManualSignal } from '../../src/Utility/Async/manual-signal';
import { ManualSignal } from '../../src/Utility/Async/manualSignal';
import { Signal } from '../../src/Utility/Async/signal';
describe('Signal', () => {
+65 -26
View File
@@ -1,26 +1,65 @@
import * as path from 'path';
import { runTests } from '@vscode/test-electron';
async function main() {
try {
// The folder containing the Extension Manifest package.json
// Passed to `--extensionDevelopmentPath`
const extensionDevelopmentPath = path.resolve(__dirname, '../../../');
// The path to the extension test script
// Passed to --extensionTestsPath
const extensionTestsPath = path.resolve(__dirname, './index');
const launchArgs = [ "--disable-extensions" ];
// Download VS Code, unzip it and run the integration test
await runTests({ launchArgs, extensionDevelopmentPath, extensionTestsPath });
} catch (err) {
console.log(err);
console.log('Failed to run tests.');
process.exit(1);
}
}
main();
import { downloadAndUnzipVSCode, resolveCliArgsFromVSCodeExecutablePath, runTests } from '@vscode/test-electron';
import { createHash } from 'crypto';
import { mkdir as md, stat } from 'fs/promises';
import { tmpdir } from 'os';
import { resolve } from 'path';
// The folder containing the Extension Manifest package.json
// Passed to `--extensionDevelopmentPath`
const extensionDevelopmentPath = resolve(__dirname, '../../../');
const isolated = resolve(tmpdir(), '.vscode-test', createHash('sha256').update(extensionDevelopmentPath).digest('hex').substring(0,6) );
const options = {
cachePath: `${isolated}/cache`,
launchArgs: ['--no-sandbox', '--disable-updates', '--skip-welcome', '--skip-release-notes', `--extensions-dir=${isolated}/extensions`, `--user-data-dir=${isolated}/user-data`]
};
async function mkdir(filePath:string) {
filePath = resolve(filePath);
try {
const s = await stat(filePath);
if( s.isDirectory() ) {
return filePath;
}
throw new Error(`Cannot create directory '${filePath}' because thre is a file there.`);
} catch {
// no worries
}
await md(filePath, { recursive: true })
return filePath;
}
async function main() {
try {
// create a folder for the isolated test environment
await mkdir(isolated);
// download VSCode to that location
const vscodeExecutablePath = await downloadAndUnzipVSCode(options);
const [cli, ...launchArgs] = resolveCliArgsFromVSCodeExecutablePath(vscodeExecutablePath).filter(each => !each.startsWith('--extensions-dir=') && !each.startsWith('--user-data-dir='));
// clean up args so that it works with the isolate extensions and data directories
launchArgs.push(`--extensions-dir=${isolated}/extensions`, `--user-data-dir=${isolated}/user-data`);
// The path to the extension test script
// Passed to --extensionTestsPath
const extensionTestsPath = resolve(__dirname, './index');
launchArgs.push("--disable-extensions");
// Download VS Code, unzip it and run the integration test
await runTests({
...options,
launchArgs,
extensionDevelopmentPath,
extensionTestsPath
});
} catch (err) {
console.log(err);
console.log('Failed to run tests.');
process.exit(1);
}
}
main();
+5 -3
View File
@@ -1,8 +1,10 @@
/* --------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
* Copyright (c) Microsoft Corporation. All Rights Reserved.
* See 'LICENSE' in the project root for license information.
* ------------------------------------------------------------------------------------------ */
/* eslint-disable no-prototype-builtins */
import * as fs from 'fs';
import * as os from 'os';
@@ -132,7 +134,7 @@ function generateOptionsSchema(): void {
packageJSON.contributes.debuggers[1].configurationAttributes.launch = schemaJSON.definitions.CppvsdbgLaunchOptions;
packageJSON.contributes.debuggers[1].configurationAttributes.attach = schemaJSON.definitions.CppvsdbgAttachOptions;
let content: string = JSON.stringify(packageJSON, null, 2);
let content: string = JSON.stringify(packageJSON, null, 4);
if (os.platform() === 'win32') {
content = content.replace(/\n/gm, "\r\n");
}
+39 -97
View File
@@ -530,15 +530,15 @@
"@microsoft/1ds-core-js" "^3.2.3"
"@microsoft/1ds-post-js" "^3.2.3"
"@vscode/test-electron@^1.6.1":
version "1.6.2"
resolved "https://registry.yarnpkg.com/@vscode/test-electron/-/test-electron-1.6.2.tgz#f639cab19a0013949015079dcfd2ff0c1aa88a1b"
integrity sha512-W01ajJEMx6223Y7J5yaajGjVs1QfW3YGkkOJHVKfAMEqNB1ZHN9wCcViehv5ZwVSSJnjhu6lYEYgwBdHtCxqhQ==
"@vscode/test-electron@^2.3.3":
version "2.3.3"
resolved "https://registry.yarnpkg.com/@vscode/test-electron/-/test-electron-2.3.3.tgz#e648700d5848eccfda99efa5d839356cfbe8cd4e"
integrity sha512-hgXCkDP0ibboF1K6seqQYyHAzCURgTwHS/6QU7slhwznDLwsRwg9bhfw1CZdyUEw8vvCmlrKWnd7BlQnI0BC4w==
dependencies:
http-proxy-agent "^4.0.1"
https-proxy-agent "^5.0.0"
rimraf "^3.0.2"
unzipper "^0.10.11"
jszip "^3.10.1"
semver "^7.3.8"
"@webassemblyjs/[email protected]", "@webassemblyjs/ast@^1.11.5":
version "1.11.6"
@@ -1063,11 +1063,6 @@ before-after-hook@^2.2.0:
resolved "https://registry.yarnpkg.com/before-after-hook/-/before-after-hook-2.2.3.tgz#c51e809c81a4e354084422b9b26bad88249c517c"
integrity sha512-NzUnlZexiaH/46WDhANlyR2bXRopNg4F/zuSA3OpZnllCUgRaOF2znDioDWrmbNVsuZk6l9pMquQB38cfBZwkQ==
big-integer@^1.6.17:
version "1.6.51"
resolved "https://registry.yarnpkg.com/big-integer/-/big-integer-1.6.51.tgz#0df92a5d9880560d3ff2d5fd20245c889d130686"
integrity sha512-GPEid2Y9QU1Exl1rpO9B2IPJGHPSupF5GnVIP0blYvNOMer2bTvSWs1jGOUg04hTmu67nmLsQ9TBo1puaotBHg==
big.js@^5.2.2:
version "5.2.2"
resolved "https://registry.yarnpkg.com/big.js/-/big.js-5.2.2.tgz#65f0af382f578bcdc742bd9c281e9cb2d7768328"
@@ -1078,14 +1073,6 @@ binary-extensions@^2.0.0:
resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.2.0.tgz#75f502eeaf9ffde42fc98829645be4ea76bd9e2d"
integrity sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==
binary@~0.3.0:
version "0.3.0"
resolved "https://registry.yarnpkg.com/binary/-/binary-0.3.0.tgz#9f60553bc5ce8c3386f3b553cff47462adecaa79"
integrity sha512-D4H1y5KYwpJgK8wk1Cue5LLPgmwHKYSChkbspQg5JtVuR5ulGckxfR62H3AE9UDkdMC8yyXlqYihuz3Aqg2XZg==
dependencies:
buffers "~0.1.1"
chainsaw "~0.1.0"
bl@^5.0.0:
version "5.1.0"
resolved "https://registry.yarnpkg.com/bl/-/bl-5.1.0.tgz#183715f678c7188ecef9fe475d90209400624273"
@@ -1095,11 +1082,6 @@ bl@^5.0.0:
inherits "^2.0.4"
readable-stream "^3.4.0"
bluebird@~3.4.1:
version "3.4.7"
resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.4.7.tgz#f72d760be09b7f76d08ed8fae98b289a8d05fab3"
integrity sha512-iD3898SR7sWVRHbiQv+sHUtHnMvC1o3nW5rAcqnq3uOn07DSAppZYUkIGslDz6gXC7HfunPe7YVBgoEJASPcHA==
brace-expansion@^1.1.7:
version "1.1.11"
resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd"
@@ -1168,11 +1150,6 @@ buffer-from@^1.0.0:
resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5"
integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==
buffer-indexof-polyfill@~1.0.0:
version "1.0.2"
resolved "https://registry.yarnpkg.com/buffer-indexof-polyfill/-/buffer-indexof-polyfill-1.0.2.tgz#d2732135c5999c64b277fcf9b1abe3498254729c"
integrity sha512-I7wzHwA3t1/lwXQh+A5PbNvJxgfo5r3xulgpYDB5zckTu/Z9oUK9biouBKQUjEqzaz3HnAT6TYoovmE+GqSf7A==
buffer@^6.0.3:
version "6.0.3"
resolved "https://registry.yarnpkg.com/buffer/-/buffer-6.0.3.tgz#2ace578459cc8fbe2a70aaa8f52ee63b6a74c6c6"
@@ -1181,11 +1158,6 @@ buffer@^6.0.3:
base64-js "^1.3.1"
ieee754 "^1.2.1"
buffers@~0.1.1:
version "0.1.1"
resolved "https://registry.yarnpkg.com/buffers/-/buffers-0.1.1.tgz#b24579c3bed4d6d396aeee6d9a8ae7f5482ab7bb"
integrity sha512-9q/rDEGSb/Qsvv2qvzIzdluL5k7AaJOTrw23z9reQthrbF7is4CtlT0DXyO1oei2DCp4uojjzQ7igaSHp1kAEQ==
builtin-modules@^3.3.0:
version "3.3.0"
resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-3.3.0.tgz#cae62812b89801e9656336e46223e030386be7b6"
@@ -1234,13 +1206,6 @@ caniuse-lite@^1.0.30001503:
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001515.tgz#418aefeed9d024cd3129bfae0ccc782d4cb8f12b"
integrity sha512-eEFDwUOZbE24sb+Ecsx3+OvNETqjWIdabMy52oOkIgcUtAsQifjUG9q4U9dgTHJM2mfk4uEPxc0+xuFdJ629QA==
chainsaw@~0.1.0:
version "0.1.0"
resolved "https://registry.yarnpkg.com/chainsaw/-/chainsaw-0.1.0.tgz#5eab50b28afe58074d0d58291388828b5e5fbc98"
integrity sha512-75kWfWt6MEKNC8xYXIdRpDehRYY/tNSgwKaJq+dbbDcxORuVrrQ+SEHoWsniVn9XPYfP4gmdWIeDk/4YNp1rNQ==
dependencies:
traverse ">=0.3.0 <0.4"
chalk@^4.0.0, chalk@^4.1.0:
version "4.1.2"
resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01"
@@ -1634,13 +1599,6 @@ doctrine@^3.0.0:
dependencies:
esutils "^2.0.2"
duplexer2@~0.1.4:
version "0.1.4"
resolved "https://registry.yarnpkg.com/duplexer2/-/duplexer2-0.1.4.tgz#8b12dab878c0d69e3e7891051662a32fc6bddcc1"
integrity sha512-asLFVfWWtJ90ZyOUHMqk7/S2w2guQKxUI2itj3d92ADHhxUSbCMGi1f1cBcJ7xM1To+pE/Khbwo1yuNbMEPKeA==
dependencies:
readable-stream "^2.0.2"
duplexer@^0.1.1, duplexer@~0.1.1:
version "0.1.2"
resolved "https://registry.yarnpkg.com/duplexer/-/duplexer-0.1.2.tgz#3abe43aef3835f8ae077d136ddce0f276b0400e6"
@@ -2402,16 +2360,6 @@ fsevents@~2.3.2:
resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a"
integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==
fstream@^1.0.12:
version "1.0.12"
resolved "https://registry.yarnpkg.com/fstream/-/fstream-1.0.12.tgz#4e8ba8ee2d48be4f7d0de505455548eae5932045"
integrity sha512-WvJ193OHa0GHPEL+AycEJgxvBEwyfRkN1vhjca23OaPVMCaLCXTd5qAu82AjTcgP1UJmytkOKb63Ypde7raDIg==
dependencies:
graceful-fs "^4.1.2"
inherits "~2.0.0"
mkdirp ">=0.5 0"
rimraf "2"
function-bind@^1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d"
@@ -2633,7 +2581,7 @@ gopd@^1.0.1:
dependencies:
get-intrinsic "^1.1.3"
[email protected], graceful-fs@^4.0.0, graceful-fs@^4.1.11, graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.10, graceful-fs@^4.2.11, graceful-fs@^4.2.2, graceful-fs@^4.2.4, graceful-fs@^4.2.8, graceful-fs@^4.2.9:
[email protected], graceful-fs@^4.0.0, graceful-fs@^4.1.11, graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.10, graceful-fs@^4.2.11, graceful-fs@^4.2.4, graceful-fs@^4.2.8, graceful-fs@^4.2.9:
version "4.2.11"
resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3"
integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==
@@ -2902,6 +2850,11 @@ ignore@^5.2.0:
resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.2.4.tgz#a291c0c6178ff1b960befe47fcdec301674a6324"
integrity sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==
immediate@~3.0.5:
version "3.0.6"
resolved "https://registry.yarnpkg.com/immediate/-/immediate-3.0.6.tgz#9db1dbd0faf8de6fbe0f5dd5e56bb606280de69b"
integrity sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ==
import-fresh@^3.0.0, import-fresh@^3.2.1:
version "3.3.0"
resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.3.0.tgz#37162c25fcb9ebaa2e6e53d5b4d88ce17d9e0c2b"
@@ -2931,7 +2884,7 @@ inflight@^1.0.4:
once "^1.3.0"
wrappy "1"
inherits@2, inherits@^2.0.1, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.0, inherits@~2.0.3:
inherits@2, inherits@^2.0.1, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.3:
version "2.0.4"
resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c"
integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==
@@ -3370,6 +3323,16 @@ jsonfile@^4.0.0:
optionalDependencies:
graceful-fs "^4.1.6"
jszip@^3.10.1:
version "3.10.1"
resolved "https://registry.yarnpkg.com/jszip/-/jszip-3.10.1.tgz#34aee70eb18ea1faec2f589208a157d1feb091c2"
integrity sha512-xXDvecyTpGLrqFrvkrUSoxxfJI5AH7U8zxxtVclpsUtMCq4JQ290LY8AW5c7Ggnr/Y/oK+bQMbqK2qmtk3pN4g==
dependencies:
lie "~3.3.0"
pako "~1.0.2"
readable-stream "~2.3.6"
setimmediate "^1.0.5"
just-debounce@^1.0.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/just-debounce/-/just-debounce-1.1.0.tgz#2f81a3ad4121a76bc7cb45dbf704c0d76a8e5ddf"
@@ -3446,6 +3409,13 @@ levn@^0.4.1:
prelude-ls "^1.2.1"
type-check "~0.4.0"
lie@~3.3.0:
version "3.3.0"
resolved "https://registry.yarnpkg.com/lie/-/lie-3.3.0.tgz#dcf82dee545f46074daf200c7c1c5a08e0f40f6a"
integrity sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ==
dependencies:
immediate "~3.0.5"
liftoff@^3.1.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/liftoff/-/liftoff-3.1.0.tgz#c9ba6081f908670607ee79062d700df062c52ed3"
@@ -3460,11 +3430,6 @@ liftoff@^3.1.0:
rechoir "^0.6.2"
resolve "^1.1.7"
listenercount@~1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/listenercount/-/listenercount-1.0.1.tgz#84c8a72ab59c4725321480c975e6508342e70937"
integrity sha512-3mk/Zag0+IJxeDrxSgaDPy4zZ3w05PRZeJNnlWhzFz5OkX49J4krc+A8X2d2M69vGMBEX0uyl8M+W+8gH+kBqQ==
load-json-file@^1.0.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-1.1.0.tgz#956905708d58b4bab4c2261b04f59f31c99374c0"
@@ -3690,7 +3655,7 @@ mixin-deep@^1.2.0:
for-in "^1.0.2"
is-extendable "^1.0.1"
"mkdirp@>=0.5 0", mkdirp@^0.5.5:
mkdirp@^0.5.5:
version "0.5.6"
resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.6.tgz#7def03d2432dcae4ba1d611445c48396062255f6"
integrity sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==
@@ -4056,6 +4021,11 @@ p-try@^2.0.0:
resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6"
integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==
pako@~1.0.2:
version "1.0.11"
resolved "https://registry.yarnpkg.com/pako/-/pako-1.0.11.tgz#6c9599d340d54dfd3946380252a35705a6b992bf"
integrity sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==
parent-module@^1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/parent-module/-/parent-module-1.0.1.tgz#691d2709e78c79fae3a156622452d00762caaaa2"
@@ -4345,7 +4315,7 @@ read-pkg@^1.0.0:
string_decoder "^1.1.1"
util-deprecate "^1.0.1"
readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.5, readable-stream@^2.1.5, readable-stream@^2.2.2, readable-stream@^2.3.3, readable-stream@^2.3.5, readable-stream@^2.3.6, readable-stream@~2.3.6:
readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.5, readable-stream@^2.1.5, readable-stream@^2.2.2, readable-stream@^2.3.3, readable-stream@^2.3.5, readable-stream@^2.3.6, readable-stream@~2.3.6:
version "2.3.8"
resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.8.tgz#91125e8042bba1b9887f49345f6277027ce8be9b"
integrity sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==
@@ -4525,13 +4495,6 @@ reusify@^1.0.4:
resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76"
integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==
rimraf@2:
version "2.7.1"
resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.7.1.tgz#35797f13a7fdadc566142c29d4f07ccad483e3ec"
integrity sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==
dependencies:
glob "^7.1.3"
rimraf@^3.0.0, rimraf@^3.0.2:
version "3.0.2"
resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a"
@@ -4608,7 +4571,7 @@ semver@^6.3.0:
resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4"
integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==
semver@^7.3.4, semver@^7.3.7, semver@^7.5.1, semver@^7.5.3:
semver@^7.3.4, semver@^7.3.7, semver@^7.3.8, semver@^7.5.1, semver@^7.5.3:
version "7.5.4"
resolved "https://registry.yarnpkg.com/semver/-/semver-7.5.4.tgz#483986ec4ed38e1c6c48c34894a9182dbff68a6e"
integrity sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==
@@ -4651,7 +4614,7 @@ set-value@^2.0.0, set-value@^2.0.1:
is-plain-object "^2.0.3"
split-string "^3.0.1"
setimmediate@~1.0.4:
setimmediate@^1.0.5:
version "1.0.5"
resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.5.tgz#290cbb232e306942d7d7ea9b83732ab7856f8285"
integrity sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==
@@ -5198,11 +5161,6 @@ tr46@~0.0.3:
resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a"
integrity sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==
"traverse@>=0.3.0 <0.4":
version "0.3.9"
resolved "https://registry.yarnpkg.com/traverse/-/traverse-0.3.9.tgz#717b8f220cc0bb7b44e40514c22b2e8bbc70d8b9"
integrity sha512-iawgk0hLP3SxGKDfnDJf8wTz4p2qImnyihM5Hh/sGvQ3K37dPi/w8sRhdNIxYA1TwFwc5mDhIJq+O0RsvXBKdQ==
ts-loader@^8.1.0:
version "8.4.0"
resolved "https://registry.yarnpkg.com/ts-loader/-/ts-loader-8.4.0.tgz#e845ea0f38d140bdc3d7d60293ca18d12ff2720f"
@@ -5354,22 +5312,6 @@ unset-value@^1.0.0:
has-value "^0.3.1"
isobject "^3.0.0"
unzipper@^0.10.11:
version "0.10.14"
resolved "https://registry.yarnpkg.com/unzipper/-/unzipper-0.10.14.tgz#d2b33c977714da0fbc0f82774ad35470a7c962b1"
integrity sha512-ti4wZj+0bQTiX2KmKWuwj7lhV+2n//uXEotUmGuQqrbVZSEGFMbI68+c6JCQ8aAmUWYvtHEz2A8K6wXvueR/6g==
dependencies:
big-integer "^1.6.17"
binary "~0.3.0"
bluebird "~3.4.1"
buffer-indexof-polyfill "~1.0.0"
duplexer2 "~0.1.4"
fstream "^1.0.12"
graceful-fs "^4.2.2"
listenercount "~1.0.1"
readable-stream "~2.3.6"
setimmediate "~1.0.4"
update-browserslist-db@^1.0.11:
version "1.0.11"
resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.0.11.tgz#9a2a641ad2907ae7b3616506f4b977851db5b940"